Files
openclaw/test/helpers/release-workflow-timeouts.ts

80 lines
3.0 KiB
TypeScript

type ReleaseTimeoutProfile = "beta" | "stable" | "full";
type ReleaseWorkflowJob = { needs?: string | string[]; "timeout-minutes"?: number | string };
type ReleaseWorkflow = { jobs?: Record<string, ReleaseWorkflowJob> };
export function releaseWorkflowJobNeeds(job: ReleaseWorkflowJob): string[] {
return Array.isArray(job.needs) ? job.needs : job.needs ? [job.needs] : [];
}
export function releaseTimeoutForProfile(
timeout: number | string | undefined,
profile: ReleaseTimeoutProfile,
): number {
if (typeof timeout === "number") {
return timeout;
}
if (timeout === "${{ matrix.group.timeout_minutes || 60 }}") {
return 60;
}
const match = timeout?.match(
/^\$\{\{ inputs\.(?:release_profile|release_test_profile) == 'full' && ([0-9]+) \|\| ([0-9]+) \}\}$/u,
);
if (!match) {
throw new Error(`Unsupported release timeout expression: ${String(timeout)}`);
}
return Number(profile === "full" ? match[1] : match[2]);
}
function requireWorkflowJob(workflow: ReleaseWorkflow, jobName: string): ReleaseWorkflowJob {
const job = workflow.jobs?.[jobName];
if (!job) {
throw new Error(`Missing release workflow job: ${jobName}`);
}
return job;
}
function requireWorkflowNeeds(
job: ReleaseWorkflowJob,
required: readonly string[],
exact = false,
): void {
const needs = releaseWorkflowJobNeeds(job);
if (
!required.every((name) => needs.includes(name)) ||
(exact && needs.length !== required.length)
) {
throw new Error(`Invalid release dependency chain: ${needs.join(",")}`);
}
}
export function pluginPrereleaseTimeoutComponents(params: {
pluginPrerelease: ReleaseWorkflow;
liveE2e: ReleaseWorkflow;
profile: ReleaseTimeoutProfile;
}) {
const jobs = {
preflight: requireWorkflowJob(params.pluginPrerelease, "preflight"),
dockerSuite: requireWorkflowJob(params.pluginPrerelease, "plugin-prerelease-docker-suite"),
suite: requireWorkflowJob(params.pluginPrerelease, "plugin-prerelease-suite"),
validateSelectedRef: requireWorkflowJob(params.liveE2e, "validate_selected_ref"),
prepareImage: requireWorkflowJob(params.liveE2e, "prepare_docker_e2e_image"),
imageReady: requireWorkflowJob(params.liveE2e, "docker_e2e_image_ready"),
dockerLanes: requireWorkflowJob(params.liveE2e, "validate_docker_lanes"),
};
requireWorkflowNeeds(jobs.dockerSuite, ["preflight"]);
requireWorkflowNeeds(jobs.prepareImage, ["validate_selected_ref"], true);
requireWorkflowNeeds(jobs.imageReady, ["prepare_docker_e2e_image"], true);
requireWorkflowNeeds(jobs.dockerLanes, ["prepare_docker_e2e_image", "docker_e2e_image_ready"]);
requireWorkflowNeeds(jobs.suite, ["plugin-prerelease-docker-suite"]);
const timeout = (job: ReleaseWorkflowJob) =>
releaseTimeoutForProfile(job["timeout-minutes"], params.profile);
return {
preflight: timeout(jobs.preflight),
validateSelectedRef: timeout(jobs.validateSelectedRef),
prepareImage: timeout(jobs.prepareImage),
imageReady: timeout(jobs.imageReady),
dockerLanes: timeout(jobs.dockerLanes),
suite: timeout(jobs.suite),
};
}