Contents
CI Instructions
Reducing CI wall-clock time
Don’t chase this proactively – it’s not worth adding real complexity for. But if a simple latency win is available while touching a job anyway, take it. Facts and constraints to reason from:
- GitHub Actions steps within one job are strictly sequential. There is no native
“run step A and step B concurrently” mechanism. The only real unit of parallelism is the
job (already exploited here via the
pg/matrix-leg lists) – reordering two independent steps changes nothing about total wall-clock time unless one of them is actually backgrounded (cmd &…wait) within a single step’s shell script. pg-start VERSIONis not a no-op or a “wait for something already running.” It installs that PostgreSQL major version viaapt.postgresql.org.sh(network + package install) and then creates and starts the “test” cluster (pg_createcluster --start) – both genuinely slow, and both block until done, like everyrun:step.- Backgrounding a step next to
pg-start(or anyapt-get install) is NOT safe by default: apt/dpkg serialize on a lock file, so a second concurrentapt-get installwould either fail immediately or block waiting for the lock – effectively serializing anyway, but now with added flakiness risk. Only background work that doesn’t touch the package manager (e.g. agit clone, or a build step that’s puregmake/gccagainst already-installed headers) alongside an apt-based step. - A genuine, low-complexity candidate, if this is ever worth doing:
pg-tle-test’s “Install pgtap” step (make pgtap, which builds pgTAP viagmake/gcc, not apt) and its “Build and install pg_tle” step (git clone+make, also not apt) are mutually independent – neither depends on the other’s output. Backgrounding one (make pgtap &) while the other runs, thenwaiting for it before the step that needs pgtap, would overlap two of the job’s slower operations. This is a small, contained change (one background job, onewait, one exit-code check) – not the kind of complexity worth avoiding on principle. actions/cacheis likely a better lever than backgrounding. pg_tle is rebuilt from source (git clone + C compile) fresh in everypg-tle-testmatrix entry and on both the old and new cluster in everypg-tle-upgrade-testleg – the same pg_tle version, rebuilt repeatedly across runs with nothing changed. Caching the builtpg_tle.so+ control/SQL files (keyed on PG major version +PG_TLE_RELEASE) would skip the clone+compile entirely on a cache hit, without touching the job’s logic at all. Worth trying before hand-rolled parallelism if CI time on the pg_tle jobs becomes a real pain point.- Double-run check: this repo’s
push:trigger is scoped tobranches: [master](not a bareon: [push, pull_request]), so pushes to a feature/PR branch only fire thepull_requestevent, not both – confirmed via run history, no double-run here. If this workflow’s triggers are ever changed, re-verify that scoping is preserved; an unscopedpush:trigger would double-run CI on every PR-branch commit.
Docs-only pushes and “what was actually tested”
A docs-only push makes the heavy jobs report “skipped” for THAT commit, which is correct (the
code didn’t change) but easy to misread on the PR’s Checks tab as “never tested.” The changes
job’s “Find the last commit where real code changed” step handles this: it walks backward
through history to the newest commit that actually changed code, looks up that commit’s CI run,
and all-checks-passed reports it (link + green/red) in its step summary – or explicitly notes
when the entire PR has never touched anything but docs. Don’t assume “skipped” means “untested”
without checking that summary first.
pull_request_target workflows can’t be tested from the PR that changes them
GitHub always executes the workflow FILE for a pull_request_target event from the BASE
branch (master), never the PR’s own version – a deliberate security control so a fork PR can’t
alter its own reviewer’s permissions/behavior. claude-code-review.yml runs this way. Practical
consequence: a PR that changes that file (e.g. adjusting its permissions: block) cannot prove
the change took effect by watching that PR’s own claude-review check – it’s still running
master’s old version. Verify changes to that file only after merging to master, on the next PR.
Where CI-only shell logic lives
.github/scripts/ holds shell scripts that are only meaningful inside a CI job (e.g.
pg_upgrade_cluster, which drives pg_ctlcluster/pg_createcluster/pg_upgrade against the
pgxn-tools image’s “test” cluster convention – not something a developer would run locally).
This is distinct from the repo-root bin/ scripts (bin/test_existing, bin/assert_fs_clean),
which a developer CAN run locally against a scratch database and are also usable outside CI.
When adding a new shared CI shell helper, put it in .github/scripts/ if it’s CI-only, bin/
if it’s usable locally too.