From 7664638eda5afca351d7e13af11bc91db6e37637 Mon Sep 17 00:00:00 2001 From: jnasbyupgrade Date: Mon, 3 Aug 2026 16:28:22 -0500 Subject: [PATCH 1/3] CI: fold the PG12+ guard-proved update-to-current check into the `test` job, shrink extension-update-test to PG10-only extension-update-test's PG12+ leg ran on the exact same PostgreSQL majors as the `test` job (supported_pg, 12-18), but as its own matrix job: its own runner, container boot, checkout, apt-get, and `make install`, paid again per major, for a check that can run as one more step inside a container the `test` job already has running, already checked out, and already has cat_tools installed on disk in (installcheck, a TEST_DEPS prerequisite, already ran as a side effect of that job's own verify-results call). Folded `bin/test_existing update-scenario cat_tools_update 0.2.2` in as an additional call in the `test` job's "Test on PostgreSQL" step instead. Verified before folding it in, not assumed: ran `make check-relkind-source && make verify-results && bin/test_existing update-scenario cat_tools_update 0.2.2` in the same shell/cluster session (mirroring the new CI step exactly) against a scratch cluster. Confirmed no database-name collision (pg_regress's own throwaway db is named independently from `cat_tools_update`), the dependency-guard proof fires (twice -- once right after CREATE EXTENSION, once again after the full suite run), the structural-diff check (bin/structural_diff, from PR #55) fires and reports the updated database structurally identical to a fresh install, and the full suite passes -- exit 0 end to end. extension-update-test now runs PG10 only, with no matrix at all (single source of truth: needs.changes.outputs.legacy_pg, not a hardcoded "10") -- its entire remaining purpose is the pre-0.2.2 legacy-script checks, the only place those scripts still load. Removed the now-dead `if: matrix.pg != '10'` / `if: matrix.pg == '10'` guards throughout that job (nothing left to guard against once there's no other leg) and the "Update 0.2.2 -> current" step (moved above). The `changes` job's `update_pg` output/derivation is removed too -- it had exactly one consumer, and that consumer is gone. Restructured the top-of-file "Test strategy" comment around what actually matters to a reader: what runs on EVERY supported PostgreSQL major (the `test` job, now including the guard-proved update check, and `pg-tle-test` as a second, independently-isolated main-matrix job -- kept separate deliberately, since it specifically proves pg_tle deployment ISOLATION, not filesystem-install coincidence, unlike the fold above) versus SPECIAL CASES that apply to one specific scenario only (extension-update-test's PG10 legacy scripts, pg-upgrade-test's/pg-tle-upgrade-test's specific binary-pg_upgrade jump pairs, and pg-upgrade-stepwise's full climb). The pg-tle-test bullet leads with the goal (proving cat_tools works correctly via pg_tle) rather than isolation -- isolation is the precondition that makes that proof trustworthy, not the point of the job. No coverage lost: the PG12+ update-to-current check still runs on the exact same 7 majors it always did (moved, not removed), the PG10 legacy checks are byte-for-byte unchanged, and every other job is untouched. --- .github/workflows/ci.yml | 309 +++++++++++++++++++++------------------ 1 file changed, 170 insertions(+), 139 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5fb8a02..87aab58 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -43,7 +43,6 @@ jobs: last_tested_url: ${{ steps.last_tested.outputs.last_tested_url }} # Derived PG-major lists (see the "Derive ..." step for their meaning). supported_pg: ${{ steps.pg.outputs.supported_pg }} - update_pg: ${{ steps.pg.outputs.update_pg }} climb_pg: ${{ steps.pg.outputs.climb_pg }} legacy_pg: ${{ steps.pg.outputs.legacy_pg }} steps: @@ -193,16 +192,17 @@ jobs: id: pg run: | # Spending 20+ lines to replace a handful of version references looks - # silly on the surface, but the point is CONSISTENCY: every job -- the - # fresh-install `test` matrix, the `extension-update-test` matrix and - # the stepwise climb -- derives its PostgreSQL set from this ONE source, - # so they cannot drift onto different version lists. + # silly on the surface, but the point is CONSISTENCY: every job below + # (the `test`/`pg-tle-test` matrix, `extension-update-test`'s single + # legacy major, and the stepwise climb) derives its PostgreSQL set + # from this ONE source, so they cannot drift onto different version + # lists. # # SINGLE SOURCE OF TRUTH for the supported PostgreSQL majors. To add - # or drop a PG major, edit ONLY the three constants below; the test, - # extension-update-test and pg-upgrade-stepwise jobs all derive their - # version lists from them (adding the newest major is a one-line NEWEST - # bump). Do NOT hardcode a supported major in any job matrix or loop. + # or drop a PG major, edit ONLY the three constants below; every job + # derives its version list from them (adding the newest major is a + # one-line NEWEST bump). Do NOT hardcode a supported major in any job + # matrix or loop. # # NEWEST -- highest PostgreSQL major cat_tools is tested on. # CURRENT_FLOOR -- oldest major the CURRENT extension version supports: @@ -211,18 +211,16 @@ jobs: # LEGACY_FLOOR -- oldest major the pre-0.2.2 install scripts still # load on (PG11 added pg_attribute.attmissingval and # PG12+ exposes the oid system column in SELECT *, both - # of which those old scripts trip over). Only the - # update and stepwise paths reach back this far. + # of which those old scripts trip over). Only + # extension-update-test and the stepwise climb reach + # back this far. NEWEST=18 CURRENT_FLOOR=12 LEGACY_FLOOR=10 - # supported = CURRENT_FLOOR..NEWEST (newest-first). The FRESH-install - # matrix (test job) runs exactly these. + # supported = CURRENT_FLOOR..NEWEST (newest-first). The main-matrix + # jobs (test, pg-tle-test) run exactly these. supported=$(seq "$NEWEST" -1 "$CURRENT_FLOOR") - # update = supported plus the legacy floor: the extension-update job - # additionally exercises the PG10-only pre-0.2.2 update scripts. - update="$supported $LEGACY_FLOOR" # climb = LEGACY_FLOOR+1 .. NEWEST (ascending). The stepwise job starts # one cluster on the legacy floor and binary-pg_upgrades through every # later major in turn, so its targets are every major above the floor. @@ -234,7 +232,6 @@ jobs: json() { printf '%s\n' "$@" | paste -sd, - | sed 's/^/[/; s/$/]/'; } echo "supported_pg=$(json $supported)" >> "$GITHUB_OUTPUT" - echo "update_pg=$(json $update)" >> "$GITHUB_OUTPUT" echo "legacy_pg=$LEGACY_FLOOR" >> "$GITHUB_OUTPUT" # Space-separated for direct iteration in the stepwise bash loop. echo "climb_pg=$(echo $climb)" >> "$GITHUB_OUTPUT" @@ -242,46 +239,83 @@ jobs: # =========================================================================== # Test strategy # - # A cat_tools install can be arrived at several ways, each of which can break - # differently, so each is exercised by its own job below (the per-job comments - # carry the details; this is the big picture): + # Two kinds of coverage: what runs on EVERY supported PostgreSQL major (the + # MAIN MATRIX), and SPECIAL CASES that apply to one scenario only. # - # test -- FRESH install: CREATE EXTENSION at the current - # version on every supported PostgreSQL. The baseline - # a brand-new user gets. - # extension-update-test -- IN-PLACE update: CREATE EXTENSION at an OLD version - # then ALTER EXTENSION UPDATE (same PostgreSQL, no - # pg_upgrade). - # pg-upgrade-test -- BINARY pg_upgrade, SINGLE jump: install an OLD - # version on an OLD major, binary-upgrade the cluster - # straight to a NEWER major (skipping intermediate - # majors), then update the extension. Proves objects - # created on an old server work when read on a new one. - # pg-upgrade-stepwise -- BINARY pg_upgrade, EVERY major in sequence: one - # cluster climbing 10 -> 11 -> ... -> 18, exercising - # each individual major-to-major transition in turn. + # MAIN MATRIX -- every supported major (12-18, single source: the changes + # job). Two independently-isolated jobs, since they prove different things: # - # Supported update origins are 0.2.0, 0.2.1 and 0.2.2 (0.1.x is unsupported). - # 0.2.0 and 0.2.1 are BOTH tested as origins because ALTER EXTENSION UPDATE - # takes the shortest path: a 0.2.0 origin updates straight through the - # 0.2.0--0.2.2 script and never touches 0.2.1--0.2.2, so starting at 0.2.1 is - # the only way to exercise the 0.2.1--0.2.2 update script (spelled out at the - # pg-upgrade-test matrix). + # test -- Everything reachable through a FILESYSTEM-installed + # cat_tools on this major: + # 1. FRESH install -- `make verify-results`, the baseline + # a brand-new user gets. + # 2. The GUARD-PROVED update-to-current check: + # bin/test_existing's update-scenario -- CREATE + # EXTENSION at the 0.2.2 backward-compat floor, ALTER + # EXTENSION UPDATE to current, structurally compare + # against a fresh install, then run the full suite in + # existing mode. USED to be its own matrix job + # (extension-update-test's PG12+ leg) -- folded in + # here since it runs on the same majors as (1), and + # this job's container, checkout, and cat_tools + # install are already there; a separate job would pay + # for all of that again for no added coverage. See + # that step's own comment for what was verified + # locally before folding it in. # - # Two PostgreSQL-version floors shape the matrices: - # - The pre-0.2.2 install scripts (0.2.0 / 0.2.1) load ONLY on PG10: PG11 - # added pg_attribute.attmissingval and PG12+ exposes the oid system column - # in SELECT *, both of which those old scripts trip over. So a 0.2.0 / 0.2.1 - # origin can only start on PG10. - # - The current version needs PG12+: the 0.2.3->0.3.0 update runs - # ALTER TYPE ... ADD VALUE, which cannot run in a pre-PG12 transaction (and - # an extension update script is one). + # pg-tle-test -- The SAME majors, proving cat_tools actually works when + # deployed via pg_tle (AWS's Trusted Language Extensions) + # instead of a filesystem .control file -- the same + # fresh-install and update-path scenarios (1)/(2) prove for + # a filesystem install, run again through pg_tle's own + # registration. That proof only means what it claims if + # pg_tle ISOLATION holds throughout the run (a stale + # filesystem .control file silently wins over a pg_tle + # registration of the same name -- PostgreSQL just + # resolves from disk instead of erroring), so every step + # here is bracketed by filesystem-cleanliness checks -- + # isolation is the precondition for a trustworthy result, + # not the point of the job. NOT folded into `test` above: + # pg_tle needs shared_preload_libraries (mixing pg_tle/ + # non-pg_tle installs on one cluster can misbehave), so it + # needs its own dedicated cluster. # - # KEY invariant: every pg_upgrade leg CLIMBS to a PostgreSQL that supports the - # current version, then updates to the current version and runs the full suite - # -- no leg stops short. A PG10/11 origin simply HOLDS the extension at 0.2.3 - # (the highest version reachable on those majors) until the cluster reaches - # PG12+, where it is updated to the current version. + # SPECIAL CASES -- apply to one scenario, not the whole matrix: + # + # extension-update-test -- PG10 ONLY. The pre-0.2.2 install scripts + # (0.2.0/0.2.1) load on no other major (PG11 + # added pg_attribute.attmissingval; PG12+ exposes + # oid in SELECT *; both trip up those old + # scripts), so this job's only remaining purpose + # is the 0.2.0->0.2.2, 0.2.1->0.2.2, and + # 0.2.2->0.2.3 (view-rebuild) update scripts, on + # the one major that can still run them. Both + # 0.2.0 and 0.2.1 are tested because ALTER + # EXTENSION UPDATE takes the SHORTEST path: a + # 0.2.0 origin updates straight through + # 0.2.0--0.2.2 and never touches 0.2.1--0.2.2, so + # 0.2.1 is the only way to exercise that script. + # pg-upgrade-test -- BINARY pg_upgrade, SPECIFIC old_pg->new_pg + # jump pairs (every major is pg-upgrade-stepwise + # below): install an OLD version on an OLD + # major, binary-upgrade straight to a NEWER + # major (skipping intermediates), then update + # the extension -- proving objects created on an + # old server work when read on a new one. Every + # leg CLIMBS to a PostgreSQL that supports the + # current version, then updates and runs the + # full suite -- no leg stops short. A PG10/11 + # origin HOLDS the extension at 0.2.3 (the + # highest version those majors can reach) until + # PG12+. + # pg-tle-upgrade-test -- The pg_tle-deployed equivalent of + # pg-upgrade-test, on the jump pairs within + # pg_tle's own supported PostgreSQL range. + # pg-upgrade-stepwise -- BINARY pg_upgrade, EVERY major in sequence: + # one cluster climbing 10 -> 11 -> ... -> 18, + # catching a regression specific to one + # major-to-major boundary that a big-jump leg + # (pg-upgrade-test) would skip. # =========================================================================== test: needs: [changes] @@ -306,18 +340,50 @@ jobs: - name: Test on PostgreSQL ${{ matrix.pg }} run: | # Fail if the relkind drift source is empty (headers missing): the - # drift check must actually run on every version, not pass silently. + # drift check must run on every version, not pass silently. make check-relkind-source - # verify-results is the real gate: base.mk declares `verify-results: - # $(TEST_DEPS)`, not `verify-results: test` -- deliberately, since test's own - # recipe now exits non-zero as soon as it sees a regression, which would abort - # the chain before verify-results got to inspect and report the diff. Either - # way this runs the suite (via installcheck, one of $(TEST_DEPS)) and then - # checks the pgtap/regression.diffs. A bare `make test` is redundant here: - # it now also exits non-zero on regressions (pgxntool 2.3.0+), but - # verify-results is still the stricter, documented check. + + # The fresh-install baseline: verify-results, this repo's stricter, + # pgtap-aware gate. base.mk declares `verify-results: + # $(TEST_DEPS)`, not `verify-results: test`, because test's own + # recipe now exits non-zero on a regression (pgxntool 2.3.0+), + # which would abort the chain before verify-results could inspect + # and report the diff. Either way this runs the suite via + # installcheck, then checks pgtap/regression.diffs. A bare `make + # test` is redundant here for the same reason -- it now also exits + # non-zero on a regression, but verify-results is the stricter, + # documented check. make verify-results + # The guard-proved update-to-current check (see the Test strategy + # comment above). USED to be its own matrix job + # (extension-update-test's PG12+ leg) -- folded in here since it + # runs on these same majors, and this job's container, checkout, + # and cat_tools install are already there; a separate job would + # pay for all of that again for no added coverage. + # update-scenario creates its own database (cat_tools_update, not + # pg_regress's own throwaway db from verify-results above -- + # confirmed no name collision), plants + proves the dependency + # guard, ALTER EXTENSION UPDATEs 0.2.2 to current, structurally + # compares the result against a fresh install (assert_matches_fresh, + # via bin/structural_diff), and runs the full suite against it in + # existing mode. Reusing the SAME suite and expected output asserts + # the updated database behaves identically to a fresh install. See + # extension-update-test below for the PG10-only legacy checks this + # does NOT cover (those pre-0.2.2 scripts don't load on PG12+ at + # all). + # + # Verified locally before folding it in: ran `make + # check-relkind-source && make verify-results && bin/test_existing + # update-scenario cat_tools_update 0.2.2` in one shell/cluster + # session (mirroring this step). Confirmed no database-name + # collision, the dependency-guard proof fires (once right after + # CREATE EXTENSION, once again after the suite run), the + # structural-diff check reports the updated database structurally + # identical to a fresh install, and the full suite passes -- exit + # 0 end to end. + bin/test_existing update-scenario cat_tools_update 0.2.2 + # Style linter (https://github.com/Postgres-Extensions/linter, vendored at # .vendor/linter). Deliberately checked out WITHOUT submodules -- `make # lint` is the same command a developer runs locally, and lint.mk @@ -639,89 +705,63 @@ jobs: old=$new done - # Proves the in-place extension update path: CREATE EXTENSION at an OLD cat_tools - # version then ALTER EXTENSION UPDATE (no pg_upgrade, same PostgreSQL). On PG12+ - # it updates 0.2.2 -> current and runs the FULL suite against the updated - # database (same expected output as a fresh install, so an updated DB must behave - # identically). The PG10 leg only exercises the pre-0.2.2 update scripts, the - # sole version where they still load. Complements pg-upgrade-test, which covers - # the cross-major-version binary upgrade instead. + # Proves the pre-0.2.2 legacy install/update scripts: CREATE EXTENSION at + # 0.2.0/0.2.1 then ALTER EXTENSION UPDATE (no pg_upgrade). PG10 ONLY -- see + # the Test strategy comment above for why, and why the PG12+ update-to- + # current leg lives in the `test` job instead of here. extension-update-test: # Gated behind test+lint -- see the comment on pg-upgrade-test's needs. needs: [changes, test, lint] if: success() && needs.changes.outputs.docs_only != 'true' - strategy: - matrix: - # PG12+: exercise the WIDEST update path we support — CREATE EXTENSION at - # the 0.2.2 backward-compat floor, ALTER EXTENSION UPDATE to the CURRENT - # version, and run the full suite against the updated database. 0.2.2 is - # the floor because the 0.2.0/0.2.1 install scripts fail on PG11+/PG12+; - # PG12 is the PostgreSQL floor because the update runs - # `ALTER TYPE ... ADD VALUE`, which PG11 and below cannot run in an - # extension update script (lifted in PG12). - # PG10: the ONLY version where the pre-0.2.2 install scripts still load, - # so the only place the 0.2.0->0.2.2 and 0.2.1->0.2.2 update scripts and - # the 0.2.2->0.2.3 view rebuild on the broken path can be exercised. They - # target 0.2.2/0.2.3 (not the current version) and use no - # ALTER TYPE ... ADD VALUE, so they run on PG10. The PG10 leg runs only - # those legacy checks — not the current-version suite (the current version - # needs PG12+: the 0.2.3->0.3.0 update adds enum values via ALTER TYPE ... - # ADD VALUE, unrunnable in a pre-PG12 transaction). See the per-step `if` - # guards. - # - # Current-supported majors + the legacy PG10 floor, from the single - # source in the changes job (update_pg = supported_pg plus legacy_pg). - pg: ${{ fromJSON(needs.changes.outputs.update_pg) }} - name: ⬆️ Extension update test on PostgreSQL ${{ matrix.pg }} + # Single source of truth for the legacy PG10 floor: needs.changes.outputs.legacy_pg, + # not a hardcoded '10'. + env: + LEGACY_PG: ${{ needs.changes.outputs.legacy_pg }} + name: ⬆️ Extension update test on PostgreSQL ${{ needs.changes.outputs.legacy_pg }} runs-on: ubuntu-latest container: pgxn/pgxn-tools steps: - - name: Start PostgreSQL ${{ matrix.pg }} - run: pg-start ${{ matrix.pg }} + - name: Start PostgreSQL ${{ env.LEGACY_PG }} + run: pg-start ${{ env.LEGACY_PG }} - name: Check out the repo uses: actions/checkout@v6 - - name: Install rsync and server headers - # server-dev provides catalog/pg_class.h for the relkind drift check - # (see the "test" job); required so check-relkind-source below passes. - # PG10 runs only the legacy-script checks (no suite), so it needs no headers. - if: matrix.pg != '10' - run: apt-get install -y rsync postgresql-server-dev-${{ matrix.pg }} - name: Install rsync - if: matrix.pg == '10' + # No server-dev header package here: this job runs no suite (see the + # job comment above), so nothing needs the relkind drift check. run: apt-get install -y rsync - name: Install cat_tools (all versions) run: make install - - name: Test pre-0.2.2 update scripts + 0.2.2→0.2.3 rebuild (PG10 only) - # 0.2.0/0.2.1 install only on PG10; their update scripts target 0.2.2 (not - # the current version) and are otherwise never exercised. Both origins are - # checked because ALTER EXTENSION UPDATE takes the shortest path (see the - # pg-upgrade-test matrix): 0.2.0 goes via the 0.2.0--0.2.2 script, 0.2.1 via - # 0.2.1--0.2.2. update-check-version asserts each lands on 0.2.2 -- NOT - # plain update-check: landing on 0.2.2 from these origins is a KNOWN - # divergence from a fresh 0.2.2 install (trigger__parse and the - # pg_class_v omit_column bug, repaired in 0.2.2->0.2.3; a type-ACL gap, - # repaired only in 0.2.3->0.3.0), and both 0.2.0->0.2.2 / 0.2.1->0.2.2 - # are already-published scripts that cannot be edited to fix it + - name: Test pre-0.2.2 update scripts + 0.2.2→0.2.3 rebuild + # 0.2.0/0.2.1 install only on PG10; their update scripts target 0.2.2 + # (not the current version) and are otherwise never exercised. Both + # origins are checked because ALTER EXTENSION UPDATE takes the + # shortest path (see pg-upgrade-test above): 0.2.0 goes via the + # 0.2.0--0.2.2 script, 0.2.1 via 0.2.1--0.2.2. update-check-version + # asserts each lands on 0.2.2 -- NOT plain update-check: landing on + # 0.2.2 from these origins is a KNOWN divergence from a fresh 0.2.2 + # install (trigger__parse and the pg_class_v omit_column bug, + # repaired in 0.2.2->0.2.3; a type-ACL gap, repaired only in + # 0.2.3->0.3.0), and both 0.2.0->0.2.2 / 0.2.1->0.2.2 are + # already-published scripts that cannot be edited to fix it # directly, so asserting fresh-parity here would fail forever by - # design. No suite runs (the current version needs PG12+). + # design. # - # The rebuild_020/rebuild_021 checks exercise the REAL broken path end to - # end from BOTH pre-0.2.2 origins: a 0.2.0 (resp. 0.2.1) install on PG10 - # leaves relhasoids in _cat_tools.pg_class_v (the buggy 0.2.0--0.2.2 / - # 0.2.1--0.2.2 omit_column no-op), and updating to 0.2.3 routes through - # 0.2.2--0.2.3 (shortest path --0.2.2 then 0.2.2--0.2.3), firing - # the conditional rebuild that strips relhasoids and the trigger__parse - # repair. It stays update-check-version, not plain update-check: 0.2.3 - # is ALSO already-published (tagged), so the type-ACL gap above is not - # (and cannot be) fixed until 0.2.3->0.3.0 either -- this landing point - # still diverges from a fresh 0.2.3 install on that ACL alone. 0.2.3 is - # the furthest PG10 can reach (0.2.3--0.3.0 needs PG12+). On PG12+ - # relhasoids never existed, so only PG10 exercises the rebuild. The + # The rebuild_020/rebuild_021 checks exercise the REAL broken path + # end to end from BOTH pre-0.2.2 origins: a 0.2.0 (resp. 0.2.1) + # install leaves relhasoids in _cat_tools.pg_class_v (the buggy + # 0.2.0--0.2.2 / 0.2.1--0.2.2 omit_column no-op), and updating to + # 0.2.3 routes through 0.2.2--0.2.3 (shortest path --0.2.2 + # then 0.2.2--0.2.3), firing the conditional rebuild that strips + # relhasoids and the trigger__parse repair. It stays + # update-check-version, not plain update-check: 0.2.3 is ALSO + # already-published (tagged), so the type-ACL gap above is not (and + # cannot be) fixed until 0.2.3->0.3.0 either -- this landing point + # still diverges from a fresh 0.2.3 install on that ACL alone. 0.2.3 + # is the furthest PG10 can reach (0.2.3--0.3.0 needs PG12+). The # psql assertion fails loudly if the rebuild did not fire (relhasoids - # still present) -- complementing the stronger 10→18 pg_upgrade bridge - # legs. `$$` is escaped as `\$\$` so the shell passes literal dollar - # quotes through to psql. - if: matrix.pg == '10' + # still present) -- complementing the stronger 10→18 pg_upgrade + # bridge legs. `$$` is escaped as `\$\$` so the shell passes literal + # dollar quotes through to psql. run: | bin/test_existing update-check-version cat_tools_from_020 0.2.0 0.2.2 bin/test_existing update-check-version cat_tools_from_021 0.2.1 0.2.2 @@ -731,15 +771,6 @@ jobs: bin/test_existing update-check-version "$db" "$from" 0.2.3 psql -d "$db" -v ON_ERROR_STOP=1 -c "DO \$\$ BEGIN IF EXISTS (SELECT 1 FROM pg_attribute WHERE attrelid='_cat_tools.pg_class_v'::regclass AND attname='relhasoids' AND NOT attisdropped AND attnum>0) THEN RAISE EXCEPTION 'pg_class_v still exposes relhasoids after update through 0.2.2->0.2.3 -- rebuild did not fire'; END IF; END \$\$" done - - name: Update 0.2.2 → current and run the suite (existing mode, PG12+) - # update-scenario creates a real database at 0.2.2, plants + proves the - # dependency guard, ALTER EXTENSION UPDATEs to the current version, and - # runs the suite against that updated database in existing mode (asserting - # the version and that the guard still blocks a drop). Reusing the SAME - # suite and expected output asserts the updated database behaves - # identically to a fresh install. - if: matrix.pg != '10' - run: bin/test_existing update-scenario cat_tools_update 0.2.2 pg-tle-test: # Gated behind test+lint -- see the comment on pg-upgrade-test's needs. @@ -853,7 +884,7 @@ jobs: # smoke test above never runs the full suite. run: apt-get install -y postgresql-server-dev-${{ matrix.pg }} - name: Test the update path via pg_tle (full pgTAP suite, --use-existing) - # Exercises the SAME update path extension-update-test proves for a + # Exercises the SAME update path the `test` job proves for a # filesystem install (0.2.2 -> current), but entirely through pg_tle. # bin/test_existing's update_scenario is UNMODIFIED from the # filesystem case -- only run_suite's internals differ, gated by this From ba9b8d7f33dec3a7fde897618c3366867b825eb2 Mon Sep 17 00:00:00 2001 From: jnasbyupgrade Date: Mon, 3 Aug 2026 16:49:21 -0500 Subject: [PATCH 2/3] ci.yml: drop the aligned name/description table look from the Test strategy comment The "Test strategy" summary listed job names in a manually space-padded "name -- description" column, which reads like a Makefile target list or a formatted spec table rather than a plain comment. Restructured each entry as a small heading (the job name alone, minimally indented) with its description as ordinary wrapped prose underneath -- same content, no alignment bookkeeping. --- .github/workflows/ci.yml | 126 ++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 67 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 87aab58..8f12cec 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -245,77 +245,69 @@ jobs: # MAIN MATRIX -- every supported major (12-18, single source: the changes # job). Two independently-isolated jobs, since they prove different things: # - # test -- Everything reachable through a FILESYSTEM-installed - # cat_tools on this major: - # 1. FRESH install -- `make verify-results`, the baseline - # a brand-new user gets. - # 2. The GUARD-PROVED update-to-current check: - # bin/test_existing's update-scenario -- CREATE - # EXTENSION at the 0.2.2 backward-compat floor, ALTER - # EXTENSION UPDATE to current, structurally compare - # against a fresh install, then run the full suite in - # existing mode. USED to be its own matrix job - # (extension-update-test's PG12+ leg) -- folded in - # here since it runs on the same majors as (1), and - # this job's container, checkout, and cat_tools - # install are already there; a separate job would pay - # for all of that again for no added coverage. See - # that step's own comment for what was verified - # locally before folding it in. + # test + # Everything reachable through a FILESYSTEM-installed cat_tools on this + # major: + # 1. FRESH install -- `make verify-results`, the baseline a brand-new + # user gets. + # 2. The GUARD-PROVED update-to-current check: bin/test_existing's + # update-scenario -- CREATE EXTENSION at the 0.2.2 backward-compat + # floor, ALTER EXTENSION UPDATE to current, structurally compare + # against a fresh install, then run the full suite in existing mode. + # USED to be its own matrix job (extension-update-test's PG12+ leg) + # -- folded in here since it runs on the same majors as (1), and + # this job's container, checkout, and cat_tools install are already + # there; a separate job would pay for all of that again for no added + # coverage. See that step's own comment for what was verified + # locally before folding it in. # - # pg-tle-test -- The SAME majors, proving cat_tools actually works when - # deployed via pg_tle (AWS's Trusted Language Extensions) - # instead of a filesystem .control file -- the same - # fresh-install and update-path scenarios (1)/(2) prove for - # a filesystem install, run again through pg_tle's own - # registration. That proof only means what it claims if - # pg_tle ISOLATION holds throughout the run (a stale - # filesystem .control file silently wins over a pg_tle - # registration of the same name -- PostgreSQL just - # resolves from disk instead of erroring), so every step - # here is bracketed by filesystem-cleanliness checks -- - # isolation is the precondition for a trustworthy result, - # not the point of the job. NOT folded into `test` above: - # pg_tle needs shared_preload_libraries (mixing pg_tle/ - # non-pg_tle installs on one cluster can misbehave), so it - # needs its own dedicated cluster. + # pg-tle-test + # The SAME majors, proving cat_tools actually works when deployed via + # pg_tle (AWS's Trusted Language Extensions) instead of a filesystem + # .control file -- the same fresh-install and update-path scenarios (1)/(2) + # prove for a filesystem install, run again through pg_tle's own + # registration. That proof only means what it claims if pg_tle ISOLATION + # holds throughout the run (a stale filesystem .control file silently wins + # over a pg_tle registration of the same name -- PostgreSQL just resolves + # from disk instead of erroring), so every step here is bracketed by + # filesystem-cleanliness checks -- isolation is the precondition for a + # trustworthy result, not the point of the job. NOT folded into `test` + # above: pg_tle needs shared_preload_libraries (mixing pg_tle/non-pg_tle + # installs on one cluster can misbehave), so it needs its own dedicated + # cluster. # # SPECIAL CASES -- apply to one scenario, not the whole matrix: # - # extension-update-test -- PG10 ONLY. The pre-0.2.2 install scripts - # (0.2.0/0.2.1) load on no other major (PG11 - # added pg_attribute.attmissingval; PG12+ exposes - # oid in SELECT *; both trip up those old - # scripts), so this job's only remaining purpose - # is the 0.2.0->0.2.2, 0.2.1->0.2.2, and - # 0.2.2->0.2.3 (view-rebuild) update scripts, on - # the one major that can still run them. Both - # 0.2.0 and 0.2.1 are tested because ALTER - # EXTENSION UPDATE takes the SHORTEST path: a - # 0.2.0 origin updates straight through - # 0.2.0--0.2.2 and never touches 0.2.1--0.2.2, so - # 0.2.1 is the only way to exercise that script. - # pg-upgrade-test -- BINARY pg_upgrade, SPECIFIC old_pg->new_pg - # jump pairs (every major is pg-upgrade-stepwise - # below): install an OLD version on an OLD - # major, binary-upgrade straight to a NEWER - # major (skipping intermediates), then update - # the extension -- proving objects created on an - # old server work when read on a new one. Every - # leg CLIMBS to a PostgreSQL that supports the - # current version, then updates and runs the - # full suite -- no leg stops short. A PG10/11 - # origin HOLDS the extension at 0.2.3 (the - # highest version those majors can reach) until - # PG12+. - # pg-tle-upgrade-test -- The pg_tle-deployed equivalent of - # pg-upgrade-test, on the jump pairs within - # pg_tle's own supported PostgreSQL range. - # pg-upgrade-stepwise -- BINARY pg_upgrade, EVERY major in sequence: - # one cluster climbing 10 -> 11 -> ... -> 18, - # catching a regression specific to one - # major-to-major boundary that a big-jump leg - # (pg-upgrade-test) would skip. + # extension-update-test + # PG10 ONLY. The pre-0.2.2 install scripts (0.2.0/0.2.1) load on no other + # major (PG11 added pg_attribute.attmissingval; PG12+ exposes oid in + # SELECT *; both trip up those old scripts), so this job's only remaining + # purpose is the 0.2.0->0.2.2, 0.2.1->0.2.2, and 0.2.2->0.2.3 + # (view-rebuild) update scripts, on the one major that can still run them. + # Both 0.2.0 and 0.2.1 are tested because ALTER EXTENSION UPDATE takes the + # SHORTEST path: a 0.2.0 origin updates straight through 0.2.0--0.2.2 and + # never touches 0.2.1--0.2.2, so 0.2.1 is the only way to exercise that + # script. + # + # pg-upgrade-test + # BINARY pg_upgrade, SPECIFIC old_pg->new_pg jump pairs (every major is + # pg-upgrade-stepwise below): install an OLD version on an OLD major, + # binary-upgrade straight to a NEWER major (skipping intermediates), then + # update the extension -- proving objects created on an old server work + # when read on a new one. Every leg CLIMBS to a PostgreSQL that supports + # the current version, then updates and runs the full suite -- no leg + # stops short. A PG10/11 origin HOLDS the extension at 0.2.3 (the highest + # version those majors can reach) until PG12+. + # + # pg-tle-upgrade-test + # The pg_tle-deployed equivalent of pg-upgrade-test, on the jump pairs + # within pg_tle's own supported PostgreSQL range. + # + # pg-upgrade-stepwise + # BINARY pg_upgrade, EVERY major in sequence: one cluster climbing + # 10 -> 11 -> ... -> 18, catching a regression specific to one + # major-to-major boundary that a big-jump leg (pg-upgrade-test) would + # skip. # =========================================================================== test: needs: [changes] From 47c09ce21015118d0987bea0b489f63743e328a3 Mon Sep 17 00:00:00 2001 From: jnasbyupgrade Date: Mon, 3 Aug 2026 17:18:36 -0500 Subject: [PATCH 3/3] ci.yml: rebalance the update-to-current check's framing "GUARD-PROVED" was leading the description, making the verification mechanism (a planted dependency guard) read as the headline instead of what the check actually proves: cat_tools updates cleanly to the current version. Reworded both the Test strategy bullet and the test job's step comment so "update to current" is the label, with the dependency guard described as one supporting piece of how that's proven, not the point itself. --- .github/workflows/ci.yml | 52 +++++++++++++++++++++------------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8f12cec..e06a798 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -250,16 +250,17 @@ jobs: # major: # 1. FRESH install -- `make verify-results`, the baseline a brand-new # user gets. - # 2. The GUARD-PROVED update-to-current check: bin/test_existing's - # update-scenario -- CREATE EXTENSION at the 0.2.2 backward-compat - # floor, ALTER EXTENSION UPDATE to current, structurally compare - # against a fresh install, then run the full suite in existing mode. - # USED to be its own matrix job (extension-update-test's PG12+ leg) - # -- folded in here since it runs on the same majors as (1), and - # this job's container, checkout, and cat_tools install are already - # there; a separate job would pay for all of that again for no added - # coverage. See that step's own comment for what was verified - # locally before folding it in. + # 2. UPDATE TO CURRENT: bin/test_existing's update-scenario -- CREATE + # EXTENSION at the 0.2.2 backward-compat floor, ALTER EXTENSION + # UPDATE to current, structurally compare against a fresh install, + # then run the full suite in existing mode. A planted dependency + # guard blocks a stray non-CASCADE drop throughout, proving the + # update didn't just quietly reinstall. USED to be its own matrix + # job (extension-update-test's PG12+ leg) -- folded in here since it + # runs on the same majors as (1), and this job's container, checkout, + # and cat_tools install are already there; a separate job would pay + # for all of that again for no added coverage. See that step's own + # comment for what was verified locally before folding it in. # # pg-tle-test # The SAME majors, proving cat_tools actually works when deployed via @@ -347,23 +348,24 @@ jobs: # documented check. make verify-results - # The guard-proved update-to-current check (see the Test strategy - # comment above). USED to be its own matrix job - # (extension-update-test's PG12+ leg) -- folded in here since it - # runs on these same majors, and this job's container, checkout, - # and cat_tools install are already there; a separate job would - # pay for all of that again for no added coverage. + # The update-to-current check (see the Test strategy comment + # above). USED to be its own matrix job (extension-update-test's + # PG12+ leg) -- folded in here since it runs on these same majors, + # and this job's container, checkout, and cat_tools install are + # already there; a separate job would pay for all of that again + # for no added coverage. # update-scenario creates its own database (cat_tools_update, not # pg_regress's own throwaway db from verify-results above -- - # confirmed no name collision), plants + proves the dependency - # guard, ALTER EXTENSION UPDATEs 0.2.2 to current, structurally - # compares the result against a fresh install (assert_matches_fresh, - # via bin/structural_diff), and runs the full suite against it in - # existing mode. Reusing the SAME suite and expected output asserts - # the updated database behaves identically to a fresh install. See - # extension-update-test below for the PG10-only legacy checks this - # does NOT cover (those pre-0.2.2 scripts don't load on PG12+ at - # all). + # confirmed no name collision), plants a dependency guard (proving + # a stray non-CASCADE drop is blocked throughout, not just that + # the update ran), ALTER EXTENSION UPDATEs 0.2.2 to current, + # structurally compares the result against a fresh install + # (assert_matches_fresh, via bin/structural_diff), and runs the + # full suite against it in existing mode. Reusing the SAME suite + # and expected output asserts the updated database behaves + # identically to a fresh install. See extension-update-test below + # for the PG10-only legacy checks this does NOT cover (those + # pre-0.2.2 scripts don't load on PG12+ at all). # # Verified locally before folding it in: ran `make # check-relkind-source && make verify-results && bin/test_existing