こんにちは。2022年11月に株式会社タイミーに入社した sinsoku です。
最近はGitHub ActionsのYAMLを書く機会が多く、YAMLも複雑化してきました。
しかし、日常的にYAMLを触っている職人以外にはパッと読めないことも多いので、社内の方々が読めるようにGitHub ActionsのYAMLの書き方をまとめたいと思います。
目次
三項演算子
GitHub Actions には三項演算子がないため、代わりに論理演算子を使います。
- steps: - run: echo "${{ (github.ref == 'refs/heads/main' && 'production') || 'staging' }}"
参考: Expressions
環境変数(env)
環境変数を使いたい場合は env
で定義します。
env: TIMEE_CEO: ryo TIMEE_CTO: kameike jobs: job-env: runs-on: ubuntu-latest steps: - run: echo $TIMEE_CEO # この実装だと置換後の文字列 `echo kameike` を実行する - run: echo ${{ env.TIMEE_CTO }}
ただし、 env で env の値を指定するとエラーになるケースがあるので注意してください。
env: DEPLOY_ENV: ${{ (github.ref == 'refs/heads/main' && 'production') || 'staging' }} # Unrecognized named-value: 'env'. Located at position 1 within expression: env.DEPLOY_ENV == 'production' IS_PROD: ${{ env.DEPLOY_ENV == 'production' }}
jobs.<job_id>.env
でも同様のエラーが出ます。
jobs: job-error: runs-on: ubuntu-latest # Unrecognized named-value: 'env'. Located at position 1 within expression: env.DEPLOY_ENV == 'production' IS_PROD: ${{ env.DEPLOY_ENV == 'production' }}
jobs.<job_id>.steps[*].env
であればエラーになりませんが、同じ階層の env の値は参照できません。
env: TIMEE_CTO: kameike jobs: job-env: runs-on: ubuntu-latest steps: # この実装だと `echo "true, foo, -bar"` を実行する - run: echo "${{ env.IS_KAMEIKE }}, ${{ env.FOO }}, ${{ env.BAR }}" env: IS_KAMEIKE: ${{ env.TIMEE_CTO == 'kameike' }} FOO: foo BAR: ${{ env.FOO }}-bar
参考: Workflow syntax for GitHub Actions
変数(outputs)
汎用的な名前の環境変数を定義すると、何かのCLIコマンドに影響する可能性があります。
これを避けるために、outputs で変数を定義することもできます。
steps: - id: var run: | echo "x=foo" >> "$GITHUB_OUTPUT" echo "y=bar" >> "$GITHUB_OUTPUT" # この実装だと `echo "foo, bar"` を実行する - run: echo "${{ steps.var.outputs.x }}, ${{ steps.var.outputs.y }}"
outputs は env と違い、 bash の処理結果を変数に定義することができます。
steps: - uses: actions/checkout@v3 - id: var run: | echo "terraform-version=`cat .terraform-version`" >> "$GITHUB_OUTPUT" # この実装だと `echo "1.4.4"` を実行する - run: echo "${{ steps.var.outputs.terraform-version }}"
関数(workflow_call)
ワークフローの一部を別のファイルに定義し、関数のように呼び出すことができます。
# .github/workflows/_say.yml name: say on: workflow_call: inputs: name: required: true type: string jobs: hello: runs-on: ubuntu-latest steps: - run: echo "Hello, ${{ inputs.name }}." bye: needs: hello runs-on: ubuntu-latest steps: - run: echo "Bye, ${{ inputs.name }}."
使い方は以下の通りです。
jobs: job-say: uses: ./.github/workflows/_say.yml with: name: kameike
関数 + 配列(dynamic matrix)
workflows_call の入力には真偽値、数字、文字列しか使えません。
The value of this parameter is a string specifying the data type of the input. This must be one of: boolean, number, or string.
引用: https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#onworkflow_callinputsinput_idtype
しかし、少し工夫することで配列を扱うことができます。
# .github/workflows/_say_multi.yml name: say_multi on: workflow_call: inputs: names: required: true type: string jobs: matrix: runs-on: ubuntu-latest outputs: names: ${{ steps.set-matrix.outputs.names }} steps: - id: set-matrix run: | names=`echo '${{ inputs.names }}' | jq -csR 'split("\\n") | map(select(. != ""))'` echo "names=$names" >> $GITHUB_OUTPUT hello: needs: matrix runs-on: ubuntu-latest strategy: matrix: name: ${{ fromJSON(needs.matrix.outputs.names) }} steps: - run: echo "Hello, ${{ matrix.name }}."
使い方は以下の通りです。
job-say-multi: uses: ./.github/workflows/_say_multi.yml with: names: | ryo kameike
GitHub CLIの活用
GitHub APIを使うことで、チェックアウトせずにファイル名を取得することができます。
job-gh-matrix: runs-on: ubuntu-latest outputs: files: ${{ steps.set-matrix.outputs.files }} steps: - id: set-matrix run: echo "files=`gh api '/repos/{owner}/{repo}/contents/.github/workflows?ref=${{ github.sha }}' --jq '[.[].name]'`" >> $GITHUB_OUTPUT env: GH_REPO: ${{ github.repository }} GH_TOKEN: ${{ github.token }} job-gh-echo: needs: job-gh-matrix runs-on: ubuntu-latest strategy: matrix: file: ${{ fromJSON(needs.job-gh-matrix.outputs.files) }} steps: - run: echo "${{ matrix.file }}"
画像のようにファイル名の一覧で並列にJobを実行できます。
まとめ
YAMLむずかしいですね。
この記事が読んだ方の参考になれば幸いです。
また、弊社のGitHub Actionsやデプロイフローについて気になることがあれば、フッターの採用ページのURLから面談の申し込みをどうぞ!