@williamthorsen/release-kit 15.0.2 → 15.0.3
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 +22 -0
- package/.readyup/kits/default.js +2 -2
- package/.readyup/kits/npm-auto-publish.js +1 -1
- package/.readyup/manifest.json +6 -6
- package/CHANGELOG.md +9 -0
- package/README.md +1 -7
- package/dist/esm/assertCleanWorkingTree.js +2 -2
- package/dist/esm/commitCommand.js +4 -4
- package/dist/esm/createTags.js +4 -4
- package/dist/esm/detectUndeclaredTagPrefixes.js +2 -2
- package/dist/esm/enumerateReleaseWindows.js +2 -2
- package/dist/esm/init/checks.js +2 -2
- package/dist/esm/init/scaffold.js +14 -5
- package/dist/esm/init/updateTemplatesCommand.js +3 -3
- package/dist/esm/previewTagPrefixes.js +2 -2
- package/dist/esm/pushRelease.js +2 -2
- package/dist/esm/releasePlan.js +1 -1
- package/dist/esm/resolveReleaseTags.js +2 -2
- package/dist/esm/sync-labels/initCommand.js +12 -4
- package/dist/esm/sync-labels/syncCommand.js +2 -2
- package/dist/esm/sync-labels/templates.d.ts +2 -2
- package/dist/esm/sync-labels/templates.js +12 -39
- package/package.json +9 -8
- package/templates/sync-labels.yaml.template +36 -0
package/.meta/changelog.json
CHANGED
|
@@ -1,4 +1,26 @@
|
|
|
1
1
|
[
|
|
2
|
+
{
|
|
3
|
+
"version": "15.0.3",
|
|
4
|
+
"date": "2026-10-27",
|
|
5
|
+
"sections": [
|
|
6
|
+
{
|
|
7
|
+
"title": "♻️ Refactoring",
|
|
8
|
+
"audience": "dev",
|
|
9
|
+
"items": [
|
|
10
|
+
{
|
|
11
|
+
"description": "Replaces the `syncLabelsWorkflow` function in `release-kit` with the verbatim file `templates/sync-labels.yaml.template`, which `sync-labels init` and `update-templates` now read from the package root and which the package's `files` list now includes. (#1114)",
|
|
12
|
+
"hash": "89c775ea0a5d603f33b1edd036055dc0fc7bb109",
|
|
13
|
+
"entry": 1
|
|
14
|
+
},
|
|
15
|
+
{
|
|
16
|
+
"description": "Apply the naming conventions to nmr-core's identifiers (#1125)",
|
|
17
|
+
"body": "Renames the identifiers in nmr-core to follow the naming conventions, including the exported option keys of `updateManagedFile` and `writeFileWithCheck`, which change from `dryRun` and `overwrite` to `isDryRun` and `shouldOverwrite`, and the constant `GIT_OUTPUT_LIMIT`, which becomes `GIT_OUTPUT_LIMIT_BYTES`. Updates the call sites in nmr, release-kit, and v11y-check to the new names.",
|
|
18
|
+
"hash": "2cb60f628512ed6ec2273a219a7b6c71aa35b1bf"
|
|
19
|
+
}
|
|
20
|
+
]
|
|
21
|
+
}
|
|
22
|
+
]
|
|
23
|
+
},
|
|
2
24
|
{
|
|
3
25
|
"version": "15.0.2",
|
|
4
26
|
"date": "2026-10-24",
|
package/.readyup/kits/default.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** @noformat -- @generated. Do not edit. Compiled by rdy. */
|
|
2
2
|
/* eslint-disable */
|
|
3
|
-
export const __readyupVersion = "0.
|
|
3
|
+
export const __readyupVersion = "0.44.0";
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
// .readyup/kits/default.ts
|
|
@@ -234,7 +234,7 @@ var CREATE_GITHUB_RELEASE_WORKFLOW_HASH_SINGLE = "d6de961de913c67b08dfa7e07f7349
|
|
|
234
234
|
|
|
235
235
|
// .readyup/kits/default.ts
|
|
236
236
|
function getMinVersion() {
|
|
237
|
-
const picked = { "version": "15.0.
|
|
237
|
+
const picked = { "version": "15.0.3" };
|
|
238
238
|
if (typeof picked["version"] !== "string") {
|
|
239
239
|
throw new TypeError("release-kit/package.json: 'version' must be a string");
|
|
240
240
|
}
|
package/.readyup/manifest.json
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
"checklist": "release-kit",
|
|
8
8
|
"checks": [
|
|
9
9
|
"@williamthorsen/release-kit in devDependencies",
|
|
10
|
-
"@williamthorsen/release-kit >= 15.0.
|
|
10
|
+
"@williamthorsen/release-kit >= 15.0.3",
|
|
11
11
|
"release.yaml workflow exists",
|
|
12
12
|
"release.yaml matches template",
|
|
13
13
|
"release.yaml does not reference deprecated tag ref",
|
|
@@ -63,7 +63,7 @@
|
|
|
63
63
|
"path": "lib/workflow-hashes.ts"
|
|
64
64
|
},
|
|
65
65
|
{
|
|
66
|
-
"hash": "
|
|
66
|
+
"hash": "5c98064e",
|
|
67
67
|
"kind": "inline",
|
|
68
68
|
"path": "../package.json",
|
|
69
69
|
"paths": [
|
|
@@ -98,10 +98,10 @@
|
|
|
98
98
|
],
|
|
99
99
|
"name": "default",
|
|
100
100
|
"path": "kits/default.js",
|
|
101
|
-
"readyupVersion": "0.
|
|
101
|
+
"readyupVersion": "0.44.0",
|
|
102
102
|
"source": "kits/default.ts",
|
|
103
103
|
"sourceHash": "ad3666b8",
|
|
104
|
-
"targetHash": "
|
|
104
|
+
"targetHash": "35d9bb56"
|
|
105
105
|
},
|
|
106
106
|
{
|
|
107
107
|
"checklistChecks": [
|
|
@@ -157,10 +157,10 @@
|
|
|
157
157
|
],
|
|
158
158
|
"name": "npm-auto-publish",
|
|
159
159
|
"path": "kits/npm-auto-publish.js",
|
|
160
|
-
"readyupVersion": "0.
|
|
160
|
+
"readyupVersion": "0.44.0",
|
|
161
161
|
"source": "kits/npm-auto-publish.ts",
|
|
162
162
|
"sourceHash": "682fdd4a",
|
|
163
|
-
"targetHash": "
|
|
163
|
+
"targetHash": "fac6bc8b"
|
|
164
164
|
}
|
|
165
165
|
]
|
|
166
166
|
}
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,15 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
|
|
5
|
+
## 15.0.3 — 2026-10-27
|
|
6
|
+
|
|
7
|
+
### ♻️ Refactoring
|
|
8
|
+
|
|
9
|
+
- Replaces the `syncLabelsWorkflow` function in `release-kit` with the verbatim file `templates/sync-labels.yaml.template`, which `sync-labels init` and `update-templates` now read from the package root and which the package's `files` list now includes. (#1114)
|
|
10
|
+
- Apply the naming conventions to nmr-core's identifiers (#1125)
|
|
11
|
+
|
|
12
|
+
Renames the identifiers in nmr-core to follow the naming conventions, including the exported option keys of `updateManagedFile` and `writeFileWithCheck`, which change from `dryRun` and `overwrite` to `isDryRun` and `shouldOverwrite`, and the constant `GIT_OUTPUT_LIMIT`, which becomes `GIT_OUTPUT_LIMIT_BYTES`. Updates the call sites in nmr, release-kit, and v11y-check to the new names.
|
|
13
|
+
|
|
5
14
|
## 15.0.2 — 2026-10-24
|
|
6
15
|
|
|
7
16
|
### 🐛 Bug fixes
|
package/README.md
CHANGED
|
@@ -6,13 +6,7 @@ Version-bumping and changelog-generation toolkit for release workflows.
|
|
|
6
6
|
|
|
7
7
|
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 the same commit history that decides each bump (with optional [editorial overrides](docs/editorial-overrides.md)).
|
|
8
8
|
|
|
9
|
-
<!-- section:release-notes -->
|
|
10
|
-
## Release notes — v15.0.2 (2026-10-24)
|
|
11
|
-
|
|
12
|
-
### 🐛 Bug fixes
|
|
13
|
-
|
|
14
|
-
- Fixes the issue that the `create-github-release.yaml` template written by `release-kit init` and `release-kit update-templates` named the workflow `Create GitHub Release` in title case, which made the default readyup kit's template check warn on a consumer workflow renamed to `Create GitHub release`. (#1102)
|
|
15
|
-
<!-- /section:release-notes -->
|
|
9
|
+
<!-- section:release-notes --><!-- /section:release-notes -->
|
|
16
10
|
|
|
17
11
|
## Installation
|
|
18
12
|
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import {
|
|
2
|
+
import { GIT_OUTPUT_LIMIT_BYTES } from '@williamthorsen/nmr-core';
|
|
3
3
|
export function assertCleanWorkingTree() {
|
|
4
4
|
const status = execFileSync('git', ['status', '--porcelain'], {
|
|
5
5
|
encoding: 'utf8',
|
|
6
|
-
maxBuffer:
|
|
6
|
+
maxBuffer: GIT_OUTPUT_LIMIT_BYTES,
|
|
7
7
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
8
8
|
}).trim();
|
|
9
9
|
if (status.length > 0) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import { readFileSync } from 'node:fs';
|
|
3
|
-
import {
|
|
3
|
+
import { GIT_OUTPUT_LIMIT_BYTES, hasErrnoCode, parseArgsOrExit } from '@williamthorsen/nmr-core';
|
|
4
4
|
import { readReleaseTags, RELEASE_SUMMARY_FILE, resolveReleaseTagsPath } from "./releaseFiles.js";
|
|
5
5
|
const commitFlagSchema = {
|
|
6
6
|
dryRun: { long: '--dry-run', type: 'boolean' },
|
|
@@ -30,7 +30,7 @@ export function commitCommand(argv) {
|
|
|
30
30
|
try {
|
|
31
31
|
const status = execFileSync('git', ['status', '--porcelain'], {
|
|
32
32
|
encoding: 'utf8',
|
|
33
|
-
maxBuffer:
|
|
33
|
+
maxBuffer: GIT_OUTPUT_LIMIT_BYTES,
|
|
34
34
|
});
|
|
35
35
|
if (status.trim().length > 0) {
|
|
36
36
|
console.info('\nUncommitted changes:');
|
|
@@ -42,7 +42,7 @@ export function commitCommand(argv) {
|
|
|
42
42
|
}
|
|
43
43
|
return;
|
|
44
44
|
}
|
|
45
|
-
execFileSync('git', ['add', '-A'], { maxBuffer:
|
|
46
|
-
execFileSync('git', ['commit', '-m', message], { maxBuffer:
|
|
45
|
+
execFileSync('git', ['add', '-A'], { maxBuffer: GIT_OUTPUT_LIMIT_BYTES });
|
|
46
|
+
execFileSync('git', ['commit', '-m', message], { maxBuffer: GIT_OUTPUT_LIMIT_BYTES });
|
|
47
47
|
console.info(`Created release commit: ${title}`);
|
|
48
48
|
}
|
package/dist/esm/createTags.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import { formatGlyphLine,
|
|
2
|
+
import { formatGlyphLine, GIT_OUTPUT_LIMIT_BYTES, hasErrnoCode } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { deleteFileIfExists } from "./deleteFileIfExists.js";
|
|
4
4
|
import { RELEASE_GLYPHS } from "./glyphs.js";
|
|
5
5
|
import { readReleaseTags, RELEASE_SUMMARY_FILE, RELEASE_TAGS_FILE } from "./releaseFiles.js";
|
|
@@ -22,7 +22,7 @@ export function createTags(options) {
|
|
|
22
22
|
const created = [];
|
|
23
23
|
for (const tag of tags) {
|
|
24
24
|
try {
|
|
25
|
-
execFileSync('git', ['tag', '-a', tag, '-m', tag], { maxBuffer:
|
|
25
|
+
execFileSync('git', ['tag', '-a', tag, '-m', tag], { maxBuffer: GIT_OUTPUT_LIMIT_BYTES });
|
|
26
26
|
created.push(tag);
|
|
27
27
|
}
|
|
28
28
|
catch (error) {
|
|
@@ -45,8 +45,8 @@ export function createTags(options) {
|
|
|
45
45
|
}
|
|
46
46
|
function assertCleanWorkingTree() {
|
|
47
47
|
try {
|
|
48
|
-
execFileSync('git', ['diff', '--quiet'], { maxBuffer:
|
|
49
|
-
execFileSync('git', ['diff', '--quiet', '--cached'], { maxBuffer:
|
|
48
|
+
execFileSync('git', ['diff', '--quiet'], { maxBuffer: GIT_OUTPUT_LIMIT_BYTES });
|
|
49
|
+
execFileSync('git', ['diff', '--quiet', '--cached'], { maxBuffer: GIT_OUTPUT_LIMIT_BYTES });
|
|
50
50
|
}
|
|
51
51
|
catch (error) {
|
|
52
52
|
if (hasErrnoCode(error, 'ENOENT')) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import {
|
|
2
|
+
import { GIT_OUTPUT_LIMIT_BYTES } from '@williamthorsen/nmr-core';
|
|
3
3
|
const EXAMPLE_TAG_LIMIT = 3;
|
|
4
4
|
const CANDIDATE_TAG_PATTERN = /^(?<prefix>[a-z][a-z0-9-]*-v)\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/;
|
|
5
5
|
export function detectUndeclaredTagPrefixes(knownPrefixes) {
|
|
@@ -8,7 +8,7 @@ export function detectUndeclaredTagPrefixes(knownPrefixes) {
|
|
|
8
8
|
try {
|
|
9
9
|
rawOutput = execFileSync('git', ['tag', '--list'], {
|
|
10
10
|
encoding: 'utf8',
|
|
11
|
-
maxBuffer:
|
|
11
|
+
maxBuffer: GIT_OUTPUT_LIMIT_BYTES,
|
|
12
12
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
13
13
|
});
|
|
14
14
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import {
|
|
2
|
+
import { GIT_OUTPUT_LIMIT_BYTES } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { chainError } from '@williamthorsen/toolbelt.errors/candidate';
|
|
4
4
|
import { matchesTagPrefix } from "./matchesTagPrefix.js";
|
|
5
5
|
const FIELD_SEPARATOR = '\u{1F}';
|
|
@@ -112,7 +112,7 @@ function runGit(args, description) {
|
|
|
112
112
|
try {
|
|
113
113
|
return execFileSync('git', args, {
|
|
114
114
|
encoding: 'utf8',
|
|
115
|
-
maxBuffer:
|
|
115
|
+
maxBuffer: GIT_OUTPUT_LIMIT_BYTES,
|
|
116
116
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
117
117
|
}).trim();
|
|
118
118
|
}
|
package/dist/esm/init/checks.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
|
-
import {
|
|
3
|
+
import { GIT_OUTPUT_LIMIT_BYTES } from '@williamthorsen/nmr-core';
|
|
4
4
|
import { parseJsonRecord } from "./parseJsonRecord.js";
|
|
5
5
|
export function isGitRepo() {
|
|
6
6
|
try {
|
|
7
|
-
execSync('git rev-parse --is-inside-work-tree', { maxBuffer:
|
|
7
|
+
execSync('git rev-parse --is-inside-work-tree', { maxBuffer: GIT_OUTPUT_LIMIT_BYTES, stdio: 'pipe' });
|
|
8
8
|
return { ok: true };
|
|
9
9
|
}
|
|
10
10
|
catch {
|
|
@@ -7,13 +7,22 @@ export function scaffoldFiles({ repoType, dryRun, overwrite, publishable, withCo
|
|
|
7
7
|
const results = [];
|
|
8
8
|
if (publishable) {
|
|
9
9
|
results.push(writeFileWithCheck(CREATE_GITHUB_RELEASE_WORKFLOW_PATH, createGithubReleaseWorkflow(repoType), {
|
|
10
|
-
dryRun,
|
|
11
|
-
overwrite,
|
|
12
|
-
}), writeFileWithCheck(PUBLISH_WORKFLOW_PATH, publishWorkflow(repoType), {
|
|
10
|
+
isDryRun: dryRun,
|
|
11
|
+
shouldOverwrite: overwrite,
|
|
12
|
+
}), writeFileWithCheck(PUBLISH_WORKFLOW_PATH, publishWorkflow(repoType), {
|
|
13
|
+
isDryRun: dryRun,
|
|
14
|
+
shouldOverwrite: overwrite,
|
|
15
|
+
}));
|
|
13
16
|
}
|
|
14
|
-
results.push(writeFileWithCheck('.github/workflows/release.yaml', releaseWorkflow(repoType), {
|
|
17
|
+
results.push(writeFileWithCheck('.github/workflows/release.yaml', releaseWorkflow(repoType), {
|
|
18
|
+
isDryRun: dryRun,
|
|
19
|
+
shouldOverwrite: overwrite,
|
|
20
|
+
}));
|
|
15
21
|
if (withConfig) {
|
|
16
|
-
results.push(writeFileWithCheck('.config/release-kit.config.ts', releaseConfigScript(repoType), {
|
|
22
|
+
results.push(writeFileWithCheck('.config/release-kit.config.ts', releaseConfigScript(repoType), {
|
|
23
|
+
isDryRun: dryRun,
|
|
24
|
+
shouldOverwrite: overwrite,
|
|
25
|
+
}));
|
|
17
26
|
}
|
|
18
27
|
return results;
|
|
19
28
|
}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
2
|
import { printError, printSkip, printStep, printSuccess, reportTemplateUpdate, updateManagedFile, } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
4
|
-
import {
|
|
4
|
+
import { readSyncLabelsWorkflowTemplate } from "../sync-labels/templates.js";
|
|
5
5
|
import { detectRepoType } from "./detectRepoType.js";
|
|
6
6
|
import { hasProvenance } from "./hasProvenance.js";
|
|
7
7
|
import { formatPrivateWorkflowSkip, hasPublishablePackage } from "./hasPublishablePackage.js";
|
|
@@ -40,7 +40,7 @@ export function updateTemplatesCommand({ dryRun, styles }) {
|
|
|
40
40
|
for (const filePath of skipped) {
|
|
41
41
|
printSkip(formatPrivateWorkflowSkip(filePath), styles.stdout);
|
|
42
42
|
}
|
|
43
|
-
results = files.map(([filePath, content]) => updateManagedFile(filePath, content, { dryRun }));
|
|
43
|
+
results = files.map(([filePath, content]) => updateManagedFile(filePath, content, { isDryRun: dryRun }));
|
|
44
44
|
}
|
|
45
45
|
catch (error) {
|
|
46
46
|
printError(`Failed to render workflows: ${describeError(error)}`, styles.stderr);
|
|
@@ -59,7 +59,7 @@ function buildManagedFiles(repoType, publishable) {
|
|
|
59
59
|
['.github/workflows/release.yaml', releaseWorkflow(repoType)],
|
|
60
60
|
];
|
|
61
61
|
if (existsSync(SYNC_LABELS_WORKFLOW_PATH)) {
|
|
62
|
-
files.push([SYNC_LABELS_WORKFLOW_PATH,
|
|
62
|
+
files.push([SYNC_LABELS_WORKFLOW_PATH, readSyncLabelsWorkflowTemplate()]);
|
|
63
63
|
}
|
|
64
64
|
return { files: files.filter(([filePath]) => !skipped.includes(filePath)), skipped };
|
|
65
65
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
2
|
import { basename } from 'node:path';
|
|
3
|
-
import {
|
|
3
|
+
import { GIT_OUTPUT_LIMIT_BYTES } from '@williamthorsen/nmr-core';
|
|
4
4
|
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
5
5
|
import { DEFAULT_PROJECT_TAG_PREFIX } from "./defaults.js";
|
|
6
6
|
import { deriveDirectoryConfig } from "./deriveDirectoryConfig.js";
|
|
@@ -91,7 +91,7 @@ function countTagsMatching(prefix) {
|
|
|
91
91
|
try {
|
|
92
92
|
const output = execFileSync('git', ['tag', '--list', `${prefix}*`], {
|
|
93
93
|
encoding: 'utf8',
|
|
94
|
-
maxBuffer:
|
|
94
|
+
maxBuffer: GIT_OUTPUT_LIMIT_BYTES,
|
|
95
95
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
96
96
|
});
|
|
97
97
|
return output.split('\n').filter((line) => matchesTagPrefix(line.trim(), [prefix])).length;
|
package/dist/esm/pushRelease.js
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import {
|
|
2
|
+
import { GIT_OUTPUT_LIMIT_BYTES } from '@williamthorsen/nmr-core';
|
|
3
3
|
export function pushRelease(resolvedTags, options = {}) {
|
|
4
4
|
const { dryRun = false, tagsOnly = false } = options;
|
|
5
5
|
const steps = [];
|
|
6
6
|
if (!tagsOnly) {
|
|
7
7
|
const branch = execFileSync('git', ['rev-parse', '--abbrev-ref', 'HEAD'], {
|
|
8
8
|
encoding: 'utf8',
|
|
9
|
-
maxBuffer:
|
|
9
|
+
maxBuffer: GIT_OUTPUT_LIMIT_BYTES,
|
|
10
10
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
11
11
|
}).trim();
|
|
12
12
|
const command = ['git', 'push', 'origin', branch];
|
package/dist/esm/releasePlan.js
CHANGED
|
@@ -26,7 +26,7 @@ function applyStep(step) {
|
|
|
26
26
|
return { outcome: 'failed', error: describeError(error) };
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
|
-
const result = writeFileWithCheck(step.path, step.content, {
|
|
29
|
+
const result = writeFileWithCheck(step.path, step.content, { isDryRun: false, shouldOverwrite: true });
|
|
30
30
|
if (result.outcome === 'failed') {
|
|
31
31
|
return { outcome: 'failed', ...(result.error !== undefined && { error: result.error }) };
|
|
32
32
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { execFileSync } from 'node:child_process';
|
|
2
|
-
import {
|
|
2
|
+
import { GIT_OUTPUT_LIMIT_BYTES } from '@williamthorsen/nmr-core';
|
|
3
3
|
import { getTargetName } from "./resolveReleaseDeclaration.js";
|
|
4
4
|
import { PROJECT_TARGET_ID } from "./resolveReleaseTargets.js";
|
|
5
5
|
const VERSION_PATTERN = /^v\d+\.\d+\.\d+/;
|
|
@@ -7,7 +7,7 @@ const SEMVER_SUFFIX_PATTERN = /^\d+\.\d+\.\d+/;
|
|
|
7
7
|
export function resolveReleaseTags(args) {
|
|
8
8
|
const output = execFileSync('git', ['tag', '--points-at', 'HEAD'], {
|
|
9
9
|
encoding: 'utf8',
|
|
10
|
-
maxBuffer:
|
|
10
|
+
maxBuffer: GIT_OUTPUT_LIMIT_BYTES,
|
|
11
11
|
});
|
|
12
12
|
const tags = output
|
|
13
13
|
.split('\n')
|
|
@@ -6,7 +6,7 @@ import { CONFIG_FILE_PATH } from "../loadConfig.js";
|
|
|
6
6
|
import { loadValidatedConfig, reportConfigProblem } from "../loadValidatedConfig.js";
|
|
7
7
|
import { generateCommand, LABELS_OUTPUT_PATH } from "./generateCommand.js";
|
|
8
8
|
import { checkRetiredSyncLabelsConfig } from "./retiredConfig.js";
|
|
9
|
-
import { buildScopeLabels, renderRepoLabelsBlock, repoLabelsConfigScript,
|
|
9
|
+
import { buildScopeLabels, readSyncLabelsWorkflowTemplate, renderRepoLabelsBlock, repoLabelsConfigScript, } from "./templates.js";
|
|
10
10
|
const WORKFLOW_PATH = '.github/workflows/sync-labels.yaml';
|
|
11
11
|
export async function syncLabelsInitCommand({ configPath, dryRun, force, styles }) {
|
|
12
12
|
const configFilePath = configPath ?? CONFIG_FILE_PATH;
|
|
@@ -43,7 +43,15 @@ export async function syncLabelsInitCommand({ configPath, dryRun, force, styles
|
|
|
43
43
|
}
|
|
44
44
|
const scopeLabels = workspace.kind === 'single-package' ? [] : buildScopeLabels(workspace.packageDirs, retiredNames);
|
|
45
45
|
console.info('\n> Scaffolding files');
|
|
46
|
-
|
|
46
|
+
let workflow;
|
|
47
|
+
try {
|
|
48
|
+
workflow = readSyncLabelsWorkflowTemplate();
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
process.stderr.write(` ${describeError(error)}\n`);
|
|
52
|
+
return 1;
|
|
53
|
+
}
|
|
54
|
+
const workflowResult = writeFileWithCheck(WORKFLOW_PATH, workflow, { isDryRun: dryRun, shouldOverwrite: force });
|
|
47
55
|
reportWriteResult(workflowResult, dryRun, styles);
|
|
48
56
|
if (configExists) {
|
|
49
57
|
console.info(`\n> ${configFilePath} already exists; add this block to the object passed to defineConfig:\n`);
|
|
@@ -62,8 +70,8 @@ export async function syncLabelsInitCommand({ configPath, dryRun, force, styles
|
|
|
62
70
|
return 0;
|
|
63
71
|
}
|
|
64
72
|
const configResult = writeFileWithCheck(CONFIG_FILE_PATH, repoLabelsConfigScript(scopeLabels), {
|
|
65
|
-
dryRun,
|
|
66
|
-
|
|
73
|
+
isDryRun: dryRun,
|
|
74
|
+
shouldOverwrite: force,
|
|
67
75
|
});
|
|
68
76
|
reportWriteResult(configResult, dryRun, styles);
|
|
69
77
|
if (workflowResult.outcome === 'failed' || configResult.outcome === 'failed') {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
import { execSync } from 'node:child_process';
|
|
2
2
|
import { existsSync } from 'node:fs';
|
|
3
|
-
import {
|
|
3
|
+
import { GIT_OUTPUT_LIMIT_BYTES, reportError } from '@williamthorsen/nmr-core';
|
|
4
4
|
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
5
5
|
import { checkRetiredSyncLabelsConfig } from "./retiredConfig.js";
|
|
6
6
|
const WORKFLOW_FILE = '.github/workflows/sync-labels.yaml';
|
|
7
7
|
function checkGhAvailable() {
|
|
8
8
|
try {
|
|
9
|
-
execSync('gh --version', { maxBuffer:
|
|
9
|
+
execSync('gh --version', { maxBuffer: GIT_OUTPUT_LIMIT_BYTES, stdio: 'pipe' });
|
|
10
10
|
return true;
|
|
11
11
|
}
|
|
12
12
|
catch {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { LabelDefinition } from './types.js';
|
|
2
|
-
/**
|
|
3
|
-
export declare function
|
|
2
|
+
/** Reads the bundled caller workflow for `sync-labels`. Throws if the template cannot be read. */
|
|
3
|
+
export declare function readSyncLabelsWorkflowTemplate(): string;
|
|
4
4
|
/**
|
|
5
5
|
* Generates scope labels from workspace paths and retired-package names.
|
|
6
6
|
*
|
|
@@ -1,42 +1,15 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
# Preview on review: The check's log has the computed diff, and the check warns about each label not declared by the file.
|
|
15
|
-
pull_request:
|
|
16
|
-
paths:
|
|
17
|
-
- .github/labels.yaml
|
|
18
|
-
|
|
19
|
-
# Permissions are fixed when a run is created and cannot vary by trigger within a job,
|
|
20
|
-
# so applying and previewing are separate jobs.
|
|
21
|
-
jobs:
|
|
22
|
-
# The push arm applies on the default branch alone. The job's \`if:\` names that branch through the event payload,
|
|
23
|
-
# which keeps this file identical across repos; a \`branches:\` filter would have to name it literally.
|
|
24
|
-
sync:
|
|
25
|
-
if: github.event_name != 'pull_request' && (github.event_name != 'push' || github.ref_name == github.event.repository.default_branch)
|
|
26
|
-
permissions:
|
|
27
|
-
contents: read
|
|
28
|
-
issues: write
|
|
29
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/sync-labels.reusable.yaml@workflow/sync-labels-v1
|
|
30
|
-
|
|
31
|
-
check:
|
|
32
|
-
if: github.event_name == 'pull_request'
|
|
33
|
-
permissions:
|
|
34
|
-
contents: read
|
|
35
|
-
issues: read
|
|
36
|
-
uses: williamthorsen/node-monorepo-tools/.github/workflows/sync-labels.reusable.yaml@workflow/sync-labels-v1
|
|
37
|
-
with:
|
|
38
|
-
dry-run: true
|
|
39
|
-
`;
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { basename, resolve } from 'node:path';
|
|
3
|
+
import { findPackageRoot } from '@williamthorsen/nmr-core';
|
|
4
|
+
import { describeError } from '@williamthorsen/toolbelt.errors';
|
|
5
|
+
export function readSyncLabelsWorkflowTemplate() {
|
|
6
|
+
const templatePath = resolve(findPackageRoot(import.meta.url), 'templates', 'sync-labels.yaml.template');
|
|
7
|
+
try {
|
|
8
|
+
return readFileSync(templatePath, 'utf8');
|
|
9
|
+
}
|
|
10
|
+
catch (error) {
|
|
11
|
+
throw new Error(`Failed to read bundled template at ${templatePath}: ${describeError(error)}`, { cause: error });
|
|
12
|
+
}
|
|
40
13
|
}
|
|
41
14
|
export function buildScopeLabels(workspacePaths, retiredNames = []) {
|
|
42
15
|
const scopes = ['root', ...workspacePaths.map((workspacePath) => basename(workspacePath)), ...retiredNames];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@williamthorsen/release-kit",
|
|
3
|
-
"version": "15.0.
|
|
3
|
+
"version": "15.0.3",
|
|
4
4
|
"description": "Version-bumping and changelog-generation toolkit for release workflows",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"changelog",
|
|
@@ -47,12 +47,13 @@
|
|
|
47
47
|
"docs",
|
|
48
48
|
"!docs/*.v*.md",
|
|
49
49
|
"presets/**",
|
|
50
|
-
"schemas/**"
|
|
50
|
+
"schemas/**",
|
|
51
|
+
"templates"
|
|
51
52
|
],
|
|
52
53
|
"dependencies": {
|
|
53
54
|
"@williamthorsen/change-grammar": "0.3.0",
|
|
54
|
-
"@williamthorsen/nmr-core": "0.
|
|
55
|
-
"@williamthorsen/toolbelt.errors": "0.
|
|
55
|
+
"@williamthorsen/nmr-core": "0.14.0",
|
|
56
|
+
"@williamthorsen/toolbelt.errors": "0.9.0",
|
|
56
57
|
"json-stringify-pretty-compact": "4.0.0",
|
|
57
58
|
"semver": "7.8.5",
|
|
58
59
|
"yaml": "2.9.1",
|
|
@@ -60,12 +61,12 @@
|
|
|
60
61
|
},
|
|
61
62
|
"devDependencies": {
|
|
62
63
|
"@types/semver": "7.8.0",
|
|
63
|
-
"@williamthorsen/toolbelt.filesystem": "0.
|
|
64
|
-
"@williamthorsen/toolbelt.testing": "0.
|
|
65
|
-
"@williamthorsen/toolbelt.vitest": "0.
|
|
64
|
+
"@williamthorsen/toolbelt.filesystem": "0.10.0",
|
|
65
|
+
"@williamthorsen/toolbelt.testing": "0.8.0",
|
|
66
|
+
"@williamthorsen/toolbelt.vitest": "0.13.0",
|
|
66
67
|
"actionlint": "2.0.6",
|
|
67
68
|
"esbuild": "0.28.2",
|
|
68
|
-
"readyup": "0.
|
|
69
|
+
"readyup": "0.44.0",
|
|
69
70
|
"smol-toml": "1.9.1",
|
|
70
71
|
"vitest": "5.0.5"
|
|
71
72
|
},
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
|
|
2
|
+
name: Sync labels
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
|
|
7
|
+
# Apply on merge, so that the repository's labels match each merged version of the labels file.
|
|
8
|
+
push:
|
|
9
|
+
paths:
|
|
10
|
+
- .github/labels.yaml
|
|
11
|
+
|
|
12
|
+
# Preview on review: The check's log has the computed diff, and the check warns about each label not declared by the file.
|
|
13
|
+
pull_request:
|
|
14
|
+
paths:
|
|
15
|
+
- .github/labels.yaml
|
|
16
|
+
|
|
17
|
+
# Permissions are fixed when a run is created and cannot vary by trigger within a job,
|
|
18
|
+
# so applying and previewing are separate jobs.
|
|
19
|
+
jobs:
|
|
20
|
+
# The push arm applies on the default branch alone. The job's `if:` names that branch through the event payload,
|
|
21
|
+
# which keeps this file identical across repos; a `branches:` filter would have to name it literally.
|
|
22
|
+
sync:
|
|
23
|
+
if: github.event_name != 'pull_request' && (github.event_name != 'push' || github.ref_name == github.event.repository.default_branch)
|
|
24
|
+
permissions:
|
|
25
|
+
contents: read
|
|
26
|
+
issues: write
|
|
27
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/sync-labels.reusable.yaml@workflow/sync-labels-v1
|
|
28
|
+
|
|
29
|
+
check:
|
|
30
|
+
if: github.event_name == 'pull_request'
|
|
31
|
+
permissions:
|
|
32
|
+
contents: read
|
|
33
|
+
issues: read
|
|
34
|
+
uses: williamthorsen/node-monorepo-tools/.github/workflows/sync-labels.reusable.yaml@workflow/sync-labels-v1
|
|
35
|
+
with:
|
|
36
|
+
dry-run: true
|