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
123 changes: 123 additions & 0 deletions .github/workflows/exact-head-acceptance.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
name: Exact-head acceptance
run-name: "Exact-head acceptance PR #${{ inputs.pr_number }} at ${{ inputs.head_sha }}"

on:
workflow_dispatch:
inputs:
pr_number:
description: Open same-repository PR number targeting main
required: true
type: number
head_sha:
description: Exact 40-character PR head SHA being accepted
required: true
type: string

permissions: {}

concurrency:
group: exact-head-acceptance-${{ github.repository }}-${{ inputs.pr_number }}
cancel-in-progress: false

jobs:
accept:
name: Publish exact-head acceptance
runs-on: ubuntu-latest
permissions:
checks: write
pull-requests: read
env:
GH_TOKEN: ${{ github.token }}
PR_NUMBER: ${{ inputs.pr_number }}
SUPPLIED_SHA: ${{ inputs.head_sha }}
DISPATCH_REF: ${{ github.ref }}
DISPATCH_ACTOR: ${{ github.actor }}
TRIGGERING_ACTOR: ${{ github.triggering_actor }}
TRUSTED_ACCEPTORS: JustinJLeopard
CHECK_NAME: Exact-head acceptance
DETAILS_URL: ${{ github.server_url }}/${{ github.repository }}/actions/runs/${{ github.run_id }}
steps:
- name: Validate live PR head and publish acceptance
shell: bash
run: |
set -euo pipefail

fail() {
echo "Acceptance rejected: $1" >&2
exit 1
}
is_trusted() {
[[ ",$TRUSTED_ACCEPTORS," == *",$1,"* ]]
}

is_trusted "$DISPATCH_ACTOR" ||
fail "dispatcher is not allowlisted"
is_trusted "$TRIGGERING_ACTOR" ||
fail "triggering actor is not allowlisted"
[[ "$DISPATCH_REF" == "refs/heads/main" ]] ||
fail "workflow must be dispatched from main"
[[ "$PR_NUMBER" =~ ^[1-9][0-9]*$ ]] ||
fail "PR number must be a positive integer"
[[ "$SUPPLIED_SHA" =~ ^[0-9a-f]{40}$ ]] ||
fail "head SHA must be 40 lowercase hexadecimal characters"

pr_json="$(
gh pr view "$PR_NUMBER" \
--repo "$GITHUB_REPOSITORY" \
--json state,isDraft,baseRefName,headRefOid,isCrossRepository
)"
if ! jq -e \
--arg sha "$SUPPLIED_SHA" \
'
.state == "OPEN" and
.isDraft == false and
.baseRefName == "main" and
.isCrossRepository == false and
.headRefOid == $sha
' <<< "$pr_json" >/dev/null; then
fail "PR must be open, non-draft, same-repository, target main, and match the supplied SHA"
fi

external_id="pr:$PR_NUMBER:$SUPPLIED_SHA"
payload="$(
jq -n \
--arg name "$CHECK_NAME" \
--arg sha "$SUPPLIED_SHA" \
--arg external_id "$external_id" \
--arg details_url "$DETAILS_URL" \
--arg actor "$DISPATCH_ACTOR" \
'{
name: $name,
head_sha: $sha,
status: "completed",
conclusion: "success",
external_id: $external_id,
details_url: $details_url,
output: {
title: "Exact PR head accepted",
summary: ("Accepted by " + $actor + ".")
}
}'
)"
check_json="$(
gh api \
-X POST \
-H "Accept: application/vnd.github+json" \
"repos/$GITHUB_REPOSITORY/check-runs" \
--input - <<< "$payload"
)"
jq -e \
--arg name "$CHECK_NAME" \
--arg sha "$SUPPLIED_SHA" \
--arg external_id "$external_id" \
'
.name == $name and
.head_sha == $sha and
.external_id == $external_id and
.status == "completed" and
.conclusion == "success"
' <<< "$check_json" >/dev/null ||
fail "Checks API response did not preserve the exact acceptance identity"

printf '### Exact head accepted\n\nPR #%s at %s; external ID %s.\n' \
"$PR_NUMBER" "$SUPPLIED_SHA" "$external_id" >> "$GITHUB_STEP_SUMMARY"
30 changes: 30 additions & 0 deletions docs/exact-head-acceptance.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Exact-head acceptance

After independent review has accepted the exact current head and required CI has
passed, an authorized maintainer publishes that decision with:

```sh
gh workflow run exact-head-acceptance.yml --ref main \
-f pr_number=NUMBER -f head_sha=FULL_40_CHARACTER_HEAD_SHA
```

Run this in the repository checkout, or add `--repo OWNER/REPO`. Verify the
workflow finishes successfully and the `Exact-head acceptance` check appears on
that exact SHA. A new commit needs a new independent review and acceptance.
Dispatch is an attestation that review has happened; it does not perform review.

The publisher only accepts an open, non-draft, same-repository PR targeting
`main`, with the supplied SHA matching its current head. Both the dispatcher and
rerun actor must be `JustinJLeopard`; dispatch must use `main`. No PR code is
checked out or executed. Publication grants only checks-write and PR-read.

Merge this publisher before adding `Exact-head acceptance` to repository rules.
The workflow alone does not enforce a merge gate. Activation is a separate
ruleset change after proving a missing acceptance blocks, an exact acceptance
passes, and a new head loses acceptance. Keep all other required checks intact.

Binding a required check to the GitHub Actions app identifies the app, not this
specific workflow. Another workflow with checks-write can publish the same
check name. This publisher and an app-bound ruleset are not a universal defense
against a malicious writer changing workflows; consumers that need that threat
model must also validate trusted workflow-run provenance.
Loading