github-branch-policy

Compare original and translation side by side

🇺🇸

Original

English
🇨🇳

Translation

Chinese

GitHub Branch Policy

GitHub 分支策略

Overview

概述

Run a repeatable audit for GitHub branch policy safety and Actions workflow hygiene. Validate ruleset enforcement, required checks, workflow registration integrity, and branch cleanup behavior that commonly break CI and auto-merge.
针对GitHub分支策略安全性和Actions工作流合规性执行可重复的审计。验证规则集执行情况、必要检查、工作流注册完整性以及通常会导致CI和自动合并失败的分支清理行为。

Use This Skill When

适用场景

Apply this skill for requests like:
  • "Audit branch protection/rulesets on this repo."
  • "Check whether auto-merge and branch cleanup are configured correctly."
  • "Find ghost workflows or stale branches causing Actions failures."
  • "Why are we getting
    Cannot update this protected ref
    ?"
  • "Make sure branch policy matches solo-developer expectations."
在以下场景中使用此技能:
  • "审计此仓库的分支保护/规则集。"
  • "检查自动合并和分支清理配置是否正确。"
  • "查找导致Actions失败的幽灵工作流或陈旧分支。"
  • "为什么我们会收到
    Cannot update this protected ref
    错误?"
  • "确保分支策略符合独立开发者的预期。"

Prerequisites

前置条件

  • gh
    authenticated for the target repo (
    repo
    +
    workflow
    scopes).
  • jq
    available.
  • Target repository known as
    OWNER/REPO
    , or current directory is a checked-out repo with a GitHub remote.
  • gh
    已针对目标仓库完成认证(需
    repo
    +
    workflow
    权限范围)。
  • 已安装
    jq
    工具。
  • 目标仓库格式为
    OWNER/REPO
    ,或当前目录是已检出的带有GitHub远程仓库的本地仓库。

Quick Setup

快速设置

bash
OWNER_REPO="${OWNER_REPO:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}"
OWNER="${OWNER_REPO%/*}"
REPO="${OWNER_REPO#*/}"
DEFAULT_BRANCH="$(gh repo view "$OWNER_REPO" --json defaultBranchRef -q .defaultBranchRef.name)"
echo "Auditing $OWNER_REPO (default: $DEFAULT_BRANCH)"
bash
OWNER_REPO="${OWNER_REPO:-$(gh repo view --json nameWithOwner -q .nameWithOwner)}"
OWNER="${OWNER_REPO%/*}"
REPO="${OWNER_REPO#*/}"
DEFAULT_BRANCH="$(gh repo view "$OWNER_REPO" --json defaultBranchRef -q .defaultBranchRef.name)"
echo "Auditing $OWNER_REPO (default: $DEFAULT_BRANCH)"

Audit Checklist

审计检查清单

1. Repository merge settings are compatible with policy

1. 仓库合并设置与策略兼容

Verification:
bash
gh api "repos/$OWNER/$REPO" \
  --jq '{allow_auto_merge,allow_squash_merge,allow_merge_commit,allow_rebase_merge,delete_branch_on_merge,default_branch}'
Pass criteria:
  • allow_auto_merge: true
    when auto-merge is expected.
  • Merge methods match branch rules (for example, squash-only policy -> squash enabled).
  • delete_branch_on_merge: true
    unless intentionally disabled.
Remediation:
  • Enable auto-merge at repo level.
  • Align repo merge methods with ruleset
    allowed_merge_methods
    .
  • Enable delete-on-merge, or document why not.

验证命令:
bash
gh api "repos/$OWNER/$REPO" \
  --jq '{allow_auto_merge,allow_squash_merge,allow_merge_commit,allow_rebase_merge,delete_branch_on_merge,default_branch}'
通过标准:
  • 当需要自动合并时,
    allow_auto_merge: true
  • 合并方式与分支规则匹配(例如,仅 squash 策略需开启 squash 合并)。
  • delete_branch_on_merge: true
    ,除非有明确理由关闭该功能。
修复措施:
  • 在仓库级别启用自动合并。
  • 对齐仓库合并方式与规则集的
    allowed_merge_methods
  • 启用合并后删除分支功能,或记录关闭理由。

2. Active ruleset applies to default branch and enforces PR + required checks

2. 活跃规则集应用于默认分支并强制执行PR与必要检查

Verification:
bash
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | {id,name,enforcement,target,include:(.conditions.ref_name.include // []),rules:[.rules[].type]}'
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | select(.enforcement=="active") | .rules[] | select(.type=="pull_request" or .type=="required_status_checks")'
Pass criteria:
  • At least one active branch ruleset applies to
    ~DEFAULT_BRANCH
    (or equivalent explicit default branch include).
  • Ruleset includes
    pull_request
    and
    required_status_checks
    .
  • Optional hardening like
    required_linear_history
    ,
    non_fast_forward
    ,
    deletion
    is intentional.
Remediation:
  • Enable or create a default-branch ruleset.
  • Add missing
    pull_request
    and
    required_status_checks
    rules.

验证命令:
bash
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | {id,name,enforcement,target,include:(.conditions.ref_name.include // []),rules:[.rules[].type]}'
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | select(.enforcement=="active") | .rules[] | select(.type=="pull_request" or .type=="required_status_checks")'
通过标准:
  • 至少有一个活跃分支规则集应用于
    ~DEFAULT_BRANCH
    (或等效的显式默认分支包含规则)。
  • 规则集包含
    pull_request
    required_status_checks
    规则。
  • 可选的强化规则如
    required_linear_history
    non_fast_forward
    deletion
    是有意配置的。
修复措施:
  • 启用或创建默认分支规则集。
  • 添加缺失的
    pull_request
    required_status_checks
    规则。

3. Required check contexts match real check names

3. 必要检查上下文与实际检查名称匹配

Verification:
bash
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | .rules[] | select(.type=="required_status_checks") | .parameters.required_status_checks[].context'
gh pr list --state all --limit 20 --json number \
  --jq '.[0].number' | xargs -I{} gh pr view {} --json statusCheckRollup
Pass criteria:
  • Required contexts exactly match real checks reported on PRs (case-sensitive), e.g.
    ci
    ,
    Vercel
    ,
    Vercel Preview Comments
    .
Remediation:
  • Update required check contexts in the ruleset to match actual check names.

验证命令:
bash
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | .rules[] | select(.type=="required_status_checks") | .parameters.required_status_checks[].context'
gh pr list --state all --limit 20 --json number \
  --jq '.[0].number' | xargs -I{} gh pr view {} --json statusCheckRollup
通过标准:
  • 必要检查上下文与PR上显示的实际检查名称完全匹配(区分大小写),例如
    ci
    Vercel
    Vercel Preview Comments
修复措施:
  • 更新规则集中的必要检查上下文,使其与实际检查名称一致。

4. Solo-dev compatibility: CODEOWNERS review not forced (if desired)

4. 独立开发者兼容性:未强制CODEOWNERS审核(如有需求)

Verification:
bash
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | {name, pull_request_rules:[.rules[] | select(.type=="pull_request") | .parameters.require_code_owner_review]}'
Pass criteria:
  • For solo-maintainer repos,
    require_code_owner_review
    is
    false
    unless intentionally required.
Remediation:
  • Set
    require_code_owner_review: false
    where solo-dev flow is desired.

验证命令:
bash
gh api "repos/$OWNER/$REPO/rulesets" \
  --jq '.[] | {name, pull_request_rules:[.rules[] | select(.type=="pull_request") | .parameters.require_code_owner_review]}'
通过标准:
  • 对于单人维护的仓库,
    require_code_owner_review
    false
    ,除非有意强制开启。
修复措施:
  • 在需要独立开发者工作流的仓库中设置
    require_code_owner_review: false

5. Actions policy allows the workflow dependencies you actually use

5. Actions策略允许实际使用的工作流依赖

Verification:
bash
gh api "repos/$OWNER/$REPO/actions/permissions" \
  --jq '{enabled,allowed_actions,sha_pinning_required}'
gh api "repos/$OWNER/$REPO/actions/permissions/selected-actions" \
  --jq '{github_owned_allowed,verified_allowed,patterns_allowed}'
Pass criteria:
  • If
    allowed_actions: selected
    , all actions used by workflows are explicitly allowed (or covered by allowed classes).
  • If SHA pinning is required, actions are pinned.
Remediation:
  • Add missing action patterns to selected-actions policy.
  • Pin unpinned actions.
  • Prefer minimal/no third-party actions for sensitive auto-merge workflows.

验证命令:
bash
gh api "repos/$OWNER/$REPO/actions/permissions" \
  --jq '{enabled,allowed_actions,sha_pinning_required}'
gh api "repos/$OWNER/$REPO/actions/permissions/selected-actions" \
  --jq '{github_owned_allowed,verified_allowed,patterns_allowed}'
通过标准:
  • 如果
    allowed_actions: selected
    ,则工作流使用的所有操作都已被明确允许(或属于允许的类别)。
  • 如果要求SHA固定,则所有操作都已固定版本。
修复措施:
  • 向选中操作策略添加缺失的操作匹配规则。
  • 为未固定版本的操作添加SHA固定。
  • 对于敏感的自动合并工作流,优先使用最少或不使用第三方操作。

6. Auto-merge workflow registration is clean (no ghost duplicates)

6. 自动合并工作流注册干净(无幽灵重复项)

Verification:
bash
gh api "repos/$OWNER/$REPO/actions/workflows" \
  --jq '.workflows[] | [.id,.name,.path,.state] | @tsv' | sort
gh workflow list --all
Pass criteria:
  • Exactly one active registration for the canonical auto-merge workflow path.
  • Legacy/stale registrations are disabled or removed.
Remediation:
  • Disable stale workflow IDs:
bash
gh workflow disable <workflow_id>
  • Keep a single canonical filename on default branch.

验证命令:
bash
gh api "repos/$OWNER/$REPO/actions/workflows" \
  --jq '.workflows[] | [.id,.name,.path,.state] | @tsv' | sort
gh workflow list --all
通过标准:
  • 标准自动合并工作流路径仅有一个活跃注册项。
  • 遗留/陈旧的注册项已被禁用或删除。
修复措施:
  • 禁用陈旧工作流ID:
bash
gh workflow disable <workflow_id>
  • 在默认分支上保留单个标准文件名。

7. Auto-merge workflow trigger and runtime behavior are reliable

7. 自动合并工作流触发与运行行为可靠

Verification:
bash
AUTO_WF="Enable PR Auto-Merge"  # adjust if needed
gh workflow view "$AUTO_WF" --yaml | sed -n '1,220p'
gh run list --workflow "$AUTO_WF" --limit 20 \
  --json databaseId,event,status,conclusion,headBranch,createdAt
Deep check for suspicious runs:
bash
RUN_ID="<id>"
gh run view "$RUN_ID" --json event,conclusion,jobs
Pass criteria:
  • Trigger is intentionally chosen (
    pull_request_target
    is preferred for base-branch controlled auto-merge orchestration;
    pull_request
    can be valid if branch consistency is guaranteed).
  • Recent PR-event runs execute real jobs.
  • No repeating failures with
    push
    event + zero jobs + missing logs (ghost workflow symptom).
Remediation:
  • Move to a stable default-branch workflow file.
  • Prefer
    pull_request_target
    for auto-merge orchestration logic that should not depend on PR-branch workflow file presence.
  • Disable stale workflow registrations.

验证命令:
bash
AUTO_WF="Enable PR Auto-Merge"  # 按需调整
gh workflow view "$AUTO_WF" --yaml | sed -n '1,220p'
gh run list --workflow "$AUTO_WF" --limit 20 \
  --json databaseId,event,status,conclusion,headBranch,createdAt
深度检查可疑运行:
bash
RUN_ID="<id>"
gh run view "$RUN_ID" --json event,conclusion,jobs
通过标准:
  • 触发方式经过合理选择(
    pull_request_target
    是基于主分支控制的自动合并编排的首选;如果能保证分支一致性,
    pull_request
    也可使用)。
  • 近期PR事件的运行能执行实际任务。
  • 没有重复出现
    push
    事件+零任务+无日志的失败情况(幽灵工作流的特征)。
修复措施:
  • 将工作流文件迁移到稳定的默认分支。
  • 对于不依赖PR分支工作流文件存在的自动合并编排逻辑,优先使用
    pull_request_target
  • 禁用陈旧的工作流注册项。

8.
Cannot update this protected ref
diagnostics for branch-update workflows

8. 分支更新工作流的
Cannot update this protected ref
错误诊断

Verification:
bash
gh workflow list --all
gh run list --workflow "Auto Update PR Branches" --limit 20
Pass criteria:
  • Workflow either:
    • updates eligible PR branches successfully, and
    • handles protected/fork branches gracefully without failing the whole run.
Remediation:
  • In update-branch loops, continue on protected/fork failures.
  • Skip PR heads that are protected or not writable.
  • Treat this error as per-PR conditional failure, not a global workflow failure.

验证命令:
bash
gh workflow list --all
gh run list --workflow "Auto Update PR Branches" --limit 20
通过标准:
  • 工作流需满足以下任一条件:
    • 成功更新符合条件的PR分支,并且
    • 能优雅处理受保护/分叉分支,不会导致整个运行失败。
修复措施:
  • 在分支更新循环中,遇到受保护/分叉分支失败时继续执行。
  • 跳过受保护或不可写的PR头部分支。
  • 将此错误视为单个PR的条件性失败,而非全局工作流失败。

9. Branch cleanup strategy is in place

9. 已配置分支清理策略

Verification:
bash
gh api "repos/$OWNER/$REPO" --jq '{delete_branch_on_merge}'
gh api "repos/$OWNER/$REPO/actions/workflows" \
  --jq '.workflows[] | {name,path,state}'
Pass criteria:
  • delete_branch_on_merge: true
    , or equivalent cleanup workflow exists and is active.
Remediation:
  • Enable delete-on-merge.
  • Add/repair cleanup workflow if additional cleanup behavior is required.

验证命令:
bash
gh api "repos/$OWNER/$REPO" --jq '{delete_branch_on_merge}'
gh api "repos/$OWNER/$REPO/actions/workflows" \
  --jq '.workflows[] | {name,path,state}'
通过标准:
  • delete_branch_on_merge: true
    ,或存在等效的活跃清理工作流。
修复措施:
  • 启用合并后删除分支功能。
  • 如果需要额外的清理行为,添加或修复清理工作流。

10. No stale branches from merged/closed PRs

10. 无来自已合并/关闭PR的陈旧分支

Verification:
bash
gh api "repos/$OWNER/$REPO/branches" --paginate --jq '.[].name' | sort -u > /tmp/live-branches.txt
gh pr list --state merged --limit 500 --json headRefName --jq '.[].headRefName' | sort -u > /tmp/merged-pr-branches.txt
gh pr list --state closed --limit 500 --json headRefName,mergedAt \
  --jq '.[] | select(.mergedAt==null) | .headRefName' | sort -u > /tmp/closed-pr-branches.txt
cat /tmp/merged-pr-branches.txt /tmp/closed-pr-branches.txt | sort -u > /tmp/candidate-stale-branches.txt
comm -12 /tmp/live-branches.txt /tmp/candidate-stale-branches.txt
Pass criteria:
  • Intersection output is empty, excluding intentional long-lived branches.
Remediation:
  • Delete confirmed stale branches:
bash
git push origin --delete "<branch>"

验证命令:
bash
gh api "repos/$OWNER/$REPO/branches" --paginate --jq '.[].name' | sort -u > /tmp/live-branches.txt
gh pr list --state merged --limit 500 --json headRefName --jq '.[].headRefName' | sort -u > /tmp/merged-pr-branches.txt
gh pr list --state closed --limit 500 --json headRefName,mergedAt \
  --jq '.[] | select(.mergedAt==null) | .headRefName' | sort -u > /tmp/closed-pr-branches.txt
cat /tmp/merged-pr-branches.txt /tmp/closed-pr-branches.txt | sort -u > /tmp/candidate-stale-branches.txt
comm -12 /tmp/live-branches.txt /tmp/candidate-stale-branches.txt
通过标准:
  • 交集输出为空,排除有意保留的长期分支。
修复措施:
  • 删除确认的陈旧分支:
bash
git push origin --delete "<branch>"

11. Rulesets are primary policy; legacy protection is not conflicting

11. 规则集为主要策略;遗留保护规则无冲突

Verification:
bash
gh api "repos/$OWNER/$REPO/rulesets" --jq 'length'
gh api "repos/$OWNER/$REPO/branches/$DEFAULT_BRANCH/protection" 2>/dev/null | jq '.'
Pass criteria:
  • Rulesets are primary mechanism.
  • Legacy branch protection is absent or intentionally non-overlapping.
  • If branch protection endpoint returns 404 while rulesets exist, that is expected.
Remediation:
  • Consolidate policy into rulesets.
  • Remove redundant legacy branch protection after parity validation.
验证命令:
bash
gh api "repos/$OWNER/$REPO/rulesets" --jq 'length'
gh api "repos/$OWNER/$REPO/branches/$DEFAULT_BRANCH/protection" 2>/dev/null | jq '.'
通过标准:
  • 规则集是主要的策略机制。
  • 遗留分支保护规则不存在或有意不重叠。
  • 如果规则集存在时,分支保护接口返回404,属于正常情况。
修复措施:
  • 将策略整合到规则集中。
  • 在验证功能一致后,移除冗余的遗留分支保护规则。

Optional Smoke Test (recommended for auto-merge incidents)

可选冒烟测试(建议在自动合并故障时使用)

  1. Create a temporary PR from a throwaway branch.
  2. Confirm auto-merge was enabled:
bash
gh pr view <pr_number> --json autoMergeRequest
  1. Confirm auto-merge workflow run event/job execution:
bash
gh run list --workflow "Enable PR Auto-Merge" --limit 5
  1. Close PR and delete branch.
  1. 从临时分支创建一个测试PR。
  2. 确认自动合并已启用:
bash
gh pr view <pr_number> --json autoMergeRequest
  1. 确认自动合并工作流的运行事件/任务执行:
bash
gh run list --workflow "Enable PR Auto-Merge" --limit 5
  1. 关闭PR并删除分支。

Report Format

报告格式

markdown
undefined
markdown
undefined

Branch Policy Audit Report

分支策略审计报告

  • Repository: OWNER/REPO
  • Default branch: <branch>
  • Timestamp (UTC): <iso8601>
  • Overall status: PASS | NEEDS_ACTION | BLOCKED
  • 仓库:OWNER/REPO
  • 默认分支:<branch>
  • 时间戳(UTC):<iso8601>
  • 整体状态:通过 | 需要处理 | 阻塞

Findings

检查结果

  1. [SEV-<1-3>] <check name> - <pass/fail summary> Evidence: <key command output summary> Remediation: <next action>
  1. [严重程度-<1-3>] <检查名称> - <通过/失败摘要> 证据:<关键命令输出摘要> 修复措施:<下一步操作>

Actions Taken

已执行操作

  1. <action performed or "none">
  1. <执行的操作或"无">

Follow-up

后续跟进

  1. <required human decision or "none">
undefined
  1. <需要人工决策或"无">
undefined

Guardrails

注意事项

  • Do not delete branches until confirmed stale and unprotected.
  • Do not disable workflows blindly; verify canonical registration first.
  • Treat
    push + 0 jobs + no logs
    on workflow runs as likely ghost/stale registration evidence.
  • Prefer deterministic
    gh api
    evidence over assumptions.
  • If permissions are insufficient, report missing scope/permission and continue with remaining checks.
  • 确认分支为陈旧且不受保护后再删除。
  • 不要盲目禁用工作流;先验证标准注册项。
  • 将工作流运行中的
    push + 0 jobs + 无日志
    视为幽灵/陈旧注册项的可能证据。
  • 优先使用确定性的
    gh api
    证据,而非假设。
  • 如果权限不足,报告缺失的权限范围并继续执行剩余检查。