Skip to content

Commit

Permalink
Merge pull request #20 from kotify/py312
Browse files Browse the repository at this point in the history
Weasyprint layer for python3.12 lambda
  • Loading branch information
kalekseev authored Feb 18, 2024
2 parents 671001a + 09a8107 commit 96c5ddb
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 183 deletions.
120 changes: 36 additions & 84 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,99 +5,51 @@ jobs:
weasyprint-build:
name: Build WeasyPrint
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]') "
steps:
- uses: actions/checkout@v2
- name: Build weasyprint
run: |
make build/weasyprint-layer-python3.8.zip
- uses: actions/checkout@v4
- name: Build Layer
run: make build/weasyprint-layer-python3.12.zip
- name: Test weasyprint
run: |
mkdir output
TEST_FILENAME=output/report.pdf make test.weasyprint
TEST_FILENAME=output/report.png make test.weasyprint
- name: Upload pdf
uses: actions/upload-artifact@v1
with:
name: WeasyPrint test results
make test.start.container &
sleep 1
TEST_FILENAME=output/report.pdf make test.print.report
rm -rf build/opt
- name: Upload Build
uses: actions/upload-artifact@v4
with:
name: WeasyPrint Layer Build
path: build
- name: Upload Test PDF
uses: actions/upload-artifact@v4
with:
name: WeasyPrint Test Results
path: output
- name: Create WeasyPrint Release
id: create_weasyprint_release
if: startsWith(github.ref, 'refs/tags/weasyprint-')
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release WeasyPrint layer
- name: Upload WeasyPrint Layer
if: startsWith(github.ref, 'refs/tags/weasyprint-')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with:
upload_url: ${{ steps.create_weasyprint_release.outputs.upload_url }}
asset_path: ./build/weasyprint-layer-python3.8.zip
asset_name: weasyprint-layer-python3.8.zip
asset_content_type: application/zip
files: |
./build/weasyprint-layer-python3.12.zip
./build/weasyprint-layer-python3.12-no-fonts.zip
wkhtmltox-build:
name: Build wkhtmltox
ghostscript-build:
name: Build GhostScript
runs-on: ubuntu-latest
if: "!contains(github.event.head_commit.message, '[skip ci]') && !contains(github.event.head_commit.message, '[ci skip]') "
steps:
- uses: actions/checkout@v2
- name: Build wkhtmltox
run: |
make build/wkhtmltox-layer.zip
make build/wkhtmltopdf-layer.zip
make build/wkhtmltoimage-layer.zip
- name: Test wkhtmltox
- uses: actions/checkout@v4
- name: Build Layer
run: |
mkdir output
TEST_FILENAME=output/google.pdf make test.wkhtmltox
TEST_FILENAME=output/google.png make test.wkhtmltox
- name: Upload pdf
uses: actions/upload-artifact@v1
with:
name: wkhtmltox test results
path: output
- name: Create wkhtmltox Release
id: create_wkhtmltox_release
if: startsWith(github.ref, 'refs/tags/wkhtmltox-')
uses: actions/create-release@latest
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release wkhtmltox layer
- name: Upload wkhtmltox Layer
if: startsWith(github.ref, 'refs/tags/wkhtmltox-')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_wkhtmltox_release.outputs.upload_url }}
asset_path: ./build/wkhtmltox-layer.zip
asset_name: wkhtmltox-layer.zip
asset_content_type: application/zip
- name: Upload wkhtmltopdf Layer
if: startsWith(github.ref, 'refs/tags/wkhtmltox-')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_wkhtmltox_release.outputs.upload_url }}
asset_path: ./build/wkhtmltopdf-layer.zip
asset_name: wkhtmltopdf-layer.zip
asset_content_type: application/zip
- name: Upload wkhtmltoimage Layer
if: startsWith(github.ref, 'refs/tags/wkhtmltox-')
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.create_wkhtmltox_release.outputs.upload_url }}
asset_path: ./build/wkhtmltoimage-layer.zip
asset_name: wkhtmltoimage-layer.zip
asset_content_type: application/zip
make build/ghostscript-layer.zip
rm -rf build/opt
- name: Upload Build
uses: actions/upload-artifact@v4
with:
name: GhostScript Layer Build
path: build
- name: Create GhostScript Release
if: startsWith(github.ref, 'refs/tags/ghostscript-')
uses: softprops/action-gh-release@4634c16e79c963813287e889244c50009e7f0981
with:
files: ./build/build/ghostscript-layer.zip
90 changes: 33 additions & 57 deletions Makefile
Original file line number Diff line number Diff line change
@@ -1,31 +1,39 @@
RUNTIME ?= python3.8
PLATFORM ?= linux/amd64
RUNTIME ?= 3.12
TEST_FILENAME ?= report.pdf
DOCKER_RUN=docker run --rm --platform=${PLATFORM}

.PHONY: stack.deploy.weasyprint clean test.weasyprint
.PHONY: stack.deploy.weasyprint clean test.start.container test.print.report

all: build/weasyprint-layer-$(RUNTIME).zip build/wkhtmltopdf-layer.zip
all: build/weasyprint-layer-python$(RUNTIME).zip

build/weasyprint-layer-$(RUNTIME).zip: weasyprint/layer_builder.sh \
build/weasyprint-layer-python$(RUNTIME).zip: weasyprint/layer_builder.sh \
build/fonts-layer.zip \
| _build
docker run --rm \
${DOCKER_RUN} \
-v `pwd`/weasyprint:/out \
-t lambci/lambda:build-${RUNTIME} \
bash /out/layer_builder.sh
mv -f ./weasyprint/layer.zip ./build/weasyprint-no-fonts-layer.zip
--entrypoint "/out/layer_builder.sh" \
-t public.ecr.aws/lambda/python:${RUNTIME}
mv -f ./weasyprint/layer.zip ./build/weasyprint-layer-python${RUNTIME}-no-fonts.zip
cd build && rm -rf ./opt && mkdir opt \
&& unzip fonts-layer.zip -d opt \
&& unzip weasyprint-no-fonts-layer.zip -d opt \
&& cd opt && zip -r9 ../weasyprint-layer-${RUNTIME}.zip .
&& unzip weasyprint-layer-python${RUNTIME}-no-fonts.zip -d opt \
&& cd opt && zip -r9 ../weasyprint-layer-python${RUNTIME}.zip .

build/fonts-layer.zip: fonts/layer_builder.sh | _build
docker run --rm \
-e INSTALL_MS_FONTS="${INSTALL_MS_FONTS}" \
${DOCKER_RUN} \
-v `pwd`/fonts:/out \
-t lambci/lambda:build-${RUNTIME} \
bash /out/layer_builder.sh
--entrypoint "/out/layer_builder.sh" \
-t public.ecr.aws/lambda/python:${RUNTIME}
mv -f ./fonts/layer.zip $@

build/ghostscript-layer.zip: ghostscript/layer_builder.sh | _build
${DOCKER_RUN} \
-v `pwd`/ghostscript:/out \
--entrypoint "/out/layer_builder.sh" \
-t public.ecr.aws/lambda/python:${RUNTIME}
mv -f ./ghostscript/layer.zip $@

stack.diff:
cd cdk-stacks && npm install && npm run build
cdk diff --app ./cdk-stacks/bin/app.js --stack PrintStack --parameters uploadBucketName=${BUCKET}
Expand All @@ -34,50 +42,22 @@ stack.deploy:
cd cdk-stacks && npm install && npm run build
cdk deploy --app ./cdk-stacks/bin/app.js --stack PrintStack --parameters uploadBucketName=${BUCKET}

test.weasyprint:
docker run --rm \
test.start.container:
${DOCKER_RUN} \
-e GDK_PIXBUF_MODULE_FILE="/opt/lib/loaders.cache" \
-e FONTCONFIG_PATH="/opt/fonts" \
-e XDG_DATA_DIRS="/opt/lib" \
-v `pwd`/weasyprint:/var/task \
-v `pwd`/build/opt:/opt \
lambci/lambda:${RUNTIME} \
lambda_function.lambda_handler \
'{"url": "https://kotify.github.io/cloud-print-utils/samples/report/", "filename": "${TEST_FILENAME}", "return": "base64"}' \
| tail -1 | jq .body | tr -d '"' | base64 -d > ${TEST_FILENAME}
@echo "Check ./${TEST_FILENAME}, eg.: xdg-open ${TEST_FILENAME}"


build/wkhtmltox-layer.zip: wkhtmltox/layer_builder.sh \
build/fonts-layer.zip \
| _build
docker run --rm \
-v `pwd`/wkhtmltox:/out \
-t lambci/lambda:build-${RUNTIME} \
bash /out/layer_builder.sh
mv -f ./wkhtmltox/layer.zip ./build/wkhtmltox-no-fonts-layer.zip
cd build && rm -rf ./opt && mkdir opt \
&& unzip fonts-layer.zip -d opt \
&& unzip wkhtmltox-no-fonts-layer.zip -d opt \
&& cd opt && zip -r9 ../wkhtmltox-layer.zip .

build/wkhtmltopdf-layer.zip: build/wkhtmltox-layer.zip
cp build/wkhtmltox-layer.zip $@
zip -d $@ "bin/wkhtmltoimage"

build/wkhtmltoimage-layer.zip: build/wkhtmltox-layer.zip
cp build/wkhtmltox-layer.zip $@
zip -d $@ "bin/wkhtmltopdf"

test.wkhtmltox:
docker run --rm \
-e FONTCONFIG_PATH="/opt/fonts" \
-v `pwd`/wkhtmltox:/var/task \
-v `pwd`/build/opt:/opt \
lambci/lambda:${RUNTIME} \
lambda_function.lambda_handler \
'{"args": "https://google.com", "filename": "${TEST_FILENAME}", "return": "base64"}' \
| tail -1 | jq .body | tr -d '"' | base64 -d > ${TEST_FILENAME}
-p 9000:8080 \
public.ecr.aws/lambda/python:${RUNTIME} \
lambda_function.lambda_handler

test.print.report:
which jq
curl --fail -s -S -XPOST "http://localhost:9000/2015-03-31/functions/function/invocations" \
-d '{"return": "base64", "filename": "${TEST_FILENAME}", "url": "https://kotify.github.io/cloud-print-utils/samples/report/"}' \
| tail -1 | jq .body | tr -d '"' | base64 -d > ${TEST_FILENAME}
@echo "Check ./${TEST_FILENAME}, eg.: xdg-open ${TEST_FILENAME}"


Expand All @@ -86,7 +66,3 @@ _build:

clean:
rm -rf ./build

fonts.list:
docker run --rm lambci/lambda:build-${RUNTIME} \
bash -c "yum search font | grep noarch | grep -v texlive"
20 changes: 7 additions & 13 deletions fonts/layer_builder.sh
Original file line number Diff line number Diff line change
Expand Up @@ -2,27 +2,21 @@
# don't fortget to set FONTCONFIG_PATH="/opt/fonts" in your lambda
set -e

yum upgrade -y ca-certificates
yum install -y yum-utils rpmdevtools
dnf install -y rpmdevtools

cd /tmp
# download fonts
yumdownloader \
dejavu-sans-fonts \
dejavu-fonts-common
dnf download dejavu-sans-fonts
dnf download dejavu-serif-fonts
dnf download dejavu-sans-mono-fonts

rpmdev-extract -- *rpm

mkdir /opt/fonts
# dnf download urw-base35-nimbus-roman-fonts
# find /tmp/*/usr/share/fonts -name '*.afm' -delete -o -name '*.t1' -delete
cp -P -r /tmp/*/usr/share/fonts/* /opt/fonts

if [ "$INSTALL_MS_FONTS" = "yes" ]; then
PYTHON=python2 amazon-linux-extras install epel -y
yum install -y fontconfig xorg-x11-font-utils cabextract
curl -L -O https://downloads.sourceforge.net/project/mscorefonts2/rpms/msttcore-fonts-installer-2.6-1.noarch.rpm
rpm -i msttcore-fonts-installer-2.6-1.noarch.rpm
cp -P -r /usr/share/fonts/msttcore /opt/fonts/
fi

cat > /opt/fonts/fonts.conf <<EOF
<?xml version="1.0" ?>
<!DOCTYPE fontconfig SYSTEM "fonts.dtd">
Expand Down
12 changes: 12 additions & 0 deletions ghostscript/layer_builder.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash
set -e
export VERSION="10.02.1"

dnf install -y gcc tar
cd /tmp/
curl -L -s https://github.com/ArtifexSoftware/ghostpdl-downloads/releases/download/gs${VERSION//./}/ghostscript-${VERSION}.tar.gz | tar zxf -
cd ghostscript-*
./configure --prefix=/opt
make && make install
cd /opt
zip -r9 /out/layer.zip bin/gs
17 changes: 4 additions & 13 deletions weasyprint/lambda_function.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,10 @@ def lambda_handler(event, context):
filename = event["filename"]
basename = os.path.basename(filename)
tmpfile = f"/tmp/{basename}"
ext = os.path.splitext(basename)[1]
if ext == ".pdf":
content_type = "application/pdf"
method = "write_pdf"
elif ext == ".png":
content_type = "image/png"
method = "write_png"
else:
raise ValueError("File extension {ext} is not supported.")
if "url" in event:
getattr(HTML(url=event["url"]), method)(target=tmpfile)
HTML(url=event["url"]).write_pdf(target=tmpfile)
else:
getattr(HTML(string=event["html"]), method)(
HTML(string=event["html"]).write_pdf(
target=tmpfile,
stylesheets=[CSS(string=event["css"])] if "css" in event else None,
)
Expand All @@ -31,7 +22,7 @@ def lambda_handler(event, context):
return {
"statusCode": 200,
"headers": {
"Content-type": content_type,
"Content-type": "application/pdf",
"Content-Disposition": f"attachment;filename={basename}",
},
"isBase64Encoded": True,
Expand All @@ -47,7 +38,7 @@ def lambda_handler(event, context):
open(tmpfile, "rb"),
bucket,
filename,
ExtraArgs={"ContentType": content_type},
ExtraArgs={"ContentType": "application/pdf"},
)
url = s3.generate_presigned_url(
ClientMethod="get_object",
Expand Down
Loading

0 comments on commit 96c5ddb

Please sign in to comment.