@williamthorsen/release-kit 5.1.0 → 5.2.1
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 +113 -65
- package/README.md +147 -70
- package/cliff.toml.template +26 -17
- package/dist/esm/.cache +1 -1
- package/dist/esm/bin/release-kit.js +96 -3
- package/dist/esm/buildChangelogEntries.d.ts +1 -0
- package/dist/esm/buildChangelogEntries.js +39 -25
- package/dist/esm/checkWorkTypesDrift.d.ts +11 -0
- package/dist/esm/checkWorkTypesDrift.js +110 -0
- package/dist/esm/collectPolicyViolations.d.ts +6 -0
- package/dist/esm/collectPolicyViolations.js +15 -0
- package/dist/esm/createGithubRelease.d.ts +12 -2
- package/dist/esm/createGithubRelease.js +12 -8
- package/dist/esm/createGithubReleaseCommand.js +2 -7
- package/dist/esm/decideRelease.d.ts +3 -0
- package/dist/esm/decideRelease.js +19 -3
- package/dist/esm/defaults.d.ts +7 -0
- package/dist/esm/defaults.js +41 -20
- package/dist/esm/deriveWorkspaceConfig.js +3 -0
- package/dist/esm/determineBumpFromCommits.d.ts +6 -1
- package/dist/esm/determineBumpFromCommits.js +9 -3
- package/dist/esm/generateChangelogs.js +14 -29
- package/dist/esm/loadConfig.js +14 -22
- package/dist/esm/parseCommitMessage.d.ts +8 -2
- package/dist/esm/parseCommitMessage.js +32 -3
- package/dist/esm/publishCommand.js +21 -2
- package/dist/esm/releasePrepare.js +39 -15
- package/dist/esm/releasePrepareMono.js +26 -3
- package/dist/esm/releasePrepareProject.js +13 -1
- package/dist/esm/renderReleaseNotes.js +2 -1
- package/dist/esm/reportPrepare.js +18 -0
- package/dist/esm/resolveCommandTags.js +16 -6
- package/dist/esm/resolveReleaseTags.d.ts +8 -1
- package/dist/esm/resolveReleaseTags.js +11 -7
- package/dist/esm/runGitCliff.d.ts +2 -0
- package/dist/esm/runGitCliff.js +27 -0
- package/dist/esm/stripEmojiPrefix.d.ts +1 -0
- package/dist/esm/stripEmojiPrefix.js +7 -0
- package/dist/esm/syncWorkTypes.d.ts +10 -0
- package/dist/esm/syncWorkTypes.js +90 -0
- package/dist/esm/types.d.ts +15 -0
- package/dist/esm/work-types.json +127 -0
- package/dist/esm/work-types.schema.json +73 -0
- package/dist/esm/workTypesData.d.ts +14 -0
- package/dist/esm/workTypesData.js +59 -0
- package/dist/esm/workTypesUtils.d.ts +5 -0
- package/dist/esm/workTypesUtils.js +16 -0
- package/package.json +6 -3
- package/dist/esm/version.d.ts +0 -1
- package/dist/esm/version.js +0 -4
package/README.md
CHANGED
|
@@ -5,49 +5,13 @@ Version-bumping and changelog-generation toolkit for release workflows.
|
|
|
5
5
|
Provides a self-contained CLI that auto-discovers workspaces from `pnpm-workspace.yaml`, parses conventional commits, determines version bumps, updates `package.json` files, and generates changelogs with `git-cliff`.
|
|
6
6
|
|
|
7
7
|
<!-- section:release-notes -->
|
|
8
|
-
## Release notes — v5.1
|
|
8
|
+
## Release notes — v5.2.1 (2026-05-05)
|
|
9
9
|
|
|
10
|
-
### Bug fixes
|
|
10
|
+
### 🐛 Bug fixes
|
|
11
11
|
|
|
12
|
-
-
|
|
12
|
+
- Soft-skip tags with no changelog entry under --tags (#366)
|
|
13
13
|
|
|
14
|
-
Fixes an issue where `release-kit
|
|
15
|
-
|
|
16
|
-
- Make `--set-version` + `project` rejection explicit (#319)
|
|
17
|
-
|
|
18
|
-
Improves the error users see when invoking `release-kit prepare --set-version` with a `project` block configured. The combination is still rejected — as before — but now produces a single, project-aware message ("--set-version cannot be combined with a project release…") rather than the previous two-step chain (`--set-version requires --only`, then `--only cannot be combined with a project release` after the user added `--only`).
|
|
19
|
-
|
|
20
|
-
- Reject `--only` that would strand excluded dependents (#321)
|
|
21
|
-
|
|
22
|
-
Fixes a silent footgun in `release-kit prepare --only=...`: an excluded internal dependent with its own changes would be left unreleased with no runtime signal, even though the targeted workspace it depends on was being released. The command now rejects such invocations up front, naming every excluded dependent whose changes would be stranded.
|
|
23
|
-
|
|
24
|
-
- Order prerelease versions correctly in changelog sort (#334)
|
|
25
|
-
|
|
26
|
-
Fixes a latent issue in `@williamthorsen/release-kit` where prerelease version tags (e.g., `1.2.3-alpha`, `1.2.3-rc.1`) were sorted as if their prerelease component were absent, causing them to appear in the wrong position relative to releases sharing the same base version. Changelog entries are now ordered per SemVer §11: prerelease versions precede the corresponding release (`1.2.3-alpha < 1.2.3`), build metadata is ignored for ordering, and entries that fail SemVer validation sort deterministically to the bottom of the list rather than collapsing into mid-list positions.
|
|
27
|
-
|
|
28
|
-
### Features
|
|
29
|
-
|
|
30
|
-
- Add `project` block for project-level release stage (#317)
|
|
31
|
-
|
|
32
|
-
Adds support for monorepos that ship a single combined deliverable to version, changelog, and release-note the project itself rather than only its constituent workspaces.
|
|
33
|
-
|
|
34
|
-
- Publish JSON Schema for `.meta/label-map.json` (#325)
|
|
35
|
-
|
|
36
|
-
Adds a JSON Schema for `.meta/label-map.json` to release-kit, packaged at `packages/release-kit/schemas/label-map.json` and shipped to npm. Consumers reference it via the stable raw URL pattern `https://github.com/williamthorsen/node-monorepo-tools/raw/release-kit-v<version>/packages/release-kit/schemas/label-map.json` — the same shape audit-deps already uses.
|
|
37
|
-
|
|
38
|
-
- Label prepare errors with the failing stage (#326)
|
|
39
|
-
|
|
40
|
-
Adds stage attribution to errors thrown during `release-kit prepare`. Errors from per-workspace bumps and changelog generation, the project release stage, and the post-release format command now begin with a stage label that identifies the failing stage and (where relevant) the affected workspace.
|
|
41
|
-
|
|
42
|
-
- Make `--force` and `--bump` orthogonal (#328)
|
|
43
|
-
|
|
44
|
-
Decouples `--force` and `--bump` so each flag has a single responsibility, and unifies skip semantics across the per-workspace and project pipelines.
|
|
45
|
-
|
|
46
|
-
### Documentation
|
|
47
|
-
|
|
48
|
-
- Document tag prefix collisions as general rule (#320)
|
|
49
|
-
|
|
50
|
-
Documents the strict-prefix tag-prefix collision rule as a general validation rule that applies to every release-kit consumer declaring more than one tag prefix: across active workspaces, declared legacy identities, retired packages, and the optional `project` block. Previously, the rule appeared only inside the `Project releases` validation list.
|
|
14
|
+
Fixes an issue where `release-kit create-github-release --tags <tag>` exited 1 — failing the calling CI workflow — when the requested tag had no changelog entry. Tooling-only releases (those whose changelog generator legitimately omits an entry) are now soft-skipped with an info-level summary, the same as releases skipped because their entry has no audience-relevant content. Typo protection is preserved: passing an unknown tag to `--tags` still exits 1.
|
|
51
15
|
<!-- /section:release-notes -->
|
|
52
16
|
|
|
53
17
|
## Installation
|
|
@@ -151,16 +115,17 @@ The config file supports both `export default config` and `export const config =
|
|
|
151
115
|
|
|
152
116
|
### `ReleaseKitConfig` reference
|
|
153
117
|
|
|
154
|
-
| Field
|
|
155
|
-
|
|
|
156
|
-
| `cliffConfigPath`
|
|
157
|
-
| `workspaces`
|
|
158
|
-
| `formatCommand`
|
|
159
|
-
| `versionPatterns`
|
|
160
|
-
| `scopeAliases`
|
|
161
|
-
| `workTypes`
|
|
162
|
-
| `
|
|
163
|
-
| `
|
|
118
|
+
| Field | Type | Description |
|
|
119
|
+
| ------------------ | --------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
120
|
+
| `cliffConfigPath` | `string` | Explicit path to cliff config. If omitted, resolved automatically: `.config/git-cliff.toml` → `cliff.toml` → bundled template |
|
|
121
|
+
| `workspaces` | `WorkspaceOverride[]` | Override or exclude discovered workspaces (matched by `dir`) |
|
|
122
|
+
| `formatCommand` | `string` | Shell command to run after changelog generation; modified file paths are appended as arguments |
|
|
123
|
+
| `versionPatterns` | `VersionPatterns` | Rules for which commit types trigger major/minor bumps |
|
|
124
|
+
| `scopeAliases` | `Record<string, string>` | Maps shorthand scope names to canonical names in commits |
|
|
125
|
+
| `workTypes` | `Record<string, WorkTypeConfig>` | Work type definitions, merged with defaults by key |
|
|
126
|
+
| `breakingPolicies` | `Record<string, 'forbidden' \| 'optional' \| 'required'>` | Per-type `!`-policy lookup. Defaults to `DEFAULT_BREAKING_POLICIES`. Replaces the default entirely when provided. Set to `{}` to disable enforcement |
|
|
127
|
+
| `retiredPackages` | `RetiredPackage[]` | Packages that once lived in this repo but have been extracted or removed; suppresses undeclared-tag-prefix warnings |
|
|
128
|
+
| `project` | `ProjectConfig` | Opt-in project-level release block. Declaring `project: {}` (even empty) enables a project-release stage in `prepare` |
|
|
164
129
|
|
|
165
130
|
All fields are optional.
|
|
166
131
|
|
|
@@ -313,30 +278,93 @@ interface VersionPatterns {
|
|
|
313
278
|
|
|
314
279
|
Default: `{ major: ['!'], minor: ['feat'] }`
|
|
315
280
|
|
|
316
|
-
###
|
|
281
|
+
### Work types and tiers
|
|
282
|
+
|
|
283
|
+
The canonical taxonomy lives in `packages/release-kit/src/work-types.json` and is split into three tiers that drive section rendering and audience classification.
|
|
284
|
+
|
|
285
|
+
| Tier | Key | Header | Aliases | `!` policy |
|
|
286
|
+
| -------- | ----------- | ------------------------- | ------------- | ------------ |
|
|
287
|
+
| Public | `feat` | 🎉 Features | `feature` | optional |
|
|
288
|
+
| Public | `drop` | 🪦 Removed | | **required** |
|
|
289
|
+
| Public | `deprecate` | 🗑️ Deprecated | | forbidden |
|
|
290
|
+
| Public | `fix` | 🐛 Bug fixes | `bugfix` | forbidden |
|
|
291
|
+
| Public | `sec` | 🔒 Security | `security` | optional |
|
|
292
|
+
| Public | `perf` | ⚡ Performance | `performance` | forbidden |
|
|
293
|
+
| Internal | `internal` | 🏗️ Internal features | `utility` | forbidden |
|
|
294
|
+
| Internal | `refactor` | ♻️ Refactoring | | forbidden |
|
|
295
|
+
| Internal | `tests` | 🧪 Tests | `test` | forbidden |
|
|
296
|
+
| Process | `tooling` | ⚙️ Tooling | | forbidden |
|
|
297
|
+
| Process | `ci` | 👷 CI | | forbidden |
|
|
298
|
+
| Process | `deps` | 📦 Dependencies | `dep` | forbidden |
|
|
299
|
+
| Process | `ai` | 🤖 Agentic support | | forbidden |
|
|
300
|
+
| Process | `docs` | 📚 Documentation | `doc` | forbidden |
|
|
301
|
+
| Process | `fmt` | (excluded from changelog) | | forbidden |
|
|
302
|
+
|
|
303
|
+
#### Tier semantics
|
|
304
|
+
|
|
305
|
+
- **Public** — visible to all audiences. Public-tier sections appear in both public release notes and dev changelogs.
|
|
306
|
+
- **Internal** — dev-only. Internal-tier sections appear in dev changelogs but not in public-facing release notes.
|
|
307
|
+
- **Process** — dev-only. Same audience treatment as Internal.
|
|
308
|
+
|
|
309
|
+
Section render order is **tier order (Public → Internal → Process), then row order within tier**. The bundled `cliff.toml.template` encodes this order via hidden `<!-- NN -->` HTML-comment prefixes on each parser's `group` value; tera's `group_by` filter sorts groups lexicographically (now monotonic by row number), and the body template's `striptags` filter erases the prefix from rendered headings.
|
|
310
|
+
|
|
311
|
+
#### `docs` reclassification
|
|
312
|
+
|
|
313
|
+
`docs`/Documentation has moved from the all-audience tier (where it lived before this taxonomy was formalised) to the dev-only Process tier. **Documentation commits no longer appear in public-facing release notes.** They still appear in `CHANGELOG.md` and `changelog.json` under the `audience: 'dev'` classification.
|
|
314
|
+
|
|
315
|
+
#### `utility` alias
|
|
316
|
+
|
|
317
|
+
`utility:` is a backward-compat alias for `internal:`. Both forms parse to the same canonical type, route to the same `🏗️ Internal features` section, and are subject to the same `!` policy.
|
|
318
|
+
|
|
319
|
+
#### `!` (breaking change) policy
|
|
320
|
+
|
|
321
|
+
Each work-type carries a `breakingPolicy` value:
|
|
322
|
+
|
|
323
|
+
- `optional` (`feat`, `sec`) — `!` is allowed; both `type:` and `type!:` parse cleanly.
|
|
324
|
+
- `forbidden` (most types) — `!` is a policy violation. The premise: types like `internal!`, `perf!`, `fix!` are contradictory; an internal change cannot break a consumer contract, a pure perf change preserves the contract, and a bug-fix is by definition not a contract change.
|
|
325
|
+
- `required` (`drop`) — bare `drop:` is a policy violation; only `drop!:` is accepted. The premise: removing a feature always breaks consumers; the `!` form makes that explicit.
|
|
326
|
+
|
|
327
|
+
##### Two-tier policy enforcement
|
|
328
|
+
|
|
329
|
+
The `!` policy operates at two distinct levels with different semantics:
|
|
317
330
|
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
| `fix` | Bug fixes | `bugfix` |
|
|
321
|
-
| `deprecate` | Deprecated | |
|
|
322
|
-
| `feat` | Features | `feature` |
|
|
323
|
-
| `internal` | Internal | |
|
|
324
|
-
| `perf` | Performance | `performance` |
|
|
325
|
-
| `refactor` | Refactoring | |
|
|
326
|
-
| `sec` | Security | `security` |
|
|
327
|
-
| `tests` | Tests | `test` |
|
|
328
|
-
| `tooling` | Tooling | |
|
|
329
|
-
| `ci` | CI | |
|
|
330
|
-
| `deps` | Dependencies | `dep` |
|
|
331
|
-
| `docs` | Documentation | `doc` |
|
|
332
|
-
| `ai` | Agentic support | |
|
|
333
|
-
| `fmt` | (skipped) | |
|
|
331
|
+
- **Write-time** (commit-msg hook) — strict rejection. Policy violations are blocked at the gate where the author can act on them immediately. _Hook-based enforcement is tracked separately and is not yet shipped._
|
|
332
|
+
- **Release-time** (`parseCommitMessage`) — tolerant warn-and-continue. Commits already in the log cannot be rewritten, so a policy-violating commit is parsed using its canonical type with `breaking: false` (the `!` is dropped from the parse) and a `onPolicyViolation` callback fires. Callers (`decideRelease` etc.) can collect these warnings and surface them in the release report. A single legacy `internal!` in a year-old log does not block releases.
|
|
334
333
|
|
|
335
|
-
|
|
334
|
+
A `BREAKING CHANGE:` body footer on a `forbidden`-policy type triggers the same warning path as the prefix `!` does — the spirit of the policy is "internal/perf/etc. cannot be breaking", which must apply to both surfaces.
|
|
336
335
|
|
|
337
|
-
`
|
|
336
|
+
The release-prepare orchestrators (`releasePrepare`, `releasePrepareMono`, `releasePrepareProject`) apply `DEFAULT_BREAKING_POLICIES` automatically. Violations encountered while parsing each workspace's or project's commit window are collected onto the corresponding result's `policyViolations` field and rendered under the section in the prepare report:
|
|
338
337
|
|
|
339
|
-
|
|
338
|
+
```
|
|
339
|
+
arrays
|
|
340
|
+
Found 1 commits since arrays-v1.0.0
|
|
341
|
+
⚠️ 1 policy violation:
|
|
342
|
+
· def5678 'internal!: refactor cache' — type 'internal' at prefix surface
|
|
343
|
+
Bumping versions (patch)...
|
|
344
|
+
📦 1.0.0 → 1.0.1 (patch)
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
To customize, set `breakingPolicies` in `release-kit.config.ts` — provide a partial map to override individual types, or `{}` to disable enforcement entirely (the parser falls back to `'optional'` for any missing type). Violations remain warnings, never failures.
|
|
348
|
+
|
|
349
|
+
#### `🚨 **Breaking:**` bullet marker
|
|
350
|
+
|
|
351
|
+
Items whose commit subject carries the `!` prefix (e.g. `feat!`, `drop!`, `feat(api)!`) are rendered with a `🚨 **Breaking:** ` prefix on the bullet:
|
|
352
|
+
|
|
353
|
+
```markdown
|
|
354
|
+
- 🚨 **Breaking:** Drop legacy /v1 endpoint
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
Only the prefix `!` triggers this marker. A `BREAKING CHANGE:` body footer on its own does **not** retroactively mark a changelog item as breaking — the changelog signal is tied to the commit-prefix policy. This avoids surprise breaking-marker appearances for older commits written under earlier conventions.
|
|
358
|
+
|
|
359
|
+
#### `fmt`
|
|
360
|
+
|
|
361
|
+
`fmt:` commits are recognized by `parseCommitMessage` (they contribute to a patch bump) but `fmt` carries `excludedFromChangelog: true`. The bundled `cliff.toml.template` skips `fmt:` commits at the parser level, so they never appear in `CHANGELOG.md`, `changelog.json`, or release notes. The label and emoji are present in `work-types.json` for schema parity with the codeassembly upstream but never render.
|
|
362
|
+
|
|
363
|
+
#### Custom work types
|
|
364
|
+
|
|
365
|
+
Work types from your config are merged with these defaults by key — your entries override or extend, they don't replace the full set. Release-notes sections are rendered in the declaration order of the merged work-types record, with any unknown titles trailing the known ones.
|
|
366
|
+
|
|
367
|
+
The default `devOnlySections` (excluded from public release notes but still written to `CHANGELOG.md`) are derived from the Internal and Process tiers (excluding `fmt`). Override via `changelogJson.devOnlySections` in your config; matching is decorator-tolerant, so a bare-name override like `['Internal features']` keeps working against the emoji-prefixed and prefix-decorated default titles.
|
|
340
368
|
|
|
341
369
|
## CLI reference
|
|
342
370
|
|
|
@@ -404,6 +432,33 @@ release-kit prepare --only arrays --set-version 1.0.0
|
|
|
404
432
|
|
|
405
433
|
An empty changelog section is expected for a bare promotion, because the changelog is generated from commits since the last tag. To include a narrative entry, land a descriptive release commit (e.g., a `feat!` describing the stable API) before running `prepare`.
|
|
406
434
|
|
|
435
|
+
### `release-kit publish`
|
|
436
|
+
|
|
437
|
+
Publish packages that have release tags on HEAD. The publish workflow's reusable workflow `publish.reusable.yaml` invokes this command in CI.
|
|
438
|
+
|
|
439
|
+
| Flag | Description |
|
|
440
|
+
| ---------------------- | ---------------------------------------------------------------------------- |
|
|
441
|
+
| `--dry-run` | Preview without publishing |
|
|
442
|
+
| `--no-git-checks` | Skip the clean-working-tree check |
|
|
443
|
+
| `--tags=tag1,tag2,...` | Only publish the named tags (comma-separated, full tag names) |
|
|
444
|
+
| `--provenance` | Generate provenance statement (requires OIDC, not supported by classic yarn) |
|
|
445
|
+
| `--help`, `-h` | Show help |
|
|
446
|
+
|
|
447
|
+
#### Publishability filter
|
|
448
|
+
|
|
449
|
+
`publish` operates only on workspaces where `package.json#private` is absent or `false`. A workspace marked `private: true` is "versioned but not published": it can still be tagged by `release-kit tag`, get a `CHANGELOG.md` entry, and get a GitHub Release via `release-kit create-github-release` — only the registry publish step is skipped. Other commands ignore this filter and operate on private workspaces unchanged.
|
|
450
|
+
|
|
451
|
+
The filter behaves differently depending on whether `--tags` is provided:
|
|
452
|
+
|
|
453
|
+
- **Without `--tags`** (implicit resolution): unpublishable tags on HEAD are silently filtered. The pre-publish listing shows only the publishable subset. If the filter empties the set, `release-kit publish` prints `Nothing to publish.` and exits 0.
|
|
454
|
+
- **With `--tags`** (explicit naming): if any named tag points at an unpublishable workspace, `release-kit publish` exits 1 with one error line per unpublishable tag, citing `package.json#private`. Explicit naming surfaces the contradiction rather than silently dropping the tag.
|
|
455
|
+
|
|
456
|
+
Example output when an explicit tag is unpublishable:
|
|
457
|
+
|
|
458
|
+
```
|
|
459
|
+
Error: basic-v1.0.0 (packages/basic) cannot be published: package.json#private is true.
|
|
460
|
+
```
|
|
461
|
+
|
|
407
462
|
### `release-kit create-github-release`
|
|
408
463
|
|
|
409
464
|
Create GitHub Releases from `changelog.json` for tags on HEAD. Independent of `npm publish`: invoking this command creates Releases regardless of whether the matching package was published.
|
|
@@ -447,6 +502,28 @@ Scaffolded files:
|
|
|
447
502
|
- `.config/release-kit.config.ts` — starter config with commented-out customization examples (with `--with-config`)
|
|
448
503
|
- `.config/git-cliff.toml` — copied from the bundled template (with `--with-config`)
|
|
449
504
|
|
|
505
|
+
### `release-kit work-types`
|
|
506
|
+
|
|
507
|
+
Manage the canonical work-types taxonomy used by changelog and release-notes generation.
|
|
508
|
+
|
|
509
|
+
| Subcommand | Description |
|
|
510
|
+
| ---------- | ----------------------------------------------------------------------------------- |
|
|
511
|
+
| `check` | Compare the local `work-types.json` against the upstream codeassembly canonical |
|
|
512
|
+
| `sync` | Overwrite the local `work-types.json` with the upstream contents (after validation) |
|
|
513
|
+
|
|
514
|
+
`check` exit codes:
|
|
515
|
+
|
|
516
|
+
| Code | Meaning |
|
|
517
|
+
| ---- | --------------------------------------------------------------------------------- |
|
|
518
|
+
| `0` | Match (or upstream missing — transitional warning printed) |
|
|
519
|
+
| `1` | Drift detected |
|
|
520
|
+
| `2` | Network error or non-OK HTTP response |
|
|
521
|
+
| `3` | Schema mismatch (upstream JSON does not parse or fails the top-level shape check) |
|
|
522
|
+
|
|
523
|
+
The check is non-blocking initially: until codeassembly publishes its `work-types.json`, the upstream URL returns 404 and `check` exits 0 with a warning. CI flip to a blocking check is tracked as a follow-up once the upstream ships.
|
|
524
|
+
|
|
525
|
+
These commands are also exposed as `nmr work-types:check` / `nmr work-types:sync` from any package directory.
|
|
526
|
+
|
|
450
527
|
### `release-kit sync-labels`
|
|
451
528
|
|
|
452
529
|
Manage GitHub label definitions via config-driven YAML files.
|
package/cliff.toml.template
CHANGED
|
@@ -10,6 +10,13 @@
|
|
|
10
10
|
# Only ticketed commits (leading #NN, PROJ-NN, or ##) are included.
|
|
11
11
|
# Unticketed maintenance commits (deps upgrades, tooling tweaks) are skipped.
|
|
12
12
|
# Use ## as a synthetic ticket prefix for ad-hoc commits that belong in the changelog.
|
|
13
|
+
#
|
|
14
|
+
# Section order: each `group` value carries a hidden `<!-- NN -->` HTML-comment
|
|
15
|
+
# prefix encoding the canonical row position. tera's `group_by` filter sorts
|
|
16
|
+
# groups lexicographically by string, and the body template's `striptags`
|
|
17
|
+
# filter erases the comment from the rendered heading. Numbering is per
|
|
18
|
+
# unique group (not per parser entry) — all parsers routing to the same group
|
|
19
|
+
# share the same prefix.
|
|
13
20
|
|
|
14
21
|
[changelog]
|
|
15
22
|
header = """
|
|
@@ -61,24 +68,26 @@ commit_preprocessors = []
|
|
|
61
68
|
commit_parsers = [
|
|
62
69
|
{ message = "^release:", skip = true },
|
|
63
70
|
{ message = "^Merge", skip = true },
|
|
64
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
65
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
66
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
67
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?deprecate(!)?:", group = "Deprecated" },
|
|
68
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
69
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
70
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
71
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
72
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?
|
|
71
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?feat(!)?:", group = "<!-- 01 -->🎉 Features" },
|
|
72
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?feature(!)?:", group = "<!-- 01 -->🎉 Features" },
|
|
73
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?drop(!)?:", group = "<!-- 02 -->🪦 Removed" },
|
|
74
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?deprecate(!)?:", group = "<!-- 03 -->🗑️ Deprecated" },
|
|
75
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?fix(!)?:", group = "<!-- 04 -->🐛 Bug fixes" },
|
|
76
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?bugfix(!)?:", group = "<!-- 04 -->🐛 Bug fixes" },
|
|
77
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?sec(!)?:", group = "<!-- 05 -->🔒 Security" },
|
|
78
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?security(!)?:", group = "<!-- 05 -->🔒 Security" },
|
|
79
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?perf(!)?:", group = "<!-- 06 -->⚡ Performance" },
|
|
80
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?performance(!)?:", group = "<!-- 06 -->⚡ Performance" },
|
|
81
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?internal(!)?:", group = "<!-- 07 -->🏗️ Internal features" },
|
|
82
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?utility(!)?:", group = "<!-- 07 -->🏗️ Internal features" },
|
|
83
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?refactor(!)?:", group = "<!-- 08 -->♻️ Refactoring" },
|
|
84
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?tests?(!)?:", group = "<!-- 09 -->🧪 Tests" },
|
|
85
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?tooling(!)?:", group = "<!-- 10 -->⚙️ Tooling" },
|
|
86
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?ci(!)?:", group = "<!-- 11 -->👷 CI" },
|
|
87
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?deps?(!)?:", group = "<!-- 12 -->📦 Dependencies" },
|
|
88
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?ai(!)?:", group = "<!-- 13 -->🤖 Agentic support" },
|
|
89
|
+
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?docs?(!)?:", group = "<!-- 14 -->📚 Documentation" },
|
|
73
90
|
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?fmt(!)?:", skip = true },
|
|
74
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?internal(!)?:", group = "Internal" },
|
|
75
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?perf(!)?:", group = "Performance" },
|
|
76
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?performance(!)?:", group = "Performance" },
|
|
77
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?refactor(!)?:", group = "Refactoring" },
|
|
78
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?sec(!)?:", group = "Security" },
|
|
79
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?security(!)?:", group = "Security" },
|
|
80
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?tests?(!)?:", group = "Tests" },
|
|
81
|
-
{ message = "^(\\#\\d+([.\\-]\\d+)?|\\#\\#|[A-Z]+-\\d+)\\s+([\\w-]+\\|)?tooling(!)?:", group = "Tooling" },
|
|
82
91
|
# Skip unticketed commits (maintenance, deps, initial scaffolding, etc.)
|
|
83
92
|
{ message = ".*", skip = true },
|
|
84
93
|
]
|
package/dist/esm/.cache
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
|
|
1
|
+
704a70608ce284c9f8ef2dda2e6604a5f38ac0c995c9419ae39206ed053775c6
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { parseArgs, translateParseError } from "@williamthorsen/nmr-core";
|
|
2
|
+
import { parseArgs, readPackageVersion, translateParseError } from "@williamthorsen/nmr-core";
|
|
3
|
+
import { checkWorkTypesDrift } from "../checkWorkTypesDrift.js";
|
|
3
4
|
import { commitCommand } from "../commitCommand.js";
|
|
4
5
|
import { createGithubReleaseCommand } from "../createGithubReleaseCommand.js";
|
|
5
6
|
import { initCommand } from "../init/initCommand.js";
|
|
@@ -10,8 +11,9 @@ import { showTagPrefixesCommand } from "../showTagPrefixesCommand.js";
|
|
|
10
11
|
import { generateCommand } from "../sync-labels/generateCommand.js";
|
|
11
12
|
import { syncLabelsInitCommand } from "../sync-labels/initCommand.js";
|
|
12
13
|
import { syncLabelsCommand } from "../sync-labels/syncCommand.js";
|
|
14
|
+
import { syncWorkTypes } from "../syncWorkTypes.js";
|
|
13
15
|
import { tagCommand } from "../tagCommand.js";
|
|
14
|
-
|
|
16
|
+
const VERSION = readPackageVersion(import.meta.url);
|
|
15
17
|
function showUsage() {
|
|
16
18
|
console.info(`
|
|
17
19
|
Usage: release-kit <command> [options]
|
|
@@ -26,6 +28,7 @@ Commands:
|
|
|
26
28
|
show-tag-prefixes Show derived and declared legacy tag prefixes per workspace
|
|
27
29
|
init Initialize release-kit in the current repository
|
|
28
30
|
sync-labels Manage GitHub label synchronization
|
|
31
|
+
work-types Check for or sync work-type taxonomy drift against the upstream canonical
|
|
29
32
|
|
|
30
33
|
Options:
|
|
31
34
|
--dry-run Preview changes without writing files
|
|
@@ -171,6 +174,49 @@ legacy tag prefixes. Surfaces any release-shaped tags whose prefix is neither a
|
|
|
171
174
|
derived prefix nor declared in \`legacyIdentities\`, with a copy-pasteable
|
|
172
175
|
config snippet.
|
|
173
176
|
|
|
177
|
+
Options:
|
|
178
|
+
--help, -h Show this help message
|
|
179
|
+
`);
|
|
180
|
+
}
|
|
181
|
+
function showWorkTypesHelp() {
|
|
182
|
+
console.info(`
|
|
183
|
+
Usage: release-kit work-types <subcommand>
|
|
184
|
+
|
|
185
|
+
Manage the canonical work-types taxonomy used by changelog and release-notes generation.
|
|
186
|
+
|
|
187
|
+
Subcommands:
|
|
188
|
+
check Compare the local work-types.json against the upstream codeassembly canonical
|
|
189
|
+
sync Overwrite the local work-types.json with the upstream contents
|
|
190
|
+
|
|
191
|
+
Exit codes (check):
|
|
192
|
+
0 Match (or upstream missing \u2014 transitional warning printed)
|
|
193
|
+
1 Drift detected
|
|
194
|
+
2 Network error
|
|
195
|
+
3 Schema mismatch
|
|
196
|
+
|
|
197
|
+
Options:
|
|
198
|
+
--help, -h Show this help message
|
|
199
|
+
`);
|
|
200
|
+
}
|
|
201
|
+
function showWorkTypesCheckHelp() {
|
|
202
|
+
console.info(`
|
|
203
|
+
Usage: release-kit work-types check
|
|
204
|
+
|
|
205
|
+
Compare the local work-types.json against the upstream codeassembly canonical and report
|
|
206
|
+
drift. Exit 0 on match, 1 on drift, 0 + warning when upstream is missing (transitional),
|
|
207
|
+
2 on network error, 3 on schema mismatch.
|
|
208
|
+
|
|
209
|
+
Options:
|
|
210
|
+
--help, -h Show this help message
|
|
211
|
+
`);
|
|
212
|
+
}
|
|
213
|
+
function showWorkTypesSyncHelp() {
|
|
214
|
+
console.info(`
|
|
215
|
+
Usage: release-kit work-types sync
|
|
216
|
+
|
|
217
|
+
Fetch the upstream work-types.json, validate its top-level shape, and overwrite the local
|
|
218
|
+
copy with the upstream content (formatted with 2-space indent + trailing newline).
|
|
219
|
+
|
|
174
220
|
Options:
|
|
175
221
|
--help, -h Show this help message
|
|
176
222
|
`);
|
|
@@ -179,7 +225,9 @@ function showPublishHelp() {
|
|
|
179
225
|
console.info(`
|
|
180
226
|
Usage: release-kit publish [options]
|
|
181
227
|
|
|
182
|
-
Publish packages that have release tags on HEAD.
|
|
228
|
+
Publish packages that have release tags on HEAD. Operates only on workspaces where
|
|
229
|
+
package.json#private is absent or false. Without --tags, unpublishable workspaces are
|
|
230
|
+
silently filtered out. With --tags, naming an unpublishable tag is an error.
|
|
183
231
|
|
|
184
232
|
Options:
|
|
185
233
|
--dry-run Preview without publishing
|
|
@@ -341,6 +389,51 @@ if (command === "sync-labels") {
|
|
|
341
389
|
showSyncLabelsHelp();
|
|
342
390
|
process.exit(1);
|
|
343
391
|
}
|
|
392
|
+
if (command === "work-types") {
|
|
393
|
+
const subcommand = flags[0];
|
|
394
|
+
const subflags = flags.slice(1);
|
|
395
|
+
if (subcommand === "--help" || subcommand === "-h" || subcommand === void 0) {
|
|
396
|
+
showWorkTypesHelp();
|
|
397
|
+
process.exit(0);
|
|
398
|
+
}
|
|
399
|
+
if (subcommand === "check") {
|
|
400
|
+
if (subflags.some((f) => f === "--help" || f === "-h")) {
|
|
401
|
+
showWorkTypesCheckHelp();
|
|
402
|
+
process.exit(0);
|
|
403
|
+
}
|
|
404
|
+
if (subflags.length > 0) {
|
|
405
|
+
console.error(`Error: Unknown option: ${subflags[0]}`);
|
|
406
|
+
process.exit(1);
|
|
407
|
+
}
|
|
408
|
+
const result = await checkWorkTypesDrift();
|
|
409
|
+
if (result.exitCode === 0) {
|
|
410
|
+
console.info(result.message);
|
|
411
|
+
} else {
|
|
412
|
+
console.error(result.message);
|
|
413
|
+
}
|
|
414
|
+
process.exit(result.exitCode);
|
|
415
|
+
}
|
|
416
|
+
if (subcommand === "sync") {
|
|
417
|
+
if (subflags.some((f) => f === "--help" || f === "-h")) {
|
|
418
|
+
showWorkTypesSyncHelp();
|
|
419
|
+
process.exit(0);
|
|
420
|
+
}
|
|
421
|
+
if (subflags.length > 0) {
|
|
422
|
+
console.error(`Error: Unknown option: ${subflags[0]}`);
|
|
423
|
+
process.exit(1);
|
|
424
|
+
}
|
|
425
|
+
const result = await syncWorkTypes();
|
|
426
|
+
if (result.exitCode === 0) {
|
|
427
|
+
console.info(result.message);
|
|
428
|
+
} else {
|
|
429
|
+
console.error(result.message);
|
|
430
|
+
}
|
|
431
|
+
process.exit(result.exitCode);
|
|
432
|
+
}
|
|
433
|
+
console.error(`Error: Unknown subcommand: ${subcommand}`);
|
|
434
|
+
showWorkTypesHelp();
|
|
435
|
+
process.exit(1);
|
|
436
|
+
}
|
|
344
437
|
console.error(`Error: Unknown command: ${command}`);
|
|
345
438
|
showUsage();
|
|
346
439
|
process.exit(1);
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
import type { GenerateChangelogOptions } from './generateChangelogs.ts';
|
|
2
2
|
import type { ChangelogEntry, ReleaseConfig } from './types.ts';
|
|
3
|
+
export declare function stripGroupDecorations(group: string): string;
|
|
3
4
|
export declare function buildChangelogEntries(config: Pick<ReleaseConfig, 'cliffConfigPath' | 'changelogJson'>, tag: string, options?: GenerateChangelogOptions): ChangelogEntry[];
|
|
@@ -1,31 +1,32 @@
|
|
|
1
|
-
import { execFileSync } from "node:child_process";
|
|
2
|
-
import { copyFileSync, mkdtempSync, rmSync } from "node:fs";
|
|
3
|
-
import { tmpdir } from "node:os";
|
|
4
|
-
import { join } from "node:path";
|
|
5
1
|
import { extractVersion } from "./changelogJsonUtils.js";
|
|
2
|
+
import { DEFAULT_WORK_TYPES } from "./defaults.js";
|
|
3
|
+
import { COMMIT_PREPROCESSOR_PATTERNS } from "./parseCommitMessage.js";
|
|
6
4
|
import { resolveCliffConfigPath } from "./resolveCliffConfigPath.js";
|
|
5
|
+
import { runGitCliff } from "./runGitCliff.js";
|
|
6
|
+
import { stripEmojiPrefix } from "./stripEmojiPrefix.js";
|
|
7
7
|
import { isRecord, isUnknownArray } from "./typeGuards.js";
|
|
8
|
+
const HTML_COMMENT_PREFIX_PATTERN = /^<!--[^>]*-->/;
|
|
9
|
+
const CANONICAL_SECTION_ORDER = new Map(
|
|
10
|
+
Object.values(DEFAULT_WORK_TYPES).map((config, index) => [stripGroupDecorations(config.header), index])
|
|
11
|
+
);
|
|
12
|
+
function canonicalSectionPriority(title) {
|
|
13
|
+
const index = CANONICAL_SECTION_ORDER.get(stripGroupDecorations(title));
|
|
14
|
+
return index ?? Number.POSITIVE_INFINITY;
|
|
15
|
+
}
|
|
16
|
+
function stripGroupDecorations(group) {
|
|
17
|
+
return stripEmojiPrefix(group.replace(HTML_COMMENT_PREFIX_PATTERN, ""));
|
|
18
|
+
}
|
|
8
19
|
function buildChangelogEntries(config, tag, options) {
|
|
9
20
|
const resolvedConfigPath = resolveCliffConfigPath(config.cliffConfigPath, import.meta.url);
|
|
10
|
-
|
|
11
|
-
let tempDir;
|
|
12
|
-
if (resolvedConfigPath.endsWith(".template")) {
|
|
13
|
-
tempDir = mkdtempSync(join(tmpdir(), "cliff-"));
|
|
14
|
-
cliffConfigPath = join(tempDir, "cliff.toml");
|
|
15
|
-
copyFileSync(resolvedConfigPath, cliffConfigPath);
|
|
16
|
-
}
|
|
17
|
-
const args = ["--config", cliffConfigPath, "--context", "--tag", tag];
|
|
21
|
+
const cliffArgs = ["--context", "--tag", tag];
|
|
18
22
|
if (options?.tagPattern !== void 0) {
|
|
19
|
-
|
|
23
|
+
cliffArgs.push("--tag-pattern", options.tagPattern);
|
|
20
24
|
}
|
|
21
25
|
for (const includePath of options?.includePaths ?? []) {
|
|
22
|
-
|
|
26
|
+
cliffArgs.push("--include-path", includePath);
|
|
23
27
|
}
|
|
24
28
|
try {
|
|
25
|
-
const contextJson =
|
|
26
|
-
encoding: "utf8",
|
|
27
|
-
stdio: ["pipe", "pipe", "inherit"]
|
|
28
|
-
});
|
|
29
|
+
const contextJson = runGitCliff(resolvedConfigPath, cliffArgs, ["pipe", "pipe", "inherit"]);
|
|
29
30
|
const releases = parseCliffContext(contextJson);
|
|
30
31
|
const devOnlySections = new Set(config.changelogJson.devOnlySections);
|
|
31
32
|
return transformReleases(releases, devOnlySections);
|
|
@@ -33,10 +34,6 @@ function buildChangelogEntries(config, tag, options) {
|
|
|
33
34
|
throw new Error(
|
|
34
35
|
`Failed to build changelog entries for tag ${tag}: ${error instanceof Error ? error.message : String(error)}`
|
|
35
36
|
);
|
|
36
|
-
} finally {
|
|
37
|
-
if (tempDir !== void 0) {
|
|
38
|
-
rmSync(tempDir, { recursive: true, force: true });
|
|
39
|
-
}
|
|
40
37
|
}
|
|
41
38
|
}
|
|
42
39
|
function parseCliffContext(json) {
|
|
@@ -76,6 +73,7 @@ function toCliffContextCommit(value) {
|
|
|
76
73
|
}
|
|
77
74
|
function transformReleases(releases, devOnlySections) {
|
|
78
75
|
const entries = [];
|
|
76
|
+
const devOnlyNormalised = new Set([...devOnlySections].map(stripGroupDecorations));
|
|
79
77
|
for (const release of releases) {
|
|
80
78
|
if (release.version === void 0) {
|
|
81
79
|
continue;
|
|
@@ -84,9 +82,10 @@ function transformReleases(releases, devOnlySections) {
|
|
|
84
82
|
const date = release.timestamp !== void 0 ? new Date(release.timestamp * 1e3).toISOString().slice(0, 10) : "unreleased";
|
|
85
83
|
const sectionMap = /* @__PURE__ */ new Map();
|
|
86
84
|
for (const commit of release.commits ?? []) {
|
|
87
|
-
const group = commit.group ?? "Other";
|
|
85
|
+
const group = stripCommentPrefix(commit.group ?? "Other");
|
|
88
86
|
const description = extractDescription(commit.message);
|
|
89
87
|
const body = extractBody(commit.message);
|
|
88
|
+
const breaking = subjectHasBreakingMarker(commit.message);
|
|
90
89
|
let items = sectionMap.get(group);
|
|
91
90
|
if (items === void 0) {
|
|
92
91
|
items = [];
|
|
@@ -96,6 +95,9 @@ function transformReleases(releases, devOnlySections) {
|
|
|
96
95
|
if (body !== void 0) {
|
|
97
96
|
item.body = body;
|
|
98
97
|
}
|
|
98
|
+
if (breaking) {
|
|
99
|
+
item.breaking = true;
|
|
100
|
+
}
|
|
99
101
|
items.push(item);
|
|
100
102
|
}
|
|
101
103
|
const sections = [];
|
|
@@ -105,16 +107,27 @@ function transformReleases(releases, devOnlySections) {
|
|
|
105
107
|
}
|
|
106
108
|
sections.push({
|
|
107
109
|
title,
|
|
108
|
-
audience:
|
|
110
|
+
audience: devOnlyNormalised.has(stripGroupDecorations(title)) ? "dev" : "all",
|
|
109
111
|
items
|
|
110
112
|
});
|
|
111
113
|
}
|
|
114
|
+
sections.sort((a, b) => canonicalSectionPriority(a.title) - canonicalSectionPriority(b.title));
|
|
112
115
|
if (sections.length > 0) {
|
|
113
116
|
entries.push({ version, date, sections });
|
|
114
117
|
}
|
|
115
118
|
}
|
|
116
119
|
return entries;
|
|
117
120
|
}
|
|
121
|
+
function stripCommentPrefix(group) {
|
|
122
|
+
return group.replace(HTML_COMMENT_PREFIX_PATTERN, "");
|
|
123
|
+
}
|
|
124
|
+
function subjectHasBreakingMarker(message) {
|
|
125
|
+
let subject = message.split("\n", 1)[0] ?? "";
|
|
126
|
+
for (const pattern of COMMIT_PREPROCESSOR_PATTERNS) {
|
|
127
|
+
subject = subject.replace(pattern, "");
|
|
128
|
+
}
|
|
129
|
+
return /^(?:[^|]+\|)?\w+(?:\([^)]+\))?!:/.test(subject);
|
|
130
|
+
}
|
|
118
131
|
function extractDescription(message) {
|
|
119
132
|
const firstLine = message.split("\n")[0] ?? message;
|
|
120
133
|
const afterColon = firstLine.split(": ").slice(1).join(": ");
|
|
@@ -155,5 +168,6 @@ function extractBody(message) {
|
|
|
155
168
|
return lines.slice(start, end).join("\n").trim();
|
|
156
169
|
}
|
|
157
170
|
export {
|
|
158
|
-
buildChangelogEntries
|
|
171
|
+
buildChangelogEntries,
|
|
172
|
+
stripGroupDecorations
|
|
159
173
|
};
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const UPSTREAM_WORK_TYPES_URL = "https://raw.githubusercontent.com/williamthorsen/codeassembly/main/packages/agents/content/skills/_data/work-types.json";
|
|
2
|
+
export interface DriftCheckResult {
|
|
3
|
+
exitCode: 0 | 1 | 2 | 3;
|
|
4
|
+
message: string;
|
|
5
|
+
}
|
|
6
|
+
export interface CheckWorkTypesDriftDependencies {
|
|
7
|
+
localPath?: string;
|
|
8
|
+
fetch?: typeof globalThis.fetch;
|
|
9
|
+
upstreamUrl?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare function checkWorkTypesDrift(dependencies?: CheckWorkTypesDriftDependencies): Promise<DriftCheckResult>;
|