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
70 changes: 67 additions & 3 deletions .github/scripts/merge-own-pr.sh
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
#!/usr/bin/env bash
# Usage: ./merge-own-pr.sh <PR_NUMBER>
# Merges a PR authored by the repo owner by temporarily relaxing branch
# protection (review count 0), squash-merging, then restoring (review count 1).
# Squash-merges a PR authored by the repo owner by temporarily relaxing both
# the legacy branch-protection rules and the "Protect main" ruleset, then
# restoring strict settings (no admin bypass after restore).
set -euo pipefail

PR="${1:?Usage: $0 <PR_NUMBER>}"
REPO="docdyhr/batless"
RULESET_ID="15969824"

# ── Legacy branch-protection (belt-and-suspenders) ──────────────────────────
STRICT_BP='{
"required_status_checks": {"strict": true, "contexts": ["CI Status"]},
"enforce_admins": true,
Expand All @@ -33,15 +36,76 @@ RELAXED_BP='{
"required_linear_history": true
}'

# ── Repository ruleset (no bypass_actors in strict — admins are enforced) ────
STRICT_RULESET=$(cat <<'JSON'
{
"name": "Protect main: require PR and CI",
"target": "branch",
"enforcement": "active",
"conditions": {"ref_name": {"exclude": [], "include": ["~DEFAULT_BRANCH"]}},
"rules": [
{"type": "pull_request", "parameters": {
"required_approving_review_count": 1,
"dismiss_stale_reviews_on_push": true,
"required_reviewers": [],
"require_code_owner_review": true,
"require_last_push_approval": true,
"required_review_thread_resolution": false,
"allowed_merge_methods": ["squash"]
}},
{"type": "required_status_checks", "parameters": {
"strict_required_status_checks_policy": true,
"do_not_enforce_on_create": false,
"required_status_checks": [{"context": "CI Status"}]
}},
{"type": "deletion"},
{"type": "non_fast_forward"}
],
"bypass_actors": []
}
JSON
)

RELAXED_RULESET=$(cat <<'JSON'
{
"name": "Protect main: require PR and CI",
"target": "branch",
"enforcement": "active",
"conditions": {"ref_name": {"exclude": [], "include": ["~DEFAULT_BRANCH"]}},
"rules": [
{"type": "pull_request", "parameters": {
"required_approving_review_count": 0,
"dismiss_stale_reviews_on_push": true,
"required_reviewers": [],
"require_code_owner_review": false,
"require_last_push_approval": false,
"required_review_thread_resolution": false,
"allowed_merge_methods": ["squash"]
}},
{"type": "required_status_checks", "parameters": {
"strict_required_status_checks_policy": true,
"do_not_enforce_on_create": false,
"required_status_checks": [{"context": "CI Status"}]
}},
{"type": "deletion"},
{"type": "non_fast_forward"}
],
"bypass_actors": []
}
JSON
)

restore() {
echo "Restoring branch protection..."
echo "$STRICT_BP" | gh api --method PUT "repos/$REPO/branches/main/protection" --input - > /dev/null
echo "Branch protection restored (1 required review)."
echo "$STRICT_RULESET" | gh api --method PUT "repos/$REPO/rulesets/$RULESET_ID" --input - > /dev/null
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

issue (bug_risk): Restoring strict settings overwrites the entire ruleset JSON, which may drop unrelated future changes

Because this uses PUT with the full JSON body, it will overwrite the entire ruleset. Any future changes made in the GitHub UI or via other tools (new rules, conditions, bypass_actors, etc.) would be removed when this script runs. To avoid that, either fetch the current ruleset and apply a minimal patch (only toggling the needed settings) or treat this script as the sole owner of that ruleset and document that it shouldn’t be edited elsewhere.

echo "Branch protection restored (1 required review, no admin bypass)."
Comment on lines 98 to +102
}
trap restore EXIT

echo "Relaxing branch protection for merge..."
echo "$RELAXED_BP" | gh api --method PUT "repos/$REPO/branches/main/protection" --input - > /dev/null
echo "$RELAXED_RULESET" | gh api --method PUT "repos/$REPO/rulesets/$RULESET_ID" --input - > /dev/null

echo "Merging PR #$PR..."
gh api --method PUT "repos/$REPO/pulls/$PR/merge" -f merge_method=squash --jq '.message'
9 changes: 9 additions & 0 deletions .github/workflows/release-consolidated.yml
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ jobs:
name: Build (${{ matrix.target }})
runs-on: ${{ matrix.os }}
needs: [validate, test]
permissions:
attestations: write
id-token: write
contents: read
strategy:
matrix:
include:
Expand Down Expand Up @@ -129,6 +133,11 @@ jobs:
tar -czf "batless-${{ matrix.target }}.tar.gz" -C "./target/${{ matrix.target }}/release" "$binary_name"
fi

- name: Attest build provenance
uses: actions/attest-build-provenance@a2bbfa25375fe432b6a289bc6b6cd05ecd0c4c32 # v4.1.0
with:
subject-path: "batless-${{ matrix.target }}.*"
Comment on lines +136 to +139
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Publish provenance as a release asset

If the goal is to fix the Scorecard Signed-Releases result, this only uploads the provenance to GitHub's Attestations API and never attaches a signature/provenance file to the GitHub release. Scorecard's Signed-Releases check looks for signature/provenance filenames in the release assets (for example *.intoto.jsonl, *.sigstore.json, *.asc), while the later release step still uploads only batless-*/batless-*, so the next release will still have no asset that the check can count.

Useful? React with 👍 / 👎.


- name: Upload release artifact
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7
with:
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/scorecard.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ jobs:
publish_results: true

- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@03e4368ac7daa2bd82b3e85262f3bf87ee112f57 # v3
uses: github/codeql-action/upload-sarif@7211b7c8077ea37d8641b6271f6a365a22a5fbfa # v4
with:
sarif_file: results.sarif
category: scorecard
Loading