今年はコロナで出かけていないので、ちょっとGitHub Actionいじってます。
やりたいこと
タイトル通りですが、やりたいことは「GitHub Actionでタグを打ったときに、git-pr-releaseみたいな前のタグからのPRのリストをリリースノートに乗せたい」です。
やりかた
これを実施するにあたり、git-pr-releaseと違ってメインブランチとサブブランチを決めてそのPRを取るという手法が使えないので以下のようにする必要があります
- 前のタグからの今のタグへの全コミット取得
- PRのコミット取得
- 対象のPRを取得
- リリースノートに反映
前のタグからの今のタグへの全コミット取得
これはGitHubのAPIからは取れなかったので、Git操作で取得します。
git log
を使えば、あるタグから別のタグまでのコミットログを取れます。
また通常のログだといろいろな情報が乗ってくるので、formatしてあげて必要な情報に絞る必要があります。
今回はコミットハッシュだけがほしいので %H
だけを使います。
コマンドで示すと以下です。
$ git log v0.10.0...v0.10.1 --pretty=format:"%H"
それとは別にtag一覧を取って、最新と一つ前を取る必要があります。 sortを使うとタグのバージョンを考慮してsortしてくれるので使わない手はありません。 コマンドでは以下になります。
$ git tag --sort=-v:refname
これのsortでは v0.1.0. v0.8.0, v0.10.0 をちゃんと並べてくれます
これをGitHubActionでやる必要があるので、実施には actions/github-script@v3 を使います. github-scriptを使うとjsで操作を記述できる上に、GitHub APIが簡単に叩けます。
では特定タグ間のコミットログのハッシュ取得部分です。 jsの simple-git というライブラリを使ってGit操作を行っています。
const simpleGit = require('simple-git'); const git = simpleGit(path); // pathは操作するリポジトリの絶対パス const logs = await git.tags({ '--sort': '-v:refname' }) .then((t) => { const tags = t.all.slice(0, 2); return git.log({ 'from': tags[0], 'to': tags[1] }) });
slice(0,2)
と指定しているのは、sortされているので最新とその次を取るためです。
(一番最初のタグのときは考慮してないので、もしやる場合は考慮させましょう)
PRのコミットを取得
const { data } = await github.pulls.list({ owner: 'mocyuto', repo: 'ec2-search', base: 'master', state: 'closed', })
これだけでmasterに向けたmege済みのPRを取得できます。
他にも操作する場合は、以下のoctokitのページを見るといろいろわかります。
localで試したい場合は、以下を参考に試してみるといいと思います。
localの場合は octokit
を使い、github-scriptの中では github
を使えば動きます。
あとはjsでfilterするだけです。
リリースノートに反映
自分は action-gh-release を使っていたので、これをベースに説明します。
ほぼREADMEに書いてあることを実施すればいいのですが、一点リリースノートを追記する際、 bodyを記載した際は追記になるので、matrixで複数リリースノートへ書き込みを行うと同じ文言がmatrix分だけ乗ってしまいます。
ですので、matrixを利用している場合はjobをわけたほうがよいです。
実際のソースコード
以下がワークフローの記述部分です
simpe-git
を使うためにnpm installしています。
あとactions/checkout@v2
はデフォルトでdepth=1なので0を指定して全部取ってきましょう。
https://github.com/mocyuto/ec2-search/blob/v0.10.1/.github/workflows/release.yml#L77-L99
そして、呼び出しているスクリプトは以下です。
https://github.com/mocyuto/ec2-search/blob/v0.10.1/.github/script/prs.js
まとめ
最初は割と面倒かなと思ったのですが、github-scriptとsimple-gitのおかげでラップしてくれたので、以外に簡単にできました。 tag打ちのときの面倒の手助けになれば。