Contributing
git clone https://github.com/gdpotter/pgmt.gitcd pgmt./scripts/test-setup.sh # Start PostgreSQL containerscargo test # Run testsPrerequisites: Rust 1.85+, Docker
Code Style
Section titled “Code Style”cargo fmtbefore committingcargo clippy -- -D warnings- no warnings- Use
anyhow::Resultfor errors - All SQL queries use sqlx compile-time verification
- Tests required for new features
Logging Guidelines
Section titled “Logging Guidelines”Correct logging is critical for UX. The default level is warn:
println!(): User-facing output (commands, results, migration plans) — always visibleinfo!(): Operational details (connection status, success messages) — visible with--verbosedebug!(): Implementation details (timing, retries, temp schemas) — visible with--debugwarn!(): Potential problems (not expected behaviors like “404 during cleanup”)
Rule of thumb: Ask “Would this scare a first-time user?” If yes, use debug!() not println!().
Adding Database Object Support
Section titled “Adding Database Object Support”Each object type needs:
-
Catalog module (
src/catalog/object.rs)fetch()function using PostgreSQL system catalogs- Include
comment: Option<String>field - Implement
DependsOnandCommentabletraits
-
Diff logic (
src/diff/object.rs)- Compare old vs new states
- Generate CREATE, DROP, ALTER operations
- Handle comment changes with
diff_comments()
-
Migration operations (
src/diff/operations/)- Define operation enums
- Implement
SqlRenderertrait
-
Tests (
tests/catalog/andtests/migrations/)
Look at src/catalog/triggers.rs for a pattern to follow.
Testing
Section titled “Testing”// Isolated test database#[tokio::test]async fn test_fetch() { with_test_db(async |db| { db.execute("CREATE TABLE users (id INT)").await; let tables = fetch(db.pool()).await.unwrap(); assert_eq!(tables.len(), 1); }).await;}
// Migration testing#[tokio::test]async fn test_migration() { let helper = MigrationTestHelper::new().await; helper.run_migration_test( &[], // Both databases &[], // Initial only &["CREATE TABLE users (id INT)"], // Target only |steps, _| { assert!(!steps.is_empty()); Ok(()) } ).await;}Pull Requests
Section titled “Pull Requests”Before submitting:
cargo testcargo fmtcargo clippy -- -D warningsSQLX_OFFLINE=true cargo buildPR requirements:
- Clear description of changes
- Tests pass
- No clippy warnings
- sqlx metadata committed (
.sqlx/files)
Releasing
Section titled “Releasing”Releases are automated with git-cliff for the changelog
and cargo-release for the version
bump and tag. Pushing a vX.Y.Z tag triggers .github/workflows/release.yml,
which builds the binaries and publishes to crates.io and npm — the local steps
deliberately do not publish.
1. Curate the changelog. CHANGELOG.md is user-facing, not a commit dump.
The ## Unreleased section is maintained by hand; draft entries from recent
commits with:
git cliff --unreleased # preview entries since the last tagMove the genuinely user-facing items into ## Unreleased under Breaking
Changes / Features / Bug Fixes / Performance, and drop noise (refactors,
tests, CI, dependency bumps) and fixes to still-unreleased work. Writing
Conventional Commits keeps the draft
clean — git-cliff groups by type and filters chores automatically.
2. Cut the release from a green main:
cargo release minor # preview: patch | minor | major | X.Y.Zcargo release minor --execute # bump Cargo.toml + Cargo.lock, stamp the # changelog, commit, tag vX.Y.Z, and pushcargo-release promotes ## Unreleased into a dated version section, then the
pushed tag drives CI, which extracts that section for the GitHub release notes
and publishes everything.
Version bumps are explicit: cargo release does exactly the level you name
(pre-1.0, a feature release is minor, e.g. 0.4.x → 0.5.0). Configuration lives
in cliff.toml and release.toml.
Reporting Issues
Section titled “Reporting Issues”Include: pgmt version, PostgreSQL version, OS, full error messages, steps to reproduce.
Code Organization
Section titled “Code Organization”| Directory | Purpose |
|---|---|
catalog/ | PostgreSQL introspection |
diff/ | Schema comparison |
commands/ | CLI implementations |
config/ | Configuration |
schema_loader/ | Multi-file schema loading |
render/ | SQL generation |