GH-200 數位教科書 開啟互動版

D4:管理企業的 GitHub Actions

D4-O1 散布與治理 actions 與工作流程

治理要回答兩件事:別人能用哪些 actions 與工作流程,以及它們跑起來有多大權限。可重用的元件本身(可重用工作流程、複合 action、組織起始工作流程)見領域二與三;本節講政策。

組織層級:哪些 actions 可以執行

在組織的 Settings → Actions → General → Policies 選擇:

選「只允許組織自己的 actions」會封鎖所有 GitHub 作者的 actions,所以 actions/checkout 也不能用。要放行其他來源時,可以選:

選項 允許什麼
GitHub 建立的 actions actions 與 github 組織裡的 actions
Marketplace 上的已驗證建立者 已驗證建立者發佈在 Marketplace 的 actions
指定的 actions 與可重用工作流程 依樣式放行或封鎖

樣式語法:action 用 OWNER/REPOSITORY@TAG-OR-SHA,可重用工作流程用 OWNER/REPOSITORY/PATH/FILENAME@TAG-OR-SHA;* 是萬用字元,, 分隔多個樣式;前面加 ! 表示封鎖。預設只有列出的樣式被允許,但 *, !space-org/action@* 表示「除了這個 action 之外全部允許」。指定的樣式不能超過 1000 個。如果工作流程受相依性鎖定檔(lockfile)涵蓋,以標籤或分支寫的項目比對不到,要改用萬用字元或完整的 commit SHA。

要求固定到完整 commit SHA:啟用「Require actions to be pinned to a full-length commit SHA」後,對組織的 actions 與 GitHub 作者的 actions 生效;可重用工作流程仍然可以用標籤參照;已被鎖定檔鎖定的相依項目也滿足這個要求,不必修改工作流程。

企業層級:政策的覆蓋方式

來自 fork 的 pull request

公開 repository 的外部協作者,可在組織層級選擇哪些人的 fork PR 工作流程需要核准:

  1. 剛加入 GitHub 的首次貢獻者;
  2. 首次貢獻者;
  3. 所有外部協作者。

預設是所有首次貢獻者都需要核准。由 pull_request_target 觸發的工作流程一律執行,不受這些設定影響。組織層級的變更會覆寫企業層級的設定。已有任何變更被合併的使用者,在前兩個選項下不再算首次貢獻者。

私有與 internal repository 的 fork PR 則有四種政策:執行工作流程(唯讀 GITHUB_TOKEN、預設沒有 secrets)、傳送寫入權杖、傳送 secrets、要求核准。

預設的 GITHUB_TOKEN 權限

保留期、快取與自訂映像的上限

項目 預設 可設定範圍
檢查、工作流程執行、狀態、成品、日誌 90 天 公開 repository 1–90 天;私有與 internal 1–400 天
快取保留 7 天 企業最大:公開 90 天、私有與 internal 365 天
每個 repository 的快取容量 10 GB 企業最大可到 10,000 GB;超過方案內含的 10 GB 要額外計費
每個自訂映像的版本數上限 20 1–100
未使用版本的保留 30 天 1–90
版本的最長存在時間 60 天 7–90

官方還提到:從 2026 年 10 月 1 日起,這些保留政策也套用到檢查、工作流程執行與 commit 狀態。

這次沒有核對到:組織層級的「required workflows」(規則集的「要求工作流程通過」)。我讀了規則集的可用規則頁面,沒有找到它,備考前請在官方頁面確認。

判斷練習

情境 A: 組織想只允許自家的 actions 與 actions/*、github/*,其餘一律禁止。

解析: 選「允許組織自己的與選定的非組織 actions」,勾選「GitHub 建立的 actions」;不要選「只允許組織自己的」,那會把 actions/checkout 也擋掉。

情境 B: 組織要求所有第三方 actions 都固定到完整 SHA,但團隊的可重用工作流程仍用 @v2 標籤。

解析: SHA 固定要求不適用於可重用工作流程,標籤參照仍然允許;它適用於組織的 actions 與 GitHub 作者的 actions。

情境 C: 企業停用了某項政策,某組織管理員想自己啟用。

解析: 不行。企業停用的政策,個別組織與 repository 不能再啟用;企業啟用的政策才可以被下層選擇性停用。

來源:Disabling or limiting GitHub Actions for your organization(GH200-DOC-31)、Enforcing policies for GitHub Actions in your enterprise(GH200-DOC-32);2026-11-03 以頁面原文比對本節的數字與條件。兩頁對預設 GITHUB_TOKEN 權限的敘述略有差異(組織頁寫 contents 與 packages 唯讀;企業頁寫 2023-02-02 之後建立的預設全部範圍唯讀),本節兩者都寫出,沒有自行調和。

D4-O2 大規模管理 runners

GitHub 代管的 runners

自管(self-hosted)runner

自管 runner 是你部署與維護的系統:控制權較大,但作業系統與其他軟體都要自己更新;GitHub 只自動更新 runner 應用程式本身。它不需要每個 job 都是乾淨的執行個體,所以 job 之間的狀態可能殘留。有三種範圍:repository 層級(服務單一 repository)、組織層級(服務多個 repository)、企業層級(可指派給多個組織)。

支援的環境:Linux(RHEL 8+、Ubuntu 20.04+、Debian 10+ 等)、Windows(Windows 10/11 64 位元、Windows Server 2016/2019/2022)、macOS 11.0 以上;架構是 x64,ARM64 在 Linux、macOS、Windows 上為公開預覽。使用 Docker 容器 action 或服務容器的工作流程,需要裝有 Docker 的 Linux 機器。

連線需求:主機必須能對外建立 443 埠的 HTTPS 連線,至少 70 kbps 的上傳與下載速度;必要的網域有 github.com、api.github.com、*.actions.githubusercontent.com,其他依工作流程而定(例如下載 actions 用 codeload.github.com、容器用 ghcr.io)。如果組織或企業使用 IP 允許清單,必須把自管 runner 的 IP 位址加進去。

自動更新:預設啟用——指派 job 時更新,或 runner 沒有 job 時在新版釋出一週內更新;註冊時用 --disableupdate 可以停用。停用後,必須在新版釋出後 30 天內安裝新版,否則 GitHub 不再把 job 排給它;重大安全更新會擋住 job,直到更新為止。

暫時性(ephemeral)runner:註冊時用 --ephemeral,GitHub 在執行一個 job 後就取消註冊,清理由你負責;它的日誌要轉送到外部儲存。

job 如何選到 runner:job 會送給標籤與群組都符合 runs-on 的、線上且閒置的 runner;如果 runner 在 60 秒內沒有接起,job 會重新排隊;沒有符合的 runner 時 job 留在佇列,排隊超過 24 小時就會失敗。

runner 群組(runner groups)

larger runners 的網路

監控與疑難排解自管 runner

狀態 意思
Idle 已連線,準備好執行 job
Active 正在執行 job
Offline 沒有連線:機器關機、runner 程式沒執行,或無法連到 GitHub

判斷練習

情境 A: 一個 job 的 runs-on: [self-hosted, linux, gpu],卻一直排隊,最後失敗。

解析: 沒有符合所有標籤與群組、線上且閒置的 runner;排隊超過 24 小時就會失敗。檢查標籤是否完全相符、runner 是否在線(不是 Offline),以及該 repository 是否有權使用該 runner 群組。

情境 B: 你停用了自管 runner 的自動更新,一個月後 job 全部不再被排到那些 runner。

解析: 停用自動更新後,新版釋出後 30 天內必須安裝,否則 GitHub 停止排 job 給它;需要手動升級 runner 應用程式。

情境 C: 組織有 IP 允許清單,新的自管 runner 註冊後連不上 GitHub。

解析: 必須把自管 runner 的 IP 位址加進允許清單;同時確認出站 443 與必要網域(github.com、api.github.com、*.actions.githubusercontent.com)可連。

來源:About GitHub-hosted runners(GH200-DOC-41)、Customize GitHub-hosted runners(GH200-DOC-42)、About self-hosted runners(GH200-DOC-34)、Self-hosted runners reference(GH200-DOC-35)、Manage access to self-hosted runners(GH200-DOC-33)、Monitor and troubleshoot self-hosted runners(GH200-DOC-36)、Manage larger runners(GH200-DOC-43);2026-11-03 以頁面原文比對本節的數字與條件。runner 群組頁面沒有涵蓋「限定特定工作流程」,本節沒有補寫。

D4-O3 管理加密 secrets 與 variables

三個層級與存取

secret 與 variable 的差別

項目 secrets variables(設定變數)
讀取方式 secrets context vars context
未設定時 評估成空字串 評估成空字串
日誌 自動遮蔽,但官方說不保證,且只能遮蔽目前 job 用到的 secret 我讀的頁面沒有寫是否遮蔽(不要把機密放在 variables)
加密 在送到 GitHub 之前就以 Libsodium sealed box 在用戶端加密 —

variables 與 env 不同:env 在工作流程、job 或步驟層級設定,作用範圍就是該元素;設定變數在介面建立,用 vars 讀取。官方把「在組織層級設預設值、讓 repository 擁有者覆寫」當成使用情境,但沒有寫出明確的優先順序,我也沒有核對到名稱限制、大小與數量上限。

使用 secrets 的規則

用 REST API 管理

範圍 建立或更新 取得公鑰
組織 PUT /orgs/{org}/actions/secrets/{secret_name}(需 encrypted_value、key_id、visibility) GET /orgs/{org}/actions/secrets/public-key
repository PUT /repos/{owner}/{repo}/actions/secrets/{secret_name}(需 encrypted_value、key_id) GET /repos/{owner}/{repo}/actions/secrets/public-key
環境 PUT /repos/{owner}/{repo}/environments/{environment_name}/secrets/{secret_name} GET .../environments/{environment_name}/secrets/public-key

判斷練習

情境 A: 同名的 API_KEY 同時存在於組織、repository 與 production 環境,工作流程的 job 指定 environment: production。

解析: 環境 secret 優先於 repository 與組織 secret。若環境設了必要審核者,job 要等核准後才拿得到它。

情境 B: 你要在 if: 判斷某個 secret 是否存在,寫了 if: secrets.TOKEN != '',工作流程無效。

解析: jobs.<id>.if 與 steps.if 可用的 context 沒有 secrets。把它放進 job 層級的環境變數(env: HAS_TOKEN: ${{ secrets.TOKEN != '' }}),再用 env 判斷。

情境 C: 平台團隊要用腳本替一百個 repository 設定同一個 secret。

解析: 先取得各端點的公鑰與 key_id,用 LibSodium 加密後 PUT 到對應端點;若這個 secret 是共用的,更適合設成組織 secret 並用存取政策限定 repository,更新一次就套用到全部。

來源:Using secrets in GitHub Actions(GH200-DOC-39)、About secrets(GH200-DOC-37)、Use variables(GH200-DOC-38)、REST: secrets(GH200-DOC-40)、Reuse workflows(GH200-DOC-08);2026-11-03 以頁面原文比對本節的數字與條件。同名 secret 在三層級之間的優先順序,只有「環境優先於 repository 或組織」一句來自可重用工作流程頁面;secret 的命名規則、單一 secret 的大小上限與各層級的數量上限,我讀的頁面沒有寫,本節沒有補寫。