Skip to content

Commit 9faa46f

Browse files
os-steveclaude
andcommitted
ci(docker): assert the SQL drivers are in the published runtime image
The smoke step proved the CLI resolved but nothing asserted that `pg` and `mysql2` -- which docker/Dockerfile installs and docker/README.md publishes as a maintained promise -- are actually in the built image. The in-repo `check:docs-image-tag` pin cannot see that: it compares the install line against the published table, and both would still agree if the drivers vanished from the image. The probe resolves from inside the global tree (`-w`), which is both how the real boot path resolves the drivers and the only spelling that discriminates: `npm install -g` writes to /usr/local/lib/node_modules, which is not on `require()`'s search path from the image's WORKDIR (/srv/app), and the node:22-slim base sets no NODE_PATH. Verified in both directions against purpose-built images before landing: green with the drivers present, red (`Cannot find module 'pg'`) without. Claude-Session: https://claude.ai/code/session_01PU9zBGbH2s2ZtxSyu963M3 Co-authored-by: Claude <noreply@anthropic.com>
1 parent c463d03 commit 9faa46f

1 file changed

Lines changed: 21 additions & 0 deletions

File tree

.github/workflows/docker-publish.yml

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,8 +97,29 @@ jobs:
9797
# `os --version` proves the CLI resolved, installed, and runs on the
9898
# pushed image; a boot test needs an artifact + DB and belongs to the
9999
# examples/e2e suites, not here.
100+
#
101+
# The `require()` line proves the SQL drivers are actually IN the built
102+
# image. `check:docs-image-tag` cannot see that: it compares the
103+
# Dockerfile install line against README.md's published table, and both
104+
# would still agree if the drivers vanished from the image. The class
105+
# has already cost a boot once -- docker/Dockerfile records that a tree
106+
# without `pg` "died at boot on `Cannot find module 'pg'`", which is why
107+
# the install line exists. `require()` needs no artifact and no
108+
# database, so it stays on the right side of the same line drawn above.
109+
#
110+
# `-w` is load-bearing, not incidental. `npm install -g` puts the
111+
# drivers in /usr/local/lib/node_modules, which is NOT on `require()`'s
112+
# search path from this image's WORKDIR (/srv/app): node's global
113+
# folders are $PREFIX/lib/node, and the node:22-slim base sets no
114+
# NODE_PATH. Run from /srv/app the probe fails on a CORRECT image, so
115+
# it would be a constant red rather than a check. Resolving from inside
116+
# the global tree is also how the real boot path resolves them --
117+
# driver-sql lives there too. Do not "simplify" this to a bare
118+
# `docker run`; verified in both directions before it landed.
100119
env:
101120
VERSION: ${{ steps.version.outputs.version }}
102121
run: |
103122
docker pull "$IMAGE:$VERSION"
104123
docker run --rm "$IMAGE:$VERSION" os --version
124+
docker run --rm -w /usr/local/lib/node_modules "$IMAGE:$VERSION" \
125+
node -e "require('pg'); require('mysql2')"

0 commit comments

Comments
 (0)