From d894e1c1bd1cdea3f18187baaa3de0cfe3a532c2 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Mon, 11 May 2020 20:17:11 +0300 Subject: [PATCH 01/10] add replaceEnvVariables --- .../yarnpkg-core/sources/Configuration.ts | 5 +++-- packages/yarnpkg-parsers/sources/index.ts | 2 +- packages/yarnpkg-parsers/sources/syml.ts | 21 +++++++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/packages/yarnpkg-core/sources/Configuration.ts b/packages/yarnpkg-core/sources/Configuration.ts index c5bc0a092556..bba9e7adc648 100644 --- a/packages/yarnpkg-core/sources/Configuration.ts +++ b/packages/yarnpkg-core/sources/Configuration.ts @@ -1,6 +1,6 @@ import {Filename, PortablePath, npath, ppath, toFilename, xfs} from '@yarnpkg/fslib'; import {DEFAULT_COMPRESSION_LEVEL} from '@yarnpkg/fslib'; -import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; +import {parseSyml, stringifySyml, replaceEnvVariables} from '@yarnpkg/parsers'; import camelcase from 'camelcase'; import chalk from 'chalk'; import {UsageError} from 'clipanion'; @@ -825,6 +825,7 @@ export class Configuration { throw new UsageError(`Parse error when loading ${rcPath}; please check it's proper Yaml${tip}`); } + data = replaceEnvVariables(data); rcFiles.push({path: rcPath, cwd: currentCwd, data}); } @@ -840,7 +841,7 @@ export class Configuration { if (xfs.existsSync(homeRcFilePath)) { const content = await xfs.readFilePromise(homeRcFilePath, `utf8`); - const data = parseSyml(content) as any; + const data = replaceEnvVariables(parseSyml(content)) as any; return {path: homeRcFilePath, cwd: homeFolder, data}; } diff --git a/packages/yarnpkg-parsers/sources/index.ts b/packages/yarnpkg-parsers/sources/index.ts index 1cfed988b86b..7b203820fbe7 100644 --- a/packages/yarnpkg-parsers/sources/index.ts +++ b/packages/yarnpkg-parsers/sources/index.ts @@ -3,4 +3,4 @@ export {parseShell} export {Resolution, parseResolution, stringifyResolution} from './resolution'; -export {parseSyml, stringifySyml} from './syml'; +export {parseSyml, stringifySyml,replaceEnvVariables} from './syml'; diff --git a/packages/yarnpkg-parsers/sources/syml.ts b/packages/yarnpkg-parsers/sources/syml.ts index 33a4ec4920f5..6f98e81bb91e 100644 --- a/packages/yarnpkg-parsers/sources/syml.ts +++ b/packages/yarnpkg-parsers/sources/syml.ts @@ -149,3 +149,24 @@ function parseViaJsYaml(source: string) { export function parseSyml(source: string) { return parseViaJsYaml(source); } + +export function replaceEnvVariables(source: string) { + const sourceAsString = JSON.stringify(source); + const splitByVariables = sourceAsString.split(/(\${[\w\d-:]+})/); + const replacedVariables = splitByVariables.map(stringPart => { + const matched = stringPart.match(/^\${(?[\d\w_]+)(?:)?-?(?[^}]+)?}$/); + if (!matched) return stringPart; + + const {variableName, colon, fallback} = matched.groups; + const variableExist = Object.prototype.hasOwnProperty.call(process.env, variableName); + const variableValue = process.env[variableName]; + + if (variableValue) return variableValue; + if (variableExist && !variableValue && colon) return fallback; + if (variableExist) return variableValue; + if (fallback) return fallback; + return ``; + }).join(``); + + return JSON.parse(replacedVariables); +} From 12cc7817642d17132b3f21e5d6f4d49ab23a988a Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Mon, 11 May 2020 20:17:25 +0300 Subject: [PATCH 02/10] add release data --- .yarn/versions/7297fb1f.yml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 .yarn/versions/7297fb1f.yml diff --git a/.yarn/versions/7297fb1f.yml b/.yarn/versions/7297fb1f.yml new file mode 100644 index 000000000000..ba29c37171c6 --- /dev/null +++ b/.yarn/versions/7297fb1f.yml @@ -0,0 +1,32 @@ +releases: + "@yarnpkg/core": prerelease + "@yarnpkg/parsers": prerelease + +declined: + - "@yarnpkg/plugin-compat" + - "@yarnpkg/plugin-constraints" + - "@yarnpkg/plugin-dlx" + - "@yarnpkg/plugin-essentials" + - "@yarnpkg/plugin-exec" + - "@yarnpkg/plugin-file" + - "@yarnpkg/plugin-git" + - "@yarnpkg/plugin-github" + - "@yarnpkg/plugin-http" + - "@yarnpkg/plugin-init" + - "@yarnpkg/plugin-interactive-tools" + - "@yarnpkg/plugin-link" + - "@yarnpkg/plugin-node-modules" + - "@yarnpkg/plugin-npm" + - "@yarnpkg/plugin-npm-cli" + - "@yarnpkg/plugin-pack" + - "@yarnpkg/plugin-patch" + - "@yarnpkg/plugin-pnp" + - "@yarnpkg/plugin-stage" + - "@yarnpkg/plugin-typescript" + - "@yarnpkg/plugin-version" + - "@yarnpkg/plugin-workspace-tools" + - "@yarnpkg/builder" + - "@yarnpkg/cli" + - "@yarnpkg/doctor" + - "@yarnpkg/pnpify" + - "@yarnpkg/shell" From 9b9728c38e8a40b6820ea34a150d7607e046cb67 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Mon, 11 May 2020 20:40:16 +0300 Subject: [PATCH 03/10] fix ts error --- packages/yarnpkg-parsers/sources/syml.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/yarnpkg-parsers/sources/syml.ts b/packages/yarnpkg-parsers/sources/syml.ts index 6f98e81bb91e..fa19a056b3d8 100644 --- a/packages/yarnpkg-parsers/sources/syml.ts +++ b/packages/yarnpkg-parsers/sources/syml.ts @@ -150,14 +150,14 @@ export function parseSyml(source: string) { return parseViaJsYaml(source); } -export function replaceEnvVariables(source: string) { +export function replaceEnvVariables(source: Object) { const sourceAsString = JSON.stringify(source); const splitByVariables = sourceAsString.split(/(\${[\w\d-:]+})/); const replacedVariables = splitByVariables.map(stringPart => { const matched = stringPart.match(/^\${(?[\d\w_]+)(?:)?-?(?[^}]+)?}$/); if (!matched) return stringPart; - const {variableName, colon, fallback} = matched.groups; + const {variableName, colon, fallback} = matched.groups || {}; const variableExist = Object.prototype.hasOwnProperty.call(process.env, variableName); const variableValue = process.env[variableName]; From b8f95a895f584592a728067634e3e1f6f1cc2391 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Sat, 23 May 2020 16:39:07 +0300 Subject: [PATCH 04/10] move env replacement into parseSingleValue --- packages/yarnpkg-core/sources/Configuration.ts | 15 ++++++++------- packages/yarnpkg-parsers/sources/syml.ts | 9 ++++----- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/packages/yarnpkg-core/sources/Configuration.ts b/packages/yarnpkg-core/sources/Configuration.ts index bba9e7adc648..8582b9b3df79 100644 --- a/packages/yarnpkg-core/sources/Configuration.ts +++ b/packages/yarnpkg-core/sources/Configuration.ts @@ -438,17 +438,19 @@ function parseSingleValue(configuration: Configuration, path: string, value: unk if (typeof value !== `string`) throw new Error(`Expected value to be a string`); + const valueWithReplacedVariables = replaceEnvVariables(value); + switch (definition.type) { case SettingsType.ABSOLUTE_PATH: - return ppath.resolve(folder, npath.toPortablePath(value)); + return ppath.resolve(folder, npath.toPortablePath(valueWithReplacedVariables)); case SettingsType.LOCATOR_LOOSE: - return structUtils.parseLocator(value, false); + return structUtils.parseLocator(valueWithReplacedVariables, false); case SettingsType.NUMBER: - return parseInt(value); + return parseInt(valueWithReplacedVariables); case SettingsType.LOCATOR: - return structUtils.parseLocator(value); + return structUtils.parseLocator(valueWithReplacedVariables); default: - return value; + return valueWithReplacedVariables; } }; @@ -825,7 +827,6 @@ export class Configuration { throw new UsageError(`Parse error when loading ${rcPath}; please check it's proper Yaml${tip}`); } - data = replaceEnvVariables(data); rcFiles.push({path: rcPath, cwd: currentCwd, data}); } @@ -841,7 +842,7 @@ export class Configuration { if (xfs.existsSync(homeRcFilePath)) { const content = await xfs.readFilePromise(homeRcFilePath, `utf8`); - const data = replaceEnvVariables(parseSyml(content)) as any; + const data = parseSyml(content) as any; return {path: homeRcFilePath, cwd: homeFolder, data}; } diff --git a/packages/yarnpkg-parsers/sources/syml.ts b/packages/yarnpkg-parsers/sources/syml.ts index fa19a056b3d8..5d5c92133a69 100644 --- a/packages/yarnpkg-parsers/sources/syml.ts +++ b/packages/yarnpkg-parsers/sources/syml.ts @@ -150,9 +150,8 @@ export function parseSyml(source: string) { return parseViaJsYaml(source); } -export function replaceEnvVariables(source: Object) { - const sourceAsString = JSON.stringify(source); - const splitByVariables = sourceAsString.split(/(\${[\w\d-:]+})/); +export function replaceEnvVariables(source: string): string { + const splitByVariables = source.split(/(\${[\w\d-:]+})/); const replacedVariables = splitByVariables.map(stringPart => { const matched = stringPart.match(/^\${(?[\d\w_]+)(?:)?-?(?[^}]+)?}$/); if (!matched) return stringPart; @@ -166,7 +165,7 @@ export function replaceEnvVariables(source: Object) { if (variableExist) return variableValue; if (fallback) return fallback; return ``; - }).join(``); + }); - return JSON.parse(replacedVariables); + return replacedVariables.join(``); } From 941a260e1ce905ef744c84e2c94bc4a4978f6081 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Sat, 23 May 2020 16:39:22 +0300 Subject: [PATCH 05/10] add tests for env replacement --- .../yarnpkg-core/tests/Configuration.test.ts | 51 +++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/packages/yarnpkg-core/tests/Configuration.test.ts b/packages/yarnpkg-core/tests/Configuration.test.ts index 2849ef58379f..32b8464ff654 100644 --- a/packages/yarnpkg-core/tests/Configuration.test.ts +++ b/packages/yarnpkg-core/tests/Configuration.test.ts @@ -33,4 +33,55 @@ describe(`Configuration`, () => { expect(secondToken).toEqual(SECRET); }); }); + + describe(`Enviroment variables`, () => { + it(`should replace env variables`, async () => { + process.env.ENV_AUTH_TOKEN = `AAA-BBB-CCC`; + process.env.EMPTY_VARIABLE = ``; + + await initializeConfiguration({ + npmScopes: { + onlyEnv: { + npmAuthToken: `\${ENV_AUTH_TOKEN}`, + }, + envInString: { + npmAuthToken: `beforeEnv-\${ENV_AUTH_TOKEN}-after-env`, + }, + envSetWithFallback: { + npmAuthToken: `\${ENV_AUTH_TOKEN-fallback-value}`, + }, + unsetEnvWithFallback: { + npmAuthToken: `\${NOT_EXISTING_ENV-fallback-value}`, + }, + emptyEnvWithStrictFallback: { + npmAuthToken: `\${EMPTY_VARIABLE-fallback-value}`, + }, + emptyEnvWithFallback: { + npmAuthToken: `\${EMPTY_VARIABLE:-fallback-for-empty-value}`, + }, + }, + }, async dir => { + const configuration = await Configuration.find(dir, { + modules: new Map([[`@yarnpkg/plugin-npm`, NpmPlugin]]), + plugins: new Set([`@yarnpkg/plugin-npm`]), + }); + + const getToken = (scope: string) => configuration.get(`npmScopes`).get(scope).get(`npmAuthToken`); + + const onlyEnv = getToken(`onlyEnv`); + const envInString = getToken(`envInString`); + const envSetWithFallback = getToken(`envSetWithFallback`); + const unsetEnvWithFallback = getToken(`unsetEnvWithFallback`); + const emptyEnvWithStrictFallback = getToken(`emptyEnvWithStrictFallback`); + const emptyEnvWithFallback = getToken(`emptyEnvWithFallback`); + + expect(onlyEnv).toEqual(`AAA-BBB-CCC`); + expect(envInString).toEqual(`beforeEnv-AAA-BBB-CCC-after-env`); + expect(envSetWithFallback).toEqual(`AAA-BBB-CCC`); + expect(unsetEnvWithFallback).toEqual(`fallback-value`); + expect(emptyEnvWithStrictFallback).toEqual(``); + expect(emptyEnvWithFallback).toEqual(`fallback-for-empty-value`); + }); + }); + }); }); From c28c223631e0ea8ba5acc50b7cc032614d16ad90 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Sat, 23 May 2020 17:05:03 +0300 Subject: [PATCH 06/10] add documentation for env variables --- packages/gatsby/src/pages/configuration/yarnrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gatsby/src/pages/configuration/yarnrc.json b/packages/gatsby/src/pages/configuration/yarnrc.json index a99456d2beba..33f3413c451e 100644 --- a/packages/gatsby/src/pages/configuration/yarnrc.json +++ b/packages/gatsby/src/pages/configuration/yarnrc.json @@ -1,7 +1,7 @@ { "title": "JSON Schema for Yarnrc files", "$schema": "https://json-schema.org/draft/2019-09/schema#", - "description": "Yarnrc files (named this way because they must be called `.yarnrc.yml`) are the one place where you'll be able to configure Yarn's internal settings. While Yarn will automatically find them in the parent directories, they should usually be kept at the root of your project (often your repository). Starting from the v2, they **must** be written in valid Yaml and have the right extension (simply calling your file `.yarnrc` won't do).\n\nThose settings can also be defined through environment variables (at least for the simpler ones; arrays and objects aren't supported yet). To do this, just prefix the names and write them in snake case: `YARN_CACHE_FOLDER` will set the cache folder (such values will overwrite any that might have been defined in the RC files - use them sparingly).", + "description": "Yarnrc files (named this way because they must be called `.yarnrc.yml`) are the one place where you'll be able to configure Yarn's internal settings. While Yarn will automatically find them in the parent directories, they should usually be kept at the root of your project (often your repository). Starting from the v2, they **must** be written in valid Yaml and have the right extension (simply calling your file `.yarnrc` won't do).\n\nThose settings can also be defined through environment variables (at least for the simpler ones; arrays and objects aren't supported yet). To do this, just prefix the names and write them in snake case: `YARN_CACHE_FOLDER` will set the cache folder (such values will overwrite any that might have been defined in the RC files - use them sparingly).\n\nEnvironment variables interpolation in Yarnrc supported too. Just wrap env like this: `${YOUR_ENV_VARIABLE}`. Also you can define fallbacks for variables. The supported forms are `${FOO-default}` (fall back if FOO is unset) and `${FOO:-default}` (fall back if FOO is unset or empty).", "type": "object", "properties": { "bstatePath": { From da1ec5863760e7e4109b8d2b460ae316d02bb1f5 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Sat, 23 May 2020 18:48:01 +0300 Subject: [PATCH 07/10] refactor replace to .search method --- packages/yarnpkg-parsers/sources/syml.ts | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/packages/yarnpkg-parsers/sources/syml.ts b/packages/yarnpkg-parsers/sources/syml.ts index 5d5c92133a69..a1c9f3a88abf 100644 --- a/packages/yarnpkg-parsers/sources/syml.ts +++ b/packages/yarnpkg-parsers/sources/syml.ts @@ -150,13 +150,10 @@ export function parseSyml(source: string) { return parseViaJsYaml(source); } -export function replaceEnvVariables(source: string): string { - const splitByVariables = source.split(/(\${[\w\d-:]+})/); - const replacedVariables = splitByVariables.map(stringPart => { - const matched = stringPart.match(/^\${(?[\d\w_]+)(?:)?-?(?[^}]+)?}$/); - if (!matched) return stringPart; - - const {variableName, colon, fallback} = matched.groups || {}; +export function replaceEnvVariables(source: string) { + const regex = /\${(?[\d\w_]+)(?:)?-?(?[^}]+)?}/g; + return source.replace(regex, (...args) => { + const {variableName, colon, fallback} = args[args.length - 1]; const variableExist = Object.prototype.hasOwnProperty.call(process.env, variableName); const variableValue = process.env[variableName]; @@ -166,6 +163,4 @@ export function replaceEnvVariables(source: string): string { if (fallback) return fallback; return ``; }); - - return replacedVariables.join(``); } From c6742de1b8db36735718ecd4f6e188b23ea91df5 Mon Sep 17 00:00:00 2001 From: Valentin Semirulnik Date: Sat, 23 May 2020 18:51:16 +0300 Subject: [PATCH 08/10] add test for mupltiple variables --- packages/yarnpkg-core/tests/Configuration.test.ts | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/packages/yarnpkg-core/tests/Configuration.test.ts b/packages/yarnpkg-core/tests/Configuration.test.ts index 32b8464ff654..03837a988083 100644 --- a/packages/yarnpkg-core/tests/Configuration.test.ts +++ b/packages/yarnpkg-core/tests/Configuration.test.ts @@ -44,6 +44,9 @@ describe(`Configuration`, () => { onlyEnv: { npmAuthToken: `\${ENV_AUTH_TOKEN}`, }, + multipleEnvs: { + npmAuthToken: `\${ENV_AUTH_TOKEN}-separator-\${ENV_AUTH_TOKEN}`, + }, envInString: { npmAuthToken: `beforeEnv-\${ENV_AUTH_TOKEN}-after-env`, }, @@ -69,6 +72,7 @@ describe(`Configuration`, () => { const getToken = (scope: string) => configuration.get(`npmScopes`).get(scope).get(`npmAuthToken`); const onlyEnv = getToken(`onlyEnv`); + const multipleEnvs = getToken(`multipleEnvs`); const envInString = getToken(`envInString`); const envSetWithFallback = getToken(`envSetWithFallback`); const unsetEnvWithFallback = getToken(`unsetEnvWithFallback`); @@ -76,6 +80,7 @@ describe(`Configuration`, () => { const emptyEnvWithFallback = getToken(`emptyEnvWithFallback`); expect(onlyEnv).toEqual(`AAA-BBB-CCC`); + expect(multipleEnvs).toEqual(`AAA-BBB-CCC-separator-AAA-BBB-CCC`); expect(envInString).toEqual(`beforeEnv-AAA-BBB-CCC-after-env`); expect(envSetWithFallback).toEqual(`AAA-BBB-CCC`); expect(unsetEnvWithFallback).toEqual(`fallback-value`); From c281509dde100968588b761b4c77aa9c2594047e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 1 Jun 2020 11:30:44 +0200 Subject: [PATCH 09/10] Some refactorings --- .../yarnpkg-core/sources/Configuration.ts | 16 +++++++++-- packages/yarnpkg-core/sources/miscUtils.ts | 28 +++++++++++++++++-- .../yarnpkg-core/tests/Configuration.test.ts | 17 ++++++++++- packages/yarnpkg-parsers/sources/index.ts | 2 +- packages/yarnpkg-parsers/sources/syml.ts | 15 ---------- 5 files changed, 56 insertions(+), 22 deletions(-) diff --git a/packages/yarnpkg-core/sources/Configuration.ts b/packages/yarnpkg-core/sources/Configuration.ts index 8582b9b3df79..0a452e5eec3e 100644 --- a/packages/yarnpkg-core/sources/Configuration.ts +++ b/packages/yarnpkg-core/sources/Configuration.ts @@ -1,6 +1,6 @@ import {Filename, PortablePath, npath, ppath, toFilename, xfs} from '@yarnpkg/fslib'; import {DEFAULT_COMPRESSION_LEVEL} from '@yarnpkg/fslib'; -import {parseSyml, stringifySyml, replaceEnvVariables} from '@yarnpkg/parsers'; +import {parseSyml, stringifySyml} from '@yarnpkg/parsers'; import camelcase from 'camelcase'; import chalk from 'chalk'; import {UsageError} from 'clipanion'; @@ -438,7 +438,9 @@ function parseSingleValue(configuration: Configuration, path: string, value: unk if (typeof value !== `string`) throw new Error(`Expected value to be a string`); - const valueWithReplacedVariables = replaceEnvVariables(value); + const valueWithReplacedVariables = miscUtils.replaceEnvVariables(value, { + env: process.env, + }); switch (definition.type) { case SettingsType.ABSOLUTE_PATH: @@ -983,7 +985,15 @@ export class Configuration { if (this.sources.has(key) && !overwrite) continue; - this.values.set(key, parseValue(this, key, data[key], definition, folder)); + let parsed; + try { + parsed = parseValue(this, key, data[key], definition, folder); + } catch (error) { + error.message += ` in ${source}`; + throw error; + } + + this.values.set(key, parsed); this.sources.set(key, source); } } diff --git a/packages/yarnpkg-core/sources/miscUtils.ts b/packages/yarnpkg-core/sources/miscUtils.ts index 4d153d6a9e4e..eaaae3438584 100644 --- a/packages/yarnpkg-core/sources/miscUtils.ts +++ b/packages/yarnpkg-core/sources/miscUtils.ts @@ -1,4 +1,5 @@ import {PortablePath, npath} from '@yarnpkg/fslib'; +import {UsageError} from 'clipanion'; import micromatch from 'micromatch'; import {Readable, Transform} from 'stream'; @@ -263,7 +264,7 @@ export function sortMap(values: Iterable, mappers: ((value: T) => string) * * @returns A `string` representing a regular expression or `null` if no glob patterns are provided */ -export const buildIgnorePattern = (ignorePatterns: Array) => { +export function buildIgnorePattern(ignorePatterns: Array) { if (ignorePatterns.length === 0) return null; @@ -273,4 +274,27 @@ export const buildIgnorePattern = (ignorePatterns: Array) => { windows: false, }).source})`; }).join(`|`); -}; +} + +export function replaceEnvVariables(value: string, {env}: {env: {[key: string]: string | undefined}}) { + const regex = /\${(?[\d\w_]+)(?:)?-?(?[^}]+)?}/g; + + return value.replace(regex, (...args) => { + const {variableName, colon, fallback} = args[args.length - 1]; + + const variableExist = Object.prototype.hasOwnProperty.call(env, variableName); + const variableValue = process.env[variableName]; + + if (variableValue) + return variableValue; + if (variableExist && !variableValue && colon) + return fallback; + if (variableExist) + return variableValue; + if (fallback) + return fallback; + + throw new UsageError(`Environment variable not found (${variableName})`); + }); +} + diff --git a/packages/yarnpkg-core/tests/Configuration.test.ts b/packages/yarnpkg-core/tests/Configuration.test.ts index 03837a988083..27a979754250 100644 --- a/packages/yarnpkg-core/tests/Configuration.test.ts +++ b/packages/yarnpkg-core/tests/Configuration.test.ts @@ -34,7 +34,7 @@ describe(`Configuration`, () => { }); }); - describe(`Enviroment variables`, () => { + describe(`Environment variables`, () => { it(`should replace env variables`, async () => { process.env.ENV_AUTH_TOKEN = `AAA-BBB-CCC`; process.env.EMPTY_VARIABLE = ``; @@ -88,5 +88,20 @@ describe(`Configuration`, () => { expect(emptyEnvWithFallback).toEqual(`fallback-for-empty-value`); }); }); + + it(`should forbid unset variables`, async () => { + await initializeConfiguration({ + npmScopes: { + onlyEnv: { + npmAuthToken: `\${A_VARIABLE_THAT_DEFINITELY_DOESNT_EXIST}`, + }, + }, + }, async dir => { + await expect(Configuration.find(dir, { + modules: new Map([[`@yarnpkg/plugin-npm`, NpmPlugin]]), + plugins: new Set([`@yarnpkg/plugin-npm`]), + })).rejects.toThrow(); + }); + }); }); }); diff --git a/packages/yarnpkg-parsers/sources/index.ts b/packages/yarnpkg-parsers/sources/index.ts index 7b203820fbe7..1cfed988b86b 100644 --- a/packages/yarnpkg-parsers/sources/index.ts +++ b/packages/yarnpkg-parsers/sources/index.ts @@ -3,4 +3,4 @@ export {parseShell} export {Resolution, parseResolution, stringifyResolution} from './resolution'; -export {parseSyml, stringifySyml,replaceEnvVariables} from './syml'; +export {parseSyml, stringifySyml} from './syml'; diff --git a/packages/yarnpkg-parsers/sources/syml.ts b/packages/yarnpkg-parsers/sources/syml.ts index a1c9f3a88abf..33a4ec4920f5 100644 --- a/packages/yarnpkg-parsers/sources/syml.ts +++ b/packages/yarnpkg-parsers/sources/syml.ts @@ -149,18 +149,3 @@ function parseViaJsYaml(source: string) { export function parseSyml(source: string) { return parseViaJsYaml(source); } - -export function replaceEnvVariables(source: string) { - const regex = /\${(?[\d\w_]+)(?:)?-?(?[^}]+)?}/g; - return source.replace(regex, (...args) => { - const {variableName, colon, fallback} = args[args.length - 1]; - const variableExist = Object.prototype.hasOwnProperty.call(process.env, variableName); - const variableValue = process.env[variableName]; - - if (variableValue) return variableValue; - if (variableExist && !variableValue && colon) return fallback; - if (variableExist) return variableValue; - if (fallback) return fallback; - return ``; - }); -} From 92ff75a8a527fb893c32688650edaf94e8bc4dd4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Mon, 1 Jun 2020 15:06:12 +0200 Subject: [PATCH 10/10] Wording --- packages/gatsby/src/pages/configuration/yarnrc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/gatsby/src/pages/configuration/yarnrc.json b/packages/gatsby/src/pages/configuration/yarnrc.json index 89e333d276fd..e55f2d30198b 100644 --- a/packages/gatsby/src/pages/configuration/yarnrc.json +++ b/packages/gatsby/src/pages/configuration/yarnrc.json @@ -1,7 +1,7 @@ { "title": "JSON Schema for Yarnrc files", "$schema": "https://json-schema.org/draft/2019-09/schema#", - "description": "Yarnrc files (named this way because they must be called `.yarnrc.yml`) are the one place where you'll be able to configure Yarn's internal settings. While Yarn will automatically find them in the parent directories, they should usually be kept at the root of your project (often your repository). Starting from the v2, they **must** be written in valid Yaml and have the right extension (simply calling your file `.yarnrc` won't do).\n\nThose settings can also be defined through environment variables (at least for the simpler ones; arrays and objects aren't supported yet). To do this, just prefix the names and write them in snake case: `YARN_CACHE_FOLDER` will set the cache folder (such values will overwrite any that might have been defined in the RC files - use them sparingly).\n\nEnvironment variables interpolation in Yarnrc supported too. Just wrap env like this: `${YOUR_ENV_VARIABLE}`. Also you can define fallbacks for variables. The supported forms are `${FOO-default}` (fall back if FOO is unset) and `${FOO:-default}` (fall back if FOO is unset or empty).", + "description": "Yarnrc files (named this way because they must be called `.yarnrc.yml`) are the one place where you'll be able to configure Yarn's internal settings. While Yarn will automatically find them in the parent directories, they should usually be kept at the root of your project (often your repository). Starting from the v2, they **must** be written in valid Yaml and have the right extension (simply calling your file `.yarnrc` won't do).\n\nEnvironment variables can be accessed from setting definitions by using the `${NAME}` syntax when defining the values. By default Yarn will require the variables to be present, but this can be turned off by using either `${NAME-fallback}` (which will return `fallback` if `NAME` isn't set) or `${NAME:-fallback}` (which will return `fallback` if `NAME` isn't set, or is an empty string).\n\nFinally, note that most settings can also be defined through environment variables (at least for the simpler ones; arrays and objects aren't supported yet). To do this, just prefix the names and write them in snake case: `YARN_CACHE_FOLDER` will set the cache folder (such values will overwrite any that might have been defined in the RC files - use them sparingly).", "type": "object", "properties": { "bstatePath": {