From 41068f6e1608466098f5d229bded5fffbbdbc62c Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 6 Mar 2024 11:34:44 -0500 Subject: [PATCH 1/4] Document exit code handling for composite actions --- .../setting-exit-codes-for-actions.md | 190 +++++++++++++++++- 1 file changed, 187 insertions(+), 3 deletions(-) diff --git a/content/actions/creating-actions/setting-exit-codes-for-actions.md b/content/actions/creating-actions/setting-exit-codes-for-actions.md index 1009fa82a28fc..5a165603cba80 100644 --- a/content/actions/creating-actions/setting-exit-codes-for-actions.md +++ b/content/actions/creating-actions/setting-exit-codes-for-actions.md @@ -17,10 +17,10 @@ type: how_to {% data variables.product.prodname_dotcom %} uses the exit code to set the action's check run status, which can be `success` or `failure`. -Exit status | Check run status | Description -------------|------------------|------------ +Exit status | Step conclusion | Description +------------|-----------------|------------ `0` | `success` | The action completed successfully and other tasks that depend on it can begin. -Nonzero value (any integer but 0)| `failure` | Any other exit code indicates the action failed. When an action fails, all concurrent actions are canceled and future actions are skipped. The check run and check suite both get a `failure` status. +Nonzero value (any integer but 0)| `failure` | Any other exit code indicates the action failed. When an action fails unless the step has `continue-on-error: true` the job will be set to `failed` and future steps in the job will be skipped unless they use `if:` with either `always()` or `failed()`. Concurrent jobs will be canceled unless `jobs..strategy.fail-fast` is `false`. ## Setting a failure exit code in a JavaScript action @@ -48,3 +48,187 @@ fi ``` For more information, see "[AUTOTITLE](/actions/creating-actions/creating-a-docker-container-action)." + +## Handling exit codes in composite actions + +### Handling failing steps in composite actions + +If a step exits with a Nonzero value (any integer but 0), its `outcome` will be `failure`. + +Any step in a composite action that doesn't have `continue-on-error: true` and has a `failure` outcome will cause the composite action `outcome` to be `failure`. + +To perform other logic based on a step that uses an action that can fail for which you don't want to automatically have the consuming action fail, you can use `continue-on-error: true` on the step and then use `steps..outcome` for that possibly failing step to control the logic of the remaining steps in the composite action. For more information, see "[AUTOTITLE](/actions/learn-github-actions/contexts#steps-context)." + +Consumers of an action in a matrix with `jobs..strategy.fail-fast` set to `true` will be canceled when an action step fails without `continue-on-error: true`. + +### Setting a success outcome in a composite action + +As long as all steps without `continue-on-error: true` yield an exit code of `0` whether explicit or implicit (e.g. a shell run step where commands don't fail or the shell is set not to treat failed steps as failures), the action's outcome will be success. + +### Setting a failure in a composite action + +Set the exit code of a step to a nonzero value and ensure that the step does not have `continue-on-error: true` to cause the composite action `outcome` to be `failure`. + +### Examples of success and failure in composite actions + +`maybe-fail/action.yml`: + +```yml +name: 'Maybe fail' +description: 'Conditionally fail based on inputs' +inputs: + return-code: + description: 'Value to use as exit code for main step' + required: false + default: '0' + continue-on-error: + description: 'Whether to run the main step with `continue-on-error`' + required: false + default: 'false' +outputs: + result: + description: "Result for posterity" + value: ${{ steps.report-outcome.outputs.result }} +runs: + using: "composite" + steps: + - name: Run step if continue-on-error = false + id: continue-on-error-false + if: ${{ inputs.continue-on-error == 'false' }} + continue-on-error: false + run: exit ${{ inputs.return-code }} + shell: bash + - name: Run step if continue-on-error != false + id: continue-on-error-true + if: ${{ inputs.continue-on-error != 'false' }} + continue-on-error: true + run: exit ${{ inputs.return-code }} + shell: bash + - id: report-outcome + if: success() || failure() + run: echo "result=$outcome" | tee -a "$GITHUB_OUTPUT" + env: + outcome: ${{ steps.continue-on-error-false.outcome != 'skipped' && steps.continue-on-error-false.outcome || steps.continue-on-error-true.outcome }} + shell: bash +``` + +`use-maybe-fail/action.yml`: + +```yml +name: 'Use maybe fail' +description: 'Call maybe fail to conditionally fail based on inputs' +inputs: + return-code: + description: 'Value to use as exit code for main step' + required: false + default: '0' + continue-on-error: + description: 'Whether to run the main step with `continue-on-error`' + required: false + default: 'false' +outputs: + result: + description: "Result for posterity" + value: ${{ steps.maybe-fail.outputs.result }} +runs: + using: "composite" + steps: + - name: Call maybe fail + id: maybe-fail + uses: ./maybe-fail + with: + return-code: ${{ inputs.return-code }} + continue-on-error: ${{ inputs.continue-on-error }} + - id: report-outcome + if: (success() || failure()) && steps.maybe-fail.outcome == 'failure' + run: | + echo 'Something must be done because maybe-fail failed!' | tee -a "$GITHUB_STEP_SUMMARY" + shell: bash +``` + +`.github/workflows/maybe-fail.yml`: + +```yml +name: Maybe-fail + +on: + push: + pull_request: + workflow_dispatch: +jobs: + use-action-without-fail-fast: + runs-on: ubuntu-latest + strategy: + matrix: + return-code: + - 0 + - 1 + continue-on-error: + - true + - false + fail-fast: false + name: Maybe fail + steps: + - uses: actions/checkout@v4 + - name: Use maybe-fail action + id: maybe-fail + uses: ./use-maybe-fail + with: + return-code: ${{ matrix.return-code }} + continue-on-error: ${{ matrix.continue-on-error }} + - name: After Action + if: success() || failure() + env: + conclusion: ${{ steps.maybe-fail.conclusion }} + outcome: ${{ steps.maybe-fail.outcome}} + result: ${{ steps.maybe-fail.outputs.result }} + run: | + ( + echo "outcome: $outcome" + echo "conclusion: $conclusion" + echo "result: $result" + echo + ) | tee -a "$GITHUB_STEP_SUMMARY" + - name: Next Step + run: + echo Next step | tee -a "$GITHUB_STEP_SUMMARY" + use-action-with-fail-fast: + runs-on: ubuntu-latest + strategy: + matrix: + return-code: + - 0 + - 1 + continue-on-error: + - false + fail-fast: true + name: Maybe fail fast + steps: + - uses: actions/checkout@v4 + - name: sleep + if: ${{ matrix.return-code == 0 }} + run: + sleep 10 + - name: Use maybe-fail action + id: maybe-fail + uses: ./maybe-fail + with: + return-code: ${{ matrix.return-code }} + continue-on-error: ${{ matrix.continue-on-error }} + - name: After Action + if: success() || failure() + env: + conclusion: ${{ steps.maybe-fail.conclusion }} + outcome: ${{ steps.maybe-fail.outcome}} + result: ${{ steps.maybe-fail.outputs.result }} + run: | + ( + echo "outcome: $outcome" + echo "conclusion: $conclusion" + echo "result: $result" + echo + ) | tee -a "$GITHUB_STEP_SUMMARY" + - name: Next Step + run: + echo Next step | tee -a "$GITHUB_STEP_SUMMARY" +``` \ No newline at end of file From 2af2dfeeebb6d8036b7710f7bbf80bf755d103c3 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Wed, 6 Mar 2024 14:40:48 -0500 Subject: [PATCH 2/4] Hi Linter --- .../setting-exit-codes-for-actions.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/content/actions/creating-actions/setting-exit-codes-for-actions.md b/content/actions/creating-actions/setting-exit-codes-for-actions.md index 5a165603cba80..1370bf532ca33 100644 --- a/content/actions/creating-actions/setting-exit-codes-for-actions.md +++ b/content/actions/creating-actions/setting-exit-codes-for-actions.md @@ -71,9 +71,9 @@ Set the exit code of a step to a nonzero value and ensure that the step does not ### Examples of success and failure in composite actions -`maybe-fail/action.yml`: +`maybe-fail/action.yaml`: -```yml +```yaml name: 'Maybe fail' description: 'Conditionally fail based on inputs' inputs: @@ -108,13 +108,13 @@ runs: if: success() || failure() run: echo "result=$outcome" | tee -a "$GITHUB_OUTPUT" env: - outcome: ${{ steps.continue-on-error-false.outcome != 'skipped' && steps.continue-on-error-false.outcome || steps.continue-on-error-true.outcome }} + outcome: ${{ steps.continue-on-error-false.outcome != 'skipped' {% raw %}&&{% endraw %} steps.continue-on-error-false.outcome || steps.continue-on-error-true.outcome }} shell: bash ``` -`use-maybe-fail/action.yml`: +`use-maybe-fail/action.yaml`: -```yml +```yaml name: 'Use maybe fail' description: 'Call maybe fail to conditionally fail based on inputs' inputs: @@ -146,9 +146,9 @@ runs: shell: bash ``` -`.github/workflows/maybe-fail.yml`: +`.github/workflows/maybe-fail.yaml`: -```yml +```yaml name: Maybe-fail on: @@ -169,7 +169,7 @@ jobs: fail-fast: false name: Maybe fail steps: - - uses: actions/checkout@v4 + - uses: {% data reusables.actions.action-checkout %} - name: Use maybe-fail action id: maybe-fail uses: ./use-maybe-fail @@ -204,7 +204,7 @@ jobs: fail-fast: true name: Maybe fail fast steps: - - uses: actions/checkout@v4 + - uses: {% data reusables.actions.action-checkout %} - name: sleep if: ${{ matrix.return-code == 0 }} run: From 5609e1886c505a32442cf2fd315053b7b6ae0733 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 8 Mar 2024 08:33:47 -0500 Subject: [PATCH 3/4] Sprinkle {% raw %} --- .../creating-actions/setting-exit-codes-for-actions.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/content/actions/creating-actions/setting-exit-codes-for-actions.md b/content/actions/creating-actions/setting-exit-codes-for-actions.md index 1370bf532ca33..e25efe9172520 100644 --- a/content/actions/creating-actions/setting-exit-codes-for-actions.md +++ b/content/actions/creating-actions/setting-exit-codes-for-actions.md @@ -74,6 +74,7 @@ Set the exit code of a step to a nonzero value and ensure that the step does not `maybe-fail/action.yaml`: ```yaml +{% raw %} name: 'Maybe fail' description: 'Conditionally fail based on inputs' inputs: @@ -108,13 +109,15 @@ runs: if: success() || failure() run: echo "result=$outcome" | tee -a "$GITHUB_OUTPUT" env: - outcome: ${{ steps.continue-on-error-false.outcome != 'skipped' {% raw %}&&{% endraw %} steps.continue-on-error-false.outcome || steps.continue-on-error-true.outcome }} + outcome: ${{ steps.continue-on-error-false.outcome != 'skipped' && steps.continue-on-error-false.outcome || steps.continue-on-error-true.outcome }} shell: bash +{% endraw %} ``` `use-maybe-fail/action.yaml`: ```yaml +{% raw %} name: 'Use maybe fail' description: 'Call maybe fail to conditionally fail based on inputs' inputs: @@ -144,11 +147,13 @@ runs: run: | echo 'Something must be done because maybe-fail failed!' | tee -a "$GITHUB_STEP_SUMMARY" shell: bash +{% endraw %} ``` `.github/workflows/maybe-fail.yaml`: ```yaml +{% raw %} name: Maybe-fail on: @@ -231,4 +236,5 @@ jobs: - name: Next Step run: echo Next step | tee -a "$GITHUB_STEP_SUMMARY" -``` \ No newline at end of file +{% endraw %} +``` From d67ff5ef07fd75ddd0c92083c4aa17ccac96f491 Mon Sep 17 00:00:00 2001 From: Josh Soref <2119212+jsoref@users.noreply.github.com> Date: Fri, 8 Mar 2024 08:55:05 -0500 Subject: [PATCH 4/4] Remove blank lines --- .../setting-exit-codes-for-actions.md | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/content/actions/creating-actions/setting-exit-codes-for-actions.md b/content/actions/creating-actions/setting-exit-codes-for-actions.md index e25efe9172520..8b327fac648d8 100644 --- a/content/actions/creating-actions/setting-exit-codes-for-actions.md +++ b/content/actions/creating-actions/setting-exit-codes-for-actions.md @@ -74,8 +74,7 @@ Set the exit code of a step to a nonzero value and ensure that the step does not `maybe-fail/action.yaml`: ```yaml -{% raw %} -name: 'Maybe fail' +{% raw %}name: 'Maybe fail' description: 'Conditionally fail based on inputs' inputs: return-code: @@ -110,15 +109,13 @@ runs: run: echo "result=$outcome" | tee -a "$GITHUB_OUTPUT" env: outcome: ${{ steps.continue-on-error-false.outcome != 'skipped' && steps.continue-on-error-false.outcome || steps.continue-on-error-true.outcome }} - shell: bash -{% endraw %} + shell: bash{% endraw %} ``` `use-maybe-fail/action.yaml`: ```yaml -{% raw %} -name: 'Use maybe fail' +{% raw %}name: 'Use maybe fail' description: 'Call maybe fail to conditionally fail based on inputs' inputs: return-code: @@ -146,15 +143,13 @@ runs: if: (success() || failure()) && steps.maybe-fail.outcome == 'failure' run: | echo 'Something must be done because maybe-fail failed!' | tee -a "$GITHUB_STEP_SUMMARY" - shell: bash -{% endraw %} + shell: bash{% endraw %} ``` `.github/workflows/maybe-fail.yaml`: ```yaml -{% raw %} -name: Maybe-fail +{% raw %}name: Maybe-fail on: push: @@ -235,6 +230,5 @@ jobs: ) | tee -a "$GITHUB_STEP_SUMMARY" - name: Next Step run: - echo Next step | tee -a "$GITHUB_STEP_SUMMARY" -{% endraw %} + echo Next step | tee -a "$GITHUB_STEP_SUMMARY"{% endraw %} ```