diff --git a/src/gitlab.ts b/src/gitlab.ts index ace2b15..691ca76 100644 --- a/src/gitlab.ts +++ b/src/gitlab.ts @@ -118,9 +118,13 @@ export const runCommandInGitlabPipeline = async (ctx: Context, task: Task): Prom */ let wasBranchRegistered = false; const waitForBranchMaxTries = 3; - const waitForBranchRetryDelay = 1024; + const waitForBranchRetryDelayMs = 2000; const branchPresenceUrl = `${gitlabProjectApi}/repository/branches/${branchNameUrlEncoded}`; + + // add small preventive delay, as checking right-away most probably would cause a retry + await millisecondsDelay(waitForBranchRetryDelayMs); + for (let waitForBranchTryCount = 0; waitForBranchTryCount < waitForBranchMaxTries; waitForBranchTryCount++) { logger.debug({ branchPresenceUrl }, `Sending request to see if the branch for task ${task.id} is ready`); const response = await fetch(branchPresenceUrl, { headers: { "PRIVATE-TOKEN": gitlab.accessToken } }); @@ -132,8 +136,9 @@ export const runCommandInGitlabPipeline = async (ctx: Context, task: Task): Prom { branchPresenceUrl, task, response }, `Branch of task ${task.id} was not found. Waiting before retrying...`, ); - await millisecondsDelay(waitForBranchRetryDelay); + await millisecondsDelay(waitForBranchRetryDelayMs); } else if (response.ok) { + logger.debug({ branchNameUrlEncoded, response }, `Found branch ${branchNameUrlEncoded} for task ${task.id}`); wasBranchRegistered = true; break; } else { @@ -143,7 +148,7 @@ export const runCommandInGitlabPipeline = async (ctx: Context, task: Task): Prom if (!wasBranchRegistered) { throw new Error( - `Task's branch was not registered on GitLab after ${waitForBranchMaxTries * waitForBranchRetryDelay}ms`, + `Task's branch was not registered on GitLab after ${waitForBranchMaxTries * waitForBranchRetryDelayMs}ms`, ); } @@ -158,6 +163,7 @@ export const runCommandInGitlabPipeline = async (ctx: Context, task: Task): Prom .keys({ id: Joi.number().required(), project_id: Joi.number().required() }) .options({ allowUnknown: true }), ); + logger.info({ pipeline, task }, `Created pipeline for task ${task.id}`); const jobFetchUrl = `${gitlabProjectApi}/pipelines/${pipeline.id}/jobs`; diff --git a/src/task.ts b/src/task.ts index 1175540..2f1811f 100644 --- a/src/task.ts +++ b/src/task.ts @@ -129,7 +129,11 @@ export const queueTask = async ( const afterTaskRun = (result: CommandOutput | null) => { const wasAlive = taskIsAlive; - logger.debug(result, "AfterTaskRun handler"); + if (result instanceof Error) { + logger.error(result, "AfterTaskRun returned an error"); + } else { + logger.debug(result, "AfterTaskRun handler"); + } void terminate().catch((error) => { logger.error(error, "Failed to terminate task on afterTaskRun"); diff --git a/src/test/github-job-cancellation.spec.ts b/src/test/github-job-cancellation.spec.ts index c73c561..1716ea8 100644 --- a/src/test/github-job-cancellation.spec.ts +++ b/src/test/github-job-cancellation.spec.ts @@ -91,7 +91,7 @@ describe("Job cancellation (GitHub webhook)", () => { .forGet("/api/v4/projects/paritytech-stg%2Fcommand-bot-test/pipelines/61/jobs") .thenReply(200, restFixures.gitlab.jobs, jsonResponseHeaders); - await until(async () => !(await mockedPipelineEndpoint.isPending()), 100, 50); + await until(async () => !(await mockedPipelineEndpoint.isPending()), 300, 50); await until( () => lastCommentBody.match(cancelCommandRegex) !== null, 100, @@ -110,7 +110,7 @@ describe("Job cancellation (GitHub webhook)", () => { const commandId = ensureDefined(lastCommentBody.match(cancelCommandRegex)?.[1]); await triggerWebhook("cancelCommandComment", { body: `bot cancel ${commandId}` }); - await until(async () => !(await mockedEndpoint.isPending()), 100, 50); + await until(async () => !(await mockedEndpoint.isPending()), 300, 50); }); test("Phase 3: cmd-bot comments about cancellation", async () => { @@ -135,7 +135,7 @@ describe("Job cancellation (GitHub webhook)", () => { await triggerWebhook("cancelCommandComment", { body: `bot cancel` }); - await until(async () => !(await mockedEndpoint.isPending()), 100, 50); + await until(async () => !(await mockedEndpoint.isPending()), 300, 50); }); test("Phase 5: cmd-bot cancel command with no active job returns ¯\\_(ツ)_/¯", async () => { diff --git a/src/utils.ts b/src/utils.ts index ae15327..564a6ed 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -70,8 +70,11 @@ export class Err { constructor(public value: T) {} } +/** + * @throws Joi.ValidationError + */ export const validatedFetch = async ( - response: ReturnType, + fetchFn: ReturnType, schema: Joi.AnySchema, { decoding }: { decoding: "json" } = { decoding: "json" }, ): Promise => { @@ -79,7 +82,7 @@ export const validatedFetch = async ( const body = await (async () => { switch (decoding) { case "json": { - return await (await response).json(); + return await (await fetchFn).json(); } default: { const exhaustivenessCheck: never = decoding; @@ -88,10 +91,13 @@ export const validatedFetch = async ( } } })(); + const validation = schema.validate(body); + if (validation.error) { throw validation.error; } + return validation.value as T; };