Skip to content

chore: bump version to 1.2.0-dev (+ automate version bumps)#341

Open
tjgreen42 wants to merge 4 commits intomainfrom
bump-to-1.2.0-dev
Open

chore: bump version to 1.2.0-dev (+ automate version bumps)#341
tjgreen42 wants to merge 4 commits intomainfrom
bump-to-1.2.0-dev

Conversation

@tjgreen42
Copy link
Copy Markdown

Summary

Post-1.1.0 dev bump, plus tooling so future bumps are mechanical.

Three commits:

  1. Drop CREATE EXTENSION load banner; add bump-version.sh — Remove
    the RAISE INFO 'pg_textsearch vX.Y.Z' block that fired on every
    `CREATE EXTENSION`. It produced one INFO line that 62 expected
    outputs had to absorb, so every release regenerated 62 files for
    the same one-line diff. Survey of nearby extensions (pgvector,
    pgvectorscale, pg_search, timescaledb) and standard contribs
    (pg_stat_statements, hstore, pg_trgm, pgcrypto, postgis) confirms
    none emit a load banner; pg_textsearch was the outlier. The
    library-version mismatch `RAISE EXCEPTION` (the actual
    correctness check) stays. Version remains discoverable via
    `SHOW pg_textsearch.library_version`, `\dx`, and
    `pg_extension.extversion`.

    Also adds `scripts/bump-version.sh`, which automates the text
    substitutions across SQL files, Makefile DATA, control file,
    mod.c, README, CLAUDE.md, test scripts, and the msmarco benchmark
    version check. Auto-detects dev-bump vs release mode from the
    version pattern; refuses to run on a dirty tree; reports
    stragglers after substituting; prints next-steps for the human.

  2. docs: simplify RELEASING.md around bump-version.sh — Collapse
    the per-file substitution checklist (the script does it now) and
    replace with a step-driven sequence. Add a section on auditing
    the upgrade SQL script — the one piece the script can't automate
    and the most likely place to ship a regression.

  3. chore: bump version to 1.2.0-dev — Generated by running
    `scripts/bump-version.sh 1.1.0 1.2.0-dev` (the dogfood proves
    the script works). Renames the base SQL file, creates the
    upgrade-script stub, updates default_version /
    PG_MODULE_MAGIC_EXT / Makefile / README / CLAUDE.md / test
    scripts / msmarco benchmark.

Testing

  • `make test` — 58/58 pass on pg18-release after the bump
  • `make format-check` — clean
  • The script itself is the integration test (commit 3 is its output)

Follow-up for the next release

Replace the banner image and add 1.1.0 to the upgrade-tests matrix
when cutting v1.2.0; `scripts/bump-version.sh` reminds you of both
in its next-steps output.

Todd J. Green added 4 commits April 24, 2026 16:54
The DO $$ RAISE INFO 'pg_textsearch vX.Y.Z' $$; block in the main
SQL file and the matching block in the upgrade SQL produce a single
INFO line that every regression test absorbs. That meant 62 expected
output files needed regeneration on every release. None of the nearby
extensions (pgvector, pgvectorscale, pg_search, timescaledb) emit a
load banner; pg_textsearch was the outlier. The library-version
mismatch RAISE EXCEPTION (the actual correctness check) stays.

Version remains discoverable via SHOW pg_textsearch.library_version,
\\dx pg_textsearch, and pg_extension.extversion.

Also add scripts/bump-version.sh, which automates the text
substitutions across the SQL files, Makefile, control file, mod.c,
README, CLAUDE.md, test scripts, and msmarco benchmark check. Auto-
detects dev-bump vs release mode from the version pattern. Refuses
to run on a dirty tree; greps for stragglers after substituting.
Collapse the per-file substitution checklist (the script does it
now) and replace with a step-driven sequence. Add a section on
auditing the upgrade SQL script — that's the one piece the script
can't automate, and the most likely place to ship a regression.
Keep the upgrade compatibility matrix, on-disk format versions,
and troubleshooting sections as-is.
Generated by scripts/bump-version.sh 1.1.0 1.2.0-dev. Renames the
base SQL file 1.1.0 → 1.2.0-dev, creates the upgrade-script stub
1.1.0--1.2.0-dev.sql (library-version check only; contributors
fill in feature DDL as work lands), and updates default_version,
PG_MODULE_MAGIC_EXT, the Makefile DATA list, README, CLAUDE.md,
test scripts, and the msmarco benchmark version check.
The check `IF lib_ver != 'X.Y.Z' THEN RAISE EXCEPTION` in
sql/pg_textsearch--1.0.0--1.1.0.sql breaks upgrade chains once a
newer dev version is the default. Walking 1.0.0 → 1.1.0 → 1.2.0-dev
runs the 1.0.0--1.1.0.sql script with the 1.2.0-dev binary loaded,
and the equality check fires.

Upgrade scripts must accept any loaded library version because they
may run as intermediate steps in a chain that ends at default_version,
not at the version named in the upgrade filename. Drop the equality
check in upgrade scripts; keep the "library is loaded" check as a
sanity guard against missing shared_preload_libraries. The
version-equality check stays in the main install file (which only
runs on CREATE EXTENSION, not on UPDATE).

Updates the script's stub template too so future bumps generate
upgrade scripts with the relaxed check.
@codecov
Copy link
Copy Markdown

codecov Bot commented Apr 25, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@tjgreen42 tjgreen42 marked this pull request as ready for review April 25, 2026 00:39
Comment thread README.md
🚀 **Status**: v1.2.0-dev - Production ready.

![Tapir and Friends](images/tapir_and_friends_v1.1.0.png)
![Tapir and Friends](images/tapir_and_friends_v1.2.0-dev.png)
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 After running scripts/bump-version.sh 1.1.0 1.2.0-dev, README.md line 21 references images/tapir_and_friends_v1.2.0-dev.png, but that file does not exist (only tapir_and_friends_v1.1.0.png is in images/). The dogfood commit in this PR therefore ships a broken image link in the rendered README on GitHub for the entire dev cycle, and the underlying script flaw will recur on every future dev bump. Fix: either skip the image-filename substitution in dev mode (treat it like the release banner, which the script intentionally leaves to the human) or add a banner reminder to the dev-mode next-steps output.

Extended reasoning...

What's wrong

The bump script unconditionally rewrites every literal occurrence of OLD to NEW inside README.md via the common_files loop in scripts/bump-version.sh:

common_files=(
    pg_textsearch.control
    src/mod.c
    README.md
    ...
)
for f in "${common_files[@]}"; do
    if [[ -f $f ]]; then
        perl -i -pe "s/\Q$OLD\E/$NEW/g" "$f"
    fi
done

In release mode that's correct — the banner image is renamed in the same release, and the next-steps output reminds the human to rename images/tapir_and_friends_v$OLD.png to images/tapir_and_friends_v$NEW.png. In dev mode, however, no banner image is renamed (the script does not produce dev-cycle images), and the dev-mode next-steps block at lines ~197-202 only says:

Next steps (dev bump):
  1. Review the generated stub $NEW_UPGRADE.
  2. Open a PR titled "chore: bump version to $NEW".

There is no reminder about the dangling image reference, so the rewritten line ships unnoticed.

Step-by-step proof

  1. ls images/ in this PR's tree shows only pageviz.jpg and tapir_and_friends_v1.1.0.png — there is no tapir_and_friends_v1.2.0-dev.png.
  2. README.md line 21 in this PR reads: ![Tapir and Friends](images/tapir_and_friends_v1.2.0-dev.png).
  3. The substitution that produced line 21 is the literal OLD → NEW rewrite inside README.md (Makefile, control file, mod.c, etc. all get the same treatment).
  4. The straggler check at the end of the script does not catch this: it greps for the literal $OLD (1.1.0), but the rewritten path no longer contains 1.1.0 — it contains 1.2.0-dev. The check is for old references the script missed, not for new references the script created pointing at non-existent files.
  5. GitHub renders README.md, so the markdown image will resolve to a 404 on github.com/timescale/pg_textsearch for the entire 1.2.0 dev cycle, until either the v1.2.0 release lands a tapir_and_friends_v1.2.0-dev.png is dropped in by hand.

Why the PR description doesn't cover it

The PR description says: "scripts/bump-version.sh reminds you of both [the banner image and the upgrade-tests matrix] in its next-steps output." That claim is true for the release branch (lines ~184-196 of the script include both reminders). It is not true for the dev branch (lines ~197-202), which mentions neither. So the human running the dev bump has no in-script signal to investigate the now-broken README link.

Impact

Cosmetic but visible: the public README on GitHub renders with a broken image until v1.2.0 ships. Not a correctness bug for the extension itself.

Suggested fix

Two reasonable options, both small:

  1. Skip the image-line substitution in dev mode. Replace the image reference rewrite with a targeted no-op for dev bumps so the README continues to point at the last released banner (v1.1.0.png) until release time. This mirrors what the script already does for the actual image file (it never renames or creates one in dev mode).
  2. Add a dev-mode next-step reminder. Append to the dev-mode cat <<EOF block something like: "3. Drop a banner image at images/tapir_and_friends_v$NEW.png (the README now references it), or revert the README image-line rewrite by hand." This keeps the substitution behavior but surfaces the consequence.

Option 1 is cleaner — it keeps the dev tree internally consistent without relying on humans reading next-steps output.

Comment thread scripts/bump-version.sh
Comment on lines +116 to +132
elif [[ $MODE == release ]]; then
# Find and rename the upgrade file `sql/pg_textsearch--PREV--OLD.sql`.
# Globbing here uses bash's nullglob so we can count safely.
shopt -s nullglob
upgrades=( sql/pg_textsearch--*--"$OLD".sql )
shopt -u nullglob
if [[ ${#upgrades[@]} -ne 1 ]]; then
echo "Error: expected exactly one sql/pg_textsearch--*--$OLD.sql," \
"found ${#upgrades[@]}." >&2
exit 2
fi
SRC_UPGRADE=${upgrades[0]}
DST_UPGRADE=${SRC_UPGRADE//$OLD.sql/$NEW.sql}

git mv "$SRC_MAIN" "$DST_MAIN"
git mv "$SRC_UPGRADE" "$DST_UPGRADE"
fi
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 Release mode of bump-version.sh skips substitutions that dev mode performs, breaking the next release. When run as ./scripts/bump-version.sh X.Y.Z-dev X.Y.Z, the elif [[ $MODE == release ]] block (lines 116–132) only does git mv on the two SQL files. It skips three things dev mode handles: (1) the perl -i -pe "s/\Q$OLD\E/$NEW/g" "$DST_MAIN" body substitution (so the renamed pg_textsearch--X.Y.Z.sql still contains IF lib_ver <> '\''X.Y.Z-dev'\'' and the version comment, causing CREATE EXTENSION to fail with library version mismatch: loaded=X.Y.Z, expected=X.Y.Z-dev once pg_textsearch.control and src/mod.c are bumped by the common_files loop); (2) the same substitution on $DST_UPGRADE (silently masked because the straggler check excludes sql/pg_textsearch--*--*.sql); and (3) the two Makefile-rewriting perl invocations (lines 109–114), which leaves DATA pointing at the now-nonexistent -dev filenames so make install fails. The dogfooded commit only exercised dev mode, so the first real release (e.g. 1.2.0-dev → 1.2.0) will hit this. Fix: move the substitutions out of the if MODE == dev block so they run unconditionally, or duplicate them into the release branch (and add Makefile to common_files).

Extended reasoning...

What the bug is

scripts/bump-version.sh has two mode branches: dev (post-release bump like 1.1.0 → 1.2.0-dev) and release (1.2.0-dev → 1.2.0). Dev mode does three things release mode skips, even though both modes need them:

Action Dev branch Release branch In common_files loop?
Rename main SQL file line 82 line 130 n/a
Substitute body of $DST_MAIN line 83 (perl -i -pe ...) missing no
Rename upgrade SQL file n/a (creates new stub) line 131 n/a
Substitute body of $DST_UPGRADE n/a missing no
Rewrite Makefile DATA list lines 109–114 missing no

The common_files loop (lines 137–152) covers pg_textsearch.control, src/mod.c, README, CLAUDE.md, three test scripts, and the msmarco benchmark — but neither the renamed SQL files nor the Makefile.

Step-by-step proof: ./scripts/bump-version.sh 1.2.0-dev 1.2.0

Starting state (current PR):

  • pg_textsearch.control says default_version = '1.2.0-dev'
  • src/mod.c says .version = "1.2.0-dev"
  • sql/pg_textsearch--1.2.0-dev.sql body contains IF lib_ver OPERATOR(pg_catalog.<>) '1.2.0-dev' THEN ... 'expected=%', ..., '1.2.0-dev'
  • Makefile DATA contains sql/pg_textsearch--1.2.0-dev.sql and sql/pg_textsearch--1.1.0--1.2.0-dev.sql

Run ./scripts/bump-version.sh 1.2.0-dev 1.2.0:

  1. Mode detected as release (line 39).
  2. git mv sql/pg_textsearch--1.2.0-dev.sql sql/pg_textsearch--1.2.0.sql (line 130). No perl substitution runs on the body.
  3. git mv sql/pg_textsearch--1.1.0--1.2.0-dev.sql sql/pg_textsearch--1.1.0--1.2.0.sql (line 131). No perl substitution runs on the body.
  4. common_files loop rewrites pg_textsearch.controldefault_version = '1.2.0' and src/mod.c.version = "1.2.0".
  5. Makefile is never touched — neither the dev branch nor common_files includes it in release mode.
  6. Straggler check at line 160 runs git grep -l --fixed-strings '1.2.0-dev'. The pathspec ':!sql/pg_textsearch--*--*.sql' excludes the upgrade file but not the main install file or the Makefile, so warnings appear for sql/pg_textsearch--1.2.0.sql and Makefile. The script exits 0; the warnings are easily missed.

End state:

  • sql/pg_textsearch--1.2.0.sql still has -- pg_textsearch extension version 1.2.0-dev and the '1.2.0-dev' literals in the version-equality block.
  • sql/pg_textsearch--1.1.0--1.2.0.sql still has -- Upgrade from 1.1.0 to 1.2.0-dev (functionally harmless, but inconsistent).
  • Makefile DATA still references sql/pg_textsearch--1.2.0-dev.sql and sql/pg_textsearch--1.1.0--1.2.0-dev.sql — files that no longer exist.

What this breaks

make install fails because PGXS reads the DATA list and tries to install files that no longer exist after the renames.

If a human catches the Makefile warning and fixes it by hand but doesn't notice the SQL warning, they get a compiling extension that fails at runtime: CREATE EXTENSION pg_textsearch raises pg_textsearch library version mismatch: loaded=1.2.0, expected=1.2.0-dev because mod.c reports 1.2.0 (substituted) while the install file's version-equality check still demands 1.2.0-dev (not substituted).

Why existing safeguards don't catch it

The straggler check at line 160 partially catches this:

  • Makefile is not in the exclusion list, so the user sees a warning.
  • sql/pg_textsearch--1.2.0.sql is not matched by :!sql/pg_textsearch--*--*.sql (only one --), so this warns too.
  • But sql/pg_textsearch--1.1.0--1.2.0.sql is matched by that exclusion (two --), so its stale -- Upgrade from 1.1.0 to 1.2.0-dev comment is silently kept.

The straggler check is a soft warning; the script's exit status is 0, the next-steps output makes no mention of fixing the SQL or Makefile, and RELEASING.md (lines 31–35) tells users "This renames the SQL files and updates every version reference across the tree." The dogfood test in commit 3 exercises only dev mode, so this regression has never been caught by CI or by the PR's own integration test.

How to fix

Either (a) duplicate dev mode's substitutions into the release branch, or (b) move them out of the mode-specific block. Option (b) is cleaner:

# After the mode-specific block (renames), before common_files:
perl -i -pe "s/\Q$OLD\E/$NEW/g" "$DST_MAIN"
[[ -n ${DST_UPGRADE:-} ]] && perl -i -pe "s/\Q$OLD\E/$NEW/g" "$DST_UPGRADE"

For the Makefile, the simplest fix is adding it to common_files. The dev-mode-specific Makefile substitution at line 109 (pg_textsearch--OLD.sql → pg_textsearch--NEW.sql) is exactly the literal substitution common_files already does, and the second invocation (lines 110–114) only matters for dev mode (it appends a new PREV--NEW.sql line). Adding Makefile to common_files correctly handles release mode (just renames OLD.sql → NEW.sql for both DATA entries) and is a no-op redundant write in dev mode. If preserving the dev-only append is desired, keep that single perl invocation in the dev branch and add Makefile to common_files for the renames.

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