Skip to content

Commit 8ebbbb5

Browse files
committed
fix checking inconsistence
1 parent 01d301b commit 8ebbbb5

File tree

2 files changed

+33
-9
lines changed

2 files changed

+33
-9
lines changed

src/spec-node/imageMetadata.ts

Lines changed: 31 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*--------------------------------------------------------------------------------------------*/
55

6-
import { PlatformInfo } from '../spec-common/commonUtils';
6+
import { GoARCH, GoOS, PlatformInfo } from '../spec-common/commonUtils';
77
import { ContainerError } from '../spec-common/errors';
88
import { LifecycleCommand, LifecycleHooksInstallMap } from '../spec-common/injectHeadless';
99
import { DevContainerConfig, DevContainerConfigCommand, DevContainerFromDockerComposeConfig, DevContainerFromDockerfileConfig, DevContainerFromImageConfig, getDockerComposeFilePaths, getDockerfilePath, HostGPURequirements, HostRequirements, isDockerFileConfig, PortAttributes, UserEnvProbe } from '../spec-configuration/configuration';
@@ -395,21 +395,45 @@ export async function getImageBuildInfoFromImage(params: DockerResolverParameter
395395
export async function getImageBuildInfoFromDockerfile(params: DockerResolverParameters | DockerCLIParameters, dockerfile: string, dockerBuildArgs: Record<string, string>, targetStage: string | undefined, substitute: SubstituteConfig) {
396396
const { output } = 'output' in params ? params : params.common;
397397
const omitSyntaxDirective = 'common' in params ? !!params.common.omitSyntaxDirective : false;
398-
return internalGetImageBuildInfoFromDockerfile(imageName => inspectDockerImage(params, imageName, true), dockerfile, dockerBuildArgs, targetStage, substitute, output, omitSyntaxDirective, params.platformInfo);
398+
const buildxPlatform = 'common' in params ? params.common.buildxPlatform : undefined;
399+
const buildxPlatforms = buildxPlatform?.split(',').map(platform => {
400+
const slash1 = platform.indexOf('/');
401+
const slash2 = platform.indexOf('/', slash1 + 1);
402+
// `--platform linux/amd64/v3` `--platform linux/arm64/v8`
403+
if (slash2 !== -1) {
404+
return {
405+
os: <GoOS>platform.slice(0, slash1),
406+
arch: <GoARCH>platform.slice(slash1 + 1, slash2),
407+
variant: platform.slice(slash2 + 1),
408+
};
409+
}
410+
// `--platform linux/amd64` and `--platform linux/arm64`
411+
return {
412+
os: <GoOS>platform.slice(0, slash1),
413+
arch: <GoARCH>platform.slice(slash1 + 1),
414+
};
415+
}) ?? [] satisfies PlatformInfo[];
416+
return internalGetImageBuildInfoFromDockerfile(imageName => inspectDockerImage(params, imageName, true), dockerfile, dockerBuildArgs, targetStage, substitute, output, omitSyntaxDirective, params.platformInfo, buildxPlatforms);
399417
}
400418

401-
export async function internalGetImageBuildInfoFromDockerfile(inspectDockerImage: (imageName: string) => Promise<ImageDetails>, dockerfileText: string, dockerBuildArgs: Record<string, string>, targetStage: string | undefined, substitute: SubstituteConfig, output: Log, omitSyntaxDirective: boolean, platformInfo: PlatformInfo): Promise<ImageBuildInfo> {
419+
export async function internalGetImageBuildInfoFromDockerfile(inspectDockerImage: (imageName: string) => Promise<ImageDetails>, dockerfileText: string, dockerBuildArgs: Record<string, string>, targetStage: string | undefined, substitute: SubstituteConfig, output: Log, omitSyntaxDirective: boolean, platformInfo: PlatformInfo, buildxPlatforms: PlatformInfo[]): Promise<ImageBuildInfo> {
402420
const dockerfile = extractDockerfile(dockerfileText);
403421
if (dockerfile.preamble.directives.syntax && omitSyntaxDirective) {
404422
output.write(`Omitting syntax directive '${dockerfile.preamble.directives.syntax}' from Dockerfile.`, LogLevel.Trace);
405423
delete dockerfile.preamble.directives.syntax;
406424
}
407-
const baseImage = findBaseImage(dockerfile, dockerBuildArgs, targetStage, platformInfo);
408-
const dummyBaseImage = findBaseImage(dockerfile, dockerBuildArgs, targetStage, { os: 'unknown', arch: 'unknown' });
409-
if (baseImage !== dummyBaseImage) {
425+
const images: string[] = [];
426+
for (const platform of buildxPlatforms) {
427+
const image = findBaseImage(dockerfile, dockerBuildArgs, targetStage, platform);
428+
if (image) {
429+
images.push(image);
430+
}
431+
}
432+
if (images.length !== 0 && !images.every(image => image === images[0])) {
410433
throw new Error(`Inconsistent base image used for multi-platform builds. Please check your Dockerfile.`);
411434
}
412-
const imageDetails = baseImage && await inspectDockerImage(baseImage) || undefined;
435+
const image = findBaseImage(dockerfile, dockerBuildArgs, targetStage, platformInfo);
436+
const imageDetails = image && await inspectDockerImage(image) || undefined;
413437
const dockerfileUser = findUserStatement(dockerfile, dockerBuildArgs, envListToObj(imageDetails?.Config.Env), targetStage);
414438
const user = dockerfileUser || imageDetails?.Config.User || 'root';
415439
const metadata = imageDetails ? getImageMetadata(imageDetails, substitute, output) : { config: [], raw: [], substitute };

src/test/dockerfileUtils.test.ts

Lines changed: 2 additions & 2 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, { os: 'linux', arch: 'amd64' });
181+
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, { 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, { os: 'linux', arch: 'amd64' });
209+
}, dockerfile, {}, undefined, testSubstitute, nullLog, false, { 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);

0 commit comments

Comments
 (0)