Skip to content

Commit

Permalink
fixup! Feat(ci): Introduce posting changelog into the Slack channel
Browse files Browse the repository at this point in the history
  • Loading branch information
literat committed Dec 17, 2024
1 parent 2cc978e commit 2e618fe
Showing 1 changed file with 78 additions and 19 deletions.
97 changes: 78 additions & 19 deletions scripts/post-changelog.mjs
Original file line number Diff line number Diff line change
@@ -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',
Expand All @@ -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')
Expand All @@ -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 name=".*"><\/a>/;
Expand All @@ -67,23 +98,44 @@ 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<string>} 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<void>}
*/
async function postSlackNotification(changelog, packageName) {
try {
$.verbose = false;
const res = await sendToWebhook({
webhookUrl: SLACK_CHANGELOG_WEBHOOK_URL,
content: {
attachments: [
{
title: getTitle(package_),
title: getTitle(packageName),
text: changelog,
color: COLOR_CORE,
},
Expand All @@ -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({
Expand All @@ -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);
Expand All @@ -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);
Expand Down

0 comments on commit 2e618fe

Please sign in to comment.