この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
こんにちは、CX事業本部 IoT事業部の若槻です。
今回は、GitHub Actionsで、GitHub CLIで取得したアイテムのリストをmatrix構文で処理してみました。
matrix構文とは
GitHub Actionsのmatrix構文を使うと、単一のJobの記述で複数パターンの変数要素を指定し、それぞれのパターンに対してJobを実行することができます。
使い方は次のようになります。Jobのstrategy.matrix
で配列形式で変数要素を指定します。
jobs:
example_matrix:
strategy:
matrix:
version: [10, 12, 14]
os: [ubuntu-latest, windows-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/setup-node@v3
with:
node-version: ${{ matrix.version }}
上記はos
が2要素、version
が3要素であるため、合わせて6パターンのJobが実行されます。
{version: 10, os: ubuntu-latest}
{version: 10, os: windows-latest}
{version: 12, os: ubuntu-latest}
{version: 12, os: windows-latest}
{version: 14, os: ubuntu-latest}
{version: 14, os: windows-latest}
このように、変数要素のパターンを変えながらJobを実行したい場合に、要素ごとにWorkflowの実行やJobの記述を分けたりする必要が無くなってとても便利です。
GitHub CLIで取得したアイテムのリストをmatrixで処理する
matrix構文で指定する変数要素は、Workflow実行内で動的に生成することも可能です。ここではGitHub CLIのgh pr listコマンドで取得したPull Requestのリストを処理してみます。
次のWorkflowでは、1つ目のJobでPull RequestのIssue番号のリストをContextに指定し、2つ目のJobでmatrixに使用しています。このようにJobを2段階にすることによりmarixの要素を動的に生成することができます。
.github/workflows/matrix.yml
on:
push
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
get_pr_matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.value }}
steps:
- name: Checkout
uses: actions/checkout@v3
- id: matrix
run: |
pr_list=$(gh pr list --json number --limit 5 | jq '[.[].number]')
echo "::set-output name=value::$(echo $pr_list | jq -c .)"
do_process:
needs: get_pr_matrix
runs-on: ubuntu-latest
strategy:
matrix:
value: ${{ fromJson(needs.get_pr_matrix.outputs.matrix) }}
steps:
- name: Processing for each pull request
- run: |
echo ${{ matrix.value }}
ポイントとしては、CLIで取得したアイテムをjq
コマンドでJsonパースしてContextに指定する際にコンパクト処理(-c
オプション)をしている所です。
# コンパクト処理をしない場合
$ gh pr list --json number --limit 5 | jq '[.[].number]'
[
1381,
1376,
1373,
1370,
1368
]
# コンパクト処理をした場合
$ pr_list=$(gh pr list --json number --limit 5 | jq '[.[].number]')
$ echo $pr_list | jq -c .
[1381,1376,1373,1370,1368]
コンパクト処理をしない(改行記号が含まれている)配列はmatrix要素に指定することはできないためです。(また、1回目のjq
実行でコンパクト処理をしていない理由としては、コンパクト処理していない値をGitHub Actions Workflow上ではなぜか変数で上手く扱えなかったためです。)
PushしてWorkflowを実行すると、matrixによりPull Request毎にJobが分けられて処理されています。(13XX
が取得したPull RequestのIssue番号です。)
matrixにより実行されるそれぞれのJob名は<Step名> (matrix要素)
となり、Workflow実行画面上での表示にも使用されるため、それを意識した要素(今回はIssue番号)を使うと良いかと思います。
おまけ:そもそもやりたかったこと
参考までに、matrix構文を使用して元々やりたかったこととしては、Cronで実行して条件に合致するPull Requestを自動でMergeする処理です。この時にGitHub CLIで取得したそれぞれのPull Requestに対して、条件の一致チェックとBase BranchへのMergeを行う必要があったため、matrix構文がとても役に立ちました。
.github/workflows/cron.yml
# そもそもやりたかったこと
on:
schedule:
- cron: 0 15 * * *
push:
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
jobs:
get_pr_matrix:
runs-on: ubuntu-latest
outputs:
matrix: ${{ steps.matrix.outputs.value }}
steps:
- name: Checkout
uses: actions/checkout@v3
- id: matrix
run: |
pr_list=$(gh pr list --json number | jq '[.[].number]')
echo "::set-output name=value::$(echo $pr_list | jq -c .)"
merge_pr:
needs: get_pr_matrix
runs-on: ubuntu-latest
strategy:
matrix:
value: ${{ fromJson(needs.get_pr_matrix.outputs.matrix) }}
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Set pull request info to Context
id: set_pr_info_to_context
run: |
pull_request=$(gh pr view ${{ matrix.value }} --json title,commits,comments | jq .)
echo ${pull_request} | jq .
last_comment_body=$(echo ${pull_request} | jq -r '.comments | .[-1].body')
echo "LAST_COMMENT_BODY=${last_comment_body}" >> $GITHUB_ENV
last_commented_at=$(echo $pull_request | jq -r '.comments | .[-1].createdAt')
unixtime_last_commented_at=$(date -d ${last_commented_at} '+%s')
echo "UNIXTIME_LAST_COMMENTED_AT=${unixtime_last_commented_at}" >> $GITHUB_ENV
last_commit_date=$(echo $pull_request | jq -r '.commits | .[-1].committedDate')
unixtime_last_committed_at=$(date -d ${last_commit_date} '+%s')
echo "UNIXTIME_LAST_COMMITTED_AT=${unixtime_last_committed_at}" >> $GITHUB_ENV
echo "UNIXTIME_THREE_DAYS_AGO=$(date --date "-3 day" '+%s')" >> $GITHUB_ENV
- name: Merge Pull Request
if:
env.LAST_COMMENT_BODY == 'published' &&
env.UNIXTIME_LAST_COMMITTED_AT < env.UNIXTIME_LAST_COMMENTED_AT &&
env.UNIXTIME_LAST_COMMENTED_AT < env.UNIXTIME_THREE_DAYS_AGO
run: |
gh pr merge ${{ matrix.value }} --merge
おわりに
GitHub Actionsで、GitHub CLIで取得したアイテムのリストをmatrix構文で処理してみました。
元々はShellのfor loop
構文を使って行っていた処理が、matrix構文を使うことにより簡略化され、また実行画面上でも処理が可視化できるようになりました。GitHub Actionsの便利なBuilt-in機能なのでどんどん使っていきたいですね!
参考
以上