内容
オブジェクトフィルタ、containsを利用して、
複数Jobs、複数Stepsの処理終了後に処理結果をまとめて判定する方法を記載する
stepsの処理結果をまとめて判定する
steps.<step_id>.outcome
を使う
jobs:
test_A:
name: test A
runs-on: ubuntu-latest
outputs:
test_result: ${{ steps.test_result.outputs.result }}
steps:
- uses: actions/checkout@v4
- name: test 1
id: test_1
shell: bash
# continue-on-error: true # stepが失敗した場合も後続のstepを実行したい場合に指定する
run: |
...
- name: test 2
id: test_2
shell: bash
# continue-on-error: true # stepが失敗した場合も後続のstepを実行したい場合に指定する
run: |
...
- name: test result
id: test_result
if: ${{ always() }} # 前段のstepが失敗しても実行する
uses: actions/github-script@v7
env:
TEST_FAILED: ${{ contains(steps.*.outcome , 'failure') }} # idが振られたstepの全結果に失敗が含まれている場合にtrueを返す
with:
result-encoding: string
script: | # 結果を文字列に変換
const result = ${{ env.TEST_FAILED }} ? 'Failed' : 'Successful';
return result;
stepのidは必須プロパティではないが、steps.<step_id>.outcome
は、step idが定義されているstepしか参照できない
${{ contains(steps.*.outcome , 'failure') }}
で前段の複数stepから成るテスト結果をまとめている
steps コンテキストのoutcome
をオブジェクトフィルタでリスト化した上で、
contains
でリストにfailure
が含まれているかをtrue/falseで取得している
steps.<step_id>.outcome
にはsuccess
、failure
、cancelled
、skipped
のいずれかが入る
continue-on-error: true
を指定し、stepが失敗した場合、steps.<step_id>.outcome
には、step結果が"失敗"から"成功"に変更される前の"失敗"が入っている
逆に変更された後の"成功"を取得したい場合は、steps.<step_id>.conclusion
を使用する
continue-on-error
stepで失敗した場合も後続のstepを実行したい場合は、continue-on-error: true
を使用する
ただし、該当stepが失敗した場合も該当stepに加え、Jobが成功扱いとなる
steps:
- uses: actions/checkout@v4
- name: test 1
id: test_1
shell: bash
continue-on-error: true # stepが失敗した場合もstepとJobは成功扱いになる
run: |
...
jobs:
test_A:
name: test A
uses: ./.github/workflows/reuse_test_a.yml
secrets: inherit
test_B:
name: test B
needs: [test_A] # test_Aが失敗した場合もtest_Bは実行される
uses: ./.github/workflows/reuse_test_b.yml
secrets: inherit
test_B
はtest_A
に依存しているが、test_A
が失敗した場合も成功扱いとなるのでtest_B
が実行されてしまう
success()
, failure()
を使う
jobs:
test_A:
name: test A
runs-on: ubuntu-latest
outputs:
test_result: ${{ steps.xxx.outputs.result }} # 単純にstepのoutputsで返却は無理
steps:
- uses: actions/checkout@v4
- name: test 1
id: test_1
shell: bash
run: |
...
- name: test 2
id: test_2
shell: bash
run: |
...
- name: test result success
id: test_result_success
if: ${{ success() }} # 前段のstepが全て成功の場合に実行
uses: actions/github-script@v7
with:
result-encoding: string
script: |
return 'Successful';
- name: test result failure
id: test_result_failure
if: ${{ failure() }} # 前段のstepに失敗が有った場合に実行
uses: actions/github-script@v7
with:
result-encoding: string
script: |
return 'Failed';
ステータスチェック関数を使ってもsteps.<step_id>.outcome
を使うパターンと似たようなことは可能だが、
結果の判定stepが2つになるため、単純にJobのoutputsとして返却することはできない
Jobsの処理結果をまとめて判定する
needs.<job_id>.result
を使う
jobs:
test_A:
name: test A
uses: ./.github/workflows/reuse_test_a.yml
secrets: inherit
test_B:
name: test B
uses: ./.github/workflows/reuse_test_b.yml
secrets: inherit
test_result:
name: test result
needs: [test_A, test_B]
if: ${{ always() }}
uses: ./.github/workflows/reuse_test_result.yml
secrets: inherit
with:
failed: ${{ contains(needs.*.result, 'failure') }} # needsで指定したJobの全結果に失敗が含まれている場合にtrueを渡す
${{ contains(needs.*.result, 'failure') }}
で依存Job(needsで指定したJob)の結果をまとめている
needs コンテキストのresult
をオブジェクトフィルタでリスト化した上で、
contains
でリストにfailure
が含まれているかをtrue/falseで取得している
needs.<job_id>.result
にはsuccess
、failure
、cancelled
、skipped
のいずれかが入る
needs.<job_id>.outputs.<output name>
以下のようにneeds.<job_id>.outputs.<output name>
をオブジェクトフィルタでリスト化することはできない
全jobに該当のoutputが含まれていることが保障されないためだと思われる
jobs:
test_A:
name: test A
uses: ./.github/workflows/reuse_test_a.yml
secrets: inherit
test_B:
name: test B
uses: ./.github/workflows/reuse_test_b.yml
secrets: inherit
test_result:
name: test result
needs: [test_A, test_B]
if: ${{ always() }}
uses: ./.github/workflows/reuse_test_result.yml
secrets: inherit
with:
result_list: ${{ needs.*.outputs.test_result }} # ※ これは不可
needs
オブジェクト
{
"test_A": {
"result": "success",
"outputs": {
"test_result": "Successful"
}
},
"test_B": {
"result": "failure",
"outputs": {
"test_result": "Failed"
}
}
}
needs.<job_id>.outputs.<output name>
をまとめて参照する場合、
needs
オブジェクトをtoJSON
でJSONに変換すると参照することができる
test_result:
name: test result
needs: [test_A, test_B]
if: ${{ always() }}
runs-on: ubuntu-latest
env:
NEEDS: ${{ toJSON(needs) }} # JSON化
steps:
- name: test result
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const needs = ${{ env.NEEDS }};
console.log(needs);
const test_result = Object.keys(needs).map(jobId => needs[jobId].outputs.test_result);
console.log(test_result);
console.log出力結果
以下のようにtoJSON
せずに参照することはできない
test_result:
name: test result
needs: [test_A, test_B]
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: test result
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const needs = ${{ needs }}; // これは不可
console.log(needs);
const test_result = Object.keys(needs).map(jobId => needs[jobId].outputs.test_result);
console.log(test_result);
console.log出力結果
reusable-workflowsのinputsにtoJSON(needs)
を渡して参照することは可能
test_result:
name: test result
needs: [test_A, test_B]
if: ${{ always() }}
uses: ./.github/workflows/reuse_needs_output.yml
secrets: inherit
with:
needs: ${{ toJSON(needs) }}
name: needs output
on:
workflow_call:
inputs:
needs:
required: true
type: string
jobs:
test_result:
name: test result
runs-on: ubuntu-latest
steps:
- name: test result
uses: actions/github-script@v7
with:
result-encoding: string
script: |
const needs = ${{ inputs.needs }};
console.log(needs);
const test_result = Object.keys(needs).map(jobId => needs[jobId].outputs.test_result);
console.log(test_result);