From 18e54a202b84f1640815dc98e82ef5999d903129 Mon Sep 17 00:00:00 2001
From: DTTerastar
Date: Fri, 6 Nov 2026 11:00:47 -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"