Skip to content

Instantly share code, notes, and snippets.

@adityathebe
Created June 25, 2026 10:09
Show Gist options
  • Select an option

  • Save adityathebe/870be1f5d27d8ae56f4d5abbccb21559 to your computer and use it in GitHub Desktop.

Select an option

Save adityathebe/870be1f5d27d8ae56f4d5abbccb21559 to your computer and use it in GitHub Desktop.
branch-protection.sh
#!/usr/bin/env bash
set -euo pipefail
RULESET_NAME="${RULESET_NAME:-Protect main from direct pushes}"
TARGET_BRANCH="${TARGET_BRANCH:-main}"
BYPASS_USER="${BYPASS_USER:-adityathebe}"
REPO="${GH_REPO:-${1:-}}"
if ! command -v gh >/dev/null 2>&1; then
echo "error: gh CLI is required" >&2
exit 1
fi
if [[ -z "${REPO}" ]]; then
REPO="$(gh repo view --json nameWithOwner --jq .nameWithOwner)"
fi
if [[ -z "${REPO}" || "${REPO}" != */* ]]; then
echo "error: could not determine GitHub repo. Pass owner/repo or set GH_REPO." >&2
exit 1
fi
BYPASS_USER_ID="$(gh api "/users/${BYPASS_USER}" --jq .id)"
payload() {
python3 - "$RULESET_NAME" "$TARGET_BRANCH" "$BYPASS_USER_ID" <<'PY'
import json
import sys
ruleset_name = sys.argv[1]
target_branch = sys.argv[2]
bypass_user_id = int(sys.argv[3])
print(json.dumps({
"name": ruleset_name,
"target": "branch",
"enforcement": "active",
"bypass_actors": [
{
"actor_id": bypass_user_id,
"actor_type": "User",
"bypass_mode": "always"
}
],
"conditions": {
"ref_name": {
"include": [f"refs/heads/{target_branch}"],
"exclude": []
}
},
"rules": [
{"type": "deletion"},
{"type": "non_fast_forward"},
{
"type": "pull_request",
"parameters": {
"required_approving_review_count": 0,
"dismiss_stale_reviews_on_push": False,
"require_code_owner_review": False,
"require_last_push_approval": False,
"required_review_thread_resolution": False,
"allowed_merge_methods": ["merge", "squash", "rebase"]
}
}
]
}))
PY
}
existing_id="$(gh api "/repos/${REPO}/rulesets" --jq ".[] | select(.name == \"${RULESET_NAME}\") | .id" 2>/dev/null || true)"
if [[ -n "${existing_id}" ]]; then
payload | gh api --method PUT "/repos/${REPO}/rulesets/${existing_id}" --input - >/dev/null
echo "Updated ruleset '${RULESET_NAME}' (${existing_id}) on ${REPO}."
else
created_id="$(payload | gh api --method POST "/repos/${REPO}/rulesets" --input - --jq .id)"
echo "Created ruleset '${RULESET_NAME}' (${created_id}) on ${REPO}."
fi
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment