From 0d1fe55b45ad601a25f201a298853e0fbf20ff20 Mon Sep 17 00:00:00 2001 From: Jeroen de Bruijn Date: Sun, 7 Mar 2021 15:25:00 +0100 Subject: [PATCH] fix: pass existing environment variables to Docker with `--env` --- src/input.ts | 50 ++++++++++++++++++++++++++++------------ src/renovate.ts | 61 ++++++++++++++++++++++++++----------------------- 2 files changed, 67 insertions(+), 44 deletions(-) diff --git a/src/input.ts b/src/input.ts index 6b07dce7..48b4749f 100644 --- a/src/input.ts +++ b/src/input.ts @@ -12,14 +12,18 @@ class Input { configurationFile: { input: 'configurationFile', env: 'RENOVATE_CONFIG_FILE', + optional: true, }, token: { input: 'token', env: 'RENOVATE_TOKEN', + optional: false, }, } as const; + readonly token: Readonly; private readonly _environmentVariables: Map; + private readonly _configurationFile: Readonly; constructor() { this._environmentVariables = new Map( @@ -28,27 +32,35 @@ class Input { ) ); - this.setEnvironmentVariable( + this.token = this.get( this.options.token.input, - this.options.token.env + this.options.token.env, + this.options.token.optional ); - this.setEnvironmentVariable( + this._configurationFile = this.get( this.options.configurationFile.input, - this.options.configurationFile.env + this.options.configurationFile.env, + this.options.configurationFile.optional ); } - configurationFile(): string { - return path.resolve( - this._environmentVariables.get(this.options.configurationFile.env) - ); + configurationFile(): EnvironmentVariable | null { + if (this._configurationFile.value !== '') { + return { + key: this._configurationFile.key, + value: path.resolve(this._configurationFile.value), + }; + } + + return null; } /** * Convert to environment variables. * - * @note The environment variable for the configuration file is filtered out - * and is available with `configurationFile()` instead. + * @note The environment variables listed below are filtered out. + * - Token, available with the `token` property. + * - Configuration file, available with the `configurationFile()` method. */ toEnvironmentVariables(): EnvironmentVariable[] { return [...this._environmentVariables].map(([key, value]) => ({ @@ -57,9 +69,15 @@ class Input { })); } - private setEnvironmentVariable(input: string, env: string) { - const optionalInput = core.getInput(input); - if (optionalInput === '' && !this._environmentVariables.has(env)) { + private get( + input: string, + env: string, + optional: boolean + ): EnvironmentVariable { + const fromInput = core.getInput(input); + const fromEnv = this._environmentVariables.get(env); + + if (fromInput === '' && fromEnv === undefined && !optional) { throw new Error( [ `'${input}' MUST be passed using its input or the '${env}'`, @@ -68,9 +86,11 @@ class Input { ); } - if (optionalInput !== '') { - this._environmentVariables.set(env, optionalInput); + this._environmentVariables.delete(env); + if (fromInput !== '') { + return { key: env, value: fromInput }; } + return { key: env, value: fromEnv !== undefined ? fromEnv : '' }; } } diff --git a/src/renovate.ts b/src/renovate.ts index 767ab6ec..b019d11c 100644 --- a/src/renovate.ts +++ b/src/renovate.ts @@ -19,25 +19,27 @@ class Renovate { async runDockerContainer(): Promise { const renovateDockerUser = 'ubuntu'; - const dockerArguments = [ - ...this.input.toEnvironmentVariables(), - { - key: this.input.options.configurationFile.env, - value: this.configFileMountPath(), - }, - ] - .map((e) => { - const quotedValue = /\s/.test(e.value) ? `'${e.value}'` : e.value; - return `--env ${e.key}=${quotedValue}`; - }) - .concat([ - `--volume ${this.input.configurationFile()}:${this.configFileMountPath()}`, - '--volume /var/run/docker.sock:/var/run/docker.sock', - '--volume /tmp:/tmp', - `--user ${renovateDockerUser}:${this.getDockerGroupId()}`, - '--rm', - this.docker.image(), - ]); + const dockerArguments = this.input + .toEnvironmentVariables() + .map((e) => `--env ${e.key}`) + .concat([`--env ${this.input.token.key}=${this.input.token.value}`]); + + if (this.input.configurationFile() !== null) { + const baseName = path.basename(this.input.configurationFile().value); + const mountPath = path.join(this.configFileMountDir, baseName); + dockerArguments.push( + `--env ${this.input.configurationFile().key}=${mountPath}`, + `--volume ${this.input.configurationFile().value}:${mountPath}` + ); + } + + dockerArguments.push( + '--volume /var/run/docker.sock:/var/run/docker.sock', + '--volume /tmp:/tmp', + `--user ${renovateDockerUser}:${this.getDockerGroupId()}`, + '--rm', + this.docker.image() + ); const command = `docker run ${dockerArguments.join(' ')}`; @@ -77,20 +79,21 @@ class Renovate { } private validateArguments(): void { - if (!fs.existsSync(this.input.configurationFile())) { + if (/\s/.test(this.input.token.value)) { + throw new Error('Token MUST NOT contain whitespace'); + } + + const configurationFile = this.input.configurationFile(); + if ( + configurationFile !== null && + (!fs.existsSync(configurationFile.value) || + !fs.statSync(configurationFile.value).isFile()) + ) { throw new Error( - `Could not locate configuration file '${this.input.configurationFile()}'.` + `configuration file '${configurationFile.value}' MUST be an existing file` ); } } - - private configFileName(): string { - return path.basename(this.input.configurationFile()); - } - - private configFileMountPath(): string { - return path.join(this.configFileMountDir, this.configFileName()); - } } export default Renovate;