Files
Sebastian Poxhofer 5f91549447 feat(gitlab): merge MRs through merge trains via the platform merge queue API (#45722)
* feat(gitlab): merge MRs through merge trains via the platform merge queue API

* feat(gitlab): report MRs waiting on a merge train through isPrInMergeQueue

* test(gitlab): drop targetBranch from mergePr calls

* Apply suggestion from @secustor

* refactor(gitlab): validate the merge train car response with a Zod schema
2026-09-09 15:21:46 +00:00

92 lines
2.4 KiB
TypeScript

import { z } from 'zod/v4';
import { LongCommitSha } from '../../../util/schema-utils/git.ts';
import { DeepNullish, LooseArray } from '../../../util/schema-utils/index.ts';
export const LastPipelineId = z
.object({
last_pipeline: z.object({
id: z.number(),
}),
})
.transform(({ last_pipeline }) => last_pipeline.id);
/**
* https://docs.gitlab.com/api/merge_trains/#get-the-status-of-a-merge-request-on-a-merge-train
*/
export const MergeTrainCarStatus = z
.object({
status: z.enum(['idle', 'stale', 'fresh', 'merged', 'merging']),
})
.transform(({ status }) => status);
const GitlabUser = z.object({
id: z.number(),
username: z.string(),
});
export const GitLabProjectMembers = LooseArray(
z.object({
username: z.string(),
access_level: z.number().optional(),
}),
);
export type GitLabProjectMember = z.infer<typeof GitLabProjectMembers>[number];
export const GitLabMergeRequest = DeepNullish(
z.object({
iid: z.number(),
title: z.string(),
description: z.string().nullable(),
state: z.string(),
source_branch: z.string(),
target_branch: z.string(),
created_at: z.string(),
updated_at: z.string(),
diverged_commits_count: z.number().optional(),
merge_status: z.string().optional(),
detailed_merge_status: z
.enum([
'approvals_syncing',
'checking',
'ci_must_pass',
'ci_still_running',
'commits_status',
'conflict',
'discussions_not_resolved',
'draft_status',
'jira_association_missing',
'mergeable',
'merge_request_blocked',
'merge_time',
'need_rebase',
'not_approved',
'not_open',
'preparing',
'requested_changes',
'security_policy_pipeline_check',
'security_policy_violations',
'status_checks_must_pass',
'unchecked',
'locked_paths',
'locked_lfs_files',
'title_regex',
'unknown',
])
.catch('unknown'),
assignee: GitlabUser.optional(),
assignees: LooseArray(GitlabUser).catch([]),
reviewers: LooseArray(GitlabUser).catch([]),
labels: z.array(z.string()).optional(),
sha: LongCommitSha.optional(),
head_pipeline: z
.object({
status: z.string(),
sha: LongCommitSha,
})
.optional(),
}),
);
export const GitLabMergeRequests = z.array(GitLabMergeRequest);
export type GitLabMergeRequest = z.infer<typeof GitLabMergeRequest>;