{"meta":{"title":"控制工作流和作业的并发性","intro":"管理哪些工作流和作业可以同时运行。","product":"GitHub Actions","breadcrumbs":[{"href":"/zh/actions","title":"GitHub Actions"},{"href":"/zh/actions/how-tos","title":"操作方法"},{"href":"/zh/actions/how-tos/write-workflows","title":"编写工作流"},{"href":"/zh/actions/how-tos/write-workflows/choose-when-workflows-run","title":"选择工作流何时运行"},{"href":"/zh/actions/how-tos/write-workflows/choose-when-workflows-run/control-workflow-concurrency","title":"控制工作流并发量"}],"documentType":"article"},"body":"# 控制工作流和作业的并发性\n\n管理哪些工作流和作业可以同时运行。\n\n## 在不同方案中使用并发\n\n可以使用 `jobs.<job_id>.concurrency` 确保只有使用相同并发组的单一作业或工作流才会同时运行。 并发组可以是任何字符串或表达式。 允许的表达式上下文：[`github`](/zh/actions/learn-github-actions/contexts#github-context)、[`inputs`](/zh/actions/learn-github-actions/contexts#inputs-context)、[`vars`](/zh/actions/learn-github-actions/contexts#vars-context)、[`needs`](/zh/actions/learn-github-actions/contexts#needs-context)、[`strategy`](/zh/actions/learn-github-actions/contexts#strategy-context) 和 [`matrix`](/zh/actions/learn-github-actions/contexts#matrix-context)。 有关表达式的详细信息，请参阅“[对工作流和操作中的表达式求值](/zh/actions/learn-github-actions/expressions)”。\n\n还可以在工作流级别指定 `concurrency`。 有关详细信息，请参阅 [`concurrency`](/zh/actions/using-workflows/workflow-syntax-for-github-actions#concurrency)。\n\n这意味着，并发组中最多可以有一个正在运行的作业或工作流。 当并发作业或工作流排队时，如果存储库中使用同一并发组的其他作业或工作流正在运行，则排队的作业或工作流将为 `pending`。 默认情况下，将取消同一并发组中的任何现有 `pending` 作业或工作流，新的排队作业或工作流将取代其位置。\n\n若还要取消同一并发组中任何当前正在运行的作业或工作流，请指定 `cancel-in-progress: true`。 若要有条件地取消同一并发组中当前正在运行的作业或工作流，可以将 `cancel-in-progress` 指定为具有任何允许的表达式上下文的表达式。\n\n若要允许多个作业或工作流运行在同一 `pending` 并发组中等待，请使用可选 `queue` 属性。 该 `queue` 属性接受以下值：\n\n* `single` （默认值）：最多可以有一个作业或工作流运行在 `pending` 并发组中。 当新任务或工作流运行排队时，同一组中的任何现有任务或工作流运行将被取消并替换。\n* `max`：最多可以有 100 个作业或工作流运行在 `pending` 并发组中。 队列已满时，任何新增作业或工作流运行将被取消。\n\n组合 `queue: max` 和 `cancel-in-progress: true` 不允许，并将导致工作流验证错误。\n\n> \\[!NOTE]\n>\n> * 并发组名称不区分大小写。 例如，`prod` 和 `Prod` 将被视为同一个并发组。\n> * 作业或工作流在同一并发组中运行时，按照每个作业开始等待该并发组的时间，以先进先出（FIFO）的顺序处理，而不是按照每个工作流的分派时间。 由于作业或运行的实际开始时间可能有所不同，因此不能保证排序。\n\n### 示例：使用并发和默认行为\n\n默认情况下，GitHub Actions 允许多个作业或工作流同时运行。 使用`concurrency` 关键字可以控制工作流运行的并发性。\n\n例如，可以在定义触发器条件以限制特定分支的整个工作流运行的并发之后立即使用 `concurrency` 关键字：\n\n```yaml\non:\n  push:\n    branches:\n      - main\n\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n```\n\n还可以通过在作业级别使用 `concurrency` 关键字来限制工作流中作业的并发性：\n\n```yaml\non:\n  push:\n    branches:\n      - main\n\njobs:\n  job-1:\n    runs-on: ubuntu-latest\n    concurrency:\n      group: example-group\n      cancel-in-progress: true\n```\n\n### 示例：并发组\n\n并发组提供了一种方法，用于管理和限制共享相同并发密钥的工作流运行或作业的执行。\n\n该 `concurrency` 密钥用于将工作流或作业组合到并发组中。 定义 `concurrency` 密钥时， GitHub Actions 请确保在任何给定时间只运行具有该密钥的一个工作流或作业。 如果新的工作流运行或作业以相同的 `concurrency` 密钥启动， GitHub Actions 将取消已使用该密钥运行的任何工作流或作业。 键 `concurrency` 可以是硬编码字符串，也可以是包含上下文变量的动态表达式。\n\n可以在工作流中定义并发条件，以便工作流或作业是并发组的一部分。\n\n这意味着，当工作流运行或作业启动时，GitHub 将取消同一并发组中正在进行的任何工作流运行或作业。 在想要防止对特定工作流或作业（例如用于部署到过渡环境的工作流或作业）进行并行运行的情况下，这非常有用，以防止可能导致冲突或消耗比必要资源更多的操作。\n\n在此示例中，`job-1` 是名为 `staging_environment` 的并发组的一部分。 如果新运行的 `job-1` 被触发，那么在并发组 `staging_environment` 中已在进行的任何同一作业的运行都将被取消。\n\n```yaml\njobs:\n  job-1:\n    runs-on: ubuntu-latest\n    concurrency:\n      group: staging_environment\n      cancel-in-progress: true\n```\n\n或者，在工作流中使用动态表达式 `concurrency: ci-${{ github.ref }}` 意味着工作流或作业将成为并发组 `ci-` 的一部分，后跟触发工作流的分支或标记的引用。 在此示例中，如果在上一次运行仍在进行中时将新的提交推送到主分支，则会取消上一次运行，并且新运行将启动：\n\n```yaml\non:\n  push:\n    branches:\n      - main\n\nconcurrency:\n  group: ci-${{ github.ref }}\n  cancel-in-progress: true\n```\n\n### 示例：对多个待处理任务进行排队\n\n默认情况下，每次只能`pending`一个作业或工作流在并发组中运行。 若要允许多个运行排入队列而不是取消，请设置 `queue: max`。 在 `queue: max` 的情况下，最多可以有 100 个作业或工作流在并发组中等待运行；队列满后，将取消任何其他作业。\n\n例如，以下工作流将部署到 `production` 环境，根据每个运行开始等待并发组的时间逐个处理它们：\n\n```yaml\non:\n  push:\n    branches:\n      - main\n\nconcurrency:\n  group: production-deploy\n  queue: max\n```\n\n请注意， `queue: max` 不能与 `cancel-in-progress: true`这两个选项结合使用，因为两个选项描述了处理正在进行的运行时发生的冲突行为。\n\n### 示例：使用并发取消任何当前作业或运行\n\n若要使用并发来取消任何正在进行的任务或运行，可以使用密钥`concurrency`，并将选项`cancel-in-progress`设置为`true`：\n\n```yaml\nconcurrency:\n  group: ${{ github.ref }}\n  cancel-in-progress: true\n```\n\n请注意，在此示例中，如果不定义特定的并发组，GitHub Actions 将取消任何正在进行的\\_作业或工作流\\_的运行。\n\n### 示例：使用回退值\n\n如果使用仅为特定事件定义的属性生成组名称，则可以使用回退值。 例如，`github.head_ref` 仅对 `pull_request` 事件定义。 如果工作流响应除了 `pull_request` 事件之外的其他事件，你将需要提供回退以避免语法错误。 以下并发组仅取消针对 `pull_request` 事件正在进行的作业或运行；如果 `github.head_ref` 未定义，并发组将回退到运行 ID，该 ID 保证是唯一的，并且是为该运行定义的。\n\n```yaml\nconcurrency:\n  group: ${{ github.head_ref || github.run_id }}\n  cancel-in-progress: true\n```\n\n### 示例：仅取消当前工作流中正在进行的作业或运行\n\n如果在同一个存储库中有多个工作流，则并发组名称在工作流中必须是唯一的，以避免从其他工作流取消正在进行的作业或运行。 否则，任何先前进行中或挂起的任务都将被取消，无论工作流如何。\n\n若要仅取消同一工作流中正在进行的运行，可以使用 `github.workflow` 属性来构建并发组。\n\n```yaml\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: true\n```\n\n### 示例：仅取消特定分支上正在进行的作业\n\n如果你想取消某些分支上正在进行的作业，但不想取消其他分支上正在进行的作业，则可以将条件表达式与 `cancel-in-progress` 一起使用。 例如，如果你想取消开发分支上正在进行的作业，但不想取消发布分支上正在进行的作业，则可以执行此操作。\n\n若要仅在未在发布分支上运行时取消同一工作流正在进行的运行，则可以设置表达式的 `cancel-in-progress`，如下所示：\n\n```yaml\nconcurrency:\n  group: ${{ github.workflow }}-${{ github.ref }}\n  cancel-in-progress: ${{ !contains(github.ref, 'release/')}}\n```\n\n在此示例中，多次推送到 `release/1.2.3` 分支不会取消正在进行的运行。 推送到另一个分支（例如 `main`）将取消正在进行的运行。\n\n## 监控组织或企业中的当前作业\n\n若要识别并发或队列的任何约束，可以检查组织或企业中 GitHub 托管的运行器上当前正在处理的作业数。 有关详细信息，请参阅“[查看当前任务](/zh/actions/using-github-hosted-runners/monitoring-your-current-jobs)”。"}