Made "gitlab:pipeline:trigger" action idempotent

Signed-off-by: Bogdan Nechyporenko <bnechyporenko@bol.com>
This commit is contained in:
Bogdan Nechyporenko
2025-03-14 20:56:04 +01:00
parent 85df833fe3
commit 984b283e2c
2 changed files with 47 additions and 19 deletions
+5
View File
@@ -0,0 +1,5 @@
---
'@backstage/plugin-scaffolder-backend-module-gitlab': patch
---
Made "gitlab:pipeline:trigger" action idempotent
@@ -62,7 +62,8 @@ export const createTriggerGitlabPipelineAction = (options: {
output: pipelineOutputProperties,
},
async handler(ctx) {
let pipelineTokenResponse: PipelineTriggerTokenSchema | null = null;
let pipelineTriggerToken: string | undefined = undefined;
let pipelineTriggerId: number | undefined = undefined;
const { repoUrl, projectId, tokenDescription, token, branch, variables } =
commonGitlabConfig.merge(pipelineInputProperties).parse(ctx.input);
@@ -71,18 +72,28 @@ export const createTriggerGitlabPipelineAction = (options: {
const api = getClient({ host, integrations, token });
try {
// Create a pipeline token
pipelineTokenResponse = (await api.PipelineTriggerTokens.create(
projectId,
tokenDescription,
)) as PipelineTriggerTokenSchema;
({ pipelineTriggerToken, pipelineTriggerId } = await ctx.checkpoint({
key: `create.pipeline.token.${projectId}`,
fn: async () => {
const res = (await api.PipelineTriggerTokens.create(
projectId,
tokenDescription,
)) as PipelineTriggerTokenSchema;
return {
pipelineTriggerToken: res.token,
pipelineTriggerId: res.id,
};
},
}));
if (!pipelineTokenResponse.token) {
ctx.logger.error('Failed to create pipeline token.');
if (!pipelineTriggerToken) {
ctx.logger.error(
`Failed to create pipeline token for project ${projectId}.`,
);
return;
}
ctx.logger.info(
`Pipeline token id ${pipelineTokenResponse.id} created.`,
`Pipeline token id ${pipelineTriggerId} created for project ${projectId}.`,
);
// Use the pipeline token to trigger the pipeline in the project
@@ -90,16 +101,20 @@ export const createTriggerGitlabPipelineAction = (options: {
(await api.PipelineTriggerTokens.trigger(
projectId,
branch,
pipelineTokenResponse.token,
pipelineTriggerToken,
{ variables },
)) as ExpandedPipelineSchema;
if (!pipelineTriggerResponse.id) {
ctx.logger.error('Failed to trigger pipeline.');
ctx.logger.error(
`Failed to trigger pipeline for project ${projectId}.`,
);
return;
}
ctx.logger.info(`Pipeline id ${pipelineTriggerResponse.id} triggered.`);
ctx.logger.info(
`Pipeline id ${pipelineTriggerResponse.id} for project ${projectId} triggered.`,
);
ctx.output('pipelineUrl', pipelineTriggerResponse.web_url);
} catch (error: any) {
@@ -115,18 +130,26 @@ export const createTriggerGitlabPipelineAction = (options: {
);
} finally {
// Delete the pipeline token if it was created
if (pipelineTokenResponse && pipelineTokenResponse.id) {
if (pipelineTriggerId) {
try {
await api.PipelineTriggerTokens.remove(
projectId,
pipelineTokenResponse.id,
);
await ctx.checkpoint({
key: `create.delete.token.${projectId}`,
fn: async () => {
if (pipelineTriggerId) {
// to make the current version of TypeScript happy
await api.PipelineTriggerTokens.remove(
projectId,
pipelineTriggerId,
);
}
},
});
ctx.logger.info(
`Deleted pipeline token ${pipelineTokenResponse.id}.`,
`Deleted pipeline with token id ${pipelineTriggerId}.`,
);
} catch (error: any) {
ctx.logger.error(
`Failed to delete pipeline token id ${pipelineTokenResponse.id}.`,
`Failed to delete pipeline with token id ${pipelineTriggerId}.`,
);
}
}