Releases: gmr/pglifecycle
Release list
2.0.0-alpha.2
Added
deployaccepts the samepg_dumpexclusions aspull—-T/--exclude-table,-N/--exclude-schema, and--exclude-extension, repeatable and conflicting with--dump. A project pulled with exclusions was previously compared against a full-database snapshot, producing "Skipping dependency on unmanaged ..." warnings and a dump slower than the pull it was compared against (#67).- A generated schema reference for all 37 object schemata, rendered from the
titleanddescriptionalready carried inschemata/*.yml, so it cannot drift from the contract the loader applies. Each schema is also published resolved as JSON atschemata/<name>.json, so an editor can validate project files against it with ayaml-language-servermodeline (#68). - Documentation for the
gmr/pglifecycle-actionGitHub Actions (#68). - Table-level
column_defaults, so a default on a column an inheritance child only inherits is kept.pg_dumpwrites those as a standaloneALTER TABLE ONLY ... SET DEFAULTwith no matching column entry, and they were silently discarded from the project (#66). - Role memberships accept the
admin,inherit, andsetoptions as a mapping, not just a bare role name.INHERIT FALSEandADMIN OPTIONwere being dropped with a warning (#66).
Changed
pullanddeployprompt for a database password themselves instead of leaving it to the client tools.pg_dump,pg_dumpall, andpsqlnow always run with-wand take the password from the environment;-Wprompts up front, and a "no password supplied" failure prompts and retries. Where nobody can answer —-w, or a non-interactive stdin — the command fails with a hint namingPGPASSWORD, pgpass, and the terminal (#69).- The documentation site matches pglifecycle.com: PostgreSQL blue on warm paper, Space Grotesk headings, IBM Plex for text and code, and dark code blocks in both colour schemes (#68).
- Every schema
$idresolves. All 37 pointed at apglifecycle.readthedocs.ioURL that returns 404, and$schemadeclared a draft-agnostic URI that validators reject (#68). - New dependency:
rpassword7, for reading the password without echo (#69).
Fixed
- A pulled project containing overloaded functions can be loaded again. The loader keyed the inventory by
(type, schema, bare name)whilepullwrites overloads tof.yaml/f_1.yaml, sobuildanddeployrefused the project outright withDuplicate FUNCTION(#66). - Hash partitions validate. The
partitionsbranches gated onfor_values_when, which no schema declares, so every hash-partitioned table failed validation and was dropped along with its dependents' edges (#66). - Tables and materialized views with
toast.storage parameters validate; the property-name pattern rejected the dot (#66). - Three more schema branches that gated on properties their object never defines:
collation.ymlrejected every collation defined bysql:orcopy_from:, andindex.ymlandview.ymlgated ontable_nameandoptions. A new test walks every bundled schema and fails anyoneOf/anyOf/allOfbranch that gates on an undeclared property (#66). - Storage parameters render as
WITH (k=v, ...). The Python implementation emitted the list without the required parentheses and the port was faithful to it, so the first table with storage parameters failed to restore withsyntax error at or near "fillfactor"(#66). - The role-membership warning fires only for a genuinely unrecognized option. PostgreSQL 16+ always writes
INHERIT TRUEandGRANTED BY, so ~600 lines of noise were hiding three realINHERIT FALSEand tenADMIN OPTIONlosses (#66). pullanddeployno longer appear to hang forever. The client tools prompt for a password on/dev/ttyrather than stdin, and the prompt landed on the line the progress spinner refreshes ten times a second — leaving a 0-byte archive on disk and no backend inpg_stat_activity(#69).
2.0.0-alpha.1
Added
- Support for PostgreSQL 18 table-level
NOT NULLconstraints, including named constraints andNO INHERIT. Pulling a PG 18 server previously dropped any table whoseCREATE TABLEcarried one, writing no file and logging only a parse warning (#64, #65). - Inheritance support for foreign tables:
INHERITS, inherited columns, and table constraints are now pulled, rendered, and reconciled on deploy. An inheriting foreign table previously pulled as name/schema/owner/server/options alone, silently (#65). - A published Docker image at
ghcr.io/gmr/pglifecycle(amd64 + arm64), built on Alpine with the PostgreSQL 17 client tools thatpull,build, anddeployshell out to (#63).
Changed
- Updated internal dependencies:
tree-sitter-postgresfrom 1.2 to 19.0.0-beta.2 (the PostgreSQL 19 grammar),libpgfmtfrom 1.2 to 1.3, andlibpgdumpfrom 2.1 to 2.2. - Deploy renames a
NOT NULLconstraint in place rather than dropping and recreating it (#65).
Fixed
- Inherited tables can be restored again. Restore ordering derived edges from foreign keys only, so a child that sorted before its parent failed with
relation "..." does not exist(#65). - Named
NOT NULLconstraints keep their name andNO INHERITflag through a pull/build round trip, instead of collapsing tonullable: falseand being auto-renamed on rebuild (#65). - Homebrew installs work for this project's unprefixed tags. The formula-update step wrote a hardcoded
vinto every download URL, pointingbrew install pglifecycleat assets that did not exist (#63). - The release workflow triggers on
release: publishedrather thancreated, which never fires for a draft-then-publish release, and verifies the tag matches theCargo.tomlversion before building (#63). - Identifiers in table-level
NOT NULLconstraints are quoted (#64).
2.0.0-alpha.0
First release of the Rust rewrite, replacing the Python implementation
(preserved at the python-final tag). The on-disk project format and
the schemata/ contract carry over unchanged, and build output is
deliberately faithful to the Python archives entry-by-entry — the
intentional deviations are enumerated at the top of src/build/mod.rs.
Alpha: the CLI surface and project format are stable enough to use, but
not yet frozen.
Commands
pull— database orpg_dumparchive → a structured YAML
project. Parses each entry's DDL through a tree-sitter-postgres CST,
merges child entries (indexes, constraints, triggers, comments, ACLs)
into their owning objects, and writes one file per object.
--update/--prunerefresh an existing project in place.build— project →pg_restore -Fcarchive.deploy— compare the project against a live database and emit
the DDL to make the database match. Output-first: the script goes to
stdout or--outputto be applied separately, and destructive
statements are excluded unless--allow-drop.create— scaffold an empty project.
Coverage
Schemas, tables (including partitions and typed tables), views,
materialized views, sequences, domains, types, functions, aggregates,
operators, casts, collations, conversions, text search objects, event
triggers, publications, subscriptions, tablespaces, foreign data
wrappers, servers, user mappings, foreign tables, and roles, users,
groups with their settings, grants, revocations, and memberships.
Notable in this release
- Role membership grants are emitted by
build(#58), including
membership in predefined roles such aspg_read_all_data, which can
only ever be referenced and never created. - Role membership modifiers that the project format cannot represent —
WITH ADMIN OPTION,GRANTED BY, and theREVOKE ... OPTION FOR
form — are now reported rather than silently dropped (#61). - The
views:ACL section is emitted, coalesced withtables:since
PostgreSQL grants on views withTABLEsyntax (#62). - Foreign objects are pulled, built, and reconciled in deploy
(#45, #46, #50). - Progress indicators and failure diagnostics across all three commands
(#29, #30, #31, #35), with SQL formatting guarded by a per-statement
timeout (#33).
Verification
just check (fmt, clippy -D warnings, tests), mkdocs build --strict, and both database gates against PostgreSQL 17 — the
round-trip gate (schema → pull → build → restore → diff) and the three
deploy gates (equivalence, convergence, safety).
Known issue
Cargo.lock pins time 0.3.48 and time-macros 0.2.28, both since
yanked from crates.io. They build and test clean; the bump is deferred
to the next release.