1485 字
7 分鐘

GitHub Actions reusable workflow 的 secrets: inherit 怎麼用?

把 GitHub Actions workflow 拆成 reusable workflow 後,最常見的錯誤是 caller 裡明明有 secret,called workflow 卻讀到空字串。原因是 secrets 不會自動傳入 reusable workflow;你必須逐一指定要傳的 secret,或在符合範圍時使用 secrets: inherit

這篇只處理 workflow-to-workflow 的傳遞邊界。它和 action 的 with、一般 job 的 env,以及 GitHub Actions cache 的安全性是不同問題;若 workflow 還會讀取不可信的 PR 程式碼,請一併檢查 pull_request_target 的 checkout 邊界

明確傳遞與 inherit 的差異#

作法會傳什麼適合情境主要風險
secrets.<name> 對應只傳指定的 secretproduction deploy、跨團隊共用 workflowcaller 與 called 的名稱需要對得上
secrets: inherit傳遞 caller 可取得的 secrets同組織內的可信任共用 workflow可能把不需要的 secret 一起交給 called workflow

兩種作法都要放在呼叫 reusable workflow 的 job 上,而不是某個 step 裡。called workflow 則必須以 on: workflow_call 接收,並在自己的 job 或 action 中透過 secrets context 使用。

先用明確 secret 建立可審核的契約#

called workflow 可以宣告它需要的 secret:

.github/workflows/deploy.yml
on:
workflow_call:
inputs:
environment:
required: true
type: string
secrets:
deploy_token:
required: true
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Deploy
env:
DEPLOY_TOKEN: ${{ secrets.deploy_token }}
run: ./scripts/deploy.sh "$DEPLOY_TOKEN"

caller 在 job 層級指定 mapping:

.github/workflows/release.yml
on:
workflow_dispatch:
jobs:
deploy:
uses: ./.github/workflows/deploy.yml
with:
environment: production
secrets:
deploy_token: ${{ secrets.DEPLOY_TOKEN }}

這種寫法多一行設定,卻把 reusable workflow 的輸入契約寫清楚:called workflow 只期待 deploy_token,caller 再決定要把哪一個 repository 或 organization secret 對應過去。對 production deploy、不同權限等級或跨團隊共用的 workflow,先採明確傳遞比較容易 review。

secrets: inherit 只在真的需要時使用#

如果 caller 和 called workflow 位於同一個 organization,或是符合 GitHub 文件所述的 enterprise 範圍,可以在呼叫 job 使用:

jobs:
deploy:
uses: ./.github/workflows/deploy.yml
secrets: inherit

called workflow 會取得 caller 可用的 secrets;這適合一組高度信任、由同一團隊維護的共用流程。不過,inherit 的便利性也代表 called workflow 可能讀到它其實不需要的 secret。若 workflow 內部會呼叫第三方 action、執行外部工具或允許多個團隊修改,明確傳遞會比較容易縮小權限。

不要把 secrets: inherit 當成「跨任意 repository 自動共享 secrets」的開關。private reusable workflow 還要符合 repository access policy;另外,secret 只會傳給直接被呼叫的 workflow。

A → B → C 時,secret 要逐層傳遞#

假設 workflow A 呼叫 B,B 再呼叫 C:

A -- secrets: inherit --> B -- 明確傳遞或 inherit --> C

GitHub 文件指出,C 不會因為 A 已經傳給 B 就自動取得 secrets。B 必須再把需要的 secret 傳給 C,否則 C 的 secrets context 會是空的。這是巢狀 reusable workflow 很常見的排錯點,尤其當 B 只是中間的共用部署層時。

如果一條 workflow chain 中每一層都把所有 secrets 繼承下去,權限範圍會越來越難追蹤。比較可維護的方式是讓每一層明確列出下一層真正需要的名稱,並把 deploy、registry、通知等用途拆開。

environment secrets 不會從 caller 直接傳入#

on.workflow_call 不支援用 environment 宣告 caller 要傳入的 environment secret。如果 called workflow 的 job 自己設定 environment,該 environment 的 secret 會被使用,而不是 caller 傳入的同名 secret。這會造成「secret 已 mapping,部署卻拿到另一個值」的錯覺。

遇到這種情況,先查:

  1. caller 呼叫 job 是否使用 secrets,而不是把 secret 寫在無法傳遞的 step env
  2. called workflow 是否有 on.workflow_call,以及 secret 名稱是否拼寫一致。
  3. called job 是否指定 environment,該 environment 的 secret policy 與 required reviewers 是否已通過。
  4. workflow 是否是 A → B → C,且每一層都明確傳遞需要的 secret。
  5. 觸發來源是否是 fork PR 或 Dependabot event;GitHub 對這些事件有額外的 secret 限制。

不要用 echo "$SECRET" 來確認值。GitHub 會嘗試遮罩 secret,但官方也提醒遮罩不是所有轉換形式都能保證;應改用不洩漏內容的存在性檢查,並以真正的部署測試驗證權限。

什麼時候選哪一種#

  • 只需要一個 deploy token:用明確 secret mapping。
  • 同一團隊維護的內部共用 workflow,且確定 caller 的 secrets 都可交給它:才考慮 secrets: inherit
  • workflow 會再呼叫下一層:每一層只傳下一層需要的 secret。
  • 需要 environment approval 或不同環境的金鑰:把 environment 的責任放在 called workflow,並明確寫進部署契約。
  • 來源是 fork PR 或 Dependabot:先假設一般 secrets 不可用,改用合適的權限與 OIDC/受控流程重新設計。

secrets: inherit 解決的是傳遞語法,不會自動降低 workflow 的信任風險。把 reusable workflow 當成一個需要明確輸入的函式,先列出最小 secret 契約,再決定是否值得使用整批繼承,排錯和審查都會簡單很多。

常見問題#

Q: reusable workflow 內為什麼讀不到 caller 的 secret?#

A: secrets 不會自動傳給 reusable workflow。caller 必須在呼叫 job 使用 secrets.<name> mapping,或在符合範圍與信任條件時使用 secrets: inherit;called workflow 則必須由 on: workflow_call 接收。若是 A → B → C 的巢狀流程,B 還要再把需要的 secret 傳給 C。

Q: secrets: inherit 會把所有 GitHub 帳號的 secrets 都傳過去嗎?#

A: 它傳的是 caller workflow 可以取得的 secrets,並且受 reusable workflow 的 repository、organization 或 enterprise 存取範圍限制,不是任意帳號的全域分享。也因此要先確認 called workflow 的維護者與第三方 action,再決定是否把整批 secrets 交給它;production 流程通常更適合明確 mapping。

Q: 可以用 workflow_call 從 caller 傳 environment secret 嗎?#

A: GitHub 文件指出,on.workflow_call 不支援 environment keyword。若 called workflow 的 job 指定了 environment,該 environment 的 secret 會被使用,可能覆蓋你以為從 caller 傳入的同名值。需要 approval 或環境隔離時,應把 environment 的責任與 secret policy 明確放在 called workflow 端。

參考資料:

GitHub Docs:Reuse workflows

GitHub Docs:Using secrets in GitHub Actions

GitHub Docs:Workflow syntax — jobs.<job_id>.secrets

GitHub Actions reusable workflow 的 secrets: inherit 怎麼用?
https://laplusda.com/posts/github-actions-reusable-workflow-secrets/
作者
Zero
發佈於
2026-08-06
許可協議
CC BY-NC-SA 4.0
這篇文章有幫助嗎?

回報錯字、失效連結,或告訴我你想看的延伸主題。