UNPKG

@gitlab/semantic-release-merge-request-analyzer

Version:

Semantic release plugin to determine version based on GitLab merge request labels

114 lines (93 loc) 3.13 kB
import getGitLabClient from "./get-gitlab-client.js"; import { getMergeRequestForCommit, getReleaseType, } from "./get-merge-request.js"; import { getDefaultLabelConfig, releaseNoteSections } from "./config.js"; /** * Generates release notes based on merge requests. * * @param {Object} pluginConfig The plugin configuration. * @param {Object} context The semantic-release context. * @returns {Promise<string>} The generated release notes. */ export async function generateNotes(pluginConfig, context) { const { env, commits, logger, nextRelease } = context; const projectId = env.CI_PROJECT_ID; const gitlab = getGitLabClient(context); logger.log(`Generating release notes for version ${nextRelease.version}`); // Get label configuration from plugin config or use defaults const labelConfig = (pluginConfig && pluginConfig.labels) || getDefaultLabelConfig(); // Get section customizations if provided const sectionEmojis = pluginConfig?.sections?.emojis || releaseNoteSections.emojis; const sectionTitles = pluginConfig?.sections?.titles || releaseNoteSections.titles; let releaseNotes = `## ${nextRelease.version}\n\n`; // Categorize merge requests by release type const mrByType = { major: [], premajor: [], minor: [], preminor: [], patch: [], prepatch: [], prerelease: [], other: [], }; // Track processed merge requests to avoid duplicates const processedMRs = new Set(); // Process each commit logger.log(`Processing ${commits.length} commits for release notes`); for (const commit of commits) { const mergeRequest = await getMergeRequestForCommit( gitlab, projectId, commit.hash, logger, ); if (!mergeRequest) { const entry =`- ${commit.message} (${commit.hash})` mrByType.other.push(entry); continue; } const { iid, title, web_url, author } = mergeRequest; if (processedMRs.has(iid)) { continue; } processedMRs.add(iid); const mrEntry = `- ${title} ([!${iid}](${web_url})) by [${author.name}](${author.web_url})` // Determine the release type for this MR using the configured labels const releaseType = getReleaseType(mergeRequest, labelConfig, logger); if (releaseType && releaseType in mrByType) { logger.log(`Adding merge request !${iid} to ${releaseType} section`); mrByType[releaseType].push(mrEntry); } else { logger.log(`Adding merge request !${iid} to other section`); mrByType.other.push(mrEntry); } } // Add sections in a specific order of importance const sectionOrder = [ "major", "premajor", "minor", "preminor", "patch", "prepatch", "prerelease", "other", ]; for (const type of sectionOrder) { const entries = mrByType[type]; if (entries.length > 0) { const emoji = sectionEmojis[type]; const title = sectionTitles[type]; releaseNotes += `### ${emoji} ${title}\n\n${entries.join("\n")}\n\n`; } } logger.success("Release notes generated"); return releaseNotes; } export default generateNotes;