mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-06 04:22:01 +00:00
Moves the type file out of the cli package and into its own standalone package. utilizes `@vercel/style-guide` too for typescript config, eslint, and prettier.
244 lines
6.0 KiB
TypeScript
244 lines
6.0 KiB
TypeScript
import bytes from 'bytes';
|
|
import chalk from 'chalk';
|
|
import {
|
|
ArchiveFormat,
|
|
createDeployment,
|
|
DeploymentOptions,
|
|
VercelClientOptions,
|
|
} from '@vercel/client';
|
|
import { Output } from '../output';
|
|
import { progress } from '../output/progress';
|
|
import Now from '../../util';
|
|
import { Org } from '@vercel-internals/types';
|
|
import ua from '../ua';
|
|
import { linkFolderToProject } from '../projects/link';
|
|
import { prependEmoji, emoji } from '../emoji';
|
|
|
|
function printInspectUrl(
|
|
output: Output,
|
|
inspectorUrl: string,
|
|
deployStamp: () => string
|
|
) {
|
|
output.print(
|
|
prependEmoji(
|
|
`Inspect: ${chalk.bold(inspectorUrl)} ${deployStamp()}`,
|
|
emoji('inspect')
|
|
) + `\n`
|
|
);
|
|
}
|
|
|
|
export default async function processDeployment({
|
|
org,
|
|
cwd,
|
|
projectName,
|
|
isSettingUpProject,
|
|
archive,
|
|
skipAutoDetectionConfirmation,
|
|
...args
|
|
}: {
|
|
now: Now;
|
|
output: Output;
|
|
paths: string[];
|
|
requestBody: DeploymentOptions;
|
|
uploadStamp: () => string;
|
|
deployStamp: () => string;
|
|
quiet: boolean;
|
|
force?: boolean;
|
|
withCache?: boolean;
|
|
org: Org;
|
|
prebuilt: boolean;
|
|
projectName: string;
|
|
isSettingUpProject: boolean;
|
|
archive?: ArchiveFormat;
|
|
skipAutoDetectionConfirmation?: boolean;
|
|
cwd?: string;
|
|
rootDirectory?: string;
|
|
}) {
|
|
let {
|
|
now,
|
|
output,
|
|
paths,
|
|
requestBody,
|
|
deployStamp,
|
|
force,
|
|
withCache,
|
|
quiet,
|
|
prebuilt,
|
|
rootDirectory,
|
|
} = args;
|
|
|
|
const { debug } = output;
|
|
|
|
const { env = {} } = requestBody;
|
|
|
|
const token = now._token;
|
|
if (!token) {
|
|
throw new Error('Missing authentication token');
|
|
}
|
|
|
|
const clientOptions: VercelClientOptions = {
|
|
teamId: org.type === 'team' ? org.id : undefined,
|
|
apiUrl: now._apiUrl,
|
|
token,
|
|
debug: now._debug,
|
|
userAgent: ua,
|
|
path: paths[0],
|
|
force,
|
|
withCache,
|
|
prebuilt,
|
|
rootDirectory,
|
|
skipAutoDetectionConfirmation,
|
|
archive,
|
|
};
|
|
|
|
const deployingSpinnerVal = isSettingUpProject
|
|
? 'Setting up project'
|
|
: `Deploying ${chalk.bold(`${org.slug}/${projectName}`)}`;
|
|
output.spinner(deployingSpinnerVal, 0);
|
|
|
|
// collect indications to show the user once
|
|
// the deployment is done
|
|
const indications = [];
|
|
|
|
try {
|
|
for await (const event of createDeployment(clientOptions, requestBody)) {
|
|
if (['tip', 'notice', 'warning'].includes(event.type)) {
|
|
indications.push(event);
|
|
}
|
|
|
|
if (event.type === 'file-count') {
|
|
const { total, missing, uploads } = event.payload;
|
|
debug(`Total files ${total.size}, ${missing.length} changed`);
|
|
|
|
const missingSize = missing
|
|
.map((sha: string) => total.get(sha).data.length)
|
|
.reduce((a: number, b: number) => a + b, 0);
|
|
const totalSizeHuman = bytes.format(missingSize, { decimalPlaces: 1 });
|
|
|
|
// When stderr is not a TTY then we only want to
|
|
// print upload progress in 25% increments
|
|
let nextStep = 0;
|
|
const stepSize = now._client.stderr.isTTY ? 0 : 0.25;
|
|
|
|
const updateProgress = () => {
|
|
const uploadedBytes = uploads.reduce((acc: number, e: any) => {
|
|
return acc + e.bytesUploaded;
|
|
}, 0);
|
|
|
|
const bar = progress(uploadedBytes, missingSize);
|
|
if (!bar) {
|
|
output.spinner(deployingSpinnerVal, 0);
|
|
} else {
|
|
const uploadedHuman = bytes.format(uploadedBytes, {
|
|
decimalPlaces: 1,
|
|
fixedDecimals: true,
|
|
});
|
|
const percent = uploadedBytes / missingSize;
|
|
if (percent >= nextStep) {
|
|
output.spinner(
|
|
`Uploading ${chalk.reset(
|
|
`[${bar}] (${uploadedHuman}/${totalSizeHuman})`
|
|
)}`,
|
|
0
|
|
);
|
|
nextStep += stepSize;
|
|
}
|
|
}
|
|
};
|
|
|
|
uploads.forEach((e: any) => e.on('progress', updateProgress));
|
|
updateProgress();
|
|
}
|
|
|
|
if (event.type === 'file-uploaded') {
|
|
debug(
|
|
`Uploaded: ${event.payload.file.names.join(' ')} (${bytes(
|
|
event.payload.file.data.length
|
|
)})`
|
|
);
|
|
}
|
|
|
|
if (event.type === 'created') {
|
|
await linkFolderToProject(
|
|
output,
|
|
cwd || paths[0],
|
|
{
|
|
orgId: org.id,
|
|
projectId: event.payload.projectId,
|
|
},
|
|
projectName,
|
|
org.slug
|
|
);
|
|
|
|
now.url = event.payload.url;
|
|
|
|
output.stopSpinner();
|
|
|
|
printInspectUrl(output, event.payload.inspectorUrl, deployStamp);
|
|
|
|
if (quiet) {
|
|
process.stdout.write(`https://${event.payload.url}`);
|
|
}
|
|
|
|
output.spinner(
|
|
event.payload.readyState === 'QUEUED' ? 'Queued' : 'Building',
|
|
0
|
|
);
|
|
}
|
|
|
|
if (event.type === 'building') {
|
|
output.spinner('Building', 0);
|
|
}
|
|
|
|
if (event.type === 'canceled') {
|
|
output.stopSpinner();
|
|
return event.payload;
|
|
}
|
|
|
|
// If `checksState` is present, we can only continue to "Completing" if the checks finished,
|
|
// otherwise we might show "Completing" before "Running Checks".
|
|
if (
|
|
event.type === 'ready' &&
|
|
(event.payload.checksState
|
|
? event.payload.checksState === 'completed'
|
|
: true)
|
|
) {
|
|
output.spinner('Completing', 0);
|
|
}
|
|
|
|
if (event.type === 'checks-running') {
|
|
output.spinner('Running Checks', 0);
|
|
}
|
|
|
|
if (event.type === 'checks-conclusion-failed') {
|
|
output.stopSpinner();
|
|
return event.payload;
|
|
}
|
|
|
|
// Handle error events
|
|
if (event.type === 'error') {
|
|
output.stopSpinner();
|
|
|
|
const error = await now.handleDeploymentError(event.payload, {
|
|
env,
|
|
});
|
|
|
|
if (error.code === 'missing_project_settings') {
|
|
return error;
|
|
}
|
|
|
|
throw error;
|
|
}
|
|
|
|
// Handle alias-assigned event
|
|
if (event.type === 'alias-assigned') {
|
|
event.payload.indications = indications;
|
|
return event.payload;
|
|
}
|
|
}
|
|
} catch (err) {
|
|
output.stopSpinner();
|
|
throw err;
|
|
}
|
|
}
|