mirror of
https://github.com/moltbot/moltbot.git
synced 2026-03-07 22:44:16 +00:00
chore: remove changelog add helper script
This commit is contained in:
@@ -38,7 +38,6 @@ When the operator says “release”, immediately do this preflight (no extra qu
|
||||
3. **Changelog & docs**
|
||||
|
||||
- [ ] Update `CHANGELOG.md` with user-facing highlights (create the file if missing); keep entries strictly descending by version.
|
||||
- Tip: use `pnpm changelog:add -- --section fixes --entry "Your entry. (#12345) Thanks @contrib."` (or `--section changes`) to append deterministically under the current Unreleased block.
|
||||
- [ ] Ensure README examples/flags match current CLI behavior (notably new commands or options).
|
||||
|
||||
4. **Validation**
|
||||
|
||||
@@ -54,7 +54,6 @@
|
||||
"build": "pnpm canvas:a2ui:bundle && tsdown && pnpm build:plugin-sdk:dts && node --import tsx scripts/write-plugin-sdk-entry-dts.ts && node --import tsx scripts/canvas-a2ui-copy.ts && node --import tsx scripts/copy-hook-metadata.ts && node --import tsx scripts/copy-export-html-templates.ts && node --import tsx scripts/write-build-info.ts && node --import tsx scripts/write-cli-compat.ts",
|
||||
"build:plugin-sdk:dts": "tsc -p tsconfig.plugin-sdk.dts.json",
|
||||
"canvas:a2ui:bundle": "bash scripts/bundle-a2ui.sh",
|
||||
"changelog:add": "node --import tsx scripts/changelog-add.ts",
|
||||
"check": "pnpm format:check && pnpm tsgo && pnpm lint",
|
||||
"check:docs": "pnpm format:docs:check && pnpm lint:docs && pnpm docs:check-links",
|
||||
"check:loc": "node --import tsx scripts/check-ts-max-loc.ts --max 500",
|
||||
|
||||
@@ -1,123 +0,0 @@
|
||||
import { readFileSync, writeFileSync } from "node:fs";
|
||||
import { resolve } from "node:path";
|
||||
|
||||
export type UnreleasedSection = "changes" | "fixes";
|
||||
|
||||
function normalizeEntry(entry: string): string {
|
||||
const trimmed = entry.trim();
|
||||
if (!trimmed) {
|
||||
throw new Error("entry must not be empty");
|
||||
}
|
||||
return trimmed.startsWith("- ") ? trimmed : `- ${trimmed}`;
|
||||
}
|
||||
|
||||
function sectionHeading(section: UnreleasedSection): string {
|
||||
return section === "changes" ? "### Changes" : "### Fixes";
|
||||
}
|
||||
|
||||
export function insertUnreleasedChangelogEntry(
|
||||
changelogContent: string,
|
||||
section: UnreleasedSection,
|
||||
entry: string,
|
||||
): string {
|
||||
const normalizedEntry = normalizeEntry(entry);
|
||||
const lines = changelogContent.split(/\r?\n/);
|
||||
const unreleasedHeaderIndex = lines.findIndex((line) =>
|
||||
/^##\s+.+\s+\(Unreleased\)\s*$/.test(line.trim()),
|
||||
);
|
||||
if (unreleasedHeaderIndex < 0) {
|
||||
throw new Error("could not find an '(Unreleased)' changelog section");
|
||||
}
|
||||
|
||||
const unreleasedEndIndex = lines.findIndex(
|
||||
(line, index) => index > unreleasedHeaderIndex && /^##\s+/.test(line.trim()),
|
||||
);
|
||||
const unreleasedLimit = unreleasedEndIndex < 0 ? lines.length : unreleasedEndIndex;
|
||||
const sectionLabel = sectionHeading(section);
|
||||
const sectionStartIndex = lines.findIndex(
|
||||
(line, index) =>
|
||||
index > unreleasedHeaderIndex && index < unreleasedLimit && line.trim() === sectionLabel,
|
||||
);
|
||||
if (sectionStartIndex < 0) {
|
||||
throw new Error(`could not find '${sectionLabel}' under unreleased section`);
|
||||
}
|
||||
|
||||
const sectionEndIndex = lines.findIndex(
|
||||
(line, index) =>
|
||||
index > sectionStartIndex &&
|
||||
index < unreleasedLimit &&
|
||||
(/^###\s+/.test(line.trim()) || /^##\s+/.test(line.trim())),
|
||||
);
|
||||
const targetIndex = sectionEndIndex < 0 ? unreleasedLimit : sectionEndIndex;
|
||||
let insertionIndex = targetIndex;
|
||||
while (insertionIndex > sectionStartIndex + 1 && lines[insertionIndex - 1].trim() === "") {
|
||||
insertionIndex -= 1;
|
||||
}
|
||||
|
||||
if (
|
||||
lines.slice(sectionStartIndex + 1, targetIndex).some((line) => line.trim() === normalizedEntry)
|
||||
) {
|
||||
return changelogContent;
|
||||
}
|
||||
|
||||
lines.splice(insertionIndex, 0, normalizedEntry);
|
||||
return `${lines.join("\n")}\n`;
|
||||
}
|
||||
|
||||
type CliArgs = {
|
||||
section: UnreleasedSection;
|
||||
entry: string;
|
||||
file: string;
|
||||
};
|
||||
|
||||
function parseCliArgs(argv: string[]): CliArgs {
|
||||
let section: UnreleasedSection | null = null;
|
||||
let entry = "";
|
||||
let file = "CHANGELOG.md";
|
||||
|
||||
for (let i = 0; i < argv.length; i += 1) {
|
||||
const arg = argv[i];
|
||||
if (arg === "--section") {
|
||||
const value = argv[i + 1];
|
||||
if (value !== "changes" && value !== "fixes") {
|
||||
throw new Error("--section must be one of: changes, fixes");
|
||||
}
|
||||
section = value;
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--entry") {
|
||||
entry = argv[i + 1] ?? "";
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
if (arg === "--file") {
|
||||
file = argv[i + 1] ?? file;
|
||||
i += 1;
|
||||
continue;
|
||||
}
|
||||
throw new Error(`unknown argument: ${arg}`);
|
||||
}
|
||||
|
||||
if (!section) {
|
||||
throw new Error("missing --section <changes|fixes>");
|
||||
}
|
||||
if (!entry.trim()) {
|
||||
throw new Error("missing --entry <text>");
|
||||
}
|
||||
return { section, entry, file };
|
||||
}
|
||||
|
||||
function runCli(): void {
|
||||
const args = parseCliArgs(process.argv.slice(2));
|
||||
const changelogPath = resolve(process.cwd(), args.file);
|
||||
const content = readFileSync(changelogPath, "utf8");
|
||||
const next = insertUnreleasedChangelogEntry(content, args.section, args.entry);
|
||||
if (next !== content) {
|
||||
writeFileSync(changelogPath, next, "utf8");
|
||||
}
|
||||
}
|
||||
|
||||
if (import.meta.url === `file://${process.argv[1]}`) {
|
||||
runCli();
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { insertUnreleasedChangelogEntry } from "../../scripts/changelog-add.ts";
|
||||
|
||||
const SAMPLE = `# Changelog
|
||||
|
||||
## 2026.2.24 (Unreleased)
|
||||
|
||||
### Changes
|
||||
|
||||
- Existing change.
|
||||
|
||||
### Fixes
|
||||
|
||||
- Existing fix.
|
||||
|
||||
## 2026.2.23
|
||||
|
||||
### Changes
|
||||
|
||||
- Older entry.
|
||||
`;
|
||||
|
||||
describe("changelog-add", () => {
|
||||
it("inserts a new unreleased fixes entry before the next version section", () => {
|
||||
const next = insertUnreleasedChangelogEntry(
|
||||
SAMPLE,
|
||||
"fixes",
|
||||
"New fix entry. (#123) Thanks @someone.",
|
||||
);
|
||||
expect(next).toContain(
|
||||
"- Existing fix.\n- New fix entry. (#123) Thanks @someone.\n\n## 2026.2.23",
|
||||
);
|
||||
});
|
||||
|
||||
it("normalizes missing bullet prefix", () => {
|
||||
const next = insertUnreleasedChangelogEntry(SAMPLE, "changes", "New change.");
|
||||
expect(next).toContain("- Existing change.\n- New change.\n\n### Fixes");
|
||||
});
|
||||
|
||||
it("does not duplicate identical entry", () => {
|
||||
const once = insertUnreleasedChangelogEntry(SAMPLE, "fixes", "New fix.");
|
||||
const twice = insertUnreleasedChangelogEntry(once, "fixes", "New fix.");
|
||||
expect(twice).toBe(once);
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user