Skip to main content

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

一次运行一个作业。

概述

默认情况下,GitHub Actions 允许同一工作流中的多个作业,在同一存储库中运行多个工作流,并且多个工作流跨存储库所有者的帐户运行并发运行。 这意味着多个工作流运行、作业或步骤可以同时运行。

GitHub Actions 还允许你控制工作流运行的并发性,以便确保在特定上下文中一次只运行一个运行、一个作业或一个步骤。 在同时运行多个工作流、作业或步骤可能会导致冲突或使用比预期更多的操作分钟数和存储的情况下,控制帐户或组织的资源非常有用。

例如,并发运行工作流的能力意味着,如果多个提交被快速推送到存储库,则每个推送都可能会触发单独的工作流运行,并且这些运行将并发执行。

在不同方案中使用并发

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

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

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

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

注意:

  • 并发组名称不区分大小写。 例如,prodProd 将被视为同一个并发组。
  • 对于使用并发组的作业或工作流运行,无法保证排序。 同一并发组中的作业或工作流运行按任意顺序进行处理。

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

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

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

若要使用并发来取消任何正在进行的作业或在 GitHub Actions 中运行,可以将 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)将取消正在进行的运行。

监控组织或企业中的当前作业

若要识别并发或队列的任何约束,可以检查组织或企业中 GitHub 托管的运行器上当前正在处理的作业数。 有关详细信息,请参阅“监视当前的工作”。