Skip to main content

Enterprise Server 3.21 目前作为发布候选版本提供。

控制工作流和作业的并发性

管理哪些工作流和作业可以同时运行。

在不同方案中使用并发

可以使用 jobs.<job_id>.concurrency 确保只有使用相同并发组的单一作业或工作流才会同时运行。 并发组可以是任何字符串或表达式。 允许的表达式上下文:githubinputsvarsneedsstrategymatrix。 有关表达式的详细信息,请参阅“对工作流和操作中的表达式求值”。

还可以在工作流级别指定 concurrency。 有关详细信息,请参阅 concurrency

这意味着在任何时候,一个并发组中最多只能同时有一个正在运行的作业和一个待处理的作业。 当并发作业或工作流排队时,如果存储库中使用同一并发组的其他作业或工作流正在运行,则排队的作业或工作流将为 pending。 将取消同一并发组中的任何现有 pending 作业或工作流(如果存在),且新的列队作业或工作流将取代其位置。

若还要取消同一并发组中任何当前正在运行的作业或工作流,请指定 cancel-in-progress: true。 若要有条件地取消同一并发组中当前正在运行的作业或工作流,可以将 cancel-in-progress 指定为具有任何允许的表达式上下文的表达式。

注意

  • 并发组名称不区分大小写。 例如,prodProd 将被视为同一个并发组。
  • 作业或工作流在同一并发组中运行时,按照每个作业开始等待该并发组的时间,以先进先出(FIFO)的顺序处理,而不是按照每个工作流的分派时间。 由于作业或运行的实际开始时间可能有所不同,因此不能保证排序。

示例:使用并发和默认行为

默认情况下,GitHub Actions 允许多个作业或工作流同时运行。 使用concurrency 关键字可以控制工作流运行的并发性。

例如,可以在定义触发器条件以限制特定分支的整个工作流运行的并发之后立即使用 concurrency 关键字:

on:
  push:
    branches:
      - main

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

还可以通过在作业级别使用 concurrency 关键字来限制工作流中作业的并发性:

on:
  push:
    branches:
      - main

jobs:
  job-1:
    runs-on: ubuntu-latest
    concurrency:
      group: example-group
      cancel-in-progress: true

示例:并发组

并发组提供了一种方法,用于管理和限制共享相同并发密钥的工作流运行或作业的执行。

concurrency 密钥用于将工作流或作业组合到并发组中。 定义 concurrency 密钥时, GitHub Actions 请确保在任何给定时间只运行具有该密钥的一个工作流或作业。 如果新的工作流运行或作业以相同的 concurrency 密钥启动, GitHub Actions 将取消已使用该密钥运行的任何工作流或作业。 键 concurrency 可以是硬编码字符串,也可以是包含上下文变量的动态表达式。

可以在工作流中定义并发条件,以便工作流或作业是并发组的一部分。

这意味着,当工作流运行或作业启动时,GitHub 将取消同一并发组中正在进行的任何工作流运行或作业。 在想要防止对特定工作流或作业(例如用于部署到过渡环境的工作流或作业)进行并行运行的情况下,这非常有用,以防止可能导致冲突或消耗比必要资源更多的操作。

在此示例中,job-1 是名为 staging_environment 的并发组的一部分。 如果新运行的 job-1 被触发,那么在并发组 staging_environment 中已在进行的任何同一作业的运行都将被取消。

jobs:
  job-1:
    runs-on: ubuntu-latest
    concurrency:
      group: staging_environment
      cancel-in-progress: true

或者,在工作流中使用动态表达式 concurrency: ci-${{ github.ref }} 意味着工作流或作业将成为并发组 ci- 的一部分,后跟触发工作流的分支或标记的引用。 在此示例中,如果在上一次运行仍在进行中时将新的提交推送到主分支,则会取消上一次运行,并且新运行将启动:

on:
  push:
    branches:
      - main

concurrency:
  group: ci-${{ github.ref }}
  cancel-in-progress: true

示例:使用并发取消任何当前作业或运行

若要使用并发来取消任何正在进行的任务或运行,可以使用密钥concurrency,并将选项cancel-in-progress设置为true

concurrency:
  group: ${{ github.ref }}
  cancel-in-progress: true

请注意,在此示例中,如果不定义特定的并发组,GitHub Actions 将取消任何正在进行的_作业或工作流_的运行。

示例:使用回退值

如果使用仅为特定事件定义的属性生成组名称,则可以使用回退值。 例如,github.head_ref 仅对 pull_request 事件定义。 如果工作流响应除了 pull_request 事件之外的其他事件,你将需要提供回退以避免语法错误。 以下并发组仅取消针对 pull_request 事件正在进行的作业或运行;如果 github.head_ref 未定义,并发组将回退到运行 ID,该 ID 保证是唯一的,并且是为该运行定义的。

concurrency:
  group: ${{ github.head_ref || github.run_id }}
  cancel-in-progress: true

示例:仅取消当前工作流中正在进行的作业或运行

如果在同一个存储库中有多个工作流,则并发组名称在工作流中必须是唯一的,以避免从其他工作流取消正在进行的作业或运行。 否则,任何先前进行中或挂起的任务都将被取消,无论工作流如何。

若要仅取消同一工作流中正在进行的运行,可以使用 github.workflow 属性来构建并发组。

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: true

示例:仅取消特定分支上正在进行的作业

如果你想取消某些分支上正在进行的作业,但不想取消其他分支上正在进行的作业,则可以将条件表达式与 cancel-in-progress 一起使用。 例如,如果你想取消开发分支上正在进行的作业,但不想取消发布分支上正在进行的作业,则可以执行此操作。

若要仅在未在发布分支上运行时取消同一工作流正在进行的运行,则可以设置表达式的 cancel-in-progress,如下所示:

concurrency:
  group: ${{ github.workflow }}-${{ github.ref }}
  cancel-in-progress: ${{ !contains(github.ref, 'release/')}}

在此示例中,多次推送到 release/1.2.3 分支不会取消正在进行的运行。 推送到另一个分支(例如 main)将取消正在进行的运行。