Skip to content

Commit 87d6021

Browse files
authored
Run manual job immediately on first validation or after rebase (#104)
1 parent 4baacbc commit 87d6021

File tree

2 files changed

+108
-29
lines changed

2 files changed

+108
-29
lines changed

server/src/Job.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,17 @@ export interface JobArgs {
88

99
export type JobFunction = (args: JobArgs) => Promise<unknown> | unknown;
1010

11+
interface JobState {
12+
checkManualJobs: boolean;
13+
}
14+
1115
export class Job {
1216
private _info: JobInfo;
1317
private _status: JobStatus;
1418
private _priority: JobPriority;
19+
private _state: JobState = {
20+
checkManualJobs: true,
21+
};
1522

1623
private readonly _id: string;
1724
private readonly _fn: JobFunction;
@@ -60,6 +67,10 @@ export class Job {
6067
this.onChange();
6168
}
6269

70+
public updateState(callback: (state: JobState) => JobState) {
71+
this._state = callback(this._state);
72+
}
73+
6374
public run(args: JobArgs): Promise<unknown> | unknown {
6475
return this._fn(args);
6576
}
@@ -80,6 +91,10 @@ export class Job {
8091
return this._priority;
8192
}
8293

94+
get state(): JobState {
95+
return this._state;
96+
}
97+
8398
public getData(): GQLJob {
8499
return {
85100
priority: this.priority,

server/src/MergeRequestAcceptor.ts

Lines changed: 93 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -387,6 +387,40 @@ export const acceptMergeRequest = async (
387387
};
388388
};
389389

390+
const resolveCurrentPipeline = async (
391+
gitlabApi: GitlabApi,
392+
user: User,
393+
mergeRequestInfo: MergeRequestInfo,
394+
): Promise<MergeRequestPipeline | null | false> => {
395+
let currentPipeline: MergeRequestPipeline | null = mergeRequestInfo.pipeline;
396+
397+
if (currentPipeline === null || currentPipeline.sha !== mergeRequestInfo.sha) {
398+
const pipelines = await gitlabApi.getMergeRequestPipelines(
399+
mergeRequestInfo.project_id,
400+
mergeRequestInfo.iid,
401+
);
402+
if (pipelines.length > 0) {
403+
const currentPipelineCandidate = pipelines.find(
404+
(pipeline) => pipeline.sha === mergeRequestInfo.sha,
405+
);
406+
407+
if (currentPipelineCandidate === undefined) {
408+
const message =
409+
mergeRequestInfo.pipeline === null
410+
? `[MR][${mergeRequestInfo.iid}] Merge request can't be merged. Pipeline does not exist`
411+
: `[MR][${mergeRequestInfo.iid}] Merge request can't be merged. The latest pipeline is not executed on the latest commit`;
412+
console.log(message);
413+
414+
return false;
415+
}
416+
417+
currentPipeline = currentPipelineCandidate;
418+
}
419+
}
420+
421+
return currentPipeline;
422+
};
423+
390424
export const runAcceptingMergeRequest = async (
391425
job: Job,
392426
gitlabApi: GitlabApi,
@@ -449,6 +483,10 @@ export const runAcceptingMergeRequest = async (
449483
await tryCancelPipeline(gitlabApi, mergeRequestInfo, user);
450484
await gitlabApi.rebaseMergeRequest(mergeRequestInfo.project_id, mergeRequestInfo.iid);
451485
job.updateStatus(JobStatus.REBASING);
486+
job.updateState((state) => ({
487+
...state,
488+
checkManualJobs: true,
489+
}));
452490
return;
453491
}
454492

@@ -464,6 +502,53 @@ export const runAcceptingMergeRequest = async (
464502
return;
465503
}
466504

505+
if (job.state.checkManualJobs) {
506+
job.updateState((state) => ({
507+
...state,
508+
checkManualJobs: false,
509+
}));
510+
const currentPipeline = await resolveCurrentPipeline(gitlabApi, user, mergeRequestInfo);
511+
if (currentPipeline !== null && currentPipeline !== false) {
512+
const jobs = uniqueNamedJobsByDate(
513+
await gitlabApi.getPipelineJobs(mergeRequestInfo.project_id, currentPipeline.id),
514+
);
515+
516+
const manualJobsToRun = jobs.filter(
517+
(job) => PipelineJobStatus.Manual === job.status && !job.allow_failure,
518+
);
519+
const canceledJobsToRun = jobs.filter(
520+
(job) => PipelineJobStatus.Canceled === job.status && !job.allow_failure,
521+
);
522+
523+
if (manualJobsToRun.length > 0 || canceledJobsToRun.length > 0) {
524+
if (!config.AUTORUN_MANUAL_BLOCKING_JOBS) {
525+
return {
526+
kind: AcceptMergeRequestResultKind.WaitingPipeline,
527+
mergeRequestInfo,
528+
user,
529+
pipeline: currentPipeline,
530+
};
531+
}
532+
533+
console.log(
534+
`[MR][${mergeRequestInfo.iid}] there are some blocking manual or canceled. triggering again`,
535+
);
536+
job.updateStatus(JobStatus.WAITING_FOR_CI);
537+
await Promise.all(
538+
manualJobsToRun.map((job) =>
539+
gitlabApi.runJob(mergeRequestInfo.project_id, job.id),
540+
),
541+
);
542+
await Promise.all(
543+
canceledJobsToRun.map((job) =>
544+
gitlabApi.retryJob(mergeRequestInfo.project_id, job.id),
545+
),
546+
);
547+
return;
548+
}
549+
}
550+
}
551+
467552
if (mergeResponse.kind === AcceptMergeRequestResultKind.PipelineInProgress) {
468553
if (!containsLabel(mergeRequestInfo.labels, BotLabels.WaitingForPipeline)) {
469554
await setBotLabels(gitlabApi, mergeRequestInfo, [
@@ -493,35 +578,14 @@ export const runAcceptingMergeRequest = async (
493578
};
494579
}
495580

496-
let currentPipeline: MergeRequestPipeline | null = mergeRequestInfo.pipeline;
497-
498-
if (currentPipeline === null || currentPipeline.sha !== mergeRequestInfo.sha) {
499-
const pipelines = await gitlabApi.getMergeRequestPipelines(
500-
mergeRequestInfo.project_id,
501-
mergeRequestInfo.iid,
502-
);
503-
if (pipelines.length > 0) {
504-
const currentPipelineCandidate = pipelines.find(
505-
(pipeline) => pipeline.sha === mergeRequestInfo.sha,
506-
);
507-
508-
if (currentPipelineCandidate === undefined) {
509-
const message =
510-
mergeRequestInfo.pipeline === null
511-
? `[MR][${mergeRequestInfo.iid}] Merge request can't be merged. Pipeline does not exist`
512-
: `[MR][${mergeRequestInfo.iid}] Merge request can't be merged. The latest pipeline is not executed on the latest commit`;
513-
console.log(message);
514-
515-
return {
516-
kind: AcceptMergeRequestResultKind.InvalidPipeline,
517-
mergeRequestInfo,
518-
user,
519-
pipeline: mergeRequestInfo.pipeline,
520-
};
521-
}
522-
523-
currentPipeline = currentPipelineCandidate;
524-
}
581+
const currentPipeline = await resolveCurrentPipeline(gitlabApi, user, mergeRequestInfo);
582+
if (currentPipeline === false) {
583+
return {
584+
kind: AcceptMergeRequestResultKind.InvalidPipeline,
585+
mergeRequestInfo,
586+
user,
587+
pipeline: mergeRequestInfo.pipeline,
588+
};
525589
}
526590

527591
if (currentPipeline !== null) {

0 commit comments

Comments
 (0)