在GitHub Actions中创建作业之间的依赖关系

77

我刚开始接触GitHub Actions,并尝试使用不同的选项来找出CI/CD流水线的良好方法。

最初,我将所有的CI步骤放在一个作业中,执行以下操作:

  • 从repo检出代码
  • lint
  • 扫描源代码以检测漏洞
  • 构建
  • 测试
  • 创建映像
  • 扫描映像以检测漏洞
  • 推送到AWS ECR

然而,其中一些步骤不需要按顺序执行。例如,我们可以并行运行linting和源代码漏洞扫描以及构建;这样可以节省时间(如果我们假设这些步骤会通过的话)。

也就是说,我希望我的流水线能够做到类似下面这样:

job1 = {
 - checkout code from repo #required per job, since each job runs on a different runner
 - lint
}
job2 = {
 - checkout code from repo
 - scan source for vulnerabilities
}
job3 = {
 - checkout code from repo
 - build
 - test
 - create image
 - scan image for vulnerabilities
 - await job1 & job2
 - push to AWS ECR
}

我有几个问题:

  1. 是否可以在作业内设置一些 await jobN 规则;即从另一个作业中查看一个作业的状态?
  2. (只有当问题1的答案为时才相关): 是否有任何方法可以立即影响同一工作流程中其他作业的失败? 例如,如果我的检测作业检测到问题,则可以立即将其称为失败,因此希望作业1中的失败立即停止作业2和作业3的运行,因为它们不再增加价值。
2个回答

116
理想情况下,应该将一些工作封装在它们自己的工作流中,例如:
  • 通过任何方式测试源代码的工作流。
  • (构建和)部署的工作流。
然后,这些工作流应该相互依赖,或者使用不同的触发器来触发。 不幸的是,至少目前为止,工作流之间的依赖关系不是一个现有的功能(参考)。 编辑:如此StackOverflow问题所讨论的那样,工作流之间的依赖关系现在也是可能的。 虽然我认为将所有提到的工作都包含在一个工作流中会创建一个长而难以维护的文件,但我相信您仍然可以通过使用GitHub actions语法提供的一些条件来实现您的目标。
可能的选项:

使用后者,一个示例语法可能如下所示:

jobs:
  job1:
  job2:
    needs: job1
  job3:
    needs: [job1, job2]

以下是与上述方法测试相关的工作流。在此示例中,仅当作业1完成后,作业2才会运行,而作业3将不会运行,因为它依赖于一个失败的作业。
name: Experiment
on: [push]

jobs:
  job1:
    name: Job 1
    runs-on: ubuntu-latest

    steps:
    - name: Sleep and Run
      run: |
        echo "Sleeping for 10"
        sleep 10

  job2:
    name: Job 2
    needs: job1
    runs-on: ubuntu-latest

    steps:
    - name: Dependant is Running
      run: |
        echo "Completed job 2, but triggering failure"
        exit 1

  job3:
    name: Job 3
    needs: job2
    runs-on: ubuntu-latest

    steps:
    - name: Will never run
      run: |
        echo "If you can read this, the experiment failed"

相关文档:


1
不错,谢谢@DannyB。将事情分成不同的工作流是个好主意;我会考虑如何从流程角度处理它。关于“需要”的部分;那很好,但会强制作业按顺序运行,这会消除我所追求的好处。我的希望是让那些彼此不依赖的任务并行运行,以减少我们知道事情是否成功或失败之前的时间。 - JohnLBevan
1
你仍然可以并行运行一些作业。如果一个作业不依赖于上一个作业的成功完成,它就不需要它。 - DannyB
2
如果您仍然希望,例如,在job2未成功或跳过的情况下运行job3,则可以在job3上使用if:${{always()}}。 https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idneeds它仍将强制首先运行job2 - gary69
在触发“重新运行失败的作业”时,是否也可以重新运行依赖的作业,仅重新运行最后一个失败的作业?例如,如果“作业3”失败,则会重新运行“作业2”和“作业3”。 - Benjamin Haegenlaeuer
1
似乎跨作业仅检查一次代码不受支持 https://github.com/actions/checkout/issues/19 - SomeGuyOnAComputer

-3

如果依赖的作业运行速度比其所依赖的作业快很多,您可以让它们并行运行。

例如:部署一个expressjs服务器通常比发布到Google Play Console要快得多。


如果一个工作真正依赖于另一个工作,让它们并行运行将会引发竞争条件(如果它们_曾经_工作)。 - derpedy-doo

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