Skip to content

Add TEST_SCHEMA test-harness switch - #54

Closed
jnasbyupgrade wants to merge 9 commits into
Postgres-Extensions:masterfrom
jnasbyupgrade:feature/test-schema
Closed

Add TEST_SCHEMA test-harness switch#54
jnasbyupgrade wants to merge 9 commits into
Postgres-Extensions:masterfrom
jnasbyupgrade:feature/test-schema

Conversation

@jnasbyupgrade

@jnasbyupgrade jnasbyupgrade commented Jul 30, 2026

Copy link
Copy Markdown
Contributor

Add TEST_SCHEMA, a second independent test-harness switch that installs cat_tools while a targeted, non-default schema is the ONLY entry on search_path, following the exact same make-var -> PGOPTIONS -> GUC -> psql propagation pattern already established by TEST_LOAD_SOURCE.

The point: prove cat_tools works correctly even when the cat_tools schema itself is never part of the active search_path -- a normal, legitimate deployment choice for a tooling extension (so it never shadows anything, and callers must always schema-qualify it). If cat_tools' own SQL secretly relied on unqualified name resolution somewhere, it would keep working by accident in an ordinary fresh-install run (which never touches search_path) and only break in that deployment; TEST_SCHEMA exists to force that scenario here instead. Empty (the default) does none of that -- CREATE EXTENSION cat_tools runs exactly as a brand-new user would type it, no WITH SCHEMA clause, landing wherever the session's ambient search_path already resolves. Non-empty creates that schema (quoting it, so mixed-case names work), SETs search_path to ONLY that schema, installs with an explicit WITH SCHEMA cat_tools clause, and asserts afterward that cat_tools never appears in the resolved search_path -- which is what makes any later pgTAP pass in that run actually mean something. \set ON_ERROR_STOP on is set near the top of test/install/load.sql so that assertion (and every other RAISE EXCEPTION in the file) can actually fail the pg_regress run instead of psql printing an error and continuing past it; this already caught a real pg_tle-specific regression once (see below).

A new TEST_LONG_SCENARIOS make variable drives test-long, an explicit list of exactly the scenarios nothing else already covers -- not a full TEST_LOAD_SOURCE x TEST_SCHEMA cross product. fresh:CatToolsSchema and update:CatToolsSchema are the only places TEST_SCHEMA is exercised at all, on the fresh and update paths respectively (the latter also a partial answer to #65, which asks for TEST_SCHEMA coverage on the update path). Both empty-schema combinations are deliberately absent: {fresh, <empty>} is exactly the plain fresh-install/default-schema case make test/installcheck already checks, and {update, <empty>} is exactly what the test job's own guard-proved update-to-current check already proves, more thoroughly (it also plants and proves the dependency guard, and structurally compares against a fresh install), on the same PostgreSQL majors -- see below for that check's own history. Each test-long iteration gates via verify-results, this repo's stricter, documented, pgtap-aware check. CI's test job runs an explicit make verify-results for the fresh/default-schema baseline (restoring what that step always did before this PR, so the baseline isn't silently dropped now that test-long no longer covers it) followed by make test-long, so every supported PostgreSQL major covers the baseline plus both quoting-requiring-schema scenarios, with no separate matrix leg needed for any of them. test-all sequences a quick make test smoke build (gates via test's own regression.diffs check as of pgxntool 2.3.0+, but not as strict as verify-results) with make test-long for a full local pre-push check.

Scope boundary, called out explicitly in the Makefile and the ci.yml "Test strategy" comment rather than left implicit: extension-update-test and pg-upgrade-test do not exercise TEST_SCHEMA at all yet -- they drive the extension through bin/test_existing's own createdb/CREATE EXTENSION/ALTER EXTENSION UPDATE flow, not this Makefile's TEST_LOAD_SOURCE path. Wiring TEST_SCHEMA through the update and pg_upgrade paths is a deliberately deferred follow-up, not an oversight.

A later commit in this PR ("CI: fold the PG12+ guard-proved update-to-current check into the test job, shrink extension-update-test to PG10-only") also fixed a real CI-cost issue found in review: extension-update-test's PG12+ leg ran on the exact same PostgreSQL majors as the test job, but as its own separate matrix job -- its own runner, container boot, checkout, apt-get, and make install, paid again per major, for a check that could instead run as one more step inside a container the test job already has running, checked out, and with cat_tools already installed on disk. Folded bin/test_existing update-scenario cat_tools_update 0.2.2 into the test job's "Test on PostgreSQL" step instead, verified beforehand by running the exact same command sequence in one shell/cluster session locally (confirmed no database-name collision, the dependency-guard proof and the structural-diff check -- from PR #55, landed since this branch's last rebase -- both fire correctly, full suite passes). extension-update-test now runs PG10 only, no matrix, referencing legacy_pg directly (the now-single-consumer update_pg output was removed). No coverage was lost: the PG12+ check still runs on the exact same 7 majors it always did, just folded into an existing job instead of a separate one -- confirmed in a real CI run, and extension-update-test's job count dropped from 8 to 1 while the test job's own per-leg duration stayed within noise of what it was before (~60s either way, since matrix legs run in parallel). The top-of-file "Test strategy" comment is restructured accordingly: what runs on every supported PostgreSQL major (the test job, 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) 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).

Verified locally on scratch PostgreSQL clusters (isolated from the container's shared clusters, since concurrent agents were also exercising cat_tools's shared roles/databases there), including a real pg_tle 1.5.2 build to reproduce and fix a pg_tle-specific regression the ON_ERROR_STOP change exposed: the existing-mode version assertion previously compared against pg_available_extensions.default_version, which is filesystem-based and returns NULL for a pg_tle-only registration; it now reads a cat_tools.pgxn_version GUC instead, mirroring bin/test_existing's own current_version() helper. make test-long runs exactly the two TEST_LONG_SCENARIOS end to end, make verify-results alone covers the baseline, and make test-all runs all of it together -- all passing the full suite with no expected-output divergence.

@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e67ce02c-3ef7-4a5a-8ea0-0dfac1a99c7e

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Comment thread Makefile
Comment thread test/install/load.sql
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Claude Code is working…

I'll analyze this and get back to you.

View job run

1 similar comment
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Claude Code is working…

I'll analyze this and get back to you.

View job run

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Claude Code is working…

I'll analyze this and get back to you.

View job run

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Claude Code is working…

I'll analyze this and get back to you.

View job run

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Claude Code is working…

I'll analyze this and get back to you.

View job run

@jnasbyupgrade jnasbyupgrade added the claude-debug Skip claude-code-review's cost gate and dump the full raw transcript to the job log label Aug 2, 2026
@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 5m 53s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, changed files)
  • Understand the request (code review per /code-review)
  • Review .github/workflows/ci.yml changes
  • Review Makefile changes
  • Review test/install/load.sql changes
  • Check prior automated review comments for context
  • Post final review

Summary

Both issues raised by the earlier automated review on this PR have already been fixed by later commits in this branch:

  • test-all gatingtest-all no longer calls the non-gating test/test-update pair for its update-mode coverage. It now runs test (quick smoke build) followed by test-long, and test-long routes every {TEST_LOAD_SOURCE, TEST_SCHEMA} combination — including update — through verify-results, the documented gate. ✅ resolved.
  • Search-path guard — the guard now checks the resolved side of the pipeline (current_setting('cat_tools.test_schema') <> ALL (current_schemas(false)) in test/install/load.sql:137) instead of pg_namespace, and \set ON_ERROR_STOP on (test/install/load.sql:61) makes RAISE EXCEPTION actually abort the script. ✅ resolved.

I re-reviewed the diff (95fb973..HEAD) fresh against both files for anything new. One finding:

Makefile:131-132 — comment mislabels make test as "non-gating", contradicting this repo's own documented behavior

# Runs every test target that can actually gate on a regression: test (fresh,
# non-gating -- see verify-results above -- but still useful as a quick smoke
# build) plus test-long, ...

CLAUDE.md (this repo's own docs, already current before this PR) states plainly: "make test returns non-zero on test regressions (pgxntool 2.3.0+): ... test's own recipe now checks test/regression.diffs and exits non-zero if it's non-empty." pgxntool/base.mk's test: recipe confirms this (@if [ -r $(TESTOUT)/regression.diffs ]; then cat ...; exit 1; fi). This PR's own ci.yml comment (lines 329-331) gets this right ("test's own recipe now exits non-zero as soon as it sees a regression"). So the new Makefile comment directly contradicts both CLAUDE.md and the parallel comment added in ci.yml in the same PR.

It's a comment-only inaccuracy (doesn't change test-all's actual behavior — test-long's verify-results calls are still the real gate either way), but it will mislead a future reader into thinking a local make test failure isn't a real signal, exactly the misconception CLAUDE.md's Bug Fixes section asks us to avoid perpetuating. Suggest rewording along the lines of: "test (fresh; gates via test's own regression.diffs check, pgxntool 2.3.0+, but not as strict as verify-results's pgtap-aware check -- still useful as a quick smoke build)".

Worth confirming, not a defect

test's "Test on PostgreSQL" step now runs make test-long instead of a single make verify-results — that's a ~4x increase in full-suite runs per matrix leg (2 TEST_LOAD_SOURCE × 2 TEST_SCHEMA), across all 7 supported majors (PG12–18). The PR description acknowledges the trade-off (comprehensive coverage without a separate matrix leg), so this looks deliberate rather than an oversight — just flagging the wall-clock cost in case it wasn't fully weighed, per this repo's own .github/workflows/CLAUDE.md guidance on CI time.

Everything else checked out: TEST_SCHEMAS ?= "" CatToolsSchema expands correctly in the test-long shell loop (the embedded "" is a real empty-string shell word, not swallowed by Make), the CREATE SCHEMA IF NOT EXISTS cat_tools/WITH SCHEMA ordering correctly avoids the extension "owning" a schema it didn't create (so DROP EXTENSION CASCADE won't drop it), the fixture's SET search_path doesn't leak into the actual pgTAP suite (separate connections), and all \endif/\if blocks are labeled per CLAUDE.md's non-indentable-block convention.

No code changes made — this was a review-only request.

@github-actions

github-actions Bot commented Aug 2, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 2m 22s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, prior review comments)
  • Review .github/workflows/ci.yml changes
  • Review Makefile changes
  • Review test/install/load.sql changes
  • Check whether prior review feedback (automated + human) has been addressed
  • Post final review

Summary

Both substantive issues flagged by the earlier automated review (2026-08-01) are resolved by the latest commits:

  • test-all gating gap (Makefile:158 comment) — test-all no longer calls the non-gating test/test-update pair for update-mode coverage. It's now $(MAKE) test (quick smoke build) followed by $(MAKE) test-long (Makefile:154-157), and test-long routes every {TEST_LOAD_SOURCE, TEST_SCHEMA} combination — including update:CatToolsSchema — through verify-results, the documented gate. ✅ resolved.
  • Search-path guard checking the wrong side / not fatal (test/install/load.sql:147 comment) — the guard now checks the resolved search_path (current_setting('cat_tools.test_schema') <> ALL (current_schemas(false)), test/install/load.sql:137) instead of pg_namespace, and \set ON_ERROR_STOP on (test/install/load.sql:61) makes RAISE EXCEPTION actually abort the script instead of psql printing and continuing. ✅ resolved.

The most recent commit (4272a4e) also fixes the follow-up finding from the automated review's last pass: the Makefile:145-148 comment previously mislabeled make test as non-gating, contradicting this repo's own CLAUDE.md ("make test returns non-zero on test regressions, pgxntool 2.3.0+") and the parallel comment already in ci.yml. I independently confirmed the underlying claim against the vendored pgxntool/base.mk: test: $(TEST_DEPS) does exit 1 on a nonempty regression.diffs (line 376), and verify-results deliberately depends on $(TEST_DEPS) directly rather than on test (lines 404-409) precisely so test's own early exit doesn't abort the chain before verify-results gets to inspect and report the diff — exactly what the Makefile's updated comment (Makefile:145-148) and ci.yml's parallel comment (lines 337-341) both now say. The wording is accurate.

I re-read both files in full against the PR description's claims (propagation of TEST_SCHEMA through PGOPTIONS, the TEST_LONG_SCENARIOS shell-loop parsing, \if/\endif nesting, and the CI job comments in ci.yml's "Test strategy" block) and didn't find anything new to flag:

  • TEST_SCHEMAS/TEST_LONG_SCENARIOS parsing (Makefile:112,128-133) is correct: ${scenario%%:*} / ${scenario#*:} split on the first colon as documented, and the three kept scenarios (fresh:, fresh:CatToolsSchema, update:CatToolsSchema) match what's described.
  • CREATE SCHEMA IF NOT EXISTS/WITH SCHEMA ordering (test/install/load.sql:247-260) correctly avoids the extension auto-creating (and thus "owning," for DROP EXTENSION CASCADE purposes) a schema it shouldn't.
  • The \if :cat_tools_mode_existing / \if :cat_tools_has_schema nesting is consistent, and every non-indentable closer (\endif) has the required trailing label comment per CLAUDE.md's convention.
  • The pg_tle-regression fix (existing-mode version check now reads cat_tools.pgxn_version instead of pg_available_extensions.default_version, test/install/load.sql:184-212) mirrors bin/test_existing's own current_version() helper as claimed.
  • ci.yml's "Test strategy" comment block (lines 242-301) accurately reflects the test job's make test-long step and calls out the extension-update-test/pg-upgrade-test TEST_SCHEMA scope boundary with a real issue link (#65), consistent with CLAUDE.md's full-URL-for-open-TODOs rule.

No code changes made — this was a review-only request, and no new findings survived scrutiny.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 2m 24s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, prior review comments)
  • Review .github/workflows/ci.yml changes
  • Review Makefile changes
  • Review test/install/load.sql changes
  • Check whether prior review feedback has been addressed since last Claude review
  • Post final review

Summary

This review focuses on what's new since the last Claude review (4272a4e): a single follow-up commit, 02a64a2 ("Narrow test-long to exactly the two scenarios nothing else covers, and restore an explicit baseline check in CI"). test/install/load.sql is unchanged since then, so both issues from the two earlier automated reviews remain resolved:

  • test-all gating gap — no longer applicable in its original form; test-all (Makefile:160-163) now runs make test followed by make test-long, and test-long's TEST_LONG_SCENARIOS (Makefile:118) routes both remaining scenarios through verify-results.
  • Search-path guard checking the wrong side / non-fataltest/install/load.sql:137 checks the resolved current_schemas(false), and \set ON_ERROR_STOP on (test/install/load.sql:61) makes it fatal. ✅ still resolved.
  • Stale "test is non-gating" comment — fixed in 4272a4e, still accurate as of Makefile:151-152.

What changed in 02a64a2: TEST_LONG_SCENARIOS dropped fresh: (the empty-schema baseline) in addition to the already-dropped update: (Makefile:118), and ci.yml's test job step now runs an explicit make verify-results (.github/workflows/ci.yml:328) before make test-long (.github/workflows/ci.yml:351) to restore baseline coverage through the strict gate. I checked this restructuring for correctness:

  • The Makefile:84-117 and ci.yml:249-273 comments are internally consistent with each other and with the actual TEST_LONG_SCENARIOS ?= fresh:CatToolsSchema update:CatToolsSchema value — no drift between the documented rationale and the code.
  • CI wall-clock is unchanged overall: previously test-long alone ran the suite 3x per major; now it's 1x explicit verify-results + 2x test-long iterations = still 3x. This addresses the earlier "worth confirming" wall-clock note from the prior review — no net increase.
  • One asymmetry, not a defect: test-all (Makefile:160-163) still gates its {fresh, <empty>} leg via plain make test (test's own regression.diffs check, pgxntool 2.3.0+) rather than the stricter verify-results that CI's test job now explicitly uses for the same scenario (.github/workflows/ci.yml:328). This is a real, if minor, difference between local test-all and CI's actual gate for that one case, but it's a deliberate, documented smoke-test/full-gate tradeoff (Makefile:151-159), not a silent gap — test does still fail on genuine regressions, just via the less pgtap-aware check. Not flagging as a required fix.
  • Confirmed bin/test_existing (invoked only by CI's separate extension-update-test job, not by any Makefile target) is what actually backs the claim that {update, <empty>} is proven "more thoroughly" elsewhere — it runs the full suite in existing mode via run-suite, not just a structural check, so the redundancy claim holds.

No new issues found. Nothing to fix.

@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 1m 15s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, prior review comments)
  • Review .github/workflows/ci.yml changes
  • Review Makefile changes
  • Review test/install/load.sql changes
  • Check whether prior review feedback has been addressed since last Claude review
  • Post final review

Summary

This review covers what's new since the last Claude review (02a64a2): a single follow-up commit, d307f93 ("Add a top-of-file summary comment for the four test targets"). It only touches Makefile (+11 lines), adding a short summary block above the existing detailed per-target comments. ci.yml and test/install/load.sql are unchanged since the last review, so both issues from the two earlier automated reviews remain resolved:

  • test-all gating gaptest-all (Makefile:171-174) runs make test then make test-long, and test-long's TEST_LONG_SCENARIOS routes both remaining scenarios through verify-results. ✅ resolved.
  • Search-path guard checking the wrong side / non-fataltest/install/load.sql:137 checks the resolved current_schemas(false), and \set ON_ERROR_STOP on makes it fatal. ✅ resolved.
  • Stale "test is non-gating" comment — fixed in 4272a4e, still accurate (Makefile:162-163).

Checked the new summary comment (Makefile:3-12) for accuracy against the code it summarizes:

  • test — "fresh install, default schema. The baseline check." matches TEST_LOAD_SOURCE ?= fresh / TEST_SCHEMA ?= defaults.
  • test-update — matches the recursive $(MAKE) test TEST_LOAD_SOURCE=update wrapper at Makefile:158-160.
  • test-long — "ONLY the scenarios nothing else covers ... Deliberately excludes anything test/test-update/CI's other jobs already check" matches TEST_LONG_SCENARIOS ?= fresh:CatToolsSchema update:CatToolsSchema (Makefile:129) and its surrounding rationale comment.
  • test-all — "test + test-long: the full local pre-push gate" matches the recipe at Makefile:171-174.

No drift between the new summary and the detailed comments/code it points at, and nothing in this repo treats leading Makefile comments as machine-parsed documentation (no help:-style target-doc generator here), so there's no risk of the new block being mis-attributed to testdeps or another target. This is a comment-only, low-risk addition.

No new issues found. Nothing to fix.

…ls cat_tools while a targeted, non-default schema is the ONLY entry on search_path, following the exact same make-var -> PGOPTIONS -> GUC -> psql propagation pattern already established by TEST_LOAD_SOURCE.

The point: prove cat_tools works correctly even when the cat_tools schema itself is never part of the active search_path -- a normal, legitimate deployment choice for a tooling extension (so it never shadows anything, and callers must always schema-qualify it). If cat_tools' own SQL secretly relied on unqualified name resolution somewhere, it would keep working by accident in an ordinary fresh-install run (which never touches search_path) and only break in that deployment; TEST_SCHEMA exists to force that scenario here instead. Empty (the default) does none of that -- CREATE EXTENSION cat_tools runs exactly as a brand-new user would type it, no WITH SCHEMA clause, landing wherever the session's ambient search_path already resolves. Non-empty creates that schema (quoting it, so mixed-case names work), SETs search_path to ONLY that schema, installs with an explicit WITH SCHEMA cat_tools clause, and asserts afterward that cat_tools never appears in the resolved search_path -- which is what makes any later pgTAP pass in that run actually mean something. \set ON_ERROR_STOP on is set near the top of test/install/load.sql so that assertion (and every other RAISE EXCEPTION in the file) can actually fail the pg_regress run instead of psql printing an error and continuing past it; this already caught a real pg_tle-specific regression once (the existing-mode version assertion used to compare against pg_available_extensions.default_version, which is filesystem-based and returns NULL for a pg_tle-only registration -- fixed by reading a new cat_tools.pgxn_version GUC instead, mirroring bin/test_existing's own current_version() helper).

A new TEST_LONG_SCENARIOS make variable drives test-long, an explicit list of exactly the scenarios nothing else already covers -- not a full TEST_LOAD_SOURCE x TEST_SCHEMA cross product. fresh:CatToolsSchema and update:CatToolsSchema are the only places TEST_SCHEMA is exercised at all (the latter also a partial answer to Postgres-Extensions#65, which asks for TEST_SCHEMA coverage on the update path). Both empty-schema combinations are deliberately absent: {fresh, <empty>} is exactly the plain fresh-install/default-schema case make test/installcheck already checks, and {update, <empty>} is exactly what CI's extension-update-test job already proves, more thoroughly, on the same PostgreSQL majors. Each test-long iteration gates via verify-results, this repo's stricter, documented, pgtap-aware check. CI's test job runs an explicit make verify-results for the fresh/default-schema baseline (restoring what that step always did before this PR) followed by make test-long, so every supported PostgreSQL major covers the baseline plus both quoting-requiring-schema scenarios, with no separate matrix leg needed for any of them. test-all sequences a quick make test smoke build with make test-long for a full local pre-push check. A short top-of-file summary comment maps all four test targets (test, test-update, test-long, test-all) for a reader who doesn't want to piece the picture together from four separate comment blocks.

Scope boundary, called out explicitly rather than left implicit: extension-update-test and pg-upgrade-test do not exercise TEST_SCHEMA at all yet. Wiring TEST_SCHEMA through the update and pg_upgrade paths is a deliberately deferred follow-up, not an oversight.
…t` 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/test-long calls). 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 && make test-long && 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, landed via PR Postgres-Extensions#55 since this branch's last rebase) 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 (supported_pg + legacy_pg) 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).

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-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 2m 12s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, prior review comments)
  • Review .github/workflows/ci.yml changes since last review
  • Review Makefile changes since last review
  • Review test/install/load.sql changes since last review
  • Post final review

Summary

test/install/load.sql and Makefile are byte-for-byte unchanged since the last Claude review (which found no outstanding issues, and coderabbitai APPROVED). The only new content is one commit, c12d0bd ("CI: fold the PG12+ guard-proved update-to-current check into the test job, shrink extension-update-test to PG10-only"), touching only .github/workflows/ci.yml. I reviewed it in full against the diff and the rest of the file:

  • The fold is structurally sound. extension-update-test's PG12+ leg (bin/test_existing update-scenario cat_tools_update 0.2.2) moved into the test job's "Test on PostgreSQL" step, after make verify-results and make test-long (ci.yml:407). bin/test_existing update-scenario createdbs its own database (cat_tools_update), independent of pg_regress's own throwaway database from the earlier make calls — confirmed by reading bin/test_existing (unchanged by this PR), matching the commit message's claim of "no database-name collision."
  • Install ordering holds. The step never calls make install directly before bin/test_existing update-scenario, but per this repo's own CLAUDE.md/pgxntool docs, installcheck (a dependency of verify-results/test-long, both of which ran first) unconditionally depends on install — so cat_tools is already on disk by the time bin/test_existing runs, as the comment at ci.yml:390-392 claims.
  • extension-update-test job correctly shrunk. The matrix (strategy.matrix.pg) is removed entirely; the job now hardcodes nothing (PG: needs.changes.outputs.legacy_pg, single source of truth), the PG12+-only step ("Update 0.2.2 → current...") is deleted rather than orphaned, and the surviving steps' if: matrix.pg == '10' / != '10' guards are correctly stripped now that the job has no other leg. Grepped the whole file for stray matrix.pg or update_pg references (both removed) — none left.
  • changes job output cleanup is complete. update_pg output, its derivation (update="$supported $LEGACY_FLOOR"), and its steps.pg.outputs.update_pg line are all removed together; all-checks-passed's needs: list and its jobs-match self-check (ci.yml:1057-1058) still enumerate extension-update-test/pg-tle-test/etc. by job name, which is unaffected by the matrix removal.
  • Comments are consistent with the code they describe — the restructured "Test strategy" block (ci.yml:242-338) accurately separates MAIN MATRIX (test, pg-tle-test) from SPECIAL CASES, and matches the per-job comments and the actual needs/if conditions.

No new issues found in this commit. Nothing to fix.

A real timing test showed a single `make verify-results` run takes ~1.1s (a tiny suite) -- the scenario-exclusion logic TEST_LONG_SCENARIOS added was solving for "avoid wasting CI time re-running the suite," but re-running it costs about a second, not worth the complexity it bought. The real CI cost is container/cluster bring-up (~40s/job) and pg-upgrade-stepwise, not suite invocations.

Removed TEST_LONG_SCENARIOS, its scenario-tuple shell-parsing loop, and every comment describing the old 2/3/4-combination cross-product design. In its place:

- `test-schema` (new): `$(MAKE) test TEST_SCHEMA=CatToolsSchema`.
- `test-update` (unchanged): stays simple/no-schema, symmetric with `test` -- resolves the "what does test-update do about schema" ambiguity by giving it none.
- `test-update-schema` (new): `$(MAKE) test TEST_LOAD_SOURCE=update TEST_SCHEMA=CatToolsSchema` -- the one scenario nothing else covers (also a partial answer to issue Postgres-Extensions#65).
- `test-long`: now a thin wrapper, `test-long: test-schema test-update-schema` -- bundles every test-* target too situational for plain test/test-update but not worth its own CI step. As the suite grows, a new such target just gets added to this prerequisite list.
- `test-all`: thin wrapper, `test-all: test test-update test-long`.

A single `.NOTPARALLEL: test test-schema test-update test-update-schema test-long test-all` covers the whole family, so test-long/test-all can use plain bare prerequisites instead of sequential $(MAKE) calls in each recipe body. Verified this is safe here specifically: grepped ci.yml/Makefile/sql.mk/lint.mk/pgxntool's own .mk files and docs -- nothing in this build ever invokes `-j`. Also verified GNU Make 4.3's actual .NOTPARALLEL behavior empirically (a throwaway two-target Makefile under `make -j4`): listing explicit targets does NOT scope narrowly to just those targets, it forces full serialization of the whole invoked build graph -- so declaring it once for the whole family gives up nothing narrower than what .NOTPARALLEL already does even when scoped "correctly," and there's no real -j parallelism anywhere in this build to lose regardless.

Verified locally against a scratch cluster: real output for test-schema, test-update-schema, test-long (2 suite runs), and test-all (4 suite runs) all passing. Then deliberately broke two independent regressions and confirmed each new target actually fails loudly rather than assuming test-update's existing precedent carries over safely: (1) reintroduced the schema-quoting bug in test/install/load.sql (unquoted SET search_path) -- `make test-schema` failed with exit 2, cascading pgTAP failures from the missing schema; (2) commented out a GRANT in sql/cat_tools--0.2.3--0.3.0.sql.in that only the update path depends on (a fresh install grants it directly) -- `make test-update-schema` failed with exit 2, a real permission-denied failure. Reverted both and confirmed clean passes again. This confirms pgxntool 2.3.0's test-exits-nonzero-on-regression behavior is a real gate for these two new targets, not just assumed from test-update's own precedent.

ci.yml's `test` job step updated to match: `make verify-results` (baseline, unchanged mechanism) followed by `make test-long` (now bundling test-schema/test-update-schema) followed by the guard-proved update-to-current check (unchanged from last round). Updated the top "Test strategy" summary block's description of what test-long bundles. Left a clarifying comment on issue Postgres-Extensions#65 noting its "Proposed approach" section's test-long example describes the now-replaced scenario-loop shape, though the issue's core ask (extension-update-test/pg-upgrade-test still don't exercise TEST_SCHEMA) is unaffected either way.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 2m 53s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, prior review comments)
  • Review the single new commit (0341d79) since the last Claude review
  • Check for stale references to the removed design
  • Post final review

Summary

This review covers what's new since the last Claude review (c12d0bd): one commit, 0341d79 ("Replace test-long's scenario-tuple design with named test-* targets"), touching Makefile and .github/workflows/ci.yml only. test/install/load.sql is unchanged, so all previously-resolved issues (search-path guard checking the resolved side + ON_ERROR_STOP, test-all gating gap) remain resolved.

What changed: the old TEST_LONG_SCENARIOS shell-loop (iterating "load_source:schema" pairs) is replaced with plain named targets — test-schema, test-update-schema (new), plus test-long: test-schema test-update-schema and test-all: test test-update test-long as thin bare-prerequisite wrappers, serialized by a single .NOTPARALLEL: test test-schema test-update test-update-schema test-long test-all.

I traced the resulting dependency graph and recipe bodies for correctness:

  • test, test-schema, test-update, test-update-schema all still recurse via $(MAKE) test ... (required so TEST_LOAD_SOURCE/TEST_SCHEMA's parse-time defaults re-evaluate in a fresh sub-make) — unchanged reasoning from before, just no longer needed for test-long/test-all since those now use bare prerequisites instead of sequential $(MAKE) calls.
  • test-long/test-all's bare prerequisites are legitimate here: test is already .PHONY in pgxntool/base.mk:370, and every new target is declared .PHONY (Makefile:117,139,164,171). No target appears twice in the graph, so under the .NOTPARALLEL serialization nothing double-runs or races against the shared throwaway test database.
  • Confirmed via grep that no -j/MAKEFLAGS usage exists anywhere in ci.yml, this Makefile, or pgxntool/*.mk — consistent with the commit message's claim, and consistent with pgxntool/base.mk:411-414's own pre-existing parallel-build caution around verify-results/$(TEST_DEPS).
  • ci.yml's test job step (verify-resultstest-long → the guard-proved update-to-current check) and its updated "Test strategy" comment block (ci.yml:255-261) accurately describe the new bundling; no stale references to the removed TEST_LONG_SCENARIOS design remain anywhere (grep -rn TEST_LONG_SCENARIOS across .yml/Makefile/.md/.sql returns nothing).
  • CatToolsSchema is hardcoded identically in both test-schema and test-update-schema recipes — no drift between them.

One point worth noting but not a defect: the top-of-file comment (Makefile:143-154) asserts GNU Make 4.3's .NOTPARALLEL: a b doesn't scope narrowly to the listed targets "even in principle." Newer GNU Make (4.4+) does scope .NOTPARALLEL to just its listed prerequisites — but since the targets listed here are exactly the ones that need serializing, that scoping (if the running Make version has it) is still correct and sufficient; the declaration works either way, so this doesn't affect actual behavior. Not flagging as an issue.

No new issues found. Nothing to fix.

…iants

The previous round incorrectly carried over a CI-cost duplication argument (that the {update, <empty>} scenario shouldn't run twice across two separate CI jobs) into test-long's own local composition, where it doesn't apply. test-long/test-all are local dev convenience bundles, not CI cost centers -- that CI-level concern is already fully and correctly handled by the fold-into-test-job/shrink-extension-update-test change from two rounds ago, which is unaffected by this fix.

The rule for test-long is simple inclusion: every test-* target except test itself, full stop. test-long now depends on test-update, test-schema, and test-update-schema (previously just the latter two). test-all simplifies to test + test-long (test-update moved out from directly under test-all since it's now reached via test-long).

Verified with real output: `make test-long` now runs `make test TEST_LOAD_SOURCE=update`, `make test TEST_SCHEMA=CatToolsSchema`, and `make test TEST_LOAD_SOURCE=update TEST_SCHEMA=CatToolsSchema` (three invocations, three suite passes), and `make test-all` runs all four (adding the plain baseline). Both exit 0. `.NOTPARALLEL` already listed test-update, so no change needed there.
Many run: script blocks had the next section's comment starting immediately on the line right after the previous command, with no separator -- so each comment+command section wasn't visually demarcated from the next one. Added a blank line after a command whenever a new comment block (documenting the NEXT, sibling command) immediately follows, throughout the whole file (not just this PR's own changes).

Left untouched, deliberately: comments that are the first line right after an if/elif/else opener (they document what follows within that new block, not a separate sibling section after a completed one -- the pattern this fix targets), and everything inside heredocs (the verify-cancel-on-close-coupling job's embedded Python script) since altering blank-line structure there touches different-language content, not this file's own comment/command structure.

Pure whitespace -- verified the file still parses as valid YAML and make lint still passes.
…oal, not isolation

Isolation (dedicated cluster, filesystem-cleanliness checks) is necessary for pg_tle testing to mean anything, but it isn't the goal -- the goal is proving cat_tools actually works correctly when deployed via pg_tle, across the same fresh-install and update-path scenarios the filesystem matrix already covers. Reworded the summary to lead with that, with isolation explained as the precondition that makes the proof trustworthy rather than the point of the exercise.

Comment-only: no job, matrix, or CI-behavior change. Scope stays exactly as it is today (pg-tle-test's fresh install + update path, pg-tle-upgrade-test's 2 jump legs, no pg_tle stepwise job) -- a fuller pg_tle matrix expansion is tracked separately, not described here as upcoming.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 2m 32s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, prior review comments)
  • Identify what's new since the last Claude review
  • Review the new commit(s) for correctness
  • Post final review

Summary

This review covers what's new since the last Claude review (0341d79): three commits — c12d0bd was already covered previously; the new ones are 9f8d5d8 ("Fix test-long: include test-update, not just the schema-targeting variants"), 9f70026 (blank-line whitespace only), and 91277a5 (comment reword only). test/install/load.sql remains unchanged, so all previously-resolved issues (search-path guard checking the resolved side + ON_ERROR_STOP, test-all gating gap) still stand resolved.

9f70026 and 91277a5 are low-risk, comment/whitespace-only changes and check out fine — the reworded pg-tle-test summary (ci.yml:282-301) accurately leads with the correctness goal and reframes isolation as the precondition, and the blank-line insertions don't touch any command logic.

9f8d5d8 introduces a real inconsistency: its own justification is contradicted by how CI actually invokes test-long

Makefile:167 now has test-long: test-update test-schema test-update-schema (previously just test-schema test-update-schema). The commit justifies this via a new comment at Makefile:155-162:

"The CI-cost concern that used to shape which scenarios ran where is handled entirely at the ci.yml level ... and does NOT apply here: test-long/test-all are local dev convenience bundles, not CI cost centers."

That claim is false: .github/workflows/ci.yml:400 calls make test-long directly inside the test job's per-PostgreSQL-major matrix step, which runs on all 7 supported majors (ci.yml:351-360). test-long is not purely a local-dev target — it's already a CI cost center, on every matrix leg.

Concretely, this re-adds, inside CI, the exact {update, <empty-schema>} duplication that an earlier commit in this same PR (c12d0bd) deliberately eliminated by folding the guard-proved update-to-current check into the test job and shrinking extension-update-test to PG10-only. test-update (now pulled in via test-long) runs TEST_LOAD_SOURCE=update with the default (empty) schema — a plain update-path suite pass — while the guard-proved update-scenario check a few lines later in the same step (ci.yml:402-419) already proves that same scenario "more thoroughly" (dependency-guard proof + structural diff against a fresh install), per this PR's own earlier stated reasoning for keeping {update, <empty>} out of test-long's scenario list. So the test job's per-major step now runs a fourth full suite pass (verify-results, then test-update + test-schema + test-update-schema via test-long, then the update-scenario check) where three used to suffice — across all 7 majors.

Compounding this, ci.yml's own comments weren't updated to match: the top-of-file "Test strategy" block (ci.yml:260-264) and the step comment (ci.yml:387-399) both still describe test-long as bundling only test-schema/test-update-schema, explicitly asserting "nothing else, not the verify-results call above, not the update-scenario call below, covers either" — which no longer matches what test-long actually runs as of 9f8d5d8.

Suggest either:

  • (a) Revert test-long's prerequisite list to just test-schema test-update-schema, restoring the CI-cost exclusion (the "simple inclusion" framing in the new Makefile comment can still apply to genuinely-local-only convenience, just not by asserting test-long is CI-invisible), or
  • (b) Keep test-update in test-long if the redundant coverage is intentionally accepted, but fix the false claim at Makefile:161-162 and update the stale ci.yml:261-264/387-399 comments to describe the new composition and acknowledge the added full-suite run per major.

Fix this →

No other new issues found in this round.

…e-scenario check

Comment-only, no behavior change. test-update's inclusion in test-long (kept exactly as instructed) means CI's test job -- which calls make test-long directly, on every supported PostgreSQL major -- now also re-proves part of what that same job's guard-proved update-scenario check already proves more thoroughly. The Makefile's test-long comment claimed test-long/test-all are local dev convenience bundles, not CI cost centers, which is false: test-long is invoked directly from CI. ci.yml's step comment similarly claimed test-long covers nothing update-scenario also covers.

Both now state plainly that this overlap is real and deliberately accepted: a single make test pass costs about a second, so one more of them per matrix leg is a different class of cost entirely from the separate-job overhead (~55s per leg) that folding update-scenario into the test job was specifically done to avoid two rounds ago.
@github-actions

github-actions Bot commented Aug 3, 2026

Copy link
Copy Markdown

Claude finished @jnasbyupgrade's task in 48s —— View job


Claude finished reviewing PR #54

  • Gather context (diff, CLAUDE.md, prior review comments)
  • Identify what's new since the last Claude review
  • Review the new commit(s) for correctness
  • Check whether the previously-flagged test-long/test-update inconsistency was addressed
  • Post final review

Summary

This review covers what's new since the last Claude review (9f8d5d8/9f70026/91277a5): one commit, 9359bb7 ("Fix stale comments claiming test-long has zero overlap with the update-scenario check"), touching only Makefile and .github/workflows/ci.yml comments (no behavior change). test/install/load.sql remains unchanged, so all previously-resolved issues (search-path guard checking the resolved side + ON_ERROR_STOP, test-all gating gap, stale "test is non-gating" comment) still stand resolved.

This commit directly fixes the inconsistency flagged in the previous review round. That review found Makefile:161-162's claim that "test-long/test-all are local dev convenience bundles, not CI cost centers" was false, since ci.yml's test job calls make test-long directly on every supported PostgreSQL major — and that test-update's inclusion in test-long re-adds real overlap with the guard-proved update-scenario check a few lines later in the same step, contradicted by comments claiming zero overlap.

I re-read both files' updated comments against the actual code and confirmed the fix is accurate and complete:

  • Makefile:157-172 now states plainly that test-long is "NOT purely a local-dev target" since CI's test job calls it directly on every major, and explicitly acknowledges test-update's overlap with update-scenario (dependency-guard proof + structural diff) as "real, acknowledged overlap, not an oversight" — matching what test-long: test-update test-schema test-update-schema (Makefile:170) actually runs.
  • ci.yml:257-271 (top-of-file "Test strategy" block) and ci.yml:397-414 (the test job's step comment) both dropped the false "nothing else... covers either" claim and now describe test-long as "every test-* target except plain test itself," calling out the same overlap and the same cost-justification (a ~1s make test pass per major vs. the ~55s separate-job overhead that folding update-scenario into the test job was done to avoid).
  • The stated cost rationale is internally consistent across both files — no drift between the Makefile's reasoning and ci.yml's restatement of it, and no lingering references anywhere to the old "zero overlap" framing (grepped both files for the removed phrasing).
  • This is comment-only, as the commit message claims — diffed against 9f8d5d8's actual test-long: test-update test-schema test-update-schema prerequisite list and confirmed it's unchanged by this commit.

No new issues found. The previously-flagged inconsistency is fully resolved.

@jnasbyupgrade
jnasbyupgrade marked this pull request as draft August 3, 2026 20:20
The prior comment framed test-long's test-update target as "real, accepted
overlap" with bin/test_existing's update-scenario check, tolerated because a
`make test` pass is cheap. That's wrong: they exercise different code paths
entirely. test-update drives test/install/load.sql's own committed update
branch (CREATE EXTENSION VERSION 0.2.2, then ALTER EXTENSION UPDATE, inside
the pre-suite install step). update-scenario issues its ALTER EXTENSION
UPDATE directly via psql, outside load.sql entirely, then runs the suite in
TEST_LOAD_SOURCE=existing mode (load.sql's assert-only branch). A bug in
load.sql's update-mode logic is only caught by test-update; a bug in the
guard/structural-diff logic is only caught by update-scenario. Rewrote the
Makefile's test-long comment and ci.yml's Test strategy block and `test`
job step comment to say so plainly.

Also added a note near pg-upgrade-test/pg-upgrade-stepwise: post-upgrade we
currently only assert the version landed and run the base suite, not every
dimension the main matrix covers (TEST_SCHEMA, or whatever test-long grows
to). Tied to Postgres-Extensions#65
(also just broadened there to explicitly cover pg-tle-test, which has the
same TEST_SCHEMA gap) rather than opening a new issue.

Trimmed wordiness in the comments touched this PR without dropping any of
the underlying reasoning.
ci.yml's own "Test strategy" NOTE already names five jobs that don't
exercise TEST_SCHEMA (extension-update-test, pg-upgrade-test,
pg-tle-upgrade-test, pg-upgrade-stepwise, pg-tle-test) -- this comment
still only named the first two. All five equally drive the extension
through bin/test_existing's shell-level flow, bypassing this Makefile's
TEST_SCHEMA machinery the same way.
jnasbyupgrade added a commit to jnasbyupgrade/cat_tools that referenced this pull request Aug 3, 2026
Distilled from PR Postgres-Extensions#54's back-and-forth over where TEST_SCHEMA and the
update-testing check should live: a make-level dimension runs locally
and never costs a container/job, while a ci.yml-level one always does
unless deliberately batched -- which is its own added complexity. The
one real exception is when a dimension's whole point is isolation
(pg_tle needing its own cluster), not just another combination to run.
@jnasbyupgrade jnasbyupgrade removed the claude-debug Skip claude-code-review's cost gate and dump the full raw transcript to the job log label Aug 3, 2026
jnasbyupgrade added a commit to jnasbyupgrade/cat_tools that referenced this pull request Aug 3, 2026
Prompted directly by PR Postgres-Extensions#54/Postgres-Extensions#75 turning into hard-to-follow walls of
text (a real contributor to a costly mid-PR mix-up), versus Postgres-Extensions#74's own
description staying easy to follow despite covering real backstory.
Length past the opening isn't the problem -- an unstructured mass of
prose is.
@jnasbyupgrade

Copy link
Copy Markdown
Contributor Author

Closing without merging -- the whole premise of this PR turned out to be a mistaken one, confirmed directly by the maintainer.

Root cause of the mistake: cat_tools' control file pins schema = 'cat_tools' with relocatable = false -- it can never be installed into a user-chosen schema, full stop. TEST_SCHEMA was built around the idea of testing "user-specified custom schema" vs. "wherever it lands on search_path" (the shape that makes sense for an extension whose control file does not pin a schema, e.g. pg_count_nulls or extension_tools in this same org). That question never applied to cat_tools -- there is no "which schema" choice to test, so a whole GUC-driven second install path/dimension (TEST_SCHEMA, test-schema/test-update-schema targets, a WITH SCHEMA clause-building toggle in test/install/load.sql) was solving a problem that doesn't exist here. Confirmed empirically along the way too: CREATE EXTENSION cat_tools WITH SCHEMA cat_tools even errors unless that exact schema already exists -- there's no "explicit schema" mode that behaves any differently from a plain CREATE EXTENSION cat_tools.

What was actually worth keeping, extracted into two small, focused PRs, both green:

Everything else here -- the TEST_SCHEMA GUC itself, test-schema/test-update-schema, test-long's original schema-scenario motivation, the WITH SCHEMA toggle, the TEST_TARGETS idea -- is dropped, not deferred.

Issue #65 (which assumed TEST_SCHEMA coverage was a real, worthwhile CI gap to close for extension-update-test/pg-upgrade-test/pg-tle-test) is being closed as moot for the same reason.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant