Skip to content

Commit

Permalink
Updates to changelog process. (#241)
Browse files Browse the repository at this point in the history
* Updates to changelog process.

* Cleanup the send to slack message.

* Sort slack messages by release date
  • Loading branch information
jthoms1 authored Oct 23, 2023
1 parent ef9e1fe commit 8e79556
Show file tree
Hide file tree
Showing 16 changed files with 766 additions and 44 deletions.
12 changes: 6 additions & 6 deletions lerna.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
{
"version": "0.8.1",
"iosVersion": "0.8.0",
"androidVersion": "0.8.3",
"rnVersion": "0.5.0",
"capacitorVersion": "5.5.0",
"iosMinVersion": "13.0",
"androidMinSdk": "22",
"rnMinVersion": "0.63.4",
"androidLiveUpdatesVersion": "0.4.1"
}
"androidLiveUpdatesVersion": "0.4.1",
"rnVersion": "0.5.1",
"iosVersion": "0.8.0",
"androidVersion": "0.8.3",
"version": "0.8.1"
}
111 changes: 85 additions & 26 deletions scripts/changelog-release.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* @typedef {import("./definitions").Release} Release
* @typedef {import("./definitions").GithubRelease} GithubRelease
* @typedef {import("./definitions").Release} Release
* */
import { promises as fs } from "fs";
import { resolve, dirname } from "path";
Expand All @@ -11,39 +11,52 @@ import fetch from "node-fetch";
import { unified } from "unified";
import markdown from "remark-parse";
import html from "remark-html";
import { postUpdatesToSlack } from "./send-to-slack.mjs";

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
const OUTPUT_PATH = resolve(
__dirname,
"../website/src/components/page/changelog/release-notes.json"
);
const processor = unified().use(markdown).use(html);

const VERSION_FILE = resolve(__dirname, "../lerna.json");

const repos = [
{
productTitle: "Portals Web Plugin",
repo: "ionic-team/ionic-portals",
outputFile: "../website/src/components/page/changelog/web.json",
pageUrl: "https://ionic.io/docs/portals/for-web/changelog",
versionFileKey: "version",
},
{
productTitle: "Portals iOS",
repo: "ionic-team/ionic-portals-ios",
outputFile: "../website/src/components/page/changelog/ios.json",
pageUrl: "https://ionic.io/docs/portals/for-ios/changelog",
versionFileKey: "iosVersion",
},
{
productTitle: "Portals Android",
repo: "ionic-team/ionic-portals-android",
outputFile: "../website/src/components/page/changelog/android.json",
pageUrl: "https://ionic.io/docs/portals/for-android/changelog",
versionFileKey: "androidVersion",
},
{
productTitle: "Portals React Native",
repo: "ionic-team/ionic-portals-react-native",
outputFile: "../website/src/components/page/changelog/react-native.json",
pageUrl: "https://ionic.io/docs/portals/for-react-native/changelog",
versionFileKey: "rnVersion",
},
];

const processor = unified().use(markdown).use(html);

/**
*
* @param {GithubRelease[]} releases
* @returns {Release[]}
*/
const formatReleases = (releases) => {
function formatReleases(releases, repo, productTitle, pageUrl) {
let previousRelease = {
repo: "",
version: "0.0.0",
Expand All @@ -68,11 +81,10 @@ const formatReleases = (releases) => {
// Reverse the list so that the versions are in chronological order
.reverse()
.map((release) => {
const mdBody = cleanup(release.body);
const mdBody = cleanupMarkdown(release.body);
const body = String(processor.processSync(mdBody));
const published_at = formatDate(release.published_at);
const version = semver.clean(release.tag_name);
const [, repo] = /.*\/repos\/(.*)\/releases\/.*/.exec(release.url);

// if list has iterated onto a new repository set go back to a zero version
if (previousRelease.repo !== repo) {
Expand All @@ -87,9 +99,13 @@ const formatReleases = (releases) => {
};

return {
productTitle,
pageUrl,
repo,
mdBody,
body,
name,
raw_published_at: release.published_at,
published_at,
tag_name,
type,
Expand All @@ -100,30 +116,33 @@ const formatReleases = (releases) => {
return -semver.compare(a.tag_name, b.tag_name);
})
);
};
}

/**
*
* @param {string} markdown
*/
function cleanup(markdown) {
function cleanupMarkdown(markdown) {
return (
markdown
.replace(/(?:\r\n)+/g, "\n")
// Change to smaller header
.replace(/^## What's Changed/, "### What's Changed")
.replace(/^## New Contributors/, "### New Contributors")
.replace(/## What's Changed\n/g, "### What's Changed\n")
// Remove the New Contributors line header
.replace(/## New Contributors\n(.*)/g, "")
// Remove new contributor lines
// bold the change type at the beginning of a commit
.replace(/\* (.\S+):/g, (_, type) => `* **${type}**:`)
.replace(/\* (\S+):/g, (_, type) => `* **${type}**:`)
// remove the contributor from the commit line
.replace(/ by \@(\S+) in /g, "")
// change the url to be a link
.replace(
/https:\/\/github.com\/ionic-team\/.*\/pull\/(.\d+)/g,
/https:\/\/github.com\/ionic-team\/.*\/pull\/(\d+)/g,
(link, commitTag) => {
return ` ([#${commitTag}](${link}))`;
}
)
.replace(/\*\*Full Changelog\*\*\: (.\S+)/g, "")
.replace(/\*\*Full Changelog\*\*\: (\S+)/g, "")
);
}

Expand All @@ -138,9 +157,9 @@ function cleanup(markdown) {
* https://docs.github.com/en/enterprise-cloud@latest/authentication/authenticating-with-saml-single-sign-on/authorizing-a-personal-access-token-for-use-with-saml-single-sign-on
*
* @param {string} repoPath
* @return {Promise<any[]>}
* @return {Promise<GithubRelease[]>}
*/
const fetchGithubReleases = async (repoPath) => {
async function fetchGithubReleases(repoPath) {
try {
const request = await fetch(
new URL(`repos/${repoPath}/releases`, "https://api.github.com"),
Expand All @@ -166,7 +185,7 @@ const fetchGithubReleases = async (repoPath) => {
} catch (error) {
return [];
}
};
}

// Takes the date in format 2019-04-26T18:24:09Z
// and returns it as April 26 2019
Expand All @@ -186,15 +205,55 @@ function formatDate(datetime) {
}

async function run() {
// Grab the current contents of the rollup version file so that we can modify it
// during the repo iteration
let rollupVersionContents = JSON.parse(await fs.readFile(VERSION_FILE));
let slackUpdateList = [];

await Promise.all(
repos.map(async ({ repo, outputFile }) => {
const githubReleaseArray = await fetchGithubReleases(repo);
await fs.writeFile(
outputFile,
JSON.stringify(formatReleases(githubReleaseArray), null, 2)
);
})
repos.map(
async ({ repo, outputFile, versionFileKey, productTitle, pageUrl }) => {
// Keep a list of the previous release JSON for comparison
const previousDocReleaseArray = JSON.parse(
await fs.readFile(outputFile)
);

const githubReleaseArray = await fetchGithubReleases(repo);
const docReleaseArray = formatReleases(
githubReleaseArray,
repo,
productTitle,
pageUrl
);
await fs.writeFile(
outputFile,
JSON.stringify(docReleaseArray, null, 2)
);

// Set new version into the rollup version contents object
rollupVersionContents[versionFileKey] = docReleaseArray[0].version;

// Find all release updates that are new by comparing to the previous release JSON
slackUpdateList = [
...slackUpdateList,
...docReleaseArray.filter(({ version }) => {
return previousDocReleaseArray.find(({ prevVersion }) => {
return version === prevVersion;
});
}),
];
}
)
);

await fs.writeFile(
VERSION_FILE,
JSON.stringify(rollupVersionContents, null, 2)
);

if (slackUpdateList.length > 0) {
await postUpdatesToSlack(slackUpdateList);
}
}

run();
4 changes: 4 additions & 0 deletions scripts/definitions.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
export type Release = {
pageUrl: string;
productTitle: string;
mdBody: string;
body: string;
name: string;
raw_published_at: string;
published_at: string;
tag_name: string;
type: string;
Expand Down
Loading

0 comments on commit 8e79556

Please sign in to comment.