Skip to content

Instantly share code, notes, and snippets.

@felixarntz
Last active July 27, 2026 16:15
Show Gist options
  • Select an option

  • Save felixarntz/05eafd221b9d6671153ac9e8f3b710a4 to your computer and use it in GitHub Desktop.

Select an option

Save felixarntz/05eafd221b9d6671153ac9e8f3b710a4 to your computer and use it in GitHub Desktop.
My scripts for setting up GitHub repos securely. I make them executable and put them in my `$PATH`, then run them from a local checkout of a specific repo. They'll automatically operate on that repo, via the `gh` CLI tool.
#!/bin/sh
RULESET_NAME="Default Branch Protection"
RULESET_PAYLOAD=$(cat <<'JSON'
{
"name": "Default Branch Protection",
"target": "branch",
"enforcement": "active",
"bypass_actors": [
{
"actor_id": 2,
"actor_type": "RepositoryRole",
"bypass_mode": "always"
},
{
"actor_id": 5,
"actor_type": "RepositoryRole",
"bypass_mode": "always"
}
],
"conditions": {
"ref_name": {
"include": ["~DEFAULT_BRANCH", "refs/heads/release/**"],
"exclude": []
}
},
"rules": [
{
"type": "deletion"
},
{
"type": "non_fast_forward"
},
{
"type": "pull_request",
"parameters": {
"allowed_merge_methods": ["squash"],
"dismiss_stale_reviews_on_push": false,
"require_code_owner_review": false,
"require_last_push_approval": false,
"required_approving_review_count": 1,
"required_review_thread_resolution": false
}
}
]
}
JSON
)
RULESET_ID=$(gh api "repos/{owner}/{repo}/rulesets" --jq ".[] | select(.name==\"${RULESET_NAME}\") | .id" | head -n 1)
if [ -n "${RULESET_ID}" ]; then
gh api "repos/{owner}/{repo}/rulesets/${RULESET_ID}" \
--method PUT \
--input - > /dev/null <<EOF
${RULESET_PAYLOAD}
EOF
echo "Updated ruleset '${RULESET_NAME}' (ID: ${RULESET_ID})."
else
gh api "repos/{owner}/{repo}/rulesets" \
--method POST \
--input - > /dev/null <<EOF
${RULESET_PAYLOAD}
EOF
echo "Created ruleset '${RULESET_NAME}'."
fi
#!/bin/sh
gh api "repos/{owner}/{repo}/actions/permissions/workflow" \
--method PUT \
-f default_workflow_permissions=read \
-F can_approve_pull_request_reviews=false \
> /dev/null
echo "Set default GITHUB_TOKEN permissions to read-only."
gh api "repos/{owner}/{repo}/actions/permissions/fork-pr-contributor-approval" \
--method PUT \
-f approval_policy=all_external_contributors \
> /dev/null
echo "Required approval for all external contributor fork PR workflows."
gh api "repos/{owner}/{repo}/actions/permissions" \
--method PUT \
-F enabled=true \
-F sha_pinning_required=true \
> /dev/null
echo "Required actions to be pinned to a full-length commit SHA."
gh api "repos/{owner}/{repo}/vulnerability-alerts" \
--method PUT \
> /dev/null
echo "Enabled Dependabot alerts."
gh api "repos/{owner}/{repo}/automated-security-fixes" \
--method PUT \
> /dev/null
echo "Enabled Dependabot security updates."
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment