(configWithRaw: SubstitutedConfig<DevContainerFromDockerComposeConfig>, projectName: string, params: DockerResolverParameters, localComposeFiles: string[], envFile: string | undefined, composeGlobalArgs: string[], runServices: string[], noCache: boolean, overrideFilePath: string, overrideFilePrefix: string, versionPrefix: string, additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>, canAddLabelsToContainer: boolean, additionalCacheFroms?: string[], noBuild?: boolean)
| 150 | } |
| 151 | |
| 152 | export async function buildAndExtendDockerCompose(configWithRaw: SubstitutedConfig<DevContainerFromDockerComposeConfig>, projectName: string, params: DockerResolverParameters, localComposeFiles: string[], envFile: string | undefined, composeGlobalArgs: string[], runServices: string[], noCache: boolean, overrideFilePath: string, overrideFilePrefix: string, versionPrefix: string, additionalFeatures: Record<string, string | boolean | Record<string, string | boolean>>, canAddLabelsToContainer: boolean, additionalCacheFroms?: string[], noBuild?: boolean) { |
| 153 | |
| 154 | const { common, dockerCLI, dockerComposeCLI: dockerComposeCLIFunc } = params; |
| 155 | const { cliHost, env, output } = common; |
| 156 | const { config } = configWithRaw; |
| 157 | |
| 158 | const cliParams: DockerCLIParameters = { cliHost, dockerCLI, dockerComposeCLI: dockerComposeCLIFunc, env, output, buildPlatformInfo: params.buildPlatformInfo, targetPlatformInfo: params.targetPlatformInfo }; |
| 159 | const composeConfig = await readDockerComposeConfig(cliParams, localComposeFiles, envFile); |
| 160 | const composeService = composeConfig.services[config.service]; |
| 161 | |
| 162 | // determine base imageName for generated features build stage(s) |
| 163 | let baseName = 'dev_container_auto_added_stage_label'; |
| 164 | let dockerfile: string | undefined; |
| 165 | let imageBuildInfo: ImageBuildInfo; |
| 166 | const serviceInfo = getBuildInfoForService(composeService, cliHost.path, localComposeFiles); |
| 167 | if (serviceInfo.build) { |
| 168 | const { context, dockerfilePath, target } = serviceInfo.build; |
| 169 | const resolvedDockerfilePath = cliHost.path.isAbsolute(dockerfilePath) ? dockerfilePath : path.resolve(context, dockerfilePath); |
| 170 | const originalDockerfile = (await cliHost.readFile(resolvedDockerfilePath)).toString(); |
| 171 | dockerfile = originalDockerfile; |
| 172 | if (target) { |
| 173 | // Explictly set build target for the dev container build features on that |
| 174 | baseName = target; |
| 175 | } else { |
| 176 | // Use the last stage in the Dockerfile |
| 177 | // Find the last line that starts with "FROM" (possibly preceeded by white-space) |
| 178 | const { lastStageName, modifiedDockerfile } = ensureDockerfileHasFinalStageName(originalDockerfile, baseName); |
| 179 | baseName = lastStageName; |
| 180 | if (modifiedDockerfile) { |
| 181 | dockerfile = modifiedDockerfile; |
| 182 | } |
| 183 | } |
| 184 | imageBuildInfo = await getImageBuildInfoFromDockerfile(params, originalDockerfile, serviceInfo.build?.args || {}, serviceInfo.build?.target, configWithRaw.substitute); |
| 185 | } else { |
| 186 | imageBuildInfo = await getImageBuildInfoFromImage(params, composeService.image, configWithRaw.substitute); |
| 187 | } |
| 188 | |
| 189 | // determine whether we need to extend with features |
| 190 | const version = parseVersion((await params.dockerComposeCLI()).version); |
| 191 | const supportsAdditionalBuildContexts = params.cliVariant === CLIVariant.Docker && version && !isEarlierVersion(version, [2, 17, 0]); |
| 192 | const optionalBuildKitParams = supportsAdditionalBuildContexts ? params : { ...params, buildKitVersion: undefined }; |
| 193 | const extendImageBuildInfo = await getExtendImageBuildInfo(optionalBuildKitParams, configWithRaw, baseName, imageBuildInfo, composeService.user, additionalFeatures, canAddLabelsToContainer); |
| 194 | |
| 195 | let overrideImageName: string | undefined; |
| 196 | let buildOverrideContent = ''; |
| 197 | if (extendImageBuildInfo?.featureBuildInfo) { |
| 198 | // Avoid retagging a previously pulled image. |
| 199 | if (!serviceInfo.build) { |
| 200 | overrideImageName = getFolderImageName(common); |
| 201 | buildOverrideContent += ` image: ${overrideImageName}\n`; |
| 202 | } |
| 203 | // Create overridden Dockerfile and generate docker-compose build override content |
| 204 | buildOverrideContent += ' build:\n'; |
| 205 | if (!dockerfile) { |
| 206 | dockerfile = `FROM ${composeService.image} AS ${baseName}\n`; |
| 207 | } |
| 208 | const { featureBuildInfo } = extendImageBuildInfo; |
| 209 | // We add a '# syntax' line at the start, so strip out any existing line |
no test coverage detected