build: copy pg_dump and pg_restore from the PostgreSQL image

postgresql-client-18 from the PGDG repository brought Perl and Debian's
client wrapper scripts into the runner for two binaries the app calls by
name. A pgclient stage on postgres:18.6-trixie, pinned by digest, now
hands over pg_dump, pg_restore and the libpq they link; the Debian
libraries libpq needs (Kerberos, LDAP, SASL) still come from apt so the
upgrade and the image scan see them. The runner registers libpq with the
loader and fails the build when either binary has an unresolved library;
the major 18 version checks stay.

The client minor follows the bundled database's: a guard holds the two
pins together, and the Dockerfile's Dependabot watch now ignores a
PostgreSQL major the same way the compose watch does.
This commit is contained in:
Marc-André Bombeck committed 2026-11-03 21:18:44 +01:00
1 parent d8743e9111
commit 377e0d0d3a
4 files changed
+82 -42

No files matched your search

@@ -61,12 +61,20 @@ describe("canvas binary hoist", () => {
expect(runner).not.toMatch(/@napi-rs\+canvas[^"'\s]*@\*/);
});
it("builds every stage on the glibc Debian base", () => {
it("builds every Node stage on the glibc Debian base", () => {
const froms = DOCKERFILE.match(/^FROM \S+/gm) ?? [];
expect(froms.length).toBeGreaterThanOrEqual(3);
for (const from of froms) {
const node = froms.filter((from) => from.startsWith("FROM node:"));
expect(node).toHaveLength(3);
for (const from of node) {
expect(from).toMatch(/^FROM node:22-trixie-slim@sha256:[0-9a-f]{64}$/);
}
// The only other stage supplies the PostgreSQL client tools, built on
// the same Debian release so its binaries find their libraries.
expect(froms.filter((from) => !from.startsWith("FROM node:"))).toEqual([
expect.stringMatching(
/^FROM postgres:18\.\d+-trixie@sha256:[0-9a-f]{64}$/,
),
]);
});
it("fails the build when the copied binary is another version", () => {
@@ -40,6 +40,32 @@ describe("the bundled database pin", () => {
}
});
it("ships pg_dump of the same minor the bundled database runs", () => {
const db = /^\s*image:\s*postgres:(\d+\.\d+)-alpine$/m.exec(
read("docker-compose.yml"),
);
const client =
/^FROM postgres:(\d+\.\d+)-trixie@sha256:[0-9a-f]{64} AS pgclient$/m.exec(
read("Dockerfile"),
);
expect(db, "the compose file pins the database").not.toBeNull();
expect(client, "the Dockerfile has a pinned pgclient stage").not.toBeNull();
// The two pins are one decision; a Dependabot PR moves them separately.
expect(client![1]).toBe(db![1]);
});
it("keeps a major bump of the client tools out of the Dockerfile watch too", () => {
const dependabot = read(".github/dependabot.yml");
const docker =
/package-ecosystem:\s*"docker"\n([\s\S]*?)(?=\n\s*- package-ecosystem:)/.exec(
dependabot,
);
expect(docker, "a docker ecosystem entry").not.toBeNull();
expect(docker![1]).toMatch(
/dependency-name:\s*"postgres"[\s\S]{0,200}version-update:semver-major/,
);
});
it("lets a major version through only as a decision, never as an update PR", () => {
const dependabot = read(".github/dependabot.yml");
// The first run of the compose ecosystem proposed 16.15 -> 18.6. A