Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,9 @@
"typecheck": "turbo run typecheck",
"typecheck:slow": "turbo run typecheck:slow",
"ci": "bun run lint && bun run typecheck && bun run test",
"lint": "oxlint -c .oxlintrc.jsonc . --deny-warnings",
"lint": "oxlint -c .oxlintrc.jsonc . --deny-warnings && bun run lint:changelog-stubs",
"lint:release-notes": "bun run scripts/check-release-notes.ts",
"lint:changelog-stubs": "bun run scripts/check-changelog-stubs.ts",
"lint:fix": "oxlint -c .oxlintrc.jsonc --fix .",
"format": "oxfmt .",
"format:check": "oxfmt --check .",
Expand Down
6 changes: 6 additions & 0 deletions packages/core/vite-plugin/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# @executor-js/vite-plugin changelog

This file exists for `changesets/action@v1` compatibility (it reads every
workspace package's `CHANGELOG.md` to build the Version Packages PR).
Canonical user-facing release notes are at `apps/cli/release-notes/next.md`
and on the GitHub Releases page.
6 changes: 6 additions & 0 deletions packages/plugins/example/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# @executor-js/plugin-example changelog

This file exists for `changesets/action@v1` compatibility (it reads every
workspace package's `CHANGELOG.md` to build the Version Packages PR).
Canonical user-facing release notes are at `apps/cli/release-notes/next.md`
and on the GitHub Releases page.
76 changes: 76 additions & 0 deletions scripts/check-changelog-stubs.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/usr/bin/env bun
/**
* Verifies every workspace package directory has a `CHANGELOG.md` file.
*
* `changesets/action@v1` (the GitHub Action wrapping the Changesets CLI in
* `release.yml`) reads every workspace package's `CHANGELOG.md` to build
* the Version Packages PR description. If any is missing, the action
* crashes with `ENOENT` at release time and blocks the release.
*
* The CLI alone (with `changelog: false` in `.changeset/config.json`)
* doesn't need them — but we run via the Action, which does.
*
* The stubs themselves are not user-facing. Canonical release notes are
* at `apps/cli/release-notes/next.md` and on the GitHub Releases page.
*
* Usage:
* bun run scripts/check-changelog-stubs.ts # fail on missing
* bun run scripts/check-changelog-stubs.ts --fix # create missing stubs
*/
import { existsSync, readFileSync, writeFileSync } from "node:fs";
import { dirname, relative, resolve } from "node:path";

const repoRoot = resolve(import.meta.dir, "..");

type Pkg = { name?: string; private?: boolean };

const findWorkspacePackages = (): string[] => {
const root = JSON.parse(readFileSync(resolve(repoRoot, "package.json"), "utf8")) as {
workspaces?: string[];
};
const patterns = root.workspaces ?? [];
const dirs = new Set<string>();
for (const pattern of patterns) {
// Bun.Glob — handles workspace patterns like "packages/*/*", "apps/*"
for (const match of new Bun.Glob(`${pattern}/package.json`).scanSync({ cwd: repoRoot })) {
dirs.add(dirname(resolve(repoRoot, match)));
}
}
return [...dirs].sort();
};

const STUB_TEMPLATE = (name: string) =>
`# ${name} changelog\n\n` +
"This file exists for `changesets/action@v1` compatibility (it reads every\n" +
"workspace package's `CHANGELOG.md` to build the Version Packages PR).\n" +
"Canonical user-facing release notes are at `apps/cli/release-notes/next.md`\n" +
"and on the GitHub Releases page.\n";

const fix = process.argv.includes("--fix");
const missing: string[] = [];

for (const pkgDir of findWorkspacePackages()) {
const changelogPath = resolve(pkgDir, "CHANGELOG.md");
if (existsSync(changelogPath)) continue;

const pkg = JSON.parse(readFileSync(resolve(pkgDir, "package.json"), "utf8")) as Pkg;
const name = pkg.name ?? relative(repoRoot, pkgDir);

if (fix) {
writeFileSync(changelogPath, STUB_TEMPLATE(name));
console.log(`Created stub: ${relative(repoRoot, changelogPath)}`);
} else {
missing.push(`${relative(repoRoot, pkgDir)} (${name})`);
}
}

if (!fix && missing.length > 0) {
console.error(
`\nMissing CHANGELOG.md in ${missing.length} workspace package(s):\n - ${missing.join("\n - ")}\n\n` +
"These are required by `changesets/action@v1` (the GitHub Action wrapping\n" +
"Changesets in release.yml). Without them, release.yml crashes with ENOENT\n" +
"and the Version Packages PR can't open.\n\n" +
"Run `bun run scripts/check-changelog-stubs.ts --fix` to create stubs.\n",
);
process.exit(1);
}
Loading