Skip to content

feat(postgres): bundle top-10 extensions in the appwrite/postgres image#2

Open
abnegate wants to merge 2 commits into
mainfrom
feat/dat-1666-postgres-extensions-image
Open

feat(postgres): bundle top-10 extensions in the appwrite/postgres image#2
abnegate wants to merge 2 commits into
mainfrom
feat/dat-1666-postgres-extensions-image

Conversation

@abnegate

@abnegate abnegate commented Jul 1, 2026

Copy link
Copy Markdown
Member

Implements DAT-1666. Bundles the ten most-used PostgreSQL extensions into the appwrite/postgres image so they are available out of the box for dedicated Postgres databases (and the VectorsDB product), built for every major version Cloud advertises.

What changed

  • Dockerfile: parameterised by PG_MAJOR (default 18). Installs pgvector, postgis (+ scripts), and pg_cron from PGDG. The other seven extensions already ship compiled in the base postgres image, so no extra package is needed for them. Sets shared_preload_libraries in the cluster config template.
  • .github/workflows/build.yml (new): builds both majors on every PR and push to main, then boots each image and runs tests/verify.sh. This gives the repo real PR CI (previously it only built on tag push).
  • .github/workflows/publish.yml: now a PG_MAJOR matrix (17, 18) producing per-major tags.
  • tests/verify.sh (new): boots the image and asserts every extension is available, installs via CREATE EXTENSION, and that both preload extensions actually load.
  • docker-compose.yml: forwards the PG_MAJOR build arg.
  • README.md (new): documents extensions, preload config, and the tag scheme.

The 10 extensions

Extension CREATE EXTENSION Preload
pgvector vector No
pg_stat_statements pg_stat_statements Yes
uuid-ossp uuid-ossp No
pgcrypto pgcrypto No
pg_trgm pg_trgm No
PostGIS postgis No
citext citext No
unaccent unaccent No
hstore hstore No
pg_cron pg_cron Yes

Preload config

pg_stat_statements and pg_cron require shared_preload_libraries, which must be set before the server starts (a runtime CREATE EXTENSION alone will not load them). The image appends this to postgresql.conf.sample, so it applies to every cluster initdb creates with no runtime configuration from edge:

shared_preload_libraries = 'pg_stat_statements,pg_cron'

Tags produced

Publishing a release tag (e.g. 0.2.0) produces, per major:

  • appwrite/postgres:18, appwrite/postgres:17 — floating per-major tag (what the edge wiring in DAT-1667 will select via version)
  • appwrite/postgres:18-0.2.0, appwrite/postgres:17-0.2.0 — immutable major + release
  • appwrite/postgres:0.2.0, appwrite/postgres:latest — default major (18), preserving the current single-tag mapping edge uses today (_APP_DATABASE_POSTGRES_IMAGE_VERSION) so nothing breaks before DAT-1667 lands

Verification

Built and booted both PG 17 and PG 18 locally (native arm64) via the committed tests/verify.sh. All checks passed for both:

  • all 10 extensions present in pg_available_extensions
  • CREATE EXTENSION IF NOT EXISTS succeeds for all 10
  • SHOW shared_preload_libraries = pg_stat_statements,pg_cron
  • pg_stat_statements view queryable and cron.schedule(...) returns a job id (both preload extensions actually loaded)
  • vector distance operator and postgis_version() (3.6) work

Server versions: PG 18.4, PG 17.10. hadolint and shellcheck clean. The CI workflow runs this same verification (linux/amd64) on the PR.

Follow-up

Does not merge. This image unblocks DAT-1667 (wire the custom appwrite/postgres image into edge for all Postgres dedicated DBs, selecting the per-major tag by version) and DAT-1668 (blue-green image-version bumps).

🤖 Generated with Claude Code

Dedicated Postgres databases (and VectorsDB) need the most-used extensions
available out of the box. Compile pgvector, PostGIS, and pg_cron into the
image (the seven contrib extensions already ship in the base image) and set
shared_preload_libraries = 'pg_stat_statements,pg_cron' in the cluster config
template, since preload libraries must be set before the server starts and
edge sets no Postgres config at runtime.

Build for every major version Cloud advertises (Postgres 17 and 18) via a
PG_MAJOR build arg and a CI matrix, tagging per major so the version -> image
mapping keeps working. A build-and-verify workflow boots each image on PRs and
asserts all ten extensions are available, install via CREATE EXTENSION, and
that the two preload extensions actually load.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings July 1, 2026 13:23

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Pull request overview

This PR enhances the appwrite/postgres Docker image so it ships with (and verifies) a curated set of commonly used PostgreSQL extensions across supported major versions (17 and 18), and adds CI to build/test the image on PRs.

Changes:

  • Parameterize the Docker build by PG_MAJOR and install pgvector, PostGIS, and pg_cron packages for that major.
  • Add CI workflow to build (PG 17/18) and run a container-based verification script on PRs/pushes.
  • Update publishing workflow to push per-major tags and add user-facing documentation for the image and tags.

Reviewed changes

Copilot reviewed 6 out of 6 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
Dockerfile Adds PG_MAJOR build arg and installs required extension packages; appends preload config to the sample config template.
tests/verify.sh New runtime verification that extensions are available/installable and preload libraries are active.
.github/workflows/build.yml New PR/push CI to build images for PG 17/18 and run tests/verify.sh.
.github/workflows/publish.yml Publishes multi-arch images with a PG-major matrix and per-major tag scheme.
docker-compose.yml Forwards PG_MAJOR into the image build for local use.
README.md Documents bundled extensions, preload behavior, and tagging scheme.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/verify.sh
Comment on lines +90 to +94
jobid="$(psql "SELECT cron.schedule('verify-job','* * * * *','SELECT 1');")"
if [[ "$jobid" =~ ^[0-9]+$ ]]; then
echo "PASS: pg_cron.schedule returned job $jobid"
psql "SELECT cron.unschedule('verify-job');" >/dev/null
else
Comment thread .github/workflows/publish.yml Outdated
@greptile-apps

greptile-apps Bot commented Jul 1, 2026

Copy link
Copy Markdown

Greptile Summary

This PR bundles the ten most-used PostgreSQL extensions (pgvector, PostGIS, pg_cron, pg_stat_statements, and six contrib modules) into the appwrite/postgres image, parametrising the Dockerfile by PG_MAJOR and producing a per-major tag matrix for both PG 17 and PG 18.

  • Dockerfile is parametrised by PG_MAJOR (default 18); installs pgvector, postgis, postgis-scripts, and pg_cron from PGDG, and appends shared_preload_libraries = 'pg_stat_statements,pg_cron' to the cluster config template so the preloaded modules are active on every initdb-created cluster.
  • build.yml (new) adds real PR CI: matrix builds for PG 17 and 18, GHA layer cache per major, and an end-to-end run of tests/verify.sh.
  • publish.yml expands to a PG_MAJOR matrix generating per-major floating tags (17, 18), immutable release tags (17-0.2.0, 18-0.2.0), and bare semver/latest gated to the default major (18) for backward compatibility.

Confidence Score: 5/5

Safe to merge — the Dockerfile changes are straightforward package installations and a single config-file append, and the tag matrix logic in the publish workflow is correct and backward-compatible.

All core changes — Dockerfile parametrisation, extension installation, preload config, CI workflow, and tag matrix — are well-structured and the author verified both majors locally and in CI. The two findings are non-blocking quality suggestions.

.github/workflows/publish.yml for the missing layer cache; .github/workflows/build.yml for the arm64 testing gap relative to what publish produces.

Important Files Changed

Filename Overview
Dockerfile Correctly parameterises PG_MAJOR (default 18), installs pgvector/postgis/postgis-scripts/pg_cron from PGDG, and appends shared_preload_libraries to the cluster config template.
.github/workflows/build.yml New CI workflow; builds both PG majors on PR and main push, runs verify.sh, and correctly configures per-scope GHA layer cache. Only linux/amd64 is tested while publish builds arm64 as well.
.github/workflows/publish.yml Adds PG_MAJOR matrix producing per-major floating tags, immutable release tags, and bare semver/latest gated to the default major. Tag logic is correct; missing Docker layer cache on multi-platform publish builds.
tests/verify.sh Comprehensive end-to-end verification covering availability, CREATE EXTENSION, and usability probes. CREATE EXTENSION result is matched against the exact command tag so a dead container is correctly detected as a failure.
docker-compose.yml Trivial update forwarding PG_MAJOR build arg with a default of 18 for local dev use.
README.md New documentation file accurately describing all 10 bundled extensions, preload config, tag scheme, and verification steps.

Reviews (2): Last reviewed commit: "test(postgres): harden verify.sh and dro..." | Re-trigger Greptile

Comment thread tests/verify.sh
Comment thread tests/verify.sh Outdated
Comment thread .github/workflows/build.yml
Address review feedback on the verification script and workflows:

- CREATE EXTENSION now asserts the exact "CREATE EXTENSION" success string,
  so empty output from a crashed container no longer counts as success.
- Unschedule the pg_cron job by its numeric id rather than name, and report
  <no output> on empty results consistently.
- Assert on postgis_version() like the other runtime usability checks instead
  of only printing it.
- Remove the unused VERSION build-arg from publish.yml (the Dockerfile never
  declared ARG VERSION).
- Cache the apt layer across build-verify runs with the GitHub Actions cache.

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

Labels

None yet

2 participants