@williamthorsen/release-kit 10.2.0 → 10.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.
@@ -52,7 +52,7 @@ function detectRepoType() {
52
52
 
53
53
  // .readyup/kits/default.ts
54
54
  function getMinVersion() {
55
- const picked = { "version": "10.2.0" };
55
+ const picked = { "version": "10.2.1" };
56
56
  if (typeof picked.version !== "string") {
57
57
  throw new TypeError("release-kit/package.json: 'version' must be a string");
58
58
  }
@@ -10,7 +10,7 @@
10
10
  "readyupVersion": "0.23.0",
11
11
  "source": "kits/default.ts",
12
12
  "sourceHash": "afe26920",
13
- "targetHash": "9b3ddc09"
13
+ "targetHash": "5ac6d830"
14
14
  },
15
15
  {
16
16
  "checklists": [
package/CHANGELOG.md CHANGED
@@ -2,6 +2,14 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file.
4
4
 
5
+ ## 10.2.1 — 2026-08-04
6
+
7
+ ### 🐛 Bug fixes
8
+
9
+ - Remove the 1 MiB ceiling on captured git output (#596)
10
+
11
+ Fixes an issue where `release-kit prepare` began aborting once a repository's release history grew long enough, leaving that repository unable to cut another release. The fix covers, in addition to `prepare`, every other release-kit command that reads from git.
12
+
5
13
  ## 10.2.0 — 2026-08-04
6
14
 
7
15
  ### 🎉 Features
package/README.md CHANGED
@@ -5,19 +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 from `git-cliff --context` output rendered in-process (with optional [editorial overrides](#editorial-overrides)).
6
6
 
7
7
  <!-- section:release-notes -->
8
- ## Release notes — v10.2.0 (2026-08-04)
8
+ ## Release notes — v10.2.1 (2026-08-04)
9
9
 
10
- ### 🎉 Features
10
+ ### 🐛 Bug fixes
11
11
 
12
- - Add status labels and clear grouped-label descriptions (#585)
12
+ - Remove the 1 MiB ceiling on captured git output (#596)
13
13
 
14
- Adds two status labels (`status:blocked` and `status:on-hold`) to the common preset and removes descriptions from other scoped labels (`priority:` and `value:`) to keep scoped groups compact in the GitHub UI.
15
-
16
- - Publish each package's readyup kit from the package that owns it (#590)
17
-
18
- ReadyUp checks for `@williamthorsen/nmr`, `@williamthorsen/release-kit`, and `v11y-check` are now run directly against these packages, guaranteeing a version-appropriate check, instead of against their host repo. The package must be installed as a direct dependency in the calling repo.
19
-
20
- The syntax is `rdy run --from npm:<package>`. `rdy run --packages` runs the kits contained in any packages listed in `.config/readyup.config.ts`. Requires `readyup` 0.23 or later.
14
+ Fixes an issue where `release-kit prepare` began aborting once a repository's release history grew long enough, leaving that repository unable to cut another release. The fix covers, in addition to `prepare`, every other release-kit command that reads from git.
21
15
  <!-- /section:release-notes -->
22
16
 
23
17
  ## Installation
@@ -1,7 +1,9 @@
1
1
  import { execFileSync } from 'node:child_process';
2
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
2
3
  export function assertCleanWorkingTree() {
3
4
  const status = execFileSync('git', ['status', '--porcelain'], {
4
5
  encoding: 'utf8',
6
+ maxBuffer: GIT_OUTPUT_LIMIT,
5
7
  stdio: ['pipe', 'pipe', 'pipe'],
6
8
  }).trim();
7
9
  if (status.length > 0) {
@@ -24,7 +24,7 @@ export function buildChangelogEntries(config, tag, options) {
24
24
  cliffArgs.push('--include-path', includePath);
25
25
  }
26
26
  try {
27
- const contextJson = runGitCliff(resolvedConfigPath, cliffArgs, ['pipe', 'pipe', 'inherit']);
27
+ const contextJson = runGitCliff(resolvedConfigPath, cliffArgs);
28
28
  const releases = parseCliffContext(contextJson);
29
29
  const devOnlySections = new Set(config.changelogJson.devOnlySections);
30
30
  return transformReleases(releases, devOnlySections);
@@ -1,6 +1,6 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import { readFileSync } from 'node:fs';
3
- import { parseArgsOrExit } from '@williamthorsen/nmr-core';
3
+ import { GIT_OUTPUT_LIMIT, parseArgsOrExit } from '@williamthorsen/nmr-core';
4
4
  import { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE } from "./prepareCommand.js";
5
5
  const commitFlagSchema = {
6
6
  dryRun: { long: '--dry-run', type: 'boolean' },
@@ -38,7 +38,10 @@ export function commitCommand(argv) {
38
38
  console.info('[dry-run] Would create commit with message:\n');
39
39
  console.info(message);
40
40
  try {
41
- const status = execFileSync('git', ['status', '--porcelain'], { encoding: 'utf8' });
41
+ const status = execFileSync('git', ['status', '--porcelain'], {
42
+ encoding: 'utf8',
43
+ maxBuffer: GIT_OUTPUT_LIMIT,
44
+ });
42
45
  if (status.trim().length > 0) {
43
46
  console.info('\nUncommitted changes:');
44
47
  console.info(status.trimEnd());
@@ -49,7 +52,7 @@ export function commitCommand(argv) {
49
52
  }
50
53
  return;
51
54
  }
52
- execFileSync('git', ['add', '-A']);
53
- execFileSync('git', ['commit', '-m', message]);
55
+ execFileSync('git', ['add', '-A'], { maxBuffer: GIT_OUTPUT_LIMIT });
56
+ execFileSync('git', ['commit', '-m', message], { maxBuffer: GIT_OUTPUT_LIMIT });
54
57
  console.info(`Created release commit: ${title}`);
55
58
  }
@@ -1,5 +1,6 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import { readFileSync } from 'node:fs';
3
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
3
4
  import { deleteFileIfExists } from "./deleteFileIfExists.js";
4
5
  import { RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE } from "./prepareCommand.js";
5
6
  export function createTags(options) {
@@ -31,7 +32,7 @@ export function createTags(options) {
31
32
  const created = [];
32
33
  for (const tag of tags) {
33
34
  try {
34
- execFileSync('git', ['tag', '-a', tag, '-m', tag]);
35
+ execFileSync('git', ['tag', '-a', tag, '-m', tag], { maxBuffer: GIT_OUTPUT_LIMIT });
35
36
  created.push(tag);
36
37
  }
37
38
  catch (error) {
@@ -54,8 +55,8 @@ export function createTags(options) {
54
55
  }
55
56
  function assertCleanWorkingTree() {
56
57
  try {
57
- execFileSync('git', ['diff', '--quiet']);
58
- execFileSync('git', ['diff', '--quiet', '--cached']);
58
+ execFileSync('git', ['diff', '--quiet'], { maxBuffer: GIT_OUTPUT_LIMIT });
59
+ execFileSync('git', ['diff', '--quiet', '--cached'], { maxBuffer: GIT_OUTPUT_LIMIT });
59
60
  }
60
61
  catch (error) {
61
62
  if (error instanceof Error && 'code' in error && error.code === 'ENOENT') {
@@ -1,4 +1,5 @@
1
1
  import { execFileSync } from 'node:child_process';
2
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
2
3
  const EXAMPLE_TAG_LIMIT = 3;
3
4
  const CANDIDATE_TAG_PATTERN = /^(?<prefix>[a-z][a-z0-9-]*-v)\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/;
4
5
  export function detectUndeclaredTagPrefixes(knownPrefixes) {
@@ -7,6 +8,7 @@ export function detectUndeclaredTagPrefixes(knownPrefixes) {
7
8
  try {
8
9
  rawOutput = execFileSync('git', ['tag', '--list'], {
9
10
  encoding: 'utf8',
11
+ maxBuffer: GIT_OUTPUT_LIMIT,
10
12
  stdio: ['pipe', 'pipe', 'pipe'],
11
13
  });
12
14
  }
@@ -1,4 +1,5 @@
1
1
  import { execFileSync } from 'node:child_process';
2
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
2
3
  const FIELD_SEPARATOR = '\u{1F}';
3
4
  function isNoTagError(err) {
4
5
  return typeof err === 'object' && err !== null && 'status' in err && err.status === 128;
@@ -14,6 +15,7 @@ function findLatestTag(tagPrefixes) {
14
15
  try {
15
16
  const tagResult = execFileSync('git', ['describe', '--tags', '--abbrev=0', ...matchArgs], {
16
17
  encoding: 'utf8',
18
+ maxBuffer: GIT_OUTPUT_LIMIT,
17
19
  stdio: ['pipe', 'pipe', 'pipe'],
18
20
  }).trim();
19
21
  return tagResult || undefined;
@@ -52,6 +54,7 @@ export function getCommitsSinceTarget(tagPrefixes, paths) {
52
54
  try {
53
55
  logOutput = execFileSync('git', args, {
54
56
  encoding: 'utf8',
57
+ maxBuffer: GIT_OUTPUT_LIMIT,
55
58
  stdio: ['pipe', 'pipe', 'pipe'],
56
59
  }).trim();
57
60
  }
@@ -1,9 +1,10 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import { existsSync, readFileSync } from 'node:fs';
3
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
3
4
  import { parseJsonRecord } from "./parseJsonRecord.js";
4
5
  export function isGitRepo() {
5
6
  try {
6
- execSync('git rev-parse --is-inside-work-tree', { stdio: 'pipe' });
7
+ execSync('git rev-parse --is-inside-work-tree', { maxBuffer: GIT_OUTPUT_LIMIT, stdio: 'pipe' });
7
8
  return { ok: true };
8
9
  }
9
10
  catch {
@@ -1,5 +1,6 @@
1
1
  import { execFileSync } from 'node:child_process';
2
2
  import { basename } from 'node:path';
3
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
3
4
  import { deriveWorkspaceConfig } from "./deriveWorkspaceConfig.js";
4
5
  import { detectUndeclaredTagPrefixes } from "./detectUndeclaredTagPrefixes.js";
5
6
  import { discoverWorkspaces } from "./discoverWorkspaces.js";
@@ -69,6 +70,7 @@ function countTagsMatching(prefix) {
69
70
  try {
70
71
  const output = execFileSync('git', ['tag', '--list', `${prefix}*`], {
71
72
  encoding: 'utf8',
73
+ maxBuffer: GIT_OUTPUT_LIMIT,
72
74
  stdio: ['pipe', 'pipe', 'pipe'],
73
75
  });
74
76
  return output.split('\n').filter((line) => line.trim() !== '').length;
@@ -1,10 +1,12 @@
1
1
  import { execFileSync } from 'node:child_process';
2
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
2
3
  export function pushRelease(resolvedTags, options = {}) {
3
4
  const { dryRun = false, tagsOnly = false } = options;
4
5
  const steps = [];
5
6
  if (!tagsOnly) {
6
7
  const branch = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
7
8
  encoding: 'utf8',
9
+ maxBuffer: GIT_OUTPUT_LIMIT,
8
10
  stdio: ['pipe', 'pipe', 'pipe'],
9
11
  }).trim();
10
12
  const command = ['git', 'push', 'origin', branch];
@@ -1,8 +1,12 @@
1
1
  import { execFileSync } from 'node:child_process';
2
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
2
3
  const VERSION_PATTERN = /^v\d+\.\d+\.\d+/;
3
4
  const SEMVER_SUFFIX_PATTERN = /^\d+\.\d+\.\d+/;
4
5
  export function resolveReleaseTags(args) {
5
- const output = execFileSync('git', ['tag', '--points-at', 'HEAD'], { encoding: 'utf8' });
6
+ const output = execFileSync('git', ['tag', '--points-at', 'HEAD'], {
7
+ encoding: 'utf8',
8
+ maxBuffer: GIT_OUTPUT_LIMIT,
9
+ });
6
10
  const tags = output
7
11
  .split('\n')
8
12
  .map((line) => line.trim())
@@ -1,3 +1,2 @@
1
- import { type StdioOptions } from 'node:child_process';
2
- export declare function runGitCliff(cliffConfigPath: string, cliffArgs: readonly string[], stdio: StdioOptions): string;
1
+ export declare function runGitCliff(cliffConfigPath: string, cliffArgs: readonly string[]): string;
3
2
  export declare function refreshGitCliffCache(): void;
@@ -1,30 +1,30 @@
1
1
  import { execFileSync } from 'node:child_process';
2
- import { copyFileSync, mkdtempSync, rmSync } from 'node:fs';
2
+ import { copyFileSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
3
3
  import { tmpdir } from 'node:os';
4
4
  import { join } from 'node:path';
5
- export function runGitCliff(cliffConfigPath, cliffArgs, stdio) {
6
- let configPath = cliffConfigPath;
7
- let tempDir;
5
+ import { GIT_OUTPUT_LIMIT } from '@williamthorsen/nmr-core';
6
+ export function runGitCliff(cliffConfigPath, cliffArgs) {
7
+ const tempDir = mkdtempSync(join(tmpdir(), 'cliff-'));
8
8
  try {
9
+ let configPath = cliffConfigPath;
9
10
  if (cliffConfigPath.endsWith('.template')) {
10
- tempDir = mkdtempSync(join(tmpdir(), 'cliff-'));
11
11
  configPath = join(tempDir, 'cliff.toml');
12
12
  copyFileSync(cliffConfigPath, configPath);
13
13
  }
14
- return execFileSync('npx', ['--prefer-offline', '--yes', 'git-cliff', '--config', configPath, ...cliffArgs], {
15
- encoding: 'utf8',
16
- stdio,
14
+ const outputPath = join(tempDir, 'output.json');
15
+ execFileSync('npx', ['--prefer-offline', '--yes', 'git-cliff', '--config', configPath, ...cliffArgs, '--output', outputPath], {
16
+ stdio: ['ignore', 'ignore', 'inherit'],
17
17
  env: { ...process.env, npm_config_progress: 'false' },
18
18
  });
19
+ return readFileSync(outputPath, 'utf8');
19
20
  }
20
21
  finally {
21
- if (tempDir !== undefined) {
22
- rmSync(tempDir, { recursive: true, force: true });
23
- }
22
+ rmSync(tempDir, { recursive: true, force: true });
24
23
  }
25
24
  }
26
25
  export function refreshGitCliffCache() {
27
26
  execFileSync('npx', ['--yes', 'git-cliff', '--version'], {
27
+ maxBuffer: GIT_OUTPUT_LIMIT,
28
28
  stdio: ['ignore', 'pipe', 'inherit'],
29
29
  env: { ...process.env, npm_config_progress: 'false' },
30
30
  });
@@ -1,11 +1,11 @@
1
1
  import { execSync } from 'node:child_process';
2
2
  import { existsSync } from 'node:fs';
3
- import { reportError } from '@williamthorsen/nmr-core';
3
+ import { GIT_OUTPUT_LIMIT, reportError } from '@williamthorsen/nmr-core';
4
4
  import { checkRetiredSyncLabelsConfig } from "./retiredConfig.js";
5
5
  const WORKFLOW_FILE = '.github/workflows/sync-labels.yaml';
6
6
  function checkGhAvailable() {
7
7
  try {
8
- execSync('gh --version', { stdio: 'pipe' });
8
+ execSync('gh --version', { maxBuffer: GIT_OUTPUT_LIMIT, stdio: 'pipe' });
9
9
  return true;
10
10
  }
11
11
  catch {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/release-kit",
3
- "version": "10.2.0",
3
+ "version": "10.2.1",
4
4
  "description": "Version-bumping and changelog-generation toolkit for release workflows",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/williamthorsen/node-monorepo-tools/tree/main/packages/release-kit#readme",
@@ -44,7 +44,7 @@
44
44
  "semver": "7.8.5",
45
45
  "yaml": "2.9.0",
46
46
  "zod": "4.4.3",
47
- "@williamthorsen/nmr-core": "0.9.0"
47
+ "@williamthorsen/nmr-core": "0.9.1"
48
48
  },
49
49
  "devDependencies": {
50
50
  "@types/semver": "7.7.1",