From dca99fde0b0dc1af53908bb5c1faa160485b9794 Mon Sep 17 00:00:00 2001 From: jnasbyupgrade Date: Wed, 12 Aug 2026 16:05:21 -0500 Subject: [PATCH] Adopt the stable pseudo-version convention (per ../ai/RELEASE.md) Standalone from issue #14's actual fix: default_version was pinned at a real, already-released version number (test_factory: 0.5.0, test_factory_pgtap: 0.1.0) the whole time between releases, meaning any ordinary source edit would silently regenerate -- and corrupt -- that frozen, already-shipped version's install script via pgxntool's own auto-generation. Set default_version = 'stable' in both control files so edits regenerate a disposable sql/--stable.sql instead. Added a genuine no-op update script for each extension (sql/test_factory--0.5.0--stable.sql, sql/test_factory_pgtap--0.1.0--stable.sql): Postgres's version-graph resolution requires an actual file to exist for ALTER EXTENSION ... UPDATE to have any path at all, regardless of whether its content would be a no-op (confirmed directly: without it, "has no update path from version 0.5.0 to version stable"). This distribution provides two extensions, so both get one, kept between releases regardless of which one(s) a given change actually touches -- that's what lets a release decide per-extension whether it needs a new version at all, by inspecting whether its own file has real content (see the forthcoming ../ai/RELEASE.md update for the full procedure). Gitignored the generated current-snapshot files (sql/test_factory--stable.sql, sql/test_factory_pgtap--stable.sql) -- named exactly, not via a sql/*--stable.sql glob, which also matches across the update scripts' second -- and would incorrectly sweep those up too (caught directly: they silently stopped showing as untracked after creation). Added .gitattributes marking that same pattern export-ignore instead, where the double-dash ambiguity is actually safe: by archive time, any extension that DID change already had its update script renamed away from that name, so only genuine no-ops can still match it -- verified directly with git archive | tar -tf -. Fixed bin/test_existing's version assertion, which compared against make -s print-PGXNVERSION (META.json's distribution version, still the real semver, never affected by default_version) instead of make -s print-EXTENSION_test_factory_VERSION (which tracks default_version directly) -- guaranteed to mismatch once default_version stopped equaling the distribution version. Verified locally on PG12 and PG17: fresh and update modes both pass, a real bin/test_existing run-suite both reports installed=expected='stable' and passes, and git archive includes the real versioned files while excluding both no-op stable-update scripts. Co-Authored-By: Claude Sonnet 5 --- .gitattributes | 13 +++++++++++++ .gitignore | 11 +++++++++++ bin/test_existing | 21 ++++++++++++++------- sql/test_factory--0.5.0--stable.sql | 15 +++++++++++++++ sql/test_factory_pgtap--0.1.0--stable.sql | 13 +++++++++++++ test_factory.control | 2 +- test_factory_pgtap.control | 2 +- 7 files changed, 68 insertions(+), 9 deletions(-) create mode 100644 .gitattributes create mode 100644 sql/test_factory--0.5.0--stable.sql create mode 100644 sql/test_factory_pgtap--0.1.0--stable.sql diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..ff58898 --- /dev/null +++ b/.gitattributes @@ -0,0 +1,13 @@ +# See ../ai/RELEASE.md's multi-extension distribution section: an +# extension with no real changes this release cycle keeps its +# --stable.sql update script un-renamed (a genuine no-op), +# rather than promoting it to a real versioned update script. That file +# must never ship in a release archive -- nothing in a tagged release +# has default_version = 'stable' for any extension, so a file only +# reachable via that pseudo-version would be permanently unreachable, +# confusing cruft in the archive. Safe as a blanket glob here (unlike +# .gitignore's exact-filename version of this same exclusion): by the +# time `make dist` archives a tag, any extension that DID change already +# had its stable-named file renamed away, so only genuine no-ops can +# still match this pattern. +sql/*--stable.sql export-ignore diff --git a/.gitignore b/.gitignore index 941a061..c6fd02e 100644 --- a/.gitignore +++ b/.gitignore @@ -18,6 +18,17 @@ control.mk # built targets # Note: Version-specific files (sql/*--*.sql) are now tracked in git and should be committed +# Exception: the `stable` pseudo-version (default_version between releases, +# see ../ai/RELEASE.md and ../ai/CLAUDE.md's "Version-specific SQL files") +# is permanently current, not a frozen release -- it would be regenerated +# and re-diffed on every source edit for zero test-coverage value if +# tracked. Named explicitly, not `sql/*--stable.sql`: that glob's `*` also +# matches across the second `--`, so it silently swept up the *update* +# scripts too (sql/----stable.sql, which must stay +# committed -- confirmed the hard way when `git status` didn't show them +# as untracked after creating them). +sql/test_factory--stable.sql +sql/test_factory_pgtap--stable.sql # Generated by asciidoctor from doc/*.asc; only the .asc source is tracked doc/*.html diff --git a/bin/test_existing b/bin/test_existing index a4f8a74..d92e4be 100755 --- a/bin/test_existing +++ b/bin/test_existing @@ -26,12 +26,12 @@ # # run-suite DB # Assert the installed version matches the current build (never -# hardcoded -- derived from `make -s print-PGXNVERSION`, so a broken -# extraction can't silently compare "" to ""), then run the suite in -# existing mode via --use-existing (pg_regress must not drop/recreate -# DB) and gate on verify-results, not a bare `make test` (pgxntool -# marks installcheck .IGNORE, so a plain test run exits 0 even when -# regression.diffs is nonempty). +# hardcoded -- derived from `make -s print-EXTENSION_test_factory_VERSION`, +# so a broken extraction can't silently compare "" to ""), then run +# the suite in existing mode via --use-existing (pg_regress must not +# drop/recreate DB) and gate on verify-results, not a bare `make test` +# (pgxntool marks installcheck .IGNORE, so a plain test run exits 0 +# even when regression.diffs is nonempty). # # No separate guard-planting subcommand: unlike cat_tools, test_factory's # dependency guard (a view in schema test_factory_drop_guard depending on @@ -57,8 +57,15 @@ psql_do() { psql -d "$db" -v ON_ERROR_STOP=1 "$@" } +# EXTENSION_test_factory_VERSION, not PGXNVERSION: the latter is the +# *distribution* version from META.json, which no longer tracks what +# CREATE EXTENSION actually installs now that test_factory.control's +# default_version sits at the literal 'stable' pseudo-version between +# releases (see ../ai/RELEASE.md) -- a bare CREATE EXTENSION always +# resolves to whatever default_version says, not the distribution's +# semver. current_version() { - make -s print-PGXNVERSION 2>/dev/null | sed -n 's/.*set to "\(.*\)"$/\1/p' + make -s print-EXTENSION_test_factory_VERSION 2>/dev/null | sed -n 's/.*set to "\(.*\)"$/\1/p' } installed_version() { diff --git a/sql/test_factory--0.5.0--stable.sql b/sql/test_factory--0.5.0--stable.sql new file mode 100644 index 0000000..e7e34b8 --- /dev/null +++ b/sql/test_factory--0.5.0--stable.sql @@ -0,0 +1,15 @@ +/* + * Genuine no-op: nothing in this extension has changed since 0.5.0 yet. + * This file exists purely so ALTER EXTENSION test_factory UPDATE has an + * edge to follow at all -- Postgres's version-graph resolution requires + * an actual sql/test_factory----.sql file to exist for a + * transition, regardless of whether its content would be a no-op + * (confirmed directly: without this file, ALTER EXTENSION UPDATE fails + * outright with "has no update path from version 0.5.0 to version + * stable", even though nothing would actually need to change). See + * ../ai/RELEASE.md's `stable` pseudo-version workflow: every subsequent + * SQL-touching PR adds whatever ALTER .../CREATE OR REPLACE ... statements + * are needed here to bring an install on 0.5.0 up to that change. + */ + +-- vi: expandtab ts=2 sw=2 diff --git a/sql/test_factory_pgtap--0.1.0--stable.sql b/sql/test_factory_pgtap--0.1.0--stable.sql new file mode 100644 index 0000000..ef78a33 --- /dev/null +++ b/sql/test_factory_pgtap--0.1.0--stable.sql @@ -0,0 +1,13 @@ +/* + * Genuine no-op: nothing in this extension has changed since 0.1.0 yet. + * Every extension this distribution provides keeps one of these between + * releases, not just the ones a given change happens to touch -- at + * release time, each extension's own --stable.sql is + * inspected to decide whether THAT extension needs a new version (see + * ../ai/RELEASE.md's multi-extension distribution section). An empty + * file here means test_factory_pgtap is not part of this cycle's + * changes and should ship at its existing version, whatever the + * distribution version does. + */ + +-- vi: expandtab ts=2 sw=2 diff --git a/test_factory.control b/test_factory.control index a18e438..565e4b6 100644 --- a/test_factory.control +++ b/test_factory.control @@ -1,3 +1,3 @@ comment = 'A framework for managing test data' -default_version = '0.5.0' +default_version = 'stable' relocatable = false diff --git a/test_factory_pgtap.control b/test_factory_pgtap.control index 8e4a75f..be2217c 100644 --- a/test_factory_pgtap.control +++ b/test_factory_pgtap.control @@ -1,4 +1,4 @@ comment = 'A framework for managing test data' -default_version = '0.1.0' +default_version = 'stable' relocatable = false requires = 'pgtap, test_factory'