#!/usr/bin/env nodeimport { execFileSync } from "node:child_process"; const args = process.argv.slice(2);const sinceIndex = args.indexOf("--since");const rangeIndex = args.indexOf("--range");const maxIndex = args.indexOf("--max"); const maxItems = Number(maxIndex === -1 ? 20 : args[maxIndex + 1]);const range = rangeIndex === -1 ? `--since=${sinceIndex === -1 ? "1 week ago" : args[sinceIndex + 1]}` : args[rangeIndex + 1]; const logArgs = rangeIndex === -1 ? ["log", "origin/main", range, "--pretty=format:%s"] : ["log", range, "--pretty=format:%s"]; const output = execFileSync("git", logArgs, { encoding: "utf8" }).trim();const subjects = output ? output.split(/\r?\n/) : []; const groups = [ ["Features", /^(feat)(?:\(.+\))?!?: (.+)$/], ["Fixes", /^(fix)(?:\(.+\))?!?: (.+)$/], ["Performance", /^(perf)(?:\(.+\))?!?: (.+)$/], ["Refactors", /^(refactor)(?:\(.+\))?!?: (.+)$/], ["Tests", /^(test)(?:\(.+\))?!?: (.+)$/], ["Infrastructure", /^(build|ci|chore|release)(?:\(.+\))?!?: (.+)$/], ["Polish", /^(micro|style)(?:\(.+\))?!?: (.+)$/], ["Documentation", /^(docs)(?:\(.+\))?!?: (.+)$/],]; const grouped = new Map(groups.map(([name]) => [name, []])); for (const subject of subjects) { for (const [name, pattern] of groups) { const match = pattern.exec(subject); if (match) { grouped.get(name).push(match[2]); break; } }} console.log("# Release Statement\n");let emitted = 0; for (const [name, items] of grouped) { if (!items.length || emitted >= maxItems) { continue; } console.log(`## ${name}\n`); for (const item of items.slice(0, maxItems - emitted)) { console.log(`- ${item}`); emitted += 1; } console.log("");} if (emitted === 0) { console.log("- No conventional release changes found for the selected range.");}
#!/usr/bin/env node
import { execFileSync } from "node:child_process";
const args = process.argv.slice(2);
const sinceIndex = args.indexOf("--since");
const rangeIndex = args.indexOf("--range");
const maxIndex = args.indexOf("--max");
const maxItems = Number(maxIndex === -1 ? 20 : args[maxIndex + 1]);
const range =
rangeIndex === -1
? `--since=${sinceIndex === -1 ? "1 week ago" : args[sinceIndex + 1]}`
: args[rangeIndex + 1];
const logArgs =
rangeIndex === -1
? ["log", "origin/main", range, "--pretty=format:%s"]
: ["log", range, "--pretty=format:%s"];
const output = execFileSync("git", logArgs, { encoding: "utf8" }).trim();
const subjects = output ? output.split(/\r?\n/) : [];
const groups = [
["Features", /^(feat)(?:\(.+\))?!?: (.+)$/],
["Fixes", /^(fix)(?:\(.+\))?!?: (.+)$/],
["Performance", /^(perf)(?:\(.+\))?!?: (.+)$/],
["Refactors", /^(refactor)(?:\(.+\))?!?: (.+)$/],
["Tests", /^(test)(?:\(.+\))?!?: (.+)$/],
["Infrastructure", /^(build|ci|chore|release)(?:\(.+\))?!?: (.+)$/],
["Polish", /^(micro|style)(?:\(.+\))?!?: (.+)$/],
["Documentation", /^(docs)(?:\(.+\))?!?: (.+)$/],
];
const grouped = new Map(groups.map(([name]) => [name, []]));
for (const subject of subjects) {
for (const [name, pattern] of groups) {
const match = pattern.exec(subject);
if (match) {
grouped.get(name).push(match[2]);
break;
}
}
}
console.log("# Release Statement\n");
let emitted = 0;
for (const [name, items] of grouped) {
if (!items.length || emitted >= maxItems) {
continue;
}
console.log(`## ${name}\n`);
for (const item of items.slice(0, maxItems - emitted)) {
console.log(`- ${item}`);
emitted += 1;
}
console.log("");
}
if (emitted === 0) {
console.log("- No conventional release changes found for the selected range.");
}