chore(deps): move the database pin to 16.15 and watch it

The bundled PostgreSQL was pinned to 16.14 while 16.15 had been out for
five weeks. The pin itself is deliberate, a database change should be
reviewable rather than whatever the registry serves on pull day, but
nothing watched it: Dependabot was configured with the docker ecosystem,
which reads the Dockerfile and never opens a compose file, so no update
PR was ever raised. CI and the integration suite meanwhile run against
the floating 16-alpine, so the shipped database was older than the
tested one.

Adds the docker-compose ecosystem so each PostgreSQL minor release
arrives as a reviewable PR, moves the pin to 16.15, and pins both halves
with a test that fails if the exact minor or the watch is dropped.
Refs #987
This commit is contained in:
Marc-André Bombeck committed 2026-09-16 12:19:09 +02:00
1 parent 0ec05c3c5a
commit 79c4c3631f
3 files changed
+68 -1

No files matched your search

@@ -0,0 +1,49 @@
import { readFileSync } from "node:fs";
import { resolve } from "node:path";
import { describe, expect, it } from "vitest";
/**
* The bundled database is pinned to an exact minor, AND something watches it.
*
* Both halves matter and only together. The pin exists so a database change is
* a deliberate, reviewable one rather than whatever the registry happens to
* serve on the day an operator pulls. But PostgreSQL ships security and
* data-corruption fixes in minor releases and recommends running the current
* one, so a pin nobody moves ships a knowingly outdated database: this line
* sat on 16.14 for five weeks after 16.15 was published, because the
* `docker` ecosystem Dependabot was configured with reads the Dockerfile and
* never looks at a compose file.
*
* So: drop the pin and the deliberate-update model goes; drop the watch and
* the pin ages in silence. This test fails on either.
*/
const ROOT = resolve(__dirname, "../..");
function read(relative: string): string {
return readFileSync(resolve(ROOT, relative), "utf8");
}
describe("the bundled database pin", () => {
it("names an exact minor version, not a floating major alias", () => {
const images = [
...read("docker-compose.yml").matchAll(/^\s*image:\s*(postgres:\S+)/gm),
].map((match) => match[1]);
expect(images.length).toBe(1);
// `postgres:16-alpine` or `postgres:16` would match a moving target.
expect(images[0]).toMatch(/^postgres:\d+\.\d+-alpine$/);
});
it("is watched by the compose ecosystem, which is not the Dockerfile one", () => {
const dependabot = read(".github/dependabot.yml");
const ecosystems = [
...dependabot.matchAll(/package-ecosystem:\s*"([^"]+)"/g),
].map((match) => match[1]);
expect(ecosystems).toContain("docker-compose");
// The Dockerfile watch is a separate entry and does not stand in for it.
expect(ecosystems).toContain("docker");
});
});