Compare commits

...

17 Commits

Author SHA1 Message Date
Matthew Stanciu
a0479338c1 , 2022-07-12 12:58:44 -07:00
Matthew Stanciu
37a8037128 Add 2022-07-12 11:55:25 -07:00
Matthew Stanciu
65fd5c49f9 Optionally pass in state to mock deployment 2022-07-08 16:36:54 -07:00
Matthew Stanciu
75a19a1b8f Remove console.logs 2022-07-08 16:20:09 -07:00
Matthew Stanciu
d2456a21a1 Merge branch 'main' into update/fix-ls-visual-bugs 2022-07-08 13:03:39 -07:00
Matthew Stanciu
8f02a5d0b1 Fix unit tests 2022-07-08 12:03:14 -07:00
Matthew Stanciu
f4cb7b3b8b Merge branch 'main' into update/fix-ls-visual-bugs 2022-07-08 11:57:56 -07:00
Matthew Stanciu
88c309ec40 use title module for state string 2022-07-08 10:46:42 -07:00
Matthew Stanciu
e383068427 styfle suggestions 2022-07-08 10:39:14 -07:00
Sean Massa
d660f110a3 Merge branch 'main' into update/fix-ls-visual-bugs 2022-07-08 11:39:39 -05:00
Matthew Stanciu
9fada88f99 Fix unit tests 2022-07-07 21:31:03 -07:00
Matthew Stanciu
0d9082dcb8 Merge branch 'main' into update/fix-ls-visual-bugs 2022-07-07 21:13:32 -07:00
Matthew Stanciu
4da688cff3 Merge branch 'update/fix-ls-visual-bugs' of https://github.com/vercel/vercel into update/fix-ls-visual-bugs 2022-07-07 17:04:07 -07:00
Matthew Stanciu
af40cf43ae Fix tests 2022-07-07 17:03:41 -07:00
Matthew Stanciu
4c100a191c Merge branch 'main' into update/fix-ls-visual-bugs 2022-07-07 16:43:15 -07:00
Matthew Stanciu
a637f2f949 Remove project ls message 2022-07-07 16:43:02 -07:00
Matthew Stanciu
f3683fff3f Fix ls visual bugs 2022-07-07 16:37:14 -07:00
5 changed files with 92 additions and 43 deletions

View File

@@ -1,10 +1,10 @@
import chalk from 'chalk';
import ms from 'ms';
import table from 'text-table';
import title from 'title';
import Now from '../util';
import getArgs from '../util/get-args';
import { handleError } from '../util/error';
import cmd from '../util/output/cmd';
import logo from '../util/output/logo';
import elapsed from '../util/output/elapsed';
import strlen from '../util/strlen';
@@ -42,6 +42,8 @@ const help = () => {
-m, --meta Filter deployments by metadata (e.g.: ${chalk.dim(
'`-m KEY=value`'
)}). Can appear many times.
-i, --inspect Display dashboard inspect URLs
--prod Filter for production URLs
-N, --next Show next page of results
${chalk.dim('Examples:')}
@@ -77,6 +79,9 @@ export default async function main(client: Client) {
'-m': '--meta',
'--next': Number,
'-N': '--next',
'--inspect': Boolean,
'-i': '--inspect',
'--prod': Boolean,
'--confirm': Boolean,
});
} catch (err) {
@@ -99,9 +104,10 @@ export default async function main(client: Client) {
}
const yes = argv['--confirm'] || false;
const inspect = argv['--inspect'] || false;
const prod = argv['--prod'] || false;
const meta = parseMeta(argv['--meta']);
const { includeScheme } = config;
let paths = [process.cwd()];
const pathValidation = await validatePaths(client, paths);
@@ -139,6 +145,7 @@ export default async function main(client: Client) {
link.project = linkedProject.project;
}
const isTeam = org?.type === 'team';
let { contextName, team } = await getScope(client);
// If user passed in a custom scope, update the current team & context name
@@ -255,37 +262,51 @@ export default async function main(client: Client) {
}
log(
`Deployments under ${chalk.bold(contextName)} ${elapsed(
`${prod ? `Production deployments` : `Deployments`} for ${chalk.bold(
chalk.magenta(app)
)} under ${chalk.bold(chalk.magenta(contextName))} ${elapsed(
Date.now() - start
)}`
);
// information to help the user find other deployments or instances
if (app == null) {
log(
`To list more deployments for a project run ${cmd(
`${getCommandName('ls [project]')}`
)}`
);
}
log(
`To list more deployments for a project, run ${getCommandName(
'ls [project]'
)}.`
);
print('\n');
client.output.print(
`${table(
[
['project', 'latest deployment', 'state', 'age', 'username'].map(
header => chalk.dim(header)
),
(isTeam
? [
'age',
inspect ? 'inspect url' : 'deployment url',
'state',
'duration',
'username',
]
: [
'age',
inspect ? 'inspect url' : 'deployment url',
'state',
'duration',
]
).map(header => chalk.bold(chalk.cyan(header))),
...deployments
.sort(sortRecent())
.map(dep => [
.map((dep, i) => [
[
getProjectName(dep),
chalk.bold((includeScheme ? 'https://' : '') + dep.url),
stateString(dep.state),
chalk.gray(ms(Date.now() - dep.createdAt)),
dep.creator.username,
i === 0
? chalk.bold(`${getDeployUrl(dep, inspect)}`)
: `${getDeployUrl(dep, inspect)}`,
stateString(dep.state),
chalk.gray(getDeploymentDuration(dep)),
isTeam ? chalk.gray(dep.creator.username) : '',
],
])
// flatten since the previous step returns a nested
@@ -298,8 +319,8 @@ export default async function main(client: Client) {
),
],
{
align: ['l', 'l', 'r', 'l', 'l'],
hsep: ' '.repeat(4),
align: isTeam ? ['l', 'l', 'l', 'l', 'l'] : ['l', 'l', 'l', 'l'],
hsep: ' '.repeat(isTeam ? 4 : 5),
stringLength: strlen,
}
).replace(/^/gm, ' ')}\n\n`
@@ -315,27 +336,43 @@ export default async function main(client: Client) {
}
}
function getProjectName(d: Deployment) {
// We group both file and files into a single project
if (d.name === 'file') {
return 'files';
}
function getDeployUrl(
deployment: Deployment,
inspect: boolean | undefined
): string {
return inspect ? deployment.inspectorUrl : 'https://' + deployment.url;
}
return d.name;
export function getDeploymentDuration(dep: Deployment): string {
if (!dep || !dep.ready || !dep.buildingAt) {
return '?';
}
const duration = ms(dep.ready - dep.buildingAt);
if (duration === '0ms') {
return '--';
}
return duration;
}
// renders the state string
export function stateString(s: string) {
const CIRCLE = '● ';
// make `s` title case
const sTitle = title(s);
switch (s) {
case 'INITIALIZING':
return chalk.yellow(s);
case 'BUILDING':
case 'DEPLOYING':
case 'ANALYZING':
return chalk.yellow(CIRCLE) + sTitle;
case 'ERROR':
return chalk.red(s);
return chalk.red(CIRCLE) + sTitle;
case 'READY':
return s;
return chalk.green(CIRCLE) + sTitle;
case 'QUEUED':
return chalk.white(CIRCLE) + sTitle;
case 'CANCELED':
return chalk.gray(sTitle);
default:
return chalk.gray('UNKNOWN');
}

View File

@@ -28,7 +28,6 @@ export interface AuthConfig {
export interface GlobalConfig {
_?: string;
currentTeam?: string;
includeScheme?: string;
collectMetrics?: boolean;
api?: string;

View File

@@ -7,17 +7,22 @@ import { Build, User } from '../../src/types';
let deployments = new Map<string, Deployment>();
let deploymentBuilds = new Map<Deployment, Build[]>();
type State = Deployment['readyState'];
export function useDeployment({
creator,
state = 'READY',
}: {
creator: Pick<User, 'id' | 'email' | 'name'>;
state?: State;
}) {
const createdAt = Date.now();
const url = new URL(chance().url());
const deployment: Deployment = {
id: `dpl_${chance().guid()}`,
url: url.hostname,
name: '',
name: chance.name,
meta: {},
regions: [],
routes: [],
@@ -26,13 +31,15 @@ export function useDeployment({
version: 2,
createdAt,
createdIn: 'sfo1',
buildingAt: Date.now(),
ownerId: creator.id,
creator: {
uid: creator.id,
email: creator.email,
username: creator.name,
},
readyState: 'READY',
readyState: state,
state: state,
env: {},
build: { env: {} },
target: 'production',

View File

@@ -35,11 +35,12 @@ describe('list', () => {
await list(client);
const output = await readOutputStream(client);
const output = await readOutputStream(client, 4);
const { org } = pluckIdentifiersFromDeploymentList(output.split('\n')[0]);
const header: string[] = parseSpacedTableRow(output.split('\n')[2]);
const data: string[] = parseSpacedTableRow(output.split('\n')[3]);
const header: string[] = parseSpacedTableRow(output.split('\n')[3]);
const data: string[] = parseSpacedTableRow(output.split('\n')[4]);
data.shift();
data.splice(2, 1);
expect(org).toEqual(team[0].slug);
@@ -52,7 +53,7 @@ describe('list', () => {
]);
expect(data).toEqual([
deployment.url,
`https://${deployment.url}`,
stateString(deployment.state || ''),
user.name,
]);
@@ -77,11 +78,12 @@ describe('list', () => {
client.setArgv(deployment.name);
await list(client);
const output = await readOutputStream(client);
const output = await readOutputStream(client, 4);
const { org } = pluckIdentifiersFromDeploymentList(output.split('\n')[0]);
const header: string[] = parseSpacedTableRow(output.split('\n')[2]);
const data: string[] = parseSpacedTableRow(output.split('\n')[3]);
const header: string[] = parseSpacedTableRow(output.split('\n')[3]);
const data: string[] = parseSpacedTableRow(output.split('\n')[4]);
data.shift();
data.splice(2, 1);
expect(org).toEqual(teamSlug);
@@ -94,7 +96,7 @@ describe('list', () => {
'username',
]);
expect(data).toEqual([
deployment.url,
`https://${deployment.url}`,
stateString(deployment.state || ''),
user.name,
]);

View File

@@ -53,6 +53,8 @@ export interface Deployment {
| 'BUILDING'
| 'DEPLOYING'
| 'READY'
| 'QUEUED'
| 'CANCELED'
| 'ERROR';
state?:
| 'INITIALIZING'
@@ -60,6 +62,8 @@ export interface Deployment {
| 'BUILDING'
| 'DEPLOYING'
| 'READY'
| 'QUEUED'
| 'CANCELED'
| 'ERROR';
createdAt: number;
createdIn: string;