@williamthorsen/release-kit 10.7.0 → 10.9.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 +71 -3
- package/.readyup/kits/default.js +3 -3
- package/.readyup/kits/npm-auto-publish.js +1 -1
- package/.readyup/manifest.json +9 -9
- package/CHANGELOG.md +49 -3
- package/README.md +21 -15
- package/dist/esm/bin/release-kit.js +20 -102
- package/dist/esm/buildChangelogEntries.d.ts +1 -1
- package/dist/esm/buildChangelogEntries.js +14 -5
- package/dist/esm/createGithubReleaseCommand.d.ts +2 -1
- package/dist/esm/createGithubReleaseCommand.js +4 -2
- package/dist/esm/createTags.d.ts +2 -0
- package/dist/esm/createTags.js +5 -4
- package/dist/esm/format.d.ts +5 -5
- package/dist/esm/format.js +5 -4
- package/dist/esm/glyphs.d.ts +3 -0
- package/dist/esm/glyphs.js +6 -0
- package/dist/esm/init/initCommand.d.ts +3 -1
- package/dist/esm/init/initCommand.js +15 -15
- package/dist/esm/loadValidatedConfig.d.ts +2 -1
- package/dist/esm/loadValidatedConfig.js +3 -3
- package/dist/esm/parseCommitMessage.d.ts +4 -5
- package/dist/esm/prepareCommand.d.ts +2 -1
- package/dist/esm/prepareCommand.js +17 -16
- package/dist/esm/publishCommand.d.ts +2 -1
- package/dist/esm/publishCommand.js +2 -2
- package/dist/esm/reportPrepare.d.ts +2 -0
- package/dist/esm/reportPrepare.js +44 -38
- package/dist/esm/resolveReleaseNotesConfig.d.ts +2 -1
- package/dist/esm/resolveReleaseNotesConfig.js +4 -4
- package/dist/esm/resolveStylesOrExit.d.ts +10 -0
- package/dist/esm/resolveStylesOrExit.js +10 -0
- package/dist/esm/showTagPrefixesCommand.d.ts +2 -1
- package/dist/esm/showTagPrefixesCommand.js +16 -10
- package/dist/esm/sync-labels/generateCommand.d.ts +4 -2
- package/dist/esm/sync-labels/generateCommand.js +4 -4
- package/dist/esm/sync-labels/initCommand.d.ts +3 -1
- package/dist/esm/sync-labels/initCommand.js +7 -7
- package/dist/esm/tagCommand.d.ts +2 -1
- package/dist/esm/tagCommand.js +2 -2
- package/dist/esm/types.d.ts +8 -7
- package/dist/esm/validateOverridesCommand.d.ts +4 -4
- package/dist/esm/validateOverridesCommand.js +6 -6
- package/dist/esm/workTypesData.d.ts +10 -9
- package/dist/esm/workTypesData.js +97 -11
- package/docs/changelogs.md +8 -8
- package/docs/configuration.md +23 -1
- package/docs/work-types.md +28 -30
- package/package.json +11 -11
- package/presets/labels/common.yaml +2 -2
- package/dist/esm/checkWorkTypesDrift.d.ts +0 -36
- package/dist/esm/checkWorkTypesDrift.js +0 -117
- package/dist/esm/syncWorkTypes.d.ts +0 -28
- package/dist/esm/syncWorkTypes.js +0 -94
- package/dist/esm/work-types.json +0 -133
- package/dist/esm/work-types.schema.json +0 -100
- package/dist/esm/workTypesUtils.d.ts +0 -22
- package/dist/esm/workTypesUtils.js +0 -16
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
import { readFileSync, writeFileSync } from 'node:fs';
|
|
2
|
-
import { dirname, resolve } from 'node:path';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import { formatErrorLine } from '@williamthorsen/nmr-core';
|
|
5
|
-
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
6
|
-
import { UPSTREAM_WORK_TYPES_URL } from "./checkWorkTypesDrift.js";
|
|
7
|
-
import { isRecord } from "./typeGuards.js";
|
|
8
|
-
import { buildFetchInit, hasExpectedTopLevelShape } from "./workTypesUtils.js";
|
|
9
|
-
function resolveDefaultLocalPath() {
|
|
10
|
-
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
11
|
-
return resolve(moduleDir, 'work-types.json');
|
|
12
|
-
}
|
|
13
|
-
function extractLocalSchemaUrl(content) {
|
|
14
|
-
let parsed;
|
|
15
|
-
try {
|
|
16
|
-
parsed = JSON.parse(content);
|
|
17
|
-
}
|
|
18
|
-
catch {
|
|
19
|
-
return undefined;
|
|
20
|
-
}
|
|
21
|
-
if (!isRecord(parsed)) {
|
|
22
|
-
return undefined;
|
|
23
|
-
}
|
|
24
|
-
const schema = parsed['$schema'];
|
|
25
|
-
return typeof schema === 'string' ? schema : undefined;
|
|
26
|
-
}
|
|
27
|
-
export async function syncWorkTypes(dependencies = {}) {
|
|
28
|
-
const localPath = dependencies.localPath ?? resolveDefaultLocalPath();
|
|
29
|
-
const fetcher = dependencies.fetch ?? globalThis.fetch;
|
|
30
|
-
const url = dependencies.upstreamUrl ?? UPSTREAM_WORK_TYPES_URL;
|
|
31
|
-
const fetchInit = buildFetchInit();
|
|
32
|
-
let response;
|
|
33
|
-
try {
|
|
34
|
-
response = fetchInit === undefined ? await fetcher(url) : await fetcher(url, fetchInit);
|
|
35
|
-
}
|
|
36
|
-
catch (error) {
|
|
37
|
-
return {
|
|
38
|
-
exitCode: 2,
|
|
39
|
-
message: formatErrorLine(`Failed to fetch upstream work-types.json: ${describeError(error)}`),
|
|
40
|
-
};
|
|
41
|
-
}
|
|
42
|
-
if (!response.ok) {
|
|
43
|
-
return {
|
|
44
|
-
exitCode: 2,
|
|
45
|
-
message: formatErrorLine(`Failed to fetch upstream work-types.json: HTTP ${response.status} ${response.statusText}`),
|
|
46
|
-
};
|
|
47
|
-
}
|
|
48
|
-
const upstreamText = await response.text();
|
|
49
|
-
let upstreamJson;
|
|
50
|
-
try {
|
|
51
|
-
upstreamJson = JSON.parse(upstreamText);
|
|
52
|
-
}
|
|
53
|
-
catch (error) {
|
|
54
|
-
return {
|
|
55
|
-
exitCode: 3,
|
|
56
|
-
message: `Upstream work-types.json is not valid JSON: ${describeError(error)}`,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
if (!hasExpectedTopLevelShape(upstreamJson)) {
|
|
60
|
-
return {
|
|
61
|
-
exitCode: 3,
|
|
62
|
-
message: 'Upstream work-types.json does not match the expected schema shape (missing `tiers` or `types`).',
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
let priorContent;
|
|
66
|
-
try {
|
|
67
|
-
priorContent = readFileSync(localPath, 'utf8');
|
|
68
|
-
}
|
|
69
|
-
catch {
|
|
70
|
-
priorContent = undefined;
|
|
71
|
-
}
|
|
72
|
-
const localSchemaUrl = priorContent !== undefined ? extractLocalSchemaUrl(priorContent) : undefined;
|
|
73
|
-
const outputJson = localSchemaUrl !== undefined ? { $schema: localSchemaUrl, ...upstreamJson } : upstreamJson;
|
|
74
|
-
const formatted = `${JSON.stringify(outputJson, null, 2)}\n`;
|
|
75
|
-
if (priorContent === formatted) {
|
|
76
|
-
return {
|
|
77
|
-
exitCode: 0,
|
|
78
|
-
message: `Local work-types.json already matches upstream (${localPath}).`,
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
try {
|
|
82
|
-
writeFileSync(localPath, formatted, 'utf8');
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
return {
|
|
86
|
-
exitCode: 2,
|
|
87
|
-
message: formatErrorLine(`Failed to write ${localPath}: ${describeError(error)}`),
|
|
88
|
-
};
|
|
89
|
-
}
|
|
90
|
-
return {
|
|
91
|
-
exitCode: 0,
|
|
92
|
-
message: `Synced work-types.json from ${url} → ${localPath}.`,
|
|
93
|
-
};
|
|
94
|
-
}
|
package/dist/esm/work-types.json
DELETED
|
@@ -1,133 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "./work-types.schema.json",
|
|
3
|
-
"tiers": ["public", "internal", "process"],
|
|
4
|
-
"types": [
|
|
5
|
-
{
|
|
6
|
-
"tier": "public",
|
|
7
|
-
"key": "feat",
|
|
8
|
-
"aliases": ["feature"],
|
|
9
|
-
"emoji": "🎉",
|
|
10
|
-
"label": "Features",
|
|
11
|
-
"breakingPolicy": "optional"
|
|
12
|
-
},
|
|
13
|
-
{
|
|
14
|
-
"tier": "public",
|
|
15
|
-
"key": "drop",
|
|
16
|
-
"aliases": [],
|
|
17
|
-
"emoji": "🪦",
|
|
18
|
-
"label": "Removed",
|
|
19
|
-
"breakingPolicy": "required"
|
|
20
|
-
},
|
|
21
|
-
{
|
|
22
|
-
"tier": "public",
|
|
23
|
-
"key": "deprecate",
|
|
24
|
-
"aliases": [],
|
|
25
|
-
"emoji": "🗑️",
|
|
26
|
-
"label": "Deprecated",
|
|
27
|
-
"breakingPolicy": "forbidden"
|
|
28
|
-
},
|
|
29
|
-
{
|
|
30
|
-
"tier": "public",
|
|
31
|
-
"key": "fix",
|
|
32
|
-
"aliases": ["bugfix"],
|
|
33
|
-
"emoji": "🐛",
|
|
34
|
-
"label": "Bug fixes",
|
|
35
|
-
"breakingPolicy": "forbidden"
|
|
36
|
-
},
|
|
37
|
-
{
|
|
38
|
-
"tier": "public",
|
|
39
|
-
"key": "sec",
|
|
40
|
-
"aliases": ["security"],
|
|
41
|
-
"emoji": "🔒",
|
|
42
|
-
"label": "Security",
|
|
43
|
-
"breakingPolicy": "optional"
|
|
44
|
-
},
|
|
45
|
-
{
|
|
46
|
-
"tier": "public",
|
|
47
|
-
"key": "perf",
|
|
48
|
-
"aliases": ["performance"],
|
|
49
|
-
"emoji": "⚡",
|
|
50
|
-
"label": "Performance",
|
|
51
|
-
"breakingPolicy": "forbidden"
|
|
52
|
-
},
|
|
53
|
-
{
|
|
54
|
-
"tier": "internal",
|
|
55
|
-
"key": "internal",
|
|
56
|
-
"aliases": ["utility"],
|
|
57
|
-
"emoji": "🏗️",
|
|
58
|
-
"label": "Internal features",
|
|
59
|
-
"breakingPolicy": "forbidden"
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
"tier": "internal",
|
|
63
|
-
"key": "refactor",
|
|
64
|
-
"aliases": [],
|
|
65
|
-
"emoji": "♻️",
|
|
66
|
-
"label": "Refactoring",
|
|
67
|
-
"breakingPolicy": "forbidden"
|
|
68
|
-
},
|
|
69
|
-
{
|
|
70
|
-
"tier": "internal",
|
|
71
|
-
"key": "tests",
|
|
72
|
-
"aliases": ["test"],
|
|
73
|
-
"emoji": "🧪",
|
|
74
|
-
"label": "Tests",
|
|
75
|
-
"breakingPolicy": "forbidden"
|
|
76
|
-
},
|
|
77
|
-
{
|
|
78
|
-
"tier": "process",
|
|
79
|
-
"key": "tooling",
|
|
80
|
-
"aliases": [],
|
|
81
|
-
"emoji": "⚙️",
|
|
82
|
-
"label": "Tooling",
|
|
83
|
-
"breakingPolicy": "forbidden"
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
"tier": "process",
|
|
87
|
-
"key": "ci",
|
|
88
|
-
"aliases": [],
|
|
89
|
-
"emoji": "👷",
|
|
90
|
-
"label": "CI",
|
|
91
|
-
"breakingPolicy": "forbidden"
|
|
92
|
-
},
|
|
93
|
-
{
|
|
94
|
-
"tier": "process",
|
|
95
|
-
"key": "deps",
|
|
96
|
-
"aliases": ["dep"],
|
|
97
|
-
"emoji": "📦",
|
|
98
|
-
"label": "Dependencies",
|
|
99
|
-
"breakingPolicy": "forbidden"
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
"tier": "process",
|
|
103
|
-
"key": "ai",
|
|
104
|
-
"aliases": [],
|
|
105
|
-
"emoji": "🤖",
|
|
106
|
-
"label": "Agentic support",
|
|
107
|
-
"breakingPolicy": "forbidden"
|
|
108
|
-
},
|
|
109
|
-
{
|
|
110
|
-
"tier": "process",
|
|
111
|
-
"key": "docs",
|
|
112
|
-
"aliases": ["doc"],
|
|
113
|
-
"emoji": "📚",
|
|
114
|
-
"label": "Documentation",
|
|
115
|
-
"breakingPolicy": "forbidden"
|
|
116
|
-
},
|
|
117
|
-
{
|
|
118
|
-
"tier": "process",
|
|
119
|
-
"key": "fmt",
|
|
120
|
-
"aliases": [],
|
|
121
|
-
"emoji": "🎨",
|
|
122
|
-
"label": "Formatting",
|
|
123
|
-
"breakingPolicy": "forbidden",
|
|
124
|
-
"excludedFromChangelog": true
|
|
125
|
-
}
|
|
126
|
-
],
|
|
127
|
-
"markers": {
|
|
128
|
-
"breaking": {
|
|
129
|
-
"emoji": "🚨",
|
|
130
|
-
"label": "Breaking"
|
|
131
|
-
}
|
|
132
|
-
}
|
|
133
|
-
}
|
|
@@ -1,100 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
-
"$id": "https://github.com/williamthorsen/node-monorepo-tools/raw/main/packages/release-kit/src/work-types.schema.json",
|
|
4
|
-
"title": "Work types",
|
|
5
|
-
"description": "Canonical taxonomy of commit work types used by release-kit. Drives section ordering, audience classification, and the `!` (breaking) policy. The structured single-source-of-truth for everything that previously lived in `DEFAULT_WORK_TYPES` and `cliff.toml.template` group definitions.",
|
|
6
|
-
"type": "object",
|
|
7
|
-
"required": ["tiers", "types", "markers"],
|
|
8
|
-
"additionalProperties": false,
|
|
9
|
-
"properties": {
|
|
10
|
-
"$schema": {
|
|
11
|
-
"type": "string",
|
|
12
|
-
"description": "Optional reference to this schema for IDE validation."
|
|
13
|
-
},
|
|
14
|
-
"tiers": {
|
|
15
|
-
"type": "array",
|
|
16
|
-
"description": "Render tiers in canonical order. Each entry's `tier` field must reference one of these names.",
|
|
17
|
-
"items": { "type": "string", "minLength": 1 },
|
|
18
|
-
"minItems": 1,
|
|
19
|
-
"uniqueItems": true
|
|
20
|
-
},
|
|
21
|
-
"types": {
|
|
22
|
-
"type": "array",
|
|
23
|
-
"description": "Work-type entries in canonical render order (tier order, then row order within tier).",
|
|
24
|
-
"items": { "$ref": "#/definitions/workType" },
|
|
25
|
-
"minItems": 1
|
|
26
|
-
},
|
|
27
|
-
"markers": {
|
|
28
|
-
"type": "object",
|
|
29
|
-
"description": "Orthogonal section markers used by downstream renderers (PR descriptions, changelogs, release notes). Keyed by marker name; values describe the rendering inputs (emoji + label). Markers are cross-cutting — they are not tied to a specific work type.",
|
|
30
|
-
"required": ["breaking"],
|
|
31
|
-
"properties": {
|
|
32
|
-
"breaking": { "$ref": "#/definitions/marker" }
|
|
33
|
-
},
|
|
34
|
-
"additionalProperties": { "$ref": "#/definitions/marker" }
|
|
35
|
-
}
|
|
36
|
-
},
|
|
37
|
-
"definitions": {
|
|
38
|
-
"marker": {
|
|
39
|
-
"type": "object",
|
|
40
|
-
"description": "Rendering inputs for a single marker. Stored as plain text; consumers apply their own formatting (e.g., bolding, prefix punctuation) at construction time.",
|
|
41
|
-
"required": ["emoji", "label"],
|
|
42
|
-
"additionalProperties": false,
|
|
43
|
-
"properties": {
|
|
44
|
-
"emoji": {
|
|
45
|
-
"type": "string",
|
|
46
|
-
"description": "Decorative emoji rendered as the prefix of the marker.",
|
|
47
|
-
"minLength": 1
|
|
48
|
-
},
|
|
49
|
-
"label": {
|
|
50
|
-
"type": "string",
|
|
51
|
-
"description": "Human-readable marker label. Plain text; consumers add their own emphasis (e.g., bold) when constructing the rendered form.",
|
|
52
|
-
"minLength": 1
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
},
|
|
56
|
-
"workType": {
|
|
57
|
-
"type": "object",
|
|
58
|
-
"required": ["tier", "key", "aliases", "emoji", "label", "breakingPolicy"],
|
|
59
|
-
"additionalProperties": false,
|
|
60
|
-
"properties": {
|
|
61
|
-
"tier": {
|
|
62
|
-
"type": "string",
|
|
63
|
-
"description": "Render tier this entry belongs to. Must match one of the names in the top-level `tiers` array."
|
|
64
|
-
},
|
|
65
|
-
"key": {
|
|
66
|
-
"type": "string",
|
|
67
|
-
"description": "Canonical work-type identifier (e.g. `feat`, `fix`). Must be globally unique across all entries.",
|
|
68
|
-
"minLength": 1,
|
|
69
|
-
"pattern": "^[a-z][a-z0-9]*$"
|
|
70
|
-
},
|
|
71
|
-
"aliases": {
|
|
72
|
-
"type": "array",
|
|
73
|
-
"description": "Alternate identifiers that resolve to this work type. Must be globally unique and not collide with any `key`.",
|
|
74
|
-
"items": { "type": "string", "minLength": 1, "pattern": "^[a-z][a-z0-9]*$" },
|
|
75
|
-
"uniqueItems": true
|
|
76
|
-
},
|
|
77
|
-
"emoji": {
|
|
78
|
-
"type": "string",
|
|
79
|
-
"description": "Decorative emoji rendered as the prefix of the section heading.",
|
|
80
|
-
"minLength": 1
|
|
81
|
-
},
|
|
82
|
-
"label": {
|
|
83
|
-
"type": "string",
|
|
84
|
-
"description": "Human-readable section label (rendered as `${emoji} ${label}` in changelogs and release notes).",
|
|
85
|
-
"minLength": 1
|
|
86
|
-
},
|
|
87
|
-
"breakingPolicy": {
|
|
88
|
-
"type": "string",
|
|
89
|
-
"description": "Policy governing the `!` (breaking) marker for this type. `forbidden`: `!` is a policy violation. `optional`: `!` is allowed. `required`: bare type is a policy violation; only the `!` form is accepted.",
|
|
90
|
-
"enum": ["forbidden", "optional", "required"]
|
|
91
|
-
},
|
|
92
|
-
"excludedFromChangelog": {
|
|
93
|
-
"type": "boolean",
|
|
94
|
-
"description": "When `true`, this type's commits never appear in any changelog or release note. Currently only `fmt` sets this. Default: `false`.",
|
|
95
|
-
"default": false
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Shared helpers for the work-types canonical-source tooling.
|
|
3
|
-
*
|
|
4
|
-
* Both `checkWorkTypesDrift` and `syncWorkTypes` need to validate the upstream JSON's top-level
|
|
5
|
-
* shape and render unknown errors as strings. Keeping a single copy here avoids byte-for-byte
|
|
6
|
-
* duplication between the two entry points.
|
|
7
|
-
*/
|
|
8
|
-
/** Sanity-check that the parsed upstream JSON carries the expected top-level shape. */
|
|
9
|
-
export declare function hasExpectedTopLevelShape(value: unknown): value is {
|
|
10
|
-
tiers: unknown[];
|
|
11
|
-
types: unknown[];
|
|
12
|
-
};
|
|
13
|
-
/**
|
|
14
|
-
* Build the `init` argument for `fetch` to reach codeassembly's canonical work-types files.
|
|
15
|
-
*
|
|
16
|
-
* Returns `{ headers: { Authorization: 'Bearer <token>' } }` when `GITHUB_TOKEN` is set in the
|
|
17
|
-
* environment; returns `undefined` otherwise so the call site stays byte-identical to an
|
|
18
|
-
* unauthenticated request. Centralised here so `checkWorkTypesDrift` and `syncWorkTypes`
|
|
19
|
-
* cannot diverge on auth handling. Tests stub the env via `vi.stubEnv` rather than parameter
|
|
20
|
-
* injection, so this reads `process.env` directly.
|
|
21
|
-
*/
|
|
22
|
-
export declare function buildFetchInit(): RequestInit | undefined;
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
export function hasExpectedTopLevelShape(value) {
|
|
2
|
-
if (typeof value !== 'object' || value === null) {
|
|
3
|
-
return false;
|
|
4
|
-
}
|
|
5
|
-
if (!('tiers' in value) || !('types' in value)) {
|
|
6
|
-
return false;
|
|
7
|
-
}
|
|
8
|
-
return Array.isArray(value.tiers) && Array.isArray(value.types);
|
|
9
|
-
}
|
|
10
|
-
export function buildFetchInit() {
|
|
11
|
-
const token = process.env['GITHUB_TOKEN'];
|
|
12
|
-
if (token === undefined || token === '') {
|
|
13
|
-
return undefined;
|
|
14
|
-
}
|
|
15
|
-
return { headers: { Authorization: `Bearer ${token}` } };
|
|
16
|
-
}
|