From f98b7fb35440d72ccce320cde1f58ea4f77c20ae Mon Sep 17 00:00:00 2001 From: DTTerastar Date: Fri, 6 Nov 2026 11:01:15 -0500 Subject: [PATCH] ci: require code owner approval via status check Branch protection's 'Require review from Code Owners' can't be satisfied by a solo code owner. DTTerastar/code-owner-approval publishes a status that passes for a code owner's own PR and otherwise needs a code owner review. Co-Authored-By: Claude Fable 5.1 Claude-Session: https://claude.ai/code/session_01CP5PymEM8y5ik8S89BbSwD --- .github/CODEOWNERS | 1 + .github/workflows/code-owner-approval.yml | 31 +++++++++++++++++++++++ .github/workflows/code-owner-review.yml | 16 ++++++++++++ 3 files changed, 48 insertions(+) create mode 100644 .github/CODEOWNERS create mode 100644 .github/workflows/code-owner-approval.yml create mode 100644 .github/workflows/code-owner-review.yml diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..bcade6e --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1 @@ +* @DTTerastar diff --git a/.github/workflows/code-owner-approval.yml b/.github/workflows/code-owner-approval.yml new file mode 100644 index 0000000..32da8bc --- /dev/null +++ b/.github/workflows/code-owner-approval.yml @@ -0,0 +1,31 @@ +name: Code owner approval + +# Required status "Code owner approval": a code owner's own PR passes; anyone else's needs a code +# owner to approve. Replaces branch protection's "Require review from Code Owners", which has no +# exemption for the author. See https://github.com/DTTerastar/code-owner-approval + +on: + pull_request_target: + types: [opened, reopened, synchronize, ready_for_review] + workflow_run: + workflows: [Code owner review] + types: [completed] + workflow_dispatch: # re-checks every open PR + schedule: + - cron: '*/30 * * * *' # backstop if a review's relay didn't run + +# One run at a time per commit, so an older evaluation can't publish over a newer one. A queued +# run is replaced by a newer one for the same commit, which is fine: each run reads the reviews fresh. +concurrency: + group: code-owner-approval-${{ github.event.pull_request.head.sha || github.event.workflow_run.head_sha || 'all' }} + +permissions: + statuses: write + pull-requests: read + contents: read + +jobs: + evaluate: + runs-on: ubuntu-latest + steps: + - uses: DTTerastar/code-owner-approval@v1 diff --git a/.github/workflows/code-owner-review.yml b/.github/workflows/code-owner-review.yml new file mode 100644 index 0000000..579bde6 --- /dev/null +++ b/.github/workflows/code-owner-review.yml @@ -0,0 +1,16 @@ +name: Code owner review + +# Reviews have no pull_request_target event, so this only starts a workflow_run of +# "Code owner approval", which runs the default branch's copy. No permissions, no code. + +on: + pull_request_review: + types: [submitted, edited, dismissed] + +permissions: {} + +jobs: + relay: + runs-on: ubuntu-latest + steps: + - run: echo "Review on PR ${{ github.event.pull_request.number }}, Code owner approval re-checks it"