Skip to content

feat: release v1.3.0 - Docker Stack, Multi-Schema Support, Auto-Container, CI Improvements, and Documentation#44

Merged
Yasirunet merged 79 commits into
mainfrom
development
Jul 2, 2026
Merged

feat: release v1.3.0 - Docker Stack, Multi-Schema Support, Auto-Container, CI Improvements, and Documentation#44
Yasirunet merged 79 commits into
mainfrom
development

Conversation

@supunappri99

@supunappri99 supunappri99 commented May 13, 2026

Copy link
Copy Markdown
Collaborator

feat: release v1.3.0 - Docker Stack, Multi-Schema Support, Auto-Container, CI Improvements, and Documentation

Branch: developmentmain

Summary

This release introduces a major upgrade to PostKit's local development experience with a fully integrated Docker Stack module, while expanding the database engine with multi-schema support, automatic local PostgreSQL containers, improved CI/CD workflows, and comprehensive documentation updates.

The new Docker Stack module enables developers to manage PostgreSQL, Keycloak, PostgREST, and Traefik using a single CLI, providing an opinionated local backend environment with automated initialization, Keycloak configuration, JWT synchronization, and lifecycle management.

In addition, v1.3.0 delivers a redesigned database architecture with multi-schema support, improved configuration management, automatic Docker-based PostgreSQL provisioning, stronger GitHub Actions pipelines, and significant documentation and testing improvements.

Changes

Docker Stack

  • Added new postkit stack module with commands:
    • stack up
    • stack down
    • stack status
    • stack logs
    • stack restart
    • stack keys
    • stack realm
  • Two-phase startup process to initialize infrastructure before application services
  • Automatic Keycloak realm import
  • Automatic PostgREST JWT key synchronization
  • Built-in and project-specific Keycloak provider support
  • Database-backed is_initial flag for first-time initialization
  • Automatic reset of initialization state when using stack down --volumes

Database

  • Added full PostgreSQL multi-schema support
  • Replaced schema with schemas
  • Added per-schema planning and generation
  • Added cross-schema migration support
  • Combined migration output across schemas
  • Added postkit db schema add command
  • Added dedicated db/infra directory
  • Added automatic Docker PostgreSQL container management for local development

Configuration

  • Split configuration into:
    • postkit.config.json
    • postkit.secrets.json
  • Improved configuration loading and migration

CI/CD

  • Added GitHub Actions PR validation workflow
  • Updated release workflow to require:
    • Build
    • Unit Tests
    • E2E Tests

Documentation

  • Added Docker Stack documentation
  • Updated architecture documentation
  • Updated E2E testing documentation
  • Added multi-schema documentation
  • Added cross-schema migration guide
  • Added schema command documentation
  • Updated agent skills
  • Updated documentation site

Testing

  • Added comprehensive unit tests for Docker Stack
  • Added Stack E2E test suite
  • Added multi-schema workflow tests
  • Added auto-container tests
  • Added restart and initialization tests
  • Added error handling tests

Type of Change

  • feat: New feature

Test Plan

  • Unit tests pass (npm run test)
  • E2E tests pass (npm run test:e2e)
  • Build succeeds (npm run build)
  • Manually tested:
    • Docker Stack lifecycle
    • Multi-schema plan/apply workflow
    • Auto-container mode
    • Keycloak initialization
    • JWT synchronization
    • Documentation site build

Breaking Changes

  • Breaking changes — existing projects must migrate before upgrading.

Configuration changes

- "schema": "public"
+ "schemas": ["public"]
+ "infraPath": "db/infra"

Directory structure

Before
db/schema/infra/

After
db/infra/

Schema layout

Before
db/schema/tables/

After
db/schema/public/tables/

Generated files

plan.sql      → plan_<schema>.sql
schema.sql    → schema_<schema>.sql

Session state

Existing active sessions should be cleared before upgrading:

postkit db abort

default and others added 30 commits April 25, 2026 19:02
…actor configuration into committed and ignored secrets files
…m postkit.config.json to postkit.secrets.json in E2E tests
…lizing utility functions and standardizing deployment steps.
…iguration storage, and internal service functions
…crets

refactor: split config/secrets, auto-container mode, dedup utilities
…ingle to array-based schema configuration and per-schema file handling
@cloudflare-workers-and-pages

cloudflare-workers-and-pages Bot commented May 15, 2026

Copy link
Copy Markdown

Deploying postkit with  Cloudflare Pages  Cloudflare Pages

Latest commit: 3b04300
Status: ✅  Deploy successful!
Preview URL: https://3139612c.postkit.pages.dev

View logs

@supunappri99

Copy link
Copy Markdown
Collaborator Author

⏺ Issue 1 — No Fix Needed

Cross-schema migration is not a supported feature of the plan command.
The intermediate apply step exists only to enable cross-schema reference resolution, which is outside the intended scope.

As a result, a failure during this step has no impact on supported workflows.
The reviewer's concern does not apply in this context.

⏺ Issue 2 — No Fix Needed

The fingerprint check is a valid and necessary safety mechanism.

The existing error message already provides clear guidance:

Run postkit db plan again

Re-running the plan command takes only a few seconds and is the correct and safest action.
There is no practical scenario where bypassing this check is safer than regenerating the plan.

Introducing a --skip-fingerprint-check flag would:

  • Expand the API surface unnecessarily
  • Increase testing and maintenance overhead
  • Allow users to apply a plan against mismatched schema files

This friction is intentional and helps prevent unsafe operations.


Answers for Questions

1. Why is intermediate apply for cross-schema resolution non-fatal?

The non-fatal behavior is intentional. The intermediate apply strips structural SQL only (CREATE/ALTER/DROP — no policies, no grants) and runs with ON_ERROR_STOP=1.

Error types that are safe to ignore:

  • "already exists" — the object was applied to the local DB in a previous session run, so it is already present for cross-schema resolution. This is the most common case.
  • Policy/grant leakage — the line-level filter in plan.ts:169-183 is a simple startsWith check, so multi-line statements can occasionally leak through and fail harmlessly without affecting structural resolution.

If the apply fails for a genuinely structural reason (e.g. a missing type), the dependent schema's pgschema run will fail anyway with a direct, clear error. The non-fatal warn avoids false-fatal errors from the "already exists" class while still surfacing that something went wrong.

Note: Cross-schema migration is not a currently supported feature. The intermediate apply block is aspirational code and its failure mode has no impact on supported workflows.


2. Should empty schema directories be allowed?

The skip-by-warn behavior is intentional and the correct UX for the current design.

postkit.config.json is committed and shared with the team, but individual developers may be at different stages of setup. A hard error on a missing directory would break postkit db plan for any developer who hasn't yet scaffolded a schema that a teammate added to config. The warn + continue approach lets everyone keep working while clearly surfacing that action is needed.

Running postkit db schema add is not a prerequisite gate — it is a convenience command. The flexible skip-by-warn is the intended behavior.


3. Any plans for automated config migration?

Automated config migration already exists. common/config.ts:182-211 runs on every loadPostkitConfig() call and silently migrates:

  • remoteDbUrlremotes.default
  • environments.*remotes.*

The migrated result is written back to postkit.secrets.json in place, so the transition is transparent to the user.

A separate postkit db migrate-config command would only be needed if breaking changes are made to postkit.config.json (the committed file). Currently all breaking format changes are in the secrets file, which the runtime auto-migration handles. No explicit command is planned unless committed config structure changes.


4. Is SHOW server_version_num reliable across all cloud providers?

Yes. server_version_num is a core PostgreSQL GUC defined in the PostgreSQL source. It cannot be overridden by providers and is not provider-specific.

Every managed Postgres service (RDS, Aurora, Cloud SQL, Neon, Supabase) runs real PostgreSQL and exposes this value correctly.

Format: Always a zero-padded 6-digit integer — XXYYZZ where XX = major, YY = minor, ZZ = patch.

Example value Meaning
160003 PostgreSQL 16.3
150008 PostgreSQL 15.8
140012 PostgreSQL 14.12

The implementation at database.ts:148 extracts the major version with Math.floor(num / 10000), which is correct for this format. No known provider deviates from it.

@nipunappri

nipunappri Bot commented May 18, 2026

Copy link
Copy Markdown

Thanks for the detailed responses on Issues 1–2 and all four questions — the reasoning is clear and no further discussion is needed there.

However, Issues 3 and 4 from the review were not addressed. Could you confirm whether these are no-fix (with rationale, as you did for Issues 1–2) or if a fix is planned?


Issue 3 — Container cleanup on SIGKILL

If the CLI process is killed with SIGKILL before stopSessionContainer is called, the Docker container leaks. abort and deploy handle the happy path, but an unexpected crash bypasses cleanup entirely.

Is adding process exit signal handlers (SIGTERM/SIGINT/SIGHUP) planned, or is this an accepted tradeoff for now?


Issue 4 — Port exhaustion error message

When all ports 15432–15532 are taken, the error thrown gives no actionable guidance to the user. The suggestion was to include a hint such as:

docker ps | grep postkit-session

...so users can identify and clean up leftover PostKit containers. This is a small UX improvement — is it something you can add to the error message?

@nipunappri

nipunappri Bot commented May 18, 2026

Copy link
Copy Markdown

📝 Blog Post Fact-Check — PR #44

Fact-checked all 5 blog posts against both the source code and general technical knowledge (Prisma, Supabase, PostgreSQL, Docker). Blogs 2 and 4 are fully accurate. Found issues in Blogs 1, 3, and 5.


✅ No Issues

  • 2026-05-06-schema-as-code-vs-migrations.md — fully accurate
  • 2026-05-10-why-session-based-migrations.md — fully accurate

🟡 Blog 1 — 2026-05-04-migrating-from-prisma.md

Minor — GIN index claim overstates Prisma's limitation

The post says: "Complex index types — GIN, BRIN, partial indexes require @@index raw map or custom SQL"

This is partially outdated. Prisma supports GIN indexes natively via type: Gin on @@index (e.g., for full-text search with gin_trgm_ops). BRIN and partial indexes do still require raw SQL — but GIN works within Prisma's schema syntax for supported use cases. Grouping all three together overstates the limitation.

Fix: Separate GIN (partially supported) from BRIN and partial indexes (require raw SQL).


🔴 Blog 3 — 2026-05-08-multi-schema-postgres.md

Issue 1 — Cross-schema FK error misattributed to PostgreSQL

The post says:

"If you write this in db/schema/app/tables/orders.sql: REFERENCES public.users(id) — you'll get ERROR: relation "public.users" does not exist"

This is presented as a PostgreSQL restriction, but it's actually a pgschema plan-time tooling limitation — pgschema processes schemas in isolation and may not have visibility into sibling schema objects at diff time. PostgreSQL itself handles cross-schema foreign keys perfectly fine natively.

Fix: Clarify that this is a pgschema diff-engine limitation ("pgschema doesn't resolve cross-schema references at plan time"), not a PostgreSQL restriction. The current wording could mislead readers into thinking cross-schema FKs don't work in PostgreSQL.

Issue 2 — "Step 2: Add the schema creation to infra" is not a manual step

The post presents adding CREATE SCHEMA IF NOT EXISTS app; to an infra file as a manual task the user must perform. But postkit db schema add app already does this automatically (Step 2 of the command calls appendSchemaToInfraFile).

Following the blog as written would result in a duplicate CREATE SCHEMA statement.

Fix: Replace Step 2 with a note: "schema add automatically appends the CREATE SCHEMA statement to your infra file — no manual edit required."

  • Source: cli/src/modules/db/commands/schema.ts, cli/src/modules/db/services/schema-scaffold.ts

Issue 3 (minor) — Infra file path is speculative

The example shows db/infra/002_schemas.sql as the target infra file. The actual path resolution (resolveInfraTargetFile) searches for an existing file containing CREATE SCHEMA, then one matching /schema/i, and falls back to a new schemas.sql — not necessarily 002_schemas.sql.

Issue 4 (minor) — SQL identifier quoting mismatch

The example shows CREATE SCHEMA IF NOT EXISTS app; (unquoted), but the implementation writes CREATE SCHEMA IF NOT EXISTS "app"; (double-quoted identifier).


🔴 Blog 5 — 2026-05-12-migrating-from-supabase-to-postkit.md

Issue 1 — RLS policies are in policies/, not grants/

The post says: "Row-level security (RLS) policies — pgschema captures these in grants/ files."

This is wrong. RLS policies (CREATE POLICY) are stored in the policies/ subdirectory. The grants/ directory holds privilege grant statements (GRANT/REVOKE). Blog 1 in this same PR correctly refers to db/schema/<name>/policies/ for RLS — Blog 5 contradicts it.

Fix: Change grants/policies/ in this sentence.

  • Source: cli/src/modules/db/services/schema-scaffold.ts SCHEMA_SUBDIRS (both policies and grants exist as separate dirs)

Issue 2 — postkit init does not create db/schema/

Step 2 of the guide lists db/schema/ as something postkit init creates. It doesn't. postkit init only creates config files and the .postkit/ internal directory structure. The db/schema/ tree is created by postkit db import (Step 4) or postkit db schema add.

Fix: Remove db/schema/ from the postkit init output list, or add a clarifying note.

  • Source: cli/src/commands/init.tsmkdirSync calls only target .postkit/db/ and .postkit/auth/

Issue 3 (minor) — public schema default grant is Supabase-specific

The post says: "Supabase's public schema has a broad default grant (GRANT ALL ON SCHEMA public TO public)" — this is accurate for Supabase, but the framing could confuse readers because PostgreSQL 15+ removed this default for standard installations. Worth qualifying with "Supabase explicitly restores this grant" so readers don't carry the misconception into non-Supabase Postgres deployments.

@supunappri99

Copy link
Copy Markdown
Collaborator Author

Fixed them in the upcoming PR #42. The read issue has also been fixed.

@supunappri99 supunappri99 changed the title feat: multi-schema support, auto-container, CI workflows, and docs feat: release v1.3.0 - Docker Stack, Multi-Schema Support, Auto-Container, CI Improvements, and Documentation Jul 2, 2026
@Yasirunet Yasirunet merged commit 038027b into main Jul 2, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants