setup-repo-guards
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
Chinesesetup-repo-guards
setup-repo-guards
対象リポジトリへ組織標準の CI ガード一式を導入する。導入するのは次の 4 点で、
Step 1 → 4 の順に、各 Step を PR → CI 全 pass → レビュースレッド resolve → squash merge で確定させてから次へ進む。
- codex-review(PR 自動レビュー workflow の wrapper)
- AGENTS.md(codex が読むレビュー観点集)
- CI 必須チェックの集約ジョブ(等)
ci-complete - branch protection ruleset・リポジトリ追加ガード(GitHub API のみ、コミット不要)
この順序を守る理由: 「必須チェックに入れる集約ジョブが先に存在する」「AGENTS.md は PR の base コミット参照のため
マージ後の次の PR から実効」という依存関係が、この順で自然に満たされる。
为目标仓库导入组织标准的全套CI防护机制。需导入以下4项内容,请按照Step 1→4的顺序,在每个步骤完成PR提交→CI全部通过→评审线程处理完毕→squash合并后,再进入下一步。
- codex-review(PR自动评审工作流的包装器)
- AGENTS.md(供codex读取的评审要点集)
- CI必填检查的汇总任务(如等)
ci-complete - branch protection规则集及仓库附加防护(仅通过GitHub API操作,无需提交代码)
遵循此顺序的原因:该顺序可自然满足「必填检查需先存在汇总任务」「AGENTS.md需参考PR的base提交,合并后从下一个PR开始生效」的依赖关系。
使い方
使用方法
setup-repo-guards Fandhe-AI/my-repo public
setup-repo-guards Fandhe-AI/repo-a public Fandhe-AI/repo-b private- 第 1 引数: 対象リポジトリ名()
owner/repo - 第 2 引数: visibility(/
public)。runner 方針の分岐に使う(public は ubuntu ホステッド、private は self-hosted。codex 実行ジョブのみ self-hosted codex runner の例外)private - 複数リポジトリへ一括適用する場合はリポジトリと visibility の組を列挙する。各リポジトリのセッション(または並列 agent)で順次消化する
setup-repo-guards Fandhe-AI/my-repo public
setup-repo-guards Fandhe-AI/repo-a public Fandhe-AI/repo-b private- 第1参数:目标仓库名称(格式)
owner/repo - 第2参数:可见性(/
public)。用于区分runner策略(public仓库使用ubuntu托管runner,private仓库使用自托管runner。仅codex执行任务例外,使用自托管codex runner)private - 如需批量应用到多个仓库,可依次列出仓库与可见性的组合。系统会在每个仓库的会话(或并行agent)中依次处理
前提条件
前提条件
- CLI がインストールされ、対象リポジトリの admin 権限で認証済みであること(
ghで確認)command -v gh && gh auth status - がインストールされていること(
jqで確認)command -v jq - Fandhe-AI/actions(reusable workflow の提供元)への参照権限があること
- 対象リポジトリを clone 済みで、CLAUDE.md・既存 workflow を読める状態であること
- 已安装CLI,并以目标仓库的管理员权限完成认证(可通过
gh确认)command -v gh && gh auth status - 已安装(可通过
jq确认)command -v jq - 拥有访问Fandhe-AI/actions(可复用工作流提供方)的权限
- 已克隆目标仓库,且能读取CLAUDE.md及现有工作流
フロー
流程
Step 1: codex-review の導入(未導入の場合のみ)
Step 1:集成codex-review(仅未集成时执行)
.github/workflows/codex-review.ymlcodex-review.yml@main参照する SHA は下記のレビュー済み SHA 定数を使う。最新 main からの動的取得
()は禁止する — 文字列上は commit SHA 固定でも、
導入のたびに未レビューの最新コードを取り込む「可動 ref の自動追従」と同じであり、
サプライチェーン対策(レビュー済み SHA 固定)を弱体化する(fandhe-frontend PR #1311 codex P1)。
gh api repos/Fandhe-AI/actions/commits/mainbash
undefined添加作为包装器,以固定commit SHA(禁止使用)引用Fandhe-AI/actions中的可复用工作流。
.github/workflows/codex-review.yml@maincodex-review.yml引用的SHA必须使用以下已评审的SHA常量。禁止从最新main分支动态获取(如)——即使表面上是固定commit SHA,但若每次导入都获取未评审的最新代码,本质与「自动跟踪可变引用」无异,会削弱供应链防护(固定已评审SHA)的效果(参考fandhe-frontend PR #1311 codex P1)。
gh api repos/Fandhe-AI/actions/commits/mainbash
undefinedレビュー済み SHA 定数(内容精査済み。既存導入リポジトリ fandhe-frontend の
已评审SHA常量(内容已核查。与已集成仓库fandhe-frontend的
.github/workflows/codex-review.yml が参照している SHA と同一)
.github/workflows/codex-review.yml中引用的SHA一致)
sha="fed9c07d98367f77e5e2b63bca38843f46feee96"
定数の更新手順(新しい SHA を採用したくなった場合):
1. 旧 SHA → 新 SHA の差分を精査する:
`gh api "repos/Fandhe-AI/actions/compare/<旧SHA>...<新SHA>"` または Web UI の compare で、
reusable workflow 本体(fork PR 拒否・fail-closed 検証・資格情報スキャン等)の変更内容を確認する
2. 問題がないと判断してから、本 SKILL.md のこの定数(full SHA)を書き換えるコミットを作成する
3. 以後の導入は更新後の定数を使う(導入時に動的取得へ戻さない)
- 書き方・fork PR 拒否等の適用条件は Fandhe-AI/actions の `docs/codex-review-runner-exception.md` と、
既存導入リポジトリ(fandhe-frontend 等)の wrapper を参照して揃える
- runner 方針: CI ジョブは public なら ubuntu ホステッド、private なら self-hosted。
codex 実行ジョブのみ self-hosted codex runner の例外。`post_feedback` ジョブは資格情報に触れないため
`ubuntu-latest` を明示する
- `CODEX_HOME_DIR` variable は設定しないsha="fed9c07d98367f77e5e2b63bca38843f46feee96"
常量更新步骤(如需采用新SHA时):
1. 核查旧SHA到新SHA的差异:
使用`gh api "repos/Fandhe-AI/actions/compare/<旧SHA>...<新SHA>"`或Web UI的compare功能,确认可复用工作流本体(如拒绝fork PR、fail-closed验证、凭证扫描等)的变更内容
2. 确认无问题后,提交修改本SKILL.md中该常量(完整SHA)的代码
3. 后续导入操作将使用更新后的常量(导入时不得恢复为动态获取)
- 编写方式、fork PR拒绝等适用条件,请参考Fandhe-AI/actions的`docs/codex-review-runner-exception.md`及已集成仓库(如fandhe-frontend)的包装器,保持一致
- Runner策略:CI任务若为public仓库则使用ubuntu托管runner,private仓库则使用自托管runner。仅codex执行任务例外,使用自托管codex runner。`post_feedback`任务因不涉及凭证,需明确指定`ubuntu-latest`
- 无需设置`CODEX_HOME_DIR`变量Step 2: AGENTS.md(codex のレビュー観点集)の追加
Step 2:添加AGENTS.md(codex的评审要点集)
codex の既定 prompt は PR の base コミットの AGENTS.md をレビュー基準として読む。
リポジトリルートに日本語で新規作成する(既存があれば基準を弱めず不足観点を追記する)。
必須 3 観点を、必ず対象リポジトリ固有の具体項目に落とし込んで書く(別リポジトリ用の記述を流用しない):
- セキュリティ観点: 秘密情報混入・インジェクション・依存監査・権限最小化など、リポジトリの実態に即して
- アーキテクチャ・設計整合の観点: CLAUDE.md・設計文書の責務境界・規約整合
- 再利用・アセット化の観点: 汎用実装の分離・ハードコード回避・転用容易性・ドキュメント整備
加えて:
- CLAUDE.md / / 設計文書から抽出したリポジトリ固有観点を整理する
.claude/rules/ - 重大度区分 P0(マージブロック)/ P1(強く推奨)/ P2(提案)を付け、P1 の定義は CI ゲートの実挙動 (codex ジョブは P1 でも fail する)と矛盾させない
- カスタム prompt()が既にある場合は二重管理を避ける: 観点の正は AGENTS.md、enforcement(完了判定・機械格上げ)の正は review.md という役割分担にし、 review.md へは AGENTS.md 読み取りの最小追記のみ行う
.github/codex/prompts/review.md - 参考実例: fandhe-backend / fandhe-frontend / Fandhe-AI/actions / agent-cli-skills の AGENTS.md
- 注意: 新基準はマージ後の次の PR から実効(base 参照仕様)
codex的默认prompt会将PR的base提交中的AGENTS.md作为评审基准读取。需在仓库根目录用日语新建该文件(若已存在,则在不降低基准的前提下补充缺失要点)。
必须将以下3个要点转化为目标仓库特有的具体内容编写(不得直接复用其他仓库的描述):
- 安全要点:结合仓库实际情况,涵盖敏感信息混入、注入攻击、依赖审计、权限最小化等内容
- 架构与设计一致性要点:符合CLAUDE.md、设计文档的职责边界与规范
- 复用与资产化要点:分离通用实现、避免硬编码、提升可移植性、完善文档
此外:
- 整理从CLAUDE.md / / 设计文档中提取的仓库特有要点
.claude/rules/ - 标注严重等级P0(阻止合并)/ P1(强烈推荐)/ P2(建议),且P1的定义需与CI防护的实际行为(codex任务在P1等级也会失败)保持一致
- 若已存在自定义prompt(),需避免重复管理:将要点定义统一到AGENTS.md,将执行逻辑(完成判定、自动升级)统一到review.md,仅在review.md中添加读取AGENTS.md的必要内容
.github/codex/prompts/review.md - 参考实例:fandhe-backend / fandhe-frontend / Fandhe-AI/actions / agent-cli-skills的AGENTS.md
- 注意:新基准将在合并后的下一个PR开始生效(基于base提交的读取规则)
Step 3: CI 必須チェックの集約ジョブ整備
Step 3:完善CI必填检查的汇总任务
複数ジョブを持つ workflow には集約ジョブ( 等)を追加する:
全ジョブを に列挙し、 を付け、 を jq で判定する。
ci-completeneeds:if: always()toJSON(needs)- fail-closed を厳守: の許容は「条件付きジョブ(
skippedを持つジョブ)」の明示リストに限定し、 他ジョブは success のみ受理する(skipped 全許容は fail-open として codex に P1 指摘される)。 change detection ゲートがある場合はゲート出力に基づき「skip が正しい状況」でのみ skipped を受理するif: - 集約ジョブには を付け、「ジョブ追加時は needs への追加が必要」のコメントを書く
permissions: {} - Fandhe-AI/actions の reusable workflow(lint-docs 等)を使っている場合、集約ジョブ
(等)が入った SHA まで参照をバンプすればチェック 1 件に集約できる
lint-docs / lint-docs-complete - YAML の に
name:や「: 」を含む場合は必ずクォートする(未クォートだと API 報告名が途中で切れ、 必須チェック名として不安定になる)#
对于包含多个任务的工作流,需添加汇总任务(如):在中列出所有任务,添加,并通过jq判定的结果。
ci-completeneeds:if: always()toJSON(needs)- 严格遵守fail-closed原则:仅允许「带条件的任务」的明确列表跳过(skipped),其他任务仅接受成功状态(允许所有任务跳过属于fail-open,会被codex标记为P1问题)。若存在变更检测防护,则仅在「跳过符合预期」的情况下接受skipped状态
if: - 汇总任务需添加,并添加注释说明「新增任务时需同步到needs中」
permissions: {} - 若使用Fandhe-AI/actions的可复用工作流(如lint-docs),只需将引用版本升级到包含汇总任务(如)的SHA,即可将多个检查合并为1项
lint-docs / lint-docs-complete - 若YAML的中包含
name:或「: 」,必须添加引号(未添加引号会导致API报告名称被截断,作为必填检查名称时会不稳定)#
Step 4: branch protection / リポジトリ設定(GitHub API のみ、コミット不要)
Step 4:分支保护/仓库配置(仅通过GitHub API操作,无需提交代码)
- マージ設定(): squash のみ(merge commit / rebase 禁止)、 マージ後ブランチ自動削除、auto-merge 許可、squash タイトル = PR_TITLE / 本文 = PR_BODY
gh api -X PATCH repos/... - ruleset (target: branch、
main-protection、enforcement: active、bypass_actors 空):~DEFAULT_BRANCH- deletion 禁止 / non_fast_forward(force push 禁止)
- pull_request: required_approving_review_count 0(人間 approver 不在の AI 運用。レビューゲートは codex の必須チェックで担保)・required_review_thread_resolution true・allowed_merge_methods ["squash"]
- required_status_checks(strict false は必須。true にすると 1 件マージするたびに他の open PR の
base が陳腐化し、implement-issue-tree の並列ランが収束しなくなる。strict は鮮度制御であって
bypass 不能性の制御ではないため、false でもクライアント側自動マージの G0 は通過する。
詳細は ): [<集約ジョブ>, (集約できない別 workflow の常時チェック), codex-review / codex] の最小集合
.claude/rules/ruleset-policy.md - 自動マージ(implement-issue-tree の )を使う場合、required_status_checks の 各エントリに発行元 App の
autoMerge: trueを束縛する(未束縛だと G0 がintegration_idで辞退する)。 ruleset を PUT で更新した後は必ず下記「検証」の 3 軸スイープを実行する(issuer-unboundはPUTを丸ごと置換するため束縛が落ち得る。複数リポへ一括適用する 場合は全リポで実行する)required_status_checks.parameters
- 必須チェック選定の注意(重要な落とし穴):
- 直近 PR の check runs で「常に報告される」チェックのみ選ぶ。workflow レベル paths フィルタで 実行されないことがあるチェックは入れない(マージが永久ブロックされる)。ジョブレベル条件の skipped は可
- Cursor Bugbot 等の外部アプリ、codex-review / post_feedback は必須にしない
- チェック名が変わる PR をマージするときは、マージ前に ruleset を新チェック名へ PUT で置換する (旧名のままだと CI 全 pass でも「Expected」のまま BLOCKED になる)。PUT は GET した JSON の required_status_checks のみ差し替えて送る
- 追加ガード: secret scanning + push protection / Dependabot alerts + automated security fixes / (public なら)private vulnerability reporting / タグ運用があれば tag ruleset(deletion・non_fast_forward)/ GITHUB_TOKEN 既定権限 read 化(全 workflow の permissions: 明示を確認してから)/ Actions の PR 作成・承認許可は自動 PR 運用(update-external 等)が無ければ false / (private なら)forking 禁止 / 未使用の wiki・projects 無効化
- プラン制限(403/422)に当たった項目は「ユーザー操作が必要」として記録し、他を続行する
- 合并配置():仅允许squash合并(禁止merge commit / rebase合并)、合并后自动删除分支、允许自动合并、squash标题=PR_TITLE / 正文=PR_BODY
gh api -X PATCH repos/... - ruleset (目标:分支,
main-protection,执行状态:active,绕过角色为空):~DEFAULT_BRANCH- 禁止删除/禁止非快进推送(force push)
- pull_request:必填批准审核数0(无人审核的AI运营模式,审核防护由codex的必填检查保障)、必填评审线程处理完成、允许的合并方式仅["squash"]
- 必填状态检查(必须设置strict false。若设置为true,每次合并都会导致其他开放PR的base提交过期,无法完成implement-issue-tree的并行任务收敛。strict用于控制提交新鲜度,而非不可绕过性,因此设置为false也可通过客户端自动合并的G0要求。详情请参考):**[<汇总任务>, (无法合并的其他工作流的常规检查), codex-review / codex]**的最小集合
.claude/rules/ruleset-policy.md - 若使用自动合并(implement-issue-tree的),需为必填状态检查的每个条目绑定发行方App的
autoMerge: true(未绑定会导致G0因integration_id拒绝执行)。使用PUT更新ruleset后,必须执行以下「验证」环节的3轴扫描(PUT会完全替换issuer-unbound,可能导致绑定丢失。批量应用到多个仓库时,需在所有仓库执行)required_status_checks.parameters
- 必填检查选择注意事项(重要陷阱):
- 仅选择「在最近PR的check runs中始终报告」的检查。若工作流通过paths过滤器存在不执行的情况,不得设置为必填(会导致合并被永久阻塞)。任务级条件导致的skipped是允许的
- 不得将Cursor Bugbot等外部应用、codex-review / post_feedback设置为必填
- 当合并修改检查名称的PR时,需在合并前使用PUT将ruleset更新为新的检查名称(若保留旧名称,即使CI全部通过,也会一直处于「Expected」阻塞状态)。PUT时只需替换GET到的JSON中的required_status_checks部分后发送
- 附加防护:启用secret scanning + push protection / Dependabot alerts + 自动安全修复 / (public仓库)启用私有漏洞报告 / 若使用标签则配置tag ruleset(禁止删除/禁止非快进推送)/ 将GITHUB_TOKEN默认权限设置为read(需先确认所有工作流已明确设置permissions)/ 若无自动PR运营(如update-external),则禁止Actions创建PR及批准 / (private仓库)禁止fork / 禁用未使用的wiki・projects
- 若遇到计划限制(403/422)的项目,需记录为「需用户手动操作」,继续执行其他项目
検証
验证
各 Step の完了は以下で確認する:
bash
repo="Fandhe-AI/<REPO>"各步骤的完成情况可通过以下方式确认:
bash
repo="Fandhe-AI/<REPO>"Step 1: wrapper の存在と SHA 固定(@main が残っていないこと)
Step 1:确认包装器存在且SHA固定(无@main)
grep -n "uses: Fandhe-AI/actions" .github/workflows/codex-review.yml
grep -n "uses: Fandhe-AI/actions" .github/workflows/codex-review.yml
Step 2: AGENTS.md の存在と P0/P1/P2 定義
Step 2:确认AGENTS.md存在且包含P0/P1/P2定义
grep -n "P0|P1|P2" AGENTS.md | head
grep -n "P0|P1|P2" AGENTS.md | head
Step 3: 直近 PR の check runs で集約ジョブが報告されること
Step 3:确认最近PR的check runs中报告了汇总任务
gh pr checks "$(gh pr list --repo "${repo}" --state merged --limit 1 --json number --jq '.[0].number')" --repo "${repo}"
gh pr checks "$(gh pr list --repo "${repo}" --state merged --limit 1 --json number --jq '.[0].number')" --repo "${repo}"
Step 4: ruleset とマージ設定
Step 4:确认ruleset与合并配置
gh api "repos/${repo}/rulesets" --jq '.[] | {id, name, enforcement}'
gh api "repos/${repo}" --jq '{allow_squash_merge, allow_merge_commit, allow_rebase_merge, delete_branch_on_merge, allow_auto_merge}'
gh api "repos/${repo}/rulesets" --jq '.[] | {id, name, enforcement}'
gh api "repos/${repo}" --jq '{allow_squash_merge, allow_merge_commit, allow_rebase_merge, delete_branch_on_merge, allow_auto_merge}'
Step 4-a: 一括更新後の 3 軸スイープ(strict / bypass_actors / integration_id 残存)
Step 4-a:批量更新后的3轴扫描(检查strict / bypass_actors / integration_id是否保留)
PUT した ruleset 単体ではなく branch target の全 ruleset を掃く(org 継承は source_type でルーティング)。
需扫描分支目标的所有ruleset(而非仅PUT更新的ruleset,组织继承规则需通过source_type区分)。
コマンド全文・判定表は .claude/rules/ruleset-policy.md の「一括更新後の検証」節を参照
完整命令及判定表请参考.claude/rules/ruleset-policy.md的「批量更新后的验证」章节
org="${repo%%/*}"
gh api "repos/${repo}/rulesets"
--jq '.[] | select(.target == "branch") | [(.id|tostring), .name, (.source_type // "unknown")] | @tsv' | while IFS=$'\t' read -r id name src; do case "${src}" in Repository) path="repos/${repo}/rulesets/${id}" ;; Organization) path="orgs/${org}/rulesets/${id}" ;; *) echo "UNKNOWN source_type: ${name} (${src}) — 手動確認"; continue ;; esac gh api "${path}" --jq '{ name: .name, enforcement: .enforcement, bypass: (.bypass_actors | length), strict: ([.rules[]? | select(.type=="required_status_checks") | .parameters.strict_required_status_checks_policy] | first), total: ([.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]?] | length), unbound: [.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]? | select(.integration_id == null) | .context] }' done
--jq '.[] | select(.target == "branch") | [(.id|tostring), .name, (.source_type // "unknown")] | @tsv' | while IFS=$'\t' read -r id name src; do case "${src}" in Repository) path="repos/${repo}/rulesets/${id}" ;; Organization) path="orgs/${org}/rulesets/${id}" ;; *) echo "UNKNOWN source_type: ${name} (${src}) — 手動確認"; continue ;; esac gh api "${path}" --jq '{ name: .name, enforcement: .enforcement, bypass: (.bypass_actors | length), strict: ([.rules[]? | select(.type=="required_status_checks") | .parameters.strict_required_status_checks_policy] | first), total: ([.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]?] | length), unbound: [.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]? | select(.integration_id == null) | .context] }' done
org="${repo%%/*}"
gh api "repos/${repo}/rulesets"
--jq '.[] | select(.target == "branch") | [(.id|tostring), .name, (.source_type // "unknown")] | @tsv' | while IFS=$'\t' read -r id name src; do case "${src}" in Repository) path="repos/${repo}/rulesets/${id}" ;; Organization) path="orgs/${org}/rulesets/${id}" ;; *) echo "UNKNOWN source_type: ${name} (${src}) — 需手动确认"; continue ;; esac gh api "${path}" --jq '{ name: .name, enforcement: .enforcement, bypass: (.bypass_actors | length), strict: ([.rules[]? | select(.type=="required_status_checks") | .parameters.strict_required_status_checks_policy] | first), total: ([.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]?] | length), unbound: [.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]? | select(.integration_id == null) | .context] }' done
--jq '.[] | select(.target == "branch") | [(.id|tostring), .name, (.source_type // "unknown")] | @tsv' | while IFS=$'\t' read -r id name src; do case "${src}" in Repository) path="repos/${repo}/rulesets/${id}" ;; Organization) path="orgs/${org}/rulesets/${id}" ;; *) echo "UNKNOWN source_type: ${name} (${src}) — 需手动确认"; continue ;; esac gh api "${path}" --jq '{ name: .name, enforcement: .enforcement, bypass: (.bypass_actors | length), strict: ([.rules[]? | select(.type=="required_status_checks") | .parameters.strict_required_status_checks_policy] | first), total: ([.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]?] | length), unbound: [.rules[]? | select(.type=="required_status_checks") | .parameters.required_status_checks[]? | select(.integration_id == null) | .context] }' done
Step 4-b: classic branch protection を別枠で掃く(defaultBranchRef 解決・@uri エンコード・HTTP status 分岐)
Step 4-b:单独扫描传统分支保护(解析defaultBranchRef / @uri编码 / HTTP状态分支处理)
db=$(gh repo view "${repo}" --json defaultBranchRef --jq '.defaultBranchRef.name')
db_enc=$(printf '%s' "${db}" | jq -sRr '@uri')
code=$(gh api -i "repos/${repo}/branches/${db_enc}/protection" 2>/dev/null | awk 'NR==1{print $2}')
case "${code}" in
200) gh api "repos/${repo}/branches/${db_enc}/protection" --jq
'{strict: (.required_status_checks.strict // "none"), unbound: [.required_status_checks.checks[]? | select(.app_id == null) | .context]}' ;; 404) echo "classic BP なし(${db})" ;; *) echo "判定不能 (HTTP ${code:-?}) — Administration: read 権限を確認。green と扱わない" ;; esac
'{strict: (.required_status_checks.strict // "none"), unbound: [.required_status_checks.checks[]? | select(.app_id == null) | .context]}' ;; 404) echo "classic BP なし(${db})" ;; *) echo "判定不能 (HTTP ${code:-?}) — Administration: read 権限を確認。green と扱わない" ;; esac
最終確認として、導入後に小さな PR を 1 件流し、codex-review の実行・必須チェックの報告・
squash merge のみ許可・スレッド resolve 必須が実際に効いていることを観察する。db=$(gh repo view "${repo}" --json defaultBranchRef --jq '.defaultBranchRef.name')
db_enc=$(printf '%s' "${db}" | jq -sRr '@uri')
code=$(gh api -i "repos/${repo}/branches/${db_enc}/protection" 2>/dev/null | awk 'NR==1{print $2}')
case "${code}" in
200) gh api "repos/${repo}/branches/${db_enc}/protection" --jq
'{strict: (.required_status_checks.strict // "none"), unbound: [.required_status_checks.checks[]? | select(.app_id == null) | .context]}' ;; 404) echo "无传统分支保护(${db})" ;; *) echo "无法判定 (HTTP ${code:-?}) — 请确认Administration: read权限。不得视为正常状态" ;; esac
'{strict: (.required_status_checks.strict // "none"), unbound: [.required_status_checks.checks[]? | select(.app_id == null) | .context]}' ;; 404) echo "无传统分支保护(${db})" ;; *) echo "无法判定 (HTTP ${code:-?}) — 请确认Administration: read权限。不得视为正常状态" ;; esac
最终确认:导入后提交一个小型PR,验证codex-review执行、必填检查报告、仅允许squash合并、必须处理评审线程等规则是否实际生效。完了報告
完成报告
Step ごとの PR 番号、AGENTS.md の観点構成、ruleset の最終必須チェック一覧、適用できなかった項目
(理由付き)を表でまとめて報告する。
需汇总并报告以下内容:各步骤的PR编号、AGENTS.md的要点结构、ruleset的最终必填检查列表、无法应用的项目(含原因)。
よくある失敗
常见失败案例
| 問題 | 回避策 |
|---|---|
| 集約ジョブの skipped 全許容が fail-open として codex に P1 指摘される | Step 3: skipped 許容を条件付きジョブの明示リストに限定する |
| チェック名変更 PR が CI 全 pass でも BLOCKED(ruleset が旧名のまま「Expected」待ち) | Step 4: マージ前に ruleset を新チェック名へ PUT で置換する |
未クォート | Step 3: name に |
| paths フィルタ付き workflow のチェックを必須にするとマージが永久ブロックされる | Step 4: 常に報告されるチェックのみ必須化する |
| 参考ファイルの取り違え(別リポジトリ用 AGENTS.md の混入)を codex が検出 | Step 2: 対象リポジトリ固有の具体項目に落とし込む |
| AGENTS.md の P1 定義と CI ゲート実挙動(P1 でも fail)の矛盾を codex が指摘 | Step 2: P1 定義をゲート実挙動と矛盾させない |
| GITHUB_TOKEN read 化で暗黙 write 依存の workflow が壊れる | Step 4: 全 workflow の permissions 明示を確認してから適用する |
ruleset を PUT したら | Step 4-a: PUT 後に 3 軸スイープ( |
| 旧 ruleset / classic BP の掃き漏らしで未束縛・strict=true が残る | Step 4-a/4-b: 全 branch ruleset を列挙して掃き、classic BP は |
| AGENTS.md に自動マージの G0 契約を書く際 strict を要件として列挙し、実装より強い契約が codex P0 の根拠になる | Step 2: G0 契約を書くなら strict は「意図的な非要件」と明記する( |
| 问题 | 规避方案 |
|---|---|
| 汇总任务允许所有任务跳过,被codex标记为fail-open的P1问题 | Step 3:仅允许明确列出的带条件任务跳过 |
| 修改检查名称的PR在CI全部通过后仍被阻塞(ruleset保留旧名称,处于「Expected」等待状态) | Step 4:合并前使用PUT将ruleset更新为新检查名称 |
未添加引号的 | Step 3:若 |
| 将带paths过滤器的工作流检查设置为必填,导致合并被永久阻塞 | Step 4:仅将始终报告的检查设置为必填 |
| codex检测到混入其他仓库的AGENTS.md内容 | Step 2:转化为目标仓库特有的具体内容 |
| codex指出AGENTS.md的P1定义与CI防护实际行为(P1等级也会失败)存在矛盾 | Step 2:确保P1定义与防护行为一致 |
| 将GITHUB_TOKEN设置为read权限后,依赖隐式write权限的工作流失效 | Step 4:先确认所有工作流已明确设置permissions,再执行该操作 |
使用PUT更新ruleset后, | Step 4-a:PUT更新后执行3轴扫描( |
| 遗漏旧ruleset/传统分支保护,导致未绑定、strict=true等问题残留 | Step 4-a/4-b:扫描所有分支ruleset,单独检查传统分支保护 |
| 在AGENTS.md中编写自动合并的G0契约时,将strict列为要求,导致契约比实际实现更严格,被codex标记为P0问题 | Step 2:若编写G0契约,需明确说明strict是「故意不设置的要求」(参考 |
注意事項
注意事项
- コミットは日本語 Conventional Commits 形式で作成し、対象リポジトリのコミット規約・フッター運用に従う。は使用しない
--no-verify - シェル変数は 形式でクォートする
"${var}" - codex の指摘が正当なら修正で応える(テスト・ゲートの弱体化やスキップでごまかさない)。 スレッドへ対応内容を返信して resolve してからマージする
- スコープ外の発見は Issue 化をユーザーに提案する(勝手に起票しない)
- このスキルはネットワーク越しの GitHub 操作(ruleset の PUT・workflow の配布)を必須とする。該当コマンドはコマンド単位で sandbox 無効にして実行する。ネットワーク遮断を解除できない環境では実行できない
- 提交代码需使用日语Conventional Commits格式,遵循目标仓库的提交规范及页脚规则。不得使用
--no-verify - shell变量需使用格式添加引号
"${var}" - 若codex的指出合理,需进行修正(不得通过测试或防护降级、跳过等方式掩盖问题)。需在评审线程中回复处理内容并标记为resolve后再合并
- 超出范围的发现需建议用户创建Issue(不得自行创建)
- 本技能需通过网络执行GitHub操作(如PUT ruleset、分发工作流)。相关命令需逐个禁用沙箱后执行。在无法解除网络隔离的环境中无法执行