Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
d3791d1
Trigger a clean, final CI run
jnasbyupgrade Aug 6, 2026
3f64d4e
Add test/install foundation: TEST_LOAD_SOURCE modes, dependency guard…
jnasbyupgrade Aug 4, 2026
655237e
Revert ci.yml pg-build-test switch: pre-existing failures on old PG p…
jnasbyupgrade Aug 4, 2026
2e64115
Add real update path from 0.1.1 (last released PGXN version) to stable
jnasbyupgrade Aug 4, 2026
fd1799c
ci: fold update-path testing into the existing test job
jnasbyupgrade Aug 5, 2026
e00688d
test_update_path.sh: branch around CASCADE for pre-PG10
jnasbyupgrade Aug 5, 2026
01060b9
ci: scope update-path leg to PG11+
jnasbyupgrade Aug 5, 2026
66fa8ba
Remove now-redundant DATA += for 0.1.1 (pgxntool#48 fixed upstream)
jnasbyupgrade Aug 5, 2026
0a6f766
ci.yml: install rsync before the update-path test steps
jnasbyupgrade Aug 10, 2026
6ef388a
Drop history-narration and a local-only doc reference from comments
jnasbyupgrade Aug 10, 2026
836639e
Drop overstated "REAL"/compat-floor framing and discovery narration f…
jnasbyupgrade Aug 10, 2026
b5c860a
Trim redundant byte-for-byte provenance justification from comments
jnasbyupgrade Aug 10, 2026
61f728f
Link the pre-PG11 DROP ROUTINE gap to an issue; drop stale/restating …
jnasbyupgrade Aug 10, 2026
876a899
Drop the DATA-wildcard NOTE from the Makefile
jnasbyupgrade Aug 10, 2026
d5a7f5c
load.sql: stop naming the update-diff script's transient -stable suffix
jnasbyupgrade Aug 10, 2026
832f60c
Drop the lead comment from sql/extension_drop--0.1.1--stable.sql
jnasbyupgrade Aug 10, 2026
451af71
ci.yml: fix stale pg-upgrade-test header comment, trim verbosity
jnasbyupgrade Aug 10, 2026
88b1f8c
Makefile: fix stale sql/extension_drop--1.0.0.sql reference in LINT_T…
jnasbyupgrade Aug 10, 2026
f373378
Makefile: derive LINT_TARGETS from EXTENSION_SQL_FILES instead of har…
jnasbyupgrade Aug 10, 2026
5121af4
Merge branch 'master' into real-update-path
jnasbyupgrade Aug 11, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 32 additions & 16 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,8 @@ name: CI
# extension_drop version on an OLD cluster, plant a dependency guard, binary
# pg_upgrade straight to a NEWER major, then run the suite in existing mode
# against the real migrated objects (see bin/test_existing). No update step
# and no bridge leg: extension_drop has only ever shipped one real version
# (1.0.0 -- see HISTORY.asc/RELEASE.md; the only PGXN listing, 0.1.x from
# 2017, predates the current SQL entirely), so extversion never changes
# across a leg and there is no known pg_upgrade-unsafe old version to bridge
# from (see ~/advanced-extension-testing.md §6c's own guidance not to build
# that preemptively). Legs' old_pg floor is 12, NOT extension_drop's own
# claimed 9.3 floor above: this workflow's CAT_TOOLS_GIT_REF (see below)
# makes `make install` build cat_tools from the `0.3.0` git tag instead of
# PGXN (see the Makefile's `cat_tools` target comment -- PGXN's published
# cat_tools is a stale 2017 release extension_drop can't use), and that
# current cat_tools requires PostgreSQL >= 12 for a fresh install (its own META.json,
# build.requires.PostgreSQL). Below PG12, `make install` cannot complete at
# all today, independent of anything this job does -- consistent with the
# already-known pre-existing old-PG failures on the plain `test` job (see
# this branch's own history: "Revert ci.yml pg-build-test switch:
# pre-existing failures on old PG predate this branch").
# and no bridge leg: extversion never changes across a leg, and there is no
# known pg_upgrade-unsafe old version to bridge from.
#
# Scope: push only runs on master (post-merge); PR commits are covered by
# pull_request -- avoids double-running CI for the same commit.
Expand Down Expand Up @@ -165,6 +151,36 @@ jobs:
uses: actions/checkout@v7
- name: Test on PostgreSQL ${{ matrix.pg }}
run: pg-build-test
# Update-path leg (0.1.1 -> stable): runs here as extra steps in the
# same already-running container/cluster rather than a separate job,
# since a whole extra job means a whole extra container boot +
# PostgreSQL startup for no isolation benefit -- nothing about this
# leg needs its own environment, unlike e.g. pg_tle's job, which
# genuinely does.
#
# PG11+ only: cat_tools.routine__parse_arg_types_text() (which
# extension_drop's install script calls unconditionally, in both 0.1.1
# and current) transitively hits cat_tools's _cat_tools.function__drop_temp,
# which runs a hardcoded `DROP ROUTINE` -- syntax that doesn't exist
# before PG11 -- see
# https://github.com/Postgres-Extensions/extension_tools/issues/44.
#
# rsync: pgxntool's test-build feature needs it (see
# pgxntool/run-test-build.sh), but pg-build-test above never actually
# exercises test-build -- it goes through a lower-level PGXS path that
# bypasses this repo's own `test:` Makefile target entirely. A plain
# `make test`/`make install` (this step, and pg-upgrade-test below)
# does, so it needs installing explicitly, same as pg-upgrade-test
# already does.
- name: Install rsync
if: matrix.pg >= 11
run: apt-get install -y rsync
- name: "Prove the update path: install 0.1.1, plant guard, ALTER EXTENSION UPDATE, re-prove guard, assert version"
if: matrix.pg >= 11
run: bin/test_update_path.sh
- name: Run the pgTAP suite in update mode (0.1.1 -> stable) against the result
if: matrix.pg >= 11
run: make test-update

# Proves extension_drop survives a BINARY pg_upgrade (in-place catalog
# migration to a newer PostgreSQL major), not just a fresh install. Each
Expand Down
37 changes: 20 additions & 17 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,11 @@ PGXNTOOL_ENABLE_TEST_INSTALL = yes
# - update: CREATE EXTENSION at TEST_UPDATE_FROM, then ALTER EXTENSION
# UPDATE -- to TEST_UPDATE_TO if set, otherwise to the current version.
# Running the SAME suite/expected output against the result asserts
# update behaves identically to a fresh install. NOTE: extension_drop has
# never had a real second released version (PGXN's only listing is
# 0.1.x from 2017, predating the current SQL entirely -- see HISTORY.asc
# and RELEASE.md), so TEST_UPDATE_FROM has no safe default; this mode is
# wired up and structurally ready, but there is nothing real to update
# FROM yet, and so no CI leg exercises it in this repo today.
# update behaves identically to a fresh install. TEST_UPDATE_FROM
# defaults to 0.1.1 (see sql/extension_drop--0.1.1.sql and
# sql/extension_drop--0.1.1--stable.sql). Empty TEST_UPDATE_TO (the
# default) means "update to the current default_version", which is now
# the `stable` pseudo-version.
# - existing: the extension is ALREADY installed (a real pg_upgrade, or an
# ALTER EXTENSION UPDATE done outside the suite). load.sql does not
# touch it; it only asserts presence + current version. Pair with
Expand All @@ -37,14 +36,15 @@ $(error TEST_LOAD_SOURCE must be 'fresh', 'update' or 'existing', got '$(TEST_LO
endif

# update-mode version range (load.sql only reads these in update mode).
# Empty TEST_UPDATE_TO means "update to the current default_version". There
# is no safe default for TEST_UPDATE_FROM (see above) -- require it
# explicitly rather than pointing it at a version that doesn't exist.
TEST_UPDATE_FROM ?=
# Empty TEST_UPDATE_TO means "update to the current default_version" (now
# `stable`). TEST_UPDATE_FROM defaults to 0.1.1, overridable if needed. The
# guard below just protects against someone explicitly blanking it out
# (TEST_UPDATE_FROM= on the command line).
TEST_UPDATE_FROM ?= 0.1.1
TEST_UPDATE_TO ?=
ifeq ($(TEST_LOAD_SOURCE),update)
ifeq ($(strip $(TEST_UPDATE_FROM)),)
$(error TEST_UPDATE_FROM must be set when TEST_LOAD_SOURCE=update -- extension_drop has no prior released version yet to default it to)
$(error TEST_UPDATE_FROM must not be blank when TEST_LOAD_SOURCE=update)
endif
endif

Expand Down Expand Up @@ -107,10 +107,13 @@ $(DESTDIR)$(datadir)/extension/cat_tools.control:
# Style linter (see https://github.com/Postgres-Extensions/linter, vendored
# at .vendor/linter -- lint.mk is the thin local hand-off, see its comment).
# Scoped to the actively-maintained source rather than the default
# `sql/ test/`: sql/extension_drop--1.0.0.sql is a frozen, already-released
# version file (RELEASE.md's "Ongoing development" section -- once a version
# is released, its sql/<ext>--<version>.sql is never hand-edited again), so
# linting it would produce permanent, unfixable findings and make `make
# lint` unusable as a CI gate. Lint the hand-maintained source instead.
LINT_TARGETS = sql/extension_drop.sql test/
# `sql/ test/`: frozen, already-released version files (RELEASE.md's
# "Ongoing development" section -- once a version is released, its
# sql/<ext>--<version>.sql is never hand-edited again) would produce
# permanent, unfixable findings and make `make lint` unusable as a CI
# gate. $(EXTENSION_SQL_FILES) (pgxntool's control.mk.sh, from each
# .control file at the repo root) is exactly the hand-maintained
# sql/<ext>.sql for every extension this distribution provides, so this
# keeps working if a second extension is ever added.
LINT_TARGETS = $(EXTENSION_SQL_FILES) test/
include lint.mk
86 changes: 86 additions & 0 deletions bin/test_update_path.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
#!/bin/sh
# Exercises the extension_drop update path: 0.1.1 -> stable.
#
# Assumes extension_drop and cat_tools are already built and installed into
# the active PostgreSQL cluster (`make install`, which pulls in the cat_tools
# deps target first) and that psql's ambient connection defaults reach it.
#
# The dependency-guard checks attempt the blocked DROP EXTENSION and inspect
# the actual error, rather than trusting the guard exists; the version check
# reads extension_drop.control's default_version dynamically rather than
# hardcoding an expected value that would silently drift out of sync with a
# future release.
# 1. CREATE EXTENSION extension_drop VERSION '0.1.1' -- installs the
# actual historical release. CASCADE (to auto-install cat_tools) only
# exists from PG10 -- pre-PG10 needs cat_tools created explicitly
# first, same as test/install/load.sql.
# 2. Plant a dependency-guard view and prove a non-CASCADE DROP EXTENSION
# is blocked -- BEFORE the update, proving the guard actually attaches
# to the 0.1.1-era extension_drop__commands table.
# 3. ALTER EXTENSION extension_drop UPDATE -- runs
# sql/extension_drop--0.1.1--stable.sql.
# 4. Re-prove the SAME guard still blocks a non-CASCADE drop -- proves the
# update script didn't touch extension_drop__commands's identity.
# 5. Assert the installed version now matches extension_drop.control's
# default_version, read dynamically from the control file rather than
# hardcoded, with empty-value guards.
set -eu

cd "$(dirname "$0")/.."

DB=${1:-extension_drop_update_test}

dropdb --if-exists "$DB"
createdb "$DB"

PG10_PLUS=$(psql -tAc "SELECT current_setting('server_version_num')::int >= 100000" -d "$DB")

if [ "$PG10_PLUS" = "t" ]; then
CREATE_EXTENSION_DROP="CREATE EXTENSION extension_drop VERSION '0.1.1' CASCADE;"
else
CREATE_EXTENSION_DROP="CREATE EXTENSION IF NOT EXISTS cat_tools;
CREATE EXTENSION extension_drop VERSION '0.1.1';"
fi

psql -v ON_ERROR_STOP=1 -d "$DB" -c "
$CREATE_EXTENSION_DROP

CREATE SCHEMA extension_drop_drop_guard;
CREATE VIEW extension_drop_drop_guard.guard AS
SELECT NULL::extension_drop__commands AS guarded_member;
"

assert_guard_blocks_drop() {
label=$1
if psql -v ON_ERROR_STOP=1 -d "$DB" -c 'DROP EXTENSION extension_drop' >/tmp/guard_drop.out 2>/tmp/guard_drop.err; then
echo "FAIL ($label): DROP EXTENSION extension_drop succeeded -- the dependency guard did not block it" >&2
exit 1
fi
if ! grep -q 'cannot drop extension extension_drop because other objects depend on it' /tmp/guard_drop.err; then
echo "FAIL ($label): DROP EXTENSION failed, but not with the expected dependency-guard error:" >&2
cat /tmp/guard_drop.err >&2
exit 1
fi
echo "OK ($label): non-CASCADE DROP EXTENSION extension_drop is blocked by the dependency guard"
}

assert_guard_blocks_drop "pre-update, at 0.1.1"

psql -v ON_ERROR_STOP=1 -d "$DB" -c "SET client_min_messages = ERROR; ALTER EXTENSION extension_drop UPDATE"

assert_guard_blocks_drop "post-update"

INSTALLED=$(psql -tAc "SELECT extversion FROM pg_extension WHERE extname = 'extension_drop'" -d "$DB" | tr -d '[:space:]')
EXPECTED=$(sed -n "s/^default_version[[:space:]]*=[[:space:]]*'\([^']*\)'.*/\1/p" extension_drop.control | tr -d '[:space:]')

if [ -z "$INSTALLED" ] || [ -z "$EXPECTED" ] || [ "$INSTALLED" != "$EXPECTED" ]; then
echo "FAIL: installed='$INSTALLED' expected='$EXPECTED' (derived from extension_drop.control)" >&2
exit 1
fi
echo "OK: extension_drop landed at '$INSTALLED' after update, matching extension_drop.control's default_version"

dropdb "$DB"

echo "PASS: 0.1.1 -> $INSTALLED update path verified (install, guard survival, version assertion)."

# vi: expandtab ts=2 sw=2
28 changes: 28 additions & 0 deletions sql/extension_drop--0.1.1--stable.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
CREATE OR REPLACE FUNCTION extension_drop__event_trigger(
) RETURNS event_trigger LANGUAGE plpgsql SET search_path FROM CURRENT AS
$body$
DECLARE
r extension_drop__commands;
BEGIN
RAISE DEBUG 'extension_drop event trigger entry: tg_event %, tg_tag %', tg_event, tg_tag;
FOR r IN
SELECT c.*
FROM extension_drop__commands c
JOIN pg_event_trigger_dropped_objects() d
ON c.extension_name = d.object_name
AND d.object_type = 'extension'
LOOP
RAISE DEBUG E'extension "%" is being dropped; executing SQL:\n%', r.extension_name, r.sql;
EXECUTE r.sql;
DELETE FROM extension_drop__commands WHERE extension_name = r.extension_name;
END LOOP;

/*
* Need to do this after the fact since the extensions being dropped have
* already been removed from the catalog by the time this function is called.
*/
PERFORM extension_drop__sanity_assert();
END
$body$;

-- vim: sw=2 ts=2 expandtab
Loading