Docusaurus V3のdocs-to-pdf手続きを自動化する #GitHubActions

Docusaurus V3にてdocs-to-pdfを用いてPDF化を行いましたが、運用効率を考えてGitHub ActionsのWorkflow化を試みました。headless chromeの動作に手を焼きました。
2023.11.15

Docusaurus V3ドキュメントのPDF化にdocs-to-pdfを試していましたが、毎回手作業も手間なのでActions Workflowにて自動化を試みました。

設定したWorkFlow

事前にDocusaurusのプロジェクトを作成し、ドキュメントを記述したMarkdownファイルもコミットされている前提です。

name: Node.js CI

on:
  push:
    branches: [ "main" ]
  pull_request:
    branches: [ "main" ]
jobs:
  build:
    runs-on: ubuntu-latest
    env:
      PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: 'true'
      CI: 'true'
    defaults:
      run:
        working-directory: "my-website"
    strategy:
      matrix:
        node-version: [18.x]
        # See supported Node.js release schedule at https://nodejs.org/en/about/releases/
    steps:
    - uses: actions/checkout@v3
    - run: |
           sudo apt-get update
           sudo apt-get install -y gconf-service libasound2 libatk1.0-0 libatk-bridge2.0-0 libc6 libcairo2 libcups2 libdbus-1-3 libexpat1 libfontconfig1 libgcc1 libgconf-2-4 libgdk-pixbuf2.0-0 libglib2.0-0 libgtk-3-0 libnspr4 libpango-1.0-0 libpangocairo-1.0-0 libstdc++6 libx11-6 libx11-xcb1 libxcb1 libxcomposite1 libxcursor1 libxdamage1 libxext6 libxfixes3 libxi6 libxrandr2 libxrender1 libxss1 libxtst6 ca-certificates fonts-liberation libappindicator1 libnss3 lsb-release xdg-utils wget
           sudo apt-get install -y libgbm-dev
           sudo apt-get install -y chromium-browser
    - name: Use Node.js ${{ matrix.node-version }}
      uses: actions/setup-node@v3
      with:
        node-version: ${{ matrix.node-version }}
        args: install
    - uses: mujo-code/puppeteer-headful@16.6.0
      env:
        CI: "true"
    - run: |
           npm install
           npm run docusaurus build
           npm run docusaurus serve &
    - name: Sleep for 30 seconds
      run: sleep 30s
      shell: bash
    - run: |
           npx docs-to-pdf --initialDocURLs="http://localhost:3000/docs/" --contentSelector="article" --paginationSelector="a.pagination-nav__link.pagination-nav__link--next" --excludeSelectors=".margin-vert--xl a,[class^='tocCollapsible'],.breadcrumbs,.theme-edit-this-page" --coverImage="http://localhost:3000/img/docusaurus.png" --coverTitle="Docusaurus v2"
    - name: Archive code coverage results
      uses: actions/upload-artifact@v3
      with:
        name: docs-to-pdf
        path: ${{ github.workspace }}/**/docs-to-pdf.pdf

注意点

今回のWorkflowは敢えて冗長にしている箇所があります。

  • docs-to-pdfのエラー対策で独立したchrome導入
  • docusaurus起動後のheadless chromeアタッチ対策で暫くスリープ

docs-to-pdfのエラー対策で独立したchrome導入

docs-to-pdfによるスクレイピングを対策無しで実行すると以下のエラーとなります。

[ERROR] Error: Failed to launch the browser process! spawn /home/runner/.cache/puppeteer/chrome/linux-119.0.6045.105/chrome-linux64/chrome ENOENT

対策としてpupeteerの依存ライブラリを個別導入しましたが、変わらず。

そこで、別途puppeteer-headful経由でchromeをインストール、及びPUPPETEER_SKIP_CHROMIUM_DOWNLOADのフラグを指定しています。

このpuppeteer-headfulのアクション指定とPUPPETEER_SKIP_CHROMIUM_DOWNLOADを環境変数に設定することで1度は実行できましたが、node_modulesをcacheから再利用した時点で元のエラーが再発しました。cacheからの個別対処がしづらく、cacheしないという選択肢をとっています。

docusaurus起動後のheadless chromeアタッチ対策で暫くスリープ

docusaurus serveをそのまま実行するとworkflowが先に進まなくなるためバックグラウンドプロセス化。その直後にdocs-to-pdfを実行していましたが、ポートフォワーディングが完了する前にアタッチを開始するようでエラーとなりました。

wait_for_responseで500が帰ってこなくなったら続行する処理も試しましたが、そもそもアタッチできなければステータスもとれません。

結論として、とりあえず待ちを少し入れれば良いはずと、sleepを入れました。試しに30秒にしていますが、実際はもっと短くても問題ないかもしれません。

なお、バックグラウンド化したプロセスはWorkflow終了時にTerminateされています。

あとがき

Action通しの繋ぎが難しいのはGitHub Workflowでよくあることですが、headless chromeの動作にこれほど振り回されるとは思いませんでした。

生成されたPDFはアクセスのためにupload-artifactを用いていますが、適切なアップロード先に転送するのもありです。