DEV Community

Cover image for Generate PDF handbook with Docusaurus using GitHub Actions

Generate PDF handbook with Docusaurus using GitHub Actions

Motivation

Having @open-sauced docs built using Docusaurus, we started exploring the plugin ecosystem and identified various improvements we could apply.

One of the community plugins we found during that process was signcl/docusaurus-prince-pdf, an npm package leveraging sindresorhus/got to crawl all the documentation and generate a PDF version.

Having a portable document generated as a downloadable release asset, we could more easily share the entirety of our docs and have that document available for offline use.

We faced the challenge of having to access the upcoming version during the deployment workflow, installing additional binaries, and deploying the generated asset as part of the release.

My Workflow

The full workflow is available here: .github/workflows/release.yml

In order to generate a handbook out of a Docusaurus instance we need to build the application in a container before uploading it as a build artifact for later workflow steps.

This is all taken care of in the new docker job that was created for the hackaton:

jobs:
  docker:
    name: Build container
    runs-on: ubuntu-latest
    steps:
      - name: "☁️ checkout repository"
        uses: actions/checkout@v2

      - name: "🔧 setup buildx"
        uses: docker/setup-buildx-action@v1

      - name: "🔧 cache docker layers"
        uses: actions/cache@v2
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-

      - name: "🔧 docker meta"
        id: meta
        uses: docker/metadata-action@v3
        with:
          images: ${{ github.repository }}
          tags: latest

      - name: "📦 docker build"
        uses: docker/build-push-action@v2
        with:
          context: .
          tags: ${{ steps.meta.outputs.tags }}
          labels: ${{ steps.meta.outputs.labels }}
          outputs: type=docker,dest=/tmp/docker.tar
          push: false
          cache-from: type=gha, scope=${{ github.workflow }}
          cache-to: type=gha, scope=${{ github.workflow }}

      - name: "📂 docker artifacts"
        uses: actions/upload-artifact@v2
        with:
          name: docker
          path: /tmp/docker.tar
Enter fullscreen mode Exit fullscreen mode

Concurrently, the build job prepares static npm assets and uploads them as an artifact for a subsequent job:

jobs:
  build:
    name: Build application
    runs-on: ubuntu-latest
    steps:
      - name: "☁️ checkout repository"
        uses: actions/checkout@v2

      - name: "🔧 setup node"
        uses: actions/setup-node@v2.1.5
        with:
          node-version: 16

      - name: "🔧 install npm@latest"
        run: npm i -g npm@latest

      - name: "📦 install dependencies"
        uses: bahmutov/npm-install@v1

      - name: "🚀 static app"
        run: npm run build

      - name: "📂 production artifacts"
        uses: actions/upload-artifact@v2
        with:
          name: build
          path: build
Enter fullscreen mode Exit fullscreen mode

We then move to the release job, downloading all the artifacts and running our custom configuration @open-sauced/semantic-release-conventional-config from a docker socket:

jobs:
  release:
    environment:
      name: production
      url: https://github.com/${{ github.repository }}/releases/tag/${{ env.RELEASE_TAG }}
    name: Semantic release
    needs:
      - docker
      - build
    runs-on: ubuntu-latest
    steps:
      - name: "☁️ checkout repository"
        uses: actions/checkout@v2
        with:
          fetch-depth: 0

      - name: "📂 download docker artifacts"
        uses: actions/download-artifact@v2
        with:
          name: docker
          path: /tmp

      - name: "📦 load tag"
        run: |
          docker load --input /tmp/docker.tar
          docker image ls -a

      - name: "📂 download build artifacts"
        uses: actions/download-artifact@v2
        with:
          name: build
          path: /tmp/build

      - name: "🚀 release"
        id: semantic-release
        uses: docker://ghcr.io/open-sauced/semantic-release-conventional-config:3.0.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Enter fullscreen mode Exit fullscreen mode

The next step is a little verbose, in order to crawl our docs website we need to:

The deploy job is doing all the heavy lifting:

jobs:
  deploy:
    name: Deploy to static
    needs:
      - build
      - release
    runs-on: ubuntu-latest
    services:
      docs:
        image: ghcr.io/${{ github.repository }}:latest
        ports:
          - 8080:80
    steps:
      - name: "☁️ checkout repository"
        uses: actions/checkout@v2

      - name: "📂 download artifacts"
        uses: actions/download-artifact@v2
        with:
          name: build
          path: /home/runner/build

      - name: Install Prince
        run: |
          curl https://www.princexml.com/download/prince-14.2-linux-generic-x86_64.tar.gz -O
          tar zxf prince-14.2-linux-generic-x86_64.tar.gz
          cd prince-14.2-linux-generic-x86_64
          yes "" | sudo ./install.sh

      - name: "🔧 setup node"
        uses: actions/setup-node@v2.1.5
        with:
          node-version: 16

      - name: "🔧 install npm@latest"
        run: npm i -g npm@latest

      - name: "📦 install dependencies"
        uses: bahmutov/npm-install@v1

      - name: "📂 copy artifacts"
        run: cp -R /home/runner/build .

      - name: "🚀 generate pdf"
        run: npm run pdf

      - name: "🚀 deploy static"
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./build
          commit_message: ${{ github.event.head_commit.message }}
          enable_jekyll: false
          cname: docs.opensauced.pizza
Enter fullscreen mode Exit fullscreen mode

As a final step, we need to clean up our build and docker artifacts, a simple but necessary step:

jobs:
  cleanup:
    name: Cleanup actions
    needs:
      - deploy
    runs-on: ubuntu-latest
    steps:
      - name: "♻️ remove build artifacts"
        uses: geekyeggo/delete-artifact@v1
        with:
          name: |
            build
            docker
Enter fullscreen mode Exit fullscreen mode

Submission Category: DIY Deployments

Yaml File or Link to Code

Live repository using this workflow:

GitHub logo open-sauced / docs.opensauced.pizza

Docs dot Open Sauced is an static rendered documentation for open source developer onboarding

Open Sauced

docs.opensauced.pizza

The path to your next Open Source contribution

Commits Issues Releases Discord Twitter

🧪 Built for Experimenting

This tool is meant to accelerate development on Open Sauced by giving contributors a way to access Docusaurus 2 powered developer documentation available at docs.opensauced.pizza.

🤝 Contributing

We encourage you to contribute to Open Sauced! Please check out the Contributing guide for guidelines about how to proceed.

🖥️ Development

npm ci
npm start
Enter fullscreen mode Exit fullscreen mode

🍕 Community

Got Questions? Join the conversation in our Discord.
Find Open Sauced videos and release overviews on our YouTube Channel.

⚖️ LICENSE

MIT © Open Sauced

Yaml file link:
@open-sauced/docs.opensauced.pizza/main/.github/workflows/release.yml

Additional Resources / Info

Here are all the open source actions we are using to power this release workflow:

Be sure to include the DEV usernames of your collaborators:

mtfoley image

Discussion (0)