@releasekit/release 0.7.48 → 0.8.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/README.md +68 -0
- package/dist/cli.js +296 -41
- package/dist/dispatcher.js +297 -42
- package/dist/index.js +47244 -0
- package/package.json +6 -6
package/README.md
CHANGED
|
@@ -223,6 +223,13 @@ The `ci` section controls automation behavior:
|
|
|
223
223
|
"major": "release:major",
|
|
224
224
|
"minor": "release:minor",
|
|
225
225
|
"patch": "release:patch"
|
|
226
|
+
},
|
|
227
|
+
|
|
228
|
+
// Map PR labels to package filters for scoped releases
|
|
229
|
+
// Example: a PR with "scope:shared" label only releases matching packages
|
|
230
|
+
"scopeLabels": {
|
|
231
|
+
"scope:shared": "@myorg/shared-*",
|
|
232
|
+
"scope:frontend": "@myorg/web-*"
|
|
226
233
|
}
|
|
227
234
|
}
|
|
228
235
|
}
|
|
@@ -245,6 +252,67 @@ Both modes support `release:stable` and `release:prerelease` as modifiers.
|
|
|
245
252
|
| `standing-pr` | Changes accumulate in a standing release PR *(planned)* |
|
|
246
253
|
| `scheduled` | Releases are triggered on a schedule *(planned)* |
|
|
247
254
|
|
|
255
|
+
#### Scope-Based Release
|
|
256
|
+
|
|
257
|
+
Use `scopeLabels` to filter which packages are released based on PR labels. This is useful for monorepos with distinct package groups.
|
|
258
|
+
|
|
259
|
+
When a PR has a matching scope label, only packages matching the pattern are included in the release:
|
|
260
|
+
|
|
261
|
+
```json
|
|
262
|
+
{
|
|
263
|
+
"ci": {
|
|
264
|
+
"scopeLabels": {
|
|
265
|
+
"scope:shared": "@myorg/shared-*",
|
|
266
|
+
"scope:ui": "@myorg/ui-*"
|
|
267
|
+
},
|
|
268
|
+
"defaultScope": "scope:shared"
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
```
|
|
272
|
+
|
|
273
|
+
**Options:**
|
|
274
|
+
|
|
275
|
+
| Option | Description |
|
|
276
|
+
|--------|-------------|
|
|
277
|
+
| `scopeLabels` | Map of PR label names to package patterns |
|
|
278
|
+
| `defaultScope` | Fallback scope to use when no scope label is found (must reference a key in `scopeLabels`) |
|
|
279
|
+
|
|
280
|
+
**Usage:**
|
|
281
|
+
- `scope:shared` + `release:minor` → Release only `@myorg/shared-*` packages with minor bump
|
|
282
|
+
- `scope:shared` + `scope:ui` → Release both matching scope groups
|
|
283
|
+
- `scope:shared` (no release label) → Release only shared packages, bump determined by conventional commits
|
|
284
|
+
- No scope label but `defaultScope` configured → Use default scope pattern
|
|
285
|
+
|
|
286
|
+
Multiple scope labels are combined with OR logic. Without a `release:*` label, conventional commits determine the version bump.
|
|
287
|
+
|
|
288
|
+
**Label conflicts:**
|
|
289
|
+
|
|
290
|
+
In label trigger mode, conflicting labels will block the release and post a comment explaining the issue:
|
|
291
|
+
- Multiple bump labels (`release:major` + `release:minor` + `release:patch`) → blocked
|
|
292
|
+
- Conflicting release type (`release:stable` + `release:prerelease`) → blocked (both modes)
|
|
293
|
+
|
|
294
|
+
**How it works:**
|
|
295
|
+
|
|
296
|
+
- **Preview mode**: Reads labels directly from the PR
|
|
297
|
+
- **Release mode**: When triggered via `workflow_run` after a PR merge, releasekit finds the merged PR(s) for the HEAD commit and reads their labels automatically
|
|
298
|
+
|
|
299
|
+
**Example workflow configuration:**
|
|
300
|
+
|
|
301
|
+
```yaml
|
|
302
|
+
# Specify a fallback target - scope labels will filter to specific packages when found
|
|
303
|
+
jobs:
|
|
304
|
+
release:
|
|
305
|
+
runs-on: ubuntu-latest
|
|
306
|
+
steps:
|
|
307
|
+
- uses: goosewobbler/releasekit@v1
|
|
308
|
+
with:
|
|
309
|
+
mode: release
|
|
310
|
+
# Fallback target - used when no scope label is found
|
|
311
|
+
target: "@myorg/shared-*,@myorg/ui-*,@myorg/api-*"
|
|
312
|
+
```
|
|
313
|
+
|
|
314
|
+
With this setup, releasekit will use the specified packages as fallback. When a PR has a scope label, it will be used instead to filter to just those packages.
|
|
315
|
+
|
|
248
316
|
### PR Preview
|
|
249
317
|
|
|
250
318
|
The `releasekit preview` command posts a comment on pull requests showing what would be released. It reads PR labels from GitHub and adapts its messaging based on `releaseStrategy` and `releaseTrigger`.
|
package/dist/cli.js
CHANGED
|
@@ -14508,7 +14508,7 @@ var init_baseError_DQHIJACF = __esm({
|
|
|
14508
14508
|
}
|
|
14509
14509
|
});
|
|
14510
14510
|
|
|
14511
|
-
// ../version/dist/chunk-
|
|
14511
|
+
// ../version/dist/chunk-GHCENMVA.js
|
|
14512
14512
|
import * as fs9 from "fs";
|
|
14513
14513
|
import * as path12 from "path";
|
|
14514
14514
|
import * as TOML2 from "smol-toml";
|
|
@@ -16297,8 +16297,8 @@ function createVersionCommand() {
|
|
|
16297
16297
|
});
|
|
16298
16298
|
}
|
|
16299
16299
|
var import_semver3, import_semver4, import_semver5, ConfigError2, MAX_JSONC_LENGTH2, GitConfigSchema2, MonorepoConfigSchema2, BranchPatternSchema2, VersionCargoConfigSchema2, VersionConfigSchema2, NpmConfigSchema2, CargoPublishConfigSchema2, PublishGitConfigSchema2, GitHubReleaseConfigSchema2, VerifyRegistryConfigSchema2, VerifyConfigSchema2, PublishConfigSchema2, TemplateConfigSchema2, LocationModeSchema2, ChangelogConfigSchema2, LLMOptionsSchema2, LLMRetryConfigSchema2, LLMTasksConfigSchema2, LLMCategorySchema2, ScopeRulesSchema2, ScopeConfigSchema2, LLMPromptOverridesSchema2, LLMPromptsConfigSchema2, LLMConfigSchema2, ReleaseNotesConfigSchema2, NotesInputConfigSchema2, NotesConfigSchema2, CILabelsConfigSchema2, CIConfigSchema2, ReleaseCIConfigSchema2, ReleaseConfigSchema2, ReleaseKitConfigSchema2, MAX_INPUT_LENGTH2, SOLE_REFERENCE_PATTERN2, AUTH_DIR2, AUTH_FILE2, CONFIG_FILE2, VersionError, VersionErrorCode, _jsonOutputMode, _pendingWrites, _jsonData, STANDARD_BUMP_TYPES, VersionMismatchError, CONVENTIONAL_COMMIT_REGEX, BREAKING_CHANGE_REGEX, PackageProcessor, GitError, VersionEngine;
|
|
16300
|
-
var
|
|
16301
|
-
"../version/dist/chunk-
|
|
16300
|
+
var init_chunk_GHCENMVA = __esm({
|
|
16301
|
+
"../version/dist/chunk-GHCENMVA.js"() {
|
|
16302
16302
|
"use strict";
|
|
16303
16303
|
init_chunk_Q3FHZORY();
|
|
16304
16304
|
init_chunk_LMPZV35Z();
|
|
@@ -16584,7 +16584,18 @@ var init_chunk_UBCKZYTO = __esm({
|
|
|
16584
16584
|
major: "release:major",
|
|
16585
16585
|
minor: "release:minor",
|
|
16586
16586
|
patch: "release:patch"
|
|
16587
|
-
})
|
|
16587
|
+
}),
|
|
16588
|
+
/**
|
|
16589
|
+
* Map of scope labels to package patterns.
|
|
16590
|
+
* When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
|
|
16591
|
+
*/
|
|
16592
|
+
scopeLabels: z3.record(z3.string(), z3.string()).optional(),
|
|
16593
|
+
/**
|
|
16594
|
+
* Default scope to use when no scope label is found on the merged PR.
|
|
16595
|
+
* Must reference a key from scopeLabels (e.g., "scope:shared").
|
|
16596
|
+
* Only applies when scopeLabels is configured.
|
|
16597
|
+
*/
|
|
16598
|
+
defaultScope: z3.string().optional()
|
|
16588
16599
|
});
|
|
16589
16600
|
ReleaseCIConfigSchema2 = z3.object({
|
|
16590
16601
|
skipPatterns: z3.array(z3.string().min(1)).optional(),
|
|
@@ -17039,7 +17050,7 @@ __export(dist_exports3, {
|
|
|
17039
17050
|
var init_dist13 = __esm({
|
|
17040
17051
|
"../version/dist/index.js"() {
|
|
17041
17052
|
"use strict";
|
|
17042
|
-
|
|
17053
|
+
init_chunk_GHCENMVA();
|
|
17043
17054
|
init_chunk_Q3FHZORY();
|
|
17044
17055
|
init_chunk_LMPZV35Z();
|
|
17045
17056
|
}
|
|
@@ -41918,7 +41929,7 @@ var init_aggregator_IUQUAVJC = __esm({
|
|
|
41918
41929
|
}
|
|
41919
41930
|
});
|
|
41920
41931
|
|
|
41921
|
-
// ../notes/dist/chunk-
|
|
41932
|
+
// ../notes/dist/chunk-5B2RYLOK.js
|
|
41922
41933
|
import * as TOML3 from "smol-toml";
|
|
41923
41934
|
import * as fs33 from "fs";
|
|
41924
41935
|
import * as path33 from "path";
|
|
@@ -43250,8 +43261,8 @@ function handleError(err) {
|
|
|
43250
43261
|
process.exit(EXIT_CODES2.GENERAL_ERROR);
|
|
43251
43262
|
}
|
|
43252
43263
|
var import_handlebars, ConfigError3, MAX_JSONC_LENGTH3, GitConfigSchema3, MonorepoConfigSchema3, BranchPatternSchema3, VersionCargoConfigSchema3, VersionConfigSchema3, NpmConfigSchema3, CargoPublishConfigSchema3, PublishGitConfigSchema3, GitHubReleaseConfigSchema3, VerifyRegistryConfigSchema3, VerifyConfigSchema3, PublishConfigSchema3, TemplateConfigSchema3, LocationModeSchema3, ChangelogConfigSchema3, LLMOptionsSchema3, LLMRetryConfigSchema3, LLMTasksConfigSchema3, LLMCategorySchema3, ScopeRulesSchema3, ScopeConfigSchema3, LLMPromptOverridesSchema3, LLMPromptsConfigSchema3, LLMConfigSchema3, ReleaseNotesConfigSchema3, NotesInputConfigSchema3, NotesConfigSchema3, CILabelsConfigSchema3, CIConfigSchema3, ReleaseCIConfigSchema3, ReleaseConfigSchema3, ReleaseKitConfigSchema3, MAX_INPUT_LENGTH3, SOLE_REFERENCE_PATTERN3, AUTH_DIR3, AUTH_FILE3, CONFIG_FILE3, NotesError, InputParseError, TemplateError, LLMError, GitHubError, ConfigError22, LLM_DEFAULTS, BaseLLMProvider, AnthropicProvider, OllamaProvider, OpenAIProvider, OpenAICompatibleProvider, DEFAULT_CATEGORIZE_PROMPT, DEFAULT_ENHANCE_PROMPT, DEFAULT_RELEASE_NOTES_PROMPT, DEFAULT_SUMMARIZE_PROMPT;
|
|
43253
|
-
var
|
|
43254
|
-
"../notes/dist/chunk-
|
|
43264
|
+
var init_chunk_5B2RYLOK = __esm({
|
|
43265
|
+
"../notes/dist/chunk-5B2RYLOK.js"() {
|
|
43255
43266
|
"use strict";
|
|
43256
43267
|
init_chunk_7TJSPQPW();
|
|
43257
43268
|
init_sdk();
|
|
@@ -43533,7 +43544,18 @@ var init_chunk_Y4S5UWCL = __esm({
|
|
|
43533
43544
|
major: "release:major",
|
|
43534
43545
|
minor: "release:minor",
|
|
43535
43546
|
patch: "release:patch"
|
|
43536
|
-
})
|
|
43547
|
+
}),
|
|
43548
|
+
/**
|
|
43549
|
+
* Map of scope labels to package patterns.
|
|
43550
|
+
* When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
|
|
43551
|
+
*/
|
|
43552
|
+
scopeLabels: z4.record(z4.string(), z4.string()).optional(),
|
|
43553
|
+
/**
|
|
43554
|
+
* Default scope to use when no scope label is found on the merged PR.
|
|
43555
|
+
* Must reference a key from scopeLabels (e.g., "scope:shared").
|
|
43556
|
+
* Only applies when scopeLabels is configured.
|
|
43557
|
+
*/
|
|
43558
|
+
defaultScope: z4.string().optional()
|
|
43537
43559
|
});
|
|
43538
43560
|
ReleaseCIConfigSchema3 = z4.object({
|
|
43539
43561
|
skipPatterns: z4.array(z4.string().min(1)).optional(),
|
|
@@ -43915,13 +43937,13 @@ function writeJson(outputPath, contexts, dryRun) {
|
|
|
43915
43937
|
var init_dist14 = __esm({
|
|
43916
43938
|
"../notes/dist/index.js"() {
|
|
43917
43939
|
"use strict";
|
|
43918
|
-
|
|
43940
|
+
init_chunk_5B2RYLOK();
|
|
43919
43941
|
init_chunk_F7MUVHZ2();
|
|
43920
43942
|
init_chunk_7TJSPQPW();
|
|
43921
43943
|
}
|
|
43922
43944
|
});
|
|
43923
43945
|
|
|
43924
|
-
// ../publish/dist/chunk-
|
|
43946
|
+
// ../publish/dist/chunk-UARK5H2F.js
|
|
43925
43947
|
import chalk5 from "chalk";
|
|
43926
43948
|
import * as fs25 from "fs";
|
|
43927
43949
|
import * as TOML4 from "smol-toml";
|
|
@@ -45458,8 +45480,8 @@ function createPublishCommand() {
|
|
|
45458
45480
|
});
|
|
45459
45481
|
}
|
|
45460
45482
|
var import_semver6, LOG_LEVELS4, PREFIXES4, COLORS4, currentLevel4, quietMode4, ReleaseKitError4, EXIT_CODES3, ConfigError4, MAX_JSONC_LENGTH4, GitConfigSchema4, MonorepoConfigSchema4, BranchPatternSchema4, VersionCargoConfigSchema4, VersionConfigSchema4, NpmConfigSchema4, CargoPublishConfigSchema4, PublishGitConfigSchema4, GitHubReleaseConfigSchema4, VerifyRegistryConfigSchema4, VerifyConfigSchema4, PublishConfigSchema4, TemplateConfigSchema4, LocationModeSchema4, ChangelogConfigSchema4, LLMOptionsSchema4, LLMRetryConfigSchema4, LLMTasksConfigSchema4, LLMCategorySchema4, ScopeRulesSchema4, ScopeConfigSchema4, LLMPromptOverridesSchema4, LLMPromptsConfigSchema4, LLMConfigSchema4, ReleaseNotesConfigSchema4, NotesInputConfigSchema4, NotesConfigSchema4, CILabelsConfigSchema4, CIConfigSchema4, ReleaseCIConfigSchema4, ReleaseConfigSchema4, ReleaseKitConfigSchema4, MAX_INPUT_LENGTH4, SOLE_REFERENCE_PATTERN4, AUTH_DIR4, AUTH_FILE4, CONFIG_FILE4, BasePublishError, PublishError, PipelineError, PublishErrorCode, VersionChangelogEntrySchema, VersionPackageChangelogSchema, VersionPackageUpdateSchema, VersionOutputSchema;
|
|
45461
|
-
var
|
|
45462
|
-
"../publish/dist/chunk-
|
|
45483
|
+
var init_chunk_UARK5H2F = __esm({
|
|
45484
|
+
"../publish/dist/chunk-UARK5H2F.js"() {
|
|
45463
45485
|
"use strict";
|
|
45464
45486
|
import_semver6 = __toESM(require_semver2(), 1);
|
|
45465
45487
|
LOG_LEVELS4 = {
|
|
@@ -45788,7 +45810,18 @@ var init_chunk_OZHNJUFW = __esm({
|
|
|
45788
45810
|
major: "release:major",
|
|
45789
45811
|
minor: "release:minor",
|
|
45790
45812
|
patch: "release:patch"
|
|
45791
|
-
})
|
|
45813
|
+
}),
|
|
45814
|
+
/**
|
|
45815
|
+
* Map of scope labels to package patterns.
|
|
45816
|
+
* When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
|
|
45817
|
+
*/
|
|
45818
|
+
scopeLabels: z5.record(z5.string(), z5.string()).optional(),
|
|
45819
|
+
/**
|
|
45820
|
+
* Default scope to use when no scope label is found on the merged PR.
|
|
45821
|
+
* Must reference a key from scopeLabels (e.g., "scope:shared").
|
|
45822
|
+
* Only applies when scopeLabels is configured.
|
|
45823
|
+
*/
|
|
45824
|
+
defaultScope: z5.string().optional()
|
|
45792
45825
|
});
|
|
45793
45826
|
ReleaseCIConfigSchema4 = z5.object({
|
|
45794
45827
|
skipPatterns: z5.array(z5.string().min(1)).optional(),
|
|
@@ -45921,7 +45954,7 @@ __export(dist_exports5, {
|
|
|
45921
45954
|
var init_dist15 = __esm({
|
|
45922
45955
|
"../publish/dist/index.js"() {
|
|
45923
45956
|
"use strict";
|
|
45924
|
-
|
|
45957
|
+
init_chunk_UARK5H2F();
|
|
45925
45958
|
}
|
|
45926
45959
|
});
|
|
45927
45960
|
|
|
@@ -46327,7 +46360,18 @@ var CIConfigSchema = z.object({
|
|
|
46327
46360
|
major: "release:major",
|
|
46328
46361
|
minor: "release:minor",
|
|
46329
46362
|
patch: "release:patch"
|
|
46330
|
-
})
|
|
46363
|
+
}),
|
|
46364
|
+
/**
|
|
46365
|
+
* Map of scope labels to package patterns.
|
|
46366
|
+
* When a PR has a label matching a key, only packages matching the corresponding pattern will be released.
|
|
46367
|
+
*/
|
|
46368
|
+
scopeLabels: z.record(z.string(), z.string()).optional(),
|
|
46369
|
+
/**
|
|
46370
|
+
* Default scope to use when no scope label is found on the merged PR.
|
|
46371
|
+
* Must reference a key from scopeLabels (e.g., "scope:shared").
|
|
46372
|
+
* Only applies when scopeLabels is configured.
|
|
46373
|
+
*/
|
|
46374
|
+
defaultScope: z.string().optional()
|
|
46331
46375
|
});
|
|
46332
46376
|
var ReleaseCIConfigSchema = z.object({
|
|
46333
46377
|
skipPatterns: z.array(z.string().min(1)).optional(),
|
|
@@ -46430,6 +46474,34 @@ function loadCIConfig(options) {
|
|
|
46430
46474
|
return config.ci;
|
|
46431
46475
|
}
|
|
46432
46476
|
|
|
46477
|
+
// src/label-utils.ts
|
|
46478
|
+
var DEFAULT_LABELS = {
|
|
46479
|
+
stable: "release:stable",
|
|
46480
|
+
prerelease: "release:prerelease",
|
|
46481
|
+
skip: "release:skip",
|
|
46482
|
+
major: "release:major",
|
|
46483
|
+
minor: "release:minor",
|
|
46484
|
+
patch: "release:patch"
|
|
46485
|
+
};
|
|
46486
|
+
function detectLabelConflicts(prLabels, labels = DEFAULT_LABELS) {
|
|
46487
|
+
const bumpLabelsPresent = [
|
|
46488
|
+
prLabels.includes(labels.major) && "major",
|
|
46489
|
+
prLabels.includes(labels.minor) && "minor",
|
|
46490
|
+
prLabels.includes(labels.patch) && "patch"
|
|
46491
|
+
].filter(Boolean);
|
|
46492
|
+
const bumpConflict = bumpLabelsPresent.length > 1;
|
|
46493
|
+
const hasStable = prLabels.includes(labels.stable);
|
|
46494
|
+
const hasPrerelease = prLabels.includes(labels.prerelease);
|
|
46495
|
+
const prereleaseConflict = hasStable && hasPrerelease;
|
|
46496
|
+
return {
|
|
46497
|
+
bumpConflict,
|
|
46498
|
+
bumpLabelsPresent,
|
|
46499
|
+
prereleaseConflict,
|
|
46500
|
+
hasStable,
|
|
46501
|
+
hasPrerelease
|
|
46502
|
+
};
|
|
46503
|
+
}
|
|
46504
|
+
|
|
46433
46505
|
// src/preview-context.ts
|
|
46434
46506
|
import * as fs4 from "fs";
|
|
46435
46507
|
function resolvePreviewContext(opts) {
|
|
@@ -46546,25 +46618,54 @@ function getIntroMessage(strategy, standingPrNumber) {
|
|
|
46546
46618
|
}
|
|
46547
46619
|
function getLabelBanner(labelContext) {
|
|
46548
46620
|
if (!labelContext) return [];
|
|
46621
|
+
const lines = [];
|
|
46622
|
+
if (labelContext.scopeLabels && labelContext.scopeLabels.length > 0) {
|
|
46623
|
+
lines.push(`> **Scope:** ${labelContext.scopeLabels.join(", ")}`, "");
|
|
46624
|
+
}
|
|
46549
46625
|
if (labelContext.trigger === "commit") {
|
|
46550
46626
|
if (labelContext.skip) {
|
|
46551
|
-
|
|
46627
|
+
lines.push("> **Warning:** This PR is marked to skip release.", "");
|
|
46628
|
+
return lines;
|
|
46552
46629
|
}
|
|
46553
46630
|
if (labelContext.bumpLabel === "major") {
|
|
46554
|
-
|
|
46555
|
-
|
|
46631
|
+
lines.push("> **Important:** This PR is labeled for a **major** release.", "");
|
|
46632
|
+
return lines;
|
|
46633
|
+
}
|
|
46634
|
+
}
|
|
46635
|
+
if (labelContext.prereleaseConflict) {
|
|
46636
|
+
const labels = labelContext.labels;
|
|
46637
|
+
const stableLabel = labels?.stable ?? "release:stable";
|
|
46638
|
+
const prereleaseLabel = labels?.prerelease ?? "release:prerelease";
|
|
46639
|
+
lines.push(
|
|
46640
|
+
"> **Error:** Conflicting release type labels detected.",
|
|
46641
|
+
`> **Note:** Please use only one of \`${stableLabel}\` or \`${prereleaseLabel}\` at a time.`,
|
|
46642
|
+
""
|
|
46643
|
+
);
|
|
46644
|
+
return lines;
|
|
46556
46645
|
}
|
|
46557
46646
|
if (labelContext.trigger === "label") {
|
|
46647
|
+
if (labelContext.bumpConflict) {
|
|
46648
|
+
const labels = labelContext.labels;
|
|
46649
|
+
const labelExamples = labels ? `\`${labels.patch}\`, \`${labels.minor}\`, or \`${labels.major}\`` : "a release label (e.g., `release:patch`, `release:minor`, `release:major`)";
|
|
46650
|
+
lines.push(
|
|
46651
|
+
"> **Error:** Conflicting bump labels detected.",
|
|
46652
|
+
`> **Note:** Please use only one release label at a time. Use ${labelExamples}.`,
|
|
46653
|
+
""
|
|
46654
|
+
);
|
|
46655
|
+
return lines;
|
|
46656
|
+
}
|
|
46558
46657
|
if (labelContext.noBumpLabel) {
|
|
46559
46658
|
const labels = labelContext.labels;
|
|
46560
46659
|
const labelExamples = labels ? `\`${labels.patch}\`, \`${labels.minor}\`, or \`${labels.major}\`` : "a release label (e.g., `release:patch`, `release:minor`, `release:major`)";
|
|
46561
|
-
|
|
46660
|
+
lines.push("> No release label detected.", `> **Note:** Add ${labelExamples} to trigger a release.`, "");
|
|
46661
|
+
return lines;
|
|
46562
46662
|
}
|
|
46563
46663
|
if (labelContext.bumpLabel) {
|
|
46564
|
-
|
|
46664
|
+
lines.push(`> This PR is labeled for a **${labelContext.bumpLabel}** release.`, "");
|
|
46665
|
+
return lines;
|
|
46565
46666
|
}
|
|
46566
46667
|
}
|
|
46567
|
-
return
|
|
46668
|
+
return lines;
|
|
46568
46669
|
}
|
|
46569
46670
|
function formatPreviewComment(result, options) {
|
|
46570
46671
|
const strategy = options?.strategy ?? "direct";
|
|
@@ -46673,6 +46774,18 @@ import { Octokit } from "@octokit/rest";
|
|
|
46673
46774
|
function createOctokit(token) {
|
|
46674
46775
|
return new Octokit({ auth: token });
|
|
46675
46776
|
}
|
|
46777
|
+
async function findMergedPRsForCommit(octokit, owner, repo, commitSha) {
|
|
46778
|
+
try {
|
|
46779
|
+
const { data: prs } = await octokit.rest.repos.listPullRequestsAssociatedWithCommit({
|
|
46780
|
+
owner,
|
|
46781
|
+
repo,
|
|
46782
|
+
commit_sha: commitSha
|
|
46783
|
+
});
|
|
46784
|
+
return prs.filter((pr) => pr.merged_at !== null).map((pr) => pr.number);
|
|
46785
|
+
} catch {
|
|
46786
|
+
return [];
|
|
46787
|
+
}
|
|
46788
|
+
}
|
|
46676
46789
|
async function findPreviewComment(octokit, owner, repo, prNumber) {
|
|
46677
46790
|
const iterator = octokit.paginate.iterator(octokit.rest.issues.listComments, {
|
|
46678
46791
|
owner,
|
|
@@ -46725,6 +46838,82 @@ function getHeadCommitMessage(cwd3) {
|
|
|
46725
46838
|
return null;
|
|
46726
46839
|
}
|
|
46727
46840
|
}
|
|
46841
|
+
function getGitHubContext() {
|
|
46842
|
+
const repo = process.env.GITHUB_REPOSITORY;
|
|
46843
|
+
const sha = process.env.GITHUB_SHA;
|
|
46844
|
+
if (!repo || !sha) {
|
|
46845
|
+
return null;
|
|
46846
|
+
}
|
|
46847
|
+
const [owner, repoName] = repo.split("/");
|
|
46848
|
+
if (!owner || !repoName) {
|
|
46849
|
+
return null;
|
|
46850
|
+
}
|
|
46851
|
+
return { owner, repo: repoName, sha };
|
|
46852
|
+
}
|
|
46853
|
+
async function applyScopeLabelsFromPR(ciConfig, options) {
|
|
46854
|
+
const scopeLabels = ciConfig?.scopeLabels ?? {};
|
|
46855
|
+
const defaultScope = ciConfig?.defaultScope;
|
|
46856
|
+
const githubContext = getGitHubContext();
|
|
46857
|
+
if (!githubContext) {
|
|
46858
|
+
return { target: options.target, scopeLabels: [], labels: [] };
|
|
46859
|
+
}
|
|
46860
|
+
const token = process.env.GITHUB_TOKEN;
|
|
46861
|
+
if (!token) {
|
|
46862
|
+
warn("No GITHUB_TOKEN available \u2014 skipping scope label detection");
|
|
46863
|
+
return { target: options.target, scopeLabels: [], labels: [] };
|
|
46864
|
+
}
|
|
46865
|
+
const octokit = createOctokit(token);
|
|
46866
|
+
const prNumbers = await findMergedPRsForCommit(octokit, githubContext.owner, githubContext.repo, githubContext.sha);
|
|
46867
|
+
const allLabels = [];
|
|
46868
|
+
const perPRLabels = /* @__PURE__ */ new Map();
|
|
46869
|
+
for (const prNumber of prNumbers) {
|
|
46870
|
+
const labels = await fetchPRLabels(octokit, githubContext.owner, githubContext.repo, prNumber);
|
|
46871
|
+
allLabels.push(...labels);
|
|
46872
|
+
perPRLabels.set(prNumber, labels);
|
|
46873
|
+
}
|
|
46874
|
+
for (const [prNumber, labels] of perPRLabels) {
|
|
46875
|
+
const conflict = detectLabelConflicts(labels, ciConfig?.labels ?? DEFAULT_LABELS);
|
|
46876
|
+
if (conflict.prereleaseConflict) {
|
|
46877
|
+
warn(
|
|
46878
|
+
`PR #${prNumber} has conflicting labels "${ciConfig?.labels?.stable ?? "release:stable"}" and "${ciConfig?.labels?.prerelease ?? "release:prerelease"}" \u2014 release blocked`
|
|
46879
|
+
);
|
|
46880
|
+
return { target: options.target, scopeLabels: [], labels: [], blocked: true };
|
|
46881
|
+
}
|
|
46882
|
+
if (conflict.bumpConflict && (ciConfig?.releaseTrigger ?? "label") === "label") {
|
|
46883
|
+
warn(`PR #${prNumber} has conflicting bump labels (${conflict.bumpLabelsPresent.join(", ")}) \u2014 release blocked`);
|
|
46884
|
+
return { target: options.target, scopeLabels: [], labels: [], blocked: true };
|
|
46885
|
+
}
|
|
46886
|
+
}
|
|
46887
|
+
if (prNumbers.length === 0) {
|
|
46888
|
+
if (defaultScope && Object.keys(scopeLabels).length > 0) {
|
|
46889
|
+
const defaultPattern = scopeLabels[defaultScope];
|
|
46890
|
+
if (defaultPattern) {
|
|
46891
|
+
info(`No merged PRs found \u2014 using default scope "${defaultScope}" (${defaultPattern})`);
|
|
46892
|
+
return { target: defaultPattern, scopeLabels: [], labels: allLabels };
|
|
46893
|
+
}
|
|
46894
|
+
}
|
|
46895
|
+
info("No merged PRs found for HEAD commit \u2014 releasing all packages");
|
|
46896
|
+
return { target: options.target, scopeLabels: [], labels: allLabels };
|
|
46897
|
+
}
|
|
46898
|
+
const matchedScopePatterns = [];
|
|
46899
|
+
for (const [labelName, packagePattern] of Object.entries(scopeLabels)) {
|
|
46900
|
+
if (allLabels.includes(labelName)) {
|
|
46901
|
+
info(`Scope label "${labelName}" detected \u2014 limiting release to packages matching "${packagePattern}"`);
|
|
46902
|
+
matchedScopePatterns.push(packagePattern);
|
|
46903
|
+
}
|
|
46904
|
+
}
|
|
46905
|
+
let finalTarget = options.target;
|
|
46906
|
+
if (matchedScopePatterns.length > 0) {
|
|
46907
|
+
finalTarget = matchedScopePatterns.join(", ");
|
|
46908
|
+
} else if (defaultScope && Object.keys(scopeLabels).length > 0) {
|
|
46909
|
+
const defaultPattern = scopeLabels[defaultScope];
|
|
46910
|
+
if (defaultPattern) {
|
|
46911
|
+
info(`No scope label found \u2014 using default scope "${defaultScope}" (${defaultPattern})`);
|
|
46912
|
+
finalTarget = defaultPattern;
|
|
46913
|
+
}
|
|
46914
|
+
}
|
|
46915
|
+
return { target: finalTarget, scopeLabels: matchedScopePatterns, labels: allLabels };
|
|
46916
|
+
}
|
|
46728
46917
|
async function runRelease(inputOptions) {
|
|
46729
46918
|
const options = { ...inputOptions };
|
|
46730
46919
|
if (options.verbose) setLogLevel("debug");
|
|
@@ -46738,6 +46927,26 @@ async function runRelease(inputOptions) {
|
|
|
46738
46927
|
throw err;
|
|
46739
46928
|
}
|
|
46740
46929
|
const releaseConfig = releaseKitConfig.release;
|
|
46930
|
+
const ciConfig = loadCIConfig({ cwd: options.projectDir, configPath: options.config });
|
|
46931
|
+
if (!options.dryRun) {
|
|
46932
|
+
const scopeResult = await applyScopeLabelsFromPR(ciConfig, options);
|
|
46933
|
+
if (scopeResult.blocked) {
|
|
46934
|
+
info("Release blocked due to conflicting PR labels");
|
|
46935
|
+
return null;
|
|
46936
|
+
}
|
|
46937
|
+
if (scopeResult.target !== options.target) {
|
|
46938
|
+
options.target = scopeResult.target;
|
|
46939
|
+
}
|
|
46940
|
+
} else if (ciConfig?.scopeLabels) {
|
|
46941
|
+
const scopeResult = await applyScopeLabelsFromPR(ciConfig, options);
|
|
46942
|
+
if (scopeResult.blocked) {
|
|
46943
|
+
info("Release blocked due to conflicting PR labels");
|
|
46944
|
+
return null;
|
|
46945
|
+
}
|
|
46946
|
+
if (scopeResult.target !== options.target) {
|
|
46947
|
+
options.target = scopeResult.target;
|
|
46948
|
+
}
|
|
46949
|
+
}
|
|
46741
46950
|
if (releaseConfig?.ci?.skipPatterns?.length) {
|
|
46742
46951
|
const headCommit = getHeadCommitMessage(options.projectDir);
|
|
46743
46952
|
if (headCommit) {
|
|
@@ -46867,14 +47076,6 @@ async function runPublishStep(versionOutput, options, releaseNotes, additionalFi
|
|
|
46867
47076
|
}
|
|
46868
47077
|
|
|
46869
47078
|
// src/preview.ts
|
|
46870
|
-
var DEFAULT_LABELS = {
|
|
46871
|
-
stable: "release:stable",
|
|
46872
|
-
prerelease: "release:prerelease",
|
|
46873
|
-
skip: "release:skip",
|
|
46874
|
-
major: "release:major",
|
|
46875
|
-
minor: "release:minor",
|
|
46876
|
-
patch: "release:patch"
|
|
46877
|
-
};
|
|
46878
47079
|
async function runPreview(options) {
|
|
46879
47080
|
const ciConfig = loadCIConfig({ cwd: options.projectDir, configPath: options.config });
|
|
46880
47081
|
if (ciConfig?.prPreview === false) {
|
|
@@ -46908,6 +47109,7 @@ async function runPreview(options) {
|
|
|
46908
47109
|
sync: false,
|
|
46909
47110
|
bump: effectiveOptions.bump,
|
|
46910
47111
|
prerelease: prereleaseFlag,
|
|
47112
|
+
stable: effectiveOptions.stable,
|
|
46911
47113
|
skipNotes: true,
|
|
46912
47114
|
skipPublish: true,
|
|
46913
47115
|
skipGit: true,
|
|
@@ -46916,7 +47118,8 @@ async function runPreview(options) {
|
|
|
46916
47118
|
json: false,
|
|
46917
47119
|
verbose: false,
|
|
46918
47120
|
quiet: true,
|
|
46919
|
-
projectDir: effectiveOptions.projectDir
|
|
47121
|
+
projectDir: effectiveOptions.projectDir,
|
|
47122
|
+
target: effectiveOptions.target
|
|
46920
47123
|
});
|
|
46921
47124
|
} else {
|
|
46922
47125
|
info("No release label detected \u2014 skipping version analysis");
|
|
@@ -46947,7 +47150,14 @@ function resolvePrerelease(options, packagePaths, projectDir) {
|
|
|
46947
47150
|
async function applyLabelOverrides(options, ciConfig, context, existingOctokit) {
|
|
46948
47151
|
const trigger = ciConfig?.releaseTrigger ?? "label";
|
|
46949
47152
|
const labels = ciConfig?.labels ?? DEFAULT_LABELS;
|
|
46950
|
-
const
|
|
47153
|
+
const scopeLabels = ciConfig?.scopeLabels ?? {};
|
|
47154
|
+
const defaultLabelContext = {
|
|
47155
|
+
trigger,
|
|
47156
|
+
skip: false,
|
|
47157
|
+
noBumpLabel: false,
|
|
47158
|
+
bumpConflict: false,
|
|
47159
|
+
prereleaseConflict: false
|
|
47160
|
+
};
|
|
46951
47161
|
if (!context) {
|
|
46952
47162
|
return {
|
|
46953
47163
|
options,
|
|
@@ -46966,7 +47176,41 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
|
|
|
46966
47176
|
};
|
|
46967
47177
|
}
|
|
46968
47178
|
const result = { ...options };
|
|
46969
|
-
const labelContext = {
|
|
47179
|
+
const labelContext = {
|
|
47180
|
+
trigger,
|
|
47181
|
+
skip: false,
|
|
47182
|
+
noBumpLabel: false,
|
|
47183
|
+
bumpConflict: false,
|
|
47184
|
+
prereleaseConflict: false,
|
|
47185
|
+
labels,
|
|
47186
|
+
scopeLabels: []
|
|
47187
|
+
};
|
|
47188
|
+
const matchedScopePatterns = [];
|
|
47189
|
+
for (const [labelName, packagePattern] of Object.entries(scopeLabels)) {
|
|
47190
|
+
if (prLabels.includes(labelName)) {
|
|
47191
|
+
info(`PR label "${labelName}" detected \u2014 limiting release to packages matching "${packagePattern}"`);
|
|
47192
|
+
matchedScopePatterns.push(packagePattern);
|
|
47193
|
+
}
|
|
47194
|
+
}
|
|
47195
|
+
labelContext.scopeLabels = matchedScopePatterns;
|
|
47196
|
+
if (matchedScopePatterns.length > 0) {
|
|
47197
|
+
result.target = matchedScopePatterns.join(", ");
|
|
47198
|
+
} else if (ciConfig?.defaultScope && scopeLabels[ciConfig.defaultScope]) {
|
|
47199
|
+
const defaultPattern = scopeLabels[ciConfig.defaultScope];
|
|
47200
|
+
info(`No scope label found \u2014 using default scope "${ciConfig.defaultScope}" (${defaultPattern})`);
|
|
47201
|
+
result.target = defaultPattern;
|
|
47202
|
+
}
|
|
47203
|
+
const conflict = detectLabelConflicts(prLabels, labels);
|
|
47204
|
+
if (trigger === "label" && conflict.bumpConflict) {
|
|
47205
|
+
warn(`Conflicting bump labels detected (${conflict.bumpLabelsPresent.join(", ")}) \u2014 release blocked`);
|
|
47206
|
+
labelContext.noBumpLabel = true;
|
|
47207
|
+
labelContext.bumpConflict = true;
|
|
47208
|
+
}
|
|
47209
|
+
if (conflict.prereleaseConflict) {
|
|
47210
|
+
warn(`Conflicting labels "${labels.stable}" and "${labels.prerelease}" detected \u2014 release blocked`);
|
|
47211
|
+
labelContext.noBumpLabel = true;
|
|
47212
|
+
labelContext.prereleaseConflict = true;
|
|
47213
|
+
}
|
|
46970
47214
|
if (trigger === "commit") {
|
|
46971
47215
|
if (prLabels.includes(labels.skip)) {
|
|
46972
47216
|
info(`PR label "${labels.skip}" detected \u2014 release will be skipped`);
|
|
@@ -46978,7 +47222,8 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
|
|
|
46978
47222
|
result.bump = "major";
|
|
46979
47223
|
}
|
|
46980
47224
|
} else {
|
|
46981
|
-
if (
|
|
47225
|
+
if (conflict.bumpConflict || conflict.prereleaseConflict) {
|
|
47226
|
+
} else if (prLabels.includes(labels.major)) {
|
|
46982
47227
|
info(`PR label "${labels.major}" detected \u2014 major release`);
|
|
46983
47228
|
labelContext.bumpLabel = "major";
|
|
46984
47229
|
result.bump = "major";
|
|
@@ -46990,17 +47235,26 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
|
|
|
46990
47235
|
info(`PR label "${labels.patch}" detected \u2014 patch release`);
|
|
46991
47236
|
labelContext.bumpLabel = "patch";
|
|
46992
47237
|
result.bump = "patch";
|
|
46993
|
-
} else {
|
|
46994
|
-
|
|
47238
|
+
} else if (matchedScopePatterns.length === 0) {
|
|
47239
|
+
const hasStableOrPrerelease = conflict.hasStable || conflict.hasPrerelease;
|
|
47240
|
+
if (!hasStableOrPrerelease) {
|
|
47241
|
+
labelContext.noBumpLabel = true;
|
|
47242
|
+
}
|
|
46995
47243
|
}
|
|
46996
47244
|
}
|
|
46997
47245
|
if (!options.stable && options.prerelease === void 0) {
|
|
46998
|
-
if (
|
|
47246
|
+
if (conflict.hasStable && conflict.hasPrerelease) {
|
|
47247
|
+
} else if (conflict.hasStable) {
|
|
46999
47248
|
info(`PR label "${labels.stable}" detected \u2014 using stable release preview`);
|
|
47000
47249
|
result.stable = true;
|
|
47001
|
-
} else if (
|
|
47250
|
+
} else if (conflict.hasPrerelease) {
|
|
47002
47251
|
info(`PR label "${labels.prerelease}" detected \u2014 using prerelease preview`);
|
|
47003
47252
|
result.prerelease = true;
|
|
47253
|
+
if (trigger === "label" && !result.bump) {
|
|
47254
|
+
info("No bump label found \u2014 defaulting to patch bump for prerelease release");
|
|
47255
|
+
result.bump = "patch";
|
|
47256
|
+
labelContext.bumpLabel = "patch";
|
|
47257
|
+
}
|
|
47004
47258
|
}
|
|
47005
47259
|
}
|
|
47006
47260
|
return { options: result, labelContext: { ...labelContext, labels } };
|
|
@@ -47008,7 +47262,7 @@ async function applyLabelOverrides(options, ciConfig, context, existingOctokit)
|
|
|
47008
47262
|
|
|
47009
47263
|
// src/preview-command.ts
|
|
47010
47264
|
function createPreviewCommand() {
|
|
47011
|
-
return new Command4("preview").description("Post a release preview comment on the current pull request").option("-c, --config <path>", "Path to config file").option("--project-dir <path>", "Project directory", process.cwd()).option("--pr <number>", "PR number (auto-detected from GitHub Actions)").option("--repo <owner/repo>", "Repository (auto-detected from GITHUB_REPOSITORY)").option("-p, --prerelease [identifier]", "Force prerelease preview (auto-detected by default)").option("--stable", "Force stable release preview (graduation from prerelease)", false).option(
|
|
47265
|
+
return new Command4("preview").description("Post a release preview comment on the current pull request").option("-c, --config <path>", "Path to config file").option("--project-dir <path>", "Project directory", process.cwd()).option("--pr <number>", "PR number (auto-detected from GitHub Actions)").option("--repo <owner/repo>", "Repository (auto-detected from GITHUB_REPOSITORY)").option("-p, --prerelease [identifier]", "Force prerelease preview (auto-detected by default)").option("--stable", "Force stable release preview (graduation from prerelease)", false).option("-t, --target <packages>", "Target specific packages (comma-separated)").option(
|
|
47012
47266
|
"-d, --dry-run",
|
|
47013
47267
|
"Print the comment to stdout without posting (GitHub context not available in dry-run mode)",
|
|
47014
47268
|
false
|
|
@@ -47021,7 +47275,8 @@ function createPreviewCommand() {
|
|
|
47021
47275
|
repo: opts.repo,
|
|
47022
47276
|
prerelease: opts.prerelease,
|
|
47023
47277
|
stable: opts.stable,
|
|
47024
|
-
dryRun: opts.dryRun
|
|
47278
|
+
dryRun: opts.dryRun,
|
|
47279
|
+
target: opts.target
|
|
47025
47280
|
});
|
|
47026
47281
|
} catch (error3) {
|
|
47027
47282
|
console.error(error3 instanceof Error ? error3.message : String(error3));
|
|
@@ -47070,7 +47325,7 @@ function createReleaseCommand() {
|
|
|
47070
47325
|
|
|
47071
47326
|
// src/cli.ts
|
|
47072
47327
|
function createReleaseProgram() {
|
|
47073
|
-
return new Command6().name("releasekit-release").description("Unified release pipeline: version, changelog, and publish").version(readPackageVersion(import.meta.url)).addCommand(
|
|
47328
|
+
return new Command6().name("releasekit-release").description("Unified release pipeline: version, changelog, and publish").version(readPackageVersion(import.meta.url)).addCommand(createPreviewCommand(), { isDefault: true }).addCommand(createReleaseCommand());
|
|
47074
47329
|
}
|
|
47075
47330
|
var isMain = (() => {
|
|
47076
47331
|
try {
|