Skip to content

Commit b73b6c0

Browse files
committed
chore: merge develop into douglashunley/indata-520-create-a-supabase-nix-pkg-for-pgbackrest
* origin/develop: (26 commits) chore(nix): remove LLVM JIT support from postgresql build (#2296) fix: cover pg_cron legacy extversion strings with alignment migration and alias scripts (#2300) docs: commit supabase/postgres's CLAUDE.md (#2395) ansible: Setup swap in stage2 not stage1 (#2381) ci: install AMI postgres profile via nix-env --set (#2309) images: clean up nix at end of process (#2393) ansible: Stop compiling binaries (#2382) Report final AMI disk usage to workflow job (#2384) Re-organize build scripts, add to shellcheck (#2380) feat: Do not hardcode `orioledb.main_buffers` in `postgresql.conf` (#2365) feat: add orioledb debug symbols (#2379) chore: Make postgresql.env optional in database-optimizations.service (#2372) feat: bump to PostgREST v14.17 (#2374) ansible: Bump versions to get new AMIs built (#2376) Revert PostgREST bump to v14.17 (#2371) fix: disable APT timers during Supabase upgrades (#2358) gha/nix-install-ephemeral: Actually copy to s3, not just echo it (#2369) feat: bump to PostgREST v14.17 (#2363) feat: add guest-to-host time synchronisation (#2364) ci: Add final job that depends on the important jobs (#2361) ...
2 parents 5a3ae34 + 7062afa commit b73b6c0

72 files changed

Lines changed: 1797 additions & 1456 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.github/actions/build-ami/action.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,9 @@ outputs:
3737
execution_id:
3838
description: 'The execution ID for this build'
3939
value: ${{ steps.set-execution-id.outputs.execution_id }}
40+
disk_usage_json:
41+
description: 'The stage 2 AMI root disk usage as json'
42+
value: ${{ steps.build-stage2.outputs.disk_usage_json }}
4043

4144
runs:
4245
using: "composite"

.github/actions/nix-install-ephemeral/setup-nix.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ if systemctl whoami &>/dev/null || [[ $(uname) == Darwin ]]; then
1212
tmpdir=$(mktemp -d)
1313
trap 'cd; rm -rf $tmpdir' EXIT
1414

15-
function maybesudo { sudo -E env "$@"; }
15+
function maybesudo { sudo -EH env "$@"; }
1616
else
1717
# systemd is *not* running so we must install in single-user mode
1818
daemon=--no-daemon

.github/actions/nix-install-ephemeral/setup-push.sh

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ cat >"$NIXCONFDIR/upload-to-cache.sh" <<-EOF
2828
fi
2929
3030
export IFS=' '
31-
echo $NIXBINDIR/nix copy --max-jobs 5 --to 's3://nix-postgres-artifacts?secret-key=$NIXCONFDIR/nix-secret-key' \$OUT_PATHS
31+
$NIXBINDIR/nix copy --max-jobs 5 --to 's3://nix-postgres-artifacts?secret-key=$NIXCONFDIR/nix-secret-key' \$OUT_PATHS
3232
EOF
3333
chmod 755 "$NIXCONFDIR/upload-to-cache.sh"
3434

.github/workflows/check-shellscripts.yml

Lines changed: 0 additions & 33 deletions
This file was deleted.

.github/workflows/nix-build.yml

Lines changed: 55 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,31 @@ concurrency:
2020

2121
jobs:
2222
nix-eval:
23-
uses: ./.github/workflows/nix-eval.yml
24-
secrets:
25-
DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }}
26-
NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }}
23+
runs-on: blacksmith-32vcpu-ubuntu-2404
24+
outputs:
25+
packages_matrix: ${{ steps.gen-matrix.outputs.packages_matrix }}
26+
checks_matrix: ${{ steps.gen-matrix.outputs.checks_matrix }}
27+
steps:
28+
- name: Checkout Repo
29+
uses: actions/checkout@8e8c483db84b4bee98b60c0593521ed34d9990e8 # v6.0.1
30+
31+
- name: Install nix
32+
uses: ./.github/actions/nix-install-ephemeral
33+
with:
34+
push-to-cache: true
35+
nix-signing-key: ${{ secrets.NIX_SIGN_SECRET_KEY }}
36+
role-to-assume: ${{ secrets.DEV_AWS_ROLE }}
37+
38+
- name: Generate Nix Matrix
39+
id: gen-matrix
40+
run: |
41+
set -Eeu -o pipefail
42+
nix run --accept-flake-config .\#github-matrix -- checks legacyPackages
43+
44+
sudo systemctl stop nix-daemon.socket || true
45+
sudo systemctl stop nix-daemon.service || true
46+
sudo pkill -9 nix-daemon || true
47+
sleep 2
2748
2849
nix-build-packages-aarch64-linux:
2950
name: >-
@@ -202,6 +223,20 @@ jobs:
202223
with:
203224
attr: .#${{ matrix.attr }}
204225

226+
nix-build-checks:
227+
name: Nix Checks ✅
228+
runs-on: blacksmith-2vcpu-ubuntu-2404
229+
needs:
230+
- nix-build-checks-aarch64-darwin
231+
- nix-build-checks-aarch64-linux
232+
- nix-build-checks-x86_64-linux
233+
steps:
234+
- name: Check dependent job results
235+
if: contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped')
236+
run: |
237+
jq -rn --argjson needs '${{ toJSON(needs) }}' '$needs|to_entries[]|select(.value.result!="success")|"::error::"+.key+": "+.value.result'
238+
exit 1
239+
205240
run-testinfra:
206241
needs:
207242
- nix-eval
@@ -227,3 +262,19 @@ jobs:
227262
secrets:
228263
DEV_AWS_ROLE: ${{ secrets.DEV_AWS_ROLE }}
229264
NIX_SIGN_SECRET_KEY: ${{ secrets.NIX_SIGN_SECRET_KEY }}
265+
266+
nix-ci-check:
267+
name: Nix CI ✅
268+
if: always()
269+
runs-on: blacksmith-2vcpu-ubuntu-2404
270+
needs:
271+
- docker-image-test
272+
- nix-build-checks
273+
- run-testinfra
274+
- run-tests
275+
steps:
276+
- name: Check dependent job results
277+
if: contains(needs.*.result, 'cancelled') || contains(needs.*.result, 'failure') || contains(needs.*.result, 'skipped')
278+
run: |
279+
jq -rn --argjson needs '${{ toJSON(needs) }}' '$needs|to_entries[]|select(.value.result!="success")|"::error::"+.key+": "+.value.result'
280+
exit 1

.github/workflows/nix-eval.yml

Lines changed: 0 additions & 42 deletions
This file was deleted.

.github/workflows/publish-nix-pgupgrade-scripts.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ on:
88
paths:
99
- '.github/workflows/publish-nix-pgupgrade-scripts.yml'
1010
- 'ansible/vars.yml'
11+
- 'ansible/files/admin_api_scripts/pg_upgrade_scripts/**'
1112
workflow_dispatch:
1213
inputs:
1314
postgresVersion:

.github/workflows/testinfra-ami-build.yml

Lines changed: 47 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ env:
1919
AWS_REGION: ap-southeast-1
2020

2121
jobs:
22-
prepare:
22+
gen-matrix:
2323
runs-on: blacksmith-2vcpu-ubuntu-2404
2424
outputs:
2525
postgres_versions: ${{ steps.set-versions.outputs.postgres_versions }}
@@ -37,11 +37,11 @@ jobs:
3737
echo "postgres_versions=$VERSIONS" >> "$GITHUB_OUTPUT"
3838
3939
test-ami-nix:
40-
needs: prepare
40+
needs: gen-matrix
4141
strategy:
4242
fail-fast: false
4343
matrix:
44-
postgres_version: ${{ fromJson(needs.prepare.outputs.postgres_versions) }}
44+
postgres_version: ${{ fromJson(needs.gen-matrix.outputs.postgres_versions) }}
4545
target:
4646
- arch: amd64
4747
instance_type: c6i.4xlarge
@@ -100,20 +100,35 @@ jobs:
100100
postgres_version: ${{ matrix.postgres_version }}
101101
region: ${{ env.AWS_REGION }}
102102

103-
- run: docker context create builders
104-
105-
- uses: docker/setup-buildx-action@8d2750c68a42422c14e847fe6c8ac0403b4cbd6f # v3.12.0
103+
- name: Save AMI disk usage
104+
env:
105+
ARCH: ${{ matrix.target.arch }}
106+
DISK_USAGE_JSON: ${{ steps.build-ami.outputs.disk_usage_json }}
107+
POSTGRES_VERSION: ${{ matrix.postgres_version }}
108+
run: >-
109+
jq -cnr
110+
--arg arch "$ARCH"
111+
--arg version "$POSTGRES_VERSION"
112+
--argjson disk_usage "$DISK_USAGE_JSON"
113+
'{$version,$arch,bytes:$disk_usage.bytes,human:$disk_usage.human}'
114+
>"ami-disk-usage-$POSTGRES_VERSION-$ARCH.json"
115+
116+
- name: Upload AMI disk usage
117+
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
106118
with:
107-
endpoint: builders
119+
name: ami-disk-usage-${{ matrix.postgres_version }}-${{ matrix.target.arch }}
120+
path: ami-disk-usage-*.json
121+
overwrite: true
122+
retention-days: 1
108123

109124
- name: Run tests
110125
timeout-minutes: 10
111126
env:
112127
AMI_ID: ${{ steps.build-ami.outputs.stage2_ami_id }}
113128
EXECUTION_ID: ${{ steps.build-ami.outputs.execution_id }}
114129
run: |
115-
# TODO: use poetry for pkg mgmt
116-
pip3 install boto3 "boto3-stubs[essential]" docker ec2instanceconnectcli pytest "pytest-testinfra[paramiko,docker]" requests
130+
# TODO: use uv for pkg mgmt
131+
pip3 install boto3 'boto3-stubs[essential]' ec2instanceconnectcli pytest 'pytest-testinfra[paramiko]' requests
117132
pytest -vv -s testinfra/test_ami_nix.py
118133
119134
- name: Cleanup resources on build cancellation
@@ -173,3 +188,26 @@ jobs:
173188
else
174189
echo "No stage 2 AMI to clean up"
175190
fi
191+
192+
report-disk-usage:
193+
needs: test-ami-nix
194+
runs-on: blacksmith-2vcpu-ubuntu-2404
195+
steps:
196+
- name: Download AMI disk usage
197+
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # v4.3.0
198+
with:
199+
pattern: ami-disk-usage-*
200+
path: ami-disk-usage
201+
merge-multiple: true
202+
203+
- name: Report AMI disk usage
204+
run: |
205+
cat <<EOF >>"$GITHUB_STEP_SUMMARY"
206+
### AMI Root Disk Usage
207+
208+
| Version | Arch | Human | Bytes |
209+
| ------- | ---- | ----- | ----- |
210+
EOF
211+
cat ami-disk-usage/ami-disk-usage-*.json |
212+
sort -V |
213+
jq -rs '.[]|{version,arch,human,bytes}|"| \(join("|")) |"' >>"$GITHUB_STEP_SUMMARY"

CLAUDE.md

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
# CLAUDE.md
2+
3+
Guidance for Claude Code sessions working in this repo.
4+
5+
## Repo identity — do not confuse with the upstream mirror
6+
7+
This is **`supabase/postgres`**: Supabase's own build/packaging repo for its
8+
PostgreSQL distribution. It does **not** contain a fork of PostgreSQL's C
9+
source.
10+
11+
## What this repo is
12+
13+
A batteries-included PostgreSQL distribution: unmodified upstream PostgreSQL
14+
(15, 17, and an `orioledb-17` fork) plus a large curated set of pre-built
15+
extensions (see the extension tables in `README.md`). It produces three
16+
release artifacts from one source tree:
17+
18+
1. **Docker images** (`Dockerfile-15`, `Dockerfile-17`, `Dockerfile-supabase`,
19+
`Dockerfile-multigres`) — used by local dev / the Supabase CLI.
20+
2. **AWS AMIs** — the production Supabase-hosted Postgres image, built via
21+
Nix + Packer + Ansible.
22+
3. **Nix packages**`nix build .#psql_15.bin` etc., the underlying build
23+
system both other artifacts consume.
24+
25+
The project is mid-migration from a pure Dockerfile-based extension build
26+
(what `CONTRIBUTING.md` still documents) to a Nix-based one (what `README.md`
27+
and `nix/docs/` describe as current). When the two disagree, trust `nix/`
28+
and `nix/docs/``CONTRIBUTING.md`'s Dockerfile-stage workflow is legacy for
29+
extensions not yet ported.
30+
31+
## Directory structure
32+
33+
| Path | Purpose |
34+
|---|---|
35+
| `nix/` | Core build system (flake-parts modules). `nix/postgresql/` = PG version configs/patches; `nix/ext/` = one file per extension package; `nix/config.nix` = pinned PG versions/hashes per major (source of truth for "what version are we on"); `nix/tests/` = pg_regress + smoke + migration NixOS tests; `nix/docs/` = the real developer docs (start here, not README) |
36+
| `ansible/` | Config management for the production AMI. `ansible/playbook.yml` = main playbook (Postgres/PostgREST/pgbouncer/Auth); `ansible/vars.yml` = **source of truth for AMI version tracking** (`postgres_release`, Docker release matrix); `ansible/files/postgresql_config/postgresql.conf.j2` = the actual GUC defaults shipped to customers |
37+
| `migrations/db/` | SQL migrations and `init-scripts/` (what every new project's schema starts with — default-enabled extensions, roles) |
38+
| `migrations/tests/extensions/` | pgTAP tests, one per extension, run via `pg_prove` against a Nix-built Postgres as part of `nix flake check` (`nix/checks.nix`) — not against a Docker image |
39+
| `docker/`, `Dockerfile-*` | Container image definitions (`Dockerfile-supabase` is the version-parameterized base; `Dockerfile-multigres` layers `pgctld` + `pgbackrest` on top) |
40+
| `ebssurrogate/`, `*.pkr.hcl` | Packer/EBS-surrogate AMI build pipeline |
41+
| `testinfra/` | pytest suite (`test_ami_nix.py`) that runs against a live AMI/instance |
42+
| `audit-specs/` | CIS-benchmark-style compliance specs run against built images |
43+
| `docs/plans/` | Design docs for in-flight features (profiler, pgbackrest, etc.) |
44+
| `.claude/skills/pg-security-release-analysis/` | Skill for triaging upstream PG quarterly security releases into a CVE/impact catalog — see below |
45+
46+
## Building and testing
47+
48+
Exact commands verified against `nix/docs/build-postgres.md`,
49+
`nix/docs/development-workflow.md`, and `CONTRIBUTING.md`. Read `nix/docs/README.md`
50+
first — it's the doc index and points to the specific runbook you need
51+
(adding a package, updating an extension, testing migrations, new major PG
52+
version, etc.) rather than duplicating them here.
53+
54+
```bash
55+
# Build a full PG install (binaries + all extensions) locally via Nix
56+
nix build .#psql_15.bin # or psql_17, psql_orioledb-17
57+
58+
# Full flake check (nix eval + pg_regress + migration tests)
59+
nix flake check -L
60+
nix build .#checks.aarch64-darwin.psql_17 -L # one target/platform only
61+
62+
# Docker images
63+
docker build -f Dockerfile-15 -t supabase-postgres:15 .
64+
docker build -f Dockerfile-supabase --build-arg PG_VERSION=17 -t supabase-postgres:17 .
65+
docker build -f Dockerfile-multigres --build-arg SUPABASE_IMAGE=supabase-postgres:17 -t multigres:17 .
66+
67+
# Remote build/cache + AMI build + testinfra (needs aws-vault; see
68+
# nix/docs/development-workflow.md for the full loop)
69+
nix run .#trigger-nix-build
70+
aws-vault exec <profile> -- nix run .#build-test-ami 17
71+
nix run .#run-testinfra -- --aws-vault-profile <profile> --ami-name <ami-name>
72+
```
73+
74+
Formatting/lint is `treefmt` (nixfmt + deadnix), wired as a git-hooks.nix
75+
pre-commit hook when using `nix develop`/direnv; also enforced in CI, so
76+
`nix flake check` catches format drift even without the hook installed.
77+
78+
## Non-obvious conventions and gotchas
79+
80+
- **Version pinning**: `nix/config.nix` pins the exact upstream PG version +
81+
source hash per major (`supabase.supportedPostgresVersions`). `ansible/vars.yml`
82+
(`postgres_release`) separately pins the *packaged* version string used for
83+
Docker/AMI tags — the two numbers look similar but serve different layers
84+
(Nix build input vs. release artifact tag); update both when bumping a PG
85+
minor.
86+
- **Adding a new extension**: two documented paths depending on era —
87+
`nix/docs/adding-new-package.md` (current, Nix-based: one file in `nix/ext/`)
88+
vs. `CONTRIBUTING.md` (legacy, Dockerfile multi-stage build + `checkinstall`
89+
into a `.deb`, then copied into the `extensions` stage). Check whether the
90+
extension already has sibling packages under `nix/ext/` before following
91+
the Dockerfile path.
92+
- **orioledb-17 is a separate PG fork**, not just another extension —
93+
security/behavior analysis needs to check whether a finding applies to
94+
vanilla 17, orioledb-17, or both.
95+
- **Multi-version extensions**: some extensions (e.g. `pg_repack`) ship
96+
multiple versions side-by-side in the same install (`pg_repack-1.4.8`,
97+
`pg_repack-1.5.2`, ...) with `switch_<ext>_version` wrapper scripts to pick
98+
one at runtime — don't assume one binary name per extension.
99+
- **`shared_preload_libraries`** (every project's postmaster preloads these)
100+
and **default-enabled extensions** (every project's initial schema) are two
101+
different, smaller lists than "everything in `nix/ext/`" — see
102+
`ansible/files/postgresql_config/postgresql.conf.j2` and
103+
`migrations/db/init-scripts/00000000000000-initial-schema.sql` respectively
104+
before assuming a change affects every customer project.
105+
- **`.claude/skills/pg-security-release-analysis/`**: run this when triaging a
106+
new upstream PG quarterly security release. It has its own gotchas baked
107+
in (e.g. `git log --grep` doesn't tell you what version a fix first landed
108+
in — use `git tag --contains`; CVE severity in commit messages can diverge
109+
from postgresql.org's canonical security page) and a Supabase-specific
110+
"surface map" (which roles, extensions, and services — wal-g, PostgREST,
111+
Realtime, pgbouncer — are affected by which class of upstream change).
112+
- Docs inside `nix/docs/` have previously gone stale relative to actual repo
113+
structure (see commit `2678fc8c docs: fix stale docs`) — if a doc and the
114+
actual `nix/` layout disagree, trust the code.

0 commit comments

Comments
 (0)