Skip to main content

重新使用工作流

了解如何通过重用现有工作流程来避免在创建工作流程时重复。

概述

您可以使工作流程可重复使用,而不是从一个工作流程复制并粘贴到另一个工作流程。 然后,您和有权访问可重用工作流程的任何人都可以从另一个工作流程调用可重用工作流程。

重用工作流程可避免重复。 这使得工作流程更易于维护,并允许您通过构建他人的工作来更快地创建新工作流程,就像您对操作所做的那样。 工作流重用还通过帮助你使用设计良好、已经过测试且已证明有效的工作流来促进最佳做法。 您的组织可以构建可集中维护的可重用工作流程库。

下图显示了使用可重用工作流的正在进行的工作流运行。

  • 在该图左侧的三个生成作业均成功完成后,将运行一个名为“部署”的依赖作业。
  • “部署”作业调用包含三个作业的可重用工作流:“暂存”、“审阅”和“生产”。
  • “生产”部署作业仅在“暂存”作业成功完成后运行。
  • 当作业以环境为目标时,工作流运行会显示一个进度条,其中显示作业中的步骤数。 在下图中,“生产”作业包含 8 个步骤,目前正在处理步骤 6。
  • 使用可重用工作流程运行部署作业,可以为每个构建运行这些作业,而无需在工作流程中重复代码。

调用可重用工作流的工作流示意图。

使用其他工作流程的工作流程称为“调用方”工作流程。 可重用工作流程是“被调用”工作流程。 一个调用方工作流程可以使用多个被调用的工作流程。 每个被调用的工作流程都在一行中引用。 结果是,调用方工作流程文件可能只包含几行 YAML,但在运行时可能会执行大量任务。 当您重用工作流程时,将使用整个被调用的工作流程,就像它是调用方工作流程的一部分一样。

如果重用其他存储库中的工作流程,则被调用工作流程中的任何操作都将像调用方工作流程的一部分一样运行。 例如,如果被调用的工作流使用 actions/checkout,则该操作将签出托管调用方工作流(而不是被调用的工作流)的存储库的内容。

当可重用工作流由调用方工作流触发时,github 上下文始终与调用方工作流关联。 调用的工作流会自动授予对 github.tokensecrets.GITHUB_TOKEN 访问权限。 有关 github 上下文的详细信息,请参阅“上下文”。

您可以将 GitHub Actions 工作流程中引用的重用工作流程视为包含工作流程的仓库依赖图中的依赖项。 有关详细信息,请参阅“关于依赖项关系图”。

可重用工作流程和入门工作流程

组织中所有有权创建工作流的人员都可利用入门工作流更快、更轻松地创建工作流。 当用户创建新工作流程时,他们可以选择入门工作流程,并且将为他们完成编写工作流程的部分或全部工作。 在入门工作流程中,您还可以引用可重用的工作流程,以便人们能够轻松地从重用集中管理的工作流程代码中受益。 如果在引用可重用工作流时使用提交 SHA,则可以确保重用该工作流的每个人都将始终使用相同的 YAML 代码。 但是,如果通过标记或分支引用可重用工作流程,请确保您可以信任该版本的工作流程。 有关详细信息,请参阅“GitHub Actions 的安全强化”。

有关详细信息,请参阅“为组织创建入门工作流程”。

访问可重复使用的工作流程

如果满足以下任意条件,则可重用工作流程可由另一个工作流使用:

  • 这两个工作流程位于同一存储库中。
  • 调用的工作流存储在公共存储库中,并且组织允许你使用公共可重用工作流。
  • 被调用的工作流存储在专用存储库中,该存储库的设置允许对其进行访问。 有关详细信息,请参阅 “与组织共享操作和工作流”和“从专用存储库共享操作和工作流”。

注意:为了增强安全性,GitHub Actions 不支持对操作或可重用工作流进行重定向。 这意味着,当所有者、操作存储库的名称或操作名称发生更改时,使用该操作并具有先前名称的任何工作流都将失败。

使用运行器

使用 GitHub 托管的运行器

始终仅使用调用方的上下文来评估 GitHub 托管的运行器的分配。 GitHub 托管的运行器的计费始终与调用方相关联。 调用方工作流程不能使用被调用存储库中 GitHub 托管的运行器。 有关详细信息,请参阅“使用 GitHub 托管的运行器”。

使用自托管的运行器

与调用方工作流程属于同一用户或组织 的被调用工作流程可以从调用方的上下文中访问自托管运行器。 这意味着被调用的工作流程可以访问自托管运行器,这些运行器具有以下特点:

  • 在调用方存储库中
  • 在调用方存储库的组织 中,前提是运行器已可供调用方存储库使用

限制

  • 最多可以连接到四个级别的工作流。 有关详细信息,请参阅“嵌套可重用工作流”。

  • 最多可以从单个工作流文件调用 20 个唯一的可重用工作流。 此限制包括可能从顶层调用方工作流文件开始调用的任何嵌套可重用工作流树。

    例如,top-level-caller-workflow.yml → called-workflow-1.yml → called-workflow-2.yml 计为 2 个可重用工作流 。

  • 对于在调用方工作流中的工作流级别定义的 env 上下文,在其中设置的任何环境变量都不会传播到被调用的工作流。 有关详细信息,请参阅“变量”和“上下文”。

  • 同样,对于在被调用的工作流中定义的 env 上下文,无法在调用方工作流的 env 上下文中访问在其中设置的环境变量。 必须改用可重用工作流的输出。 有关详细信息,请参阅“使用可重用工作流的输出”。

  • 若要在多个工作流中重复使用变量,请在组织、存储库或环境级别设置变量,并使用 vars 上下文来引用它们。 有关详细信息,请参阅“变量”和“上下文”。

  • 可重用工作流直接在作业中调用,而不是从作业步骤中调用。 因此,不能使用 GITHUB_ENV 将值传递给调用方工作流中的作业步骤。

创建可重用的工作流程

可重用工作流程是 YAML 格式的文件,与任何其他工作流程文件非常相似。 与其他工作流文件一样,可以在存储库的 .github/workflows 目录中找到可重用的工作流。 不支持 workflows 目录的子目录。

若要使工作流可重用,on 的值必须包括 workflow_call

on:
  workflow_call:

在可重用工作流程中使用输入和机密

您可以定义输入和机密,这些输入和机密可以从调用方工作流程传递,然后在被调用的工作流程中使用。 在可重用工作流程中使用输入或机密有三个阶段。

  1. 在可重用工作流中,使用 inputssecrets 关键字定义将从调用方工作流传递的输入或机密。

    on:
      workflow_call:
        inputs:
          config-path:
            required: true
            type: string
        secrets:
          envPAT:
            required: true
    

    有关定义输入和机密的语法的详细信息,请参阅 on.workflow_call.inputson.workflow_call.secrets

  2. 在可重用工作流中,引用在上一步的 on 键中定义的输入或机密。

    注意:如果在调用工作流中使用 secrets: inherit 继承机密,那么即使未在 on 键中显式定义机密,也可以引用它们。 有关详细信息,请参阅“GitHub Actions 的工作流语法”。

    jobs:
      reusable_workflow_job:
        runs-on: ubuntu-latest
        environment: production
        steps:
        - uses: actions/labeler@v4
          with:
            repo-token: ${{ secrets.envPAT }}
            configuration-path: ${{ inputs.config-path }}
    

在上面的示例中,envPAT 是已添加到 production 环境的环境机密。 因此,在作业中引用了此环境。

注意:环境机密是存储在你为存储库定义的环境中的加密字符串。 环境机密仅适用于引用相应环境的工作流程作业。 有关详细信息,请参阅“使用环境进行部署”。

  1. 传递来自调用方工作流程的输入或机密。

    若要将命名输入传递到调用的工作流,请在作业中使用 with 关键字。 使用 secrets 关键字传递命名机密。 对于输入,输入值的数据类型必须与调用的工作流中指定的类型(布尔值、数字或字符串)匹配。

    jobs:
      call-workflow-passing-data:
        uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main
        with:
          config-path: .github/labeler.yml
        secrets:
          envPAT: ${{ secrets.envPAT }}
    

    在同一组织或企业中调用可重用工作流的工作流可使用 inherit 关键字隐式传递机密。

    jobs:
      call-workflow-passing-data:
        uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main
        with:
          config-path: .github/labeler.yml
        secrets: inherit
    

示例可重用工作流程

此名为 workflow-B.yml 的可重用工作流文件(稍后将在调用方工作流示例中引用此文件)从调用方工作流中获取输入字符串和机密,并在操作中使用它们。

YAML
name: Reusable workflow example

on:
  workflow_call:
    inputs:
      config-path:
        required: true
        type: string
    secrets:
      token:
        required: true

jobs:
  triage:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/labeler@v4
      with:
        repo-token: ${{ secrets.token }}
        configuration-path: ${{ inputs.config-path }}

调用可重用工作流程

使用 uses 关键字调用可重用工作流。 与在工作流程中使用操作不同,您可以直接在作业中调用可重用工作流程,而不是从作业步骤中调用。

jobs.<job_id>.uses

可以使用以下语法之一引用可重用的工作流文件:

  • {owner}/{repo}/.github/workflows/{filename}@{ref} 用于公共和专用存储库中的可重用工作流。
  • ./.github/workflows/{filename} 用于同一存储库中的可重用工作流。

在第一个选项中,{ref} 可以是 SHA、发布标记或分支名称。 如果发布标记和分支具有相同的名称,则发布标记优先于分支名称。 出于稳定性和安全性考虑,使用提交 SHA 是最稳妥的选项。 有关详细信息,请参阅“GitHub Actions 的安全强化”。

如果使用第二个语法选项(不带 {owner}/{repo}@{ref}),则调用的工作流来自与调用方工作流相同的提交。 不允许使用 refs/headsrefs/tags 等引用前缀。

您可以调用多个工作流程,在单独的作业中引用每个工作流程。

jobs:
  call-workflow-1-in-local-repo:
    uses: octo-org/this-repo/.github/workflows/workflow-1.yml@172239021f7ba04fe7327647b213799853a9eb89
  call-workflow-2-in-local-repo:
    uses: ./.github/workflows/workflow-2.yml
  call-workflow-in-another-repo:
    uses: octo-org/another-repo/.github/workflows/workflow.yml@v1

将输入和机密传递到可重用的工作流程

若要将命名输入传递到调用的工作流,请在作业中使用 with 关键字。 使用 secrets 关键字传递命名机密。 对于输入,输入值的数据类型必须与调用的工作流中指定的类型(布尔值、数字或字符串)匹配。

jobs:
  call-workflow-passing-data:
    uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main
    with:
      config-path: .github/labeler.yml
    secrets:
      envPAT: ${{ secrets.envPAT }}

在同一组织或企业中调用可重用工作流的工作流可使用 inherit 关键字隐式传递机密。

jobs:
  call-workflow-passing-data:
    uses: octo-org/example-repo/.github/workflows/reusable-workflow.yml@main
    with:
      config-path: .github/labeler.yml
    secrets: inherit

将矩阵策略与可重用工作流配合使用

使用矩阵策略的作业可以调用可重用工作流。

使用矩阵策略,可以在单个作业定义中使用变量自动创建基于变量组合的多个作业运行。 例如,可以使用矩阵策略将不同输入传递给可重用工作流。 有关矩阵的详细信息,请参阅“对作业使用矩阵”。

以下示例作业调用可重用工作流,并通过使用值 [dev, stage, prod] 定义变量 target 来引用矩阵上下文。 它将运行三个作业,变量中的每个值对应一个作业。

YAML
jobs:
  ReuseableMatrixJobForDeployment:
    strategy:
      matrix:
        target: [dev, stage, prod]
    uses: octocat/octo-repo/.github/workflows/deployment.yml@main
    with:
      target: ${{ matrix.target }}

调用可重用工作流程的作业支持的关键字

调用可重用工作流程时,只能在包含调用的作业中使用以下关键字:

示例调用方工作流程

此工作流程文件调用两个工作流程文件。 向其中的第二个文件 workflow-B.yml(如可重用工作流示例中所示)传递了一个输入 (config-path) 和一个机密 (token)。

YAML
name: Call a reusable workflow

on:
  pull_request:
    branches:
      - main

jobs:
  call-workflow:
    uses: octo-org/example-repo/.github/workflows/workflow-A.yml@v1

  call-workflow-passing-data:
    permissions:
      contents: read
      pull-requests: write
    uses: octo-org/example-repo/.github/workflows/workflow-B.yml@main
    with:
      config-path: .github/labeler.yml
    secrets:
      token: ${{ secrets.GITHUB_TOKEN }}

嵌套可重用工作流

最多可以连接四个级别的工作流 - 即顶级调用方工作流和最多三个级别的可重用工作流。 例如:caller-workflow.yml → called-workflow-1.yml → called-workflow-2.yml → called-workflow-3.yml 。 不允许工作流树中存在循环。

在可重用工作流中,可以调用另一个可重用工作流。

YAML
name: Reusable workflow

on:
  workflow_call:

jobs:
  call-another-reusable:
    uses: octo-org/example-repo/.github/workflows/another-reusable.yml@v1

将机密传递给嵌套工作流

可以在调用工作流中使用 jobs.<job_id>.secrets 将命名机密传递给直接调用的工作流。 或者,可以使用 jobs.<job_id>.secrets.inherit 将调用工作流的所有机密传递给直接调用的工作流。 有关详细信息,请参阅上面的“重新使用工作流”部分和参考文章“GitHub Actions 的工作流语法”。 机密仅传递给直接调用的工作流,因此在工作流链 A > B > C 中,工作流 C 仅从 A 接收从 A 传递给 B,然后从 B 传递给 C 的机密。

在以下示例中,工作流 A 使用 inherit 关键字将其所有机密传递给工作流 B,但工作流 B 仅将一个机密传递给工作流 C。传递给工作流 B 的任何其他机密都不可供工作流 C 使用。

jobs:
  workflowA-calls-workflowB:
    uses: octo-org/example-repo/.github/workflows/B.yml@main
    secrets: inherit # pass all secrets
jobs:
  workflowB-calls-workflowC:
    uses: different-org/example-repo/.github/workflows/C.yml@main
    secrets:
      envPAT: ${{ secrets.envPAT }} # pass just this secret

访问和权限

如果初始调用方工作流无法访问任何嵌套工作流,则包含嵌套可重用工作流的工作流会失败。 有关详细信息,请参阅“重新使用工作流”。

GITHUB_TOKEN 权限在嵌套工作流中只能相同或更严格。 例如,在工作流链 A > B > C 中,如果工作流 A 具有 package: read 令牌权限,则 B 和 C 不能具有 package: write 权限。 有关详细信息,请参阅“自动令牌身份验证”。

有关如何使用 API 确定特定工作流运行中涉及哪些工作流文件的信息,请参阅“监视正在使用哪些工作流”。

使用可重用工作流程的输出

可重用工作流程可能会生成要在调用方工作流程中使用的数据。 若要使用这些输出,必须将它们指定为可重用工作流的输出。

如果设置输出的可重用工作流使用矩阵策略来执行,则输出会是由矩阵的最后一个成功完成且实际设置值的可重用工作流设置的输出。 这意味着,如果最后一个成功完成可重用工作流为其输出设置空字符串,而倒数第二个成功完成可重用工作流为其输出设置实际值,则输出会包含倒数第二个完成可重用工作流的值。

以下可重用工作流程具有包含两个步骤的单个作业。 在每个步骤中,我们设置一个单词作为输出:"hello" 和 "world"。 在作业的 outputs 部分,我们将这些步骤输出映射到名为 output1output2 的作业输出。 然后,在 on.workflow_call.outputs 部分中,为工作流本身定义两个输出,一个称为 firstword,映射到 output1,另一个称为 secondword,映射到 output2

YAML
name: Reusable workflow

on:
  workflow_call:
    # Map the workflow outputs to job outputs
    outputs:
      firstword:
        description: "The first output string"
        value: ${{ jobs.example_job.outputs.output1 }}
      secondword:
        description: "The second output string"
        value: ${{ jobs.example_job.outputs.output2 }}

jobs:
  example_job:
    name: Generate output
    runs-on: ubuntu-latest
    # Map the job outputs to step outputs
    outputs:
      output1: ${{ steps.step1.outputs.firstword }}
      output2: ${{ steps.step2.outputs.secondword }}
    steps:
      - id: step1
        run: echo "firstword=hello" >> $GITHUB_OUTPUT
      - id: step2
        run: echo "secondword=world" >> $GITHUB_OUTPUT

现在,我们可以在调用方工作流程中使用输出,就像使用同一工作流程中作业的输出一样。 我们使用在可重用工作流中的工作流级别定义的名称引用输出:firstwordsecondword。 在此工作流中,job1 调用可重用工作流,job2 将可重用工作流的输出(“hello world”)呈现在工作流日志的标准输出中。

YAML
name: Call a reusable workflow and use its outputs

on:
  workflow_dispatch:

jobs:
  job1:
    uses: octo-org/example-repo/.github/workflows/called-workflow.yml@v1

  job2:
    runs-on: ubuntu-latest
    needs: job1
    steps:
      - run: echo ${{ needs.job1.outputs.firstword }} ${{ needs.job1.outputs.secondword }}

有关使用作业输出的详细信息,请参阅“GitHub Actions 的工作流语法”。 如果要在工作流之间共享变量以外的内容(例如生成工件),请参阅“将工作流程数据存储为构件”。

监控正在使用的工作流程

您可以使用 GitHub REST API 来监控可重用工作流程的使用过程。 prepared_workflow_job 审核日志操作会在工作流作业启动时触发。 记录的数据包括:

  • repo - 工作流作业所在的组织/存储库。 对于调用其他工作流程的作业,这是调用方工作流程的组织/存储库。

  • @timestamp - 启动作业的日期和时间,采用 Unix 纪元格式。

  • job_name - 运行的作业的名称。

  • calling_workflow_refs - 此工作流作业中涉及的所有调用方工作流的文件路径数组。 数组中的项的顺序与它们被调用的顺序相反。 例如,在工作流 A > B > C 的链中,当查看工作流 C 中作业的日志时,数组为 ["octo-org/octo-repo/.github/workflows/B.yml", "octo-org/octo-repo/.github/workflows/A.yml"]

  • calling_workflow_shas - 此工作流作业中涉及的所有调用方工作流的 SHA 数组。 数组包含的项数与 calling_workflow_refs 数组的相同,并且这些项的顺序相同。

  • job_workflow_ref - 使用的工作流文件,采用 {owner}/{repo}/{path}/{filename}@{ref} 格式。 对于调用其他工作流程的作业,这用于标识被调用的工作流程。

有关使用 REST API 查询组织的审核日志的信息,请参阅“适用于组织的 REST API 终结点”。

注意:只能使用 REST API 查看 prepared_workflow_job 的审核数据。 它在 GitHub Web 界面中不可见,也不包含在 JSON/CSV 导出的审核数据中。

使用可重用工作流重新运行工作流和作业

可使用 SHA、发布标记或分支名称引用公共存储库中的可重用工作流。 有关详细信息,请参阅“重新使用工作流”。

重新运行使用可重用工作流且引用不是 SHA 的工作流时,有一些行为需要注意:

  • 重新运行工作流中的所有作业时将使用指定引用中的可重用工作流。 若要详细了解如何重新运行工作流中的所有作业,请参阅“重新运行工作流程和作业”。
  • 重新运行失败的作业或工作流中的特定作业时将使用第一次尝试的同一提交 SHA 中的可重用工作流。 若要详细了解如何重新运行工作流中失败的作业,请参阅“重新运行工作流程和作业”。 若要详细了解如何重新运行工作流中的特定作业,请参阅“重新运行工作流程和作业”。

后续步骤

若要继续了解 GitHub Actions,请参阅“触发工作流的事件”。