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. 建立 App 到 https://github.com/organizations/shibamimi-tech/settings/apps/new:
| 欄位 | 值 |
|---|---|
| GitHub App name | shibamimi-tech-workflow |
| Homepage URL | https://github.com/shibamimi-tech |
| Webhook → Active | ☐ 取消勾選(reusable workflow 只用 installation token,不需要 webhook) |
| Repository permissions | Contents: Read & write、Pull requests: Read & write、Workflows: Read & write、Metadata: Read(必選) |
| Where can be installed | Only 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 secrets 到 https://github.com/organizations/shibamimi-tech/settings/secrets/actions:
| Secret name | Value | Repository access |
|---|---|---|
SHIBAMIMI_WORKFLOW_CLIENT_ID | Client 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-preview、open-preview-to-main、release)不會觸發,整條鏈死掉。
GitHub App installation token 不受此限:App 觸發的 push 是正常 push event,自然觸發下游 workflows。詳見 工作流程規範 — Actions / App 關係圖 段落。
Step 2:建立 repo + initial commit
推薦走 app-template 一鍵派生(跳過本步直接 Step 3)。
若不從 template 派生:
- GitHub UI 建 repo(private/public 依需求,shibamimi-tech 慣例為 private)
- 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 methods | allow_squash_merge=true、allow_merge_commit=true、allow_rebase_merge=false |
| Auto-merge | allow_auto_merge=true(沒這項所有 PR 的 enablePullRequestAutoMerge 都會被拒絕) |
| Branch lifecycle | delete_branch_on_merge=true(讓 feature/* 與 changeset-release/main merge 後自動清掉)、allow_update_branch=true |
| Commit message defaults | Squash/Merge 都用 PR_TITLE;Squash body=PR_BODY、Merge body=BLANK |
| Workflow permissions | default_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-pr | open-feature-to-preview-pr.yml::open-pr | contents: write, pull-requests: write |
open-preview-to-main-pr.yml::open-pr | open-preview-to-main-pr.yml::open-pr | contents: write, pull-requests: write |
release.yml::release | release-app.yml::open-version-pr | contents: write, pull-requests: write, packages: read(注意有第三項) |
deploy-preview.yml::deploy | deploy-staging-app.yml::deploy | contents: read, packages: read |
deploy-production.yml::deploy | deploy-production-app.yml::deploy | contents: read, packages: read |
ci.yml::ci | ci-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 要求)——這是個反模式,不要重蹈:
@shibamimi-tech/cli init-repo每次都會把 default 設回read,這個「修」會被打回原形 → 又壞 → 又翻成 write → 反覆。- 設定層級錯了。reusable 對 permissions 的要求是 workflow 檔本身的契約,應該在 workflow 檔內表達;用 repo setting 去 mask 等同把 contract 散落在 repo settings、永遠看不到全貌。
- 新派生 repo 一樣會踩。從
app-template派生的新 repo default 一律 read,每個都得手動翻 write,這條 workaround 不可擴展。
根因修法:在 caller workflow 的對應 job 上明寫完整 permissions: block。app-template / corp-site / investor-relations / docs 的 release.yml 都已對齊三項,未來新派生即帶這個對齊。
實際案例:2026-05-28 docs / app-template 第一次跑 release.yml 即 startup_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(callerci.yml的jobs.ci→ reusableci-node.yml的jobs.ci)check-changeset / gate(callerfeature-pipeline.yml的jobs.check-changeset→ reusablecheck-changeset.yml的jobs.gate,驗證「本次 push 動到.changeset/*.md」+「HEAD 仍存在便利貼」)
- 必選 required status checks(注意:required check 的名字格式是
- ☑ 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
- v2.3 曾把
- ☑ 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)。 - DNS:
deploy.sh::ensure_dns_records自動 upsert CNAME(apex zone 須已在 CF 帳號)。 - Zero Trust Access(如需限制存取):
https://one.dash.cloudflare.com→ Zero Trust → Settings → Authentication → 設 IdP(最簡:One-time PIN)- Zero Trust → Access → Applications → Add an application → Self-hosted → 填
<subdomain>.<domain> - Add Policy → Action=Allow → Selector=Emails → 填授權 email
- 上線前先設好,避免空窗期
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"
流程:
- 從
main切出release/v0.1.0分支 - 加入初始 changeset:
pnpm changeset,選 minor,描述「初始發佈」 - Push 分支 →
feature-pipelinegate 過 → App auto-merge 進preview preview收到 push →deploy-preview+open-preview-to-main-pr自動跑 → 你在 preview URL 確認 + approve PR → App merge 到 mainmain收到 push →release.yml開 Version PR + App auto-merge → main 取得 v0.1.0 + CHANGELOG- 你到 Actions 點 Deploy Production workflow_dispatch → wrangler deploy production
- production live 🎉
冷啟動完成後,repo 即可開放給開發人員依 工作流程規範 — Phase 1 正常開發。
已知限制(未來改進方向)
- Packages access 無 API:見 Step 4 第 3 項,目前只能 UI 操作授權其他 repo 讀取 packages
- Zero Trust 無自動化:見 Step 4 第 5 項,需 dashboard 設定 Access Application
過去 v2.4 列出的「GITHUB_TOKEN 不觸發下游 workflows」問題已在 v2.5 透過 GitHub App
shibamimi-tech-workflow解決,不再列為限制。
相關文件
- 工作流程規範 — 主工作流規範(Phase 1 開發階段起,所有開發人員必讀)
shibamimi-tech/app-template— 新 repo template repo@shibamimi-tech/cli— 提供init-repo等維運子命令