Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .devcontainer/devcontainer-lock.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,4 @@
"integrity": "sha256:ce078b7bf7d9ef3bcb9813b32103795d8d72172446890b64772cbe1dec6baafd"
}
}
}
}
8 changes: 5 additions & 3 deletions src/spec-configuration/containerFeaturesConfiguration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,12 +203,14 @@ export function getContainerFeaturesBaseDockerFile(contentSourceRootPath: string

#{nonBuildKitFeatureContentFallback}

FROM $_DEV_CONTAINERS_BASE_IMAGE AS dev_containers_feature_content_normalize
ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder

FROM \${_DEV_CONTAINERS_BASE_IMAGE:-scratch} AS dev_containers_feature_content_normalize
USER root
COPY --from=dev_containers_feature_content_source ${path.posix.join(contentSourceRootPath, 'devcontainer-features.builtin.env')} /tmp/build-features/
RUN chmod -R 0755 /tmp/build-features/

FROM $_DEV_CONTAINERS_BASE_IMAGE AS dev_containers_target_stage
FROM \${_DEV_CONTAINERS_BASE_IMAGE:-scratch} AS dev_containers_target_stage

USER root

Expand Down Expand Up @@ -1122,7 +1124,7 @@ export async function fetchContentsAtTarballUri(params: { output: Log; env: Node

// No 'metadataFile' to look for.
if (!metadataFile) {
await cleanupIterationFetchAndMerge(tempTarballPath, output);
await cleanupIterationFetchAndMerge(tempTarballPath, output);
return { computedDigest, metadata: undefined };
}

Expand Down
84 changes: 40 additions & 44 deletions src/spec-node/containerFeatures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,8 +174,7 @@ export function generateContainerEnvsV1(featuresConfig: FeaturesConfig) {
let result = '';
for (const fSet of featuresConfig.featureSets) {
// We only need to generate this ENV references for the initial features specification.
if (fSet.internalVersion !== '2')
{
if (fSet.internalVersion !== '2') {
result += '\n';
result += fSet.features
.filter(f => (includeAllConfiguredFeatures || f.included) && f.value)
Expand All @@ -197,23 +196,23 @@ export interface ImageBuildOptions {
}

async function getImageBuildOptions(params: DockerResolverParameters, config: SubstitutedConfig<DevContainerConfig>, dstFolder: string, baseName: string, imageBuildInfo: ImageBuildInfo): Promise<ImageBuildOptions> {
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
return {
dstFolder,
dockerfileContent: `
FROM $_DEV_CONTAINERS_BASE_IMAGE AS dev_containers_target_stage
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
return {
dstFolder,
dockerfileContent: `
FROM \${_DEV_CONTAINERS_BASE_IMAGE:-scratch} AS dev_containers_target_stage
${getDevcontainerMetadataLabel(getDevcontainerMetadata(imageBuildInfo.metadata, config, { featureSets: [] }, [], getOmitDevcontainerPropertyOverride(params.common)))}
`,
overrideTarget: 'dev_containers_target_stage',
dockerfilePrefixContent: `${syntax ? `# syntax=${syntax}` : ''}
ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder
overrideTarget: 'dev_containers_target_stage',
dockerfilePrefixContent: `${syntax ? `# syntax=${syntax}` : ''}
ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder
`,
buildArgs: {
_DEV_CONTAINERS_BASE_IMAGE: baseName,
} as Record<string, string>,
buildKitContexts: {} as Record<string, string>,
securityOpts: [],
};
buildArgs: {
_DEV_CONTAINERS_BASE_IMAGE: baseName,
} as Record<string, string>,
buildKitContexts: {} as Record<string, string>,
securityOpts: [],
};
}

function getOmitDevcontainerPropertyOverride(resolverParams: { omitConfigRemotEnvFromMetadata?: boolean }): (keyof DevContainerConfig & keyof ImageMetadataEntry)[] {
Expand Down Expand Up @@ -244,10 +243,10 @@ async function getFeaturesBuildOptions(params: DockerResolverParameters, devCont
const useBuildKitBuildContexts = buildKitVersionParsed ? !isEarlierVersion(buildKitVersionParsed, minRequiredVersion) : false;
const buildContentImageName = 'dev_container_feature_content_temp';
const disableSELinuxLabels = useBuildKitBuildContexts && await isUsingSELinuxLabels(params);
// Access Docker engine version
const dockerEngineVersionParsed = params.dockerEngineVersion?.versionMatch ? parseVersion(params.dockerEngineVersion.versionMatch) : undefined;
const minDockerEngineVersion = [23, 0, 0];
const skipDefaultSyntax = dockerEngineVersionParsed ? !isEarlierVersion(dockerEngineVersionParsed, minDockerEngineVersion) : false;
// Access Docker engine version
const dockerEngineVersionParsed = params.dockerEngineVersion?.versionMatch ? parseVersion(params.dockerEngineVersion.versionMatch) : undefined;
const minDockerEngineVersion = [23, 0, 0];
const skipDefaultSyntax = dockerEngineVersionParsed ? !isEarlierVersion(dockerEngineVersionParsed, minDockerEngineVersion) : false;
const omitPropertyOverride = params.common.skipPersistingCustomizationsFromFeatures ? ['customizations'] : [];
const imageMetadata = getDevcontainerMetadata(imageBuildInfo.metadata, devContainerConfig, featuresConfig, omitPropertyOverride, getOmitDevcontainerPropertyOverride(params.common));
const { containerUser, remoteUser } = findContainerUsers(imageMetadata, composeServiceUser, imageBuildInfo.user);
Expand All @@ -268,22 +267,20 @@ async function getFeaturesBuildOptions(params: DockerResolverParameters, devCont
.replace('#{devcontainerMetadata}', getDevcontainerMetadataLabel(imageMetadata))
.replace('#{containerEnvMetadata}', generateContainerEnvs(devContainerConfig.config.containerEnv, true))
;
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
const omitSyntaxDirective = common.omitSyntaxDirective; // Can be removed when https://github.com/moby/buildkit/issues/4556 is fixed
const dockerfilePrefixContent = `${omitSyntaxDirective ? '' :
skipDefaultSyntax ? (syntax ? `# syntax=${syntax}` : '') :
useBuildKitBuildContexts && !(imageBuildInfo.dockerfile && supportsBuildContexts(imageBuildInfo.dockerfile)) ? '# syntax=docker/dockerfile:1.4' :
syntax ? `# syntax=${syntax}` : ''}
const syntax = imageBuildInfo.dockerfile?.preamble.directives.syntax;
const omitSyntaxDirective = common.omitSyntaxDirective; // Can be removed when https://github.com/moby/buildkit/issues/4556 is fixed
const dockerfilePrefixContent = `${omitSyntaxDirective ? '' :
skipDefaultSyntax ? (syntax ? `# syntax=${syntax}` : '') :
useBuildKitBuildContexts && !(imageBuildInfo.dockerfile && supportsBuildContexts(imageBuildInfo.dockerfile)) ? '# syntax=docker/dockerfile:1.4' :
syntax ? `# syntax=${syntax}` : ''}
ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder
`;

// Build devcontainer-features.env and devcontainer-features-install.sh file(s) for each features source folder
for await (const fSet of featuresConfig.featureSets) {
if (fSet.internalVersion === '2')
{
if (fSet.internalVersion === '2') {
for await (const fe of fSet.features) {
if (fe.cachePath)
{
if (fe.cachePath) {
fe.internalVersion = '2';
const envPath = cliHost.path.join(fe.cachePath, 'devcontainer-features.env');
const variables = getFeatureEnvVariables(fe);
Expand All @@ -305,17 +302,17 @@ ARG _DEV_CONTAINERS_BASE_IMAGE=placeholder
cliHost.writeFile(envPath, Buffer.from(featuresEnv)),
...fSet.features
.filter(f => (includeAllConfiguredFeatures || f.included) && f.value)
.map(f => {
const consecutiveId = f.consecutiveId;
if (!consecutiveId) {
throw new Error('consecutiveId is undefined for Feature ' + f.id);
}
const featuresEnv = [
...getFeatureEnvVariables(f),
`_BUILD_ARG_${getSafeId(f.id)}_TARGETPATH=${path.posix.join('/usr/local/devcontainer-features', consecutiveId)}`
]
.join('\n');
const envPath = cliHost.path.join(dstFolder, consecutiveId, 'devcontainer-features.env'); // next to bin/acquire
.map(f => {
const consecutiveId = f.consecutiveId;
if (!consecutiveId) {
throw new Error('consecutiveId is undefined for Feature ' + f.id);
}
const featuresEnv = [
...getFeatureEnvVariables(f),
`_BUILD_ARG_${getSafeId(f.id)}_TARGETPATH=${path.posix.join('/usr/local/devcontainer-features', consecutiveId)}`
]
.join('\n');
const envPath = cliHost.path.join(dstFolder, consecutiveId, 'devcontainer-features.env'); // next to bin/acquire
return cliHost.writeFile(envPath, Buffer.from(featuresEnv));
})
]);
Expand Down Expand Up @@ -378,7 +375,7 @@ async function isUsingSELinuxLabels(params: DockerResolverParameters): Promise<b
} catch {
// If we can't run the commands, assume SELinux is not enabled.
return false;

}
}

Expand All @@ -395,8 +392,7 @@ function getFeatureEnvVariables(f: Feature) {
const idSafe = getSafeId(f.id);
const variables = [];

if(f.internalVersion !== '2')
{
if (f.internalVersion !== '2') {
if (values) {
variables.push(...Object.keys(values)
.map(name => `_BUILD_ARG_${idSafe}_${getSafeId(name)}="${values[name]}"`));
Expand Down
Loading