如何在前一步失败的情况下运行下一个 Github Action 步骤,同时仍然使作业失败?

16
这个问题类似于如何在github-actions中运行步骤,即使前一个步骤失败,仍会导致作业失败,但是已接受的答案对我没有帮助,因为它创建了一个额外的作业。
我想要实现以下目标:
  • 当test-app(step2)通过时,应该运行test-clean步骤,github action工作流返回成功。
  • 当test-app(step2)失败时,应运行test-clean、action-slack和fail-action步骤。github action工作流返回失败。
我该如何修改以下代码以实现这一点?
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

1个回答

23

你可以使用状态检查函数来了解之前步骤的状态。如果不包含这样的函数,则会隐式地使用 if: success() && ...。这意味着作业将不会在以前的作业失败时运行,除非在 if 子句中使用 always()failure()

要处理先前步骤的结果,可以使用步骤上下文,例如 steps.<id>.outcome(应用 continue-on-error 之前)或 steps.<id>.conclusion(应用 continue-on-error 之后)。

这里有一个结合了所有内容的可行示例:

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 }}'"

注:在另一个问题的答案中,并没有增加额外的工作,而是提供了一个如何跨越多个工作应用它的示例。然而,那个答案并没有解决你确切的用例,但可以通过给出一些指针来帮助你。


谢谢。对于action-slack步骤,“&& steps.test-app.outcome != success”似乎是多余的,因为failure()已经处理了它。你是不是只是为了演示而添加了它? - sgowd
1
@sgowd,我添加了这个步骤,因为你的要求是在第二步失败时运行它。如果你想让action-slack步骤在任何前面的步骤失败时运行,那么你可以安全地删除failure()之后的部分。 - Matt
我认为你的意思是:“如果你希望它在……时运行”。是的,我只是问了这个问题来获得更好的理解。你的回答已经足够让我解除了阻塞。 - sgowd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接