@williamthorsen/release-kit 11.0.0 → 12.0.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/.meta/changelog.json +62 -2
- package/.readyup/kits/default.js +1 -17
- package/.readyup/manifest.json +4 -4
- package/CHANGELOG.md +40 -0
- package/README.md +25 -44
- package/dist/esm/attachChangelogDiagnostics.d.ts +4 -0
- package/dist/esm/attachChangelogDiagnostics.js +11 -0
- package/dist/esm/bin/release-kit.js +4 -3
- package/dist/esm/buildChangelogEntries.d.ts +59 -17
- package/dist/esm/buildChangelogEntries.js +194 -111
- package/dist/esm/buildReleaseSummary.js +2 -2
- package/dist/esm/changelogOverrides.d.ts +31 -13
- package/dist/esm/changelogOverrides.js +138 -58
- package/dist/esm/classifyChangelogCommit.d.ts +38 -0
- package/dist/esm/classifyChangelogCommit.js +33 -0
- package/dist/esm/decideRelease.d.ts +11 -37
- package/dist/esm/decideRelease.js +5 -27
- package/dist/esm/defaults.d.ts +1 -1
- package/dist/esm/defaults.js +3 -0
- package/dist/esm/determineBumpType.d.ts +11 -11
- package/dist/esm/determineBumpType.js +6 -7
- package/dist/esm/enumerateReleaseWindows.d.ts +50 -0
- package/dist/esm/enumerateReleaseWindows.js +124 -0
- package/dist/esm/generateChangelogs.d.ts +5 -23
- package/dist/esm/generateChangelogs.js +0 -14
- package/dist/esm/glyphs.d.ts +1 -1
- package/dist/esm/help/prepareHelp.d.ts +1 -1
- package/dist/esm/help/prepareHelp.js +4 -6
- package/dist/esm/index.d.ts +1 -1
- package/dist/esm/init/initCommand.js +1 -1
- package/dist/esm/init/scaffold.d.ts +0 -2
- package/dist/esm/init/scaffold.js +2 -30
- package/dist/esm/loadConfig.d.ts +1 -1
- package/dist/esm/loadConfig.js +1 -4
- package/dist/esm/parseChangeRecordBlock.d.ts +37 -0
- package/dist/esm/parseChangeRecordBlock.js +134 -0
- package/dist/esm/parseCommitMessage.d.ts +31 -6
- package/dist/esm/parseCommitMessage.js +6 -5
- package/dist/esm/prepareCommand.js +4 -12
- package/dist/esm/releasePrepare.d.ts +7 -8
- package/dist/esm/releasePrepare.js +53 -73
- package/dist/esm/releasePrepareMono.js +48 -85
- package/dist/esm/releasePrepareProject.d.ts +1 -1
- package/dist/esm/releasePrepareProject.js +19 -37
- package/dist/esm/reportPrepare.js +39 -28
- package/dist/esm/types.d.ts +99 -55
- package/dist/esm/types.js +1 -1
- package/dist/esm/validateConfig.js +4 -0
- package/dist/esm/validateOverridesCommand.d.ts +6 -5
- package/dist/esm/validateOverridesCommand.js +16 -23
- package/docs/changelogs.md +64 -25
- package/docs/configuration.md +2 -3
- package/docs/editorial-overrides.md +75 -16
- package/docs/project-releases.md +4 -4
- package/docs/releasing.md +13 -8
- package/docs/work-types.md +13 -9
- package/package.json +1 -2
- package/schemas/changelog-overrides.json +39 -0
- package/cliff.toml.template +0 -65
- package/dist/esm/collectPolicyViolations.d.ts +0 -15
- package/dist/esm/collectPolicyViolations.js +0 -12
- package/dist/esm/determineBumpFromCommits.d.ts +0 -17
- package/dist/esm/determineBumpFromCommits.js +0 -28
- package/dist/esm/getCommitsSinceTarget.d.ts +0 -21
- package/dist/esm/getCommitsSinceTarget.js +0 -66
- package/dist/esm/resolveCliffConfigPath.d.ts +0 -11
- package/dist/esm/resolveCliffConfigPath.js +0 -20
- package/dist/esm/runGitCliff.d.ts +0 -38
- package/dist/esm/runGitCliff.js +0 -25
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
import type { PolicyViolationHandler } from './parseCommitMessage.js';
|
|
2
|
-
import type { PolicyViolation } from './types.js';
|
|
3
|
-
/**
|
|
4
|
-
* Build a fresh `policyViolations` accumulator paired with the `onPolicyViolation` callback
|
|
5
|
-
* that pushes structured entries into it.
|
|
6
|
-
*
|
|
7
|
-
* Used by all three release-prepare orchestrators (`releasePrepare`, `releasePrepareMono`,
|
|
8
|
-
* `releasePrepareProject`) to collect parser-side `!`-policy violations into a result-attachable
|
|
9
|
-
* array. Centralizing the callback shape keeps the `commitSubject` extraction rule (`firstLine
|
|
10
|
-
* post-split`) consistent across orchestrators.
|
|
11
|
-
*/
|
|
12
|
-
export declare function createPolicyViolationCollector(): {
|
|
13
|
-
violations: PolicyViolation[];
|
|
14
|
-
onPolicyViolation: PolicyViolationHandler;
|
|
15
|
-
};
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
export function createPolicyViolationCollector() {
|
|
2
|
-
const violations = [];
|
|
3
|
-
const onPolicyViolation = (commit, type, surface) => {
|
|
4
|
-
violations.push({
|
|
5
|
-
commitHash: commit.hash,
|
|
6
|
-
commitSubject: commit.message.split('\n', 1)[0] ?? '',
|
|
7
|
-
type,
|
|
8
|
-
surface,
|
|
9
|
-
});
|
|
10
|
-
};
|
|
11
|
-
return { violations, onPolicyViolation };
|
|
12
|
-
}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import { type PolicyViolationHandler } from './parseCommitMessage.js';
|
|
2
|
-
import type { Commit, ReleaseType, VersionPatterns, WorkTypeConfig } from './types.js';
|
|
3
|
-
/** Aggregate result of parsing commits and determining the bump type. */
|
|
4
|
-
export interface BumpDetermination {
|
|
5
|
-
releaseType: ReleaseType | undefined;
|
|
6
|
-
parsedCommitCount: number;
|
|
7
|
-
unparseableCommits: Commit[] | undefined;
|
|
8
|
-
}
|
|
9
|
-
/** Optional configuration for parser-policy plumbing. */
|
|
10
|
-
export interface DetermineBumpOptions {
|
|
11
|
-
/** Per-canonical-type breaking-policy lookup (drives `!` policy enforcement). */
|
|
12
|
-
breakingPolicies?: Record<string, 'forbidden' | 'optional' | 'required'>;
|
|
13
|
-
/** Receives policy-violation notifications from `parseCommitMessage`. */
|
|
14
|
-
onPolicyViolation?: PolicyViolationHandler;
|
|
15
|
-
}
|
|
16
|
-
/** Parse commits, determine bump type, and apply patch floor when commits exist but none parsed. */
|
|
17
|
-
export declare function determineBumpFromCommits(commits: Commit[], workTypes: Record<string, WorkTypeConfig>, versionPatterns: VersionPatterns, scopeAliases: Record<string, string> | undefined, options?: DetermineBumpOptions): BumpDetermination;
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
import { determineBumpType } from "./determineBumpType.js";
|
|
2
|
-
import { parseCommitMessage, } from "./parseCommitMessage.js";
|
|
3
|
-
export function determineBumpFromCommits(commits, workTypes, versionPatterns, scopeAliases, options) {
|
|
4
|
-
const parseOptions = {
|
|
5
|
-
...(options?.breakingPolicies !== undefined && { breakingPolicies: options.breakingPolicies }),
|
|
6
|
-
...(options?.onPolicyViolation !== undefined && { onPolicyViolation: options.onPolicyViolation }),
|
|
7
|
-
};
|
|
8
|
-
const parsedCommits = [];
|
|
9
|
-
const unparseable = [];
|
|
10
|
-
for (const commit of commits) {
|
|
11
|
-
const parsed = parseCommitMessage(commit.message, commit.hash, workTypes, scopeAliases, parseOptions);
|
|
12
|
-
if (parsed === undefined) {
|
|
13
|
-
unparseable.push(commit);
|
|
14
|
-
}
|
|
15
|
-
else {
|
|
16
|
-
parsedCommits.push(parsed);
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
let releaseType = determineBumpType(parsedCommits, workTypes, versionPatterns);
|
|
20
|
-
if (releaseType === undefined && commits.length > 0) {
|
|
21
|
-
releaseType = 'patch';
|
|
22
|
-
}
|
|
23
|
-
return {
|
|
24
|
-
releaseType,
|
|
25
|
-
parsedCommitCount: parsedCommits.length,
|
|
26
|
-
unparseableCommits: unparseable.length > 0 ? unparseable : undefined,
|
|
27
|
-
};
|
|
28
|
-
}
|
|
@@ -1,21 +0,0 @@
|
|
|
1
|
-
import type { Commit } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
* Gets commits since the latest baseline tag matching any of the given prefixes.
|
|
4
|
-
*
|
|
5
|
-
* Uses `git log` to retrieve commit messages and hashes between the closest reachable
|
|
6
|
-
* baseline tag and HEAD. When no tag matches any prefix, all commits reachable from HEAD
|
|
7
|
-
* are returned.
|
|
8
|
-
*
|
|
9
|
-
* Callers must pass at least one prefix; the single-prefix case is the common one (the
|
|
10
|
-
* workspace's derived prefix). Multiple prefixes are used to include historical tag prefixes
|
|
11
|
-
* from `legacyIdentities`.
|
|
12
|
-
*
|
|
13
|
-
* @param tagPrefixes - Tag prefixes to search as a union (e.g., `['core-v', 'old-core-v']`).
|
|
14
|
-
* @param paths - Optional glob patterns to filter commits by path (appended after `--` in `git log`).
|
|
15
|
-
* Path patterns use POSIX-style forward slashes; Windows compatibility is not guaranteed.
|
|
16
|
-
* @returns An object with the found tag (if any) and the list of commits.
|
|
17
|
-
*/
|
|
18
|
-
export declare function getCommitsSinceTarget(tagPrefixes: readonly string[], paths?: string[]): {
|
|
19
|
-
tag: string | undefined;
|
|
20
|
-
commits: Commit[];
|
|
21
|
-
};
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
|
|
3
|
-
import { chainError } from '@williamthorsen/toolbelt.errors/candidate';
|
|
4
|
-
const FIELD_SEPARATOR = '\u{1F}';
|
|
5
|
-
function isNoTagError(err) {
|
|
6
|
-
return typeof err === 'object' && err !== null && 'status' in err && err.status === 128;
|
|
7
|
-
}
|
|
8
|
-
function findLatestTag(tagPrefixes) {
|
|
9
|
-
if (tagPrefixes.length === 0) {
|
|
10
|
-
throw new Error('findLatestTag: tagPrefixes must contain at least one entry');
|
|
11
|
-
}
|
|
12
|
-
const matchArgs = tagPrefixes.map((prefix) => `--match=${prefix}*`);
|
|
13
|
-
try {
|
|
14
|
-
const tagResult = execFileSync('git', ['describe', '--tags', '--abbrev=0', ...matchArgs], {
|
|
15
|
-
encoding: 'utf8',
|
|
16
|
-
maxBuffer: GIT_OUTPUT_LIMIT,
|
|
17
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
18
|
-
}).trim();
|
|
19
|
-
return tagResult || undefined;
|
|
20
|
-
}
|
|
21
|
-
catch (error) {
|
|
22
|
-
if (isNoTagError(error)) {
|
|
23
|
-
return undefined;
|
|
24
|
-
}
|
|
25
|
-
throw chainError(`Failed to run 'git describe'`, error);
|
|
26
|
-
}
|
|
27
|
-
}
|
|
28
|
-
const RELEASE_COMMIT_PREFIX = 'release:';
|
|
29
|
-
function parseLogOutput(logOutput) {
|
|
30
|
-
const commits = [];
|
|
31
|
-
for (const line of logOutput.split('\n')) {
|
|
32
|
-
const trimmedLine = line.trim();
|
|
33
|
-
if (trimmedLine === '') {
|
|
34
|
-
continue;
|
|
35
|
-
}
|
|
36
|
-
const [message, hash] = trimmedLine.split(FIELD_SEPARATOR);
|
|
37
|
-
if (message !== undefined && hash !== undefined && !message.startsWith(RELEASE_COMMIT_PREFIX)) {
|
|
38
|
-
commits.push({ message, hash });
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
return commits;
|
|
42
|
-
}
|
|
43
|
-
export function getCommitsSinceTarget(tagPrefixes, paths) {
|
|
44
|
-
const tag = findLatestTag(tagPrefixes);
|
|
45
|
-
const range = tag === undefined ? 'HEAD' : `${tag}..HEAD`;
|
|
46
|
-
const format = `%s${FIELD_SEPARATOR}%H`;
|
|
47
|
-
const args = ['log', range, `--pretty=format:${format}`];
|
|
48
|
-
if (paths !== undefined && paths.length > 0) {
|
|
49
|
-
args.push('--', ...paths);
|
|
50
|
-
}
|
|
51
|
-
let logOutput;
|
|
52
|
-
try {
|
|
53
|
-
logOutput = execFileSync('git', args, {
|
|
54
|
-
encoding: 'utf8',
|
|
55
|
-
maxBuffer: GIT_OUTPUT_LIMIT,
|
|
56
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
57
|
-
}).trim();
|
|
58
|
-
}
|
|
59
|
-
catch (error) {
|
|
60
|
-
throw chainError(`Failed to run 'git log' for range '${range}'`, error);
|
|
61
|
-
}
|
|
62
|
-
if (logOutput === '') {
|
|
63
|
-
return { tag, commits: [] };
|
|
64
|
-
}
|
|
65
|
-
return { tag, commits: parseLogOutput(logOutput) };
|
|
66
|
-
}
|
|
@@ -1,11 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Resolve the git-cliff configuration file path.
|
|
3
|
-
*
|
|
4
|
-
* Checks candidates in order: explicit `cliffConfigPath` -> `.config/git-cliff.toml` ->
|
|
5
|
-
* `cliff.toml` -> bundled `cliff.toml.template`. Returns the first path that exists,
|
|
6
|
-
* or throws if even the bundled template cannot be found.
|
|
7
|
-
*
|
|
8
|
-
* When an explicit `cliffConfigPath` is provided, it is returned as-is without checking
|
|
9
|
-
* existence, preserving current behavior (git-cliff reports the error if the file is missing).
|
|
10
|
-
*/
|
|
11
|
-
export declare function resolveCliffConfigPath(cliffConfigPath: string | undefined, metaUrl: string): string;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
import { existsSync } from 'node:fs';
|
|
2
|
-
import { resolve } from 'node:path';
|
|
3
|
-
import { findPackageRoot } from '@williamthorsen/nmr-core';
|
|
4
|
-
export function resolveCliffConfigPath(cliffConfigPath, metaUrl) {
|
|
5
|
-
if (cliffConfigPath !== undefined) {
|
|
6
|
-
return cliffConfigPath;
|
|
7
|
-
}
|
|
8
|
-
const candidates = ['.config/git-cliff.toml', 'cliff.toml'];
|
|
9
|
-
for (const candidate of candidates) {
|
|
10
|
-
if (existsSync(candidate)) {
|
|
11
|
-
return candidate;
|
|
12
|
-
}
|
|
13
|
-
}
|
|
14
|
-
const root = findPackageRoot(metaUrl);
|
|
15
|
-
const bundledPath = resolve(root, 'cliff.toml.template');
|
|
16
|
-
if (existsSync(bundledPath)) {
|
|
17
|
-
return bundledPath;
|
|
18
|
-
}
|
|
19
|
-
throw new Error(`Could not resolve a git-cliff config file. Searched: ${candidates.join(', ')}, and bundled template at ${bundledPath}`);
|
|
20
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The exact `git-cliff` version every invocation resolves.
|
|
3
|
-
*
|
|
4
|
-
* npm's `git-cliff` trails the upstream release, so this pin normally sits behind the newest version cliff
|
|
5
|
-
* itself reports. Bumping it is an edit to this line, once npm publishes the version you want.
|
|
6
|
-
*/
|
|
7
|
-
export declare const GIT_CLIFF_VERSION = "2.13.1";
|
|
8
|
-
/** The npx arguments that precede the cliff args at every invocation, and that the dry-run report renders. */
|
|
9
|
-
export declare const GIT_CLIFF_NPX_ARGS: readonly string[];
|
|
10
|
-
/**
|
|
11
|
-
* Invokes `git-cliff` via `npx` and returns the output it produced.
|
|
12
|
-
*
|
|
13
|
-
* Single entry point for `git-cliff` invocations from `release-kit`. Owns three pieces of shared lifecycle
|
|
14
|
-
* that would otherwise duplicate (and silently drift) across call sites: the npx flags, the spawned-process
|
|
15
|
-
* environment, and the temp dir holding both the `.template`→`.toml` config copy and cliff's output file.
|
|
16
|
-
*
|
|
17
|
-
* Output is routed through `--output` to a temp file and read back. `--context` emits a workspace's
|
|
18
|
-
* entire matching tag history on every run, so its size grows without bound with the repo;
|
|
19
|
-
* a file accommodates that, while a pipe is bounded by `maxBuffer`.
|
|
20
|
-
*
|
|
21
|
-
* The npx spec names an exact version, which leaves npm no staleness to check, so `--prefer-offline` skips the
|
|
22
|
-
* per-call registry revalidation round-trip (~2.5 s per invocation on a warm cache) without stranding the run
|
|
23
|
-
* on whatever the cache happens to hold.
|
|
24
|
-
*
|
|
25
|
-
* Two env entries are set for the child. `npm_config_progress=false` suppresses npx's animated stderr spinner,
|
|
26
|
-
* which otherwise renders as a transient flicker. `RUST_LOG=warn` drops cliff's INFO lines, among them the
|
|
27
|
-
* crates.io update notice it emits on every invocation while npm trails upstream, and leaves warnings and errors
|
|
28
|
-
* in place; an inherited `RUST_LOG` wins, so raising the level for debugging still works.
|
|
29
|
-
*
|
|
30
|
-
* The helper injects `--config <path>` and `--output <path>` itself — callers must NOT include either in `cliffArgs`.
|
|
31
|
-
* `--output` is appended last so a caller that passes one anyway cannot redirect the output the helper then reads.
|
|
32
|
-
* The caller is responsible for resolving the cliff config path (via `resolveCliffConfigPath`) before calling,
|
|
33
|
-
* since the resolution depends on the caller's `import.meta.url`.
|
|
34
|
-
*
|
|
35
|
-
* Errors from `execFileSync` are not caught: callers wrap with site-specific messages.
|
|
36
|
-
* The temp-dir cleanup runs in a `finally` so it still happens on throw.
|
|
37
|
-
*/
|
|
38
|
-
export declare function runGitCliff(cliffConfigPath: string, cliffArgs: readonly string[]): string;
|
package/dist/esm/runGitCliff.js
DELETED
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import { copyFileSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
|
|
3
|
-
import { tmpdir } from 'node:os';
|
|
4
|
-
import { join } from 'node:path';
|
|
5
|
-
export const GIT_CLIFF_VERSION = '2.13.1';
|
|
6
|
-
export const GIT_CLIFF_NPX_ARGS = ['--prefer-offline', '--yes', `git-cliff@${GIT_CLIFF_VERSION}`];
|
|
7
|
-
export function runGitCliff(cliffConfigPath, cliffArgs) {
|
|
8
|
-
const tempDir = mkdtempSync(join(tmpdir(), 'cliff-'));
|
|
9
|
-
try {
|
|
10
|
-
let configPath = cliffConfigPath;
|
|
11
|
-
if (cliffConfigPath.endsWith('.template')) {
|
|
12
|
-
configPath = join(tempDir, 'cliff.toml');
|
|
13
|
-
copyFileSync(cliffConfigPath, configPath);
|
|
14
|
-
}
|
|
15
|
-
const outputPath = join(tempDir, 'output.json');
|
|
16
|
-
execFileSync('npx', [...GIT_CLIFF_NPX_ARGS, '--config', configPath, ...cliffArgs, '--output', outputPath], {
|
|
17
|
-
stdio: ['ignore', 'ignore', 'inherit'],
|
|
18
|
-
env: { ...process.env, npm_config_progress: 'false', RUST_LOG: process.env['RUST_LOG'] ?? 'warn' },
|
|
19
|
-
});
|
|
20
|
-
return readFileSync(outputPath, 'utf8');
|
|
21
|
-
}
|
|
22
|
-
finally {
|
|
23
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
24
|
-
}
|
|
25
|
-
}
|