CI: binary pg_upgrade testing, docs-only gate, single-source PG matrix - #23
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Organization UI Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
- test job: `make verify-results` alone races install vs installcheck under this container's ambient parallel make (they're independent prerequisites of the same `test` target) -- pg_regress could start, and fail with "extension ... is not available", before install's file copy finished. Split into two separate `make` invocations, which can't race with each other. Reproduced the failure mode's shape locally (though not the race itself -- couldn't get this container's make to lose the race on demand) and confirmed the two-step form still passes. - pg-upgrade-test job: never installed pgtap system-wide on either cluster. It worked by accident in local dry-runs only because this dev container already had pgtap installed for some PG majors from earlier testing -- confirmed by deliberately clearing /usr/share/postgresql/16/extension/ (a major this container had never used) and re-running the full recreate-old -> prepare-old -> pg_upgrade -> run-suite cycle end to end: it failed the same way PR Postgres-Extensions#23's CI did ("extension pgtap is not available"), then passed once both `pgxn install pgtap --sudo --pg_config ...` steps were added (old cluster before prepare-old, new cluster before its make install -- pg_upgrade itself needs pgtap available on the new cluster too, not just post-upgrade). --pg_config is explicit on both, not left to rely on pg-start's PATH-switching, since that's exactly the kind of ambient-state assumption that already broke once in this same job. Verified locally end-to-end (real pg_ctlcluster/pg_createcluster/pg_upgrade, not just make test): old=12/new=16, a pair this container had never exercised before, all the way through bin/test_existing run-suite with zero raw "not ok" TAP lines. Also re-confirmed plain `make test` still passes on PG12 and PG17 after these changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
|
First CI run failed everywhere (all 7 PG-matrix jobs + both pg_upgrade legs). Root-caused and fixed in 812e493:
Both fixes verified locally end-to-end (real |
…rim comments CI (.github/workflows/ci.yml): pg-build-test's own failure detection (`make installcheck || status=$?`) can never actually trip -- pgxntool marks `installcheck` .IGNORE, so `make installcheck` always exits 0 regardless of real regression failures (verified locally with a deliberately broken test). Confirmed from pg-build-test's actual source (pgxn/docker-pgxn-tools bin/pg-build-test): `make all; sudo make install; make installcheck || status=$?` -- it never calls `make test` either, so test-build was never reachable through it regardless. Replaced with a direct `make verify-results`, which inspects the real TAP output instead of trusting an exit code, and pulls in test-build via the same `test` dependency chain it already runs. Confirmed locally (4 repeated runs) that a single `make verify-results` with no separate `make install` first is deterministic once pg-build-test's own `MAKEFLAGS=-j $(nproc)` export is out of the picture -- that export (not anything the container sets globally) was the actual source of the install/installcheck race PR Postgres-Extensions#23 found and worked around; not re-litigating that fix there, just noting root cause now confirmed. test/build/syntax.sql: wrapped the \i calls in BEGIN/ROLLBACK with ON_ERROR_ROLLBACK on, so nothing persists in the database whether this runs under pg_regress or ad hoc locally (previously: autocommit, no rollback, would leave a real mess in a developer's own database). Bonus: running the whole thing as one transaction is also more faithful to how CREATE EXTENSION actually behaves, so `current_setting('..._role')` now correctly survives to the end of each file -- the third known/expected error (SET ROLE "" from the role-restore code) is gone entirely, not just documented away. Regenerated expected output from a real run. Trimmed both test/build/*.sql files' comments substantially and added a one-line cross-reference between them (install.sql tests packaging via a real CREATE EXTENSION; syntax.sql tests raw SQL syntax by bypassing it) -- the previous version buried that distinction in multi-paragraph essays. CLAUDE.md: noted that this PGXN distribution ships two structurally similar extensions (test_factory, test_factory_pgtap) and that the test suite shares infrastructure between them accordingly. Verified on both PG12 and PG17: full make test passes, and a plain `psql -f test/build/syntax.sql` against a scratch database leaves zero test_factory objects behind afterward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The previous commit (95d8be4) removed this based on local testing that turned out to be invalid: a concurrent process in this dev container had installed PostgreSQL 18, silently shifting the default `pg_config` on PATH out from under an unrelated test, which produced a false "it works without the extra step" result. Re-tested properly (PG_CONFIG pinned to match the actual target cluster, extension deliberately removed from the system first) and found a REAL, pre-existing pgxntool bug, independent of anything in this PR: on a genuinely fresh system, `make test`/`make verify-results` runs the main suite's `installcheck` before `install` ever copies the extension's files into place. Root cause: `TEST_DEPS` textually ends up as `testdeps check-stale-expected test-build install installcheck`, but `check-stale-expected: installcheck` is its own direct dependency edge -- Make resolves that early (2nd in the list), running the main suite against a not-yet-installed extension, well before it ever reaches the literal `install installcheck` pair at the end. `test-build` avoids this by luck, not shared design: it declares its own `test-build: install`, which protects only itself. Filed as Postgres-Extensions/pgxntool-test#62 (not fixed in the vendored copy here). Also corrects the record on PR Postgres-Extensions#23's similar-looking fix: that one attributed the same symptom to "ambient parallel make" from pg-build-test's `MAKEFLAGS=-j $(nproc)` export -- confirmed here, with a plain serial `make -n` dry run (no -j anywhere), that the real cause is this TEST_DEPS ordering issue instead. The fix (explicit `make install` first) happened to be correct either way. Reproduced 3/3 times with the extension deliberately removed from /usr/share/postgresql/*/extension first, and confirmed fixed 3/3 times, on both PG12 and PG17, with PG_CONFIG correctly pinned throughout this time. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
…rim comments CI (.github/workflows/ci.yml): pg-build-test's own failure detection (`make installcheck || status=$?`) can never actually trip -- pgxntool marks `installcheck` .IGNORE, so `make installcheck` always exits 0 regardless of real regression failures (verified locally with a deliberately broken test). Confirmed from pg-build-test's actual source (pgxn/docker-pgxn-tools bin/pg-build-test): `make all; sudo make install; make installcheck || status=$?` -- it never calls `make test` either, so test-build was never reachable through it regardless. Replaced with a direct `make verify-results`, which inspects the real TAP output instead of trusting an exit code, and pulls in test-build via the same `test` dependency chain it already runs. Confirmed locally (4 repeated runs) that a single `make verify-results` with no separate `make install` first is deterministic once pg-build-test's own `MAKEFLAGS=-j $(nproc)` export is out of the picture -- that export (not anything the container sets globally) was the actual source of the install/installcheck race PR Postgres-Extensions#23 found and worked around; not re-litigating that fix there, just noting root cause now confirmed. test/build/syntax.sql: wrapped the \i calls in BEGIN/ROLLBACK with ON_ERROR_ROLLBACK on, so nothing persists in the database whether this runs under pg_regress or ad hoc locally (previously: autocommit, no rollback, would leave a real mess in a developer's own database). Bonus: running the whole thing as one transaction is also more faithful to how CREATE EXTENSION actually behaves, so `current_setting('..._role')` now correctly survives to the end of each file -- the third known/expected error (SET ROLE "" from the role-restore code) is gone entirely, not just documented away. Regenerated expected output from a real run. Trimmed both test/build/*.sql files' comments substantially and added a one-line cross-reference between them (install.sql tests packaging via a real CREATE EXTENSION; syntax.sql tests raw SQL syntax by bypassing it) -- the previous version buried that distinction in multi-paragraph essays. CLAUDE.md: noted that this PGXN distribution ships two structurally similar extensions (test_factory, test_factory_pgtap) and that the test suite shares infrastructure between them accordingly. Verified on both PG12 and PG17: full make test passes, and a plain `psql -f test/build/syntax.sql` against a scratch database leaves zero test_factory objects behind afterward. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The previous commit (95d8be4) removed this based on local testing that turned out to be invalid: a concurrent process in this dev container had installed PostgreSQL 18, silently shifting the default `pg_config` on PATH out from under an unrelated test, which produced a false "it works without the extra step" result. Re-tested properly (PG_CONFIG pinned to match the actual target cluster, extension deliberately removed from the system first) and found a REAL, pre-existing pgxntool bug, independent of anything in this PR: on a genuinely fresh system, `make test`/`make verify-results` runs the main suite's `installcheck` before `install` ever copies the extension's files into place. Root cause: `TEST_DEPS` textually ends up as `testdeps check-stale-expected test-build install installcheck`, but `check-stale-expected: installcheck` is its own direct dependency edge -- Make resolves that early (2nd in the list), running the main suite against a not-yet-installed extension, well before it ever reaches the literal `install installcheck` pair at the end. `test-build` avoids this by luck, not shared design: it declares its own `test-build: install`, which protects only itself. Filed as Postgres-Extensions/pgxntool-test#62 (not fixed in the vendored copy here). Also corrects the record on PR Postgres-Extensions#23's similar-looking fix: that one attributed the same symptom to "ambient parallel make" from pg-build-test's `MAKEFLAGS=-j $(nproc)` export -- confirmed here, with a plain serial `make -n` dry run (no -j anywhere), that the real cause is this TEST_DEPS ordering issue instead. The fix (explicit `make install` first) happened to be correct either way. Reproduced 3/3 times with the extension deliberately removed from /usr/share/postgresql/*/extension first, and confirmed fixed 3/3 times, on both PG12 and PG17, with PG_CONFIG correctly pinned throughout this time. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
946c79a to
9d7d76b
Compare
…trix Implements the remaining CI-structure items from the advanced update+upgrade testing pattern (modeled on Postgres-Extensions/cat_tools's ci.yml/ bin/test_existing and what has landed on its master since), stacked on the foundation from PR Postgres-Extensions#22 (TEST_LOAD_SOURCE, dependency guard, load.sql): - Scope `push` to `branches: [master]`; `pull_request` stays unrestricted -- fixes the double-triggered-CI-on-every-PR-commit bug (test_factory was named as one of the repos still needing this). - Job-level `changes` gate: computes a per-push docs-only diff (fail-safe = not-docs-only as the literal first line) instead of a workflow-level `paths-ignore`, so heavy jobs can skip on doc-only pushes without leaving all-checks-passed stuck Pending. - Single source of truth for the supported-PostgreSQL-major list (NEWEST=17, FLOOR=10, matching the existing matrix), derived once in `changes` and consumed via fromJSON by both the `test` and new `pg-upgrade-test` matrices. - `all-checks-passed` gate, self-checking that its `needs` list matches the actual job set. - New `pg-upgrade-test` job: binary pg_upgrade legs (10->17, 16->17) -- install the current version on an old cluster, pg_upgrade to a newer major, then run the suite against the migrated objects in existing mode. No bridge step needed: test_factory has shipped only one version, so every leg installs current directly on the old cluster. Mechanics factored into `.github/scripts/pg_upgrade_cluster` (generic, modeled on cat_tools's script of the same name) and `bin/test_existing` (test_factory-specific, much smaller than cat_tools's own since there's no bridge/multi-origin machinery to carry -- prepare-old + run-suite is the whole surface). - `test` job now gates on `make verify-results` instead of pgxn-tools' `pg-build-test`: pgxntool marks installcheck `.IGNORE`, so the old job was silently exiting 0 even when regression.diffs was nonempty. PGXNTOOL_ENABLE_VERIFY_RESULTS is already pgxntool's own default but is now pinned explicitly in the Makefile, matching ENABLE_TEST_INSTALL's existing explicit-over-implicit convention. - Dynamic version assertion (bin/test_existing's assert_version): the installed version is always derived from `make -s print-PGXNVERSION`, never hardcoded, with empty-value guards on both sides. Real bug found by actually running the pg_upgrade dry run locally (PG12/16 -> PG17, using throwaway data directories, per the verification requirement -- not just written and trusted): test/helpers/create.sql's security-definer function check had no ORDER BY, so its row order depended on pg_proc's physical layout. That happens to match creation order on a fresh CREATE EXTENSION but is NOT preserved by pg_upgrade's dump/restore, which produced a real (but harmless -- every individual assertion still said "ok") text diff against the fresh-install expected output. Fixed with an explicit ORDER BY, which turns out to make one set of expected-output files valid for fresh, existing, AND pg_upgraded modes alike -- no third numbered alternate file needed, simpler than it first looked. Skipped, per the scoping decided before starting (see PR description for full reasoning): extension-update-test job (no second version has ever shipped), bridge/multi-origin update machinery (cat_tools-specific technical debt test_factory doesn't have), pg-upgrade-stepwise (test_factory has no catalog-internals-touching views/functions), pg_tle testing (not a deployment target), the `stable` pseudo-version (real feature work, not requested). Verified locally: make verify-results passes cleanly on both PG12 and PG17 (shared clusters); a full old-cluster-install -> pg_upgrade -> new-cluster existing-mode suite run (PG12->PG17 and PG12->PG16, using scratch data directories, never touching the shared clusters) passes with zero raw "not ok" TAP lines using the actual committed bin/test_existing and pg_upgrade_cluster scripts, not just ad hoc commands. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
- test job: `make verify-results` alone races install vs installcheck under this container's ambient parallel make (they're independent prerequisites of the same `test` target) -- pg_regress could start, and fail with "extension ... is not available", before install's file copy finished. Split into two separate `make` invocations, which can't race with each other. Reproduced the failure mode's shape locally (though not the race itself -- couldn't get this container's make to lose the race on demand) and confirmed the two-step form still passes. - pg-upgrade-test job: never installed pgtap system-wide on either cluster. It worked by accident in local dry-runs only because this dev container already had pgtap installed for some PG majors from earlier testing -- confirmed by deliberately clearing /usr/share/postgresql/16/extension/ (a major this container had never used) and re-running the full recreate-old -> prepare-old -> pg_upgrade -> run-suite cycle end to end: it failed the same way PR Postgres-Extensions#23's CI did ("extension pgtap is not available"), then passed once both `pgxn install pgtap --sudo --pg_config ...` steps were added (old cluster before prepare-old, new cluster before its make install -- pg_upgrade itself needs pgtap available on the new cluster too, not just post-upgrade). --pg_config is explicit on both, not left to rely on pg-start's PATH-switching, since that's exactly the kind of ambient-state assumption that already broke once in this same job. Verified locally end-to-end (real pg_ctlcluster/pg_createcluster/pg_upgrade, not just make test): old=12/new=16, a pair this container had never exercised before, all the way through bin/test_existing run-suite with zero raw "not ok" TAP lines. Also re-confirmed plain `make test` still passes on PG12 and PG17 after these changes. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
The ORDER BY rationale added for the pg_upgrade row-ordering fix used consecutive -- lines for one continuous remark; convert it to a /* */ block per the repo's comment convention (see the sibling foundation fix in advanced-testing/foundation).
The pgtap.sql rebase conflict resolution two commits back had to pick a side for test/expected/pgtap.out arbitrarily to unblock the rebase; it kept the pre-ORDER-BY (creation-order) content instead of the alphabetically-sorted order test/helpers/create.sql's new `ORDER BY p.oid::regproc::text` actually produces. test/expected/pgtap_1.out (the existing-mode alternate) already had the correct sorted order -- it merged cleanly during the rebase without needing this fix. Verified fresh mode, existing mode (against a real pre-populated database), and -j4 parallel make all pass cleanly with the regenerated file.
…bump checkout - ci.yml: pg-upgrade-test now needs [changes, test], not just [changes] -- a trivially-broken PR (fails the cheap fresh-install matrix) no longer also burns the full, expensive binary pg_upgrade matrix. Added a top-level concurrency block (cancel-in-progress) so a superseded push cancels an in-flight run instead of letting that expensive matrix run to completion for nothing. all-checks-passed's own needs/self-check invariant is unaffected (its needs list and job set didn't change shape). - bin/test_existing: run_suite() called make test then make verify-results back to back -- verify-results already depends on test (pgxntool's base.mk), so every pg-upgrade-test CI leg paid for two full pg_regress --use-existing runs against the real migrated database instead of one. Dropped the redundant call. - actions/checkout@v4 -> @v7 (current latest major), all 5 occurrences (lint, changes, test, pg-upgrade-test, all-checks-passed -- one more than the brief's "4" since the lint job wasn't part of this branch when that count was written). Verified locally: full make lint + make verify-results (fresh mode) still pass. Reproduced a REAL binary pg_upgrade leg end to end (16 -> 17, using throwaway pg_createcluster data directories on custom ports, never touching this container's shared main clusters): recreated old cluster with data checksums, installed pgtap + test_factory, prepared it via bin/test_existing prepare-old, created the new cluster, installed pgtap + test_factory there too, ran the actual pg_upgrade binary, started the new cluster, then ran bin/test_existing run-suite against it -- all 3 tests passed with the deduplicated run_suite().
9d2fb69 to
4e7e8c7
Compare
The advanced-extension-testing doc's reference implementation (cat_tools) is on NEWEST=18; this repo was still on 17. Rather than assume pg-start's `apt.postgresql.org.sh -i -p -v "$PGVERSION"` can install PG18 (a matrix expansion that silently failed to install would be a much worse failure mode than not bumping), confirmed it via an actual CI run: pushed NEWEST=18 alone first and watched the new "PostgreSQL 18" job -- it installed postgresql-18 18.4-1.pgdg13+1 via pg-start and the full fresh-install suite passed. With NEWEST=18, also shifted pg-upgrade-test's "newest-boundary" leg from 16->17 to 17->18 and its "oldest-to-newest" leg from 10->17 to 10->18, keeping both legs matching the job's own stated rationale (widest catalog distance; most likely to hit a *new* major's catalog change first) now that 18 is the newest major instead of 17.
6a7b673 to
e4b559f
Compare
Caught by the job's own self-verification step on the first full CI run of this rebased branch (confirmed via a real run, not just local YAML parsing): the `lint` job (SQL Lint, inherited via the pgxntool 2.3.0 sync stacked below this PR -- not part of this PR's own original commits) was present in the workflow but missing from all-checks-passed's needs: list, since that list was carried over unmodified from before `lint` existed on this branch. all-checks-passed would otherwise silently ignore SQL Lint results entirely -- exactly the class of bug its own self-check step exists to catch, which is what actually caught it here.
|
Superseded by #35 -- recreated as an upstream-branch PR so it can be part of a formal GitHub stack ( |
Rebase note + follow-up fixes
Rebased onto the updated
advanced-testing/foundation(this stack issync-pgxntool-2.3.0->add-test-build(#26) ->advanced-testing/foundation(#22) -> this PR; coordinator is handlinggh stack linkseparately).advanced-testing/cihad a merge commit bringing in the OLDadvanced-testing/foundationhistory directly, so a plaingit rebasetried to replay that entire flattened history against the new base -- usedgit rebase --onto <new-foundation> <old-foundation-tip>instead, to replay only this branch's own unique commits.Real conflicts requiring judgment (not mechanical):
.github/workflows/ci.yml(this PR'schanges/pg-upgrade-test/all-checks-passedstructure vs. the now-simplifiedlint+teststructure inherited from #26/the pgxntool 2.3.0 sync -- merged both),test/expected/pgtap.out(this PR'sORDER BYfix fortest/helpers/create.sql's security-definer-function check reorders that output; regenerated the fresh-mode expected file from a real run once the conflict was resolved --pgtap_1.out, the existing-mode alternate, already had the correct sorted order and needed no change), and the sametest/sql/install.sql/pgtap.sqlmode-gating reconciliation #22 already needed against #26's trim (nothing new here, just replayed).Fixes applied per this round of review, all verified locally before pushing
(a)
pg-upgrade-testnow gates ontest, plus addedconcurrency. Previouslyneeds: [changes]only, so a trivially-broken PR still burned the full binarypg_upgradematrix. Nowneeds: [changes, test]. Added a top-levelconcurrency: {group: "${{ github.workflow }}-${{ github.ref }}", cancel-in-progress: true}so a superseded push cancels an in-flight run.all-checks-passed's ownneeds/self-check invariant is unaffected (job set didn't change shape).(b)
bin/test_existing'srun_suite()was running the full suite twice.make testfollowed immediately bymake verify-results--verify-resultsalready depends ontest(pgxntool'sbase.mk), so everypg-upgrade-testleg paid for two fullpg_regress --use-existingruns against the real migrated database. Dropped the redundantmake testcall. Verified this is still correct post-pgxntool-2.3.0 by reproducing a REALpg_upgradeleg end to end locally (16 -> 17 at the time, using throwawaypg_createclusterdata directories on custom ports -- never touching this container's shared clusters): recreated the old cluster with data checksums, installed pgtap + test_factory, prepared it viabin/test_existing prepare-old, created the new cluster, installed pgtap + test_factory there too, ran the actualpg_upgradebinary, started the new cluster, then ranbin/test_existing run-suiteagainst it -- all 3 tests passed with the deduplicatedrun_suite().(c)
actions/checkout@v4->@v7(current latest major -- v5/v6 have both released since v4), all 5 occurrences (lint,changes,test,pg-upgrade-test,all-checks-passed-- one more than the original "4" since thelintjob wasn't part of this branch when that count was written; it arrived via the pgxntool 2.3.0 sync / #26 stacked below). Coordination note: PR #29 (ci/bump-actions-versions, someone else's, out of scope for me to touch) also bumps this same pin elsewhere in this file for the original, not-yet-restructured job set -- whichever of these two efforts merges second will need a finalgrep -rn 'actions/checkout@v4'sweep to make sure nothing was missed.(d)
NEWESTbumped 17 -> 18. The advanced-extension-testing doc's reference implementation (cat_tools) is already onNEWEST=18. Rather than assume PG18 installs cleanly in thepgxn/pgxn-toolsimage, confirmed it via an actual CI run first (pushed theNEWEST=18bump alone, watched the new "PostgreSQL 18" job) -- it installedpostgresql-18 18.4-1.pgdg13+1viapg-startand the fresh-install suite passed. With 18 now the newest major, also shiftedpg-upgrade-test's two legs to match its own stated rationale (widest catalog distance; most likely to hit a new major's catalog change first): oldest-to-newest is now10 -> 18(was10 -> 17), and the newest-boundary leg is now17 -> 18(was16 -> 17).Verification after all fixes
make lintandmake verify-results(fresh mode) pass locally.bash -non both shell scripts, YAML parse check onci.yml.pg_upgradeleg (see (b) above) passes with the deduplicated script.changes, alltestmatrix legs (10-18),pg-upgrade-test's two legs (10->18, 17->18), andall-checks-passed.Summary
PR 2 of the advanced update+upgrade (U&U) testing stack, on top of #22
(
advanced-testing/foundation, not yet merged -- this PR targets thatbranch, not
master). Implements the remaining CI-structure items from theadvanced-extension-testing pattern, modeled on
Postgres-Extensions/cat_tools'sactual
ci.yml/bin/test_existing(read directly off itsmaster, not justprose about it) and scoped down deliberately per the plan agreed before
starting.
Note:
advanced-testing/foundationwas pushed to this repo (unchanged, samecommit as the fork's branch backing #22) purely so this PR's base could
reference it directly -- it is not new work, just a ref needed for a clean
stacked diff. Once #22 merges, this PR should be retargeted to
masteras afollow-up (not done here).
What shipped
pushscoped tobranches: [master];pull_requeststays unrestricted. test_factory was explicitlynamed as one of the repos still needing this.
changes/docs-only gate instead of workflow-levelpaths-ignore-- computes the real per-push diff, fail-safe (docs_only=false)written as the literal first line so any early exit/error leaves the safe
default in place. Avoids the stuck-Pending-required-check trap a
workflow-level
paths-ignorewould cause.(
NEWEST=18,FLOOR=10), derivedonce in the
changesjob and consumed viafromJSONby both thetestand new
pg-upgrade-testmatrices.all-checks-passedgate, self-verifying its ownneeds:list matchesthe actual job set. This is the check to wire up as required in branch
protection -- I don't have permission to change that setting myself.
pg-upgrade-testjob: binarypg_upgradelegs (10 -> 18,17 -> 18, updated from the original10 -> 17/16 -> 17onceNEWESTwas bumped -- see the rebase note above) -- install the current version on an old cluster,pg_upgradeto a newer major, run the suite against the migrated objects in
existingmode. No bridge step: test_factory has shipped only one version (0.5.0),
so every leg installs current directly on the old cluster -- there's no
older,
pg_upgrade-unsafe install to carry forward.bin/test_existing(new, test_factory-specific) and.github/scripts/pg_upgrade_cluster(new, generic pg_upgrade CImechanics) -- the install -> pg_upgrade -> assert -> run-suite flow
factored into committed scripts instead of inline YAML per job, per the
doc's own guidance.
bin/test_existingis much smaller than cat_tools'sown: no bridge/multi-origin subcommands, just
prepare-old+run-suite.testjob now gates onmake verify-results, not pgxn-tools'pg-build-test. Found while rewriting this job:pg-build-test's ownmake installcheck || status=$?never actually catches a failure, becausepgxntool marks
installcheck.IGNORE--makeitself exits 0 thereregardless of
regression.diffs. The old CI was silently green on a realregression.
PGXNTOOL_ENABLE_VERIFY_RESULTSwas already pgxntool's owndefault, but I pinned it explicitly in the Makefile (matching
ENABLE_TEST_INSTALL's existing explicit-over-implicit convention) so afuture pgxntool default change can't silently disable the gate.
bin/test_existing'sassert_versionderives the expected version from
make -s print-PGXNVERSION, neverhardcoded, with empty-value guards on both sides (
"" != ""is false, so abroken extraction can't silently pass).
A real bug the local pg_upgrade dry run actually found
Per the brief, I ran the full old-cluster-install ->
pg_upgrade->new-cluster-suite-run cycle locally before trusting any of this in CI (PG12
-> PG17 and PG12 -> PG16, using throwaway
initdbdata directories, nevertouching the container's shared clusters) -- and it surfaced a real, if
low-stakes, bug:
test/helpers/create.sql's security-definer-function checkhad no
ORDER BY, so its row order depended onpg_proc's physical layout.That happens to match creation order on a fresh
CREATE EXTENSIONbut isnot preserved by
pg_upgrade's dump/restore (which reconstructs it in adifferent, apparently name-sorted, order) -- producing a real but harmless
text diff (every individual pgTAP assertion still said
ok, just reordered)against the fresh-install expected output. Fixed with an explicit
ORDER BY p.oid::regproc::text.Bonus: this makes ONE set of expected-output files valid for fresh,
existing, and pg_upgraded modes alike -- no third numbered alternate file
needed (unlike the doc's more general guidance for genuinely different
axes like
TEST_SCHEMA), since the divergence here was pure incidentalnon-determinism, not a legitimate different-but-correct scenario. Simpler
than it first looked once actually run.
Convergence / divergence from cat_tools PR #16 (and its
mastersince)Took near-verbatim (generic CI mechanics, no cat_tools-specific
content): the shape of
.github/scripts/pg_upgrade_cluster(
recreate-old/upgradesubcommands,INITDB_OPTSconvention, pg_upgradelog capture for both PG17+'s
pg_upgrade_output.d/and older's CWD), thechangesjob's docs-only fail-safe-first-line pattern, theall-checks-passedself-verifyingneedscheck, and the dynamicversion-assertion empty-guard pattern.
Adapted:
bin/test_existingkeeps only two subcommands(
prepare-old/run-suite) instead of cat_tools's six -- noplant-guard/update/update-scenario/update-check, becausetest_factory's dependency guard is planted and proved entirely inside
test/install/load.sql's existing-mode branch (from PR #22), not by thisscript, and there's no update path to exercise yet. The
changesjob alsodrops cat_tools's "find the last commit where real code changed" reporting
machinery -- useful polish, but not part of the checklist items this PR
scoped to; noting it here as a real simplification, not an oversight, in
case a human wants it added later.
Skipped, and why (all decided before starting, confirmed still correct
after doing the work):
extension-update-testjob -- test_factory has shipped only one version(0.5.0), so
TEST_LOAD_SOURCE=updatehas no real historical update scriptto exercise yet. The mechanism exists (PR Add test/install foundation for update+upgrade testing (fresh/update/existing) #22); no CI job drives it.
(recovering from old
pg_upgrade-unsafe releases). test_factory has nocatalog-touching views and only one shipped version, so there's nothing to
bridge from.
pg-upgrade-stepwise(every-major climb) -- test_factory has nocatalog-internals-touching views/functions (no
SELECT *over a systemcatalog), so the per-major-boundary risk this protects against is low. A
human may disagree and ask for it later; flagging explicitly rather than
silently omitting.
deployment.
stablepseudo-version -- real feature work, not part of atesting-infrastructure PR, not requested.
Verification
make verify-resultspasses cleanly (fresh mode) on both PG12 and PG17.pg_upgrade-> new-cluster-suite-run cycle,using the actual committed
bin/test_existingand.github/scripts/pg_upgrade_cluster(not just ad hoc commands), passeswith zero raw
not okTAP lines -- run twice, PG12->PG17 and PG12->PG16,in scratch data directories that never touched the container's shared
clusters.
.github/workflows/ci.ymlparses cleanly under PyYAML; both new shellscripts pass
bash -n.Test plan
test+pg-upgrade-test+all-checks-passed)master(follow-up, not done here)all-checks-passedas a required status check inbranch protection
🤖 Generated with Claude Code