Skip to content

Commit 5fc70f4

Browse files
inistorclaude
andcommitted
fix(pullImage): force pull when platform is requested
Cubic flagged on PR #1856 that the `image inspect` cache-check inside pullImage is platform-agnostic — a different-arch variant of the same image name will satisfy it, so the requested platform silently diverges from what's actually on disk. Fix: short-circuit the cache check when `imagePlatform` is set and always invoke the explicit pull (which then carries `--platform` to docker). Pulls are idempotent: if the requested variant is already local, `docker pull` returns "Image is up to date" quickly. Tightens the integration test by dropping `pullPolicy: "always"` — the new short-circuit is now the path under test. Identified by cubic. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 68f7a62 commit 5fc70f4

2 files changed

Lines changed: 14 additions & 2 deletions

File tree

src/job.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1265,6 +1265,16 @@ If you know what you're doing and would like to suppress this warning, use one o
12651265
await actualPull();
12661266
return;
12671267
}
1268+
// The `image inspect` cache check is platform-agnostic — a different-arch
1269+
// variant of the same image name will satisfy it, causing the requested
1270+
// platform to silently differ from what's actually on disk. Force a pull
1271+
// when a specific platform was requested so the matching manifest is
1272+
// guaranteed locally. Pulls are idempotent: if the variant is already
1273+
// cached, `docker pull` short-circuits with "Image is up to date".
1274+
if (imagePlatform) {
1275+
await actualPull();
1276+
return;
1277+
}
12681278
try {
12691279
await Utils.spawn([this.argv.containerExecutable, "image", "inspect", imageToPull]);
12701280
} catch {

tests/test-cases/image/integration.test.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -132,15 +132,17 @@ test.concurrent("image <image-platform>", async () => {
132132
const writeStreams = new WriteStreamsMock();
133133

134134
await handler({
135-
pullPolicy: "always",
136135
cwd: "tests/test-cases/image",
137136
job: ["image-platform"],
138137
stateDir: ".gitlab-ci-local-image-platform",
139138
}, writeStreams);
140139

141140
// The "pulled" log line includes the requested platform, proving --platform
142141
// was forwarded to `docker pull` rather than silently dropped. Use `.*` to
143-
// span the chalk ANSI escape codes between tokens.
142+
// span the chalk ANSI escape codes between tokens. We deliberately don't
143+
// pass `pullPolicy: "always"` — the platform-aware short-circuit inside
144+
// pullImage forces a pull whenever a platform is set, regardless of whether
145+
// a different-arch variant of the same image happens to be cached locally.
144146
expect(writeStreams.stdoutLines.join("\n")).toMatch(/pulled.*alpine.*linux\/amd64/);
145147

146148
// The job runs successfully on the host (linux/amd64 matches the CI runner arch).

0 commit comments

Comments
 (0)