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
5 changes: 5 additions & 0 deletions .github/workflows/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,11 @@ self-hosted NixOS runner. Installs `pg_stat_statements`, then
`pgFirstAid.sql` + `view_pgFirstAid_managed.sql`, runs the pytest
integration suite, and finishes with `seed_and_validate.py --managed`.

Fork pull requests skip the privileged job before runner assignment
because the job-level guard evaluates in the base workflow file; only
same-repository pull requests and owner-triggered `workflow_dispatch`
runs reach the self-hosted runner and the Neon secrets.

Required secrets (one set per PG version):
`PG{15,16,17,18}_{HOST,PORT,USER,PASSWORD,DATABASE}`.

Expand Down
15 changes: 9 additions & 6 deletions .github/workflows/neon-before-after-validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,15 +39,14 @@
# (b) leave it blank and apply changes outside this workflow
# (you only need the pre- and post- comparison jobs).
#
# Note: pull_request from forks gets no repo secrets. Fork PRs fail at
# "Create Neon branch". That is the intended safe failure mode.
# Note: fork pull requests skip the privileged job before runner assignment.
# Maintainers can validate a fork PR by running workflow_dispatch manually,
# or by pushing the change to a same-repo branch first.

name: Neon Before/After Validation

on:
pull_request:
pull_request_target:
paths:
- 'migrations/**'
- 'pgFirstAid.sql'
Expand Down Expand Up @@ -75,6 +74,9 @@ env:
jobs:
before-after-validation:
name: Before/After Health Validation
if: >-
github.event_name != 'pull_request_target' ||
github.event.pull_request.head.repo.full_name == github.repository
runs-on: [self-hosted, nix, nixos, x86_64-linux]
timeout-minutes: 20
permissions:
Expand All @@ -90,7 +92,8 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 1
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.ref }}

- name: Add Nix profile paths
run: |
Expand Down Expand Up @@ -174,7 +177,7 @@ jobs:
echo " Pre-change baseline captured above."
echo ""
echo " The change being tested:"
echo " ${{ github.event_name == 'pull_request' && format('PR #{0}', github.event.number) || 'manual dispatch' }}"
echo " ${{ github.event_name == 'pull_request_target' && format('PR #{0}', github.event.number) || 'manual dispatch' }}"
echo ""
echo " Now applying SQL changes..."
echo ""
Expand Down Expand Up @@ -251,7 +254,7 @@ jobs:
fi

- name: Post PR comment
if: ${{ github.event_name == 'pull_request' }}
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/github-script@v7
with:
script: |
Expand Down
12 changes: 8 additions & 4 deletions .github/workflows/neon-integration-pg-matrix.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@
# PG17_HOST, PG17_PORT, PG17_USER, PG17_PASSWORD, PG17_DATABASE
# PG18_HOST, PG18_PORT, PG18_USER, PG18_PASSWORD, PG18_DATABASE
#
# Note: pull_request from forks gets no repo secrets. Fork PRs fail at
# "Validate required PG env vars". Maintainers can validate by pushing
# the change to a same-repo branch first.
# Note: fork pull requests skip the privileged job before runner assignment.
# Maintainers can validate a fork PR by running workflow_dispatch manually,
# or by pushing the change to a same-repo branch first.

name: Neon Integration (PG15-PG18)

on:
workflow_dispatch:
pull_request:
pull_request_target:
Comment thread
randoneering marked this conversation as resolved.
types: [opened, synchronize]
paths:
- pgFirstAid.sql
Expand All @@ -35,6 +35,9 @@ concurrency:

jobs:
integration:
if: >-
github.event_name != 'pull_request_target' ||
github.event.pull_request.head.repo.full_name == github.repository
runs-on: [self-hosted, nix, nixos, x86_64-linux]
permissions:
contents: read
Expand Down Expand Up @@ -109,6 +112,7 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.ref }}

- name: Add Nix profile paths
Expand Down
20 changes: 10 additions & 10 deletions .github/workflows/nixos-local-test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
# instances your secrets point at (Neon / DigitalOcean / etc.).
#
# Triggers:
# - pull_request [opened, synchronize]: full matrix on PG15-18. Fork PRs
# get no secrets, so they fail at env validation. That's the point.
# - pull_request_target [opened, synchronize]: full matrix on PG15-18.
# Fork PRs skip the privileged job before runner assignment.
# - workflow_dispatch: pick a PG version and cloud_provider label.
#
# The NixOS runner already has psql, uv, and network access to the test PG
Expand Down Expand Up @@ -41,7 +41,7 @@ on:
- gcp
- azure
default: 'direct'
pull_request:
pull_request_target:
types: [opened, synchronize]
paths:
- pgFirstAid.sql
Expand All @@ -57,14 +57,13 @@ concurrency:

jobs:
local-test:
if: >-
github.event_name != 'pull_request_target' ||
github.event.pull_request.head.repo.full_name == github.repository
runs-on: [self-hosted, nix, nixos, x86_64-linux]
# No job-level `if:`. The original conditional referenced
# `matrix.postgres_version` which is only valid in the strategy scope
# (after matrix evaluation), not at the job level. GitHub Actions
# rejects the workflow with "Unrecognized named-value: 'matrix'."
# The PR validation pass runs the full matrix unconditionally on
# pull_request; the workflow_dispatch path's per-version selection
# is handled by the strategy below.
# Skip fork pull requests before assigning a persistent self-hosted
# runner. The PR validation pass runs the full matrix for trusted PRs;
# the workflow_dispatch path's per-version selection is handled below.
permissions:
contents: read
concurrency:
Expand Down Expand Up @@ -126,6 +125,7 @@ jobs:
uses: actions/checkout@v4
with:
fetch-depth: 1
persist-credentials: false
ref: ${{ github.event.pull_request.head.sha || github.ref }}

- name: Add Nix profile paths
Expand Down
42 changes: 42 additions & 0 deletions .github/workflows/pr-safe-checks.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
name: PR Safe Checks

on:
pull_request:
types: [opened, synchronize, reopened]

permissions:
contents: read

jobs:
safe-checks:
name: PR Safe Checks
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout PR head
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ github.event.pull_request.head.sha }}
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
version: "0.12.9"
checksum: "ec7a99cd05e0cd7f80243f135ce1361c76835cb0ee60055d14d20eba8eba1460"
enable-cache: true

- name: Sync dependencies
run: uv sync --frozen

- name: Run pure contract tests
run: |
uv run pytest -q \
testing/test_workflow_security.py \
testing/integration/tests/integration/test_pgtap_suite.py::test_every_health_check_has_pgtap_coverage \
testing/integration/tests/integration/test_pgtap_suite.py::test_both_view_sql_files_cover_all_health_checks
66 changes: 66 additions & 0 deletions .github/workflows/pr-workflow-guard.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
name: Workflow Security Guard

on:
pull_request_target:
types: [opened, synchronize, reopened]

permissions:
contents: read

jobs:
workflow-security:
name: Workflow Security Guard
runs-on: ubuntu-latest
timeout-minutes: 10
steps:
- name: Checkout base
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
persist-credentials: false

- name: Set up Python
uses: actions/setup-python@f677139bbe7f9c59b41e40162b753c062f5d49a3 # v5.2.0
with:
python-version: "3.11"

- name: Install uv
uses: astral-sh/setup-uv@c771a70e6277c0a99b617c7a806ffedaca235ff9 # v9.0.0
with:
version: "0.12.9"
checksum: "ec7a99cd05e0cd7f80243f135ce1361c76835cb0ee60055d14d20eba8eba1460"
enable-cache: true

- name: Sync dependencies
run: uv sync --frozen

- name: Fetch PR workflow files as data
env:
GH_TOKEN: ${{ github.token }}
HEAD_REPO: ${{ github.event.pull_request.head.repo.full_name }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
set -euo pipefail
mkdir -p /tmp/pr-workflows /tmp/pr-distributed
for f in \
pr-safe-checks.yml \
pr-workflow-guard.yml \
neon-before-after-validate.yml \
neon-integration-pg-matrix.yml \
nixos-local-test.yml; do
gh api \
"repos/${HEAD_REPO}/contents/.github/workflows/${f}?ref=${HEAD_SHA}" \
--jq .content | base64 -d > "/tmp/pr-workflows/${f}"
done
gh api \
"repos/${HEAD_REPO}/contents/workflows/neon-before-after-validate.yml?ref=${HEAD_SHA}" \
--jq .content | base64 -d > /tmp/pr-distributed/neon-before-after-validate.yml

- name: Overlay PR YAML for verifier
run: |
set -euo pipefail
cp /tmp/pr-workflows/*.yml .github/workflows/
mkdir -p workflows
cp /tmp/pr-distributed/neon-before-after-validate.yml workflows/neon-before-after-validate.yml

- name: Run trusted verifier
run: uv run pytest -q testing/test_workflow_security.py
2 changes: 1 addition & 1 deletion .github/workflows/release-drafter.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
permissions:
contents: write
pull-requests: write
runs-on: [self-hosted, nix, nixos, x86_64-linux]
runs-on: ubuntu-latest
steps:
- uses: release-drafter/release-drafter@v5
env:
Expand Down
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ AGENTS.md
CLAUDE.md

# Local docs
docs/superpowers/plans/
docs/superpowers/

# Python
__pycache__/
Expand Down
Loading
Loading