Skip to content

Commit 7788d14

Browse files
authored
Tweaks the .env implementation (#5548)
**What's the problem this PR addresses?** It was raised in yarnpkg/berry#5544 (comment) that automatically injecting the `.env` file in the environment could break compatibility with some software that already do this in their own way. It makes sense, and I prefer to avoid doing that if there's a reasonable compromise. Also closes yarnpkg/berry#5545. **How did you fix it?** Yarn will now default into loading the `.env.yarn` file, rather than `.env`. **Checklist** <!--- Don't worry if you miss something, chores are automatically tested. --> <!--- This checklist exists to help you remember doing the chores when you submit a PR. --> <!--- Put an `x` in all the boxes that apply. --> - [x] I have read the [Contributing Guide](https://yarnpkg.com/advanced/contributing). <!-- See https://yarnpkg.com/advanced/contributing#preparing-your-pr-to-be-released for more details. --> <!-- Check with `yarn version check` and fix with `yarn version check -i` --> - [x] I have set the packages that need to be released for my changes to be effective. <!-- The "Testing chores" workflow validates that your PR follows our guidelines. --> <!-- If it doesn't pass, click on it to see details as to what your PR might be missing. --> - [x] I will check that all automated PR checks pass before the PR gets reviewed.
1 parent 4ea24ab commit 7788d14

File tree

8 files changed

+100
-43
lines changed

8 files changed

+100
-43
lines changed

Diff for: .yarn/versions/523ca228.yml

+36
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
releases:
2+
"@yarnpkg/cli": patch
3+
"@yarnpkg/core": patch
4+
"@yarnpkg/parsers": patch
5+
6+
declined:
7+
- "@yarnpkg/plugin-compat"
8+
- "@yarnpkg/plugin-constraints"
9+
- "@yarnpkg/plugin-dlx"
10+
- "@yarnpkg/plugin-essentials"
11+
- "@yarnpkg/plugin-exec"
12+
- "@yarnpkg/plugin-file"
13+
- "@yarnpkg/plugin-git"
14+
- "@yarnpkg/plugin-github"
15+
- "@yarnpkg/plugin-http"
16+
- "@yarnpkg/plugin-init"
17+
- "@yarnpkg/plugin-interactive-tools"
18+
- "@yarnpkg/plugin-link"
19+
- "@yarnpkg/plugin-nm"
20+
- "@yarnpkg/plugin-npm"
21+
- "@yarnpkg/plugin-npm-cli"
22+
- "@yarnpkg/plugin-pack"
23+
- "@yarnpkg/plugin-patch"
24+
- "@yarnpkg/plugin-pnp"
25+
- "@yarnpkg/plugin-pnpm"
26+
- "@yarnpkg/plugin-stage"
27+
- "@yarnpkg/plugin-typescript"
28+
- "@yarnpkg/plugin-version"
29+
- "@yarnpkg/plugin-workspace-tools"
30+
- "@yarnpkg/builder"
31+
- "@yarnpkg/doctor"
32+
- "@yarnpkg/extensions"
33+
- "@yarnpkg/nm"
34+
- "@yarnpkg/pnpify"
35+
- "@yarnpkg/sdks"
36+
- "@yarnpkg/shell"

Diff for: CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,7 @@ The following changes only affect people writing Yarn plugins:
9090

9191
### Features
9292

93+
- `yarn run` now injects the environment variables defined in `.env.yarn` when spawning a process. The list of files thus injected can be controlled using the `injectEnvironmentFiles` variable.
9394
- `yarn workspaces foreach` now automatically enables the `-v,--verbose` flag in interactive terminal environments.
9495

9596
### Bugfixes

Diff for: packages/acceptance-tests/pkg-tests-specs/sources/commands/config/set.test.ts

+21-5
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,32 @@
1-
import {PortablePath, xfs} from '@yarnpkg/fslib';
2-
import {EOL} from 'os';
1+
import {Filename, ppath, xfs} from '@yarnpkg/fslib';
2+
import {parseSyml} from '@yarnpkg/parsers';
3+
import {EOL} from 'os';
34

45
describe(`Commands`, () => {
56
describe(`config set`, () => {
7+
test(
8+
`it shouldn't remove empty arrays from the files`,
9+
makeTemporaryEnv({}, async ({path, run, source}) => {
10+
await xfs.writeJsonPromise(ppath.join(path, Filename.rc), {
11+
injectEnvironmentFiles: [],
12+
});
13+
14+
await run(`config`, `set`, `pnpShebang`, `#!/usr/bin/env iojs\n`);
15+
16+
expect(parseSyml(await xfs.readFilePromise(ppath.join(path, Filename.rc), `utf8`))).toMatchObject({
17+
injectEnvironmentFiles: [],
18+
});
19+
}),
20+
);
21+
622
test(
723
`it should print the configured value for the current directory`,
824
makeTemporaryEnv({}, async ({path, run, source}) => {
925
await expect(run(`config`, `set`, `pnpShebang`, `#!/usr/bin/env iojs\n`)).resolves.toMatchObject({
1026
stdout: expect.stringContaining(`#!/usr/bin/env iojs\\n`),
1127
});
1228

13-
await expect(xfs.readFilePromise(`${path}/.yarnrc.yml` as PortablePath, `utf8`)).resolves.toContain(`pnpShebang`);
29+
await expect(xfs.readFilePromise(ppath.join(path, Filename.rc), `utf8`)).resolves.toContain(`pnpShebang`);
1430
}),
1531
);
1632

@@ -22,7 +38,7 @@ describe(`Commands`, () => {
2238
expect(stdout).not.toContain(`foobar`);
2339
expect(stdout).toContain(`********`);
2440

25-
await expect(xfs.readFilePromise(`${path}/.yarnrc.yml` as PortablePath, `utf8`)).resolves.toContain(`npmAuthToken: foobar`);
41+
await expect(xfs.readFilePromise(ppath.join(path, Filename.rc), `utf8`)).resolves.toContain(`npmAuthToken: foobar`);
2642
}),
2743
);
2844

@@ -36,7 +52,7 @@ describe(`Commands`, () => {
3652
expect(stdout).toContain(`npmScopes.yarnpkg`);
3753
expect(stdout).toContain(`npmAlwaysAuth: false`);
3854

39-
await expect(xfs.readFilePromise(`${path}/.yarnrc.yml` as PortablePath, `utf8`)).resolves.toContain(
55+
await expect(xfs.readFilePromise(ppath.join(path, Filename.rc), `utf8`)).resolves.toContain(
4056
`npmScopes:${EOL}` +
4157
` yarnpkg:${EOL}` +
4258
` npmAlwaysAuth: false`,

Diff for: packages/acceptance-tests/pkg-tests-specs/sources/features/dotEnvFiles.test.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import {Filename, ppath, xfs} from '@yarnpkg/fslib';
22

33
describe(`DotEnv files`, () => {
4-
it(`should automatically inject a .env file in the environment`, makeTemporaryEnv({}, async ({path, run, source}) => {
4+
it(`should automatically inject a .env.yarn file in the environment`, makeTemporaryEnv({}, async ({path, run, source}) => {
55
await run(`install`);
66

7-
await xfs.writeFilePromise(ppath.join(path, `.env`), [
7+
await xfs.writeFilePromise(ppath.join(path, `.env.yarn`), [
88
`INJECTED_FROM_ENV_FILE=hello\n`,
99
].join(``));
1010

@@ -16,7 +16,7 @@ describe(`DotEnv files`, () => {
1616
it(`should allow .env variables to be interpolated`, makeTemporaryEnv({}, async ({path, run, source}) => {
1717
await run(`install`);
1818

19-
await xfs.writeFilePromise(ppath.join(path, `.env`), [
19+
await xfs.writeFilePromise(ppath.join(path, `.env.yarn`), [
2020
`INJECTED_FROM_ENV_FILE=\${FOO}\n`,
2121
].join(``));
2222

@@ -28,7 +28,7 @@ describe(`DotEnv files`, () => {
2828
it(`should allow .env variables to be used in the next ones`, makeTemporaryEnv({}, async ({path, run, source}) => {
2929
await run(`install`);
3030

31-
await xfs.writeFilePromise(ppath.join(path, `.env`), [
31+
await xfs.writeFilePromise(ppath.join(path, `.env.yarn`), [
3232
`INJECTED_FROM_ENV_FILE_1=hello\n`,
3333
`INJECTED_FROM_ENV_FILE_2=\${INJECTED_FROM_ENV_FILE_1} world\n`,
3434
].join(``));
@@ -38,7 +38,7 @@ describe(`DotEnv files`, () => {
3838
});
3939
}));
4040

41-
it(`shouldn't read the .env if the injectEnvironmentFiles setting is defined`, makeTemporaryEnv({}, async ({path, run, source}) => {
41+
it(`shouldn't read the .env.yarn file if the injectEnvironmentFiles setting is defined`, makeTemporaryEnv({}, async ({path, run, source}) => {
4242
await xfs.writeJsonPromise(ppath.join(path, Filename.rc), {
4343
injectEnvironmentFiles: [],
4444
});
@@ -114,7 +114,7 @@ describe(`DotEnv files`, () => {
114114
it(`should allow values from environment files to be reused in other configuration settings`, makeTemporaryEnv({}, async ({path, run, source}) => {
115115
await run(`install`);
116116

117-
await xfs.writeFilePromise(ppath.join(path, `.env`), [
117+
await xfs.writeFilePromise(ppath.join(path, `.env.yarn`), [
118118
`INJECTED_FROM_ENV_FILE=hello\n`,
119119
].join(``));
120120

Diff for: packages/plugin-essentials/sources/commands/install.ts

+20-18
Original file line numberDiff line numberDiff line change
@@ -519,30 +519,32 @@ async function autofixLegacyPlugins(configuration: Configuration, immutable: boo
519519
const legacyPlugins: Array<PortablePath> = [];
520520
const yarnPluginDir = ppath.join(configuration.projectCwd, `.yarn/plugins/@yarnpkg`);
521521

522-
const changed = await Configuration.updateConfiguration(configuration.projectCwd, current => {
523-
if (!Array.isArray(current.plugins))
524-
return current;
522+
const changed = await Configuration.updateConfiguration(configuration.projectCwd, {
523+
plugins: plugins => {
524+
if (!Array.isArray(plugins))
525+
return plugins;
525526

526-
const plugins = current.plugins.filter((plugin: {spec: string, path: PortablePath}) => {
527-
if (!plugin.path)
528-
return true;
527+
const filteredPlugins = plugins.filter((plugin: {spec: string, path: PortablePath}) => {
528+
if (!plugin.path)
529+
return true;
529530

530-
const resolvedPath = ppath.resolve(configuration.projectCwd!, plugin.path);
531-
const isLegacy = LEGACY_PLUGINS.has(plugin.spec) && ppath.contains(yarnPluginDir, resolvedPath);
531+
const resolvedPath = ppath.resolve(configuration.projectCwd!, plugin.path);
532+
const isLegacy = LEGACY_PLUGINS.has(plugin.spec) && ppath.contains(yarnPluginDir, resolvedPath);
532533

533-
if (isLegacy)
534-
legacyPlugins.push(resolvedPath);
534+
if (isLegacy)
535+
legacyPlugins.push(resolvedPath);
535536

536-
return !isLegacy;
537-
});
537+
return !isLegacy;
538+
});
538539

539-
if (current.plugins.length === plugins.length)
540-
return current;
540+
if (filteredPlugins.length === 0)
541+
return Configuration.deleteProperty;
541542

542-
return {
543-
...current,
544-
plugins,
545-
};
543+
if (filteredPlugins.length === plugins.length)
544+
return plugins;
545+
546+
return filteredPlugins;
547+
},
546548
}, {
547549
immutable,
548550
});

Diff for: packages/plugin-essentials/sources/commands/plugin/remove.ts

+14-12
Original file line numberDiff line numberDiff line change
@@ -51,21 +51,23 @@ export default class PluginRemoveCommand extends BaseCommand {
5151
}
5252

5353
report.reportInfo(MessageName.UNNAMED, `Updating the configuration...`);
54-
await Configuration.updateConfiguration(project.cwd, (current: {[key: string]: unknown}) => {
55-
if (!Array.isArray(current.plugins))
56-
return current;
54+
await Configuration.updateConfiguration(project.cwd, {
55+
plugins: plugins => {
56+
if (!Array.isArray(plugins))
57+
return plugins;
5758

58-
const plugins = current.plugins.filter((plugin: {path: string}) => {
59-
return plugin.path !== relativePath;
60-
});
59+
const filteredPlugins = plugins.filter((plugin: {path: string}) => {
60+
return plugin.path !== relativePath;
61+
});
6162

62-
if (current.plugins.length === plugins.length)
63-
return current;
63+
if (filteredPlugins.length === 0)
64+
return Configuration.deleteProperty;
6465

65-
return {
66-
...current,
67-
plugins,
68-
};
66+
if (filteredPlugins.length === plugins.length)
67+
return plugins;
68+
69+
return filteredPlugins;
70+
},
6971
});
7072
});
7173

Diff for: packages/yarnpkg-core/sources/Configuration.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -540,7 +540,7 @@ export const coreDefinitions: {[coreSettingName: string]: SettingsDefinition} =
540540
injectEnvironmentFiles: {
541541
description: `List of all the environment files that Yarn should inject inside the process when it starts`,
542542
type: SettingsType.ABSOLUTE_PATH,
543-
default: [`.env?`],
543+
default: [`.env.yarn?`],
544544
isArray: true,
545545
},
546546

Diff for: packages/yarnpkg-parsers/sources/syml.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ function isRemovableField(value: any): boolean {
2525
if (typeof value === `undefined`)
2626
return true;
2727

28-
if (typeof value === `object` && value !== null)
28+
if (typeof value === `object` && value !== null && !Array.isArray(value))
2929
return Object.keys(value).every(key => isRemovableField(value[key]));
3030

3131
return false;

0 commit comments

Comments
 (0)