Contents
PGXN packaging, automatic versions, and publishing
pg_local_cache is packaged as a regular PGXS extension. The repository ships
PGXN 1.0 metadata, a deterministic source bundle, automatic semantic
versioning, and an authenticated release workflow.
After the one-time PGXN credentials are configured, merging a release-worthy
change to master is enough. The repository prepares the next version, runs the
full CI and binary release pipelines, and uploads the exact stable ZIP to PGXN.
No per-release PGXN Manager upload is required.
One-time repository setup
- Create and approve the maintainer account in PGXN Manager.
Add these GitHub Actions repository secrets:
PGXN_USERNAMEPGXN_PASSWORD
Allow GitHub Actions
contents: writeandactions: write. Ifmasterhas a branch protection rule, allow the repository Actions identity to create the generated release commit, or replace the checkout credential with a narrowly scoped repository token that has that permission.
The workflow writes the credentials to a mode-0600 temporary .netrc on
the ephemeral runner and sends the ZIP to PGXN Manager’s authenticated
POST /upload endpoint as multipart field archive. The credentials are not
written to the distribution, GitHub release, or repository. GitHub masks
repository-secret values in workflow output.
Automatic release sequence
A human push or merged pull request to master starts
.github/workflows/auto-version.yml.
scripts/auto_version.pyfinds the highest reachable stablevX.Y.Ztag.- It classifies all commits since that tag.
- When a release is required, it updates every version-bearing source file and creates the PostgreSQL install and upgrade SQL for the new version.
- The workflow commits the result as
chore(release): prepare vX.Y.Z [skip version]. - Because GitHub does not recursively trigger workflows for a push made with
GITHUB_TOKEN, the workflow explicitly dispatchesci.ymlfor the new version-bearingmastercommit. - The existing release workflow builds and verifies PostgreSQL 14–18 artifacts and creates immutable GitHub releases.
- The
PGXN packageworkflow rebuilds the ZIP from the exact stable release SHA, verifies thatvX.Y.Zpoints to that SHA, and uploads it directly to PGXN Manager over HTTPS.
A rerun is idempotent. Before and after upload, the workflow downloads the published PGXN archive and byte-compares it with the stable GitHub release asset. An existing equal archive is accepted; different bytes fail closed. PGXN versions are immutable and are never overwritten.
Semantic version rules
The latest stable Git tag is the baseline. Conventional Commit messages select the highest required bump:
| Change since the stable tag | Version bump |
|---|---|
type!: or a BREAKING CHANGE: footer |
major |
feat: |
minor |
fix:, perf:, refactor:, build:, revert:, security: |
patch |
only docs:, test:, ci:, chore:, or style: |
no stable release |
| an unclassified non-merge production commit | patch, as a fail-safe |
The generated release commit contains [skip version], so it never asks for a
second bump. Re-running the planner before the stable tag is created also stays
idempotent: if the calculated version is already present, no files change.
Inspect the plan locally:
make version-next
python3 scripts/auto_version.py --json
Apply it locally for review:
make version-bump
Normal development does not need to run version-bump; the master workflow
owns the release commit.
PostgreSQL upgrade SQL
Released install files are immutable. The version planner compares the current install SQL with the same file from the latest stable tag.
For a C-only release, it creates:
- a new full install file, for example
pg_local_cache--1.2.0.sql; - an explicit no-op upgrade file, for example
pg_local_cache--1.1.0--1.2.0.sql.
When a change modifies extension SQL objects, commit the final full install SQL and also put only the incremental migration statements in:
sql/pg_local_cache--unreleased.sql
The planner consumes that fragment into the generated old--new upgrade file,
removes the fragment, and restores the released old install file from its tag.
It fails closed if install SQL changed without an explicit migration, or if a
migration fragment exists while the install SQL is unchanged.
Install from PGXN
Requirements:
- PostgreSQL 14–18 server development files for the target installation;
- a C compiler and GNU Make;
- the PGXN client;
- permission to write to the target PostgreSQL library and extension directories.
Choose the same pg_config used by the PostgreSQL server:
pgxn install \
--pg_config /usr/lib/postgresql/16/bin/pg_config \
--sudo -- \
pg_local_cache
pgxn install downloads, compiles, and copies the extension files. It does not
configure the server, restart PostgreSQL, or attach application tables.
pg_local_cache must be present in shared_preload_libraries before
CREATE EXTENSION because its shared-memory layout is allocated at postmaster
startup. Preserve every existing preload entry, configure the extension memory
and database settings, perform one controlled restart, and then run:
CREATE EXTENSION pg_local_cache;
SELECT local_cache.attach_table('public.items'::regclass);
Use the existing-server installation guide for preflight, memory sizing, restart, verification, HA, and rollback. The PGXN client replaces only the source download/build/copy part of that procedure.
Do not use pgxn load before the preload configuration and restart. Loading the
SQL objects without the preloaded module cannot initialize the shared cache.
Validate and build the distribution
Validate the metadata and repository version contracts:
make pgxn-check
Build the upload archive without requiring pg_config:
make dist
The output is:
dist/pg_local_cache-<version>.zip
The builder packages the exact committed revision with one
pg_local_cache-<version>/ root, validates required metadata and source files,
rejects dirty or unsafe release inputs, and prints the archive SHA-256 digest.
Recovery and manual verification
Automatic publishing intentionally stops before PGXN when any invariant is not
proven: missing credentials, a moving master, a stable tag pointing to another
commit, metadata drift, a failed CI/release job, or an existing GitHub asset
with different bytes.
The generated ZIP is retained as a GitHub Actions artifact and attached to the immutable GitHub release. A maintainer can inspect it with:
VERSION="$(python3 scripts/validate_pgxn_meta.py --print-version)"
unzip -t "dist/pg_local_cache-${VERSION}.zip"
sha256sum "dist/pg_local_cache-${VERSION}.zip"
Never reuse an existing semantic version for a different commit. Fix the release input and produce a higher version instead of attempting to replace an immutable PGXN distribution.