-
Notifications
You must be signed in to change notification settings - Fork 39
Expand file tree
/
Copy pathutil.ts
More file actions
109 lines (93 loc) · 3.82 KB
/
util.ts
File metadata and controls
109 lines (93 loc) · 3.82 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
//Get duration ago (E.g: 1 day ago)
export const timeAgo = (dateString: string): string => {
const now = new Date();
const date = new Date(dateString);
const diffMs = now.getTime() - date.getTime();
const diffSeconds = Math.floor(diffMs / 1000);
const diffMinutes = Math.floor(diffSeconds / 60);
const diffHours = Math.floor(diffMinutes / 60);
const diffDays = Math.floor(diffHours / 24);
if (diffSeconds < 60) {
return `${diffSeconds <= 1 ? 1 : diffSeconds} second${diffSeconds === 1 ? '' : 's'} ago`;
} else if (diffMinutes < 60) {
return `${diffMinutes} minute${diffMinutes === 1 ? '' : 's'} ago`;
} else if (diffHours < 24) {
return `${diffHours} hour${diffHours === 1 ? '' : 's'} ago`;
} else {
return `${diffDays} day${diffDays === 1 ? '' : 's'} ago`;
}
}
// Get the commit url from the repo url and sha
export function getCommitUrl(repoUrl: string, sha: string): string {
if (!repoUrl || !sha) return '';
const cleanRepoUrl = repoUrl.replace(/\/$/, '');
// SCM-specific commit URL path patterns, keyed by domain.
// Fallback is '/commit/' which works for GitHub, Gitea, Forgejo, and Azure DevOps.
const scmCommitPaths: { domain: string; path: string }[] = [
{ domain: 'bitbucket.org', path: '/commits/' },
{ domain: 'gitlab.com', path: '/-/commit/' },
];
const match = scmCommitPaths.find(scm => cleanRepoUrl.includes(scm.domain));
return `${cleanRepoUrl}${match ? match.path : '/commit/'}${sha}`;
}
//Extract name from 'Name <email>'
export function extractNameOnly(author: string): string {
const match = author.match(/^([^<]+)</);
if (match) return match[1].trim();
return author;
}
//Extracts the body before trailers
export function extractBodyPreTrailer(body: string): string {
if (!body) return '';
const lines = body.split(/\r?\n/);
const trailerStart = lines.findIndex(line =>
/^([A-Za-z0-9-]+:|Signed-off-by:)/.test(line.trim())
);
if (trailerStart === -1) return body.trim();
return lines.slice(0, trailerStart).join('\n').trim();
}
// date formatting (e.g: Jul 5 2025, 12:15pm EDT)
export function formatDate(date?: string): string {
if (!date) return '-';
const d = new Date(date);
return d.toLocaleString(undefined, {
month: 'short',
day: 'numeric',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
hour12: true,
timeZoneName: 'short'
}).replace(',', '').replace(/:00 /, ' '); // Remove seconds if present
}
// Get the last commit time from a PromotionStrategy
export function getLastCommitTime(ps: any): Date | null {
//Determine the last commit time between both active/proposed hydrated commit
const commitTimes = [
...(ps.status?.environments?.map((env: any) => env.active?.dry?.commitTime) || []),
...(ps.status?.environments?.map((env: any) => env.active?.hydrated?.commitTime) || []),
...(ps.status?.environments?.map((env: any) => env.proposed?.dry?.commitTime) || []),
...(ps.status?.environments?.map((env: any) => env.proposed?.hydrated?.commitTime) || [])
].filter(Boolean);
if (commitTimes.length) {
return new Date(Math.max(...commitTimes.map(t => new Date(t as string).getTime())));
}
if (ps.metadata?.creationTimestamp) {
return new Date(ps.metadata.creationTimestamp);
}
return null;
}
// Get the overall promotion status from individual environment statuses
export function getOverallPromotionStatus(environmentStatuses: string[]): 'promoted' | 'failure' | 'pending' | 'unknown' {
if (environmentStatuses.length === 0) return 'unknown';
if (environmentStatuses.some(status => status === 'failure')) {
return 'failure';
}
if (environmentStatuses.some(status => status === 'pending')) {
return 'pending';
}
if (environmentStatuses.every(status => status === 'promoted')) {
return 'promoted';
}
return 'unknown';
}