内容
GitHub Actionsを構成するコンポーネントの概要と要点について記載する
イベント
各イベント説明に記載されているGITHUB_REF
、GITHUB_SHA
は、ブランチ名、コミットIDで、
workflowはそのソースコードの状態で実行される
actions/checkout
でソースコードをcheckoutする際にデフォルトではこのブランチ名、コミットIDが使用される(パラメータrefで変更可能)
Noteに「このイベントは、ワークフローファイルがデフォルト ブランチにある場合にのみワークフローの実行をトリガーします。」とあるイベントは、
デフォルトブランチにworkflowの実装がマージされたあとでしか実行・動作確認できないため注意
pull_request
PRの各種操作をトリガーにworkflowを起動する
以下のようにブランチやファイルパスでイベントのフィルターも可能
on:
pull_request:
types:
- opened
- synchronize
branches:
- 'releases/**'
paths:
- '**.js'
使用頻度の高いtypesとしてはopened
, closed
, synchronize
等、
PRのマージ時にworkflowを実行する場合は以下のようにgithub.event.pull_request.merged
と合わせて判定する
on:
pull_request:
types:
- closed
jobs:
if_merged:
if: github.event.pull_request.merged == true
runs-on: ubuntu-latest
steps:
- run: |
echo The PR was merged
typesopened
, synchronize
でPR発行時、PRに対してコミットpush時にテストworkflowを実行、
typesclosed
でPRマージ時に実環境にデプロイする等の使い分けが考えられる
synchronize
を入れるとコミット頻度が高い場合や、workflowが重い場合にActionsの実行時間が増加して料金への影響もあるため要検討
pull_requestイベントはGITHUB_REF
、GITHUB_SHA
が特殊で、
PRマージブランチ(PRがマージされた後の状態のソースコード)になる
pull requestのheadブランチへの最後のコミットのコミットIDを取得する場合は、
代わりにgithub.event.pull_request.head.sha
を使用する
「このイベントは、ワークフローファイルがデフォルト ブランチにある場合にのみワークフローの実行をトリガーします。」の記載がないため、
pull_requestトリガーのworkflowを新規追加したPRを発行すると、そのPRに対してworkflowがトリガーされる
workflow_dispatch
workflowを手動実行する際に使用する
「このイベントは、ワークフローファイルがデフォルト ブランチにある場合にのみワークフローの実行をトリガーします。」の記載があるが、
デフォルトブランチにdispatch workflowがあり、他ブランチでそのworkflowを変更、pushした場合は、
以下のように他ブランチを選択して実行することで変更が反映された状態で実行することができる
workflow_call
他のworkflowからworkflowを呼び出す際に使用する
他イベントとは用途が違って、workflowの共通化や、冗長性の解消等に使用する
reusable-workflowsで後述
workflows
workflowのトリガーとなるイベントとjob,stepから構成される
name: Run CI
on: [push, pull_request]
jobs:
normal_ci:
runs-on: ubuntu-latest
steps:
- name: Run normal CI
run: echo "Running normal CI"
pull_request_ci:
runs-on: ubuntu-latest
if: ${{ github.event_name == 'pull_request' }} # イベント名を参照
steps:
- name: Run PR CI
run: echo "Running PR only CI"
上記github.event_name
のようにワークフローの実行、変数、ランナーの環境、ジョブ、ステップに関する情報にはコンテキストを使ってアクセスする
github コンテキストのevent
github.event
にはGitHubのWebhookペイロードが含まれる(例:pull_request)
github.event
は、トリガーのイベントによって内容が異なる
そのため、共通処理のreusable-workflowやcomposite-action内でgithub.event.pull_request.head.sha
のようなイベント依存の値を参照すると、
pull_request
以外のイベントでは参照できないため注意が必要
env
以下のように各階層で環境変数envを定義することができる(変数に情報を格納する抜粋)
name: Greeting on variable day
on:
workflow_dispatch
env: # workflowレベルの環境変数
DAY_OF_WEEK: Monday
jobs:
greeting_job:
runs-on: ubuntu-latest
env: # jobレベルの環境変数
Greeting: Hello
steps:
- name: "Say Hello Mona it's Monday"
run: echo "$Greeting $First_Name. Today is $DAY_OF_WEEK!"
env: # stepレベルの環境変数
First_Name: Mona
ただし、workflow_callイベントの場合はトップ階層のenvが使用できない(issues: https://github.com/actions/runner/issues/2372)
on:
workflow_call:
env:
env_1: 123
jobs:
job_1:
runs-on: ubuntu-latest
env:
env_2: ${{ env.env_1 }} # ERROR (Unrecognized named-value: 'env', Available expression contexts: github, inputs, vars, needs, strategy, matrix, secrets)
steps:
- run: echo "hello"
解決方法として、inputsのdefaultで代用することができる
on:
workflow_call:
inputs:
param_1:
required: false # 呼び出し元から指定されない前提
type: string
default: 123
jobs:
job_1:
runs-on: ubuntu-latest
env:
env_2: ${{ inputs.param_1 }}
steps:
- run: echo "hello"
reusable-workflows
reusable-workflowsはworkflow_call
イベントによって実行される
以下、reusable-workflowstest_1.yml
workflowはuses
で呼び出す例
secrets: inherit
を指定することで、organization、repository、environmentレベルのシークレットを継承できる
ただし、github.token
、secrets.GITHUB_TOKEN
へのアクセス権は自動的に呼び出し先workflowに付与される(GITHUB_TOKEN
についてはpermissions参照)
name: 適当なreusable-workflows
on:
workflow_call:
jobs:
job_1:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
jobs:
test_1:
secrets: inherit # reusable-workflowsへのシークレットの継承
uses: ./.github/workflows/test_1.yml # reusable-workflows呼び出し
workflow_dispatch
, workflow_call
は、workflowに対するパラメータ(inputs)が指定できる
指定できるinputsのtypeはそれぞれ異なり、
workflow_dispatch
でinputsに指定できるtype(on.workflow_dispatch.inputs..type)は、boolean、choice、number、environmentまたはstring
workflow_call
でinputsに指定できるtype(on.workflow_call.inputs..type)は、boolean、number、または string
また、workflowの出力(outputs)も指定できる
stepの出力をworkflowの出力にする場合、以下のようにsteps → jobs → workflowの順で出力を連携する必要がある
name: Test output
on:
workflow_call:
inputs:
param_1:
required: true
type: string
outputs:
workflow_output: # jobsのoutputをworkflowのoutputに連携
value: ${{ jobs.job_1.outputs.job_output }}
jobs:
job_1:
runs-on: ubuntu-latest
outputs:
job_output: ${{ steps.output_step.outputs.output_1 }} # stepsのoutputをjobsのoutputに連携
steps:
- uses: actions/checkout@v4
- id: output_step
run: |
output="hello"
echo "output_1=${output}" >> $GITHUB_OUTPUT
呼び出し元では以下のようにinputsを指定、outputsを参照する
jobs:
test_1:
secrets: inherit
uses: ./.github/workflows/test_1.yml
with:
param_1: "test" # reusable-workflowsのinputs指定
test_2:
runs-on: ubuntu-latest
env:
test_1_output: ${{ jobs.test_1.outputs.workflow_output }} # reusable-workflowsのoutputsを参照
steps:
- run: |
echo $test_1_output
job
jobには以下のようにruns-on
, permissions
, environment
, needs
, env
, steps
等を指定できる
jobs:
test_1:
...
test_2:
name: Test 2
runs-on: ubuntu-latest
permissions:
id-token: write
contents: write
pull-requests: write
environment:
name: dev
needs: [test_1]
env:
env_1: "abc"
steps:
- uses: actions/checkout@v4
- name: Build Python
id: build_python
...
各Jobはそれぞれ異なる環境のため、
Jobでcheckoutしたソースコード、インストールしたツール、作成したファイル等は他Jobに引き継がれない
そのため、Jobを分けすぎると無駄に環境構築処理が複数回発生し、処理時間の増加につながる
cache(actions/cache)や、artifact(actions/upload-artifact) を使うことでJob間でファイルを共有することができる
cache、artifactについてはGitHub Actions - cacheとartifact参照
runs-on
runs-on
にはランナー(jobの実行に使用するimage)を指定する
ubuntu-latest
やwindows-latest
等、基本的には標準のGitHubでホストされたランナーにある中から選択する
各ランナーのリンクから、該当のランナーにインストールされているツールの情報が確認できる(例: ubuntu-latest
)
ユーザが管理するセルフホステッドランナーを使用することもできる(GitHub Actions - セルフホステッド ランナー(AWS CodeBuild)にて使用方法を記載)
permissions
GitHubの操作を行うActionに使用されるGITHUB_TOKEN
の権限の変更に使用する
permissionsにある中から選択する
githubコンテキストのtokengithub.token
とGITHUB_TOKEN
は同じものである
actions/checkout
もGitHub操作であるため、デフォルトでGITHUB_TOKEN
を使用している(パラメータtoken
で変更可能)
GitHub CLI等でGitHub操作をする場合は、以下のように環境変数でGITHUB_TOKEN
を渡す必要がある(GITHUB_TOKEN シークレットについて抜粋)
name: Open new issue
on: workflow_dispatch
jobs:
open-issue:
runs-on: ubuntu-latest
permissions:
contents: read
issues: write
steps:
- run: |
gh issue --repo ${{ github.repository }} \
create --title "Issue title" --body "Issue body"
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
environment
GitHub Actions - environment と Deployment protection rules参照
needs
workflow内に複数のJobが存在する場合、既定では全Jobは並列実行される
Jobの実行順番を制御するためにはneeds
を使用してJobの依存関係を指定する
needs
に指定されたJobが成功した場合のみJobが実行される
jobs:
job1:
job2:
needs: job1
job3:
needs: [job1, job2]
needs
に指定したJobの成功/失敗問わずJobを実行したい場合は以下のようにalways()
を使用する
jobs:
job1:
job2:
needs: job1
job3:
if: ${{ always() }}
needs: [job1, job2]
needs
に指定したJobの出力(jobs..outputs)は以下のようにアクセスできる
jobs:
job1:
runs-on: ubuntu-latest
# Map a step output to a job output
outputs:
output1: ${{ steps.step1.outputs.test }}
output2: ${{ steps.step2.outputs.test }}
steps:
- id: step1
run: echo "test=hello" >> "$GITHUB_OUTPUT"
- id: step2
run: echo "test=world" >> "$GITHUB_OUTPUT"
job2:
runs-on: ubuntu-latest
needs: job1
steps:
- env:
OUTPUT1: ${{needs.job1.outputs.output1}}
OUTPUT2: ${{needs.job1.outputs.output2}}
run: echo "$OUTPUT1 $OUTPUT2"
step
ステップでは、コマンドを実行する、設定タスクを実行する、
あるいはactions/checkout
のような公開されたアクションを実行することができる
composite-action
複数stepからなる処理を共通化したい場合等に使用する
実装したcomposite-actionは、.github/actions/{任意の名前}/action.yml
に格納しておく
以下、AWS認証を行うcomposite-actionと実行例
name: AWS Credentials Setting
description: Configure AWS credentials
inputs:
region:
description: AWS region
required: true
account_id:
description: AWS account
required: true
role_name:
description: Role to assume
required: true
runs:
using: "composite" # composite-action指定
steps:
- uses: aws-actions/configure-aws-credentials@v4
with:
aws-region: ${{ inputs.region }}
role-to-assume: arn:aws:iam::${{ inputs.account_id }}:role/${{ inputs.role_name }}
role-duration-seconds: 3600
jobs:
aws_:
runs-on: ubuntu-latest
permissions:
id-token: write
environment:
name: dev
steps:
- uses: actions/checkout@v4 # composite-action実行前にcheckoutが必須
- uses: ./.github/actions/aws-credential
with:
account_id: ${{ vars.ACCOUNT_ID }}
region: ${{ vars.REGION }}
role_name: ${{ secrets.ASSUME_ROLE_NAME }}
composite-action実行前にcheckoutが必須となる
composite-action内ではsecretsが参照できない、そのためsecretsを使用する場合はinputsで渡す必要がある
composite-action内ではコマンド実行(run
)を行う際に、shell: bash
のようにshell指定が必須となる