diff --git a/package.json b/package.json index 9338b7b736..40a4106961 100644 --- a/package.json +++ b/package.json @@ -1424,6 +1424,10 @@ "type": "string" } }, + "envFile": { + "type": "string", + "description": "%vscode-docker.tasks.docker-compose.dockerCompose.envFile.description%" + }, "files": { "type": "array", "description": "%vscode-docker.tasks.docker-compose.dockerCompose.files.description%", diff --git a/package.nls.json b/package.nls.json index 8c5e607570..25f3004f51 100644 --- a/package.nls.json +++ b/package.nls.json @@ -112,7 +112,8 @@ "vscode-docker.tasks.docker-compose.dockerCompose.down.removeImages": "Images to remove.", "vscode-docker.tasks.docker-compose.dockerCompose.down.removeVolumes": "Whether or not to remove named and anonymous volumes.", "vscode-docker.tasks.docker-compose.dockerCompose.down.customOptions": "Any other options to add to the `docker-compose down` command. Cannot be combined with `up`.", - "vscode-docker.tasks.docker-compose.dockerCompose.envFiles.description": "Files of environment variables read in and applied to the Docker containers.", + "vscode-docker.tasks.docker-compose.dockerCompose.envFiles.description": "(DEPRECATED) Use `envFile` instead.", + "vscode-docker.tasks.docker-compose.dockerCompose.envFile.description": "File of environment variables read in and applied to the Docker containers.", "vscode-docker.tasks.docker-compose.dockerCompose.files.description": "The docker-compose files to include, in order.", "vscode-docker.config.docker.promptForRegistryWhenPushingImages": "Prompt for registry selection if the image is not explicitly tagged.", "vscode-docker.config.template.build.template": "The command template.", diff --git a/src/tasks/DockerComposeTaskDefinitionBase.ts b/src/tasks/DockerComposeTaskDefinitionBase.ts index 1ab14b5523..fb89b62fc7 100644 --- a/src/tasks/DockerComposeTaskDefinitionBase.ts +++ b/src/tasks/DockerComposeTaskDefinitionBase.ts @@ -26,7 +26,18 @@ export interface DockerComposeDownOptions { }; } -export type DockerComposeOptions = (DockerComposeUpOptions | DockerComposeDownOptions) & { envFiles?: string[], files?: string[] }; +export interface DockerComposeUpAndDownOptions { + envFile?: string; + + /** + * @deprecated Use `envFile` instead + */ + envFiles?: string[]; + + files?: string[]; +} + +export type DockerComposeOptions = (DockerComposeUpOptions | DockerComposeDownOptions) & DockerComposeUpAndDownOptions; export interface DockerComposeTaskDefinitionBase extends TaskDefinitionBase { dockerCompose?: DockerComposeOptions; diff --git a/src/tasks/DockerComposeTaskProvider.ts b/src/tasks/DockerComposeTaskProvider.ts index 269fa0de2f..fa9b246bcd 100644 --- a/src/tasks/DockerComposeTaskProvider.ts +++ b/src/tasks/DockerComposeTaskProvider.ts @@ -29,7 +29,10 @@ export class DockerComposeTaskProvider extends DockerTaskProvider { const definition = cloneObject(task.definition); definition.dockerCompose = definition.dockerCompose || {}; definition.dockerCompose.files = definition.dockerCompose.files || []; - definition.dockerCompose.envFiles = definition.dockerCompose.envFiles || []; + + // Fix wrong environment file option name + definition.dockerCompose.envFile = this.normalizeEnvFile(definition.dockerCompose); + definition.dockerCompose.envFiles = undefined; await this.validateResolvedDefinition(context, definition.dockerCompose); @@ -66,10 +69,8 @@ export class DockerComposeTaskProvider extends DockerTaskProvider { } } - for (const file of dockerCompose.envFiles) { - if (!(await fse.pathExists(path.resolve(context.folder.uri.fsPath, resolveVariables(file, context.folder))))) { - throw new Error(localize('vscode-docker.tasks.composeProvider.invalidEnvFile', 'One or more environment files does not exist or could not be accessed.')); - } + if (dockerCompose.envFile && !(await fse.pathExists(path.resolve(context.folder.uri.fsPath, resolveVariables(dockerCompose.envFile, context.folder))))) { + throw new Error(localize('vscode-docker.tasks.composeProvider.invalidEnvFile', 'Environment file does not exist or could not be accessed.')); } } @@ -87,7 +88,7 @@ export class DockerComposeTaskProvider extends DockerTaskProvider { return CommandLineBuilder .create(await getComposeCliCommand()) .withArrayArgs('-f', options.files) - .withArrayArgs('--env-file', options.envFiles) + .withNamedArg('--env-file', options.envFile) .withArrayArgs('--profile', options.up.profiles) .withArg('up') .withFlagArg('--detach', !!options.up.detached) @@ -100,11 +101,24 @@ export class DockerComposeTaskProvider extends DockerTaskProvider { return CommandLineBuilder .create(await getComposeCliCommand()) .withArrayArgs('-f', options.files) - .withArrayArgs('--env-file', options.envFiles) + .withNamedArg('--env-file', options.envFile) .withArg('down') .withNamedArg('--rmi', options.down.removeImages) .withFlagArg('--volumes', options.down.removeVolumes) .withArg(options.down.customOptions); } } + + private normalizeEnvFile(options: DockerComposeOptions): string { + if (options.envFile) { + // If the new option is specified, always use it + return options.envFile; + } else if (options.envFiles?.length) { + // Otherwise use the old option if it is specified + // Compose' behavior is to ignore all prior entries and use only the last environment file + return options.envFiles[options.envFiles.length - 1]; + } else { + return undefined; + } + } }