mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-06 04:22:01 +00:00
[cli] Change vc env pull default output file to .env.local (#9892)
`vc deploy` ignores `.env.local`. To make sure we don't inadvertently push people's secrets to source control, have all environment pulls default to writing to `.env.local`.
This commit is contained in:
5
.changeset/neat-otters-happen.md
Normal file
5
.changeset/neat-otters-happen.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'vercel': major
|
||||
---
|
||||
|
||||
Change `vc env pull` default output file to `.env.local`
|
||||
@@ -4,7 +4,7 @@
|
||||
|
||||
You ran `vercel dev` inside a project that contains a `vercel.json` file with `env` or `build.env` properties that use [Vercel Secrets](https://vercel.com/docs/concepts/projects/environment-variables).
|
||||
|
||||
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env`.
|
||||
In order to use environment variables in your project locally that have values defined using the Vercel Secrets format (e.g. `@my-secret-value`), you will need to provide the value as an environment variable using a `.env.local`.
|
||||
|
||||
We require this to ensure your app works as you intend it to, in the development environment, and to provide you with a way to mirror or separate private environment variables within your applications, for example when connecting to a database.
|
||||
|
||||
@@ -12,11 +12,11 @@ Read below for how to address this error.
|
||||
|
||||
#### Possible Ways to Fix It
|
||||
|
||||
The error message will list environment variables that are required and which file they are required to be included in `.env`.
|
||||
The error message will list environment variables that are required and which file they are required to be included in `.env.local`.
|
||||
|
||||
If the file does not exist yet, please create the file that the error message mentions and insert the missing environment variable into it.
|
||||
|
||||
For example, if the error message shows that the environment variable `TEST` is missing from `.env`, then the `.env` file should look like this:
|
||||
For example, if the error message shows that the environment variable `TEST` is missing from `.env.local`, then the `.env.local` file should look like this:
|
||||
|
||||
```
|
||||
TEST=value
|
||||
|
||||
2
packages/cli/src/commands/env/index.ts
vendored
2
packages/cli/src/commands/env/index.ts
vendored
@@ -26,7 +26,7 @@ const help = () => {
|
||||
ls [environment] [gitbranch] List all variables for the specified Environment
|
||||
add [name] [environment] [gitbranch] Add an Environment Variable (see examples below)
|
||||
rm [name] [environment] [gitbranch] Remove an Environment Variable (see examples below)
|
||||
pull [filename] Pull all Development Environment Variables from the cloud and write to a file [.env]
|
||||
pull [filename] Pull all Development Environment Variables from the cloud and write to a file [.env.local]
|
||||
|
||||
${chalk.dim('Options:')}
|
||||
|
||||
|
||||
2
packages/cli/src/commands/env/pull.ts
vendored
2
packages/cli/src/commands/env/pull.ts
vendored
@@ -67,7 +67,7 @@ export default async function pull(
|
||||
}
|
||||
|
||||
// handle relative or absolute filename
|
||||
const [filename = '.env'] = args;
|
||||
const [filename = '.env.local'] = args;
|
||||
const fullPath = resolve(cwd, filename);
|
||||
const skipConfirmation = opts['--yes'];
|
||||
const gitBranch = opts['--git-branch'];
|
||||
|
||||
18
packages/cli/test/integration-1.test.ts
vendored
18
packages/cli/test/integration-1.test.ts
vendored
@@ -751,9 +751,9 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
);
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
|
||||
expect(stderr).toMatch(/Created .env file/gm);
|
||||
expect(stderr).toMatch(/Created .env.local file/gm);
|
||||
|
||||
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
||||
const contents = fs.readFileSync(path.join(target, '.env.local'), 'utf8');
|
||||
expect(contents).toMatch(/^# Created by Vercel CLI\n/);
|
||||
expect(contents).toMatch(/MY_NEW_ENV_VAR="my plaintext value"/);
|
||||
expect(contents).toMatch(/MY_STDIN_VAR="{"expect":"quotes"}"/);
|
||||
@@ -771,12 +771,12 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
);
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
|
||||
expect(stderr).toMatch(/Overwriting existing .env file/gm);
|
||||
expect(stderr).toMatch(/Updated .env file/gm);
|
||||
expect(stderr).toMatch(/Overwriting existing .env.local file/gm);
|
||||
expect(stderr).toMatch(/Updated .env.local file/gm);
|
||||
}
|
||||
|
||||
async function vcEnvPullConfirm() {
|
||||
fs.writeFileSync(path.join(target, '.env'), 'hahaha');
|
||||
fs.writeFileSync(path.join(target, '.env.local'), 'hahaha');
|
||||
|
||||
const vc = execCli(binaryPath, ['env', 'pull'], {
|
||||
cwd: target,
|
||||
@@ -784,7 +784,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
|
||||
await waitForPrompt(
|
||||
vc,
|
||||
'Found existing file ".env". Do you want to overwrite?'
|
||||
'Found existing file ".env.local". Do you want to overwrite?'
|
||||
);
|
||||
vc.stdin?.end('y\n');
|
||||
|
||||
@@ -904,7 +904,7 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
|
||||
expect(exitCode, formatOutput({ stdout, stderr })).toBe(0);
|
||||
|
||||
const contents = fs.readFileSync(path.join(target, '.env'), 'utf8');
|
||||
const contents = fs.readFileSync(path.join(target, '.env.local'), 'utf8');
|
||||
|
||||
const lines = new Set(contents.split('\n'));
|
||||
|
||||
@@ -1024,11 +1024,11 @@ test('Deploy `api-env` fixture and test `vercel env` command', async () => {
|
||||
await vcEnvPullConfirm();
|
||||
await vcDeployWithVar();
|
||||
await vcDevWithEnv();
|
||||
fs.unlinkSync(path.join(target, '.env'));
|
||||
fs.unlinkSync(path.join(target, '.env.local'));
|
||||
await vcDevAndFetchCloudVars();
|
||||
await enableAutoExposeSystemEnvs();
|
||||
await vcEnvPullFetchSystemVars();
|
||||
fs.unlinkSync(path.join(target, '.env'));
|
||||
fs.unlinkSync(path.join(target, '.env.local'));
|
||||
await vcDevAndFetchSystemVars();
|
||||
await vcEnvRemove();
|
||||
await vcEnvRemoveWithArgs();
|
||||
|
||||
@@ -24,10 +24,10 @@ describe('env', () => {
|
||||
await expect(client.stderr).toOutput(
|
||||
'Downloading `development` Environment Variables for Project vercel-env-pull'
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created .env file');
|
||||
await expect(client.stderr).toOutput('Created .env.local file');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env'));
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env.local'));
|
||||
|
||||
// check for development env value
|
||||
const devFileHasDevEnv = rawDevEnv.toString().includes('SPECIAL_FLAG');
|
||||
@@ -56,11 +56,11 @@ describe('env', () => {
|
||||
await expect(client.stderr).toOutput(
|
||||
'Downloading `preview` Environment Variables for Project vercel-env-pull'
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created .env file');
|
||||
await expect(client.stderr).toOutput('Created .env.local file');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
|
||||
// check for Preview env vars
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env'), 'utf8');
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env.local'), 'utf8');
|
||||
expect(rawDevEnv).toContain(
|
||||
'REDIS_CONNECTION_STRING="redis://abc123@redis.example.com:6379"'
|
||||
);
|
||||
@@ -93,11 +93,11 @@ describe('env', () => {
|
||||
await expect(client.stderr).toOutput(
|
||||
'Downloading `preview` Environment Variables for Project vercel-env-pull'
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created .env file');
|
||||
await expect(client.stderr).toOutput('Created .env.local file');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
|
||||
// check for Preview env vars
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env'), 'utf8');
|
||||
const rawDevEnv = await fs.readFile(path.join(cwd, '.env.local'), 'utf8');
|
||||
expect(rawDevEnv).toContain(
|
||||
'REDIS_CONNECTION_STRING="redis://abc123@redis.example.com:6379"'
|
||||
);
|
||||
@@ -159,10 +159,10 @@ describe('env', () => {
|
||||
await expect(client.stderr).toOutput(
|
||||
`Downloading \`production\` Environment Variables for Project vercel-env-pull`
|
||||
);
|
||||
await expect(client.stderr).toOutput('Created .env file');
|
||||
await expect(client.stderr).toOutput('Created .env.local file');
|
||||
await expect(exitCodePromise).resolves.toEqual(0);
|
||||
|
||||
const rawProdEnv = await fs.readFile(path.join(cwd, '.env'));
|
||||
const rawProdEnv = await fs.readFile(path.join(cwd, '.env.local'));
|
||||
|
||||
// check for development env value
|
||||
const envFileHasEnv = rawProdEnv
|
||||
@@ -261,7 +261,7 @@ describe('env', () => {
|
||||
await expect(client.stderr).toOutput(
|
||||
'+ SPECIAL_FLAG (Updated)\n+ NEW_VAR\n- TEST\n'
|
||||
);
|
||||
await expect(client.stderr).toOutput('Updated .env file');
|
||||
await expect(client.stderr).toOutput('Updated .env.local file');
|
||||
|
||||
await expect(pullPromise).resolves.toEqual(0);
|
||||
} finally {
|
||||
@@ -282,7 +282,7 @@ describe('env', () => {
|
||||
|
||||
client.setArgv('env', 'pull', '--yes', '--cwd', cwd);
|
||||
const pullPromise = env(client);
|
||||
await expect(client.stderr).toOutput('Updated .env file');
|
||||
await expect(client.stderr).toOutput('Updated .env.local file');
|
||||
await expect(pullPromise).resolves.toEqual(0);
|
||||
});
|
||||
|
||||
@@ -299,7 +299,7 @@ describe('env', () => {
|
||||
client.setArgv('env', 'pull', '--yes', '--cwd', cwd);
|
||||
const pullPromise = env(client);
|
||||
await expect(client.stderr).toOutput('> No changes found.');
|
||||
await expect(client.stderr).toOutput('Updated .env file');
|
||||
await expect(client.stderr).toOutput('Updated .env.local file');
|
||||
await expect(pullPromise).resolves.toEqual(0);
|
||||
});
|
||||
|
||||
@@ -335,7 +335,7 @@ describe('env', () => {
|
||||
'Downloading `development` Environment Variables for Project env-pull-delta'
|
||||
);
|
||||
await expect(client.stderr).toOutput('No changes found.\n');
|
||||
await expect(client.stderr).toOutput('Updated .env file');
|
||||
await expect(client.stderr).toOutput('Updated .env.local file');
|
||||
|
||||
await expect(pullPromise).resolves.toEqual(0);
|
||||
} finally {
|
||||
|
||||
Reference in New Issue
Block a user