Repo 建置與設定 新 repo 一次性建置 SOP + 完整 branch protection 對照

shibamimi-tech 組織新 repo 從 GitHub App 設置、@shibamimi-tech/cli init-repo、手動 checklist、Branch Protection 細部設定到冷啟動 v0.1.0 的完整步驟。僅 owner(ShibaMiMi-Admin)執行。

最後更新
閱讀時間
約 14 分鐘
作者
柴米科技有限公司
版本
v1.1.0

本文件於 v1.0 由 工作流程規範 v2.6 抽出,獨立維護新 repo 建置 SOP;v1.1 起併入原 workflow 文章「Branch Protection 建議設定」段,集中所有 repo 建置與設定相關內容。

適用範圍

任何新建的完整 5-phase repo(無論 lib 或 app),Phase 1 啟動前必須完成本文件全部步驟。一次性動作。

簡化流程 repo(.github.claude)不適用 — 兩者由 admin 直推 main,無 preview 分支、無 caller workflow、無 changeset gate。

推薦流程:從 shibamimi-tech/app-template 的「Use this template」一鍵派生(template 已含 caller workflows + .changeset/ + package.json + CLAUDE.md),可直接跳過 Step 2 從 Step 3 @shibamimi-tech/cli init-repo 開始。詳見 app-template 的 TEMPLATE_USAGE.md

Step 1:GitHub App 設置(org 一次性,所有 repo 共用

只需在組織歷史上做一次。若已設好,新 repo bootstrap 跳過本步直接進 Step 2。

1. 建立 Apphttps://github.com/organizations/shibamimi-tech/settings/apps/new

欄位
GitHub App nameshibamimi-tech-workflow
Homepage URLhttps://github.com/shibamimi-tech
Webhook → Active取消勾選(reusable workflow 只用 installation token,不需要 webhook)
Repository permissionsContents: Read & writePull requests: Read & writeWorkflows: Read & writeMetadata: Read(必選)
Where can be installedOnly on this account

2. 記下憑證

  • App 建好後,settings 頁 About 區段顯示 Client ID(字串,例 Iv23li...,記下)
  • General → Private keys → Generate a private key → 下載 .pem 檔(只能下載一次,務必保管

3. Install App 到 org

左側 sidebar Install App → shibamimi-tech 旁點 Install → 選 All repositories(推薦:未來新 repo 自動涵蓋)→ Install

4. 設 org secretshttps://github.com/organizations/shibamimi-tech/settings/secrets/actions

Secret nameValueRepository access
SHIBAMIMI_WORKFLOW_CLIENT_IDClient ID 字串(例 Iv23li...All repositories
SHIBAMIMI_WORKFLOW_PRIVATE_KEY.pem 檔整份內容(含 BEGIN/END 兩行,保留換行)All repositories

為什麼非用 App 不可:

GitHub 對 GITHUB_TOKEN 設了硬規則:GITHUB_TOKEN 觸發的 push 不會觸發其他 workflow runs」(防 infinite loop)。若 reusable workflow 用 GITHUB_TOKEN 啟用 auto-merge,PR fire 後的 push 由 GITHUB_TOKEN 推出 → 下游 workflow(如 deploy-previewopen-preview-to-mainrelease)不會觸發,整條鏈死掉。

GitHub App installation token 不受此限:App 觸發的 push 是正常 push event,自然觸發下游 workflows。詳見 工作流程規範 — Actions / App 關係圖 段落。

Step 2:建立 repo + initial commit

推薦走 app-template 一鍵派生(跳過本步直接 Step 3)。

若不從 template 派生:

  1. GitHub UI 建 repo(private/public 依需求,shibamimi-tech 慣例為 private)
  2. local clone、加 README 與初始 commit,push 到 main
git clone git@github.com:shibamimi-tech/<repo>.git
cd <repo>
echo "# <repo>" > README.md
git add README.md && git commit -m "docs: initial README"
git push -u origin main

Step 3:跑 @shibamimi-tech/cli init-repo(腳本範圍內 — GitHub side)

cd shibamimi-tech/<new-repo>
pnpm dlx @shibamimi-tech/cli init-repo          # in-repo 模式:偵測 cwd repo → confirm 套用
# 或
pnpm dlx @shibamimi-tech/cli init-repo --all    # 互動多選 org 所有 repo(政策 fan-out)

腳本自動套用:

項目設定
Merge methodsallow_squash_merge=trueallow_merge_commit=trueallow_rebase_merge=false
Auto-mergeallow_auto_merge=true沒這項所有 PR 的 enablePullRequestAutoMerge 都會被拒絕
Branch lifecycledelete_branch_on_merge=true(讓 feature/* 與 changeset-release/main merge 後自動清掉)、allow_update_branch=true
Commit message defaultsSquash/Merge 都用 PR_TITLE;Squash body=PR_BODY、Merge body=BLANK
Workflow permissionsdefault_workflow_permissions=read + can_approve_pull_request_reviews=true底線權限;caller workflow 必須在 job 上完整明寫 reusable 宣告的所有 permissions: scope,否則 startup_failure;詳見下方「caller permissions 對齊」段落)
preview 分支main HEAD 建立(idempotent;已存在則跳過)

腳本結尾印 5 項手動 checklist(見 Step 4)。

⚠️ preview 分支誤刪陷阱delete_branch_on_merge=true 是針對 feature/* 自動清掉用的,main/preview 受 org-level ruleset 16747626/16747883 的 deletion rule 保護。但管理員身分手動跑 gh pr merge X --merge --auto 觸發 preview→main PR 會 bypass ruleset deletion 保護,連帶被 delete_branch_on_merge=true 殺掉 preview。preview→main merge 一律讓 App auto-merge 自然觸發(在 工作流程規範 Phase 3 App 啟用 auto-merge 後立即 fire),不要管理員手動跑 gh pr merge。實際案例:2026-05-24 將 animations / susumie / youyan / app-template 遷入 5-phase 時踩坑,preview 全部被刪,需從 main HEAD 重建。

Caller permissions 對齊(最常踩的坑,請務必細讀)

default_workflow_permissions=read 是組織安全底線,由 @shibamimi-tech/cli init-repo 強制套用,不會也不應該被翻成 write。但 caller workflow 一旦在 job 上宣告 permissions: block,未列入的 scope 即 NONE,不會 fallback 到 default——因此每個 caller 必須完整列出所對應 reusable 在 job 層宣告的所有 scope,否則 reusable 啟動時 GitHub validation 失敗 → startup_failure(無 jobs 出現)。

各 caller 對應 reusable 的完整宣告(一旦在 caller 上加 permissions: block,必須一字不漏列出):

Caller workflow對應 reusable job必填 permissions
feature-pipeline.yml::open-propen-feature-to-preview-pr.yml::open-prcontents: write, pull-requests: write
open-preview-to-main-pr.yml::open-propen-preview-to-main-pr.yml::open-prcontents: write, pull-requests: write
release.yml::releaserelease-app.yml::open-version-prcontents: write, pull-requests: write, packages: read(注意有第三項)
deploy-preview.yml::deploydeploy-staging-app.yml::deploycontents: read, packages: read
deploy-production.yml::deploydeploy-production-app.yml::deploycontents: read, packages: read
ci.yml::cici-node.yml::ci(可省略 block,token 取 default=read 全 scope 自然涵蓋)

特別注意 release.yml:reusable release-app.yml::open-version-pr 同時宣告三項 —— contents: write + pull-requests: write(開 Version PR)+ packages: read(reusable 內部跑 pnpm install@shibamimi-tech/* GitHub Packages)。caller 只給前兩項是常見踩坑案例。

反模式:翻 default_workflow_permissions=write 來「修」這個錯

歷史上 investor-relations 曾透過把 repo default_workflow_permissions 改成 write 來繞過缺漏的 caller permissions block(caller 無 block 時 token 取 default 全 scope,自然涵蓋 reusable 要求)——這是個反模式,不要重蹈:

  1. @shibamimi-tech/cli init-repo 每次都會把 default 設回 read,這個「修」會被打回原形 → 又壞 → 又翻成 write → 反覆。
  2. 設定層級錯了。reusable 對 permissions 的要求是 workflow 檔本身的契約,應該在 workflow 檔內表達;用 repo setting 去 mask 等同把 contract 散落在 repo settings、永遠看不到全貌。
  3. 新派生 repo 一樣會踩。從 app-template 派生的新 repo default 一律 read,每個都得手動翻 write,這條 workaround 不可擴展。

根因修法:在 caller workflow 的對應 job 上明寫完整 permissions: block。app-template / corp-site / investor-relations / docsrelease.yml 都已對齊三項,未來新派生即帶這個對齊。

實際案例:2026-05-28 docs / app-template 第一次跑 release.ymlstartup_failure;查明後(一)改 app-template 根因,(二)IR release.yml 補齊三項並把 default 翻回 read 移除歷史特例,(三)docs 補齊三項走完整 pipeline → v0.1.0 順利 ship。

Step 4:腳本範圍外(必須手動完成)

⚠️ 下列項目目前無 GitHub / Cloudflare API 可自動化,或範圍超出 init-repo 設計(不碰 CF)。漏做任一項都會在後續流程踩坑

1. Branch protection(main + preview)

組織內所有完整 5-phase repo 的 branch protection 由 org-level ruleset 自動套用

  • ruleset 16747626(main):approvals=0, allowed_merge_methods=[merge, squash], deletion/creation/non_fast_forward 保護(不設 required_status_checks — v2.6 起改為 preview 端把關)
  • ruleset 16747883(preview):approvals=0, allowed_merge_methods=[squash], required_status_checks=[ci / ci, check-changeset / gate], required_linear_history, deletion 保護

實際展開後,等同於以下兩組 GitHub UI 設定(可進 repo Settings → Branches 對照):

preview 分支:

  • ☑ Require a pull request before merging
  • Require approvals = 0(不需人工 approve;改靠 status check)
  • ☑ Require status checks to pass before merging
    • 必選 required status checks(注意:required check 的名字格式是 <workflow-job-id> / <reusable-job-id>):
      • ci / ci(caller ci.ymljobs.ci → reusable ci-node.ymljobs.ci
      • check-changeset / gate(caller feature-pipeline.ymljobs.check-changeset → reusable check-changeset.ymljobs.gate,驗證「本次 push 動到 .changeset/*.md」+「HEAD 仍存在便利貼」)
  • ☑ Require branches to be up to date before merging
  • 不需要勾「Dismiss stale pull request approvals when new commits are pushed」

status check 是 per-commit 的,新 commit 沒有兩個 required check 都通過時,auto-merge 會自動停下來等。無需依賴 GitHub 的 stale review dismissal 機制。

另需 repo Settings → General 勾選 「Allow auto-merge」,否則 open-feature-to-preview-pr 啟用 auto-merge 會失敗(不影響 PR 建立,但要手動 merge)。

main 分支:

  • ☑ Require a pull request before merging
  • Require approvals = 0(無人工簽核點 — v2.7 起 main 全自動)
    • Phase 3:preview→main PR 由 App 啟用 auto-merge 後立即 fire(merge commit)— 無需人工 approve
    • Phase 4:Version PR 由 App 啟用 auto-merge 後立即 fire(squash)— 無需人工 approve
    • Phase 5:人工 gate 只在 production deploy(workflow_dispatch 觸發 deploy-production-app.yml / publish-lib.yml
  • 不設 required status checks
    • v2.3 曾把 ci / ci + check-changeset / gate 設為 main 的 required check,但這兩個 caller workflow 的 trigger 是 branches-ignore: [main, preview] → 永遠不會 fire 在 preview HEAD 上 → preview→main PR 永遠 BLOCKED
    • 改為「preview 端把關(preview ruleset 16747883 require 這兩個 check)+ main 端不設 gate」
    • 註:gh pr merge --auto 在無任何 required condition 時仍可正常啟用,會在 PR 開啟瞬間就 fire
  • ☑ Require branches to be up to date before merging
  • 不要勾「Require linear history」(preview→main 用 merge commit,會被擋)
  • Allowed merge methods:勾 Merge(preview→main 用)+ Squash(Version PR 用)

⚠️ 品質把關責任前移:main 無人工 approve gate,因此每筆 push 進 feature/* 都要當作「ready-to-ship」對待 — 本地測試完成、changeset 描述正確才推。Phase 3 Cloudflare preview deploy 仍會跑,但通常 preview→main merge 比 staging deploy 更快完成,staging URL 主要供「上線後 sanity check + rollback」用。

驗證 ruleset 已套用到新 repo:

gh api repos/shibamimi-tech/<repo>/rules/branches/main
gh api repos/shibamimi-tech/<repo>/rules/branches/preview

若 ruleset 沒涵蓋新 repo → 到 Organization Settings → Repository → Rulesets → 各 ruleset → Target → Include repository names 加入。

2. Repo secrets(app repo only)

repo → Settings → Secrets and variables → Actions

  • CLOUDFLARE_API_TOKEN(Pages:Edit + Zone:Edit)
  • CLOUDFLARE_ACCOUNT_ID

NODE_AUTH_TOKEN 在 reusable workflow 內部由 ${{ secrets.GITHUB_TOKEN }} 繼承,不需手動設

3. Cross-repo @shibamimi-tech/* packages 讀取權限

若新 repo import 自任一 published package(@shibamimi-tech/ui@shibamimi-tech/content…),GITHUB_TOKEN 預設無 cross-repo packages 讀權限,CI 會 ERR_PNPM_FETCH_403

https://github.com/orgs/shibamimi-tech/packages → 每個用到的 package → Package settings → Manage Actions access → Add Repository → 選新 repo,Role: Read。

⚠️ 此設定無 REST/GraphQL API 可用,只能 UI 操作。腳本只能列出需檢查的 packages 清單。

4. Actions 啟用

repo → Settings → Actions → General → Allow all actions and reusable workflows。新 repo 預設可能 disable。

5. Cloudflare 設定(app repo only)

  • Pages project:首次 deploy 時 scripts/deploy.sh::ensure_pages_project 自動建立(idempotent)。
  • DNSdeploy.sh::ensure_dns_records 自動 upsert CNAME(apex zone 須已在 CF 帳號)。
  • Zero Trust Access(如需限制存取):
    1. https://one.dash.cloudflare.com → Zero Trust → Settings → Authentication → 設 IdP(最簡:One-time PIN)
    2. Zero Trust → Access → Applications → Add an application → Self-hosted → 填 <subdomain>.<domain>
    3. Add Policy → Action=Allow → Selector=Emails → 填授權 email
    4. 上線前先設好,避免空窗期

Step 5:冷啟動 v0.1.0

冷啟動同樣走 工作流程規範 — 鐵則:分支線性不變式不繞 preview

前提:

  • 已完成 Step 1 ~ 4(含 GitHub App 設置 + @shibamimi-tech/cli init-repo 跑過建立 preview 分支)
  • repo 已有 main + preview 分支
  • package.json#version"0.0.0""0.1.0"

流程:

  1. main 切出 release/v0.1.0 分支
  2. 加入初始 changeset:pnpm changeset,選 minor,描述「初始發佈」
  3. Push 分支 → feature-pipeline gate 過 → App auto-merge 進 preview
  4. preview 收到 push → deploy-preview + open-preview-to-main-pr 自動跑 → 你在 preview URL 確認 + approve PR → App merge 到 main
  5. main 收到 push → release.yml 開 Version PR + App auto-merge → main 取得 v0.1.0 + CHANGELOG
  6. 你到 Actions 點 Deploy Production workflow_dispatch → wrangler deploy production
  7. production live 🎉

冷啟動完成後,repo 即可開放給開發人員依 工作流程規範 — Phase 1 正常開發。

已知限制(未來改進方向)

  1. Packages access 無 API:見 Step 4 第 3 項,目前只能 UI 操作授權其他 repo 讀取 packages
  2. Zero Trust 無自動化:見 Step 4 第 5 項,需 dashboard 設定 Access Application

過去 v2.4 列出的「GITHUB_TOKEN 不觸發下游 workflows」問題已在 v2.5 透過 GitHub App shibamimi-tech-workflow 解決,不再列為限制。

相關文件