88 lines
2.7 KiB
TypeScript
88 lines
2.7 KiB
TypeScript
/**
|
|
* Auto-paginate a list endpoint.
|
|
* If opts includes a specific page, returns just that page (no auto-pagination).
|
|
*/
|
|
export async function autoPaginate<T>(
|
|
fetchPage: (page: number, perPage: number) => Promise<T[]>,
|
|
opts?: { page?: number; perPage?: number },
|
|
): Promise<T[]> {
|
|
const perPage = opts?.perPage || 50;
|
|
|
|
// If caller requests a specific page, return just that page
|
|
if (opts?.page) {
|
|
return fetchPage(opts.page, perPage);
|
|
}
|
|
|
|
// Otherwise auto-paginate through all pages
|
|
const all: T[] = [];
|
|
let page = 1;
|
|
while (true) {
|
|
const items = await fetchPage(page, perPage);
|
|
all.push(...items);
|
|
if (items.length < perPage) break;
|
|
page++;
|
|
}
|
|
return all;
|
|
}
|
|
|
|
/**
|
|
* Compute duration in seconds from two ISO timestamps.
|
|
*/
|
|
export function computeDuration(startedAt?: string, completedAt?: string): number {
|
|
if (!startedAt || !completedAt) return 0;
|
|
const ms = new Date(completedAt).getTime() - new Date(startedAt).getTime();
|
|
return ms > 0 ? Math.round(ms / 1000) : 0;
|
|
}
|
|
|
|
/**
|
|
* Gitea uses `status` for run state (running, waiting, completed)
|
|
* and `conclusion` for the actual result (success, failure, cancelled, skipped).
|
|
* When status is "completed", the conclusion carries the meaningful status.
|
|
*/
|
|
export function resolveGiteaStatus(status: string, conclusion: string): string {
|
|
if (status === 'completed' && conclusion) {
|
|
return conclusion;
|
|
}
|
|
return status || conclusion || '';
|
|
}
|
|
|
|
/**
|
|
* Extract a human-readable ref from the Gitea `path` field.
|
|
* path format: "workflow.yaml@refs/tags/v1.0.0" or "workflow.yaml@refs/heads/main"
|
|
*/
|
|
export function extractRefFromPath(path?: string): string {
|
|
if (!path) return '';
|
|
const atIdx = path.indexOf('@');
|
|
if (atIdx < 0) return '';
|
|
const ref = path.substring(atIdx + 1);
|
|
return ref.replace(/^refs\/tags\//, '').replace(/^refs\/heads\//, '');
|
|
}
|
|
|
|
/**
|
|
* Extract the workflow filename from the Gitea `path` field.
|
|
* path format: "workflow.yaml@refs/tags/v1.0.0" → "workflow.yaml"
|
|
*/
|
|
export function extractWorkflowIdFromPath(path?: string): string {
|
|
if (!path) return '';
|
|
const atIdx = path.indexOf('@');
|
|
return atIdx >= 0 ? path.substring(0, atIdx) : path;
|
|
}
|
|
|
|
/**
|
|
* Translate normalized status names to Gitea API-native query parameter values.
|
|
* Gitea accepts: pending, queued, in_progress, failure, success, skipped
|
|
*/
|
|
export function toGiteaApiStatus(status?: string): string | undefined {
|
|
if (!status) return undefined;
|
|
const map: Record<string, string> = {
|
|
running: 'in_progress',
|
|
failed: 'failure',
|
|
canceled: 'cancelled',
|
|
pending: 'pending',
|
|
success: 'success',
|
|
skipped: 'skipped',
|
|
waiting: 'queued',
|
|
};
|
|
return map[status] || status;
|
|
}
|