@williamthorsen/release-kit 2.1.0 → 2.3.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.
Files changed (68) hide show
  1. package/CHANGELOG.md +110 -0
  2. package/README.md +1 -11
  3. package/bin/release-kit.js +2 -0
  4. package/dist/esm/.cache +1 -1
  5. package/dist/esm/bin/release-kit.js +148 -0
  6. package/dist/esm/bumpAllVersions.d.ts +2 -2
  7. package/dist/esm/bumpAllVersions.js +1 -4
  8. package/dist/esm/component.d.ts +1 -1
  9. package/dist/esm/component.js +2 -3
  10. package/dist/esm/createTags.d.ts +5 -0
  11. package/dist/esm/createTags.js +73 -0
  12. package/dist/esm/detectPackageManager.d.ts +2 -0
  13. package/dist/esm/detectPackageManager.js +44 -0
  14. package/dist/esm/findPackageRoot.d.ts +1 -0
  15. package/dist/esm/findPackageRoot.js +17 -0
  16. package/dist/esm/format.d.ts +3 -0
  17. package/dist/esm/format.js +14 -0
  18. package/dist/esm/generateChangelogs.d.ts +2 -2
  19. package/dist/esm/generateChangelogs.js +12 -12
  20. package/dist/esm/hasPrettierConfig.d.ts +1 -0
  21. package/dist/esm/hasPrettierConfig.js +42 -0
  22. package/dist/esm/index.d.ts +12 -2
  23. package/dist/esm/index.js +11 -2
  24. package/dist/esm/init/initCommand.js +9 -2
  25. package/dist/esm/init/scaffold.d.ts +3 -2
  26. package/dist/esm/init/scaffold.js +18 -44
  27. package/dist/esm/init/templates.js +14 -4
  28. package/dist/esm/loadConfig.js +0 -6
  29. package/dist/esm/prepareCommand.d.ts +10 -0
  30. package/dist/esm/prepareCommand.js +96 -20
  31. package/dist/esm/publish.d.ts +7 -0
  32. package/dist/esm/publish.js +49 -0
  33. package/dist/esm/publishCommand.d.ts +1 -0
  34. package/dist/esm/publishCommand.js +54 -0
  35. package/dist/esm/releasePrepare.d.ts +2 -2
  36. package/dist/esm/releasePrepare.js +46 -17
  37. package/dist/esm/releasePrepareMono.d.ts +2 -2
  38. package/dist/esm/releasePrepareMono.js +54 -24
  39. package/dist/esm/reportPrepare.d.ts +2 -0
  40. package/dist/esm/reportPrepare.js +120 -0
  41. package/dist/esm/resolveCliffConfigPath.js +4 -4
  42. package/dist/esm/resolveReleaseTags.d.ts +6 -0
  43. package/dist/esm/resolveReleaseTags.js +42 -0
  44. package/dist/esm/runReleasePrepare.js +3 -2
  45. package/dist/esm/sync-labels/generateCommand.d.ts +4 -0
  46. package/dist/esm/sync-labels/generateCommand.js +51 -0
  47. package/dist/esm/sync-labels/initCommand.d.ts +6 -0
  48. package/dist/esm/sync-labels/initCommand.js +62 -0
  49. package/dist/esm/sync-labels/loadSyncLabelsConfig.d.ts +3 -0
  50. package/dist/esm/sync-labels/loadSyncLabelsConfig.js +59 -0
  51. package/dist/esm/sync-labels/presets.d.ts +2 -0
  52. package/dist/esm/sync-labels/presets.js +40 -0
  53. package/dist/esm/sync-labels/resolveLabels.d.ts +2 -0
  54. package/dist/esm/sync-labels/resolveLabels.js +43 -0
  55. package/dist/esm/sync-labels/scaffold.d.ts +6 -0
  56. package/dist/esm/sync-labels/scaffold.js +25 -0
  57. package/dist/esm/sync-labels/syncCommand.d.ts +1 -0
  58. package/dist/esm/sync-labels/syncCommand.js +33 -0
  59. package/dist/esm/sync-labels/templates.d.ts +4 -0
  60. package/dist/esm/sync-labels/templates.js +50 -0
  61. package/dist/esm/sync-labels/types.d.ts +9 -0
  62. package/dist/esm/sync-labels/types.js +0 -0
  63. package/dist/esm/tagCommand.d.ts +1 -0
  64. package/dist/esm/tagCommand.js +20 -0
  65. package/dist/esm/types.d.ts +29 -1
  66. package/dist/esm/validateConfig.js +11 -6
  67. package/package.json +12 -5
  68. package/presets/labels/common.yaml +52 -0
@@ -0,0 +1,33 @@
1
+ import { execSync } from "node:child_process";
2
+ import { existsSync } from "node:fs";
3
+ const WORKFLOW_FILE = ".github/workflows/sync-labels.yaml";
4
+ function checkGhAvailable() {
5
+ try {
6
+ execSync("gh --version", { stdio: "pipe" });
7
+ return true;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ function syncLabelsCommand() {
13
+ if (!checkGhAvailable()) {
14
+ console.error("Error: The `gh` CLI is not installed or not in PATH. Install it from https://cli.github.com/");
15
+ return 1;
16
+ }
17
+ if (!existsSync(WORKFLOW_FILE)) {
18
+ console.error(`Error: ${WORKFLOW_FILE} not found. Run \`release-kit sync-labels init\` first.`);
19
+ return 1;
20
+ }
21
+ try {
22
+ execSync("gh workflow run sync-labels.yaml", { stdio: "inherit" });
23
+ } catch (error) {
24
+ const message = error instanceof Error ? error.message : String(error);
25
+ console.error(`Error triggering workflow: ${message}`);
26
+ return 1;
27
+ }
28
+ console.info("Workflow triggered successfully. View runs at: gh run list --workflow=sync-labels.yaml");
29
+ return 0;
30
+ }
31
+ export {
32
+ syncLabelsCommand
33
+ };
@@ -0,0 +1,4 @@
1
+ import type { LabelDefinition } from './types.ts';
2
+ export declare function syncLabelsWorkflow(): string;
3
+ export declare function buildScopeLabels(workspacePaths: string[]): LabelDefinition[];
4
+ export declare function syncLabelsConfigScript(scopeLabels: LabelDefinition[]): string;
@@ -0,0 +1,50 @@
1
+ import { basename } from "node:path";
2
+ function syncLabelsWorkflow() {
3
+ return `# yaml-language-server: $schema=https://json.schemastore.org/github-workflow.json
4
+ name: Sync labels
5
+
6
+ on:
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ sync:
11
+ uses: williamthorsen/node-monorepo-tools/.github/workflows/sync-labels.yaml@sync-labels-v1
12
+ `;
13
+ }
14
+ function buildScopeLabels(workspacePaths) {
15
+ const labels = [
16
+ { name: "scope:root", color: "00ff96", description: "Monorepo root configuration" }
17
+ ];
18
+ for (const workspacePath of workspacePaths) {
19
+ const name = basename(workspacePath);
20
+ labels.push({ name: `scope:${name}`, color: "00ff96", description: `${name} package` });
21
+ }
22
+ return labels;
23
+ }
24
+ function escapeForSingleQuotedString(value) {
25
+ return value.replace(/\\/g, "\\\\").replace(/'/g, String.raw`\'`);
26
+ }
27
+ function syncLabelsConfigScript(scopeLabels) {
28
+ const labelsArray = scopeLabels.map((label) => {
29
+ const name = escapeForSingleQuotedString(label.name);
30
+ const color = escapeForSingleQuotedString(label.color);
31
+ const description = escapeForSingleQuotedString(label.description);
32
+ return ` { name: '${name}', color: '${color}', description: '${description}' },`;
33
+ }).join("\n");
34
+ return `import type { SyncLabelsConfig } from '@williamthorsen/release-kit';
35
+
36
+ const config: SyncLabelsConfig = {
37
+ presets: ['common'],
38
+ labels: [
39
+ ${labelsArray}
40
+ ],
41
+ };
42
+
43
+ export default config;
44
+ `;
45
+ }
46
+ export {
47
+ buildScopeLabels,
48
+ syncLabelsConfigScript,
49
+ syncLabelsWorkflow
50
+ };
@@ -0,0 +1,9 @@
1
+ export interface LabelDefinition {
2
+ name: string;
3
+ color: string;
4
+ description: string;
5
+ }
6
+ export interface SyncLabelsConfig {
7
+ presets?: string[];
8
+ labels?: LabelDefinition[];
9
+ }
File without changes
@@ -0,0 +1 @@
1
+ export declare function tagCommand(argv: string[]): void;
@@ -0,0 +1,20 @@
1
+ import { createTags } from "./createTags.js";
2
+ function tagCommand(argv) {
3
+ const knownFlags = /* @__PURE__ */ new Set(["--dry-run", "--no-git-checks"]);
4
+ const unknownFlags = argv.filter((f) => !knownFlags.has(f));
5
+ if (unknownFlags.length > 0) {
6
+ console.error(`Error: Unknown option: ${unknownFlags[0]}`);
7
+ process.exit(1);
8
+ }
9
+ const dryRun = argv.includes("--dry-run");
10
+ const noGitChecks = argv.includes("--no-git-checks");
11
+ try {
12
+ createTags({ dryRun, noGitChecks });
13
+ } catch (error) {
14
+ console.error(error instanceof Error ? error.message : String(error));
15
+ process.exit(1);
16
+ }
17
+ }
18
+ export {
19
+ tagCommand
20
+ };
@@ -1,4 +1,33 @@
1
1
  export type ReleaseType = 'major' | 'minor' | 'patch';
2
+ export interface BumpResult {
3
+ currentVersion: string;
4
+ newVersion: string;
5
+ files: string[];
6
+ }
7
+ export interface ComponentPrepareResult {
8
+ name?: string | undefined;
9
+ status: 'released' | 'skipped';
10
+ previousTag?: string | undefined;
11
+ commitCount: number;
12
+ parsedCommitCount?: number | undefined;
13
+ releaseType?: ReleaseType | undefined;
14
+ currentVersion?: string | undefined;
15
+ newVersion?: string | undefined;
16
+ tag?: string | undefined;
17
+ bumpedFiles: string[];
18
+ changelogFiles: string[];
19
+ skipReason?: string | undefined;
20
+ }
21
+ export interface PrepareResult {
22
+ components: ComponentPrepareResult[];
23
+ tags: string[];
24
+ formatCommand?: {
25
+ command: string;
26
+ executed: boolean;
27
+ files: string[];
28
+ } | undefined;
29
+ dryRun: boolean;
30
+ }
2
31
  export interface WorkTypeConfig {
3
32
  header: string;
4
33
  aliases?: string[];
@@ -17,7 +46,6 @@ export interface ReleaseKitConfig {
17
46
  }
18
47
  export interface ComponentOverride {
19
48
  dir: string;
20
- tagPrefix?: string;
21
49
  shouldExclude?: boolean;
22
50
  }
23
51
  export interface Commit {
@@ -36,6 +36,7 @@ function validateComponents(value, config, errors) {
36
36
  return;
37
37
  }
38
38
  const components = [];
39
+ const knownComponentFields = /* @__PURE__ */ new Set(["dir", "shouldExclude"]);
39
40
  for (const [i, entry] of value.entries()) {
40
41
  if (!isRecord(entry)) {
41
42
  errors.push(`components[${i}]: must be an object`);
@@ -45,14 +46,18 @@ function validateComponents(value, config, errors) {
45
46
  errors.push(`components[${i}]: 'dir' is required`);
46
47
  continue;
47
48
  }
48
- const component = { dir: entry.dir };
49
- if (entry.tagPrefix !== void 0) {
50
- if (typeof entry.tagPrefix === "string") {
51
- component.tagPrefix = entry.tagPrefix;
52
- } else {
53
- errors.push(`components[${i}]: 'tagPrefix' must be a string`);
49
+ for (const key of Object.keys(entry)) {
50
+ if (!knownComponentFields.has(key)) {
51
+ if (key === "tagPrefix") {
52
+ errors.push(
53
+ `components[${i}]: 'tagPrefix' is no longer supported; remove it to use the default '${entry.dir}-v'`
54
+ );
55
+ } else {
56
+ errors.push(`components[${i}]: unknown field '${key}'`);
57
+ }
54
58
  }
55
59
  }
60
+ const component = { dir: entry.dir };
56
61
  if (entry.shouldExclude !== void 0) {
57
62
  if (typeof entry.shouldExclude === "boolean") {
58
63
  component.shouldExclude = entry.shouldExclude;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@williamthorsen/release-kit",
3
- "version": "2.1.0",
3
+ "version": "2.3.0",
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",
@@ -21,20 +21,24 @@
21
21
  }
22
22
  },
23
23
  "bin": {
24
- "release-kit": "./dist/esm/bin/release-kit.js"
24
+ "release-kit": "./bin/release-kit.js"
25
25
  },
26
26
  "files": [
27
+ "bin",
27
28
  "dist/*",
28
29
  "cliff.toml.template",
30
+ "presets/**",
29
31
  "CHANGELOG.md"
30
32
  ],
31
33
  "dependencies": {
32
34
  "glob": "13.0.6",
33
35
  "jiti": "2.6.1",
34
- "js-yaml": "4.1.1"
36
+ "js-yaml": "4.1.1",
37
+ "@williamthorsen/node-monorepo-core": "0.2.0"
35
38
  },
36
39
  "devDependencies": {
37
- "@types/js-yaml": "4.0.9"
40
+ "@types/js-yaml": "4.0.9",
41
+ "smol-toml": "1.6.1"
38
42
  },
39
43
  "engines": {
40
44
  "node": ">=18.17.0"
@@ -44,6 +48,9 @@
44
48
  "registry": "https://registry.npmjs.org"
45
49
  },
46
50
  "scripts": {
47
- "ws": "node --import tsx ../../scripts/run-workspace-script.ts --int-test"
51
+ "test": "pnpm exec vitest --config=vitest.standalone.config.ts",
52
+ "test:coverage": "pnpm exec vitest --config=vitest.standalone.config.ts --coverage",
53
+ "test:integration": "pnpm exec vitest --config=vitest.integration.config.ts",
54
+ "test:watch": "pnpm exec vitest --config=vitest.standalone.config.ts --watch"
48
55
  }
49
56
  }
@@ -0,0 +1,52 @@
1
+ # Common label definitions for GitHub repositories.
2
+ # Compatible with EndBug/label-sync format.
3
+
4
+ # Main categories
5
+ - name: breaking
6
+ color: b60205
7
+ description: Breaking API change or removal of functionality
8
+ - name: bug
9
+ color: d73a4a
10
+ description: "Something isn't working"
11
+ - name: documentation
12
+ color: a2eeef
13
+ description: Improvements or additions to documentation
14
+ - name: feature
15
+ color: '0075ca'
16
+ description: Added or improved external functionality
17
+
18
+ # Guidance
19
+ - name: good first issue
20
+ color: 90ee90
21
+ description: Good for newcomers
22
+ - name: help wanted
23
+ color: '008672'
24
+ description: Please help if you can
25
+ - name: question
26
+ color: fbca04
27
+ description: Further information is needed
28
+
29
+ # Refactoring
30
+ - name: dependencies
31
+ color: edc287
32
+ description: Change to dependencies
33
+ - name: refactoring
34
+ color: edc287
35
+ description: Improvement to code without change in functionality
36
+ - name: tests
37
+ color: edc287
38
+ description: Tests
39
+ - name: tooling
40
+ color: edc287
41
+ description: Development tools
42
+ - name: utility
43
+ color: 1d76db
44
+ description: Changed internal functionality
45
+
46
+ # Triage
47
+ - name: duplicate
48
+ color: cfd3d7
49
+ description: Duplicates another issue or pull request
50
+ - name: wontfix
51
+ color: ffffff
52
+ description: This will not be worked on