mirror of
https://github.com/LukeHagar/vercel.git
synced 2025-12-09 21:07:46 +00:00
[deployment-retention]: feat: preview policies
This commit is contained in:
@@ -36,6 +36,16 @@ export const listCommand: Command = {
|
||||
type: String,
|
||||
deprecated: false,
|
||||
},
|
||||
{
|
||||
name: 'policy',
|
||||
description:
|
||||
'Preview deployments by retention policy (e.g.: `-p preview=1w`). Can appear many times.',
|
||||
argument:
|
||||
'[canceled|errored|preview|production]=[1d|1w|1m|2m|3m|1y|unlimited]',
|
||||
shorthand: null,
|
||||
type: [String],
|
||||
deprecated: false,
|
||||
},
|
||||
],
|
||||
examples: [
|
||||
{
|
||||
@@ -54,5 +64,9 @@ export const listCommand: Command = {
|
||||
name: 'Paginate deployments for a project, where `1584722256178` is the time in milliseconds since the UNIX epoch',
|
||||
value: `${packageName} list my-app --next 1584722256178`,
|
||||
},
|
||||
{
|
||||
name: 'Preview deployments affected by deployment retention policies',
|
||||
value: `${packageName} list -policy canceled=1d -policy errored=1w -policy preview=1m -policy production=1y`,
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
@@ -21,6 +21,18 @@ import { isErrnoException } from '@vercel/error-utils';
|
||||
import { help } from '../help';
|
||||
import { listCommand } from './command';
|
||||
|
||||
function ToDate(timestamp: number): string {
|
||||
const date = new Date(timestamp);
|
||||
const options: Intl.DateTimeFormatOptions = {
|
||||
year: '2-digit',
|
||||
month: '2-digit',
|
||||
day: '2-digit',
|
||||
};
|
||||
|
||||
// The locale 'en-US' ensures the format is MM/DD/YY
|
||||
return date.toLocaleDateString('en-US', options);
|
||||
}
|
||||
|
||||
export default async function list(client: Client) {
|
||||
let argv;
|
||||
|
||||
@@ -34,6 +46,8 @@ export default async function list(client: Client) {
|
||||
'--prod': Boolean, // this can be deprecated someday
|
||||
'--yes': Boolean,
|
||||
'-y': '--yes',
|
||||
'--policy': [String],
|
||||
'-p': '--policy',
|
||||
|
||||
// deprecated
|
||||
'--confirm': Boolean,
|
||||
@@ -65,6 +79,7 @@ export default async function list(client: Client) {
|
||||
|
||||
const autoConfirm = !!argv['--yes'];
|
||||
const meta = parseMeta(argv['--meta']);
|
||||
const policy = parseMeta(argv['--policy']);
|
||||
|
||||
const target = argv['--prod']
|
||||
? 'production'
|
||||
@@ -180,6 +195,7 @@ export default async function list(client: Client) {
|
||||
meta,
|
||||
nextTimestamp,
|
||||
target,
|
||||
policy,
|
||||
});
|
||||
|
||||
let {
|
||||
@@ -249,6 +265,7 @@ export default async function list(client: Client) {
|
||||
|
||||
const headers = ['Age', 'Deployment', 'Status', 'Environment', 'Duration'];
|
||||
if (showUsername) headers.push('Username');
|
||||
if (policy) headers.push(...['Expiration', 'Proposed Expiration']);
|
||||
const urls: string[] = [];
|
||||
|
||||
client.output.print(
|
||||
@@ -266,6 +283,10 @@ export default async function list(client: Client) {
|
||||
dep.target === 'production' ? 'Production' : 'Preview',
|
||||
chalk.gray(getDeploymentDuration(dep)),
|
||||
showUsername ? chalk.gray(dep.creator?.username) : '',
|
||||
policy && dep.expiration ? ToDate(dep.expiration) : '',
|
||||
policy && dep.proposedExpiration
|
||||
? ToDate(dep.proposedExpiration)
|
||||
: '',
|
||||
];
|
||||
})
|
||||
.filter(app =>
|
||||
|
||||
@@ -63,6 +63,7 @@ export interface ListOptions {
|
||||
meta?: Dictionary<string>;
|
||||
nextTimestamp?: number;
|
||||
target?: string;
|
||||
policy?: Dictionary<string>;
|
||||
}
|
||||
|
||||
export default class Now extends EventEmitter {
|
||||
@@ -343,7 +344,13 @@ export default class Now extends EventEmitter {
|
||||
|
||||
async list(
|
||||
app?: string,
|
||||
{ version = 4, meta = {}, nextTimestamp, target }: ListOptions = {},
|
||||
{
|
||||
version = 4,
|
||||
meta = {},
|
||||
nextTimestamp,
|
||||
target,
|
||||
policy = {},
|
||||
}: ListOptions = {},
|
||||
prod?: boolean
|
||||
) {
|
||||
const fetchRetry = async (url: string, options: FetchOptions = {}) => {
|
||||
@@ -371,7 +378,7 @@ export default class Now extends EventEmitter {
|
||||
);
|
||||
};
|
||||
|
||||
if (!app && !Object.keys(meta).length) {
|
||||
if (!app && !Object.keys(meta).length && !Object.keys(policy).length) {
|
||||
// Get the 20 latest projects and their latest deployment
|
||||
const query = new URLSearchParams({ limit: (20).toString() });
|
||||
if (nextTimestamp) {
|
||||
@@ -400,7 +407,13 @@ export default class Now extends EventEmitter {
|
||||
query.set('app', app);
|
||||
}
|
||||
|
||||
if (Object.keys(meta).length) {
|
||||
Object.keys(meta).map(key => query.set(`meta-${key}`, meta[key]));
|
||||
}
|
||||
|
||||
if (Object.keys(policy).length) {
|
||||
Object.keys(policy).map(key => query.set(`policy-${key}`, policy[key]));
|
||||
}
|
||||
|
||||
query.set('limit', '20');
|
||||
|
||||
|
||||
Reference in New Issue
Block a user