@williamthorsen/release-kit 4.8.0 → 5.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +134 -4
- package/README.md +404 -40
- package/cliff.toml.template +2 -1
- package/dist/esm/.cache +1 -1
- package/dist/esm/assertCleanWorkingTree.js +1 -1
- package/dist/esm/bin/release-kit.js +45 -14
- package/dist/esm/buildChangelogEntries.d.ts +3 -0
- package/dist/esm/{generateChangelogJson.js → buildChangelogEntries.js} +40 -77
- package/dist/esm/buildDependencyGraph.d.ts +4 -3
- package/dist/esm/buildDependencyGraph.js +18 -11
- package/dist/esm/buildReleaseSummary.js +12 -4
- package/dist/esm/buildSyntheticChangelogEntry.d.ts +5 -0
- package/dist/esm/buildSyntheticChangelogEntry.js +13 -0
- package/dist/esm/bumpAllVersions.d.ts +1 -0
- package/dist/esm/bumpAllVersions.js +16 -2
- package/dist/esm/bumpVersion.js +3 -0
- package/dist/esm/changelogJsonFile.d.ts +4 -0
- package/dist/esm/changelogJsonFile.js +68 -0
- package/dist/esm/commitCommand.js +1 -1
- package/dist/esm/compareVersions.d.ts +1 -0
- package/dist/esm/compareVersions.js +27 -0
- package/dist/esm/createGithubRelease.d.ts +6 -2
- package/dist/esm/createGithubRelease.js +17 -17
- package/dist/esm/createGithubReleaseCommand.d.ts +1 -0
- package/dist/esm/createGithubReleaseCommand.js +41 -0
- package/dist/esm/decideRelease.d.ts +25 -0
- package/dist/esm/decideRelease.js +28 -0
- package/dist/esm/defaults.d.ts +1 -0
- package/dist/esm/defaults.js +7 -3
- package/dist/esm/deriveWorkspaceConfig.d.ts +2 -0
- package/dist/esm/deriveWorkspaceConfig.js +37 -0
- package/dist/esm/detectUndeclaredTagPrefixes.d.ts +7 -0
- package/dist/esm/detectUndeclaredTagPrefixes.js +46 -0
- package/dist/esm/generateChangelogs.d.ts +1 -1
- package/dist/esm/generateChangelogs.js +14 -3
- package/dist/esm/getCommitsSinceTarget.d.ts +1 -1
- package/dist/esm/getCommitsSinceTarget.js +8 -4
- package/dist/esm/index.d.ts +2 -39
- package/dist/esm/index.js +0 -75
- package/dist/esm/init/initCommand.js +1 -1
- package/dist/esm/init/scaffold.d.ts +1 -1
- package/dist/esm/init/scaffold.js +8 -5
- package/dist/esm/init/templates.d.ts +1 -0
- package/dist/esm/init/templates.js +35 -5
- package/dist/esm/injectReleaseNotesIntoReadme.d.ts +6 -1
- package/dist/esm/injectReleaseNotesIntoReadme.js +20 -7
- package/dist/esm/loadConfig.d.ts +12 -2
- package/dist/esm/loadConfig.js +161 -14
- package/dist/esm/parseRequestedTags.d.ts +1 -0
- package/dist/esm/parseRequestedTags.js +10 -0
- package/dist/esm/prepareCommand.d.ts +3 -1
- package/dist/esm/prepareCommand.js +121 -31
- package/dist/esm/previewTagPrefixes.d.ts +30 -0
- package/dist/esm/previewTagPrefixes.js +120 -0
- package/dist/esm/propagateBumps.d.ts +1 -0
- package/dist/esm/propagateBumps.js +1 -1
- package/dist/esm/publish.d.ts +0 -1
- package/dist/esm/publish.js +3 -3
- package/dist/esm/publishCommand.js +18 -14
- package/dist/esm/pushCommand.js +5 -4
- package/dist/esm/readCurrentVersion.d.ts +1 -0
- package/dist/esm/readCurrentVersion.js +21 -0
- package/dist/esm/releasePrepare.d.ts +2 -0
- package/dist/esm/releasePrepare.js +140 -54
- package/dist/esm/releasePrepareMono.js +312 -143
- package/dist/esm/releasePrepareProject.d.ts +9 -0
- package/dist/esm/releasePrepareProject.js +109 -0
- package/dist/esm/renderReleaseNotes.d.ts +1 -0
- package/dist/esm/renderReleaseNotes.js +29 -2
- package/dist/esm/reportPrepare.js +146 -73
- package/dist/esm/resolveCliffConfigPath.js +1 -1
- package/dist/esm/resolveCommandTags.d.ts +1 -1
- package/dist/esm/resolveCommandTags.js +17 -13
- package/dist/esm/resolveReleaseNotesConfig.d.ts +8 -1
- package/dist/esm/resolveReleaseNotesConfig.js +17 -7
- package/dist/esm/resolveReleaseTags.d.ts +2 -1
- package/dist/esm/resolveReleaseTags.js +19 -14
- package/dist/esm/showTagPrefixesCommand.d.ts +1 -0
- package/dist/esm/showTagPrefixesCommand.js +84 -0
- package/dist/esm/sync-labels/initCommand.js +1 -1
- package/dist/esm/sync-labels/presets.js +1 -1
- package/dist/esm/tagCommand.js +1 -1
- package/dist/esm/types.d.ts +77 -19
- package/dist/esm/validateConfig.js +205 -36
- package/dist/esm/validateOnlyExcludesStrandedDependents.d.ts +14 -0
- package/dist/esm/validateOnlyExcludesStrandedDependents.js +109 -0
- package/dist/esm/version.d.ts +1 -1
- package/dist/esm/version.js +1 -1
- package/dist/esm/writeReleaseNotesPreviews.d.ts +18 -0
- package/dist/esm/writeReleaseNotesPreviews.js +65 -0
- package/package.json +5 -2
- package/presets/labels/common.yaml +9 -6
- package/schemas/label-map.json +24 -0
- package/dist/esm/component.d.ts +0 -2
- package/dist/esm/component.js +0 -14
- package/dist/esm/findPackageRoot.d.ts +0 -1
- package/dist/esm/findPackageRoot.js +0 -17
- package/dist/esm/generateChangelogJson.d.ts +0 -7
- package/dist/esm/githubReleaseCommand.d.ts +0 -1
- package/dist/esm/githubReleaseCommand.js +0 -35
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function createGithubReleaseCommand(argv: string[]): Promise<void>;
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { parseArgs, translateParseError } from "@williamthorsen/nmr-core";
|
|
2
|
+
import { createGithubReleases } from "./createGithubRelease.js";
|
|
3
|
+
import { parseRequestedTags } from "./parseRequestedTags.js";
|
|
4
|
+
import { resolveCommandTags } from "./resolveCommandTags.js";
|
|
5
|
+
import { resolveReleaseNotesConfig } from "./resolveReleaseNotesConfig.js";
|
|
6
|
+
const createGithubReleaseFlagSchema = {
|
|
7
|
+
dryRun: { long: "--dry-run", type: "boolean" },
|
|
8
|
+
tags: { long: "--tags", type: "string" }
|
|
9
|
+
};
|
|
10
|
+
async function createGithubReleaseCommand(argv) {
|
|
11
|
+
let parsed;
|
|
12
|
+
try {
|
|
13
|
+
parsed = parseArgs(argv, createGithubReleaseFlagSchema);
|
|
14
|
+
} catch (error) {
|
|
15
|
+
console.error(`Error: ${translateParseError(error)}`);
|
|
16
|
+
process.exit(1);
|
|
17
|
+
}
|
|
18
|
+
const { dryRun } = parsed.flags;
|
|
19
|
+
const requestedTags = parseRequestedTags(parsed.flags.tags);
|
|
20
|
+
const resolvedTags = await resolveCommandTags(requestedTags);
|
|
21
|
+
const { changelogJsonOutputPath, sectionOrder } = await resolveReleaseNotesConfig({ strictLoad: true });
|
|
22
|
+
let outcome;
|
|
23
|
+
try {
|
|
24
|
+
outcome = createGithubReleases(resolvedTags, changelogJsonOutputPath, dryRun, sectionOrder);
|
|
25
|
+
} catch (error) {
|
|
26
|
+
console.error(`Error creating GitHub Releases: ${error instanceof Error ? error.message : String(error)}`);
|
|
27
|
+
process.exit(1);
|
|
28
|
+
}
|
|
29
|
+
if (requestedTags !== void 0 && outcome.created.length === 0) {
|
|
30
|
+
console.error(
|
|
31
|
+
`Error: no GitHub Releases were created for requested tags: ${outcome.skipped.join(", ")}. Each was skipped (missing changelog entry, no all-audience content, or empty rendered body).`
|
|
32
|
+
);
|
|
33
|
+
process.exit(1);
|
|
34
|
+
}
|
|
35
|
+
if (outcome.skipped.length > 0) {
|
|
36
|
+
console.info(`Skipped ${outcome.skipped.length} tag(s) with no releasable content: ${outcome.skipped.join(", ")}.`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export {
|
|
40
|
+
createGithubReleaseCommand
|
|
41
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { Commit, ReleaseType, VersionPatterns, WorkTypeConfig } from './types.ts';
|
|
2
|
+
export interface DecideReleaseArgs {
|
|
3
|
+
commits: readonly Commit[];
|
|
4
|
+
force?: boolean | undefined;
|
|
5
|
+
bumpOverride: ReleaseType | undefined;
|
|
6
|
+
workTypes: Record<string, WorkTypeConfig>;
|
|
7
|
+
versionPatterns: VersionPatterns;
|
|
8
|
+
scopeAliases: Record<string, string> | undefined;
|
|
9
|
+
skipReasons: {
|
|
10
|
+
noCommits: string;
|
|
11
|
+
noBumpWorthy: string;
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
export type DecideReleaseResult = {
|
|
15
|
+
outcome: 'release';
|
|
16
|
+
releaseType: ReleaseType;
|
|
17
|
+
parsedCommitCount: number;
|
|
18
|
+
unparseableCommits: Commit[] | undefined;
|
|
19
|
+
} | {
|
|
20
|
+
outcome: 'skip';
|
|
21
|
+
skipReason: string;
|
|
22
|
+
parsedCommitCount: number;
|
|
23
|
+
unparseableCommits: Commit[] | undefined;
|
|
24
|
+
};
|
|
25
|
+
export declare function decideRelease(args: DecideReleaseArgs): DecideReleaseResult;
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { determineBumpType } from "./determineBumpType.js";
|
|
2
|
+
import { parseCommitMessage } from "./parseCommitMessage.js";
|
|
3
|
+
function decideRelease(args) {
|
|
4
|
+
const { commits, force = false, bumpOverride, workTypes, versionPatterns, scopeAliases, skipReasons } = args;
|
|
5
|
+
const parsedCommits = [];
|
|
6
|
+
const unparseable = [];
|
|
7
|
+
for (const commit of commits) {
|
|
8
|
+
const parsed = parseCommitMessage(commit.message, commit.hash, workTypes, scopeAliases);
|
|
9
|
+
if (parsed === void 0) {
|
|
10
|
+
unparseable.push(commit);
|
|
11
|
+
} else {
|
|
12
|
+
parsedCommits.push(parsed);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
const parsedCommitCount = parsedCommits.length;
|
|
16
|
+
const unparseableCommits = unparseable.length > 0 ? unparseable : void 0;
|
|
17
|
+
const naturalBump = determineBumpType(parsedCommits, workTypes, versionPatterns);
|
|
18
|
+
const shouldRelease = naturalBump !== void 0 || force;
|
|
19
|
+
if (!shouldRelease) {
|
|
20
|
+
const skipReason = commits.length === 0 ? skipReasons.noCommits : skipReasons.noBumpWorthy;
|
|
21
|
+
return { outcome: "skip", skipReason, parsedCommitCount, unparseableCommits };
|
|
22
|
+
}
|
|
23
|
+
const releaseType = bumpOverride ?? naturalBump ?? "patch";
|
|
24
|
+
return { outcome: "release", releaseType, parsedCommitCount, unparseableCommits };
|
|
25
|
+
}
|
|
26
|
+
export {
|
|
27
|
+
decideRelease
|
|
28
|
+
};
|
package/dist/esm/defaults.d.ts
CHANGED
|
@@ -3,3 +3,4 @@ export declare const DEFAULT_WORK_TYPES: Record<string, WorkTypeConfig>;
|
|
|
3
3
|
export declare const DEFAULT_VERSION_PATTERNS: VersionPatterns;
|
|
4
4
|
export declare const DEFAULT_CHANGELOG_JSON_CONFIG: ChangelogJsonConfig;
|
|
5
5
|
export declare const DEFAULT_RELEASE_NOTES_CONFIG: ReleaseNotesConfig;
|
|
6
|
+
export declare const DEFAULT_PROJECT_TAG_PREFIX = "v";
|
package/dist/esm/defaults.js
CHANGED
|
@@ -11,6 +11,9 @@ const DEFAULT_WORK_TYPES = {
|
|
|
11
11
|
ci: { header: "CI" },
|
|
12
12
|
deps: { header: "Dependencies", aliases: ["dep"] },
|
|
13
13
|
docs: { header: "Documentation", aliases: ["doc"] },
|
|
14
|
+
ai: { header: "Agentic support" },
|
|
15
|
+
// `fmt` is retained for bump-determination (`parseCommitMessage`), even though
|
|
16
|
+
// `cliff.toml.template` skips `fmt:` commits so they never enter the changelog.
|
|
14
17
|
fmt: { header: "Formatting" }
|
|
15
18
|
};
|
|
16
19
|
const DEFAULT_VERSION_PATTERNS = {
|
|
@@ -20,14 +23,15 @@ const DEFAULT_VERSION_PATTERNS = {
|
|
|
20
23
|
const DEFAULT_CHANGELOG_JSON_CONFIG = {
|
|
21
24
|
enabled: true,
|
|
22
25
|
outputPath: ".meta/changelog.json",
|
|
23
|
-
devOnlySections: ["CI", "Dependencies", "
|
|
26
|
+
devOnlySections: ["Agentic support", "CI", "Dependencies", "Internal", "Refactoring", "Tests", "Tooling"]
|
|
24
27
|
};
|
|
25
28
|
const DEFAULT_RELEASE_NOTES_CONFIG = {
|
|
26
|
-
shouldInjectIntoReadme: false
|
|
27
|
-
shouldCreateGithubRelease: false
|
|
29
|
+
shouldInjectIntoReadme: false
|
|
28
30
|
};
|
|
31
|
+
const DEFAULT_PROJECT_TAG_PREFIX = "v";
|
|
29
32
|
export {
|
|
30
33
|
DEFAULT_CHANGELOG_JSON_CONFIG,
|
|
34
|
+
DEFAULT_PROJECT_TAG_PREFIX,
|
|
31
35
|
DEFAULT_RELEASE_NOTES_CONFIG,
|
|
32
36
|
DEFAULT_VERSION_PATTERNS,
|
|
33
37
|
DEFAULT_WORK_TYPES
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { readFileSync } from "node:fs";
|
|
2
|
+
import { basename } from "node:path";
|
|
3
|
+
import { isRecord } from "./typeGuards.js";
|
|
4
|
+
function deriveWorkspaceConfig(workspacePath) {
|
|
5
|
+
const dir = basename(workspacePath);
|
|
6
|
+
const packageJsonPath = `${workspacePath}/package.json`;
|
|
7
|
+
let parsed;
|
|
8
|
+
try {
|
|
9
|
+
parsed = JSON.parse(readFileSync(packageJsonPath, "utf8"));
|
|
10
|
+
} catch (error) {
|
|
11
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
12
|
+
throw new Error(`Failed to read ${packageJsonPath}: ${message}`);
|
|
13
|
+
}
|
|
14
|
+
const name = isRecord(parsed) ? parsed.name : void 0;
|
|
15
|
+
if (typeof name !== "string" || name.length === 0) {
|
|
16
|
+
throw new Error(`${packageJsonPath} is missing a 'name' field (required for tag derivation).`);
|
|
17
|
+
}
|
|
18
|
+
const unscopedName = stripNpmScope(name);
|
|
19
|
+
return {
|
|
20
|
+
dir,
|
|
21
|
+
name,
|
|
22
|
+
tagPrefix: `${unscopedName}-v`,
|
|
23
|
+
workspacePath,
|
|
24
|
+
packageFiles: [packageJsonPath],
|
|
25
|
+
changelogPaths: [workspacePath],
|
|
26
|
+
paths: [`${workspacePath}/**`]
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
function stripNpmScope(name) {
|
|
30
|
+
if (name.startsWith("@") && name.includes("/")) {
|
|
31
|
+
return name.slice(name.indexOf("/") + 1);
|
|
32
|
+
}
|
|
33
|
+
return name;
|
|
34
|
+
}
|
|
35
|
+
export {
|
|
36
|
+
deriveWorkspaceConfig
|
|
37
|
+
};
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
const EXAMPLE_TAG_LIMIT = 3;
|
|
3
|
+
const CANDIDATE_TAG_PATTERN = /^(?<prefix>[a-z][a-z0-9-]*-v)\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/;
|
|
4
|
+
function detectUndeclaredTagPrefixes(knownPrefixes) {
|
|
5
|
+
const known = new Set(knownPrefixes);
|
|
6
|
+
let rawOutput;
|
|
7
|
+
try {
|
|
8
|
+
rawOutput = execFileSync("git", ["tag", "--list"], {
|
|
9
|
+
encoding: "utf8",
|
|
10
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
11
|
+
});
|
|
12
|
+
} catch {
|
|
13
|
+
return [];
|
|
14
|
+
}
|
|
15
|
+
const grouped = /* @__PURE__ */ new Map();
|
|
16
|
+
for (const line of rawOutput.split("\n")) {
|
|
17
|
+
const tag = line.trim();
|
|
18
|
+
if (tag === "") continue;
|
|
19
|
+
const match = CANDIDATE_TAG_PATTERN.exec(tag);
|
|
20
|
+
if (match === null) continue;
|
|
21
|
+
const prefix = match.groups?.prefix ?? "";
|
|
22
|
+
if (prefix === "" || known.has(prefix)) continue;
|
|
23
|
+
let tags = grouped.get(prefix);
|
|
24
|
+
if (tags === void 0) {
|
|
25
|
+
tags = [];
|
|
26
|
+
grouped.set(prefix, tags);
|
|
27
|
+
}
|
|
28
|
+
tags.push(tag);
|
|
29
|
+
}
|
|
30
|
+
const results = [];
|
|
31
|
+
for (const [prefix, tags] of grouped) {
|
|
32
|
+
results.push({
|
|
33
|
+
prefix,
|
|
34
|
+
tagCount: tags.length,
|
|
35
|
+
exampleTags: tags.slice(0, EXAMPLE_TAG_LIMIT),
|
|
36
|
+
suggestedDir: stripTrailingTagMarker(prefix)
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
return results.sort((a, b) => a.prefix.localeCompare(b.prefix));
|
|
40
|
+
}
|
|
41
|
+
function stripTrailingTagMarker(prefix) {
|
|
42
|
+
return prefix.endsWith("-v") ? prefix.slice(0, -2) : prefix;
|
|
43
|
+
}
|
|
44
|
+
export {
|
|
45
|
+
detectUndeclaredTagPrefixes
|
|
46
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ReleaseConfig } from './types.ts';
|
|
2
|
-
export declare function buildTagPattern(
|
|
2
|
+
export declare function buildTagPattern(tagPrefixes: readonly string[]): string;
|
|
3
3
|
export interface GenerateChangelogOptions {
|
|
4
4
|
tagPattern?: string;
|
|
5
5
|
includePaths?: string[];
|
|
@@ -3,8 +3,19 @@ import { copyFileSync, mkdtempSync, rmSync } from "node:fs";
|
|
|
3
3
|
import { tmpdir } from "node:os";
|
|
4
4
|
import { join } from "node:path";
|
|
5
5
|
import { resolveCliffConfigPath } from "./resolveCliffConfigPath.js";
|
|
6
|
-
function buildTagPattern(
|
|
7
|
-
|
|
6
|
+
function buildTagPattern(tagPrefixes) {
|
|
7
|
+
if (tagPrefixes.length === 0) {
|
|
8
|
+
throw new Error("buildTagPattern: tagPrefixes must contain at least one entry");
|
|
9
|
+
}
|
|
10
|
+
if (tagPrefixes.length === 1) {
|
|
11
|
+
const single = tagPrefixes[0] ?? "";
|
|
12
|
+
return `${single}[0-9].*`;
|
|
13
|
+
}
|
|
14
|
+
const escaped = tagPrefixes.map(escapeRegex);
|
|
15
|
+
return `(${escaped.join("|")})[0-9].*`;
|
|
16
|
+
}
|
|
17
|
+
function escapeRegex(value) {
|
|
18
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, String.raw`\$&`);
|
|
8
19
|
}
|
|
9
20
|
function generateChangelog(config, changelogPath, tag, dryRun, options) {
|
|
10
21
|
const resolvedConfigPath = resolveCliffConfigPath(config.cliffConfigPath, import.meta.url);
|
|
@@ -41,7 +52,7 @@ function generateChangelog(config, changelogPath, tag, dryRun, options) {
|
|
|
41
52
|
}
|
|
42
53
|
}
|
|
43
54
|
function generateChangelogs(config, tag, dryRun) {
|
|
44
|
-
const tagPattern = buildTagPattern(config.tagPrefix);
|
|
55
|
+
const tagPattern = buildTagPattern([config.tagPrefix]);
|
|
45
56
|
const results = [];
|
|
46
57
|
for (const changelogPath of config.changelogPaths) {
|
|
47
58
|
results.push(...generateChangelog(config, changelogPath, tag, dryRun, { tagPattern }));
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Commit } from './types.ts';
|
|
2
|
-
export declare function getCommitsSinceTarget(
|
|
2
|
+
export declare function getCommitsSinceTarget(tagPrefixes: readonly string[], paths?: string[]): {
|
|
3
3
|
tag: string | undefined;
|
|
4
4
|
commits: Commit[];
|
|
5
5
|
};
|
|
@@ -6,9 +6,13 @@ function isNoTagError(err) {
|
|
|
6
6
|
function errorMessage(err) {
|
|
7
7
|
return err instanceof Error ? err.message : String(err);
|
|
8
8
|
}
|
|
9
|
-
function findLatestTag(
|
|
9
|
+
function findLatestTag(tagPrefixes) {
|
|
10
|
+
if (tagPrefixes.length === 0) {
|
|
11
|
+
throw new Error("findLatestTag: tagPrefixes must contain at least one entry");
|
|
12
|
+
}
|
|
13
|
+
const matchArgs = tagPrefixes.map((prefix) => `--match=${prefix}*`);
|
|
10
14
|
try {
|
|
11
|
-
const tagResult = execFileSync("git", ["describe", "--tags", "--abbrev=0",
|
|
15
|
+
const tagResult = execFileSync("git", ["describe", "--tags", "--abbrev=0", ...matchArgs], {
|
|
12
16
|
encoding: "utf8",
|
|
13
17
|
stdio: ["pipe", "pipe", "pipe"]
|
|
14
18
|
}).trim();
|
|
@@ -35,8 +39,8 @@ function parseLogOutput(logOutput) {
|
|
|
35
39
|
}
|
|
36
40
|
return commits;
|
|
37
41
|
}
|
|
38
|
-
function getCommitsSinceTarget(
|
|
39
|
-
const tag = findLatestTag(
|
|
42
|
+
function getCommitsSinceTarget(tagPrefixes, paths) {
|
|
43
|
+
const tag = findLatestTag(tagPrefixes);
|
|
40
44
|
const range = tag === void 0 ? "HEAD" : `${tag}..HEAD`;
|
|
41
45
|
const format = `%s${FIELD_SEPARATOR}%H`;
|
|
42
46
|
const args = ["log", range, `--pretty=format:${format}`];
|
package/dist/esm/index.d.ts
CHANGED
|
@@ -1,39 +1,2 @@
|
|
|
1
|
-
export type {
|
|
2
|
-
export type {
|
|
3
|
-
export type { GenerateChangelogOptions } from './generateChangelogs.ts';
|
|
4
|
-
export type { PublishOptions } from './publish.ts';
|
|
5
|
-
export type { ReleasePrepareOptions } from './releasePrepare.ts';
|
|
6
|
-
export type { ResolvedTag } from './resolveReleaseTags.ts';
|
|
7
|
-
export type { LabelDefinition, SyncLabelsConfig } from './sync-labels/types.ts';
|
|
8
|
-
export type { BumpResult, ChangelogAudience, ChangelogEntry, ChangelogItem, ChangelogJsonConfig, ChangelogSection, Commit, ComponentConfig, ComponentOverride, ComponentPrepareResult, MonorepoReleaseConfig, ParsedCommit, PrepareResult, ReleaseConfig, ReleaseKitConfig, ReleaseNotesConfig, ReleaseType, VersionPatterns, WorkTypeConfig, } from './types.ts';
|
|
9
|
-
export { DEFAULT_CHANGELOG_JSON_CONFIG, DEFAULT_RELEASE_NOTES_CONFIG, DEFAULT_VERSION_PATTERNS, DEFAULT_WORK_TYPES, } from './defaults.ts';
|
|
10
|
-
export { buildReleaseSummary } from './buildReleaseSummary.ts';
|
|
11
|
-
export { bumpAllVersions } from './bumpAllVersions.ts';
|
|
12
|
-
export { bumpVersion } from './bumpVersion.ts';
|
|
13
|
-
export { commitCommand } from './commitCommand.ts';
|
|
14
|
-
export { component } from './component.ts';
|
|
15
|
-
export type { CreateGithubReleaseOptions } from './createGithubRelease.ts';
|
|
16
|
-
export { createGithubRelease, createGithubReleases } from './createGithubRelease.ts';
|
|
17
|
-
export { createTags } from './createTags.ts';
|
|
18
|
-
export { deleteFileIfExists } from './deleteFileIfExists.ts';
|
|
19
|
-
export { detectPackageManager } from './detectPackageManager.ts';
|
|
20
|
-
export { determineBumpType } from './determineBumpType.ts';
|
|
21
|
-
export { discoverWorkspaces } from './discoverWorkspaces.ts';
|
|
22
|
-
export { generateChangelogJson, generateSyntheticChangelogJson } from './generateChangelogJson.ts';
|
|
23
|
-
export { generateChangelog, generateChangelogs } from './generateChangelogs.ts';
|
|
24
|
-
export { getCommitsSinceTarget } from './getCommitsSinceTarget.ts';
|
|
25
|
-
export { injectReleaseNotesIntoReadme, resolveReadmePath } from './injectReleaseNotesIntoReadme.ts';
|
|
26
|
-
export { injectSection } from './injectSection.ts';
|
|
27
|
-
export { COMMIT_PREPROCESSOR_PATTERNS, parseCommitMessage } from './parseCommitMessage.ts';
|
|
28
|
-
export { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE, writeReleaseTags } from './prepareCommand.ts';
|
|
29
|
-
export { publishPackage } from './publish.ts';
|
|
30
|
-
export type { PushReleaseOptions } from './pushRelease.ts';
|
|
31
|
-
export { pushRelease } from './pushRelease.ts';
|
|
32
|
-
export { releasePrepare } from './releasePrepare.ts';
|
|
33
|
-
export { releasePrepareMono } from './releasePrepareMono.ts';
|
|
34
|
-
export type { RenderOptions } from './renderReleaseNotes.ts';
|
|
35
|
-
export { matchesAudience, renderReleaseNotesMulti, renderReleaseNotesSingle } from './renderReleaseNotes.ts';
|
|
36
|
-
export { reportPrepare } from './reportPrepare.ts';
|
|
37
|
-
export { resolveCommandTags } from './resolveCommandTags.ts';
|
|
38
|
-
export { resolveReleaseTags } from './resolveReleaseTags.ts';
|
|
39
|
-
export { stripScope } from './stripScope.ts';
|
|
1
|
+
export type { SyncLabelsConfig } from './sync-labels/types.ts';
|
|
2
|
+
export type { ReleaseKitConfig } from './types.ts';
|
package/dist/esm/index.js
CHANGED
|
@@ -1,75 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
DEFAULT_CHANGELOG_JSON_CONFIG,
|
|
3
|
-
DEFAULT_RELEASE_NOTES_CONFIG,
|
|
4
|
-
DEFAULT_VERSION_PATTERNS,
|
|
5
|
-
DEFAULT_WORK_TYPES
|
|
6
|
-
} from "./defaults.js";
|
|
7
|
-
import { buildReleaseSummary } from "./buildReleaseSummary.js";
|
|
8
|
-
import { bumpAllVersions } from "./bumpAllVersions.js";
|
|
9
|
-
import { bumpVersion } from "./bumpVersion.js";
|
|
10
|
-
import { commitCommand } from "./commitCommand.js";
|
|
11
|
-
import { component } from "./component.js";
|
|
12
|
-
import { createGithubRelease, createGithubReleases } from "./createGithubRelease.js";
|
|
13
|
-
import { createTags } from "./createTags.js";
|
|
14
|
-
import { deleteFileIfExists } from "./deleteFileIfExists.js";
|
|
15
|
-
import { detectPackageManager } from "./detectPackageManager.js";
|
|
16
|
-
import { determineBumpType } from "./determineBumpType.js";
|
|
17
|
-
import { discoverWorkspaces } from "./discoverWorkspaces.js";
|
|
18
|
-
import { generateChangelogJson, generateSyntheticChangelogJson } from "./generateChangelogJson.js";
|
|
19
|
-
import { generateChangelog, generateChangelogs } from "./generateChangelogs.js";
|
|
20
|
-
import { getCommitsSinceTarget } from "./getCommitsSinceTarget.js";
|
|
21
|
-
import { injectReleaseNotesIntoReadme, resolveReadmePath } from "./injectReleaseNotesIntoReadme.js";
|
|
22
|
-
import { injectSection } from "./injectSection.js";
|
|
23
|
-
import { COMMIT_PREPROCESSOR_PATTERNS, parseCommitMessage } from "./parseCommitMessage.js";
|
|
24
|
-
import { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE, writeReleaseTags } from "./prepareCommand.js";
|
|
25
|
-
import { publishPackage } from "./publish.js";
|
|
26
|
-
import { pushRelease } from "./pushRelease.js";
|
|
27
|
-
import { releasePrepare } from "./releasePrepare.js";
|
|
28
|
-
import { releasePrepareMono } from "./releasePrepareMono.js";
|
|
29
|
-
import { matchesAudience, renderReleaseNotesMulti, renderReleaseNotesSingle } from "./renderReleaseNotes.js";
|
|
30
|
-
import { reportPrepare } from "./reportPrepare.js";
|
|
31
|
-
import { resolveCommandTags } from "./resolveCommandTags.js";
|
|
32
|
-
import { resolveReleaseTags } from "./resolveReleaseTags.js";
|
|
33
|
-
import { stripScope } from "./stripScope.js";
|
|
34
|
-
export {
|
|
35
|
-
COMMIT_PREPROCESSOR_PATTERNS,
|
|
36
|
-
DEFAULT_CHANGELOG_JSON_CONFIG,
|
|
37
|
-
DEFAULT_RELEASE_NOTES_CONFIG,
|
|
38
|
-
DEFAULT_VERSION_PATTERNS,
|
|
39
|
-
DEFAULT_WORK_TYPES,
|
|
40
|
-
RELEASE_SUMMARY_FILE,
|
|
41
|
-
RELEASE_TAGS_FILE,
|
|
42
|
-
buildReleaseSummary,
|
|
43
|
-
bumpAllVersions,
|
|
44
|
-
bumpVersion,
|
|
45
|
-
commitCommand,
|
|
46
|
-
component,
|
|
47
|
-
createGithubRelease,
|
|
48
|
-
createGithubReleases,
|
|
49
|
-
createTags,
|
|
50
|
-
deleteFileIfExists,
|
|
51
|
-
detectPackageManager,
|
|
52
|
-
determineBumpType,
|
|
53
|
-
discoverWorkspaces,
|
|
54
|
-
generateChangelog,
|
|
55
|
-
generateChangelogJson,
|
|
56
|
-
generateChangelogs,
|
|
57
|
-
generateSyntheticChangelogJson,
|
|
58
|
-
getCommitsSinceTarget,
|
|
59
|
-
injectReleaseNotesIntoReadme,
|
|
60
|
-
injectSection,
|
|
61
|
-
matchesAudience,
|
|
62
|
-
parseCommitMessage,
|
|
63
|
-
publishPackage,
|
|
64
|
-
pushRelease,
|
|
65
|
-
releasePrepare,
|
|
66
|
-
releasePrepareMono,
|
|
67
|
-
renderReleaseNotesMulti,
|
|
68
|
-
renderReleaseNotesSingle,
|
|
69
|
-
reportPrepare,
|
|
70
|
-
resolveCommandTags,
|
|
71
|
-
resolveReadmePath,
|
|
72
|
-
resolveReleaseTags,
|
|
73
|
-
stripScope,
|
|
74
|
-
writeReleaseTags
|
|
75
|
-
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { printError, printStep, printSuccess, reportWriteResult } from "@williamthorsen/
|
|
1
|
+
import { printError, printStep, printSuccess, reportWriteResult } from "@williamthorsen/nmr-core";
|
|
2
2
|
import { hasPackageJson, isGitRepo, usesPnpm } from "./checks.js";
|
|
3
3
|
import { detectRepoType } from "./detectRepoType.js";
|
|
4
4
|
import { scaffoldFiles } from "./scaffold.js";
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from "node:fs";
|
|
2
2
|
import { resolve } from "node:path";
|
|
3
|
-
import { writeFileWithCheck } from "@williamthorsen/
|
|
4
|
-
import {
|
|
5
|
-
import { publishWorkflow, releaseConfigScript, releaseWorkflow } from "./templates.js";
|
|
3
|
+
import { findPackageRoot, writeFileWithCheck } from "@williamthorsen/nmr-core";
|
|
4
|
+
import { createGithubReleaseWorkflow, publishWorkflow, releaseConfigScript, releaseWorkflow } from "./templates.js";
|
|
6
5
|
function copyCliffTemplate(dryRun, overwrite) {
|
|
7
6
|
const destPath = ".config/git-cliff.toml";
|
|
8
7
|
const root = findPackageRoot(import.meta.url);
|
|
@@ -21,8 +20,12 @@ function copyCliffTemplate(dryRun, overwrite) {
|
|
|
21
20
|
}
|
|
22
21
|
function scaffoldFiles({ repoType, dryRun, overwrite, withConfig }) {
|
|
23
22
|
const results = [
|
|
24
|
-
writeFileWithCheck(".github/workflows/release.yaml",
|
|
25
|
-
|
|
23
|
+
writeFileWithCheck(".github/workflows/create-github-release.yaml", createGithubReleaseWorkflow(repoType), {
|
|
24
|
+
dryRun,
|
|
25
|
+
overwrite
|
|
26
|
+
}),
|
|
27
|
+
writeFileWithCheck(".github/workflows/publish.yaml", publishWorkflow(repoType), { dryRun, overwrite }),
|
|
28
|
+
writeFileWithCheck(".github/workflows/release.yaml", releaseWorkflow(repoType), { dryRun, overwrite })
|
|
26
29
|
];
|
|
27
30
|
if (withConfig) {
|
|
28
31
|
results.push(
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { RepoType } from './detectRepoType.ts';
|
|
2
2
|
export declare function releaseConfigScript(repoType: RepoType): string;
|
|
3
3
|
export declare function publishWorkflow(repoType: RepoType): string;
|
|
4
|
+
export declare function createGithubReleaseWorkflow(repoType: RepoType): string;
|
|
4
5
|
export declare function releaseWorkflow(repoType: RepoType): string;
|
|
@@ -3,8 +3,12 @@ function releaseConfigScript(repoType) {
|
|
|
3
3
|
return `import type { ReleaseKitConfig } from '@williamthorsen/release-kit';
|
|
4
4
|
|
|
5
5
|
const config: ReleaseKitConfig = {
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
releaseNotes: {
|
|
7
|
+
shouldInjectIntoReadme: true,
|
|
8
|
+
},
|
|
9
|
+
|
|
10
|
+
// Uncomment to exclude workspaces from release processing:
|
|
11
|
+
// workspaces: [
|
|
8
12
|
// { dir: 'my-package', shouldExclude: true },
|
|
9
13
|
// ],
|
|
10
14
|
|
|
@@ -23,6 +27,10 @@ export default config;
|
|
|
23
27
|
return `import type { ReleaseKitConfig } from '@williamthorsen/release-kit';
|
|
24
28
|
|
|
25
29
|
const config: ReleaseKitConfig = {
|
|
30
|
+
releaseNotes: {
|
|
31
|
+
shouldInjectIntoReadme: true,
|
|
32
|
+
},
|
|
33
|
+
|
|
26
34
|
// Formatting: prettier is auto-detected. Set formatCommand to override.
|
|
27
35
|
|
|
28
36
|
// Uncomment to override the default version patterns:
|
|
@@ -54,6 +62,27 @@ jobs:
|
|
|
54
62
|
uses: williamthorsen/node-monorepo-tools/.github/workflows/publish.reusable.yaml@workflow/publish-v1
|
|
55
63
|
with:
|
|
56
64
|
provenance: true
|
|
65
|
+
tags: \${{ github.ref_name }}
|
|
66
|
+
`;
|
|
67
|
+
}
|
|
68
|
+
function createGithubReleaseWorkflow(repoType) {
|
|
69
|
+
const tagPattern = repoType === "monorepo" ? "'*-v[0-9]*.[0-9]*.[0-9]*'" : "'v[0-9]*.[0-9]*.[0-9]*'";
|
|
70
|
+
return `# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
71
|
+
name: Create GitHub Release
|
|
72
|
+
|
|
73
|
+
on:
|
|
74
|
+
push:
|
|
75
|
+
tags:
|
|
76
|
+
- ${tagPattern}
|
|
77
|
+
|
|
78
|
+
permissions:
|
|
79
|
+
contents: write
|
|
80
|
+
|
|
81
|
+
jobs:
|
|
82
|
+
create-github-release:
|
|
83
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/create-github-release.reusable.yaml@workflow/create-github-release-v1
|
|
84
|
+
with:
|
|
85
|
+
tag: \${{ github.ref_name }}
|
|
57
86
|
`;
|
|
58
87
|
}
|
|
59
88
|
function releaseWorkflow(repoType) {
|
|
@@ -65,7 +94,7 @@ on:
|
|
|
65
94
|
workflow_dispatch:
|
|
66
95
|
inputs:
|
|
67
96
|
only:
|
|
68
|
-
description: '
|
|
97
|
+
description: 'Workspaces to release (comma-separated, leave empty for all)'
|
|
69
98
|
required: false
|
|
70
99
|
type: string
|
|
71
100
|
bump:
|
|
@@ -78,7 +107,7 @@ on:
|
|
|
78
107
|
- minor
|
|
79
108
|
- major
|
|
80
109
|
force:
|
|
81
|
-
description: 'Force a release even when
|
|
110
|
+
description: 'Force a release even when no commits or no bump-worthy commits exist (defaults to patch; combine with --bump for a different level)'
|
|
82
111
|
required: false
|
|
83
112
|
type: boolean
|
|
84
113
|
default: false
|
|
@@ -112,7 +141,7 @@ on:
|
|
|
112
141
|
- minor
|
|
113
142
|
- major
|
|
114
143
|
force:
|
|
115
|
-
description: 'Force a release even when
|
|
144
|
+
description: 'Force a release even when no commits or no bump-worthy commits exist (defaults to patch; combine with --bump for a different level)'
|
|
116
145
|
required: false
|
|
117
146
|
type: boolean
|
|
118
147
|
default: false
|
|
@@ -130,6 +159,7 @@ jobs:
|
|
|
130
159
|
`;
|
|
131
160
|
}
|
|
132
161
|
export {
|
|
162
|
+
createGithubReleaseWorkflow,
|
|
133
163
|
publishWorkflow,
|
|
134
164
|
releaseConfigScript,
|
|
135
165
|
releaseWorkflow
|
|
@@ -1,2 +1,7 @@
|
|
|
1
|
-
export
|
|
1
|
+
export interface RenderedInjectedReadme {
|
|
2
|
+
injectedReadme: string;
|
|
3
|
+
releaseNotesMarkdown: string;
|
|
4
|
+
}
|
|
5
|
+
export declare function renderInjectedReadme(readme: string, changelogJsonPath: string, tag: string, sectionOrder?: string[]): RenderedInjectedReadme | undefined;
|
|
6
|
+
export declare function injectReleaseNotesIntoReadme(readmePath: string, changelogJsonPath: string, tag: string, sectionOrder?: string[]): string | undefined;
|
|
2
7
|
export declare function resolveReadmePath(workspacePath: string): string | undefined;
|
|
@@ -3,12 +3,11 @@ import { join } from "node:path";
|
|
|
3
3
|
import { extractVersion, readChangelogEntries } from "./changelogJsonUtils.js";
|
|
4
4
|
import { injectSection } from "./injectSection.js";
|
|
5
5
|
import { matchesAudience, renderReleaseNotesSingle } from "./renderReleaseNotes.js";
|
|
6
|
-
function
|
|
6
|
+
function renderInjectedReadme(readme, changelogJsonPath, tag, sectionOrder) {
|
|
7
7
|
if (!existsSync(changelogJsonPath)) {
|
|
8
8
|
console.warn(`Warning: ${changelogJsonPath} not found; skipping README injection`);
|
|
9
9
|
return void 0;
|
|
10
10
|
}
|
|
11
|
-
const originalReadme = readFileSync(readmePath, "utf8");
|
|
12
11
|
const version = extractVersion(tag);
|
|
13
12
|
const entries = readChangelogEntries(changelogJsonPath);
|
|
14
13
|
if (entries === void 0) {
|
|
@@ -20,16 +19,29 @@ function injectReleaseNotesIntoReadme(readmePath, changelogJsonPath, tag) {
|
|
|
20
19
|
console.warn(`Warning: no changelog entry for version ${version}; skipping README injection`);
|
|
21
20
|
return void 0;
|
|
22
21
|
}
|
|
23
|
-
const
|
|
22
|
+
const renderedSections = renderReleaseNotesSingle(entry, {
|
|
24
23
|
filter: matchesAudience("all"),
|
|
25
|
-
includeHeading: false
|
|
24
|
+
includeHeading: false,
|
|
25
|
+
...sectionOrder === void 0 ? {} : { sectionOrder }
|
|
26
26
|
});
|
|
27
|
-
if (
|
|
27
|
+
if (renderedSections.trimEnd().length === 0) {
|
|
28
28
|
console.warn(`Warning: no user-facing release notes for version ${version}; skipping README injection`);
|
|
29
29
|
return void 0;
|
|
30
30
|
}
|
|
31
|
-
const
|
|
32
|
-
|
|
31
|
+
const labeledHeading = `## Release notes \u2014 v${version} (${entry.date})`;
|
|
32
|
+
const releaseNotesMarkdown = `${labeledHeading}
|
|
33
|
+
|
|
34
|
+
${renderedSections.trimEnd()}`;
|
|
35
|
+
const injectedReadme = injectSection(readme, "release-notes", releaseNotesMarkdown);
|
|
36
|
+
return { injectedReadme, releaseNotesMarkdown };
|
|
37
|
+
}
|
|
38
|
+
function injectReleaseNotesIntoReadme(readmePath, changelogJsonPath, tag, sectionOrder) {
|
|
39
|
+
const originalReadme = readFileSync(readmePath, "utf8");
|
|
40
|
+
const rendered = renderInjectedReadme(originalReadme, changelogJsonPath, tag, sectionOrder);
|
|
41
|
+
if (rendered === void 0) {
|
|
42
|
+
return void 0;
|
|
43
|
+
}
|
|
44
|
+
writeFileSync(readmePath, rendered.injectedReadme, "utf8");
|
|
33
45
|
return originalReadme;
|
|
34
46
|
}
|
|
35
47
|
function resolveReadmePath(workspacePath) {
|
|
@@ -38,5 +50,6 @@ function resolveReadmePath(workspacePath) {
|
|
|
38
50
|
}
|
|
39
51
|
export {
|
|
40
52
|
injectReleaseNotesIntoReadme,
|
|
53
|
+
renderInjectedReadme,
|
|
41
54
|
resolveReadmePath
|
|
42
55
|
};
|
package/dist/esm/loadConfig.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
|
-
import type { MonorepoReleaseConfig, ReleaseConfig, ReleaseKitConfig } from './types.ts';
|
|
1
|
+
import type { MonorepoReleaseConfig, ReleaseConfig, ReleaseKitConfig, WorkTypeConfig } from './types.ts';
|
|
2
|
+
export declare const ROOT_PACKAGE_JSON_PATH = "package.json";
|
|
3
|
+
export declare function readRootPackageVersion(): {
|
|
4
|
+
exists: boolean;
|
|
5
|
+
version: string | undefined;
|
|
6
|
+
};
|
|
2
7
|
export declare const CONFIG_FILE_PATH = ".config/release-kit.config.ts";
|
|
3
8
|
export declare function loadConfig(): Promise<unknown>;
|
|
4
|
-
export
|
|
9
|
+
export interface RootPackageInfo {
|
|
10
|
+
exists: boolean;
|
|
11
|
+
version: string | undefined;
|
|
12
|
+
}
|
|
13
|
+
export declare function mergeMonorepoConfig(discoveredPaths: string[], userConfig: ReleaseKitConfig | undefined, rootPackage?: RootPackageInfo): MonorepoReleaseConfig;
|
|
5
14
|
export declare function mergeSinglePackageConfig(userConfig: ReleaseKitConfig | undefined): ReleaseConfig;
|
|
15
|
+
export declare function resolveWorkTypes(userWorkTypes?: Record<string, WorkTypeConfig>): Record<string, WorkTypeConfig>;
|