如何在 GitHub Actions 工作流失败时运行一个 job?

11
我希望运行一个通知任务,让我知道我的工作流失败了,有没有一种方法可以做到这一点,而不必需要每个工作都进行 needs 并检查每个工作的状态?
如果我有很多工作,现在我必须这样做,但这会变得繁琐:
jobs:
  first-job:
    runs-on: ubuntu-20.04
    steps:
      - exit 0


  second-job:
    runs-on: ubuntu-20.04
    steps:
      - exit 1

  notify-job:
    runs-on: ubuntu-20.04
    needs: [first-job, second-job]
    if: ${{ always() && (needs.first-job.result == 'failure' || needs.second-job.result == 'failure') }}
    steps:
      - ./notify.sh

我想简单地检查工作流程是否在任何情况下失败,即是否有任何作业失败,这可能吗?
我看到了这份文档,以检查触发工作流程是否失败(https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#running-a-workflow-based-on-the-conclusion-of-another-workflow)。
是否有一种方法在当前工作流程结束时运行finallyensure状态检查?
3个回答

11

2
Github合作伙伴brightranthis post中表示:

默认情况下,一旦运行作业中的一个步骤失败,所有后续步骤都将被跳过,并且此作业将被标记为失败。如果您希望后续步骤仍然执行,则可以在每个后续步骤中添加if条件(if:always())。

在job1和job2的末尾添加两个额外的步骤,并设置这两个步骤始终执行(if:always())。第一个用于创建文本文件并将作业状态写入其中,第二个用于将此文本文件上传为artifact。在job3中,您还需要添加下载artifact的步骤并读取jo1和jo2的状态。

使用此工作流程作为演示:

jobs:
  JOB_01:
    name: Job 01
    . . .
    steps:
      - name: Some steps of job 01
      . . .
      - name: Create file status_job01.txt and write the job status into it
        if: always()
        run: |
          echo ${{ job.status }} > status_job01.txt

      - name: Upload file status_job01.txt as an artifact
        if: always()
        uses: actions/upload-artifact@v1
        with:
          name: pass_status_job01
          path: status_job01.txt

  JOB_02:
    name: Job 02
    . . .
    steps:
      - name: Some steps of job 02
      . . .
      - name: Create file status_job02.txt and write the job status into it
        if: always()
        run: |
          echo ${{ job.status }} > status_job02.txt

      - name: Upload file status_job02.txt as an artifact
        if: always()
        uses: actions/upload-artifact@v1
        with:
          name: pass_status_job02
          path: status_job02.txt

  JOB_03:
    needs: [JOB_01, JOB_02]
    if: always()
    name: Job 03
    . . .
    steps:
      - name: Download artifact pass_status_job01
        uses: actions/download-artifact@v1
        with:
          name: pass_status_job01

      - name: Download artifact pass_status_job02
        uses: actions/download-artifact@v1
        with:
          name: pass_status_job02

      - name: Set the statuses of Job 01 and Job 02 as output parameters
        id: set_outputs
        run: |
          echo "::set-output name=status_job01::$(<pass_status_job01/status_job01.txt)"
          echo "::set-output name=status_job02::$(<pass_status_job02/status_job02.txt)"

      - name: Show the values of the outputs
        run: |
          # using the syntax steps.<step_id>.outputs.<output_name> to access the output parameters
          echo "status_job01 = ${{ steps.set_outputs.outputs.status_job01 }}"
          echo "status_job02 = ${{ steps.set_outputs.outputs.status_job02 }}"

      - name: Some other steps of job 03
      . . .

在你的情况下,你最终可以使用这些“状态作业”输出来根据它们在if条件中的值执行或不执行作业,就像你在问题中建议的那样(这可能会在将它们设置为job3输出后的第4个作业中)。这不是一个“好看”的解决方案(因为它相当冗长),但它是有效的。

3
这样做对于我在几个工作流中有的超过5个工作岗位来说是有道理的,但会变得非常繁琐。我发现在每个工作的结尾添加一个 if: failure() 步骤会更少繁琐一些。希望 GitHub 能尽快支持这一功能。 - jshah

-1

您可以使用 ${{ failure() }}

steps:
  ...
  - name: The job has failed
    if: ${{ failure() }}

来自Github文档

当作业的任何一个先前步骤失败时返回 true。如果您有一系列依赖作业,则如果任何祖先作业失败,failure() 将返回 true。

编辑:正如@Pieter Van der Haegen所指出的那样,它仅在作业级别而不是工作流级别上起作用!


1
这仅适用于一个作业,而不是工作流程中。 - Pieter Van der Haegen

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