配了三年 reusable workflow,今天才发现 github.workflow_ref 从来不是 workflow 自己的——这件事今天被 GitHub 彻底原生化了

配了三年 reusable workflow,今天才发现 github.workflow_ref 从来不是 workflow 自己的——这件事今天被 GitHub 彻底原生化了

Reusable workflow 是个好东西。把 CI 逻辑抽到一个独立文件,主 workflow 调一下 uses: 就能复用,维护成本降一大截。但你有没有遇到过这种情况:你想在 reusable workflow 里做日志审计,想知道「这个 job 到底用的是哪个 workflow 文件定义的」——结果 github.workflow_ref 给你返回的是调用者的信息,而不是你自己。

这就是所谓「身份反转」问题。

旧方案的痛:你在自己的 workflow 里,却不知道你是谁

Reusable workflow 存在已久,但它的上下文属性一直有个设计问题:github.workflow_refgithub.workflow_sha 这两个属性,指向的是调用者(caller)的 workflow 文件,而不是被调用者(called/reusable)自己的 workflow 文件。

举个例子:你的主 workflow 是 A.yml,它调用了一个 reusable workflow B.yml。在 B.yml 的 job 里,github.workflow_ref 返回的是 A.yml 的路径,而不是 B.yml。如果 B.yml 需要知道「自己是谁」——比如做签名校验、打印自己所在的 commit——它拿到的信息是错的。

社区解决这个问题靠的是 canonical/get-workflow-version-action 这个第三方 action:手动获取 called workflow 的真实 ref 和 SHA。但这是一个带副作用的 workaround:多一个 action 依赖,多一个供应链风险点。

2025 年 3 月的 tj-actions 供应链攻击(CVE-2025-30066)就是典型——攻击者通过污染 GitHub Actions 生态里的一个热门 action,窃取了 23000+ 个仓库的 runner 内存中的 secrets。问题根源之一正是 over-permissioned tokens 和过多的第三方 action 依赖。

*GitHub 的原生修复:四个新的 job. 属性**

2026 年 9 月,GitHub 给 reusable workflow 补上了这四个新属性:

  • job.workflow_ref — 定义当前 job 的 workflow 文件的完整 ref
  • job.workflow_sha — 定义当前 job 的 workflow 文件的 commit SHA
  • job.workflow_repository — 定义当前 job 的 workflow 文件所在仓库(owner/repo)
  • job.workflow_file_path — 定义当前 job 的 workflow 文件相对于仓库根目录的路径

这四个属性才是 reusable workflow 真正需要知道的「我是谁」。

关键区别是:直接写在 workflow 里的 job,job.workflow_ref 等于 github.workflow_ref;而对于 reusable workflow,job.workflow_ref 指向被调用 workflow,两者才真正分开。

两个实际用法

第一个:reusable workflow 检出自己的代码,不用硬编码仓库路径。

旧写法(硬编码):

- uses: actions/checkout@v4
  with:
    repository: my-org/my-repo
    ref: ${{ github.sha }}

新写法(动态自引用):

- uses: actions/checkout@v4
  with:
    repository: ${{ job.workflow_repository }}
    ref: ${{ job.workflow_sha }}

这样 reusable workflow 本身不需要知道调用者是谁,天然支持跨仓库复用。

第二个(更重要):在 reusable workflow 开头打印 job.workflow_sha,为 SLSA 审计链条提供密码学证明。

- name: Log workflow identity for audit trail
  run: echo "Running workflow SHA: ${{ job.workflow_sha }}"

GitHub 的 SLSA 工具链可以消费这个信息,让 workflow 自己证明自己的身份,而不是依赖调用者传入的数据。这个在出了供应链事故之后会特别有价值——你可以独立验证「到底是哪个版本的 workflow 在跑」。

一个限制:GitHub Enterprise Server 暂时没有

目前这四个属性只对 github.com 公开,GitHub Enterprise Server 还没上线。如果你的 CI 全跑在 GHES 上,暂时还用不了。

下一步:三个具体动作

  1. 立刻:如果你的 reusable workflow 还在用 canonical/get-workflow-version-action,查一下它的依赖情况,考虑迁移到原生 job.workflow_sha。这个 action 已经 deprecated,但还没删除,越早换越安全。

  2. 本周:在所有 reusable workflow 的开头加一行 echo "job.workflow_sha: ${{ job.workflow_sha }}"——不需要任何额外 action,三行 YAML,审计链条就建立起来了。

  3. 长期:配合 GitHub 九月同批的 vulnerability-alerts: read 权限(最小权限读 Dependabot alerts,不再需要 contents: write),以及 runner deprecation REST API,三个改动加在一起,几小时工作,CI 安全基线明显提升。

Reusable workflow 的「身份反转」这个问题存在了很久,社区用第三方 action 打补丁也是一种工程判断。现在 GitHub 补上了原生能力,是时候把那个 workaround 卸掉了。

评论区

0 条评论

登录后可评论。