diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index d3712eb6..720ffe80 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -15,11 +15,12 @@ jobs: os: - ubuntu-latest node-version: - - 12.x - - 14.x + - 14 + - 16 + - 18 include: - os: ubuntu-latest - node-version: '14.x' + node-version: '16' primary: true runs-on: ${{ matrix.os }} outputs: @@ -48,6 +49,17 @@ jobs: run: | npm run lint npm t + - name: Setup Docker + # taken from https://github.com/docker/github-actions/blob/0f18e2abad9a4ac2963d2516246787375b5ec917/Dockerfile#L32 + run: curl -fL https://download.docker.com/linux/static/stable/x86_64/docker-20.10.4.tgz | tar xzO docker/docker > docker && sudo mv -f docker /usr/bin/docker && sudo chmod +x /usr/bin/docker + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Build container image + run: make packageLocalDocker + - name: Smoke test + run: make testDocker - name: Build binary run: | npm run build diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 4783ae47..3e50ac1e 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 16 # libgbm-dev is required by Puppeteer 3+ - name: Install system dependencies run: | @@ -33,7 +33,7 @@ jobs: - uses: actions/checkout@v3 - uses: actions/setup-node@v3 with: - node-version: 14 + node-version: 16 # libgbm-dev is required by Puppeteer 3+ - name: Install system dependencies run: | diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..83549152 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,43 @@ +# Package the Node.js project into a single binary +FROM --platform=${TARGETPLATFORM:-linux/amd64} node:16.16.0-alpine3.16 as builder + +# Workaround: https://github.com/nodejs/docker-node/issues/813#issuecomment-407339011 +# Error: could not get uid/gid +# [ 'nobody', 0 ] +RUN npm config set unsafe-perm true + +RUN npm install --location=global pkg@5.6.0 pkg-fetch@3.3.0 + +ENV NODE node16 +ENV PLATFORM alpine +RUN /usr/local/bin/pkg-fetch -n ${NODE} -p ${PLATFORM} -a $([ "$TARGETARCH" == "amd64" ] && echo "x64" || echo "$TARGETARCH") + +COPY package.json package-lock.json /app/ +COPY lib /app/lib +COPY bin /app/bin +COPY css /app/css +WORKDIR /app + +RUN PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 npm ci + +RUN /usr/local/bin/pkg bin/asciidoctor-web-pdf --config package.json --targets ${NODE}-${PLATFORM}-$([ "$TARGETARCH" == "amd64" ] && echo "x64" || echo "$TARGETARCH") -o app.bin + +# Create the image +FROM --platform=${TARGETPLATFORM:-linux/amd64} alpine:3.16.1 + +RUN addgroup -g 1000 asciidoctor && adduser -D -G asciidoctor -u 1000 asciidoctor + +RUN apk add --quiet --no-cache --update chromium font-noto-emoji ttf-freefont font-noto \ + && fc-cache -f + +COPY --chown=asciidoctor:asciidoctor --from=builder /app/app.bin /usr/bin/asciidoctor-web-pdf +COPY --chown=asciidoctor:asciidoctor --from=builder /app/node_modules/mathjax/es5 /usr/bin/assets/mathjax + +ENV PUPPETEER_EXECUTABLE_PATH=/usr/lib/chromium/chrome + +RUN mkdir /usr/app && chown asciidoctor:asciidoctor /usr/app + +USER asciidoctor +WORKDIR /usr/app + +ENTRYPOINT ["/usr/bin/asciidoctor-web-pdf"] diff --git a/Makefile b/Makefile new file mode 100644 index 00000000..eabd8181 --- /dev/null +++ b/Makefile @@ -0,0 +1,25 @@ +MULTI_ARCH_AVAILABLE := $(shell docker buildx inspect | grep amd64 | grep arm64 > /dev/null 2>&1; echo $$?) + +.PHONY: packageDocker publishDocker + +default: packageDocker + +packageDocker: +ifeq ($(MULTI_ARCH_AVAILABLE), 0) + docker buildx build --tag asciidoctor-web-pdf:latest -o type="image,push=false" --platform linux/amd64,linux/arm64 . +else + docker build -t asciidoctor-web-pdf . +endif + +packageLocalDocker: + docker build -t asciidoctor-web-pdf:latest . + +testDocker: + echo "= Test" | docker run -i --rm asciidoctor-web-pdf:latest -a reproducible - > test/output/docker-smoke-test.pdf + md5sum -c test/docker-smoke-test.md5sum + +publishDocker: +ifndef RELEASE_VERSION + $(error RELEASE_VERSION is undefined) +endif + docker buildx build --push --platform linux/amd64,linux/arm64 --tag asciidoctor-web-pdf:latest --tag asciidoctor-web-pdf:${RELEASE_VERSION} . diff --git a/README.md b/README.md index e213afd8..1e332f51 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,48 @@ Verify that the `asciidoctor-web-pdf` command is available on your `PATH` by run $ yarn global add @asciidoctor/core asciidoctor-pdf ``` +### Using Docker + +Currently, the Docker image is not yet published on [Docker Hub](https://hub.docker.com/). +Therefore, you will need to build the Docker image from the Dockerfile. + +To build the Docker image, clone this repository and type the following commands: + +```bash +docker build . -t asciidoctor-web-pdf:latest +``` + +**NOTE:** If `make` is installed on your system you can use: `make packageLocalDocker` + +Verify that the Docker image is working by running: + +```bash +docker run --rm asciidoctor-web-pdf --version + +Asciidoctor Web PDF 1.0.0-alpha.14 using Asciidoctor.js 2.2.6 (Asciidoctor 2.0.17) [https://asciidoctor.org] +Runtime Environment (node v16.17.0 on linux) +CLI version 3.5.0 +``` + +If you want to render the cheatsheet example, move to the root of this repository and type: + +```bash +docker run -i --rm \ + --volume=$PWD/examples/cheat-sheet:"/usr/app" \ + -u $(id -u ${USER}):$(id -g ${USER}) \ + asciidoctor-web-pdf:latest \ + --template-require ./snyk/template.js maven-security-cheat-sheet.adoc +``` + +The `--volume` option will mount your local copy of the Asciidoctor Web PDF repository on the container. +Since it is a non-root user we have to map our user to `asciidoctor` user in the container. + +You can also use `stdin` and `stdout` without the need of volumes. + +```bash +cat examples/document/basic-example.adoc | docker run -i --rm asciidoctor-web-pdf:latest - > doc.pdf +``` + ## Get started Asciidoctor Web PDF provides a standard document layout. diff --git a/package.json b/package.json index c6efc49d..659c38e9 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,7 @@ "test:js": "mocha test/**_test.js", "lint": "standard lib/**.js test/**.js tasks/**js", "publish": "node tasks/publish.js", - "test:update-linux-reference": "docker build -f test/Dockerfile -t asciidoctor-web-pdf/test . && docker run --name asciidoctorwebpdftest asciidoctor-web-pdf/test:latest; docker cp asciidoctorwebpdftest:/app/test/output/. ./test/reference/linux/ && docker rm asciidoctorwebpdftest" + "test:update-linux-reference": "docker build -f test/Dockerfile -t asciidoctor/web-pdf-test . && docker run --name asciidoctorwebpdftest asciidoctor/web-pdf-test:latest; docker cp asciidoctorwebpdftest:/app/test/output/. ./test/reference/linux/ && docker rm asciidoctorwebpdftest" }, "repository": { "type": "git", diff --git a/test/docker-smoke-test.md5sum b/test/docker-smoke-test.md5sum new file mode 100644 index 00000000..d9c99b80 --- /dev/null +++ b/test/docker-smoke-test.md5sum @@ -0,0 +1 @@ +67b7ee0303907fdd271dd80df8aab3a8 test/output/docker-smoke-test.pdf diff --git a/test/output/.gitkeep b/test/output/.gitkeep new file mode 100644 index 00000000..e69de29b