Pull RequestトリガーのGitHub ActionsでSkip CIを実現する (Deprecated)
この記事で説明している手法は不要になりました
GitHub Actionsは、組み込みでSkip CIをサポートするようになりました (GitHub Actions: Skip pull request and push workflows with [skip ci] - GitHub Changelog)。コミットメッセージに以下のキーワードが含まれていると、Workflowの実行が自動的にスキップされます。
[skip ci]
[ci skip]
[no ci]
[skip actions]
[actions skip]
そのため、この記事で紹介しているSkip CIの実現方法は不要になりました。記事を残しておきますが、以下で説明するJobをWorkflowに追加する必要はありません。
ここから不要になった方法の紹介です
Pull Requestトリガーで実行されるGitHub Actions Workflowで、コミットメッセージに [skip ci]
などの特定のキーワードが含まれていたら、ビルドの実行をキャンセルする方法を紹介します。
PushトリガーのWorkflowの場合
PushトリガーのWorkflowでは、以下の記事で紹介されている方法で、Skip CIの仕組みを実現できます。
WorkflowがPushイベントで起動した場合、github
コンテキストの github.event.head_commit.message
プロパティにコミットメッセージが設定されています。contains
組み込み関数でコミットメッセージがキーワードを含んでいるかどうかを調べ、その結果を反転してJobの if
に設定すれば、Jobの実行有無を制御することができます。
on: push
jobs:
accept_commit:
runs-on: ubuntu-20.04
if: "! contains(github.event.head_commit.message, '[skip ci]')"
steps:
- run: echo "build is NOT skipped"
build:
runs-on: ubuntu-20.04
needs: accept_commit
steps:
Pull RequestトリガーのWorkflowの場合
Pull RequestトリガーのWorkflowでは、github
コンテキストのプロパティにコミットメッセージが入ってこないので、上記の方法は使うことができません。その代わり、コミットのハッシュが github.event.pull_request.head.sha
プロパティでわかるため、git log
コマンドでコミットメッセージを取得し、grep
コマンドでキーワードの有無を調べることができます。以下に例を示します。
on: pull_request
jobs:
check_commit:
runs-on: ubuntu-20.04
env:
SKIP_CI_KEYWORD: "[skip ci]"
outputs:
skip_ci: ${{ steps.check_message.outputs.skip_ci }}
steps:
- uses: actions/checkout@v2
with:
fetch-depth: 2
- name: Check commit message
id: check_message
run: |
message=$(git log --format=%B -n 1 ${{ github.event.pull_request.head.sha }})
if echo "$message" | grep -q -F "${{ env.SKIP_CI_KEYWORD }}"; then
echo "::set-output name=skip_ci::true"
else
echo "::set-output name=skip_ci::false"
fi
build:
runs-on: ubuntu-20.04
needs: check_commit
if: ${{ needs.check_commit.outputs.skip_ci != 'true' }}
steps:
check_commit
ジョブで、以下のことを実行しています。
- リポジトリをチェックアウトする
- コミットハッシュ
github.event.pull_request.head.sha
のコミットメッセージを取得して、[skip ci]
キーワードが含まれているかどうかを調べる - 調べた結果を、
check_commit
ジョブのOutputskip_ci
にtrue
orfalse
で設定する
後続のジョブは、needs
で check_commit
ジョブに依存することを宣言し、needs.check_commit.outputs.skip_ci
で check_commit
ジョブの skip_ci
Outputを参照することができます。あとは、ジョブの if
条件文で、needs.check_commit.outputs.skip_ci
が true
でない場合にジョブを実行する (= needs.check_commit.outputs.skip_ci
が true
だったらジョブの実行をキャンセルする)、と記述することで、Skip CIの仕組みを実現できます。
ここで、check_commit
ジョブにおいて、GITHUB_SHA
をコミットのハッシュとして利用することはできないので、注意が必要です。Pull RequestトリガーのWorkflowでは、GITHUB_REF
はGitHubが自動的に生成するのPRマージブランチ refs/pull/:prNumber/merge
を指しており、GITHUB_SHA
はこのPRマージブランチの最新コミットを指しています (Events that trigger workflows - GitHub Docs)。PRマージブランチは、GitHubが自動的に生成するブランチで、Pull Requestの作業ブランチとベースブランチをマージした状態を追跡しています。Pull Requestの作業ブランチとベースブランチのマージコミットが常に自動的に作成されており、Pull RequestトリガーのWorkflowでは GITHUB_SHA
はそのマージコミットを指しています。今回、コミットメッセージを調べたいコミットは、Pull Request作業ブランチの最新コミット = マージコミット (GITHUB_SHA
) の1つ前のコミットです。actions/checkout@v2
アクションは、デフォルトでは GITHUB_SHA
のコミットだけしかチェックアウトしないので、fetch-depth: 2
パラメーターを指定してその1つ前のコミットまでチェックアウトし、GITHUB_SHA
ではなく github.event.pull_request.head.sha
のコミットを調べる必要があります。
GitHub Actionsのサンプル
上で紹介した方法のサンプルは、kafumi/github-actions-skip-ci-samples に配置してあります。
- PushトリガーのWorkflowのサンプル:
.github/workflows/push.yml
- Pull RequestトリガーのWorkflowのサンプル:
.github/workflows/pull_request.yml
Discussion