Skip to content

Commit de5f84d

Browse files
committed
use separate arguments for baseImageEnv and globalBuildxPlatformArgs
1 parent ff3f044 commit de5f84d

3 files changed

Lines changed: 28 additions & 33 deletions

File tree

src/spec-node/dockerfileUtils.ts

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,7 @@ export function extractDockerfile(dockerfile: string): Dockerfile {
8181
} as Dockerfile;
8282
}
8383

84-
export function findUserStatement(dockerfile: Dockerfile, buildArgs: Record<string, string>, baseImageEnv: Record<string, string>, target: string | undefined) {
84+
export function findUserStatement(dockerfile: Dockerfile, buildArgs: Record<string, string>, baseImageEnv: Record<string, string>, globalBuildxPlatformArgs: Record<string, string> = {}, target: string | undefined) {
8585
let stage: Stage | undefined = target ? dockerfile.stagesByLabel[target] : dockerfile.stages[dockerfile.stages.length - 1];
8686
const seen = new Set<Stage>();
8787
while (stage) {
@@ -92,9 +92,9 @@ export function findUserStatement(dockerfile: Dockerfile, buildArgs: Record<stri
9292

9393
const i = findLastIndex(stage.instructions, i => i.instruction === 'USER');
9494
if (i !== -1) {
95-
return replaceVariables(dockerfile, buildArgs, baseImageEnv, stage.instructions[i].name, stage, i) || undefined;
95+
return replaceVariables(dockerfile, buildArgs, baseImageEnv, globalBuildxPlatformArgs, stage.instructions[i].name, stage, i) || undefined;
9696
}
97-
const image = replaceVariables(dockerfile, buildArgs, baseImageEnv, stage.from.image, dockerfile.preamble, dockerfile.preamble.instructions.length);
97+
const image = replaceVariables(dockerfile, buildArgs, baseImageEnv, globalBuildxPlatformArgs, stage.from.image, dockerfile.preamble, dockerfile.preamble.instructions.length);
9898
stage = dockerfile.stagesByLabel[image];
9999
}
100100
return undefined;
@@ -109,7 +109,7 @@ export function findBaseImage(dockerfile: Dockerfile, buildArgs: Record<string,
109109
}
110110
seen.add(stage);
111111

112-
const image = replaceVariables(dockerfile, buildArgs, globalBuildxPlatformArgs, stage.from.image, dockerfile.preamble, dockerfile.preamble.instructions.length);
112+
const image = replaceVariables(dockerfile, buildArgs, /* not available in FROM instruction */ {}, globalBuildxPlatformArgs, stage.from.image, dockerfile.preamble, dockerfile.preamble.instructions.length);
113113
const nextStage = dockerfile.stagesByLabel[image];
114114
if (!nextStage) {
115115
return image;
@@ -155,12 +155,12 @@ function getExpressionValue(option: string, isSet: boolean, word: string, value:
155155
return operations[option](isSet, word, value).replace(/^['"]|['"]$/g, ''); // remove quotes from start and end of the string
156156
}
157157

158-
function replaceVariables(dockerfile: Dockerfile, buildArgs: Record<string, string>, baseImageEnv: Record<string, string>, str: string, stage: { from?: From; instructions: Instruction[] }, beforeInstructionIndex: number) {
158+
function replaceVariables(dockerfile: Dockerfile, buildArgs: Record<string, string>, baseImageEnv: Record<string, string>, globalBuildxPlatformArgs: Record<string, string> = {}, str: string, stage: { from?: From; instructions: Instruction[] }, beforeInstructionIndex: number) {
159159
return [...str.matchAll(argumentExpression)]
160160
.map(match => {
161161
const variable = match.groups!.variable;
162162
const isVarExp = match.groups!.isVarExp ? true : false;
163-
let value = findValue(dockerfile, buildArgs, baseImageEnv, variable, stage, beforeInstructionIndex) || '';
163+
let value = findValue(dockerfile, buildArgs, baseImageEnv, globalBuildxPlatformArgs, variable, stage, beforeInstructionIndex) || '';
164164
if (isVarExp) {
165165
// Handle replacing variable expressions (${var:+word}) if they exist
166166
const option = match.groups!.option;
@@ -178,7 +178,7 @@ function replaceVariables(dockerfile: Dockerfile, buildArgs: Record<string, stri
178178
.reduce((str, { begin, end, value }) => str.substring(0, begin) + value + str.substring(end), str);
179179
}
180180

181-
function findValue(dockerfile: Dockerfile, buildArgs: Record<string, string>, baseImageEnv: Record<string, string>, variable: string, stage: { from?: From; instructions: Instruction[] }, beforeInstructionIndex: number): string | undefined {
181+
function findValue(dockerfile: Dockerfile, buildArgs: Record<string, string>, baseImageEnv: Record<string, string>, globalBuildxPlatformArgs: Record<string, string> = {}, variable: string, stage: { from?: From; instructions: Instruction[] }, beforeInstructionIndex: number): string | undefined {
182182
let considerArg = true;
183183
const seen = new Set<typeof stage>();
184184
while (true) {
@@ -191,22 +191,22 @@ function findValue(dockerfile: Dockerfile, buildArgs: Record<string, string>, ba
191191
if (i !== -1) {
192192
const instruction = stage.instructions[i];
193193
if (instruction.instruction === 'ENV') {
194-
return replaceVariables(dockerfile, buildArgs, baseImageEnv, instruction.value!, stage, i);
194+
return replaceVariables(dockerfile, buildArgs, baseImageEnv, globalBuildxPlatformArgs, instruction.value!, stage, i);
195195
}
196196
if (instruction.instruction === 'ARG') {
197-
return replaceVariables(dockerfile, buildArgs, baseImageEnv, buildArgs[instruction.name] ?? instruction.value, stage, i);
197+
return replaceVariables(dockerfile, buildArgs, baseImageEnv, globalBuildxPlatformArgs, buildArgs[instruction.name] ?? instruction.value, stage, i);
198198
}
199199
}
200200

201201
if (!stage.from) {
202-
const value = baseImageEnv[variable];
202+
const value = baseImageEnv[variable] ?? globalBuildxPlatformArgs[variable];
203203
if (typeof value === 'string') {
204204
return value;
205205
}
206206
return undefined;
207207
}
208208

209-
const image = replaceVariables(dockerfile, buildArgs, baseImageEnv, stage.from.image, dockerfile.preamble, dockerfile.preamble.instructions.length);
209+
const image = replaceVariables(dockerfile, buildArgs, baseImageEnv, globalBuildxPlatformArgs, stage.from.image, dockerfile.preamble, dockerfile.preamble.instructions.length);
210210
stage = dockerfile.stagesByLabel[image] || dockerfile.preamble;
211211
beforeInstructionIndex = stage.instructions.length;
212212
considerArg = stage === dockerfile.preamble;

src/spec-node/imageMetadata.ts

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -425,10 +425,7 @@ export async function internalGetImageBuildInfoFromDockerfile(inspectDockerImage
425425
};
426426
const baseImage = findBaseImage(dockerfile, dockerBuildArgs, targetStage, globalBuildxPlatformArgs);
427427
const imageDetails = baseImage && await inspectDockerImage(baseImage) || undefined;
428-
const dockerfileUser = findUserStatement(dockerfile, dockerBuildArgs, {
429-
...envListToObj(imageDetails?.Config.Env),
430-
...globalBuildxPlatformArgs,
431-
}, targetStage);
428+
const dockerfileUser = findUserStatement(dockerfile, dockerBuildArgs, envListToObj(imageDetails?.Config.Env), globalBuildxPlatformArgs, targetStage);
432429
const user = dockerfileUser || imageDetails?.Config.User || 'root';
433430
const metadata = imageDetails ? getImageMetadata(imageDetails, substitute, output) : { config: [], raw: [], substitute };
434431
return {

src/test/dockerfileUtils.test.ts

Lines changed: 16 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ FROM ubuntu:latest as dev
178178
const info = await internalGetImageBuildInfoFromDockerfile(async (imageName) => {
179179
assert.strictEqual(imageName, 'ubuntu:latest');
180180
return details;
181-
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, {} as any, {} as any);
181+
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, { os: 'linux', arch: 'arm64' }, { os: 'linux', arch: 'amd64' });
182182
assert.strictEqual(info.user, 'imageUser');
183183
assert.strictEqual(info.metadata.config.length, 1);
184184
assert.strictEqual(info.metadata.config[0].id, 'testid-substituted');
@@ -206,7 +206,7 @@ USER dockerfileUserB
206206
const info = await internalGetImageBuildInfoFromDockerfile(async (imageName) => {
207207
assert.strictEqual(imageName, 'ubuntu:latest');
208208
return details;
209-
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, {} as any, {} as any);
209+
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, { os: 'linux', arch: 'arm64' }, { os: 'linux', arch: 'amd64' });
210210
assert.strictEqual(info.user, 'dockerfileUserB');
211211
assert.strictEqual(info.metadata.config.length, 0);
212212
assert.strictEqual(info.metadata.raw.length, 0);
@@ -221,8 +221,6 @@ FROM ubuntu:latest as base-arm64
221221
USER arm64_user
222222
223223
FROM base-\${TARGETARCH}
224-
225-
ARG TARGETARCH
226224
`;
227225
const details: ImageDetails = {
228226
Id: '123',
@@ -239,7 +237,7 @@ ARG TARGETARCH
239237
const info = await internalGetImageBuildInfoFromDockerfile(async (imageName) => {
240238
assert.strictEqual(imageName, 'ubuntu:latest');
241239
return details;
242-
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, {} as any, { os: 'linux', arch: 'amd64' });
240+
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, { os: 'linux', arch: 'arm64' }, { os: 'linux', arch: 'amd64' });
243241
assert.strictEqual(info.user, 'amd64_user');
244242
assert.strictEqual(info.metadata.config.length, 0);
245243
assert.strictEqual(info.metadata.raw.length, 0);
@@ -424,7 +422,7 @@ describe('findUserStatement', () => {
424422
USER user1
425423
`;
426424
const extracted = extractDockerfile(dockerfile);
427-
const user = findUserStatement(extracted, {}, {}, undefined);
425+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
428426
assert.strictEqual(user, 'user1');
429427
});
430428

@@ -434,7 +432,7 @@ ARG IMAGE_USER=user2
434432
USER $IMAGE_USER
435433
`;
436434
const extracted = extractDockerfile(dockerfile);
437-
const user = findUserStatement(extracted, {}, {}, undefined);
435+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
438436
assert.strictEqual(user, 'user2');
439437
});
440438

@@ -446,7 +444,7 @@ USER $IMAGE_USER
446444
const extracted = extractDockerfile(dockerfile);
447445
const user = findUserStatement(extracted, {
448446
IMAGE_USER: 'user3'
449-
}, {}, undefined);
447+
}, {}, {}, undefined);
450448
assert.strictEqual(user, 'user3');
451449
});
452450

@@ -462,7 +460,7 @@ FROM image4 as stage4
462460
USER user4
463461
`;
464462
const extracted = extractDockerfile(dockerfile);
465-
const image = findUserStatement(extracted, {}, {}, 'stage2');
463+
const image = findUserStatement(extracted, {}, {}, {}, 'stage2');
466464
assert.strictEqual(image, 'user3_2');
467465
});
468466

@@ -474,7 +472,7 @@ ARG USERNAME=user2
474472
USER \${USERNAME}
475473
`;
476474
const extracted = extractDockerfile(dockerfile);
477-
const user = findUserStatement(extracted, {}, {}, undefined);
475+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
478476
assert.strictEqual(user, 'user2');
479477
});
480478

@@ -488,7 +486,7 @@ FROM one as two
488486
USER \${USERNAME}
489487
`;
490488
const extracted = extractDockerfile(dockerfile);
491-
const user = findUserStatement(extracted, {}, {}, undefined);
489+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
492490
assert.strictEqual(user, 'user1');
493491
});
494492

@@ -499,7 +497,7 @@ FROM debian
499497
USER \${USERNAME}
500498
`;
501499
const extracted = extractDockerfile(dockerfile);
502-
const user = findUserStatement(extracted, {}, {}, undefined);
500+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
503501
assert.strictEqual(user, 'user1');
504502
});
505503

@@ -511,7 +509,7 @@ ARG USERNAME
511509
USER \${USERNAME}
512510
`;
513511
const extracted = extractDockerfile(dockerfile);
514-
const user = findUserStatement(extracted, {}, {}, undefined);
512+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
515513
assert.strictEqual(user, 'user1');
516514
});
517515

@@ -521,7 +519,7 @@ FROM debian
521519
USER \${USERNAME}
522520
`;
523521
const extracted = extractDockerfile(dockerfile);
524-
const user = findUserStatement(extracted, {}, {}, undefined);
522+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
525523
assert.strictEqual(user, undefined);
526524
});
527525

@@ -533,7 +531,7 @@ ENV USERNAME=user2
533531
USER \${USERNAME}
534532
`;
535533
const extracted = extractDockerfile(dockerfile);
536-
const user = findUserStatement(extracted, {}, {}, undefined);
534+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
537535
assert.strictEqual(user, 'user2');
538536
});
539537

@@ -545,7 +543,7 @@ ENV USERNAME2=\${USERNAME1}
545543
USER \${USERNAME2}
546544
`;
547545
const extracted = extractDockerfile(dockerfile);
548-
const user = findUserStatement(extracted, {}, {}, undefined);
546+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
549547
assert.strictEqual(user, 'user1');
550548
});
551549

@@ -557,7 +555,7 @@ ENV USERNAME2=user2
557555
USER A\${USERNAME1}A\${USERNAME2}A
558556
`;
559557
const extracted = extractDockerfile(dockerfile);
560-
const user = findUserStatement(extracted, {}, {}, undefined);
558+
const user = findUserStatement(extracted, {}, {}, {}, undefined);
561559
assert.strictEqual(user, 'Auser1Auser2A');
562560
});
563561

@@ -567,7 +565,7 @@ FROM mybase
567565
USER \${USERNAME}
568566
`;
569567
const extracted = extractDockerfile(dockerfile);
570-
const user = findUserStatement(extracted, {}, { USERNAME: 'user1' }, undefined);
568+
const user = findUserStatement(extracted, {}, { USERNAME: 'user1' }, {}, undefined);
571569
assert.strictEqual(user, 'user1');
572570
});
573571
});

0 commit comments

Comments
 (0)