Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions scripts/setup-pr-quality-ruleset.sh
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@
# What this script does:
# 1. Checks whether the "pr-quality" ruleset already exists
# 2. Creates it if missing, or updates it if present so drifted parameters
# (e.g. dismiss_stale_reviews_on_push) reconverge to the codified standard
# (idempotent — safe to re-run)
# (e.g. dismiss_stale_reviews_on_push, require_last_push_approval)
# reconverge to the codified standard (idempotent — safe to re-run)
Comment thread
don-petry marked this conversation as resolved.
Comment thread
don-petry marked this conversation as resolved.
Comment thread
coderabbitai[bot] marked this conversation as resolved.
#
# Prerequisites: gh (authenticated with repo admin rights)
# Usage:
Expand Down Expand Up @@ -79,7 +79,24 @@ JSON

if [[ -n "$EXISTING_ID" ]]; then
echo " ↻ '$RULESET_NAME' ruleset already exists (id: $EXISTING_ID) — updating to ensure compliance..."
printf '%s\n' "$RULESET_PAYLOAD" | gh api "repos/$REPO/rulesets/$EXISTING_ID" --method PUT --input -
# Fetch existing ruleset and preserve all fields not being updated
EXISTING_RULESET=$(gh api "repos/$REPO/rulesets/$EXISTING_ID")
# Merge new configuration into existing ruleset: preserve bypass_actors and other fields
UPDATE_PAYLOAD=$(printf '%s' "$RULESET_PAYLOAD" | jq --slurpfile existing <(echo "$EXISTING_RULESET") '
. as $new
| $existing[0]
| .name = $new.name
| .target = $new.target
| .enforcement = $new.enforcement
| .conditions = $new.conditions
| .rules = $new.rules
')
# Validate required fields are present
if ! printf '%s' "$UPDATE_PAYLOAD" | jq -e '.name and .target and .rules and (.rules | length > 0)' >/dev/null 2>&1; then
echo "Error: Invalid ruleset payload after merge (missing required fields)" >&2
exit 1
fi
printf '%s\n' "$UPDATE_PAYLOAD" | gh api "repos/$REPO/rulesets/$EXISTING_ID" --method PUT --input -
echo " ✓ '$RULESET_NAME' ruleset updated successfully."
echo ""
echo "=== Done ==="
Expand Down
30 changes: 30 additions & 0 deletions scripts/tests/setup-pr-quality-ruleset.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,4 +59,34 @@ describe('setup-pr-quality-ruleset.sh codified ruleset', () => {
const script = fs.readFileSync(scriptPath, 'utf8')
expect(script).toMatch(/--method PUT/)
})

it('script preserves existing bypass_actors when updating an existing ruleset', () => {
const scriptPath = path.join(__dirname, '..', 'setup-pr-quality-ruleset.sh')
const script = fs.readFileSync(scriptPath, 'utf8')
// The update path must fetch the existing ruleset and merge fields so a PUT
// preserves bypass_actors and other fields set by administrators.
expect(script).toMatch(/bypass_actors/)
expect(script).toMatch(/EXISTING_RULESET/)
})

it('script merges new configuration into existing ruleset preserving all fields', () => {
const scriptPath = path.join(__dirname, '..', 'setup-pr-quality-ruleset.sh')
const script = fs.readFileSync(scriptPath, 'utf8')
// The update flow must fetch the existing ruleset and selectively update
// fields (name, target, enforcement, conditions, rules) while preserving
// bypass_actors and other fields not in the new payload.
expect(script).toMatch(/EXISTING_RULESET=.*gh api.*rulesets.*EXISTING_ID/)
expect(script).toMatch(/slurpfile.*existing/)
// Verify field-by-field update pattern in jq to preserve all existing fields
expect(script).toMatch(/\.name = \$new\.name/)
expect(script).toMatch(/\.rules = \$new\.rules/)
expect(script).toMatch(/\$existing\[0\]/)
})

it('script validates merged payload before submitting', () => {
const scriptPath = path.join(__dirname, '..', 'setup-pr-quality-ruleset.sh')
const script = fs.readFileSync(scriptPath, 'utf8')
// Validation ensures the merged payload is well-formed and contains required fields
expect(script).toMatch(/jq -e.*\.name.*\.target.*\.rules/)
})
})
Loading