Revert "Revert "[cli] Add support for vc pull command with repo link"" (#10078)

Reverts vercel/vercel#10076

Restores the original PR: https://github.com/vercel/vercel/pull/10071

With the fix from: https://github.com/vercel/vercel/pull/10073
This commit is contained in:
Sean Massa
2023-06-07 02:49:45 -05:00
committed by GitHub
parent 6107c1ed22
commit 709c9509f4
9 changed files with 85 additions and 35 deletions

View File

@@ -0,0 +1,5 @@
---
'vercel': patch
---
Add support for `vc pull` command with repo link

View File

@@ -398,20 +398,35 @@ export interface PaginationOptions {
prev: number | null; prev: number | null;
} }
export type ProjectLinked = {
status: 'linked';
org: Org;
project: Project;
repoRoot?: string;
};
export type ProjectNotLinked = {
status: 'not_linked';
org: null;
project: null;
};
export type ProjectLinkedError = {
status: 'error';
exitCode: number;
reason?:
| 'HEADLESS'
| 'NOT_AUTHORIZED'
| 'TEAM_DELETED'
| 'PATH_IS_FILE'
| 'INVALID_ROOT_DIRECTORY'
| 'MISSING_PROJECT_SETTINGS';
};
export type ProjectLinkResult = export type ProjectLinkResult =
| { status: 'linked'; org: Org; project: Project; repoRoot?: string } | ProjectLinked
| { status: 'not_linked'; org: null; project: null } | ProjectNotLinked
| { | ProjectLinkedError;
status: 'error';
exitCode: number;
reason?:
| 'HEADLESS'
| 'NOT_AUTHORIZED'
| 'TEAM_DELETED'
| 'PATH_IS_FILE'
| 'INVALID_ROOT_DIRECTORY'
| 'MISSING_PROJECT_SETTINGS';
};
/** /**
* @deprecated - `RollbackJobStatus` has been replace by `LastAliasRequest['jobStatus']`. * @deprecated - `RollbackJobStatus` has been replace by `LastAliasRequest['jobStatus']`.

View File

@@ -15,6 +15,7 @@ import {
getEnvTargetPlaceholder, getEnvTargetPlaceholder,
} from '../util/env/env-target'; } from '../util/env/env-target';
import { ensureLink } from '../util/link/ensure-link'; import { ensureLink } from '../util/link/ensure-link';
import humanizePath from '../util/humanize-path';
const help = () => { const help = () => {
return console.log(` return console.log(`
@@ -115,7 +116,7 @@ export default async function main(client: Client) {
return argv; return argv;
} }
const cwd = argv._[1] || process.cwd(); let cwd = argv._[1] || process.cwd();
const autoConfirm = Boolean(argv['--yes']); const autoConfirm = Boolean(argv['--yes']);
const environment = parseEnvironment(argv['--environment'] || undefined); const environment = parseEnvironment(argv['--environment'] || undefined);
@@ -124,7 +125,11 @@ export default async function main(client: Client) {
return link; return link;
} }
const { project, org } = link; const { project, org, repoRoot } = link;
if (repoRoot) {
cwd = join(repoRoot, project.rootDirectory || '');
}
client.config.currentTeam = org.type === 'team' ? org.id : undefined; client.config.currentTeam = org.type === 'team' ? org.id : undefined;
@@ -141,13 +146,14 @@ export default async function main(client: Client) {
client.output.print('\n'); client.output.print('\n');
client.output.log('Downloading project settings'); client.output.log('Downloading project settings');
await writeProjectSettings(cwd, project, org); const isRepoLinked = typeof repoRoot === 'string';
await writeProjectSettings(cwd, project, org, isRepoLinked);
const settingsStamp = stamp(); const settingsStamp = stamp();
client.output.print( client.output.print(
`${prependEmoji( `${prependEmoji(
`Downloaded project settings to ${chalk.bold( `Downloaded project settings to ${chalk.bold(
join(VERCEL_DIR, VERCEL_DIR_PROJECT) humanizePath(join(cwd, VERCEL_DIR, VERCEL_DIR_PROJECT))
)} ${chalk.gray(settingsStamp())}`, )} ${chalk.gray(settingsStamp())}`,
emoji('success') emoji('success')
)}\n` )}\n`

View File

@@ -1,15 +1,10 @@
import { Org, Project } from '@vercel-internals/types';
import Client from '../client'; import Client from '../client';
import setupAndLink from '../link/setup-and-link'; import setupAndLink from '../link/setup-and-link';
import param from '../output/param'; import param from '../output/param';
import { getCommandName } from '../pkg-name'; import { getCommandName } from '../pkg-name';
import { getLinkedProject } from '../projects/link'; import { getLinkedProject } from '../projects/link';
import type { SetupAndLinkOptions } from '../link/setup-and-link'; import type { SetupAndLinkOptions } from '../link/setup-and-link';
import type { ProjectLinked } from '@vercel-internals/types';
type LinkResult = {
org: Org;
project: Project;
};
/** /**
* Checks if a project is already linked and if not, links the project and * Checks if a project is already linked and if not, links the project and
@@ -31,7 +26,7 @@ export async function ensureLink(
client: Client, client: Client,
cwd: string, cwd: string,
opts: SetupAndLinkOptions opts: SetupAndLinkOptions
): Promise<LinkResult | number> { ): Promise<ProjectLinked | number> {
let { link } = opts; let { link } = opts;
if (!link) { if (!link) {
link = await getLinkedProject(client, cwd); link = await getLinkedProject(client, cwd);
@@ -61,5 +56,5 @@ export async function ensureLink(
return link.exitCode; return link.exitCode;
} }
return { org: link.org, project: link.project }; return link;
} }

View File

@@ -195,7 +195,10 @@ export async function ensureRepoLink(
await writeFile( await writeFile(
join(rootPath, VERCEL_DIR, VERCEL_DIR_README), join(rootPath, VERCEL_DIR, VERCEL_DIR_README),
await readFile(join(__dirname, 'VERCEL_DIR_README.txt'), 'utf8') await readFile(
join(__dirname, '..', 'projects', 'VERCEL_DIR_README.txt'),
'utf8'
)
); );
// update .gitignore // update .gitignore

View File

@@ -5,7 +5,7 @@ import { join } from 'path';
import { VercelConfig } from '@vercel/client'; import { VercelConfig } from '@vercel/client';
import { PartialProjectSettings } from '../input/edit-project-settings'; import { PartialProjectSettings } from '../input/edit-project-settings';
export type ProjectLinkAndSettings = ProjectLink & { export type ProjectLinkAndSettings = Partial<ProjectLink> & {
settings: { settings: {
createdAt: Project['createdAt']; createdAt: Project['createdAt'];
installCommand: Project['installCommand']; installCommand: Project['installCommand'];
@@ -26,7 +26,8 @@ export type ProjectLinkAndSettings = ProjectLink & {
export async function writeProjectSettings( export async function writeProjectSettings(
cwd: string, cwd: string,
project: Project, project: Project,
org: Org org: Org,
isRepoLinked: boolean
) { ) {
let analyticsId: string | undefined; let analyticsId: string | undefined;
if ( if (
@@ -39,8 +40,8 @@ export async function writeProjectSettings(
} }
const projectLinkAndSettings: ProjectLinkAndSettings = { const projectLinkAndSettings: ProjectLinkAndSettings = {
projectId: project.id, projectId: isRepoLinked ? undefined : project.id,
orgId: org.id, orgId: isRepoLinked ? undefined : org.id,
settings: { settings: {
createdAt: project.createdAt, createdAt: project.createdAt,
framework: project.framework, framework: project.framework,

View File

@@ -47,7 +47,7 @@ export function setupTmpDir(fixtureName?: string) {
const cwd = path.join(tempRoot.name, String(tempNumber++), fixtureName ?? ''); const cwd = path.join(tempRoot.name, String(tempNumber++), fixtureName ?? '');
fs.mkdirpSync(cwd); fs.mkdirpSync(cwd);
return cwd; return fs.realpathSync(cwd);
} }
export function cleanupFixtures() { export function cleanupFixtures() {

View File

@@ -26,7 +26,7 @@ describe('pull', () => {
`Created .vercel${path.sep}.env.development.local file` `Created .vercel${path.sep}.env.development.local file`
); );
await expect(client.stderr).toOutput( await expect(client.stderr).toOutput(
`Downloaded project settings to .vercel${path.sep}project.json` `Downloaded project settings to ${cwd}${path.sep}.vercel${path.sep}project.json`
); );
await expect(exitCodePromise).resolves.toEqual(0); await expect(exitCodePromise).resolves.toEqual(0);
@@ -92,7 +92,7 @@ describe('pull', () => {
`Created .vercel${path.sep}.env.development.local file` `Created .vercel${path.sep}.env.development.local file`
); );
await expect(client.stderr).toOutput( await expect(client.stderr).toOutput(
`Downloaded project settings to .vercel${path.sep}project.json` `Downloaded project settings to ${cwd}${path.sep}.vercel${path.sep}project.json`
); );
await expect(exitCodePromise).resolves.toEqual(0); await expect(exitCodePromise).resolves.toEqual(0);
@@ -130,7 +130,7 @@ describe('pull', () => {
`Created .vercel${path.sep}.env.preview.local file` `Created .vercel${path.sep}.env.preview.local file`
); );
await expect(client.stderr).toOutput( await expect(client.stderr).toOutput(
`Downloaded project settings to .vercel${path.sep}project.json` `Downloaded project settings to ${cwd}${path.sep}.vercel${path.sep}project.json`
); );
await expect(exitCodePromise).resolves.toEqual(0); await expect(exitCodePromise).resolves.toEqual(0);
@@ -161,7 +161,7 @@ describe('pull', () => {
`Created .vercel${path.sep}.env.production.local file` `Created .vercel${path.sep}.env.production.local file`
); );
await expect(client.stderr).toOutput( await expect(client.stderr).toOutput(
`Downloaded project settings to .vercel${path.sep}project.json` `Downloaded project settings to ${cwd}${path.sep}.vercel${path.sep}project.json`
); );
await expect(exitCodePromise).resolves.toEqual(0); await expect(exitCodePromise).resolves.toEqual(0);
@@ -177,4 +177,29 @@ describe('pull', () => {
.includes('SQL_CONNECTION_STRING'); .includes('SQL_CONNECTION_STRING');
expect(previewFileHasPreviewEnv2).toBeTruthy(); expect(previewFileHasPreviewEnv2).toBeTruthy();
}); });
it('should work with repo link', async () => {
const cwd = setupUnitFixture('monorepo-link');
useUser();
useTeams('team_dummy');
useProject({
...defaultProject,
id: 'QmbKpqpiUqbcke',
name: 'dashboard',
rootDirectory: 'dashboard',
});
client.cwd = path.join(cwd, 'dashboard');
client.setArgv('pull');
const exitCodePromise = pull(client);
await expect(client.stderr).toOutput(
'Downloading `development` Environment Variables for Project dashboard'
);
await expect(client.stderr).toOutput(
`Created .vercel${path.sep}.env.development.local file`
);
await expect(client.stderr).toOutput(
`Downloaded project settings to ${cwd}${path.sep}dashboard${path.sep}.vercel${path.sep}project.json`
);
await expect(exitCodePromise).resolves.toEqual(0);
});
}); });