implement try catch for gitlab premium feature, implement conditional for automatic mr reviewer assignment

Signed-off-by: Hghtwr <johannes.sonner@outlook.com>
This commit is contained in:
Hghtwr
2025-01-31 15:13:36 +01:00
parent 72f9a9d1ff
commit 829e5015c4
@@ -25,6 +25,8 @@ import {
RepositoryTreeSchema,
CommitAction,
SimpleUserSchema,
ExpandedMergeRequestSchema,
Camelize,
} from '@gitbeaker/rest';
import path from 'path';
import { ScmIntegrationRegistry } from '@backstage/integration';
@@ -81,6 +83,56 @@ async function getFileAction(
return defaultCommitAction;
}
async function getReviewersFromApprovalRules(
api: InstanceType<typeof Gitlab>,
mergerequestIId: number,
repoID: string,
ctx: any,
): Promise<number[]> {
try {
// Because we don't know the code owners before the MR is created, we can't check the approval rules beforehand.
// Getting the approval rules beforehand is very difficult, especially, because of the inheritance rules for groups.
// Code owners take a moment to be processed and added to the approval rules after the MR is created.
let mergeRequest:
| ExpandedMergeRequestSchema
| Camelize<ExpandedMergeRequestSchema> = await api.MergeRequests.show(
repoID,
mergerequestIId,
);
while (
mergeRequest.detailed_merge_status === 'preparing' ||
mergeRequest.detailed_merge_status === 'approvals_syncing' ||
mergeRequest.detailed_merge_status === 'checking'
) {
mergeRequest = await api.MergeRequests.show(repoID, mergeRequest.iid);
ctx.logger.info(`${mergeRequest.detailed_merge_status}`);
}
const approvalRules = await api.MergeRequestApprovals.allApprovalRules(
repoID,
{
mergerequestIId: mergeRequest.iid,
},
);
return approvalRules
.filter(rule => rule.eligible_approvers !== undefined)
.map(rule => {
return rule.eligible_approvers as SimpleUserSchema[];
})
.flat()
.map(user => user.id);
} catch (e) {
ctx.logger.warn(
`Failed to retrieve approval rules for MR ${mergerequestIId}: ${getErrorMessage(
e,
)}. Proceeding with MR creation without reviewers from approval rules.`,
);
return [];
}
}
/**
* Create a new action that creates a gitlab merge request.
*
@@ -106,6 +158,7 @@ export const createPublishGitlabMergeRequestAction = (options: {
removeSourceBranch?: boolean;
assignee?: string;
reviewers?: string[];
assignReviewersFromApprovalRules?: boolean;
}>({
id: 'publish:gitlab:merge-request',
examples,
@@ -193,6 +246,12 @@ which uses additional API calls in order to detect whether to 'create', 'update'
},
description: 'Users that will be assigned as reviewers',
},
assignReviewersFromApprovalRules: {
title: 'Assign reviewers from approval rules',
type: 'boolean',
description:
'Automatically assign reviewers from the approval rules of the MR. Includes Codeowners',
},
},
},
output: {
@@ -404,48 +463,35 @@ which uses additional API calls in order to detect whether to 'create', 'update'
},
);
// Because we don't know the code owners before the MR is created, we can't check the approval rules beforehand.
// Getting the approval rules beforehand is very difficult, especially, because of the inheritance rules for groups.
// Code owners take a moment to be processed and added to the approval rules after the MR is created.
if (ctx.input.assignReviewersFromApprovalRules) {
try {
const reviewersFromApprovalRules =
await getReviewersFromApprovalRules(
api,
mergeRequest.iid,
repoID,
ctx,
);
const eligibleUserIds = new Set([
...reviewersFromApprovalRules,
...(reviewerIds ?? []),
]);
while (
mergeRequest.detailed_merge_status === 'preparing' ||
mergeRequest.detailed_merge_status === 'approvals_syncing' ||
mergeRequest.detailed_merge_status === 'checking'
) {
mergeRequest = await api.MergeRequests.show(repoID, mergeRequest.iid);
ctx.logger.info(`${mergeRequest.detailed_merge_status}`);
mergeRequest = await api.MergeRequests.edit(
repoID,
mergeRequest.iid,
{
reviewerIds: Array.from(eligibleUserIds),
},
);
} catch (e) {
ctx.logger.warn(
`Failed to assign reviewers from approval rules: ${getErrorMessage(
e,
)}`,
);
}
}
const approvalRules = await api.MergeRequestApprovals.allApprovalRules(
repoID,
{
mergerequestIId: mergeRequest.iid,
},
);
if (approvalRules.length !== 0) {
const eligibleApprovers = approvalRules
.filter(rule => rule.eligible_approvers !== undefined)
.map(rule => {
return rule.eligible_approvers as SimpleUserSchema[];
})
.flat();
const eligibleUserIds = new Set([
...eligibleApprovers.map(user => user.id),
...(reviewerIds ?? []),
]);
mergeRequest = await api.MergeRequests.edit(
repoID,
mergeRequest.iid,
{
reviewerIds: Array.from(eligibleUserIds),
},
);
}
ctx.output('projectid', repoID);
ctx.output('targetBranchName', targetBranch);
ctx.output('projectPath', repoID);