mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-10 12:57:47 +00:00
This PR adds a new message to the end of `vc env pull` which shows delta of what was added, changed, and removed. Example: you have a local `.env` file in a directory linked to a Vercel project. You change `TEST_1`, remove `TEST_2` via `vc env rm TEST_2`, and add `TEST_3` via `vc env add`. Then you run `vc env pull`. Here's what you will see: ``` > Updating existing .env file > Downloading `development` Environment Variables for Project name ✅ Updated .env file + TEST_3 ~ TEST_1 - TEST_2 ``` <img width="562" alt="Screen Shot 2022-07-20 at 11 09 56 AM" src="https://user-images.githubusercontent.com/14811170/180064534-2ff5facb-95cb-4712-aaad-cbb47490cebe.png"> ### 📋 Checklist <!-- Please keep your PR as a Draft until the checklist is complete --> #### Tests - [x] The code changed/added as part of this PR has been covered with tests - [x] All tests pass locally with `yarn test-unit` #### Code Review - [ ] This PR has a concise title and thorough description useful to a reviewer - [ ] Issue from task tracker has a link to this PR
181 lines
6.0 KiB
TypeScript
181 lines
6.0 KiB
TypeScript
import fs from 'fs-extra';
|
|
import path from 'path';
|
|
import pull from '../../../src/commands/pull';
|
|
import { setupFixture } from '../../helpers/setup-fixture';
|
|
import { client } from '../../mocks/client';
|
|
import { defaultProject, useProject } from '../../mocks/project';
|
|
import { useTeams } from '../../mocks/team';
|
|
import { useUser } from '../../mocks/user';
|
|
|
|
describe('pull', () => {
|
|
it('should handle pulling', async () => {
|
|
const cwd = setupFixture('vercel-pull-next');
|
|
useUser();
|
|
useTeams('team_dummy');
|
|
useProject({
|
|
...defaultProject,
|
|
id: 'vercel-pull-next',
|
|
name: 'vercel-pull-next',
|
|
});
|
|
client.setArgv('pull', cwd);
|
|
const exitCodePromise = pull(client);
|
|
await expect(client.stderr).toOutput(
|
|
'Downloading `development` Environment Variables for Project vercel-pull-next'
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Created .vercel${path.sep}.env.development.local file`
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Downloaded project settings to .vercel${path.sep}project.json`
|
|
);
|
|
await expect(exitCodePromise).resolves.toEqual(0);
|
|
|
|
const rawDevEnv = await fs.readFile(
|
|
path.join(cwd, '.vercel', '.env.development.local')
|
|
);
|
|
const devFileHasDevEnv = rawDevEnv.toString().includes('SPECIAL_FLAG');
|
|
expect(devFileHasDevEnv).toBeTruthy();
|
|
});
|
|
|
|
it('should fail with message to pull without a link and without --env', async () => {
|
|
client.stdin.isTTY = false;
|
|
|
|
const cwd = setupFixture('vercel-pull-unlinked');
|
|
useUser();
|
|
useTeams('team_dummy');
|
|
|
|
client.setArgv('pull', cwd);
|
|
const exitCodePromise = pull(client);
|
|
await expect(client.stderr).toOutput(
|
|
'Command `vercel pull` requires confirmation. Use option "--yes" to confirm.'
|
|
);
|
|
await expect(exitCodePromise).resolves.toEqual(1);
|
|
});
|
|
|
|
it('should fail without message to pull without a link and with --env', async () => {
|
|
const cwd = setupFixture('vercel-pull-next');
|
|
useUser();
|
|
useTeams('team_dummy');
|
|
|
|
client.setArgv('pull', cwd, '--yes');
|
|
const exitCodePromise = pull(client);
|
|
await expect(client.stderr).not.toOutput(
|
|
'Command `vercel pull` requires confirmation. Use option "--yes" to confirm.'
|
|
);
|
|
await expect(exitCodePromise).resolves.toEqual(1);
|
|
});
|
|
|
|
it('should handle pulling with env vars (headless mode)', async () => {
|
|
try {
|
|
process.env.VERCEL_PROJECT_ID = 'vercel-pull-next';
|
|
process.env.VERCEL_ORG_ID = 'team_dummy';
|
|
|
|
const cwd = setupFixture('vercel-pull-next');
|
|
|
|
// Remove the `.vercel` dir to ensure that the `pull`
|
|
// command creates a new one based on env vars
|
|
await fs.remove(path.join(cwd, '.vercel'));
|
|
|
|
useUser();
|
|
useTeams('team_dummy');
|
|
useProject({
|
|
...defaultProject,
|
|
id: 'vercel-pull-next',
|
|
name: 'vercel-pull-next',
|
|
});
|
|
client.setArgv('pull', cwd);
|
|
const exitCodePromise = pull(client);
|
|
await expect(client.stderr).toOutput(
|
|
'Downloading `development` Environment Variables for Project vercel-pull-next'
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Created .vercel${path.sep}.env.development.local file`
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Downloaded project settings to .vercel${path.sep}project.json`
|
|
);
|
|
await expect(exitCodePromise).resolves.toEqual(0);
|
|
|
|
const config = await fs.readJSON(path.join(cwd, '.vercel/project.json'));
|
|
expect(config).toMatchInlineSnapshot(`
|
|
Object {
|
|
"orgId": "team_dummy",
|
|
"projectId": "vercel-pull-next",
|
|
"settings": Object {
|
|
"createdAt": 1555413045188,
|
|
},
|
|
}
|
|
`);
|
|
} finally {
|
|
delete process.env.VERCEL_PROJECT_ID;
|
|
delete process.env.VERCEL_ORG_ID;
|
|
}
|
|
});
|
|
|
|
it('should handle --environment=preview flag', async () => {
|
|
const cwd = setupFixture('vercel-pull-next');
|
|
useUser();
|
|
useTeams('team_dummy');
|
|
useProject({
|
|
...defaultProject,
|
|
id: 'vercel-pull-next',
|
|
name: 'vercel-pull-next',
|
|
});
|
|
client.setArgv('pull', '--environment=preview', cwd);
|
|
const exitCodePromise = pull(client);
|
|
await expect(client.stderr).toOutput(
|
|
'Downloading `preview` Environment Variables for Project vercel-pull-next'
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Created .vercel${path.sep}.env.preview.local file`
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Downloaded project settings to .vercel${path.sep}project.json`
|
|
);
|
|
await expect(exitCodePromise).resolves.toEqual(0);
|
|
|
|
const rawPreviewEnv = await fs.readFile(
|
|
path.join(cwd, '.vercel', '.env.preview.local')
|
|
);
|
|
const previewFileHasPreviewEnv = rawPreviewEnv
|
|
.toString()
|
|
.includes('REDIS_CONNECTION_STRING');
|
|
expect(previewFileHasPreviewEnv).toBeTruthy();
|
|
});
|
|
|
|
it('should handle --environment=production flag', async () => {
|
|
const cwd = setupFixture('vercel-pull-next');
|
|
useUser();
|
|
useTeams('team_dummy');
|
|
useProject({
|
|
...defaultProject,
|
|
id: 'vercel-pull-next',
|
|
name: 'vercel-pull-next',
|
|
});
|
|
client.setArgv('pull', '--environment=production', cwd);
|
|
const exitCodePromise = pull(client);
|
|
await expect(client.stderr).toOutput(
|
|
'Downloading `production` Environment Variables for Project vercel-pull-next'
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Created .vercel${path.sep}.env.production.local file`
|
|
);
|
|
await expect(client.stderr).toOutput(
|
|
`Downloaded project settings to .vercel${path.sep}project.json`
|
|
);
|
|
await expect(exitCodePromise).resolves.toEqual(0);
|
|
|
|
const rawProdEnv = await fs.readFile(
|
|
path.join(cwd, '.vercel', '.env.production.local')
|
|
);
|
|
const previewFileHasPreviewEnv1 = rawProdEnv
|
|
.toString()
|
|
.includes('REDIS_CONNECTION_STRING');
|
|
expect(previewFileHasPreviewEnv1).toBeTruthy();
|
|
const previewFileHasPreviewEnv2 = rawProdEnv
|
|
.toString()
|
|
.includes('SQL_CONNECTION_STRING');
|
|
expect(previewFileHasPreviewEnv2).toBeTruthy();
|
|
});
|
|
});
|