Release Gate Checklist
Use this page as the pre-release validation runbook for contributors and agents. It is intentionally command-oriented: start with the local checks, run the aggregate release gate, then add the environment-specific gates that are disabled by default.
Run commands from the repository root unless a block starts with cd graph.
Use disposable databases for every heavy script. Use disposable PostgreSQL
clusters for crash, upgrade, and memory-inspection scripts.
Low-Context Agent Rules
Use these rules when an automated or low-context agent runs the checklist:
- Treat any nonzero command exit as a failed gate unless the release owner explicitly waives it.
- Do not continue after a failed required gate. Capture the command, exit code, and last useful log lines, then stop.
- Do not retry a failed gate more than once unless the failure is clearly environmental, such as a transient Docker pull, stale pgrx install, or disposable database name collision.
- Run
RUN_CRASH=1,RUN_TX_DELTA_CRASH=1,crash_recovery.sh, andtx_delta_crash_recovery.shonly throughscripts/with_disposable_postgres.sh; the fixture refuses clusters without its per-run sentinel and connected-server identity checks. - Run PostgreSQL binary-upgrade checks through
run_pg_upgrade_matrix.sh; the lower-level validator refuses directories outside its per-run sentinel. - Do not run package-manager
installoraddcommands without thesfwwrapper. - Do not mark skipped opt-in gates as passed. Record them as skipped with a reason and owner.
For every gate, record:
command:
working directory:
start time:
end time:
exit code:
result: pass | fail | skipped | waived
log or artifact path:
notes:Pre-Run Sanity Check
Run this first and save the output with release evidence:
pwd
git rev-parse --show-toplevel
git rev-parse HEAD
git status --short
command -v cargo
command -v cargo-pgrx
command -v psql
command -v createdb
command -v dropdb
command -v pg_config
command -v pgbench
command -v docker
command -v cargo-deny
pg_config --version
psql --version
docker --version
cargo --version
cargo pgrx --version
cargo deny --versionIf PG_CONFIG is set, also verify it points at the intended PostgreSQL major:
"$PG_CONFIG" --versionIf the release uses a non-default PostgreSQL connection, record these environment variables before running heavy tests:
PGHOST=
PGPORT=
PGUSER=
PGDATABASE=
PG_VERSION_FEATURE=
PG_CONFIG=The normal PostgreSQL 17 release path should use PG_VERSION_FEATURE=pg17.
Release Owner Summary
Before tagging a release, collect successful output for:
- docs drift, dependency freshness, formatting, clippy, docs, unit tests, pgrx SQL tests, dependency audit, checked-cast drift, Miri mapped validation, fuzz compile, and projection fuzz seed corpora;
- package validation, fresh install smoke, SQL metadata audit, SQLSTATE/ACL boundary, backup/restore, lock regressions, concurrency stress, synthetic release fixture, playground query gate, GQL write lifecycle gates, named graph gate, durable projection gates, tx-delta lifecycle, and pgbench sync stress;
- explicit opt-in gates for Docker smoke, crash recovery, tx-delta crash recovery, PostgreSQL-major matrix, peak RSS, mmap PSS, sanitizer runs, and benchmarks when the release owner requires them.
Do not mark release verification complete when a gate is skipped, interrupted, or run against the wrong PostgreSQL major. Rerun the gate or record an explicit release-owner waiver with the exact command, reason, and available evidence.
Environment Prerequisites
Required for the normal PostgreSQL 17 release path:
- Rust toolchain for the crate and
cargo-pgrx. - PostgreSQL server, client tools, and headers for the target major.
pg_configfor the target major onPATH, or setPG_CONFIG.psql,pg_dump,pg_restore,createdb,dropdb, and related client binaries onPATH.cargo-denyfor the dependency policy gate.- A pgrx test cluster initialized for the target major.
- Docker for Docker, package, playground, or matrix gates.
pgbenchfor sync stress gates.- Nix for regenerating and validating
flake.lockwhen the dependency freshness gate reportsgithub:nixpkgs,github:rust-overlay, or other flake input updates. On macOS, current upstream Nix no longer supports single-user installs; use the official daemon installer on a release machine where system-level/nix, user, and launchd changes are acceptable.
PostgreSQL 17 is the default release feature:
export PG_VERSION_FEATURE=pg17
export PG_CONFIG=/path/to/postgresql-17/bin/pg_configInitialize pgrx once per machine and PostgreSQL major:
cd graph
cargo pgrx init --pg17 "$PG_CONFIG"If pgrx reports SQL definition drift after code changes, reinstall against the same PostgreSQL version:
cd graph
cargo pgrx install --pg-config "$PG_CONFIG" --features pg17 --no-default-featuresFast Preflight
Run this before long release gates so basic failures are found quickly:
./scripts/check_docs_drift.sh
python3 scripts/check_dependency_updates.py
cd graph
cargo fmt --check
cargo clippy --features "pg17 development" --all-targets -- -D warnings
cargo doc --features pg17 --no-deps
cargo test --features pg17
cargo pgrx test --features "pg17 development" pg17
cargo deny check advisories bans licenses sourcesDocumentation doctests are part of the public Rust API contract:
cd graph
cargo test --doc --features pg17Documentation And Metadata Checks
Run the aggregate docs drift gate from the repository root:
./scripts/check_docs_drift.shIt runs:
./scripts/check_doc_references.py
./scripts/check_sql_api_drift.py
./scripts/check_rust_doc_map_drift.pyUse targeted inventories when a failure needs diagnosis:
python3 scripts/check_sql_api_drift.py --list-implemented
python3 scripts/check_rust_doc_map_drift.py --listRun dependency freshness before release metadata freezes:
python3 scripts/check_dependency_updates.pyThe dependency checker reports update candidates without rewriting manifests
unless an explicit --update ... --yes is passed. Any package-manager command
that installs or adds a new dependency must use sfw.
Rust And SQL Test Layers
Use the narrowest layer while iterating, then run the broader release layers.
| Layer | Command | Required before release |
|---|---|---|
| Formatting | cd graph && cargo fmt --check | Yes |
| Clippy | cd graph && cargo clippy --features "pg17 development" --all-targets -- -D warnings | Yes |
| Rust unit tests | cd graph && cargo test --features pg17 | Yes |
| Rust docs | cd graph && cargo doc --features pg17 --no-deps | Yes |
| Rust doctests | cd graph && cargo test --doc --features pg17 | Yes |
| pgrx SQL tests | cd graph && cargo pgrx test --features "pg17 development" pg17 | Yes |
| Dependency audit | cd graph && cargo deny check advisories bans licenses sources | Yes |
| pgrx focused test | cd graph && cargo pgrx test pg17 <test_name> | Iteration only |
| pg_regress setup smoke | graph/tests/pg_regress/ | Packaging-style smoke only |
The pgrx SQL test files live in graph/src/pg_tests/ and cover discovery,
GQL, Cypher compatibility, traversal, paths, filters, registration/search,
sync/config/build behavior, maintenance/admin APIs, named graphs, workflow
APIs, validation, and synthetic release SQL shape.
Fuzz Gates
The release gate compiles fuzz binaries with cargo check --bins inside
graph/fuzz and runs projection seed corpora:
cd graph
(cd fuzz && cargo check --bins)
./fuzz/run_projection_seed_corpora.shWhen a release includes parser, loader, filter, sync, traversal option, or projection format changes, also run the cargo-fuzz compile smoke:
cd graph/fuzz
cargo fuzz buildFuzz targets currently cover:
| Target | Boundary |
|---|---|
load_graph_file | Persisted graph artifact loader |
node_ref_string | Node reference parser |
traverse_options | Traversal option parser |
sync_properties | Sync JSON property parser |
structured_filter | Structured filter validation |
gql_parser | GQL parser frontend |
cypher_parser | openCypher compatibility parser frontend |
load_projection_manifest | Durable projection manifest loader |
load_projection_segment | Durable projection segment loader |
Aggregate Release Gate
Run the main PostgreSQL 17 release gate from graph/:
cd graph
PG_VERSION_FEATURE=pg17 ./tests/heavy/run_release_gate.shBy default, this gate runs:
cargo fmt --check;cargo clippy --features "pg17 development" --all-targets -- -D warnings;cargo doc --features pg17 --no-deps;cargo test --features pg17;cargo pgrx test --features "pg17 development" pg17;cargo deny check advisories bans licenses sources;- fuzz binary compile and projection fuzz seed corpora;
package_validate.sh;fresh_install_smoke.sh;function_metadata_audit.sh;run_sqlstate_acl_boundary.sh;backup_restore_validate.sh;background_job_lock_regression.sh;build_lock_regression.sh;concurrency_stress.sh;synthetic_release_smoke.sh;playground_release_gate.sh;run_pgbench_sync.sh;gql_create_tx_lifecycle.sh;gql_set_tx_lifecycle.sh;gql_delete_tx_lifecycle.sh;gql_merge_race.sh;gql_relationship_race.sh;named_graphs_heavy_gate.sh;cross_backend_durable_projection.sh;projection_recovery_gate.sh;tx_delta_lifecycle.sh;gql_write_recheck_race.sh.
The default gate does not run Docker smoke, crash recovery, tx-delta crash recovery, full PostgreSQL-major matrix, or peak RSS. Enable those explicitly.
Full Production Gate
Use the repository’s disposable PostgreSQL wrapper for crash gates. It refuses caller-supplied clusters, development databases, and production paths.
For the reproducible RC tier, the repository creates and removes that cluster, retains one log per gate, and records dependency lockfile and artifact hashes:
python3 scripts/run_release.py --tier rcUse this lower-level aggregate form only for diagnosis; the wrapper still owns the cluster:
cd graph
PG_VERSION_FEATURE=pg17 \
DB_PREFIX=pggraph_release \
RUN_DOCKER=1 \
RUN_CRASH=1 \
RUN_TX_DELTA_CRASH=1 \
RUN_FULL_MATRIX=1 \
RUN_RSS=1 \
../scripts/with_disposable_postgres.sh ./tests/heavy/run_release_gate.shFor a staged environment that cannot run Docker, playground, pgbench, or crash checks, make skips explicit in the command and record why:
cd graph
PG_VERSION_FEATURE=pg17 \
DB_PREFIX=pggraph_release_staged \
RUN_PLAYGROUND=0 \
RUN_PGBENCH=0 \
RUN_DOCKER=0 \
RUN_CRASH=0 \
RUN_TX_DELTA_CRASH=0 \
./tests/heavy/run_release_gate.shRelease Gate Toggles
run_release_gate.sh accepts these environment variables:
| Variable | Default | Meaning |
|---|---|---|
PG_VERSION_FEATURE | pg17 | Cargo/PostgreSQL feature to test |
DB_PREFIX | pggraph_release | Prefix for disposable database names |
RUN_FULL_MATRIX | 0 | Run local PostgreSQL-major matrix first |
RUN_PACKAGE | 1 | Run package validation |
RUN_INSTALL | 1 | Run fresh install smoke |
RUN_METADATA | 1 | Run SQL function metadata audit |
RUN_BOUNDARY | 1 | Run SQLSTATE/ACL boundary tests |
RUN_BACKUP_RESTORE | 1 | Run backup/restore validation |
RUN_BACKGROUND_LOCK | 1 | Run background-job lock regression |
RUN_BUILD_LOCK | 1 | Run build/vacuum lock regression |
RUN_CONCURRENCY | 1 | Run mixed concurrency stress |
RUN_SYNTHETIC | 1 | Run synthetic release fixture |
RUN_PLAYGROUND | 1 | Run playground query gate |
RUN_PGBENCH | 1 | Run pgbench sync stress |
RUN_GQL_CREATE_TX | 1 | Run GQL CREATE transaction lifecycle |
RUN_GQL_SET_TX | 1 | Run GQL SET transaction lifecycle |
RUN_GQL_DELETE_TX | 1 | Run GQL DELETE transaction lifecycle |
RUN_GQL_MERGE_RACE | 1 | Run GQL MERGE race proof |
RUN_GQL_WRITE_RECHECK | 1 | Run GQL stale-predicate recheck race proof |
RUN_TX_DELTA_LIFECYCLE | 1 | Run internal tx-delta lifecycle proof |
RUN_NAMED_GRAPHS_HEAVY | 1 | Run named graph heavy policy gate |
RUN_CROSS_BACKEND_DURABLE | 1 | Run cross-backend durable projection gate |
RUN_PROJECTION_RECOVERY | 1 | Run projection recovery gate |
RUN_DOCKER | 0 | Run Docker smoke |
RUN_CRASH | 0 | Run crash recovery, requires disposable PGDATA |
RUN_TX_DELTA_CRASH | 0 | Run tx-delta crash recovery, requires disposable PGDATA |
RUN_RSS | 0 | Run peak RSS measurement |
RUN_BUILD_MEMORY_STRESS | 0 | Run baseline, small-batch, rebuild, and low-memory rebuild RSS profiles |
Synthetic fixture tuning:
| Variable | Default |
|---|---|
SYNTHETIC_NODE_COUNT | 50000 |
SYNTHETIC_HUB_FANOUT | 1000 |
SYNTHETIC_MAX_BUILD_MS | 60000 |
SYNTHETIC_MAX_QUERY_MS | 1000 |
pgbench sync tuning:
| Variable | Default |
|---|---|
CLIENTS | 4 |
JOBS | 2 |
TIME | 30 |
Heavy Script Inventory
Run these from graph/. Most accept PG_VERSION_FEATURE=pg17 and a disposable
DBNAME. Scripts that kill, upgrade, or inspect PostgreSQL clusters require
disposable cluster paths.
| Script | Release purpose | Example |
|---|---|---|
run_release_gate.sh | Aggregate release gate | PG_VERSION_FEATURE=pg17 ./tests/heavy/run_release_gate.sh |
run_pg_matrix.sh | Local PostgreSQL 14 through 18 matrix | ./tests/heavy/run_pg_matrix.sh |
run_pg_matrix_docker.sh | Docker PostgreSQL-major matrix | ./tests/heavy/run_pg_matrix_docker.sh |
run_gql_write_matrix.sh | PostgreSQL-major GQL write matrix | ./tests/heavy/run_gql_write_matrix.sh |
package_validate.sh | Validate pgrx package shape and companion files | PG_VERSION_FEATURE=pg17 ./tests/heavy/package_validate.sh |
fresh_install_smoke.sh | Install extension and run quick workflow | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_install ./tests/heavy/fresh_install_smoke.sh |
function_metadata_audit.sh | Audit SQL volatility, security, cost, rows, and parallel metadata | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_metadata ./tests/heavy/function_metadata_audit.sh |
run_sqlstate_acl_boundary.sh | Assert client-visible SQLSTATEs and restricted-role ACL behavior | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_boundary ./tests/heavy/run_sqlstate_acl_boundary.sh |
backup_restore_validate.sh | Validate dump/restore of source tables, graph catalog, sync state, and persisted graph behavior | PG_VERSION_FEATURE=pg17 SOURCE_DB=pggraph_backup_src RESTORE_DB=pggraph_backup_dst ./tests/heavy/backup_restore_validate.sh |
background_job_lock_regression.sh | Check background job lock and failure-state behavior | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_background_lock ./tests/heavy/background_job_lock_regression.sh |
build_lock_regression.sh | Check build/vacuum lock conflict behavior | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_build_lock ./tests/heavy/build_lock_regression.sh |
concurrency_stress.sh | Exercise build, sync, vacuum, maintenance, and traversal concurrently | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_concurrency CLIENTS=3 ROUNDS=3 ./tests/heavy/concurrency_stress.sh |
synthetic_release_smoke.sh | Deterministic release fixture for build, persistence, traversal, search, filters, paths, and components | DBNAME=pggraph_synthetic NODE_COUNT=50000 HUB_FANOUT=1000 ./tests/heavy/synthetic_release_smoke.sh |
run_synthetic_release_evidence.sh | Synthetic smoke plus metadata and persisted artifact inspection | NODE_COUNT=50000 HUB_FANOUT=1000 ./tests/heavy/run_synthetic_release_evidence.sh |
playground_release_gate.sh | Validate every playground sidebar query against stable summaries | PGGRAPH_PLAYGROUND_YES=1 ./tests/heavy/playground_release_gate.sh |
run_pgbench_sync.sh | Concurrent DML and trigger-sync stress | DBNAME=pggraph_pgbench CLIENTS=4 JOBS=2 TIME=30 ./tests/heavy/run_pgbench_sync.sh |
read_latency_under_sync.sh | Measure read p50/p95/p99 with no backlog, pending backlog, and concurrent writers | DBNAME=pggraph_read_latency NODE_COUNT=10000 SAMPLES=25 ./tests/heavy/read_latency_under_sync.sh |
gql_create_tx_lifecycle.sh | Public mapped GQL CREATE commit and rollback proof | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_gql_create_tx ./tests/heavy/gql_create_tx_lifecycle.sh |
gql_set_tx_lifecycle.sh | Public mapped GQL property SET rollback and filter-delta proof | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_gql_set_tx ./tests/heavy/gql_set_tx_lifecycle.sh |
gql_delete_tx_lifecycle.sh | Public mapped GQL edge-row DELETE rollback and tombstone proof | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_gql_delete_tx ./tests/heavy/gql_delete_tx_lifecycle.sh |
gql_merge_race.sh | Concurrent mapped MERGE same-key convergence proof | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_gql_merge_race ./tests/heavy/gql_merge_race.sh |
gql_relationship_race.sh | Concurrent relationship CREATE/DELETE winner, SQLSTATE, and rollback proof | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_gql_relationship_race ./tests/heavy/gql_relationship_race.sh |
gql_write_recheck_race.sh | Two-session stale predicate recheck proof for mapped writes | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_gql_write_recheck ./tests/heavy/gql_write_recheck_race.sh |
tx_delta_lifecycle.sh | Internal mutable-overlay transaction lifecycle proof | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_tx_delta ./tests/heavy/tx_delta_lifecycle.sh |
named_graphs_heavy_gate.sh | Named-graph behavior and policy guardrails | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_named_graphs bash ./tests/heavy/named_graphs_heavy_gate.sh |
cross_backend_durable_projection.sh | Cross-backend visibility for durable mutable projection state | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_cross_backend bash ./tests/heavy/cross_backend_durable_projection.sh |
projection_recovery_gate.sh | Durable projection recovery behavior | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_projection_rec bash ./tests/heavy/projection_recovery_gate.sh |
docker_smoke.sh | Build root Docker image and run extension workflow in container | IMAGE=pggraph:smoke CONTAINER=pggraph-smoke PG_MAJOR=17 ./tests/heavy/docker_smoke.sh |
crash_recovery.sh | Kill and restart disposable postmaster, then verify reload and corrupt artifact rejection | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_crash PGDATA=/path/to/disposable/pgdata ./tests/heavy/crash_recovery.sh |
tx_delta_crash_recovery.sh | Kill disposable postmaster with uncommitted overlay and verify it does not persist | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_tx_delta_crash PGDATA=/path/to/disposable/pgdata ./tests/heavy/tx_delta_crash_recovery.sh |
run_crash_matrix.sh | Run both destructive crash profiles on PostgreSQL 14–18 through new disposable clusters | PG_VERSIONS="14 15 16 17 18" ./tests/heavy/run_crash_matrix.sh |
run_pg_upgrade_matrix.sh | Run adjacent PostgreSQL 14→15 through 17→18 pg_upgrade --check and rebuild validation | ./tests/heavy/run_pg_upgrade_matrix.sh |
pg_upgrade_validate.sh | Validate one sentinel-owned PostgreSQL upgrade pair; normally called by the matrix wrapper | ./tests/heavy/run_pg_upgrade_matrix.sh |
measure_build_rss.sh | Capture peak backend RSS during graph build | PG_VERSION_FEATURE=pg17 DBNAME=pggraph_rss NODE_COUNT=200000 MAX_RSS_MB=0 ./tests/heavy/measure_build_rss.sh |
build_memory_stress.sh | Run baseline, small-batch, repeated-rebuild, and low-memory rebuild profiles | PG_VERSION_FEATURE=pg17 DB_PREFIX=pggraph_memstress ./tests/heavy/build_memory_stress.sh |
measure_mmap_pss.sh | Linux-only mmap sharing PSS measurement across backends | DBNAME=graph_test BACKENDS=50 ./tests/heavy/measure_mmap_pss.sh |
run_memory_sanitizers.sh | pgrx suite plus optional Rust ASan or disposable PostgreSQL-process Valgrind checks | DBNAME=pggraph_pgbench ./tests/heavy/run_memory_sanitizers.sh |
run_postgres_process_sanitizer.sh | Require zero unsuppressed Valgrind errors across persisted mmap, corruption, callback, guarded-error, and build-job paths | PG_VERSION_FEATURE=pg17 ./tests/heavy/run_postgres_process_sanitizer.sh |
run_durable_projection_matrix.sh | Run cross-backend durable lifecycle, concurrent relation-identity DDL, and publication/writer-lock evidence on PostgreSQL 14-18 | RUN_RUST_TESTS=0 RUN_PGRX_SQL=0 RUN_GQL_WRITE_MATRIX=0 RUN_DURABLE_PROJECTION_MATRIX=1 ./tests/heavy/run_pg_matrix_docker.sh |
pgbench_sync.sql, sqlstate_acl_boundary.sql, and
playground_release_gate.py are support files used by the shell gates.
Crash, Upgrade, And Cluster Safety
Crash gates deliberately kill PostgreSQL. Run them only against a disposable cluster, and pass restart options when the instance uses custom socket or port settings:
cd graph
PGHOST=/tmp/pggraph-crash \
PGPORT=55437 \
PGDATA=/tmp/pggraph-crash/data \
POSTGRES_CTL=/path/to/pg_ctl \
POSTGRES_OPTS="-p 55437 -k /tmp/pggraph-crash" \
DBNAME=pggraph_release_crash \
./tests/heavy/crash_recovery.shRun the tx-delta crash gate with the same disposable cluster pattern:
cd graph
PGHOST=/tmp/pggraph-crash \
PGPORT=55437 \
PGDATA=/tmp/pggraph-crash/data \
POSTGRES_CTL=/path/to/pg_ctl \
POSTGRES_OPTS="-p 55437 -k /tmp/pggraph-crash" \
PG_CONFIG=/path/to/pg_config \
PG_VERSION_FEATURE=pg17 \
DBNAME=pggraph_release_tx_delta_crash \
./tests/heavy/tx_delta_crash_recovery.shRun upgrade validation in the supported-major Docker environment. The wrapper creates both clusters, installs the matching extension binaries, and supplies the required safety sentinel:
cd graph
./tests/heavy/run_pg_upgrade_matrix.shMatrix Gates
Run the local PostgreSQL-major matrix when all supported pg_config binaries
are available:
cd graph
./tests/heavy/run_pg_matrix.shUse Docker when local headers are unavailable:
cd graph
./tests/heavy/run_pg_matrix_docker.shThe project supports PostgreSQL 14 through 18 in release automation. If a matrix leg is skipped locally, record which major was skipped and where it will be validated.
Performance And Benchmark Evidence
Run Criterion when engine-level traversal, filter, storage, or overlay changes could affect hot paths:
cd graph
cargo bench --bench bfs_benchWhen comparing against a saved Criterion baseline:
cd graph
cargo bench --features "pg17 benchmarks" --bench bfs_bench -- --baseline pre_releaseRun SQL-facing benchmark harnesses only when the release owner asks for performance evidence or the change affects SQL-facing query timing:
sandbox/run_benchmarks.sh panama
sandbox/run_benchmarks.sh ldbc
sandbox/run_benchmarks.sh all --yesKeep generated report.json files with release evidence. Include the exact
command, commit, dirty status, PostgreSQL version, Docker resource settings,
machine details, and whether the host was otherwise idle.
Run read-latency evidence when query-time sync semantics or topology-read freshness change:
cd graph
DBNAME=pggraph_read_latency \
NODE_COUNT=10000 \
SAMPLES=25 \
CONCURRENT_SAMPLES=25 \
SMALL_BACKLOG=100 \
LARGE_BACKLOG=5000 \
CLIENTS=4 \
JOBS=2 \
TIME=30 \
RATE=100 \
./tests/heavy/read_latency_under_sync.shKeep read-latency-samples.csv and read-latency-summary.csv with milestone
evidence.
Package And Publish Workflow Checks
Publishing requires four explicit release-owner steps after all required gates pass: tag, sign, package, and push. Do not start these steps from a dirty worktree or from a commit that has not completed the required release gate.
Required local state:
- The release commit is checked out and
git status --shortis empty. graph/Cargo.toml, package metadata, docs, Docker defaults, and release notes identify the intended version.- Before tagging,
scripts/validate_release.pypasses with--version X.Y.Z, the exact full commit SHA,--check-main, and--require-clean. - A signing key is configured for Git tags. Use the repository’s required signing backend, such as GPG, SSH signing, or the platform-managed signing flow.
- Docker is available if preparing Docker images or validating playground packaging.
- PGXN credentials, GitHub credentials, Docker registry credentials, and any required 2FA/session state are available to the release owner.
Prepare and verify the exact source candidate before any tag or publication:
commit="$(git rev-parse HEAD)"
scripts/prepare_release_bundle.py --ref "$commit" --out-dir dist/release-bundle
scripts/verify_release_bundle.py dist/release-bundle --commit "$commit"The bundle contains one PGXN ZIP, SPDX 2.3 SBOM, provenance statement,
release-manifest.json, and SHA256SUMS. Repeating preparation from the same
commit must produce the same payload digests. Publication consumes these exact
verified bytes; it does not rebuild the ZIP.
Before release automation:
./scripts/clean_generated_artifacts.sh --dry-run
./scripts/check_docs_drift.sh
python3 scripts/check_dependency_updates.py
cd graph
PG_VERSION_FEATURE=pg17 ./tests/heavy/package_validate.sh
PG_VERSION_FEATURE=pg17 DBNAME=pggraph_install ./tests/heavy/fresh_install_smoke.shCreate the signed release tag only after the release commit and evidence are final:
git status --short
git log -1 --oneline
git tag -s vX.Y.Z -m "vX.Y.Z"
git tag -v vX.Y.ZIf the project uses SSH tag signing instead of GPG, configure Git before creating the tag:
git config gpg.format ssh
git config user.signingkey /path/to/release-signing-key.pub
git tag -s vX.Y.Z -m "vX.Y.Z"
git -c gpg.ssh.allowedSignersFile=release/ssh-allowed-signers tag -v vX.Y.ZThe checked-in SSH allowed-signers file is the publication trust policy used by local validation and the release workflow. Changes to that file require explicit release-owner review.
Build and validate release packages before pushing the tag:
scripts/validate_release.py --tag vX.Y.Z --check-main \
--require-clean --require-signed-tag
cd graph
PG_VERSION_FEATURE=pg17 ./tests/heavy/package_validate.shPush only after package validation and tag verification pass:
git push origin HEAD
git push origin vX.Y.ZThe GitHub Actions release workflow has two manual phases. The intended tag name is supplied to both, but preparation happens before the tag exists:
| Phase | Required state |
|---|---|
prepare | A full 40-character source commit is supplied; the verified source bundle and Docker manifests are prepared and attested. |
publish | A signed annotated tag and GitHub Release exist at that exact commit; the prepared run ID is supplied and every published byte or image digest is reused without rebuilding. |
Run the prepare phase first and inspect its generated artifacts and
attestations before creating the tag. The publish phase must consume prepared
artifacts for the exact tag; it must not rebuild from a moving branch or
untagged commit.
Homebrew is a separate channel. After the signed release exists, the tap owner
updates the formula URL and SHA-256 from the verified source bundle, runs
brew audit --strict --online pggraph, brew style pggraph, and
brew test pggraph, then verifies the installed PostgreSQL 17 extension reports
the released version. Do not describe the formula as available before that
handoff completes.
Use this when validating release metadata locally:
scripts/validate_release.py --version X.Y.Z --ref "$(git rev-parse HEAD)" --check-main --require-cleanEvidence Template
Record this for each release candidate:
Release candidate:
Commit:
Dirty status:
Date:
Machine/OS:
PostgreSQL major:
PG_CONFIG:
pgrx version:
Docker version:
Required gates:
- docs drift:
- dependency freshness:
- fmt:
- clippy:
- cargo doc:
- cargo test:
- cargo test --doc:
- cargo pgrx test:
- cargo deny:
- fuzz compile:
- projection seed corpora:
- aggregate release gate:
Opt-in gates:
- Docker smoke:
- crash recovery:
- tx-delta crash recovery:
- PostgreSQL-major matrix:
- RSS/PSS:
- sanitizer:
- Criterion:
- sandbox benchmark:
Skipped gates and waivers:
- gate:
reason:
owner:
follow-up: