READMEに、リポジトリにおいているコードを埋め込みたい時があります。 そんな時に便利なのが、embedmeです。
今回は、GitHub Actionsを使ってREADMEにリポジトリのコードを埋め込むことをしたので紹介します。
概要
- GitHub Actionsでembedmeを実行して、README.mdにリポジトリのコードを埋め込み自動化ができる
- リポジトリとREADME.mdで同じコードを示す時の二重管理が解消するのでうれしい
- 軽量シンプルなので、pull_request、push、workflow_dispatchなど任意のトリガーで組めて便利
embedme の基本的な利用例
例として、README.mdにsrc/example.ts
の中身を埋め込むことを考えてみましょう。
まずはembedmeをインストールします。
npm install -g embedme
README.mdに次のようにコードブロックと言語を示しておいてリポジトリのファイルパスを示します。
https://gist.github.com/guitarrapc/6849719bbeb5b34042349eeef87b9325
TIPS: OS問わずファイルパスは
/
区切りがいいです。
あとは、インストールしたembedmeをREADME.mdに実行します。
embedme README.md
これでexample.tsのファイルがコードブロックに差し込まれます。便利。
https://gist.github.com/guitarrapc/3e0eda90cf93776aa68c7ede11ca85aa
行指定も直感的にできます。
// src/embedme.lib.ts#L44-L82
embedme のいいところ
個人的に気に入ってるところは3つあります。
埋め込むときに使ったコメントがコードブロックに残る
埋め込み後もコメントが残ることで、埋め込むソースコードを更新してembedmeを実行すると埋め込みが更新されるので、勝手にメンテが維持します。 どことリンクしていたかも一目瞭然で、README.mdを見る人が探すこともできるので好きです。
実行が軽い
インストール、実行が早いのはいいこととです。
npm install -g embedme
で入るので、GitHub ActionsなどのCIとの相性もいいです。
実行も即座に終了するのでカジュアルに走らせられる安心感があります。
実行履歴
README.mdの何行目のコードブロックを実行した、実行できなかったを理由を添えて表示してくれます。 例えばファイルパスが見つからず埋め込みできなかったら次のように教えてくれます。
README.md#L381-L383 Found filename .github\workflows\concurrency_control_cancel_in_progress.yaml in comment in first line, but file does not exist at /home/runner/work/githubactions-lab/githubactions-lab/.github\workflows\concurrency_control_cancel_in_progress.yaml!
十分です。
embedme で困るであろうこと
コードブロックのコメント
コードブロック内のコメントを検知するので、埋め込む前提になってないのにコメントを適当にいれたコードブロックを作ると警告は出ます。 ファイルパスが示されていないければ問題ないですが注意です。
言語ごとのコメントが違う
言語ごとに対応しているので当然ですが注意しましょう。
yamlやbashなら#
でコメント認識ですし、jsやtsなら//
でコメント認識です。
GitHub Actions で自動化する
embedmeはGitHub Actionsとしては公開されていないので適当に組みます。 今回は、GitHub Actionsをいろいろ試しているリポジトリで組んだ例を示します。
大量にyamlを埋め込んでいるので本当に助かっています。
GitHub Actions workflow を用意する
普段はpull_requestで実行して、変更があればPRにコミットを積むようにします。 必要に応じてworkflow_dispatchで手動更新もできるようにします。
https://gist.github.com/guitarrapc/f873228e307a3cda8a2f1ed682ef10e8
PRでリポジトリをcheckoutするときは、MergeコミットではなくPRのコミットをcheckoutします。
refを指定せずcheckoutすると、後段でgit push
したときにマージコミットがPRに入ってしまいます。
- if: ${{ github.event_name == 'pull_request' }} uses: actions/checkout@v3 with: ref: ${{ github.event.pull_request.head.sha }} # checkout PR HEAD commit instead of merge commit
19-22行目でembedded を実行します。
- name: Embedding Code into README run: | npm install -g embedme embedme README.md
あとは変更があればgit push
します。
- name: git diff id: diff run: | git add -N . git diff --name-only --exit-code continue-on-error: true - if: steps.diff.outcome == 'failure' name: git-commit run: | git config user.name github-actions[bot] git config user.email 41898282+github-actions[bot]@users.noreply.github.com git add . git commit -m "[auto commit] Embed code" - if: steps.diff.outcome == 'failure' name: Push changes uses: ad-m/github-push-action@master with: github_token: ${{ secrets.GITHUB_TOKEN }} branch: ${{ github.head_ref }}
pushで実行してもいいですが、私のリポジトリではREADMEの目次作成 (toc) をpushでやっているのでpull_requestにしています。 コード生成は重なると直列実行とcheckout時のref伝搬を気にしないといけないので注意です。
まとめ
embedme便利です。 あんまりREADMEにリポジトリのコードを埋め込むのを考えてこなかったのですが、いざやってみると便利でいろいろ使えそうです。(実際コピー&ペーストではることありますし)
補足情報として、類似したものにtokusumi/markdown-embed-codeがありますが、これはそもそも実行できなかったのとdockerのpullが走って重すぎるので好みじゃなかったです。