Skip to content

Commit

Permalink
[cli] Add support for vc deploy --prebuilt command with repo link (#…
Browse files Browse the repository at this point in the history
…10083)

When repo linked, `vc deploy --prebuilt` will change working directory to the Project root directory, instead of the repo root, so that the project's local `.vercel/output` directory is what gets uploaded + deployed.
  • Loading branch information
TooTallNate committed Jun 9, 2023
1 parent fecebfa commit dea58de
Show file tree
Hide file tree
Showing 7 changed files with 109 additions and 53 deletions.
5 changes: 5 additions & 0 deletions .changeset/mighty-grapes-whisper.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'vercel': patch
---

Add support for `vc deploy --prebuilt` command with repo link
110 changes: 60 additions & 50 deletions packages/cli/src/commands/deploy/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -203,56 +203,6 @@ export default async (client: Client): Promise<number> => {
return target;
}

// build `--prebuilt`
if (argv['--prebuilt']) {
const prebuiltExists = await fs.pathExists(join(cwd, '.vercel/output'));
if (!prebuiltExists) {
error(
`The ${param(
'--prebuilt'
)} option was used, but no prebuilt output found in ".vercel/output". Run ${getCommandName(
'build'
)} to generate a local build.`
);
return 1;
}

const prebuiltBuild = await getPrebuiltJson(cwd);

// Ensure that there was not a build error
const prebuiltError =
prebuiltBuild?.error ||
prebuiltBuild?.builds?.find(build => 'error' in build)?.error;
if (prebuiltError) {
output.log(
`Prebuilt deployment cannot be created because ${getCommandName(
'build'
)} failed with error:\n`
);
prettyError(prebuiltError);
return 1;
}

// Ensure that the deploy target matches the build target
const assumedTarget = target || 'preview';
if (prebuiltBuild?.target && prebuiltBuild.target !== assumedTarget) {
let specifyTarget = '';
if (prebuiltBuild.target === 'production') {
specifyTarget = ` --prod`;
}

prettyError({
message: `The ${param(
'--prebuilt'
)} option was used with the target environment "${assumedTarget}", but the prebuilt output found in ".vercel/output" was built with target environment "${
prebuiltBuild.target
}". Please run ${getCommandName(`--prebuilt${specifyTarget}`)}.`,
link: 'https://vercel.link/prebuilt-environment-mismatch',
});
return 1;
}
}

const archive = argv['--archive'];
if (typeof archive === 'string' && !isValidArchive(archive)) {
output.error(`Format must be one of: ${VALID_ARCHIVE_FORMATS.join(', ')}`);
Expand Down Expand Up @@ -355,6 +305,66 @@ export default async (client: Client): Promise<number> => {
throw new Error(`"org" is not defined`);
}

// build `--prebuilt`
if (argv['--prebuilt']) {
// For repo-style linking, update `cwd` to be the Project
// subdirectory when `rootDirectory` setting is defined
if (
link.status === 'linked' &&
link.repoRoot &&
link.project.rootDirectory
) {
cwd = join(cwd, link.project.rootDirectory);
}

const prebuiltExists = await fs.pathExists(join(cwd, '.vercel/output'));
if (!prebuiltExists) {
error(
`The ${param(
'--prebuilt'
)} option was used, but no prebuilt output found in ".vercel/output". Run ${getCommandName(
'build'
)} to generate a local build.`
);
return 1;
}

const prebuiltBuild = await getPrebuiltJson(cwd);

// Ensure that there was not a build error
const prebuiltError =
prebuiltBuild?.error ||
prebuiltBuild?.builds?.find(build => 'error' in build)?.error;
if (prebuiltError) {
output.log(
`Prebuilt deployment cannot be created because ${getCommandName(
'build'
)} failed with error:\n`
);
prettyError(prebuiltError);
return 1;
}

// Ensure that the deploy target matches the build target
const assumedTarget = target || 'preview';
if (prebuiltBuild?.target && prebuiltBuild.target !== assumedTarget) {
let specifyTarget = '';
if (prebuiltBuild.target === 'production') {
specifyTarget = ` --prod`;
}

prettyError({
message: `The ${param(
'--prebuilt'
)} option was used with the target environment "${assumedTarget}", but the prebuilt output found in ".vercel/output" was built with target environment "${
prebuiltBuild.target
}". Please run ${getCommandName(`--prebuilt${specifyTarget}`)}.`,
link: 'https://vercel.link/prebuilt-environment-mismatch',
});
return 1;
}
}

// Set the `contextName` and `currentTeam` as specified by the
// Project Settings, so that API calls happen with the proper scope
const contextName = org.slug;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"orgId": "team_dummy",
"projectId": "build-output-api-failed-before-builds"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"orgId": "team_dummy",
"projectId": "build-output-api-failed-within-build"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"orgId": "team_dummy",
"projectId": "build-output-api-preview"
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"orgId": "team_dummy",
"projectId": "build-output-api-production"
}
31 changes: 28 additions & 3 deletions packages/cli/test/unit/commands/deploy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,14 @@ describe('deploy', () => {
it('should reject deploying when `--prebuilt` is used and `vc build` failed before Builders', async () => {
const cwd = setupUnitFixture('build-output-api-failed-before-builds');

useUser();
useTeams('team_dummy');
useProject({
...defaultProject,
id: 'build-output-api-failed-before-builds',
name: 'build-output-api-failed-before-builds',
});

client.setArgv('deploy', cwd, '--prebuilt');
const exitCodePromise = deploy(client);
await expect(client.stderr).toOutput(
Expand All @@ -56,6 +64,14 @@ describe('deploy', () => {
it('should reject deploying when `--prebuilt` is used and `vc build` failed within a Builder', async () => {
const cwd = setupUnitFixture('build-output-api-failed-within-build');

useUser();
useTeams('team_dummy');
useProject({
...defaultProject,
id: 'build-output-api-failed-within-build',
name: 'build-output-api-failed-within-build',
});

client.setArgv('deploy', cwd, '--prebuilt');
const exitCodePromise = deploy(client);
await expect(client.stderr).toOutput(
Expand All @@ -65,7 +81,16 @@ describe('deploy', () => {
});

it('should reject deploying a directory that does not contain ".vercel/output" when `--prebuilt` is used', async () => {
client.setArgv('deploy', __dirname, '--prebuilt');
useUser();
useTeams('team_dummy');
useProject({
...defaultProject,
name: 'static',
id: 'static',
});

client.cwd = setupUnitFixture('commands/deploy/static');
client.setArgv('deploy', '--prebuilt');
const exitCodePromise = deploy(client);
await expect(client.stderr).toOutput(
'Error: The "--prebuilt" option was used, but no prebuilt output found in ".vercel/output". Run `vercel build` to generate a local build.\n'
Expand Down Expand Up @@ -102,8 +127,8 @@ describe('deploy', () => {
useTeams('team_dummy');
useProject({
...defaultProject,
id: 'build-output-api-preview',
name: 'build-output-api-preview',
id: 'build-output-api-production',
name: 'build-output-api-production',
});

client.setArgv('deploy', cwd, '--prebuilt');
Expand Down

0 comments on commit dea58de

Please sign in to comment.