Skip to content

Commit 40be134

Browse files
committed
add script to yeet prerelease changelogs
1 parent 1caf253 commit 40be134

File tree

4 files changed

+174
-1
lines changed

4 files changed

+174
-1
lines changed

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,12 @@
99
"build": "pnpm run --recursive --if-present build",
1010
"test": "pnpm run --recursive --if-present test",
1111
"changeset": "changeset",
12-
"changeset:version": "changeset version && node ./scripts/remove-prerelease-changelogs.mjs && node ./scripts/patchup-version.mjs",
12+
"changeset:version": "changeset version && node ./scripts/remove-prerelease-changelogs.mjs",
1313
"changeset:release": "pnpm run build && changeset publish"
1414
},
1515
"dependencies": {
1616
"@changesets/cli": "^2.26.1",
17+
"@manypkg/get-packages": "^2.1.0",
1718
"@remix-run/changelog-github": "^0.0.5",
1819
"@tsconfig/node16": "^1.0.3",
1920
"@types/node": "^18.15.11",

pnpm-lock.yaml

Lines changed: 35 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,122 @@
1+
import * as fs from "node:fs";
2+
import path from "node:path";
3+
import * as url from "node:url";
4+
import { getPackagesSync } from "@manypkg/get-packages";
5+
6+
const __dirname = url.fileURLToPath(new URL(".", import.meta.url));
7+
const rootDir = path.join(__dirname, "..");
8+
9+
const DRY_RUN = false;
10+
// pre-release headings look like: "1.15.0-pre.2"
11+
const PRE_RELEASE_HEADING_REGEXP = /^\d+\.\d+\.\d+-pre\.\d+$/i;
12+
// pre-release headings look like: "1.15.0"
13+
const STABLE_HEADING_REGEXP = /^\d+\.\d+\.\d+$/i;
14+
15+
main();
16+
17+
async function main() {
18+
// if (isPrereleaseMode()) {
19+
// console.log("🚫 Skipping changelog removal in prerelease mode");
20+
// return;
21+
// }
22+
await removePreReleaseChangelogs();
23+
console.log("✅ Removed pre-release changelogs");
24+
}
25+
26+
async function removePreReleaseChangelogs() {
27+
let allPackages = getPackagesSync(rootDir).packages;
28+
29+
/** @type {Promise<any>[]} */
30+
let processes = [];
31+
for (let pkg of allPackages) {
32+
let changelogPath = path.join(pkg.dir, "CHANGELOG.md");
33+
if (!fs.existsSync(changelogPath)) {
34+
continue;
35+
}
36+
let changelogFileContents = fs.readFileSync(changelogPath, "utf-8");
37+
processes.push(
38+
(async () => {
39+
let preReleaseHeadingIndex = findHeadingLineIndex(
40+
changelogFileContents,
41+
{
42+
level: 2,
43+
startAtIndex: 0,
44+
matcher: PRE_RELEASE_HEADING_REGEXP,
45+
}
46+
);
47+
48+
while (preReleaseHeadingIndex !== -1) {
49+
let nextStableHeadingIndex = findHeadingLineIndex(
50+
changelogFileContents,
51+
{
52+
level: 2,
53+
startAtIndex: preReleaseHeadingIndex + 1,
54+
matcher: STABLE_HEADING_REGEXP,
55+
}
56+
);
57+
58+
// remove all lines between the pre-release heading and the next stable
59+
// heading
60+
changelogFileContents = removeLines(changelogFileContents, {
61+
start: preReleaseHeadingIndex,
62+
end: nextStableHeadingIndex === -1 ? "max" : nextStableHeadingIndex,
63+
});
64+
65+
// find the next pre-release heading
66+
preReleaseHeadingIndex = findHeadingLineIndex(changelogFileContents, {
67+
level: 2,
68+
startAtIndex: 0,
69+
matcher: PRE_RELEASE_HEADING_REGEXP,
70+
});
71+
}
72+
73+
if (DRY_RUN) {
74+
console.log("FILE CONTENTS:\n\n" + changelogFileContents);
75+
} else {
76+
await fs.promises.writeFile(
77+
changelogPath,
78+
changelogFileContents,
79+
"utf-8"
80+
);
81+
}
82+
})()
83+
);
84+
}
85+
return Promise.all(processes);
86+
}
87+
88+
function isPrereleaseMode() {
89+
try {
90+
let prereleaseFilePath = path.join(rootDir, ".changeset", "pre.json");
91+
return fs.existsSync(prereleaseFilePath);
92+
} catch (err) {
93+
return false;
94+
}
95+
}
96+
97+
/**
98+
* @param {string} markdownContents
99+
* @param {{ level: number; startAtIndex: number; matcher: RegExp }} opts
100+
*/
101+
function findHeadingLineIndex(
102+
markdownContents,
103+
{ level, startAtIndex, matcher }
104+
) {
105+
let index = markdownContents.split("\n").findIndex((line, i) => {
106+
if (i < startAtIndex || !line.startsWith(`${"#".repeat(level)} `))
107+
return false;
108+
let headingContents = line.slice(level + 1).trim();
109+
return matcher.test(headingContents);
110+
});
111+
return index;
112+
}
113+
114+
/**
115+
* @param {string} markdownContents
116+
* @param {{ start: number; end: number | 'max' }} param1
117+
*/
118+
function removeLines(markdownContents, { start, end }) {
119+
let lines = markdownContents.split("\n");
120+
lines.splice(start, end === "max" ? lines.length - start : end - start);
121+
return lines.join("\n");
122+
}

scripts/tsconfig.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"include": ["."],
3+
"exclude": ["./deployment-test", "./playground/template/**/*"],
4+
"compilerOptions": {
5+
"allowJs": true,
6+
"checkJs": true,
7+
"forceConsistentCasingInFileNames": true,
8+
"allowSyntheticDefaultImports": true,
9+
"moduleResolution": "nodenext",
10+
"module": "ESNext",
11+
"noEmit": true,
12+
"strict": true,
13+
"target": "ES2018"
14+
}
15+
}

0 commit comments

Comments
 (0)