-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements .env file support (#5531)
**What's the problem this PR addresses?** A common need is to provide environment values into the environment via `.env` files. There's been a couple of issues and attempts at implementation already, which all were decently upvoted. I myself could have used it once or twice 😄 Props to @jj811208 for his implementation in #4835 - I wanted to make the configuration a little more generic (allowing to have multiple environment files, and to possibly disable it altogether), but it was a appreciated start. Fixes #4718 Closes #4835 (Supercedes it) **How did you fix it?** A new setting, `injectEnvironmentFiles`, lets you define files that Yarn will load and inject into all scripts. It only affects subprocesses - Yarn itself still uses `process.env` for its checks, so you can't for example set `YARN_*` values and expect them to be applied to the current process (use the yarnrc file for that instead). The `injectEnvironmentFiles` setting has a few properties: - It defaults to `.env` - Nothing will be injected if it's set to an empty array or null - The paths inside may be suffixed by `?` - in that case, Yarn won't throw if the file doesn't exist The idea with this last property is to allow for simple user configuration (imagine, with the example below, that the project also has a gitignore with `.env.*`): ``` injectEnvironmentFiles: - .env - .env.${USER}? ``` **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.
- Loading branch information
Showing
12 changed files
with
213 additions
and
10 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
releases: | ||
"@yarnpkg/cli": major | ||
"@yarnpkg/core": major | ||
"@yarnpkg/fslib": major | ||
"@yarnpkg/plugin-essentials": major | ||
"@yarnpkg/plugin-npm-cli": major | ||
"@yarnpkg/plugin-workspace-tools": major | ||
|
||
declined: | ||
- "@yarnpkg/plugin-compat" | ||
- "@yarnpkg/plugin-constraints" | ||
- "@yarnpkg/plugin-dlx" | ||
- "@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-nm" | ||
- "@yarnpkg/plugin-npm" | ||
- "@yarnpkg/plugin-pack" | ||
- "@yarnpkg/plugin-patch" | ||
- "@yarnpkg/plugin-pnp" | ||
- "@yarnpkg/plugin-pnpm" | ||
- "@yarnpkg/plugin-stage" | ||
- "@yarnpkg/plugin-typescript" | ||
- "@yarnpkg/plugin-version" | ||
- vscode-zipfs | ||
- "@yarnpkg/builder" | ||
- "@yarnpkg/doctor" | ||
- "@yarnpkg/extensions" | ||
- "@yarnpkg/libzip" | ||
- "@yarnpkg/nm" | ||
- "@yarnpkg/pnp" | ||
- "@yarnpkg/pnpify" | ||
- "@yarnpkg/sdks" | ||
- "@yarnpkg/shell" |
113 changes: 113 additions & 0 deletions
113
packages/acceptance-tests/pkg-tests-specs/sources/features/dotEnvFiles.test.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,113 @@ | ||
import {Filename, ppath, xfs} from '@yarnpkg/fslib'; | ||
|
||
describe(`DotEnv files`, () => { | ||
it(`should automatically inject a .env file in the environment`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await run(`install`); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.env`), [ | ||
`INJECTED_FROM_ENV_FILE=hello\n`, | ||
].join(``)); | ||
|
||
await expect(run(`exec`, `env`)).resolves.toMatchObject({ | ||
stdout: expect.stringMatching(/^INJECTED_FROM_ENV_FILE=hello$/m), | ||
}); | ||
})); | ||
|
||
it(`should allow .env variables to be interpolated`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await run(`install`); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.env`), [ | ||
`INJECTED_FROM_ENV_FILE=\${FOO}\n`, | ||
].join(``)); | ||
|
||
await expect(run(`exec`, `env`, {env: {FOO: `foo`}})).resolves.toMatchObject({ | ||
stdout: expect.stringMatching(/^INJECTED_FROM_ENV_FILE=foo$/m), | ||
}); | ||
})); | ||
|
||
it(`should allow .env variables to be used in the next ones`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await run(`install`); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.env`), [ | ||
`INJECTED_FROM_ENV_FILE_1=hello\n`, | ||
`INJECTED_FROM_ENV_FILE_2=\${INJECTED_FROM_ENV_FILE_1} world\n`, | ||
].join(``)); | ||
|
||
await expect(run(`exec`, `env`, {env: {FOO: `foo`}})).resolves.toMatchObject({ | ||
stdout: expect.stringMatching(/^INJECTED_FROM_ENV_FILE_2=hello world$/m), | ||
}); | ||
})); | ||
|
||
it(`shouldn't read the .env if the injectEnvironmentFiles setting is defined`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { | ||
injectEnvironmentFiles: [], | ||
}); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.my-env`), [ | ||
`INJECTED_FROM_ENV_FILE=hello\n`, | ||
].join(``)); | ||
|
||
await run(`install`); | ||
|
||
await expect(run(`exec`, `env`)).resolves.toMatchObject({ | ||
stdout: expect.not.stringMatching(/^INJECTED_FROM_ENV_FILE=/m), | ||
}); | ||
})); | ||
|
||
it(`should allow multiple environment files to be defined`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { | ||
injectEnvironmentFiles: [`.my-env`, `.my-other-env`], | ||
}); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.my-env`), [ | ||
`INJECTED_FROM_ENV_FILE_1=hello\n`, | ||
].join(``)); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.my-other-env`), [ | ||
`INJECTED_FROM_ENV_FILE_2=world\n`, | ||
].join(``)); | ||
|
||
await run(`install`); | ||
|
||
const {stdout} = await run(`exec`, `env`); | ||
|
||
expect(stdout).toMatch(/^INJECTED_FROM_ENV_FILE_1=hello$/m); | ||
expect(stdout).toMatch(/^INJECTED_FROM_ENV_FILE_2=world$/m); | ||
})); | ||
|
||
it(`should let the last environment file override the first`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { | ||
injectEnvironmentFiles: [`.my-env`, `.my-other-env`], | ||
}); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.my-env`), [ | ||
`INJECTED_FROM_ENV_FILE=hello\n`, | ||
].join(``)); | ||
|
||
await xfs.writeFilePromise(ppath.join(path, `.my-other-env`), [ | ||
`INJECTED_FROM_ENV_FILE=world\n`, | ||
].join(``)); | ||
|
||
await run(`install`); | ||
|
||
await expect(run(`exec`, `env`)).resolves.toMatchObject({ | ||
stdout: expect.stringMatching(/^INJECTED_FROM_ENV_FILE=world$/m), | ||
}); | ||
})); | ||
|
||
it(`should throw an error if the settings reference a non-existing file`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { | ||
injectEnvironmentFiles: [`.my-env`], | ||
}); | ||
|
||
await expect(run(`install`)).rejects.toThrow(); | ||
})); | ||
|
||
it(`shouldn't throw an error if the settings reference a non-existing file with a ?-suffixed path`, makeTemporaryEnv({}, async ({path, run, source}) => { | ||
await xfs.writeJsonPromise(ppath.join(path, Filename.rc), { | ||
injectEnvironmentFiles: [`.my-env?`], | ||
}); | ||
|
||
await run(`install`); | ||
})); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters