12

This question is similar to How to run a github-actions step, even if the previous step fails, while still failing the job but the accepted answer does not help me because the it creates an additional job.

What i am trying to accomplish below is

  • When the test-app (step2) passes; the test-clean step should run and the github action workflow returns success.
  • When the test-app (step2) fails; the test-clean, action-slack and fail-action steps should run. The github action workflow returns fails.

How do I fix the below code to make it happen?

name: CI
on:
  pull_request:
    branches:
    - master
  push:
    branches:
      - master

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v1    

    - name: test-app
      run: ./gradlew test

    - name: test-clean
      run: some cleanup that should run always

    - name: action-slack
      if: ${{ step2.result != 'success' }}
      uses: 8398a7/action-slack@v3
      with:
          status: ${{ step2.result }}
          fields: repo,message,commit,author,action,eventName,ref,workflow,job,took
      env:
          SLACK_WEBHOOK_URL: ${{ secrets.SLACK_WEBHOOK_URL }}

    - name: fail-action        
      run:  |
         if ${{ step2.result != 'success' }}; then
            exit 1
         fi

sgowd
  • 946
  • 3
  • 10
  • 27

1 Answers1

18

You can use the status check functions to know the status of previous steps. If you don't include such a function, if: success() && ... is implied. This means that a job will not run when previous jobs failed unless you use always() or failure() in the if clause.

To address the result of previous steps, you can use the steps context like steps.<id>.outcome (before continue-on-error is applied) or steps.<id>.conclusion (after continue-on-error is applied).

Here is a working example combining everything:

jobs:
  build-and-test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v2

    # Mock to test workflow
    - name: Test app
      id: test-app # will be referenced later
      run: |
        echo "Testing app (randomly fails)"
        if [[ $(($RANDOM % 2)) == 0 ]]; then exit 0; else exit 1; fi

    # runs always
    - name: test-clean
      if: always()
      run: echo "Cleanup after tests"

    # runs if previous jobs failed and test-app was not successful (failure/cancelled)
    - name: action-slack
      if: failure() && steps.test-app.outcome != 'success'
      run: |
        echo "Run action-slack"
        echo "Result of test-app was '${{ steps.test-app.outcome }}'"

PS: The answer in the other question does not add an additional job but includes an example on how to apply it across jobs. However, that answer does not address your exact use case but it could have helped you by giving some pointers.

Matt
  • 12,848
  • 2
  • 31
  • 53
  • Thank you. For the action-slack step, "&& steps.test-app.outcome != success" seems redundant because failure() already takes care of it. Did you add it just to demonstrate? – sgowd Mar 11 '22 at 07:09
  • @sgowd I added it since your requirement was specifically to run it when step 2 fails. If you want the action-slack step to run when any previous step failed, then you can safely remove the part after `failure()`. – Matt Mar 11 '22 at 07:12
  • I think you meant "If you want it to run when...". Yeah, i asked it only to gain better understanding . Your reply is good enough to unblock me. – sgowd Mar 11 '22 at 07:16