Skip to content

feat(postgres): upgrade to PostgreSQL 18 with data migration - #194

Merged
koydas merged 3 commits into
mainfrom
dependabot/docker/databases/postgre/postgres-18
Oct 1, 2026
Merged

koydas merged 3 commits into
mainfrom
dependabot/docker/databases/postgre/postgres-18

Conversation

@dependabot

@dependabot dependabot Bot commented on behalf of github Sep 29, 2026 •

Copy link
Copy Markdown
Contributor

Closes #203. Started as Dependabot's postgres 16 → 18 bump, completed with the migration it needs (ADR-004, ADR-005).

Why the bare bump failed

Changes

  • 18+ layout: VOLUME /var/lib/postgresql. The root compose uses a new postgres18-data volume, and the local runner (start.sh, databases/postgre/docker-compose.yml) uses ./pgdata. The 16 volume/directory is left untouched.
  • databases/postgre/upgrade-major.sh: pg_dumpall with the old image, then a restore into an empty destination with the new image. The source is only read. It accepts volume names or absolute host paths. Defaults cover compose 16 → 18. The only error it tolerates is the superuser's CREATE ROLE (that role already exists in the new cluster); any other restore error fails the run.
  • db-upgrade harness: the PostgreSQL mount is read from each image's VOLUME. A new DB_UPGRADE_MIGRATE_SCRIPT makes the harness migrate to a new volume when the postgres major changes (exit 6 if the script fails). The workflow sets it for postgres (databases/postgre) only. The 16 → 17 self-test, which must exit 4, is unchanged.
  • Docs: ADR-005 (database major upgrades), the procedure in databases/postgre/README.md, and a new RUNBOOK section (3).

Validation (local, Docker)

  • Harness, CI-like: base image (16) → head image (18) with migration returns 0. Without migration it returns 4, as expected. Self-test 16 → 17 returns 4. Same-major 18 → 18 with the script set stays in place and returns 0. mongo:8 → mongo:8 returns 0.
  • upgrade-major.sh, 16 → 18 on a volume with tables, a sequence, a second login role with grants and a second database: all present and readable on 18, with data under /var/lib/postgresql/18/docker. The source volume still reports PG_VERSION 16. A non-empty destination and a missing source are both refused (exit 1). Bind-path mode was also checked.
  • Full procedure: PG16 compose volume with services-service migrated by alembic plus one row → upgrade-major.sh (defaults) → docker compose up postgres → the row and alembic_version are readable on 18.6.
  • services-service against compose PG18 on a fresh volume: alembic upgrade head passes, and POST/GET /api/services work.
  • shellcheck, actionlint and npm run test:consistency (10/10) are clean.

Notes

  • Anyone with local data runs upgrade-major.sh once (see the README). Without it, PG18 simply starts empty on the new volume and nothing is lost.
  • services/services-service/.devops/secret.yaml points to a postgres host that has no manifest in this repository. A cluster-side PostgreSQL, if there is one, needs its own upgrade procedure.

Checklist

  • All CI checks pass
  • README.md updated if behaviour changed (databases/postgre/README.md, docs/RUNBOOK.md)
  • ADR created or updated if an architectural decision was made (ADR-005)
  • New service registered in discover-services.js and smoke tests added if applicable: N/A

🤖 Generated with Claude Code

https://claude.ai/code/session_01AjJSKb3q2o1MHd4gRs98tL

@dependabot dependabot Bot added dependencies Pull requests that update a dependency file docker Pull requests that update docker code labels Sep 29, 2026
@dependabot
dependabot Bot requested a review from koydas as a code owner September 29, 2026 23:34
@dependabot dependabot Bot added dependencies Pull requests that update a dependency file docker Pull requests that update docker code labels Sep 29, 2026
Bumps postgres from 16 to 18.

---
updated-dependencies:
- dependency-name: postgres
  dependency-version: '18'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
@dependabot
dependabot Bot force-pushed the dependabot/docker/databases/postgre/postgres-18 branch from eff7bd5 to 9814051 Compare October 1, 2026 15:17
claude added 2 commits October 1, 2026 15:44
PostgreSQL 18 cannot open a 16 data directory, and its image refuses a
mount at /var/lib/postgresql/data (data now lives in
/var/lib/postgresql/<major>/docker).

- Mount /var/lib/postgresql on a new postgres18-data volume (compose,
  local runner); the 16 volume is left untouched.
- databases/postgre/upgrade-major.sh: pg_dumpall with the old image,
  restore into the new volume with the new image; source is read only.
- db-upgrade harness: per-image PostgreSQL mount, and a migration path
  (DB_UPGRADE_MIGRATE_SCRIPT, exit 6) used by CI for postgres majors.
- ADR-005, postgres README and RUNBOOK document the procedure.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AjJSKb3q2o1MHd4gRs98tL
@koydas koydas changed the title chore(deps): bump postgres from 16 to 18 in /databases/postgre feat(postgres): upgrade to PostgreSQL 18 with data migration Oct 1, 2026

@koydas koydas left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All checks green on cbdd907. postgres (databases/postgre) ran the migration path: base image (16) seeded, upgrade-major.sh dump/restore, probe read back on 18. The 16 → 17 self-test still exits 4, and smoke passes on the new /var/lib/postgresql mount. Local validation is in the PR description.


Generated by Claude Code

@koydas
koydas merged commit eed666e into main Oct 1, 2026
8 checks passed
@dependabot
dependabot Bot deleted the dependabot/docker/databases/postgre/postgres-18 branch October 1, 2026 15:58
koydas pushed a commit that referenced this pull request Oct 1, 2026
- .NET 8 -> .NET 10 (#202), 4 -> 5 ADRs (ADR-005).
- DB upgrade row: PostgreSQL majors go through the tested dump/restore
  migration (#194); the 16 -> 17 self-test is same-volume.
- Migrations row: they are applied on service startup, so state
  "versioned, never ORM auto-create" instead of "never done at runtime".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AjJSKb3q2o1MHd4gRs98tL
koydas added a commit that referenced this pull request Oct 1, 2026
…ting at nonexistent paths (#204)

* docs: lead README with the CI guarantees, not the CRUD

Add a tagline and a guarantees table: DB image upgrade tests against
existing volumes (with a self-test that must fail), runtime consistency
between CI and Dockerfiles, versioned migrations per stack, full-stack
smoke + Playwright E2E, fail-fast secrets, hardened agent endpoint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ywYTqfmdv1DbzxFBmwvUE

* fix(gitops): remove Applications pointing at nonexistent paths

client-application.yaml targeted services/client/.devops and
server-application.yaml targeted services/server/.devops; neither exists.
Drop both and their references in README, RUNBOOK and services/README,
including the claim of an Ingress that has no manifest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ywYTqfmdv1DbzxFBmwvUE

* docs(readme): align guarantees table with current main

- .NET 8 -> .NET 10 (#202), 4 -> 5 ADRs (ADR-005).
- DB upgrade row: PostgreSQL majors go through the tested dump/restore
  migration (#194); the 16 -> 17 self-test is same-volume.
- Migrations row: they are applied on service startup, so state
  "versioned, never ORM auto-create" instead of "never done at runtime".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AjJSKb3q2o1MHd4gRs98tL

---------

Co-authored-by: Claude <noreply@anthropic.com>
koydas added a commit that referenced this pull request Oct 2, 2026
…tabase images (#208)

* docs: lead README with the CI guarantees, not the CRUD

Add a tagline and a guarantees table: DB image upgrade tests against
existing volumes (with a self-test that must fail), runtime consistency
between CI and Dockerfiles, versioned migrations per stack, full-stack
smoke + Playwright E2E, fail-fast secrets, hardened agent endpoint.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ywYTqfmdv1DbzxFBmwvUE

* fix(gitops): remove Applications pointing at nonexistent paths

client-application.yaml targeted services/client/.devops and
server-application.yaml targeted services/server/.devops; neither exists.
Drop both and their references in README, RUNBOOK and services/README,
including the claim of an Ingress that has no manifest.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ywYTqfmdv1DbzxFBmwvUE

* docs(readme): align guarantees table with current main

- .NET 8 -> .NET 10 (#202), 4 -> 5 ADRs (ADR-005).
- DB upgrade row: PostgreSQL majors go through the tested dump/restore
  migration (#194); the 16 -> 17 self-test is same-volume.
- Migrations row: they are applied on service startup, so state
  "versioned, never ORM auto-create" instead of "never done at runtime".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AjJSKb3q2o1MHd4gRs98tL

* docs: lead README with the Postgres 16 to 18 upgrade that CI caught

Address the #204 review findings that landed after merge:
- first screen: problem-first hook, the Dependabot postgres 16 -> 18 story
  with its red and green runs, a Mermaid of the probe flow, a two-command
  try-it, and 3 badges instead of 7
- scope the upgrade guarantee to bumps made through a PR and name the
  floating mongo:8 / mssql 2025-latest tags
- prerequisites: Node.js 26, the version the Dockerfiles ship

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ywYTqfmdv1DbzxFBmwvUE

* chore(databases): pin every database image to the version it runs today

mongo:8 -> 8.3.11, postgres:18 -> 18.6 (both the exact versions those
tags resolve to now) and mssql/server:2025-latest pinned by digest
(2025-CU9-ubuntu-24.04). Floating tags let an upstream image change
ship with no PR, so the db-upgrade harness never ran on it; with pins,
Dependabot proposes the change (tag or digest) and the harness tests it.
The README guarantee no longer needs the 'through a PR' qualifier.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ywYTqfmdv1DbzxFBmwvUE

---------

Co-authored-by: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

dependencies Pull requests that update a dependency file docker Pull requests that update docker code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEATURE] - Migrate PostgreSQL 16 to 18 with a data migration path

2 participants