UNPKG

sfdx-hardis

Version:

Swiss-army-knife Toolbox for Salesforce. Allows you to define a complete CD/CD Pipeline. Orchestrate base commands and assist users with interactive wizards

187 lines (185 loc) • 8.6 kB
import { Gitlab } from "@gitbeaker/node"; import c from "chalk"; import { getCurrentGitBranch, git, uxLog } from "../utils/index.js"; import { GitProviderRoot } from "./gitProviderRoot.js"; import { CONSTANTS } from "../../config/index.js"; export class GitlabProvider extends GitProviderRoot { gitlabApi; serverUrl; token; constructor() { super(); // Gitlab URL is always provided by default CI variables this.serverUrl = process.env.CI_SERVER_URL || ""; // It's better to have a project token defined in a CI_SFDX_HARDIS_GITLAB_TOKEN variable, to have the rights to act on Pull Requests this.token = process.env.CI_SFDX_HARDIS_GITLAB_TOKEN || process.env.ACCESS_TOKEN || ""; this.gitlabApi = new Gitlab({ host: this.serverUrl, token: this.token, rejectUnauthorized: process?.env?.GITLAB_API_REJECT_UNAUTHORIZED === "false" ? false : true, }); } getLabel() { return "sfdx-hardis Gitlab connector"; } // Returns current job URL async getCurrentJobUrl() { if (process.env.PIPELINE_JOB_URL) { return process.env.PIPELINE_JOB_URL; } if (process.env.CI_JOB_URL) { return process.env.CI_JOB_URL; } return null; } // Returns current job URL async getCurrentBranchUrl() { if (process.env.CI_PROJECT_URL && process.env.CI_COMMIT_REF_NAME) return `${process.env.CI_PROJECT_URL}/-/tree/${process.env.CI_COMMIT_REF_NAME}`; return null; } // Gitlab supports mermaid in PR markdown async supportsMermaidInPrMarkdown() { return true; } // Find pull request info async getPullRequestInfo() { // Case when MR is found in the context const projectId = process.env.CI_PROJECT_ID || null; const mrNumber = process.env.CI_MERGE_REQUEST_IID || null; if (mrNumber !== null) { const mergeRequests = await this.gitlabApi.MergeRequests.all({ projectId: projectId || "", iids: [parseInt(mrNumber)], }); if (mergeRequests.length > 0) { const mergeRequest = mergeRequests[0]; return this.completePullRequestInfo(mergeRequest); } } // Case when we find MR from a commit const sha = await git().revparse(["HEAD"]); const latestMergeRequestsOnBranch = await this.gitlabApi.MergeRequests.all({ projectId: projectId || "", state: "merged", sort: "desc", sha: sha, }); if (latestMergeRequestsOnBranch.length > 0) { const currentGitBranch = await getCurrentGitBranch(); const candidateMergeRequests = latestMergeRequestsOnBranch.filter((pr) => pr.target_branch === currentGitBranch); if (candidateMergeRequests.length > 0) { return this.completePullRequestInfo(candidateMergeRequests[0]); } } uxLog(this, c.grey(`[Gitlab Integration] Unable to find related Merge Request Info`)); return null; } async getBranchDeploymentCheckId(gitBranch) { let deploymentCheckId = null; const projectId = process.env.CI_PROJECT_ID || null; const latestMergeRequestsOnBranch = await this.gitlabApi.MergeRequests.all({ projectId: projectId || "", state: "merged", sort: "desc", targetBranch: gitBranch, }); if (latestMergeRequestsOnBranch.length > 0) { const latestMergeRequest = latestMergeRequestsOnBranch[0]; const latestMergeRequestId = latestMergeRequest.iid; deploymentCheckId = await this.getDeploymentIdFromPullRequest(projectId || "", latestMergeRequestId, deploymentCheckId, this.completePullRequestInfo(latestMergeRequest)); } return deploymentCheckId; } async getPullRequestDeploymentCheckId() { const pullRequestInfo = await this.getPullRequestInfo(); if (pullRequestInfo) { const projectId = process.env.CI_PROJECT_ID || null; return await this.getDeploymentIdFromPullRequest(projectId || "", pullRequestInfo.idNumber, null, pullRequestInfo); } return null; } async getDeploymentIdFromPullRequest(projectId, latestMergeRequestId, deploymentCheckId, latestMergeRequest) { const existingNotes = await this.gitlabApi.MergeRequestNotes.all(projectId, latestMergeRequestId); for (const existingNote of existingNotes) { if (existingNote.body.includes("<!-- sfdx-hardis deployment-id ")) { const matches = /<!-- sfdx-hardis deployment-id (.*) -->/gm.exec(existingNote.body); if (matches) { deploymentCheckId = matches[1]; uxLog(this, c.gray(`Found deployment id ${deploymentCheckId} on MR #${latestMergeRequestId} ${latestMergeRequest.title}`)); break; } } } return deploymentCheckId; } // Posts a note on the merge request async postPullRequestMessage(prMessage) { // Get CI variables const projectId = process.env.CI_PROJECT_ID || null; const mergeRequestId = process.env.CI_MERGE_REQUEST_IID || process.env.CI_MERGE_REQUEST_ID || null; if (projectId == null || mergeRequestId == null) { uxLog(this, c.grey("[Gitlab integration] No project and merge request, so no note posted...")); return { posted: false, providerResult: { info: "No related merge request" } }; } const gitlabCiJobName = process.env.CI_JOB_NAME; const gitlabCIJobUrl = process.env.CI_JOB_URL; // Build note message const messageKey = prMessage.messageKey + "-" + gitlabCiJobName + "-" + mergeRequestId; let messageBody = `**${prMessage.title || ""}** ${prMessage.message} _Powered by [sfdx-hardis](${CONSTANTS.DOC_URL_ROOT}) from job [${gitlabCiJobName}](${gitlabCIJobUrl})_ <!-- sfdx-hardis message-key ${messageKey} --> `; // Add deployment id if present if (globalThis.pullRequestDeploymentId) { messageBody += `\n<!-- sfdx-hardis deployment-id ${globalThis.pullRequestDeploymentId} -->`; } // Check for existing note from a previous run uxLog(this, c.grey("[Gitlab integration] Listing Notes of Merge Request...")); const existingNotes = await this.gitlabApi.MergeRequestNotes.all(projectId, mergeRequestId); let existingNoteId = null; for (const existingNote of existingNotes) { if (existingNote.body.includes(`<!-- sfdx-hardis message-key ${messageKey} -->`)) { existingNoteId = existingNote.id; } } // Create or update MR note if (existingNoteId) { // Update existing note uxLog(this, c.grey("[Gitlab integration] Updating Merge Request Note on Gitlab...")); const gitlabEditNoteResult = await this.gitlabApi.MergeRequestNotes.edit(projectId, mergeRequestId, existingNoteId, messageBody); const prResult = { posted: gitlabEditNoteResult.id > 0, providerResult: gitlabEditNoteResult, }; return prResult; } else { // Create new note if no existing not was found uxLog(this, c.grey("[Gitlab integration] Adding Merge Request Note on Gitlab...")); const gitlabPostNoteResult = await this.gitlabApi.MergeRequestNotes.create(projectId, mergeRequestId, messageBody); const prResult = { posted: gitlabPostNoteResult.id > 0, providerResult: gitlabPostNoteResult, }; return prResult; } } completePullRequestInfo(prData) { const prInfo = { idNumber: prData?.iid || prData?.id || 0, idStr: String(prData?.iid || prData?.id || ""), sourceBranch: (prData?.source_branch || "").replace("refs/heads/", ""), targetBranch: (prData?.target_branch || "").replace("refs/heads/", ""), title: prData?.title || "", description: prData?.description || "", authorName: prData?.author?.name || "", webUrl: prData?.web_url || "", providerInfo: prData, customBehaviors: {} }; return this.completeWithCustomBehaviors(prInfo); } } //# sourceMappingURL=gitlab.js.map