Skip to content

Pin the base image, publish to GHCR, and watch it with Dependabot - #1

Merged
alandotcom merged 2 commits into
mainfrom
add-ci-and-dependabot
Aug 6, 2026
Merged

Pin the base image, publish to GHCR, and watch it with Dependabot#1
alandotcom merged 2 commits into
mainfrom
add-ci-and-dependabot

Conversation

@alandotcom

Copy link
Copy Markdown
Contributor

Context

This repo builds Railway's Postgres image with pg_cron added. pg_cron runs the Inngest
run/trace retention job (ops/inngest-prune.sql in the monorepo), which is the only thing
bounding those trace stores.

Only staging consumes this repo today, and it does so by building from source. Dev and prod
still run the stock ghcr.io/railwayapp-templates/postgres-ssl:17.

Problem / What's broken

Two issues, found on 2026-08-06.

Dev and prod are one container replacement away from a database that will not boot.
pg_cron was apt-installed inside their running containers, on 2026-06-08 and 2026-06-19
respectively, confirmed by dpkg mtimes sitting long after the base image packages. That
splits the install across two lifetimes: shared_preload_libraries = pg_stat_statements,pg_cron
lives in postgresql.conf inside PGDATA on the volume, while pg_cron.so lives only in the
container filesystem. Any redeploy, image change, or platform restart gives a container
without the library while the config still demands it, and Postgres refuses to start with
FATAL: could not access file "pg_cron".

Consuming this repo as a repo build costs database recognition. Staging builds from
source, and Railway no longer treats it as a database: no Data tab, and railway connect
answers No supported database found in service. Dev and prod are image-sourced and keep it.

The base tag was also pinned to 17.6 while prod runs 17.10. Pointing a 17.10 data
directory at a 17.6 binary is a minor-version downgrade, which PostgreSQL does not guarantee.

What this PR changes

  • Dockerfile-17: base bumped 17.6 -> 17.10, matching what prod runs. Header explains
    why the extension is baked in and the two rules for merging a Dependabot bump.
  • .github/workflows/build.yml: builds and pushes ghcr.io/fountain-bio/postgres:17 plus
    a 17-<sha> tag for rollback. Pull requests build without publishing. A final step asserts
    pg_cron.so and pg_cron.control exist in the built image, so a base image that drops or
    renames the package fails the build rather than a database.
  • .github/dependabot.yml: weekly docker and github-actions updates. Dependabot's
    docker fetcher matches any filename containing "dockerfile" (DOCKER_REGEXP in
    dependabot-core), so Dockerfile-17 is covered without a rename.

Why we're making this change

Baking pg_cron into a published image makes container replacement survivable, and consuming
it as a Source Image rather than a repo build keeps Railway's database features. Pinning
the base gives Dependabot something to bump, so Postgres minor releases arrive as reviewable
PRs instead of drifting silently under a floating tag.

How to test

Verified locally before opening this:

  • docker build --platform linux/amd64 -f Dockerfile-17 . succeeds on the pinned base.
  • The built image reports postgres (PostgreSQL) 17.10 (Debian 17.10-1.pgdg13+1), an exact
    match for prod's running version.
  • /usr/lib/postgresql/17/lib/pg_cron.so and /usr/share/postgresql/17/extension/pg_cron.control
    are both present.
  • Both YAML files parse.

After merge, CI publishes the image. Then per service, change Source Image and leave the
source type as image:

  1. Dev first, to ghcr.io/fountain-bio/postgres:17. Confirm the Data tab opens, railway connect
    works, and Postgres starts with shared_preload_libraries intact.
  2. Staging, which also moves it off the repo build and should restore its database recognition.
  3. Prod last.

The GHCR package has to be pullable by Railway. Make it public, or add registry credentials on
each service.

Rollout / Risk notes

  • Merging publishes an image. It deploys nothing. Each Railway service moves when its Source
    Image is changed.
  • Do not redeploy dev or prod on the stock image before this lands. That is the exact event
    that loses pg_cron.so and stops Postgres from starting. Moving to this image is what makes
    redeploys safe again.
  • Switching Source Image replaces the container, which is why prod goes last, after dev has
    proven the swap keeps database recognition.
  • A Dependabot base bump is a Postgres minor upgrade. Never merge one that moves below the
    minor version a live data directory runs.

🤖 Generated with Claude Code

https://claude.ai/code/session_014TnDappY3DcbhiFS1BgKGW

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014TnDappY3DcbhiFS1BgKGW
@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014TnDappY3DcbhiFS1BgKGW
@alandotcom
alandotcom merged commit bcaef74 into main Aug 6, 2026
1 check 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.

1 participant