第36章|GitHub Actions 可复用组件:composite action 与 reusable workflow

复制粘贴 YAML 是技术债的复利:第十个仓库改一行,你得改十次。 把重复能力沉淀成可复用资产:在 step 粒度用 composite action, 在 job / workflow 粒度用 workflow_call——本章讲清边界、输入输出、版本钉扎与治理。

Composite

步骤级复用

  • action.yml
  • runs: composite
  • inputs / outputs
Reusable

工作流级复用

  • on: workflow_call
  • secrets: inherit / pass
  • outputs across jobs
Governance

版本与所有权

  • pin by tag / SHA
  • CODEOWNERS
  • breaking changes

1. 先选粒度:你要复用「几步」还是「整条流水线」?

Composite action:像「可插拔零件」——在同一个 job里多段 run/uses 打包成一个 uses:。 适合:统一安装工具链、统一缓存策略、统一安全扫描入口。

Reusable workflow:像「整条装配线」——另一个 workflow 以 job 形式被调用,可包含多个 job、needs、环境、审批。 适合:组织级标准 CI/CD、多仓库同一套发布模板。

Step-level vs workflow-level reuse composite action uses: org/setup-toolchain@v3 expands to internal steps step A → step B → step C same job, same runner reusable workflow uses: org/ci/.github/workflows/ci.yml@main separate workflow run segment job 1 job 2
图 1:composite 仍在同一 job内展开步骤;reusable workflow 调用另一份 workflow,可包含多 job 与编排。

2. Composite action:action.yml 与 runs: composite

在仓库 action.yml(或 action.yaml)声明 runs: using: composite, 下列 steps: 与平常 job 类似,但可使用 inputsoutputs 与调用方交互。

# action.yml (simplified)
name: Setup toolchain
description: Install Node and cache dependencies
inputs:
  node-version:
    required: true
runs:
  using: composite
  steps:
    - uses: actions/setup-node@v4
      with:
        node-version: ${{ inputs.node-version }}
    - run: npm ci
      shell: bash

调用方仓库中:uses: ./path/to/actionuses: org/repo@v1

3. Reusable workflow:on.workflow_call

在被调用仓库的 workflow 里写 on: workflow_call:,定义 inputssecrets。 调用方用 uses: org/repo/.github/workflows/x.yml@ref,并传入 with: / secrets:

# .github/workflows/reusable-ci.yml
on:
  workflow_call:
    inputs:
      node-version:
        required: true
        type: string
    secrets:
      NPM_TOKEN:
        required: false

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: ${{ inputs.node-version }}
# caller workflow
jobs:
  ci:
    uses: my-org/shared-workflows/.github/workflows/reusable-ci.yml@v1
    with:
      node-version: '20'
    secrets: inherit
secrets:secrets: inherit 可把调用方可见的 secrets 传给被调用 workflow(仍受信任边界约束);显式传递则更清晰。
Caller repo → shared workflow repo application repo caller workflow shared-workflows repo reusable-ci.yml @v1 workflow_call
图 2:多仓库复用同一 workflow_call 定义;用 tag 或 SHA 钉版本,避免 @main 悄悄改行为。

4. 版本钉扎:ref 是契约

对可复用组件使用 tagv1v2)或 commit SHA 固定行为;主分支引用适合快速迭代但会带来不可预期变更。 发布可复用 workflow 的仓库应把 breaking changes 写进 release notes。

5. 治理:所有权、评审与依赖面

.github/workflowsaction.yml 配置 CODEOWNERS;第三方 action 使用官方或可信来源,并钉版本。 可复用资产变更 = 多仓库影响面,走评审与灰度。

Reuse governance: review → tag → consumers CODEOWNERS + required review change to shared action / workflow release v1.2.0 repo A @v1.2.0 repo B @v1.2.0 repo C @v1.2.0
图 3:共享资产变更影响多个消费者;用评审、语义化 tag 与发布说明降低“静默破坏”。

6. 何时不用 reusable workflow?

若只需要共享几步 shell,composite 更轻;若需要跨 job 并行、环境审批、复杂 needs,选 reusable workflow。 不要把业务特有的参数硬塞进万能模板——可复用的是结构,不是所有细节

Choose reuse primitive Need only bundled steps in one job? yes → composite no → reusable workflow action.yml workflow_call ?
图 4:决策直觉——单 job 内步骤打包用 composite;多 job、编排、环境用 reusable workflow。

7. 最小清单

  1. 先画重复块:是步骤级还是整条流水线级,再选 composite 或 workflow_call
  2. 对外暴露 inputs/outputs(与 secrets 边界)并写清楚文档。
  3. 用 tag 或 SHA 钉版本;谨慎使用浮动分支引用。
  4. 共享仓库配 CODEOWNERS 与 required review;重大版本发 release notes。
← 上一章:Secrets 与 OIDC 下一章:CD 基础(环境与审批)→