229 lines
6.6 KiB
TypeScript
229 lines
6.6 KiB
TypeScript
import { GluegunMenuToolbox } from '@lenne.tech/gluegun-menu';
|
|
import chalk = require('chalk');
|
|
import { defaultMenuSettings, getSettings } from '../../../../globals';
|
|
import { getTestStacksInfo } from '../../../../common/testservers';
|
|
import { getIssueFromRepo } from '../../../../services/github_rest';
|
|
const tto = require('terminal-table-output').create();
|
|
|
|
module.exports = {
|
|
name: 'status',
|
|
alias: ['s'],
|
|
description: 'Show status for available testservers (s)',
|
|
hidden: false,
|
|
run: async (toolbox: GluegunMenuToolbox) => {
|
|
// Load settings
|
|
const config = await getSettings(toolbox);
|
|
if (!config) {
|
|
await toolbox.menu.showMenu('setup', defaultMenuSettings);
|
|
return;
|
|
}
|
|
|
|
const testStacks = await getTestStacksInfo(toolbox);
|
|
const status = (status: string) => {
|
|
switch (status) {
|
|
case 'UPDATE_FAILED':
|
|
case 'CREATE_FAILED':
|
|
case 'ROLLBACK_COMPLETE':
|
|
return `(${chalk.red('FAILED')})`;
|
|
case 'UPDATE_IN_PROGRESS':
|
|
case 'CREATE_IN_PROGRESS':
|
|
return `(${chalk.yellow('IN PROGRESS')})`;
|
|
case 'UPDATE_COMPLETE':
|
|
case 'CREATE_COMPLETE':
|
|
return `(${chalk.green('OK')})`;
|
|
default:
|
|
return `(${chalk.red.bold('?')})`;
|
|
}
|
|
};
|
|
|
|
const getStatusIcon = (status: string): string => {
|
|
switch (status) {
|
|
case 'open':
|
|
return '✅ open';
|
|
case 'closed':
|
|
return '❌ closed';
|
|
case 'null':
|
|
return '❔ unknown';
|
|
}
|
|
};
|
|
|
|
const getIssueStatus = async (issueNumber: string) => {
|
|
if (!issueNumber) return getStatusIcon('null'); // GUARD
|
|
|
|
const issueData = await getIssueFromRepo(
|
|
toolbox,
|
|
config.gh_token,
|
|
'photowall',
|
|
issueNumber,
|
|
);
|
|
|
|
return {
|
|
issue: issueNumber,
|
|
status: getStatusIcon(issueData ? issueData.state : 'null'),
|
|
issueUpdated: issueData ? issueData.updated_at : null,
|
|
};
|
|
};
|
|
|
|
const printIssueStatus = (
|
|
issueStatuses: { issue: string; status: string }[],
|
|
issueNumber: string,
|
|
) => {
|
|
const issueStatus = issueStatuses.find(
|
|
(issueStatus) => issueStatus.issue === issueNumber,
|
|
);
|
|
return issueStatus ? issueStatus.status : getStatusIcon('null');
|
|
};
|
|
|
|
const stackUrl = (stackname: string) => {
|
|
return `https://test-${
|
|
stackname.split('photowall-test-')[1]
|
|
}.photowall-test.com/us`;
|
|
};
|
|
|
|
const ellipsis = (a: string, max: number) => {
|
|
if (a) {
|
|
return a.length > max ? a.substr(0, max) + '..' : a;
|
|
} else {
|
|
return a;
|
|
}
|
|
};
|
|
|
|
const timeSince = (date: number) => {
|
|
const now = Date.now();
|
|
const seconds = Math.floor((now - date) / 1000);
|
|
|
|
let interval = seconds / 31536000;
|
|
|
|
// Years
|
|
if (interval > 1) {
|
|
return Math.floor(interval) + ' years';
|
|
}
|
|
// Months
|
|
interval = seconds / 2592000;
|
|
if (interval > 1) {
|
|
return `${chalk.red('WTF!')}`;
|
|
}
|
|
// Days
|
|
interval = seconds / 86400;
|
|
if (interval > 1) {
|
|
const days = Math.floor(interval);
|
|
let color = 'green';
|
|
|
|
if (days >= 2) {
|
|
if (days <= 12) {
|
|
// Gradient from yellow (#FFFF00) to dark red (#8B0000) over 10 days (days 2-12)
|
|
const gradientColors = [
|
|
'#FFFF00', // 2 days - yellow
|
|
'#FFE600', // 3 days
|
|
'#FFCC00', // 4 days
|
|
'#FFB300', // 5 days
|
|
'#FF9900', // 6 days
|
|
'#FF8000', // 7 days
|
|
'#FF6600', // 8 days
|
|
'#FF4D00', // 9 days
|
|
'#FF3300', // 10 days
|
|
'#CC2900', // 11 days
|
|
'#8B0000', // 12 days - dark red
|
|
];
|
|
const colorIndex = Math.min(days - 2, gradientColors.length - 1);
|
|
color = gradientColors[colorIndex];
|
|
} else {
|
|
color = '#8B0000'; // dark red for 12+ days
|
|
}
|
|
return `${chalk.hex(color)(days + ' days')}`;
|
|
} else {
|
|
return `${chalk.green(days + ' days')}`;
|
|
}
|
|
}
|
|
// Hours
|
|
interval = seconds / 3600;
|
|
if (interval > 1) {
|
|
return `${chalk.green(Math.floor(interval) + ' hours')}`;
|
|
}
|
|
// Minutes
|
|
interval = seconds / 60;
|
|
if (interval > 1) {
|
|
return `${chalk.green(Math.floor(interval) + ' minutes')}`;
|
|
}
|
|
// Seconds
|
|
return Math.floor(seconds) + ' seconds';
|
|
};
|
|
|
|
tto.line('-');
|
|
tto
|
|
.pushrow([
|
|
'| status',
|
|
'stack',
|
|
'branch',
|
|
'issue status',
|
|
// 'issue updated',
|
|
'last commit',
|
|
// 'url'
|
|
])
|
|
.line('-');
|
|
// Sort on stackname
|
|
testStacks.sort((a, b) => {
|
|
if (a.name < b.name) return -1;
|
|
if (a.name > b.name) return 1;
|
|
return 0;
|
|
});
|
|
|
|
// Get issue status
|
|
const issueStatusPromises = [];
|
|
for (const stack of testStacks) {
|
|
const regex = /^(\d+)/;
|
|
const match = stack.branch.match(regex);
|
|
const branchIssueNumber = match ? match[1] : null;
|
|
|
|
if (branchIssueNumber) {
|
|
issueStatusPromises.push(getIssueStatus(branchIssueNumber));
|
|
}
|
|
}
|
|
const issueStatuses = await Promise.all(issueStatusPromises);
|
|
|
|
// Sort the testStacks list on number. They are named like photowall-test-XX where XX is the number.
|
|
testStacks.sort((a, b) => {
|
|
const aNumber = parseInt(a.name.split('photowall-test-')[1]);
|
|
const bNumber = parseInt(b.name.split('photowall-test-')[1]);
|
|
return aNumber - bNumber;
|
|
});
|
|
|
|
for (const stack of testStacks) {
|
|
const regex = /^(\d+)/;
|
|
const match = stack.branch.match(regex);
|
|
const branchIssueNumber = match ? match[1] : null;
|
|
|
|
const t = new Date(stack.updated);
|
|
tto.pushrow([
|
|
status(stack.status),
|
|
stack.name,
|
|
ellipsis(stack.branch, 24),
|
|
printIssueStatus(issueStatuses, branchIssueNumber),
|
|
// issueStatuses.find(
|
|
// (issueStatus) => issueStatus.issue === branchIssueNumber,
|
|
// )
|
|
// ? timeSince(
|
|
// new Date(
|
|
// issueStatuses.find(
|
|
// (issueStatus) => issueStatus.issue === branchIssueNumber,
|
|
// ).issueUpdated,
|
|
// ).getTime(),
|
|
// )
|
|
// : '-',
|
|
!isNaN(t.getTime())
|
|
? timeSince(t.getTime())
|
|
: timeSince(new Date(stack.created).getTime()),
|
|
// stackUrl(stack.name)
|
|
]);
|
|
}
|
|
tto.print(true);
|
|
|
|
if (toolbox.fromMenu()) {
|
|
await toolbox.menu.showMenu(
|
|
'deployment testservers',
|
|
defaultMenuSettings,
|
|
);
|
|
}
|
|
},
|
|
};
|