how to exclude an exit code in github actions workflow result status?

Viewed 3817

I have a work flow which in one of its steps, if the commands finish with exit code 1 (failure), i want to run next command/job (fix the problem which caused previous command failure), but i don't want that exit code 1 affect on a workflow result status.
in this situation, if i have exit code 1, even if i fix the problem, the result status will be failure, but i want if the second command fixed the problem, the result status be succeed.
is it possible?

here is my workflow.yml:

if the job build with command run: black --check . have exit code 1, i want to run job reformat to fix the problem and push that in repository. the second job works fine, but final result label is failure!!

name: autoblack
on: [pull_request, push]
jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Set up Python 3.8
        uses: actions/setup-python@v2.2.2
        with:
          python-version: 3.8
      - name: Install Black
        run: pip3 install git+git://github.com/psf/black
        
      - name: Run black --check .
        run: black --check .
  
  reformat:
    runs-on: ubuntu-latest
    needs: [build]
    if: always() && (needs.build.result == 'failure')
    steps:
      - uses: actions/checkout@v2.3.4
      - name: Set up Python 3.8
        uses: actions/setup-python@v2.2.2
        with:
          python-version: 3.8
      - name: Install Black
        run: pip3 install git+git://github.com/psf/black
      - name: If needed, commit black changes to the pull request
        env:
          NEEDS_CONTEXT: ${{ toJSON(needs) }}
        run: |
          black --fast .
          git config --global user.name 'autoblack'
          git config --global user.email 'signorrayan@users.noreply.github.com'
          git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/$GITHUB_REPOSITORY
          git checkout $GITHUB_HEAD_REF
          echo "$NEEDS_CONTEXT"
          git commit -am "fixup: Format Python code with Black"
          git push
          echo "$NEEDS_CONTEXT"
2 Answers

The continue-on-error attribute of the step (also available on the job) can be used to prevent a job from failing when a step fails.

Then the steps context contains a steps.<step_id>.outcome that can be used in expressions to determine if the prior step failed. For example, in the workflow below I have a step that will fail when the commitlint command fails, but it uses continue-on-error to allow the workflow to continue:

      - name: commitlint
        id: commitlint
        continue-on-error: true
        run: |
          npx commitlint --from ${{ github.event.pull_request.base.sha }} --to ${{ github.event.pull_request.head.sha }} --verbose

Then the subsequent two steps will apply or remove a label based on the commitlint step's success/failure outcome:

      - name: label when commitlint fails
        if: ${{ steps.commitlint.outcome == 'failure' }}
        uses: andymckay/labeler@1.0.4
        with:
          add-labels: "commit-message-rule-violation"

      - name: label removal when commitlint succeeds
        if: ${{ steps.commitlint.outcome == 'success' }}
        uses: andymckay/labeler@1.0.4
        with:
          remove-labels: "commit-message-rule-violation"

The workflow ultimately succeeds regardless of whether the commitlint step fails or not due to continue-on-error: true.

The complete working workflow for this is here

As an example, you can use an if condition to set the output parameter and refer to it in subsequent steps

    steps:
      - uses: actions/checkout@master
      - name: Install Black
        run: pip3 install git+git://github.com/psf/black
      - name: Check black status
        id: black_status
        run: |
          if black --check .; then
            echo "::set-output name=result::true"
          else
            echo "::set-output name=result::false"
          fi
      - if: steps.black_status.outputs.result == 'true'
        name: Check1
        run: echo "hi"
      - if: steps.black_status.outputs.result == 'false'
        name: Check2
        run: echo "yo"
Related