こんにちは、お散歩の時に道に落ちていたごみを見た娘が「こんな所に捨てて駄目ね、この美しい私達の街を守らないと!」と言ってきてビックリした木村です。何事かと思ったらどうも何かのTVのセリフを覚えてたようです。
この記事はInfocom Advent Calendar 2022の14日目の記事です。
弊社はGitHubの公式パートナーで、GitHub Enterpriseも取り扱っています。
そういったこともあり、今年のオルターブース Advent Calendar 2022はGitHub関連の記事も沢山エントリーしていますので皆さん是非ご覧いただけたらと思います。
せっかくなので私もGitHub Actionsでやってみたことを書こうかと思います。
報告書作成のワークフロー
皆さん、普段の報告書はどういう形で残されていますか?Wordで書かれたり、何らかの文書管理システムで書かれたりというケースは多いかと思いますが、弊社では基本的にマークダウン形式で記載し、gitで管理しています。そして、お客様に提出する際はPDFに変換して送付しています。
今年に入って社内のワークフローをGitHubに寄せていこうという動きの中で、この報告書についてもGitHubで管理することになりました。ワークフローは以下のような感じです。
- 報告書を保存するリポジトリを作成する(初回のみ)
- 報告書を作成するときはIssueを作成し、そこから作成用のブランチを作って報告書を書く
- 報告書に必要な情報のやり取りや質問はIssue内で行う
- マークダウン形式で報告書を書き終えたら、プロジェクトの責任者をレビュアーとしてプルリクエストを作成する
- 責任者は問題なければプルリクエストをマージする
- マージされた文書をPDFに変換し、顧客に送付する
- 提出したらIssueをクローズする
一般的なgitでの開発フローをそのまま文書作成にも利用している感じですね。
このフローの「PDFに変換する」という部分は、これまではVisualStudio CodeのMarkdown PDF拡張機能を使って手動でやっていたのですが、せっかくGitHubでやってるので自動化しようと思ってちょっと試してみました。
作成するワークフロー
今回、以下のようなワークフローを作成することにします。
- masterブランチへのコミットをターゲットに動かす
- コミットで更新された全てのマークダウンファイルについて、PDFに変換する
- 変換は独自に準備したコンテナで行う
- 変換にはmd-to-pdfを使う
- 最後に更新されたReleaseに、
docs-yyyymmdd-id.tgz
という名前でアップロードする subdir1/subdir2/sample.md
のようなファイル名の場合、subdir1_subdir2_sample.pdf
というファイル名になる- ファイル名やディレクトリ名は日本語も可
PDFファイルはアーティファクトにアップロードするだけでも良かったのですが、Releaseへのファイル配置も試してみたかったので盛り込んでいます。
コンテナイメージの準備
md-to-pdfを動かすために、Node.jsの最新版のイメージをベースにして必要なライブラリ等をインストールしていきます。
Dockerfileは以下のようになります。
FROM node:latest RUN apt update -y RUN apt install -y libnss3-dev RUN apt install -y libatk1.0-0 RUN apt install -y libatk-bridge2.0-0 RUN apt install -y libcups2 RUN apt install -y libdrm2 RUN apt install -y libxkbcommon-x11-0 RUN apt install -y libxcomposite-dev RUN apt install -y libxdamage-dev RUN apt install -y libxrandr-dev RUN apt install -y libgbm-dev RUN apt install -y libasound2 RUN apt install -y fonts-noto RUN apt install -y fonts-ipafont-gothic RUN apt install -y locales RUN sed -i -E 's/# (ja_JP.UTF-8)/\1/' /etc/locale.gen RUN locale-gen RUN update-locale LANG=ja_JP.UTF-8 RUN yarn add md-to-pdf COPY md2pdf.sh /usr/bin/
apt install
は1行にまとめられると思いますが、必要なライブラリを確認しながら作成した状況を残すためにこの形にしています。
最後に/usr/bin/
にコピーしている、変換を行うシェルスクリプトmd2pdf.sh
はこちらです。引数で渡されたファイルに対して、出力ファイル名を調整しながらmd-to-pdf
を動かす感じですね。
#!/bin/bash export LANG=ja_JP.UTF-8 for file in $@;do suf=`echo $file | sed 's/^.*\.\([^\.]*\)$/\1/'` if [ $suf = 'md' ] ; then outfile=`echo $file | sed 's/\//_/g' |sed 's/\.md$/\.pdf/i'` cat $file | npx md-to-pdf --launch-options '{"args": ["--no-sandbox"]}' --md-file-encoding utf-8 > $outfile fi done tar cvfz docs.tgz `find . -name '*.pdf'`
このコンテナイメージを適当なところに置きます。私はdocker hubに置いています。
ワークフローを作成する
ワークフローを以下のように作成します。
name: CI on: push: branches: [ master ] jobs: container-test-job: runs-on: ubuntu-latest container: image: kenichirokimura/md2pdf:latest options: --cpus 1 steps: - name: Checkout uses: actions/checkout@v2 with: fetch-depth: 0 - name: Git config run: git config --local core.quotepath false - name: Get changed files id: changed-files uses: tj-actions/changed-files@v10.1 - name: Md2pdf run: /usr/bin/md2pdf.sh ${{ steps.changed-files.outputs.all_modified_files }} - name: Gets latest created release info id: latest_release_info uses: jossef/action-latest-release-info@v1.1.0 env: GITHUB_TOKEN: ${{ github.token }} - name: Upload Release Asset id: upload-release-asset uses: WebFreak001/deploy-nightly@v1.1.0 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} with: upload_url: ${{ steps.latest_release_info.outputs.upload_url }} release_id: ${{ steps.latest_release_info.outputs.id }} asset_path: ./docs.tgz asset_name: docs-$$.tgz asset_content_type: application/x-gzip
先ほどのコンテナイメージをjobs.container-test-job.container.image
で指定しています。
Get changed files
ステップで、今回のコミットで変更になったファイル名の一覧を取得します。取得にはtj-actions/changed-filesを使います。
Md2pdf
ステップでは、Get changed files
ステップの結果(変更になったファイル名の一覧)をsteps.changed-files.outputs.all_modified_files
で取得して、コンテナ内のmd2pdf.sh
シェルスクリプトを起動します。
Gets latest created release info
ステップでは、最新のリリース情報を取得します。取得にはjossef/action-latest-release-infoを使います。
最後にUpload Release Asset
ステップで、Gets latest created release info
ステップで取得したアップロード先のURLならびにリリース先を使って、作成したファイルをアップロードします。アップロードにはWebFreak001/deploy-nightlyを使います。このアクションの機能で、Releaseにdocs-{yyyy}{mm}{dd}-{id}.tgz
というファイルがアップロードされます。
なお、このワークフローでは「最後に更新したReleaseに対してアップする」という動作のため、事前にReleaseを1つ作っておく必要がありますのでご注意ください(手抜き)。
まとめ
今回作ったワークフローで、マークダウンファイルのPDFへの変換を自動化できました。現在はPDFをReleaseにアップロードしていますが、いずれは作成したPDFをお客様に提出する部分まで自動化できればと思っています。
ここまで作ったものを、以下のリポジトリで公開しています。実際にアクションを動かしてReleaseにPDFを設置もしていますので、興味のある方はそちらを参照したり、forkして色々と試してみてください。
皆様の参考になれば幸いです。