168 lines
4.4 KiB
JavaScript
168 lines
4.4 KiB
JavaScript
// Dependencies
|
|
const fs = require("fs");
|
|
const yaml = require("js-yaml");
|
|
const axios = require("axios");
|
|
|
|
// Use GitHub token if available
|
|
if (process.env.GITHUB_TOKEN) axios.defaults.headers.common["Authorization"] = `Bearer ${process.env.GITHUB_TOKEN}`;
|
|
|
|
// Check changelog directory.
|
|
if (!process.env.CHANGELOG_DIR) {
|
|
console.log("CHANGELOG_DIR not defined, exiting.");
|
|
return process.exit(1);
|
|
}
|
|
|
|
const ChangelogFilePath = `../../../${process.env.CHANGELOG_DIR}`
|
|
|
|
// Regexes
|
|
const HeaderRegex = /^\s*(?::cl:|๐) *([a-z0-9_\-, ]+)?/img; // :cl: or ๐ [0] followed by optional author name [1]
|
|
const EntryRegex = /^ *[*-]? *(add|remove|tweak|fix): *([^\n\r]+)\r?$/img; // * or - followed by change type [0] and change message [1]
|
|
const CommentRegex = /<!--.*?-->/gs; // HTML comments
|
|
|
|
// Main function
|
|
async function main() {
|
|
// Get PR details
|
|
const pr = await axios.get(`https://api.github.com/repos/${process.env.GITHUB_REPOSITORY}/pulls/${process.env.PR_NUMBER}`);
|
|
const { merged_at, body, user } = pr.data;
|
|
|
|
// Remove comments from the body
|
|
commentlessBody = body.replace(CommentRegex, '');
|
|
|
|
// Get author
|
|
const headerMatch = HeaderRegex.exec(commentlessBody);
|
|
if (!headerMatch) {
|
|
console.log("No changelog entry found, skipping");
|
|
return;
|
|
}
|
|
|
|
let author = headerMatch[1];
|
|
if (!author) {
|
|
console.log("No author found, setting it to author of the PR\n");
|
|
author = user.login;
|
|
} else {
|
|
author = author.trim()
|
|
}
|
|
|
|
// Offset results past the header
|
|
commentlessBody = commentlessBody.slice(HeaderRegex.lastIndex);
|
|
|
|
// Get all changes from the body
|
|
const entries = getChanges(commentlessBody);
|
|
|
|
|
|
// Time is something like 2021-08-29T20:00:00Z
|
|
// Time should be something like 2023-02-18T00:00:00.0000000+00:00
|
|
let time = merged_at;
|
|
if (time)
|
|
{
|
|
time = time.replace("z", ".0000000+00:00").replace("Z", ".0000000+00:00");
|
|
}
|
|
else
|
|
{
|
|
console.log("Pull request was not merged, skipping");
|
|
return;
|
|
}
|
|
|
|
|
|
// Construct changelog yml entry
|
|
const entry = {
|
|
author: author,
|
|
changes: entries,
|
|
id: getHighestCLNumber() + 1,
|
|
time: time,
|
|
url: `https://github.com/${process.env.GITHUB_REPOSITORY}/pull/${process.env.PR_NUMBER}`,
|
|
};
|
|
|
|
// Write changelogs
|
|
writeChangelog(entry);
|
|
|
|
console.log(`Changelog updated with changes from PR #${process.env.PR_NUMBER}`);
|
|
}
|
|
|
|
|
|
// Code chunking
|
|
|
|
// Get all changes from the PR body
|
|
function getChanges(body) {
|
|
const matches = [];
|
|
const entries = [];
|
|
|
|
for (const match of body.matchAll(EntryRegex)) {
|
|
matches.push([match[1], match[2]]);
|
|
}
|
|
|
|
if (!matches)
|
|
{
|
|
console.log("No changes found, skipping");
|
|
return;
|
|
}
|
|
|
|
|
|
// Check change types and construct changelog entry
|
|
matches.forEach((entry) => {
|
|
let type;
|
|
|
|
switch (entry[0].toLowerCase()) {
|
|
case "add":
|
|
type = "Add";
|
|
break;
|
|
case "remove":
|
|
type = "Remove";
|
|
break;
|
|
case "tweak":
|
|
type = "Tweak";
|
|
break;
|
|
case "fix":
|
|
type = "Fix";
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (type) {
|
|
entries.push({
|
|
type: type,
|
|
message: entry[1],
|
|
});
|
|
}
|
|
});
|
|
|
|
return entries;
|
|
}
|
|
|
|
// Get the highest changelog number from the changelogs file
|
|
function getHighestCLNumber() {
|
|
// Read changelogs file
|
|
const file = fs.readFileSync(ChangelogFilePath, "utf8");
|
|
|
|
// Get list of CL numbers
|
|
const data = yaml.load(file);
|
|
const entries = data && data.Entries ? Array.from(data.Entries) : [];
|
|
const clNumbers = entries.map((entry) => entry.id);
|
|
|
|
// Return highest changelog number
|
|
return Math.max(...clNumbers, 0);
|
|
}
|
|
|
|
function writeChangelog(entry) {
|
|
let data = { Entries: [] };
|
|
|
|
// Create a new changelogs file if it does not exist
|
|
if (fs.existsSync(ChangelogFilePath)) {
|
|
const file = fs.readFileSync(ChangelogFilePath, "utf8");
|
|
data = yaml.load(file);
|
|
}
|
|
|
|
data.Entries.push(entry);
|
|
|
|
// Write updated changelogs file
|
|
fs.writeFileSync(
|
|
ChangelogFilePath,
|
|
"Entries:\n" +
|
|
yaml.dump(data.Entries, { indent: 2 }).replace(/^---/, "")
|
|
);
|
|
}
|
|
|
|
// Run main
|
|
main();
|