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
21 changes: 21 additions & 0 deletions .github/workflows/governance-drift.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
name: Governance drift

on:
schedule:
- cron: '23 3 * * 1'
workflow_dispatch:

permissions:
contents: read

jobs:
drift:
name: drift
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Compare the twin repositories
run: sh pr-governance/scripts/check-twin-drift.sh
1 change: 1 addition & 0 deletions VERSION
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
3
19 changes: 16 additions & 3 deletions pr-governance/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ A pull request may merge when all of these hold:
Branch protection, not this action, is the merge constraint. The action only
publishes evidence; it cannot merge, label, or write repository contents.

The gate applies to repositories that build, deploy or run code. A repository
that only publishes a static site through a `pages` workflow keeps that
deployment workflow and is exempt from the gate.

## Risk tiers

| Tier | Typical paths | Requirement |
Expand Down Expand Up @@ -124,6 +128,15 @@ a fresh review instead of silently reusing one.
## Private repositories

GitHub Free does not provide branch protection or secret scanning for private
repositories, and hosted Actions may be billing-blocked. Use the local track:
the same policy file, a pre-push hook and `scripts/local` commands recording
the same receipt and scan results locally. See `docs/private-repositories.md`.
repositories, and hosted Actions may be billing-blocked. Private repositories
use a local enforcement track instead: Git hooks that reject staged credentials,
unconventional commit headers, direct pushes to a protected branch, and
non-fast-forward pushes, plus an audit over the tracked tree.


## Twin repositories

`pr-governance/` is byte-identical in `Pigbibi/governance`, `GdeiAssistant/.github`
and `QuantStrategyLab/.github`; `VERSION` names the shared revision. Each
repository runs `scripts/check-twin-drift.sh` weekly and on demand. A change to
any shared file is applied to all three before the drift check can pass.
34 changes: 34 additions & 0 deletions pr-governance/scripts/check-twin-drift.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#!/bin/sh
# Compare the shared governance content across the three twin repositories.
set -eu

REPOS="Pigbibi/governance GdeiAssistant/.github QuantStrategyLab/.github"
base=$(cd "$(dirname "$0")/../.." && pwd)
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' EXIT
status=0

for repo in $REPOS; do
slug=$(printf '%s' "$repo" | tr '/' '_')
mkdir -p "$tmp/$slug"
archive="$tmp/$slug.tar.gz"
if ! curl --fail --silent --show-error --location --retry 2 \
"https://codeload.github.com/$repo/tar.gz/refs/heads/main" --output "$archive"; then
echo "cannot download $repo" >&2
status=1
continue
fi
if ! tar -xzf "$archive" -C "$tmp/$slug" --strip-components=1; then
echo "cannot extract $repo" >&2
status=1
continue
fi
for path in pr-governance VERSION; do
if ! diff -ru -x '__pycache__' "$base/$path" "$tmp/$slug/$path"; then
echo "drift: $path differs from $repo" >&2
status=1
fi
done
done

exit $status
Loading