内容
オブジェクトフィルタ、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);

