From 2e618fe89443ecc9f4020d129691ebbba833c1c1 Mon Sep 17 00:00:00 2001 From: literat Date: Tue, 17 Dec 2024 11:41:54 +0100 Subject: [PATCH] fixup! Feat(ci): Introduce posting changelog into the Slack channel --- scripts/post-changelog.mjs | 97 ++++++++++++++++++++++++++++++-------- 1 file changed, 78 insertions(+), 19 deletions(-) diff --git a/scripts/post-changelog.mjs b/scripts/post-changelog.mjs index 447de79bee..9381424fda 100644 --- a/scripts/post-changelog.mjs +++ b/scripts/post-changelog.mjs @@ -1,20 +1,36 @@ +/* eslint-disable import/no-unresolved */ +/* eslint-disable import/no-extraneous-dependencies */ /* eslint-disable no-console */ -import { $, fetch, argv } from 'zx'; import dotenv from 'dotenv-safe'; -import slackifyMarkdown from 'slackify-markdown'; -import { simpleGit } from 'simple-git'; import gitDiffParser from 'gitdiff-parser'; +import { simpleGit } from 'simple-git'; +import slackifyMarkdown from 'slackify-markdown'; +import { $, fetch, argv } from 'zx'; const COLOR_CORE = '#00A58E'; const PACKAGES = ['web', 'web-react', 'web-twig', 'design-tokens', 'icons', 'codemods', 'analytics']; const SLACK_CHANGELOG_WEBHOOK_URL = process.env.SLACK_CHANGELOG_WEBHOOK_URL ?? ''; +/** + * Generates a title for the given package. + * + * @param {string} pkg - The package name. + * @returns {string} The generated title. + */ function getTitle(pkg) { return `🚀 New ${pkg .split('-') .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) .join(' ')} package release`; } + +/** + * Sends the content to the specified webhook URL. + * + * @param {object} params - The parameters. + * @param {object} params.content - The content to send. + * @param {string} params.webhookUrl - The webhook URL to send the content to. + */ async function sendToWebhook({ content, webhookUrl }) { await fetch(webhookUrl, { method: 'POST', @@ -31,14 +47,23 @@ async function sendToWebhook({ content, webhookUrl }) { }); } -function format(str, package_, prefix = '@lmc-eu') { +/** + * Formats the changelog string with the given package name and prefix. + * + * @param {string} str - The changelog string to format. + * @param {string} packageName - The name of the package. + * @param {string} prefix - The prefix to use for the package. + * + * @returns {string} The formatted changelog string. + */ +function format(str, packageName, prefix = '@lmc-eu') { const output = str .replace( /^#+ /, - `# 📦 ${package_ + `# 📦 ${packageName .split('-') .map((part) => part.charAt(0).toUpperCase() + part.slice(1)) - .join(' ')} \`${prefix}/spirit-${package_}\` `, + .join(' ')} \`${prefix}/spirit-${packageName}\` `, ) .replace('Bug Fixes', '🐛 Bug Fixes') .replace('Features', '⚡ Features') @@ -54,6 +79,12 @@ function format(str, package_, prefix = '@lmc-eu') { return output; } +/** + * Extracts the changelog content from the given diff files. + * + * @param {Array} files - The diff files to extract the changelog from. + * @returns {string} The extracted changelog content. + */ function getChangelogFromDiff(files) { // Only one file as we're only looking at the changelog const versionPattern = /<\/a>/; @@ -67,15 +98,36 @@ function getChangelogFromDiff(files) { return changelog; } +/** + * Gets the diff for the given tag and path. + * + * @param {string} tag - The tag to get the diff for. + * @param {string} path - The path to get the diff for. + * @returns {Promise} The diff output. + */ function getDiff(tag, path) { return simpleGit().show([tag, path]); } -function changelogPath(package_) { - return `packages/${package_}/CHANGELOG.md`; +/** + * Returns the changelog path for the given package name. + * + * @param {string} packageName - The name of the package. + * @returns {string} The changelog path. + */ +function changelogPath(packageName) { + return `packages/${packageName}/CHANGELOG.md`; } -async function postSlackNotification(changelog, package_) { +/** + * Posts a Slack notification with the given changelog. + * + * @param {string} changelog - The changelog content to post. + * @param {string} packageName - The name of the package. + * + * @returns {Promise} + */ +async function postSlackNotification(changelog, packageName) { try { $.verbose = false; const res = await sendToWebhook({ @@ -83,7 +135,7 @@ async function postSlackNotification(changelog, package_) { content: { attachments: [ { - title: getTitle(package_), + title: getTitle(packageName), text: changelog, color: COLOR_CORE, }, @@ -97,9 +149,12 @@ async function postSlackNotification(changelog, package_) { console.error(err); } - return undefined; + return null; } +/** + * Configures the webhook URL from the environment variables. + */ async function configureWebhookURL() { try { dotenv.config({ @@ -113,27 +168,31 @@ async function configureWebhookURL() { } } -async function publishChangelog(package_) { +/** + * Publish the changelog for the given npm package. + * + * @param {string} npmPackage - The name of the npm package. + */ +async function publishChangelog(npmPackage) { try { await simpleGit().fetch(['origin', 'main', '--tags']); const tags = await simpleGit().tags({ '--sort': '-taggerdate' }); - console.log(tags.latest); - const diff = await getDiff(tags.latest ?? '', changelogPath(package_)); + const diff = await getDiff(tags.latest ?? '', changelogPath(npmPackage)); const files = gitDiffParser.parse(diff); if (files.length === 0) { - console.log(`No changes in ${package_}`); + console.log(`No changes in ${npmPackage}`); return; } const changelog = getChangelogFromDiff(files); - const formattedChangelog = format(changelog, package_); + const formattedChangelog = format(changelog, npmPackage); const slackifiedChangelog = slackifyMarkdown(formattedChangelog); if (argv.dry) { console.info(formattedChangelog); } else { await configureWebhookURL(); - await postSlackNotification(slackifiedChangelog, package_); + await postSlackNotification(slackifiedChangelog, npmPackage); } } catch (err) { console.error(err); @@ -143,8 +202,8 @@ async function publishChangelog(package_) { (async () => { await Promise.all( - PACKAGES.map(async (package_) => { - await publishChangelog(package_); + PACKAGES.map(async (npmPackage) => { + await publishChangelog(npmPackage); }), ); process.exit(0);