@qlover/fe-release 3.0.0 → 3.1.2
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/dist/cli.cjs +2356 -17
- package/dist/cli.js +2356 -17
- package/dist/index.cjs +2355 -16
- package/dist/index.d.ts +2281 -35
- package/dist/index.js +2355 -16
- package/package.json +5 -4
package/dist/cli.cjs
CHANGED
|
@@ -4288,7 +4288,7 @@ var import_commander = require("commander");
|
|
|
4288
4288
|
|
|
4289
4289
|
// package.json
|
|
4290
4290
|
var description = "A tool for releasing front-end projects, supporting multiple release modes and configurations, simplifying the release process and improving efficiency.";
|
|
4291
|
-
var version = "3.
|
|
4291
|
+
var version = "3.1.2";
|
|
4292
4292
|
|
|
4293
4293
|
// src/cli.ts
|
|
4294
4294
|
var import_semver = __toESM(require_semver2(), 1);
|
|
@@ -4331,6 +4331,31 @@ var BATCH_PR_BODY = "\n## ${name} ${version}\n${changelog}\n";
|
|
|
4331
4331
|
// src/implments/ReleaseContext.ts
|
|
4332
4332
|
var import_scripts_context = require("@qlover/scripts-context");
|
|
4333
4333
|
var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
4334
|
+
/**
|
|
4335
|
+
* Creates a new ReleaseContext instance
|
|
4336
|
+
*
|
|
4337
|
+
* Initializes the context with provided options and sets up
|
|
4338
|
+
* default values for required configuration:
|
|
4339
|
+
* - rootPath: Defaults to current working directory
|
|
4340
|
+
* - sourceBranch: Uses environment variables or default
|
|
4341
|
+
* - releaseEnv: Uses environment variables or 'development'
|
|
4342
|
+
*
|
|
4343
|
+
* Environment Variable Priority:
|
|
4344
|
+
* - sourceBranch: FE_RELEASE_BRANCH > FE_RELEASE_SOURCE_BRANCH > DEFAULT_SOURCE_BRANCH
|
|
4345
|
+
* - releaseEnv: FE_RELEASE_ENV > NODE_ENV > 'development'
|
|
4346
|
+
*
|
|
4347
|
+
* @param name - Unique identifier for this release context
|
|
4348
|
+
* @param options - Configuration options
|
|
4349
|
+
*
|
|
4350
|
+
* @example
|
|
4351
|
+
* ```typescript
|
|
4352
|
+
* const context = new ReleaseContext('web-app', {
|
|
4353
|
+
* rootPath: '/projects/web-app',
|
|
4354
|
+
* sourceBranch: 'main',
|
|
4355
|
+
* releaseEnv: 'production'
|
|
4356
|
+
* });
|
|
4357
|
+
* ```
|
|
4358
|
+
*/
|
|
4334
4359
|
constructor(name, options) {
|
|
4335
4360
|
super(name, options);
|
|
4336
4361
|
if (!this.options.rootPath) {
|
|
@@ -4347,27 +4372,124 @@ var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
|
4347
4372
|
});
|
|
4348
4373
|
}
|
|
4349
4374
|
}
|
|
4375
|
+
/**
|
|
4376
|
+
* Gets the root path of the project
|
|
4377
|
+
*
|
|
4378
|
+
* @returns Absolute path to project root
|
|
4379
|
+
*
|
|
4380
|
+
* @example
|
|
4381
|
+
* ```typescript
|
|
4382
|
+
* const root = context.rootPath;
|
|
4383
|
+
* // '/path/to/project'
|
|
4384
|
+
* ```
|
|
4385
|
+
*/
|
|
4350
4386
|
get rootPath() {
|
|
4351
4387
|
return this.getOptions("rootPath");
|
|
4352
4388
|
}
|
|
4389
|
+
/**
|
|
4390
|
+
* Gets the source branch for the release
|
|
4391
|
+
*
|
|
4392
|
+
* @returns Branch name to use as source
|
|
4393
|
+
*
|
|
4394
|
+
* @example
|
|
4395
|
+
* ```typescript
|
|
4396
|
+
* const branch = context.sourceBranch;
|
|
4397
|
+
* // 'main' or custom branch name
|
|
4398
|
+
* ```
|
|
4399
|
+
*/
|
|
4353
4400
|
get sourceBranch() {
|
|
4354
4401
|
return this.getOptions("sourceBranch");
|
|
4355
4402
|
}
|
|
4403
|
+
/**
|
|
4404
|
+
* Gets the release environment
|
|
4405
|
+
*
|
|
4406
|
+
* @returns Environment name (e.g., 'development', 'production')
|
|
4407
|
+
*
|
|
4408
|
+
* @example
|
|
4409
|
+
* ```typescript
|
|
4410
|
+
* const env = context.releaseEnv;
|
|
4411
|
+
* // 'development' or custom environment
|
|
4412
|
+
* ```
|
|
4413
|
+
*/
|
|
4356
4414
|
get releaseEnv() {
|
|
4357
4415
|
return this.getOptions("releaseEnv");
|
|
4358
4416
|
}
|
|
4417
|
+
/**
|
|
4418
|
+
* Gets all configured workspaces
|
|
4419
|
+
*
|
|
4420
|
+
* @returns Array of workspace configurations or undefined
|
|
4421
|
+
*
|
|
4422
|
+
* @example
|
|
4423
|
+
* ```typescript
|
|
4424
|
+
* const allWorkspaces = context.workspaces;
|
|
4425
|
+
* // [{ name: 'pkg-a', version: '1.0.0', ... }]
|
|
4426
|
+
* ```
|
|
4427
|
+
*/
|
|
4359
4428
|
get workspaces() {
|
|
4360
4429
|
return this.getOptions("workspaces.workspaces");
|
|
4361
4430
|
}
|
|
4431
|
+
/**
|
|
4432
|
+
* Gets the current active workspace
|
|
4433
|
+
*
|
|
4434
|
+
* @returns Current workspace configuration or undefined
|
|
4435
|
+
*
|
|
4436
|
+
* @example
|
|
4437
|
+
* ```typescript
|
|
4438
|
+
* const current = context.workspace;
|
|
4439
|
+
* // { name: 'pkg-a', version: '1.0.0', ... }
|
|
4440
|
+
* ```
|
|
4441
|
+
*/
|
|
4362
4442
|
get workspace() {
|
|
4363
4443
|
return this.getOptions("workspaces.workspace");
|
|
4364
4444
|
}
|
|
4445
|
+
/**
|
|
4446
|
+
* Sets the workspace configurations
|
|
4447
|
+
*
|
|
4448
|
+
* Updates the workspace list while preserving other workspace settings
|
|
4449
|
+
*
|
|
4450
|
+
* @param workspaces - Array of workspace configurations
|
|
4451
|
+
*
|
|
4452
|
+
* @example
|
|
4453
|
+
* ```typescript
|
|
4454
|
+
* context.setWorkspaces([{
|
|
4455
|
+
* name: 'pkg-a',
|
|
4456
|
+
* version: '1.0.0',
|
|
4457
|
+
* path: 'packages/a'
|
|
4458
|
+
* }]);
|
|
4459
|
+
* ```
|
|
4460
|
+
*/
|
|
4365
4461
|
setWorkspaces(workspaces) {
|
|
4366
4462
|
this.options.workspaces = {
|
|
4367
4463
|
...this.options.workspaces,
|
|
4368
4464
|
workspaces
|
|
4369
4465
|
};
|
|
4370
4466
|
}
|
|
4467
|
+
/**
|
|
4468
|
+
* Gets package.json data for the current workspace
|
|
4469
|
+
*
|
|
4470
|
+
* Provides type-safe access to package.json fields with optional
|
|
4471
|
+
* path and default value support.
|
|
4472
|
+
*
|
|
4473
|
+
* @param key - Optional dot-notation path to specific field
|
|
4474
|
+
* @param defaultValue - Default value if field not found
|
|
4475
|
+
* @returns Package data of type T
|
|
4476
|
+
* @throws Error if package.json not found
|
|
4477
|
+
*
|
|
4478
|
+
* @example Basic usage
|
|
4479
|
+
* ```typescript
|
|
4480
|
+
* // Get entire package.json
|
|
4481
|
+
* const pkg = context.getPkg();
|
|
4482
|
+
*
|
|
4483
|
+
* // Get specific field
|
|
4484
|
+
* const version = context.getPkg<string>('version');
|
|
4485
|
+
*
|
|
4486
|
+
* // Get nested field with default
|
|
4487
|
+
* const script = context.getPkg<string>(
|
|
4488
|
+
* 'scripts.build',
|
|
4489
|
+
* 'echo "No build script"'
|
|
4490
|
+
* );
|
|
4491
|
+
* ```
|
|
4492
|
+
*/
|
|
4371
4493
|
getPkg(key, defaultValue) {
|
|
4372
4494
|
const packageJson = this.workspace?.packageJson;
|
|
4373
4495
|
if (!packageJson) {
|
|
@@ -4378,6 +4500,28 @@ var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
|
4378
4500
|
}
|
|
4379
4501
|
return (0, import_get.default)(packageJson, key, defaultValue);
|
|
4380
4502
|
}
|
|
4503
|
+
/**
|
|
4504
|
+
* Generates template context for string interpolation
|
|
4505
|
+
*
|
|
4506
|
+
* Combines context options, workspace data, and specific paths
|
|
4507
|
+
* for use in template processing. Includes deprecated fields
|
|
4508
|
+
* for backward compatibility.
|
|
4509
|
+
*
|
|
4510
|
+
* @returns Combined template context
|
|
4511
|
+
*
|
|
4512
|
+
* @example
|
|
4513
|
+
* ```typescript
|
|
4514
|
+
* const context = releaseContext.getTemplateContext();
|
|
4515
|
+
* // {
|
|
4516
|
+
* // publishPath: 'packages/my-pkg',
|
|
4517
|
+
* // env: 'production', // deprecated
|
|
4518
|
+
* // branch: 'main', // deprecated
|
|
4519
|
+
* // releaseEnv: 'production', // use this instead
|
|
4520
|
+
* // sourceBranch: 'main', // use this instead
|
|
4521
|
+
* // ...other options
|
|
4522
|
+
* // }
|
|
4523
|
+
* ```
|
|
4524
|
+
*/
|
|
4381
4525
|
getTemplateContext() {
|
|
4382
4526
|
return {
|
|
4383
4527
|
...this.getOptions(),
|
|
@@ -4388,6 +4532,28 @@ var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
|
4388
4532
|
branch: this.sourceBranch
|
|
4389
4533
|
};
|
|
4390
4534
|
}
|
|
4535
|
+
/**
|
|
4536
|
+
* Executes changeset CLI commands
|
|
4537
|
+
*
|
|
4538
|
+
* Automatically detects and uses appropriate package manager
|
|
4539
|
+
* (pnpm or npx) to run changeset commands.
|
|
4540
|
+
*
|
|
4541
|
+
* @param name - Changeset command name
|
|
4542
|
+
* @param args - Optional command arguments
|
|
4543
|
+
* @returns Command output
|
|
4544
|
+
*
|
|
4545
|
+
* @example Version bump
|
|
4546
|
+
* ```typescript
|
|
4547
|
+
* // Bump version with snapshot
|
|
4548
|
+
* await context.runChangesetsCli('version', ['--snapshot', 'alpha']);
|
|
4549
|
+
*
|
|
4550
|
+
* // Create new changeset
|
|
4551
|
+
* await context.runChangesetsCli('add');
|
|
4552
|
+
*
|
|
4553
|
+
* // Status check
|
|
4554
|
+
* await context.runChangesetsCli('status');
|
|
4555
|
+
* ```
|
|
4556
|
+
*/
|
|
4391
4557
|
async runChangesetsCli(name, args) {
|
|
4392
4558
|
let packageManager = "pnpm";
|
|
4393
4559
|
try {
|
|
@@ -4414,6 +4580,28 @@ var DEFAULT_RELEASE_CONFIG = {
|
|
|
4414
4580
|
batchTagName: "batch-${length}-packages-${timestamp}"
|
|
4415
4581
|
};
|
|
4416
4582
|
var ReleaseParams = class {
|
|
4583
|
+
/**
|
|
4584
|
+
* Creates a new ReleaseParams instance
|
|
4585
|
+
*
|
|
4586
|
+
* Initializes with logger for debug output and optional configuration
|
|
4587
|
+
* overrides. Uses default configuration values for any unspecified options.
|
|
4588
|
+
*
|
|
4589
|
+
* @param logger - Logger instance for debug output
|
|
4590
|
+
* @param config - Optional configuration overrides
|
|
4591
|
+
*
|
|
4592
|
+
* @example
|
|
4593
|
+
* ```typescript
|
|
4594
|
+
* // Basic initialization
|
|
4595
|
+
* const params = new ReleaseParams(logger);
|
|
4596
|
+
*
|
|
4597
|
+
* // With custom configuration
|
|
4598
|
+
* const params = new ReleaseParams(logger, {
|
|
4599
|
+
* maxWorkspace: 5,
|
|
4600
|
+
* multiWorkspaceSeparator: '-',
|
|
4601
|
+
* workspaceVersionSeparator: '#'
|
|
4602
|
+
* });
|
|
4603
|
+
* ```
|
|
4604
|
+
*/
|
|
4417
4605
|
constructor(logger, config = {}) {
|
|
4418
4606
|
this.logger = logger;
|
|
4419
4607
|
this.config = {
|
|
@@ -4421,7 +4609,49 @@ var ReleaseParams = class {
|
|
|
4421
4609
|
...config
|
|
4422
4610
|
};
|
|
4423
4611
|
}
|
|
4612
|
+
/**
|
|
4613
|
+
* Current configuration
|
|
4614
|
+
* @private
|
|
4615
|
+
*/
|
|
4424
4616
|
config;
|
|
4617
|
+
/**
|
|
4618
|
+
* Generates a release branch name for a single package
|
|
4619
|
+
*
|
|
4620
|
+
* Uses the branch name template from shared configuration or
|
|
4621
|
+
* falls back to the default template 'release-${tagName}'.
|
|
4622
|
+
* Supports variable interpolation in the template.
|
|
4623
|
+
*
|
|
4624
|
+
* Template Variables:
|
|
4625
|
+
* - ${pkgName}: Package name
|
|
4626
|
+
* - ${releaseName}: Release name (same as pkgName)
|
|
4627
|
+
* - ${tagName}: Release tag
|
|
4628
|
+
* - All shared config properties
|
|
4629
|
+
*
|
|
4630
|
+
* @param releaseName - Name of the package being released
|
|
4631
|
+
* @param tagName - Version tag for the release
|
|
4632
|
+
* @param shared - Shared configuration with branch template
|
|
4633
|
+
* @returns Formatted branch name
|
|
4634
|
+
* @throws Error if branch name template is not a string
|
|
4635
|
+
*
|
|
4636
|
+
* @example
|
|
4637
|
+
* ```typescript
|
|
4638
|
+
* // With default template
|
|
4639
|
+
* const branch = params.getReleaseBranchName(
|
|
4640
|
+
* 'my-pkg',
|
|
4641
|
+
* 'v1.0.0',
|
|
4642
|
+
* {}
|
|
4643
|
+
* );
|
|
4644
|
+
* // 'release-v1.0.0'
|
|
4645
|
+
*
|
|
4646
|
+
* // With custom template
|
|
4647
|
+
* const branch = params.getReleaseBranchName(
|
|
4648
|
+
* 'my-pkg',
|
|
4649
|
+
* 'v1.0.0',
|
|
4650
|
+
* { branchName: '${pkgName}-release-${tagName}' }
|
|
4651
|
+
* );
|
|
4652
|
+
* // 'my-pkg-release-v1.0.0'
|
|
4653
|
+
* ```
|
|
4654
|
+
*/
|
|
4425
4655
|
getReleaseBranchName(releaseName, tagName, shared) {
|
|
4426
4656
|
const branchNameTpl = shared.branchName || "release-${tagName}";
|
|
4427
4657
|
if (typeof branchNameTpl !== "string") {
|
|
@@ -4436,6 +4666,49 @@ var ReleaseParams = class {
|
|
|
4436
4666
|
...shared
|
|
4437
4667
|
});
|
|
4438
4668
|
}
|
|
4669
|
+
/**
|
|
4670
|
+
* Generates a release branch name for multiple packages
|
|
4671
|
+
*
|
|
4672
|
+
* Uses the batch branch name template from configuration.
|
|
4673
|
+
* Supports variable interpolation with additional batch-specific
|
|
4674
|
+
* variables.
|
|
4675
|
+
*
|
|
4676
|
+
* Template Variables:
|
|
4677
|
+
* - ${pkgName}: Package name
|
|
4678
|
+
* - ${releaseName}: Combined release name
|
|
4679
|
+
* - ${tagName}: Combined tag name
|
|
4680
|
+
* - ${length}: Number of packages
|
|
4681
|
+
* - ${timestamp}: Current timestamp
|
|
4682
|
+
* - All shared config properties
|
|
4683
|
+
*
|
|
4684
|
+
* @param releaseName - Combined name of packages
|
|
4685
|
+
* @param tagName - Combined version tag
|
|
4686
|
+
* @param shared - Shared configuration
|
|
4687
|
+
* @param length - Number of packages in batch
|
|
4688
|
+
* @returns Formatted batch branch name
|
|
4689
|
+
* @throws Error if branch name template is not a string
|
|
4690
|
+
*
|
|
4691
|
+
* @example
|
|
4692
|
+
* ```typescript
|
|
4693
|
+
* // With default template
|
|
4694
|
+
* const branch = params.getBatchReleaseBranchName(
|
|
4695
|
+
* 'pkg-a@1.0.0_pkg-b@2.0.0',
|
|
4696
|
+
* 'batch-2-packages-1234567890',
|
|
4697
|
+
* {},
|
|
4698
|
+
* 2
|
|
4699
|
+
* );
|
|
4700
|
+
* // 'batch-pkg-a@1.0.0_pkg-b@2.0.0-2-packages-1234567890'
|
|
4701
|
+
*
|
|
4702
|
+
* // With custom template
|
|
4703
|
+
* const branch = params.getBatchReleaseBranchName(
|
|
4704
|
+
* 'pkg-a@1.0.0_pkg-b@2.0.0',
|
|
4705
|
+
* 'v1.0.0',
|
|
4706
|
+
* {},
|
|
4707
|
+
* 2,
|
|
4708
|
+
* );
|
|
4709
|
+
* // Custom formatted branch name
|
|
4710
|
+
* ```
|
|
4711
|
+
*/
|
|
4439
4712
|
getBatchReleaseBranchName(releaseName, tagName, shared, length) {
|
|
4440
4713
|
const branchNameTpl = this.config.batchBranchName;
|
|
4441
4714
|
if (typeof branchNameTpl !== "string") {
|
|
@@ -4452,6 +4725,45 @@ var ReleaseParams = class {
|
|
|
4452
4725
|
timestamp: Date.now()
|
|
4453
4726
|
});
|
|
4454
4727
|
}
|
|
4728
|
+
/**
|
|
4729
|
+
* Generates a release name from workspace configurations
|
|
4730
|
+
*
|
|
4731
|
+
* For single packages, returns the package name.
|
|
4732
|
+
* For multiple packages, combines names and versions up to
|
|
4733
|
+
* the configured maximum number of workspaces.
|
|
4734
|
+
*
|
|
4735
|
+
* Format:
|
|
4736
|
+
* - Single: packageName
|
|
4737
|
+
* - Multiple: pkg1@1.0.0_pkg2@2.0.0_pkg3@3.0.0
|
|
4738
|
+
*
|
|
4739
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
4740
|
+
* @returns Formatted release name
|
|
4741
|
+
*
|
|
4742
|
+
* @example
|
|
4743
|
+
* ```typescript
|
|
4744
|
+
* // Single package
|
|
4745
|
+
* const name = params.getReleaseName([
|
|
4746
|
+
* { name: 'pkg-a', version: '1.0.0' }
|
|
4747
|
+
* ]);
|
|
4748
|
+
* // 'pkg-a'
|
|
4749
|
+
*
|
|
4750
|
+
* // Multiple packages
|
|
4751
|
+
* const name = params.getReleaseName([
|
|
4752
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
4753
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
4754
|
+
* ]);
|
|
4755
|
+
* // 'pkg-a@1.0.0_pkg-b@2.0.0'
|
|
4756
|
+
*
|
|
4757
|
+
* // With max limit
|
|
4758
|
+
* const name = params.getReleaseName([
|
|
4759
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
4760
|
+
* { name: 'pkg-b', version: '2.0.0' },
|
|
4761
|
+
* { name: 'pkg-c', version: '3.0.0' },
|
|
4762
|
+
* { name: 'pkg-d', version: '4.0.0' }
|
|
4763
|
+
* ]);
|
|
4764
|
+
* // Only first 3: 'pkg-a@1.0.0_pkg-b@2.0.0_pkg-c@3.0.0'
|
|
4765
|
+
* ```
|
|
4766
|
+
*/
|
|
4455
4767
|
getReleaseName(composeWorkspaces) {
|
|
4456
4768
|
if (composeWorkspaces.length === 1) {
|
|
4457
4769
|
return composeWorkspaces[0].name;
|
|
@@ -4461,6 +4773,36 @@ var ReleaseParams = class {
|
|
|
4461
4773
|
({ name, version: version2 }) => `${name}${workspaceVersionSeparator}${version2}`
|
|
4462
4774
|
).join(multiWorkspaceSeparator);
|
|
4463
4775
|
}
|
|
4776
|
+
/**
|
|
4777
|
+
* Generates a tag name for the release
|
|
4778
|
+
*
|
|
4779
|
+
* For single packages, uses the package version.
|
|
4780
|
+
* For multiple packages, generates a batch tag name using
|
|
4781
|
+
* the configured template.
|
|
4782
|
+
*
|
|
4783
|
+
* Format:
|
|
4784
|
+
* - Single: version
|
|
4785
|
+
* - Multiple: batch-${length}-packages-${timestamp}
|
|
4786
|
+
*
|
|
4787
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
4788
|
+
* @returns Formatted tag name
|
|
4789
|
+
*
|
|
4790
|
+
* @example
|
|
4791
|
+
* ```typescript
|
|
4792
|
+
* // Single package
|
|
4793
|
+
* const tag = params.getReleaseTagName([
|
|
4794
|
+
* { name: 'pkg-a', version: '1.0.0' }
|
|
4795
|
+
* ]);
|
|
4796
|
+
* // '1.0.0'
|
|
4797
|
+
*
|
|
4798
|
+
* // Multiple packages
|
|
4799
|
+
* const tag = params.getReleaseTagName([
|
|
4800
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
4801
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
4802
|
+
* ]);
|
|
4803
|
+
* // 'batch-2-packages-1234567890'
|
|
4804
|
+
* ```
|
|
4805
|
+
*/
|
|
4464
4806
|
getReleaseTagName(composeWorkspaces) {
|
|
4465
4807
|
if (composeWorkspaces.length === 1) {
|
|
4466
4808
|
return composeWorkspaces[0].version;
|
|
@@ -4471,6 +4813,44 @@ var ReleaseParams = class {
|
|
|
4471
4813
|
timestamp: Date.now()
|
|
4472
4814
|
});
|
|
4473
4815
|
}
|
|
4816
|
+
/**
|
|
4817
|
+
* Generates branch and tag parameters for the release
|
|
4818
|
+
*
|
|
4819
|
+
* Combines the generation of branch name and tag name into
|
|
4820
|
+
* a single operation. Handles both single and multi-package
|
|
4821
|
+
* releases appropriately.
|
|
4822
|
+
*
|
|
4823
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
4824
|
+
* @param shared - Shared configuration
|
|
4825
|
+
* @returns Object containing tag name and branch name
|
|
4826
|
+
*
|
|
4827
|
+
* @example Single package
|
|
4828
|
+
* ```typescript
|
|
4829
|
+
* const params = releaseParams.getReleaseBranchParams(
|
|
4830
|
+
* [{ name: 'pkg-a', version: '1.0.0' }],
|
|
4831
|
+
* { branchName: 'release-${tagName}' }
|
|
4832
|
+
* );
|
|
4833
|
+
* // {
|
|
4834
|
+
* // tagName: '1.0.0',
|
|
4835
|
+
* // releaseBranch: 'release-1.0.0'
|
|
4836
|
+
* // }
|
|
4837
|
+
* ```
|
|
4838
|
+
*
|
|
4839
|
+
* @example Multiple packages
|
|
4840
|
+
* ```typescript
|
|
4841
|
+
* const params = releaseParams.getReleaseBranchParams(
|
|
4842
|
+
* [
|
|
4843
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
4844
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
4845
|
+
* ],
|
|
4846
|
+
* {}
|
|
4847
|
+
* );
|
|
4848
|
+
* // {
|
|
4849
|
+
* // tagName: 'batch-2-packages-1234567890',
|
|
4850
|
+
* // releaseBranch: 'batch-pkg-a@1.0.0_pkg-b@2.0.0-2-packages-1234567890'
|
|
4851
|
+
* // }
|
|
4852
|
+
* ```
|
|
4853
|
+
*/
|
|
4474
4854
|
getReleaseBranchParams(composeWorkspaces, shared) {
|
|
4475
4855
|
const releaseTagName = this.getReleaseTagName(composeWorkspaces);
|
|
4476
4856
|
const releaseName = this.getReleaseName(composeWorkspaces);
|
|
@@ -4485,6 +4865,50 @@ var ReleaseParams = class {
|
|
|
4485
4865
|
releaseBranch: releaseBranchName
|
|
4486
4866
|
};
|
|
4487
4867
|
}
|
|
4868
|
+
/**
|
|
4869
|
+
* Generates a title for the release pull request
|
|
4870
|
+
*
|
|
4871
|
+
* Uses the configured PR title template or falls back to the default.
|
|
4872
|
+
* Supports variable interpolation with release parameters and context.
|
|
4873
|
+
*
|
|
4874
|
+
* Template Variables:
|
|
4875
|
+
* - ${tagName}: Release tag name
|
|
4876
|
+
* - ${pkgName}: Package/branch name
|
|
4877
|
+
* - All template context properties
|
|
4878
|
+
*
|
|
4879
|
+
* @param releaseBranchParams - Release branch parameters
|
|
4880
|
+
* @param context - Template context for variable interpolation
|
|
4881
|
+
* @returns Formatted PR title
|
|
4882
|
+
*
|
|
4883
|
+
* @example
|
|
4884
|
+
* ```typescript
|
|
4885
|
+
* // With default template
|
|
4886
|
+
* const title = params.getPRTitle(
|
|
4887
|
+
* {
|
|
4888
|
+
* tagName: '1.0.0',
|
|
4889
|
+
* releaseBranch: 'release-1.0.0'
|
|
4890
|
+
* },
|
|
4891
|
+
* {
|
|
4892
|
+
* env: 'production',
|
|
4893
|
+
* pkgName: 'my-package'
|
|
4894
|
+
* }
|
|
4895
|
+
* );
|
|
4896
|
+
* // 'Release production my-package 1.0.0'
|
|
4897
|
+
*
|
|
4898
|
+
* // With custom template
|
|
4899
|
+
* const title = params.getPRTitle(
|
|
4900
|
+
* {
|
|
4901
|
+
* tagName: '1.0.0',
|
|
4902
|
+
* releaseBranch: 'release-1.0.0'
|
|
4903
|
+
* },
|
|
4904
|
+
* {
|
|
4905
|
+
* env: 'staging',
|
|
4906
|
+
* pkgName: 'my-package'
|
|
4907
|
+
* }
|
|
4908
|
+
* );
|
|
4909
|
+
* // Custom formatted title
|
|
4910
|
+
* ```
|
|
4911
|
+
*/
|
|
4488
4912
|
getPRTitle(releaseBranchParams, context) {
|
|
4489
4913
|
const prTitleTpl = this.config.PRTitle || DEFAULT_PR_TITLE;
|
|
4490
4914
|
return import_scripts_context2.Shell.format(prTitleTpl, {
|
|
@@ -4494,10 +4918,67 @@ var ReleaseParams = class {
|
|
|
4494
4918
|
});
|
|
4495
4919
|
}
|
|
4496
4920
|
/**
|
|
4497
|
-
*
|
|
4921
|
+
* Generates the body content for the release pull request
|
|
4922
|
+
*
|
|
4923
|
+
* Handles both single and multi-package releases, combining
|
|
4924
|
+
* changelogs appropriately. For batch releases, formats each
|
|
4925
|
+
* package's changelog according to the batch template.
|
|
4926
|
+
*
|
|
4927
|
+
* Template Variables:
|
|
4928
|
+
* - ${tagName}: Release tag or combined workspace versions
|
|
4929
|
+
* - ${changelog}: Single changelog or combined batch changelogs
|
|
4930
|
+
* - All template context properties
|
|
4931
|
+
*
|
|
4932
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
4933
|
+
* @param releaseBranchParams - Release branch parameters
|
|
4934
|
+
* @param context - Template context for variable interpolation
|
|
4935
|
+
* @returns Formatted PR body content
|
|
4498
4936
|
*
|
|
4499
|
-
* @
|
|
4500
|
-
*
|
|
4937
|
+
* @example Single package
|
|
4938
|
+
* ```typescript
|
|
4939
|
+
* const body = params.getPRBody(
|
|
4940
|
+
* [{
|
|
4941
|
+
* name: 'pkg-a',
|
|
4942
|
+
* version: '1.0.0',
|
|
4943
|
+
* changelog: '- Feature: New functionality\n- Fix: Bug fix'
|
|
4944
|
+
* }],
|
|
4945
|
+
* {
|
|
4946
|
+
* tagName: '1.0.0',
|
|
4947
|
+
* releaseBranch: 'release-1.0.0'
|
|
4948
|
+
* },
|
|
4949
|
+
* context
|
|
4950
|
+
* );
|
|
4951
|
+
* // Custom formatted body with single changelog
|
|
4952
|
+
* ```
|
|
4953
|
+
*
|
|
4954
|
+
* @example Multiple packages
|
|
4955
|
+
* ```typescript
|
|
4956
|
+
* const body = params.getPRBody(
|
|
4957
|
+
* [
|
|
4958
|
+
* {
|
|
4959
|
+
* name: 'pkg-a',
|
|
4960
|
+
* version: '1.0.0',
|
|
4961
|
+
* changelog: '- Feature: Package A changes'
|
|
4962
|
+
* },
|
|
4963
|
+
* {
|
|
4964
|
+
* name: 'pkg-b',
|
|
4965
|
+
* version: '2.0.0',
|
|
4966
|
+
* changelog: '- Feature: Package B changes'
|
|
4967
|
+
* }
|
|
4968
|
+
* ],
|
|
4969
|
+
* {
|
|
4970
|
+
* tagName: 'batch-2-packages-1234567890',
|
|
4971
|
+
* releaseBranch: 'batch-release'
|
|
4972
|
+
* },
|
|
4973
|
+
* context
|
|
4974
|
+
* );
|
|
4975
|
+
* // Formatted body with combined changelogs:
|
|
4976
|
+
* // ## pkg-a 1.0.0
|
|
4977
|
+
* // - Feature: Package A changes
|
|
4978
|
+
* //
|
|
4979
|
+
* // ## pkg-b 2.0.0
|
|
4980
|
+
* // - Feature: Package B changes
|
|
4981
|
+
* ```
|
|
4501
4982
|
*/
|
|
4502
4983
|
getPRBody(composeWorkspaces, releaseBranchParams, context) {
|
|
4503
4984
|
const PRBodyTpl = this.config.PRBody;
|
|
@@ -4523,10 +5004,36 @@ var ReleaseParams = class {
|
|
|
4523
5004
|
var import_scripts_context3 = require("@qlover/scripts-context");
|
|
4524
5005
|
var import_rest = require("@octokit/rest");
|
|
4525
5006
|
var GithubManager = class {
|
|
5007
|
+
/**
|
|
5008
|
+
* Creates a new GithubManager instance
|
|
5009
|
+
*
|
|
5010
|
+
* @param context - Release context containing configuration
|
|
5011
|
+
*
|
|
5012
|
+
* @example
|
|
5013
|
+
* ```typescript
|
|
5014
|
+
* const manager = new GithubManager(context);
|
|
5015
|
+
* ```
|
|
5016
|
+
*/
|
|
4526
5017
|
constructor(context) {
|
|
4527
5018
|
this.context = context;
|
|
4528
5019
|
}
|
|
5020
|
+
/** Lazy-loaded Octokit instance */
|
|
4529
5021
|
_octokit = null;
|
|
5022
|
+
/**
|
|
5023
|
+
* Gets GitHub repository information
|
|
5024
|
+
*
|
|
5025
|
+
* Retrieves the owner and repository name from the context.
|
|
5026
|
+
* This information is required for most GitHub API operations.
|
|
5027
|
+
*
|
|
5028
|
+
* @returns Repository owner and name
|
|
5029
|
+
* @throws Error if owner or repo name is not set
|
|
5030
|
+
*
|
|
5031
|
+
* @example
|
|
5032
|
+
* ```typescript
|
|
5033
|
+
* const info = manager.getGitHubUserInfo();
|
|
5034
|
+
* // { owner: 'org-name', repo: 'repo-name' }
|
|
5035
|
+
* ```
|
|
5036
|
+
*/
|
|
4530
5037
|
getGitHubUserInfo() {
|
|
4531
5038
|
const { authorName, repoName } = this.context.getOptions();
|
|
4532
5039
|
if (!authorName || !repoName) {
|
|
@@ -4537,6 +5044,28 @@ var GithubManager = class {
|
|
|
4537
5044
|
repo: repoName
|
|
4538
5045
|
};
|
|
4539
5046
|
}
|
|
5047
|
+
/**
|
|
5048
|
+
* Gets GitHub API token
|
|
5049
|
+
*
|
|
5050
|
+
* Retrieves the GitHub API token from environment variables.
|
|
5051
|
+
* The token name can be configured via the tokenRef option.
|
|
5052
|
+
*
|
|
5053
|
+
* @returns GitHub API token
|
|
5054
|
+
* @throws Error if token is not set
|
|
5055
|
+
*
|
|
5056
|
+
* @example Default token
|
|
5057
|
+
* ```typescript
|
|
5058
|
+
* const token = manager.getToken();
|
|
5059
|
+
* // Uses GITHUB_TOKEN env var
|
|
5060
|
+
* ```
|
|
5061
|
+
*
|
|
5062
|
+
* @example Custom token
|
|
5063
|
+
* ```typescript
|
|
5064
|
+
* context.options.githubPR.tokenRef = 'CUSTOM_TOKEN';
|
|
5065
|
+
* const token = manager.getToken();
|
|
5066
|
+
* // Uses CUSTOM_TOKEN env var
|
|
5067
|
+
* ```
|
|
5068
|
+
*/
|
|
4540
5069
|
getToken() {
|
|
4541
5070
|
const { tokenRef = "GITHUB_TOKEN" } = this.context.getOptions("githubPR");
|
|
4542
5071
|
const token = this.context.env.get(tokenRef);
|
|
@@ -4547,6 +5076,24 @@ var GithubManager = class {
|
|
|
4547
5076
|
}
|
|
4548
5077
|
return token;
|
|
4549
5078
|
}
|
|
5079
|
+
/**
|
|
5080
|
+
* Gets Octokit instance
|
|
5081
|
+
*
|
|
5082
|
+
* Lazily initializes and returns an Octokit instance configured
|
|
5083
|
+
* with the GitHub token and timeout settings.
|
|
5084
|
+
*
|
|
5085
|
+
* @returns Configured Octokit instance
|
|
5086
|
+
* @throws Error if token retrieval fails
|
|
5087
|
+
*
|
|
5088
|
+
* @example
|
|
5089
|
+
* ```typescript
|
|
5090
|
+
* const octokit = manager.octokit;
|
|
5091
|
+
* await octokit.rest.issues.create({
|
|
5092
|
+
* ...manager.getGitHubUserInfo(),
|
|
5093
|
+
* title: 'Issue title'
|
|
5094
|
+
* });
|
|
5095
|
+
* ```
|
|
5096
|
+
*/
|
|
4550
5097
|
get octokit() {
|
|
4551
5098
|
if (this._octokit) {
|
|
4552
5099
|
return this._octokit;
|
|
@@ -4561,9 +5108,37 @@ var GithubManager = class {
|
|
|
4561
5108
|
this._octokit = new import_rest.Octokit(options);
|
|
4562
5109
|
return this._octokit;
|
|
4563
5110
|
}
|
|
5111
|
+
/**
|
|
5112
|
+
* Gets logger instance
|
|
5113
|
+
*
|
|
5114
|
+
* Provides access to the context's logger for consistent
|
|
5115
|
+
* logging across the manager.
|
|
5116
|
+
*
|
|
5117
|
+
* @returns Logger instance
|
|
5118
|
+
*
|
|
5119
|
+
* @example
|
|
5120
|
+
* ```typescript
|
|
5121
|
+
* manager.logger.info('Creating release...');
|
|
5122
|
+
* manager.logger.debug('API response:', response);
|
|
5123
|
+
* ```
|
|
5124
|
+
*/
|
|
4564
5125
|
get logger() {
|
|
4565
5126
|
return this.context.logger;
|
|
4566
5127
|
}
|
|
5128
|
+
/**
|
|
5129
|
+
* Gets shell interface
|
|
5130
|
+
*
|
|
5131
|
+
* Provides access to the context's shell interface for
|
|
5132
|
+
* executing Git commands and other shell operations.
|
|
5133
|
+
*
|
|
5134
|
+
* @returns Shell interface
|
|
5135
|
+
*
|
|
5136
|
+
* @example
|
|
5137
|
+
* ```typescript
|
|
5138
|
+
* await manager.shell.exec('git fetch origin');
|
|
5139
|
+
* await manager.shell.exec(['git', 'push', 'origin', 'main']);
|
|
5140
|
+
* ```
|
|
5141
|
+
*/
|
|
4567
5142
|
get shell() {
|
|
4568
5143
|
return this.context.shell;
|
|
4569
5144
|
}
|
|
@@ -4572,6 +5147,23 @@ var GithubManager = class {
|
|
|
4572
5147
|
*
|
|
4573
5148
|
* @default `squash`
|
|
4574
5149
|
*/
|
|
5150
|
+
/**
|
|
5151
|
+
* Gets auto-merge type for pull requests
|
|
5152
|
+
*
|
|
5153
|
+
* Determines how pull requests should be merged when
|
|
5154
|
+
* auto-merge is enabled. Defaults to 'squash'.
|
|
5155
|
+
*
|
|
5156
|
+
* @returns Auto-merge type ('merge', 'squash', or 'rebase')
|
|
5157
|
+
*
|
|
5158
|
+
* @example
|
|
5159
|
+
* ```typescript
|
|
5160
|
+
* const mergeType = manager.autoMergeType;
|
|
5161
|
+
* // 'squash' (default)
|
|
5162
|
+
*
|
|
5163
|
+
* context.options.autoMergeType = 'rebase';
|
|
5164
|
+
* manager.autoMergeType; // 'rebase'
|
|
5165
|
+
* ```
|
|
5166
|
+
*/
|
|
4575
5167
|
get autoMergeType() {
|
|
4576
5168
|
return this.context.getOptions().autoMergeType || DEFAULT_AUTO_MERGE_TYPE;
|
|
4577
5169
|
}
|
|
@@ -4580,6 +5172,25 @@ var GithubManager = class {
|
|
|
4580
5172
|
*
|
|
4581
5173
|
* @default `999999`
|
|
4582
5174
|
*/
|
|
5175
|
+
/**
|
|
5176
|
+
* Gets pull request number for dry runs
|
|
5177
|
+
*
|
|
5178
|
+
* Returns a placeholder PR number when running in dry-run mode.
|
|
5179
|
+
* This allows testing PR-related functionality without creating
|
|
5180
|
+
* actual pull requests.
|
|
5181
|
+
*
|
|
5182
|
+
* @returns Dry run PR number (default: '999999')
|
|
5183
|
+
*
|
|
5184
|
+
* @example
|
|
5185
|
+
* ```typescript
|
|
5186
|
+
* context.dryRun = true;
|
|
5187
|
+
* const prNumber = manager.dryRunPRNumber;
|
|
5188
|
+
* // '999999'
|
|
5189
|
+
*
|
|
5190
|
+
* context.options.githubPR.dryRunPRNumber = '123456';
|
|
5191
|
+
* manager.dryRunPRNumber; // '123456'
|
|
5192
|
+
* ```
|
|
5193
|
+
*/
|
|
4583
5194
|
get dryRunPRNumber() {
|
|
4584
5195
|
return this.context.getOptions("githubPR.dryRunPRNumber", "999999");
|
|
4585
5196
|
}
|
|
@@ -4588,6 +5199,23 @@ var GithubManager = class {
|
|
|
4588
5199
|
*
|
|
4589
5200
|
* @default `false`
|
|
4590
5201
|
*/
|
|
5202
|
+
/**
|
|
5203
|
+
* Gets auto-merge setting for release PRs
|
|
5204
|
+
*
|
|
5205
|
+
* Determines whether release pull requests should be
|
|
5206
|
+
* automatically merged after creation. Defaults to false.
|
|
5207
|
+
*
|
|
5208
|
+
* @returns True if auto-merge is enabled
|
|
5209
|
+
*
|
|
5210
|
+
* @example
|
|
5211
|
+
* ```typescript
|
|
5212
|
+
* const autoMerge = manager.autoMergeReleasePR;
|
|
5213
|
+
* // false (default)
|
|
5214
|
+
*
|
|
5215
|
+
* context.options.autoMergeReleasePR = true;
|
|
5216
|
+
* manager.autoMergeReleasePR; // true
|
|
5217
|
+
* ```
|
|
5218
|
+
*/
|
|
4591
5219
|
get autoMergeReleasePR() {
|
|
4592
5220
|
return this.context.getOptions("autoMergeReleasePR") || DEFAULT_AUTO_MERGE_RELEASE_PR;
|
|
4593
5221
|
}
|
|
@@ -4597,6 +5225,30 @@ var GithubManager = class {
|
|
|
4597
5225
|
* @param prNumber - The pull request number to merge.
|
|
4598
5226
|
* @param releaseBranch - The branch to merge into.
|
|
4599
5227
|
*/
|
|
5228
|
+
/**
|
|
5229
|
+
* Merges a pull request
|
|
5230
|
+
*
|
|
5231
|
+
* Merges the specified pull request using the configured
|
|
5232
|
+
* merge method. In dry-run mode, logs the merge action
|
|
5233
|
+
* without performing it.
|
|
5234
|
+
*
|
|
5235
|
+
* @param prNumber - Pull request number
|
|
5236
|
+
* @param releaseBranch - Branch to merge
|
|
5237
|
+
* @throws Error if merge fails
|
|
5238
|
+
*
|
|
5239
|
+
* @example Basic merge
|
|
5240
|
+
* ```typescript
|
|
5241
|
+
* await manager.mergePR('123', 'release-1.0.0');
|
|
5242
|
+
* // Merges PR #123 using configured merge method
|
|
5243
|
+
* ```
|
|
5244
|
+
*
|
|
5245
|
+
* @example Dry run
|
|
5246
|
+
* ```typescript
|
|
5247
|
+
* context.dryRun = true;
|
|
5248
|
+
* await manager.mergePR('123', 'release-1.0.0');
|
|
5249
|
+
* // Logs merge action without performing it
|
|
5250
|
+
* ```
|
|
5251
|
+
*/
|
|
4600
5252
|
async mergePR(prNumber, releaseBranch) {
|
|
4601
5253
|
if (!prNumber) {
|
|
4602
5254
|
this.logger.error("Failed to create Pull Request.", prNumber);
|
|
@@ -4616,6 +5268,24 @@ var GithubManager = class {
|
|
|
4616
5268
|
merge_method: mergeMethod
|
|
4617
5269
|
});
|
|
4618
5270
|
}
|
|
5271
|
+
/**
|
|
5272
|
+
* Gets commits from a pull request
|
|
5273
|
+
*
|
|
5274
|
+
* Retrieves all commits associated with the specified pull request.
|
|
5275
|
+
* Useful for generating changelogs or analyzing changes.
|
|
5276
|
+
*
|
|
5277
|
+
* @param prNumber - Pull request number
|
|
5278
|
+
* @returns Promise resolving to array of commit information
|
|
5279
|
+
* @throws Error if request fails
|
|
5280
|
+
*
|
|
5281
|
+
* @example
|
|
5282
|
+
* ```typescript
|
|
5283
|
+
* const commits = await manager.getPullRequestCommits(123);
|
|
5284
|
+
* commits.forEach(commit => {
|
|
5285
|
+
* console.log(commit.sha, commit.commit.message);
|
|
5286
|
+
* });
|
|
5287
|
+
* ```
|
|
5288
|
+
*/
|
|
4619
5289
|
async getPullRequestCommits(prNumber) {
|
|
4620
5290
|
const pr = await this.octokit.rest.pulls.listCommits({
|
|
4621
5291
|
...this.getGitHubUserInfo(),
|
|
@@ -4623,6 +5293,23 @@ var GithubManager = class {
|
|
|
4623
5293
|
});
|
|
4624
5294
|
return pr.data;
|
|
4625
5295
|
}
|
|
5296
|
+
/**
|
|
5297
|
+
* Gets detailed information about a commit
|
|
5298
|
+
*
|
|
5299
|
+
* Retrieves detailed information about a specific commit,
|
|
5300
|
+
* including files changed, author details, and commit message.
|
|
5301
|
+
*
|
|
5302
|
+
* @param commitSha - Commit SHA
|
|
5303
|
+
* @returns Promise resolving to commit information
|
|
5304
|
+
* @throws Error if request fails
|
|
5305
|
+
*
|
|
5306
|
+
* @example
|
|
5307
|
+
* ```typescript
|
|
5308
|
+
* const info = await manager.getCommitInfo('abc123');
|
|
5309
|
+
* console.log(info.commit.message);
|
|
5310
|
+
* console.log(info.files.map(f => f.filename));
|
|
5311
|
+
* ```
|
|
5312
|
+
*/
|
|
4626
5313
|
async getCommitInfo(commitSha) {
|
|
4627
5314
|
const pr = await this.octokit.rest.repos.getCommit({
|
|
4628
5315
|
...this.getGitHubUserInfo(),
|
|
@@ -4630,6 +5317,24 @@ var GithubManager = class {
|
|
|
4630
5317
|
});
|
|
4631
5318
|
return pr.data;
|
|
4632
5319
|
}
|
|
5320
|
+
/**
|
|
5321
|
+
* Gets pull request information
|
|
5322
|
+
*
|
|
5323
|
+
* Retrieves detailed information about a pull request,
|
|
5324
|
+
* including title, body, labels, and review status.
|
|
5325
|
+
*
|
|
5326
|
+
* @param prNumber - Pull request number
|
|
5327
|
+
* @returns Promise resolving to pull request information
|
|
5328
|
+
* @throws Error if request fails
|
|
5329
|
+
*
|
|
5330
|
+
* @example
|
|
5331
|
+
* ```typescript
|
|
5332
|
+
* const pr = await manager.getPullRequest(123);
|
|
5333
|
+
* console.log(pr.title);
|
|
5334
|
+
* console.log(pr.labels.map(l => l.name));
|
|
5335
|
+
* console.log(pr.mergeable_state);
|
|
5336
|
+
* ```
|
|
5337
|
+
*/
|
|
4633
5338
|
async getPullRequest(prNumber) {
|
|
4634
5339
|
const pr = await this.octokit.rest.pulls.get({
|
|
4635
5340
|
...this.getGitHubUserInfo(),
|
|
@@ -4643,6 +5348,27 @@ var GithubManager = class {
|
|
|
4643
5348
|
* @param prNumber - The pull request number to check.
|
|
4644
5349
|
* @param releaseBranch - The branch to check against.
|
|
4645
5350
|
*/
|
|
5351
|
+
/**
|
|
5352
|
+
* Checks pull request status and cleans up
|
|
5353
|
+
*
|
|
5354
|
+
* Verifies pull request status and deletes the release branch
|
|
5355
|
+
* if the PR has been merged. Used for post-merge cleanup.
|
|
5356
|
+
*
|
|
5357
|
+
* Process:
|
|
5358
|
+
* 1. Verify PR exists and status
|
|
5359
|
+
* 2. Delete release branch if PR merged
|
|
5360
|
+
* 3. Log cleanup results
|
|
5361
|
+
*
|
|
5362
|
+
* @param prNumber - Pull request number
|
|
5363
|
+
* @param releaseBranch - Branch to clean up
|
|
5364
|
+
* @throws Error if verification or cleanup fails
|
|
5365
|
+
*
|
|
5366
|
+
* @example
|
|
5367
|
+
* ```typescript
|
|
5368
|
+
* await manager.checkedPR('123', 'release-1.0.0');
|
|
5369
|
+
* // Verifies PR #123 and deletes release-1.0.0 if merged
|
|
5370
|
+
* ```
|
|
5371
|
+
*/
|
|
4646
5372
|
async checkedPR(prNumber, releaseBranch) {
|
|
4647
5373
|
try {
|
|
4648
5374
|
await this.getPullRequest(Number(prNumber));
|
|
@@ -4743,10 +5469,55 @@ var GithubManager = class {
|
|
|
4743
5469
|
throw error;
|
|
4744
5470
|
}
|
|
4745
5471
|
}
|
|
5472
|
+
/**
|
|
5473
|
+
* Truncates long PR/release body text
|
|
5474
|
+
*
|
|
5475
|
+
* GitHub has a limit on PR and release body length.
|
|
5476
|
+
* This method ensures the text stays within limits by
|
|
5477
|
+
* truncating if necessary.
|
|
5478
|
+
*
|
|
5479
|
+
* @param body - Body text to truncate
|
|
5480
|
+
* @returns Truncated text (if > 124000 chars)
|
|
5481
|
+
*
|
|
5482
|
+
* @example
|
|
5483
|
+
* ```typescript
|
|
5484
|
+
* const body = manager.truncateBody(veryLongText);
|
|
5485
|
+
* // Returns truncated text if > 124000 chars
|
|
5486
|
+
* // Adds '...' to indicate truncation
|
|
5487
|
+
* ```
|
|
5488
|
+
* @private
|
|
5489
|
+
*/
|
|
4746
5490
|
truncateBody(body) {
|
|
4747
5491
|
if (body && body.length >= 124e3) return body.substring(0, 124e3) + "...";
|
|
4748
5492
|
return body;
|
|
4749
5493
|
}
|
|
5494
|
+
/**
|
|
5495
|
+
* Builds GitHub release options
|
|
5496
|
+
*
|
|
5497
|
+
* Combines default release options with provided overrides
|
|
5498
|
+
* and context configuration. Handles formatting of release
|
|
5499
|
+
* name, body, and other settings.
|
|
5500
|
+
*
|
|
5501
|
+
* @param options - Override options for release
|
|
5502
|
+
* @returns Complete release options
|
|
5503
|
+
*
|
|
5504
|
+
* @example
|
|
5505
|
+
* ```typescript
|
|
5506
|
+
* const opts = manager.getOctokitReleaseOptions({
|
|
5507
|
+
* tag_name: 'v1.0.0',
|
|
5508
|
+
* body: 'Release notes...'
|
|
5509
|
+
* });
|
|
5510
|
+
* // Returns merged options with defaults:
|
|
5511
|
+
* // {
|
|
5512
|
+
* // name: 'Release v1.0.0',
|
|
5513
|
+
* // body: 'Release notes...',
|
|
5514
|
+
* // draft: false,
|
|
5515
|
+
* // prerelease: false,
|
|
5516
|
+
* // ...
|
|
5517
|
+
* // }
|
|
5518
|
+
* ```
|
|
5519
|
+
* @private
|
|
5520
|
+
*/
|
|
4750
5521
|
getOctokitReleaseOptions(options) {
|
|
4751
5522
|
const {
|
|
4752
5523
|
releaseName,
|
|
@@ -4772,6 +5543,37 @@ var GithubManager = class {
|
|
|
4772
5543
|
...this.getGitHubUserInfo()
|
|
4773
5544
|
};
|
|
4774
5545
|
}
|
|
5546
|
+
/**
|
|
5547
|
+
* Creates a GitHub release
|
|
5548
|
+
*
|
|
5549
|
+
* Creates a new GitHub release for a workspace with:
|
|
5550
|
+
* - Formatted release name
|
|
5551
|
+
* - Changelog as release notes
|
|
5552
|
+
* - Proper tag
|
|
5553
|
+
* - Configurable settings (draft, prerelease, etc.)
|
|
5554
|
+
*
|
|
5555
|
+
* Handles dry run mode and error cases gracefully.
|
|
5556
|
+
*
|
|
5557
|
+
* @param workspace - Workspace to create release for
|
|
5558
|
+
* @throws Error if tag name is missing or creation fails
|
|
5559
|
+
*
|
|
5560
|
+
* @example Basic release
|
|
5561
|
+
* ```typescript
|
|
5562
|
+
* await manager.createRelease({
|
|
5563
|
+
* name: 'pkg-a',
|
|
5564
|
+
* version: '1.0.0',
|
|
5565
|
+
* tagName: 'v1.0.0',
|
|
5566
|
+
* changelog: '...'
|
|
5567
|
+
* });
|
|
5568
|
+
* ```
|
|
5569
|
+
*
|
|
5570
|
+
* @example Dry run
|
|
5571
|
+
* ```typescript
|
|
5572
|
+
* context.dryRun = true;
|
|
5573
|
+
* await manager.createRelease(workspace);
|
|
5574
|
+
* // Logs release info without creating
|
|
5575
|
+
* ```
|
|
5576
|
+
*/
|
|
4775
5577
|
async createRelease(workspace) {
|
|
4776
5578
|
const meragedOptions = this.getOctokitReleaseOptions({
|
|
4777
5579
|
tag_name: workspace.tagName,
|
|
@@ -4811,6 +5613,30 @@ var GithubManager = class {
|
|
|
4811
5613
|
var import_isString = __toESM(require_isString(), 1);
|
|
4812
5614
|
var import_scripts_context4 = require("@qlover/scripts-context");
|
|
4813
5615
|
var GitBase = class extends import_scripts_context4.ScriptPlugin {
|
|
5616
|
+
/**
|
|
5617
|
+
* Plugin initialization hook
|
|
5618
|
+
*
|
|
5619
|
+
* Runs before plugin execution to set up repository context:
|
|
5620
|
+
* 1. Retrieves repository information
|
|
5621
|
+
* 2. Gets current branch
|
|
5622
|
+
* 3. Switches to current branch if needed
|
|
5623
|
+
* 4. Updates context with repository info
|
|
5624
|
+
*
|
|
5625
|
+
* @throws Error if repository information cannot be retrieved
|
|
5626
|
+
*
|
|
5627
|
+
* @example
|
|
5628
|
+
* ```typescript
|
|
5629
|
+
* class MyPlugin extends GitBase<GitBaseProps> {
|
|
5630
|
+
* async onExec() {
|
|
5631
|
+
* // onBefore has already:
|
|
5632
|
+
* // - Set up repository info
|
|
5633
|
+
* // - Switched to correct branch
|
|
5634
|
+
* // - Updated context
|
|
5635
|
+
* await this.doSomething();
|
|
5636
|
+
* }
|
|
5637
|
+
* }
|
|
5638
|
+
* ```
|
|
5639
|
+
*/
|
|
4814
5640
|
async onBefore() {
|
|
4815
5641
|
const repoInfo = await this.getUserInfo();
|
|
4816
5642
|
if (!repoInfo) {
|
|
@@ -4831,12 +5657,44 @@ var GitBase = class extends import_scripts_context4.ScriptPlugin {
|
|
|
4831
5657
|
currentBranch
|
|
4832
5658
|
});
|
|
4833
5659
|
}
|
|
5660
|
+
/**
|
|
5661
|
+
* Gets the current Git branch name
|
|
5662
|
+
*
|
|
5663
|
+
* Retrieves the name of the currently checked out Git branch.
|
|
5664
|
+
* Includes a small delay to ensure Git's internal state is updated.
|
|
5665
|
+
*
|
|
5666
|
+
* @returns Promise resolving to branch name
|
|
5667
|
+
* @throws Error if branch name cannot be retrieved
|
|
5668
|
+
*
|
|
5669
|
+
* @example
|
|
5670
|
+
* ```typescript
|
|
5671
|
+
* const branch = await plugin.getCurrentBranch();
|
|
5672
|
+
* // 'main' or 'feature/new-feature'
|
|
5673
|
+
* ```
|
|
5674
|
+
*/
|
|
4834
5675
|
async getCurrentBranch() {
|
|
4835
5676
|
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
4836
5677
|
return this.context.shell.exec("git rev-parse --abbrev-ref HEAD", {
|
|
4837
5678
|
dryRun: false
|
|
4838
5679
|
});
|
|
4839
5680
|
}
|
|
5681
|
+
/**
|
|
5682
|
+
* Gets the Git remote URL
|
|
5683
|
+
*
|
|
5684
|
+
* Retrieves the URL of the 'origin' remote from Git configuration.
|
|
5685
|
+
* This URL is used to identify the GitHub repository.
|
|
5686
|
+
*
|
|
5687
|
+
* @returns Promise resolving to remote URL
|
|
5688
|
+
* @throws Error if remote URL cannot be retrieved
|
|
5689
|
+
*
|
|
5690
|
+
* @example
|
|
5691
|
+
* ```typescript
|
|
5692
|
+
* const url = await plugin.getRemoteUrl();
|
|
5693
|
+
* // 'https://github.com/org/repo.git'
|
|
5694
|
+
* // or
|
|
5695
|
+
* // 'git@github.com:org/repo.git'
|
|
5696
|
+
* ```
|
|
5697
|
+
*/
|
|
4840
5698
|
async getRemoteUrl() {
|
|
4841
5699
|
return (await this.context.shell.exec("git config --get remote.origin.url", {
|
|
4842
5700
|
dryRun: false
|
|
@@ -4890,9 +5748,53 @@ var GitBase = class extends import_scripts_context4.ScriptPlugin {
|
|
|
4890
5748
|
* @param value - The value to check.
|
|
4891
5749
|
* @returns True if the value is a valid string, otherwise false.
|
|
4892
5750
|
*/
|
|
5751
|
+
/**
|
|
5752
|
+
* Type guard for valid string values
|
|
5753
|
+
*
|
|
5754
|
+
* Checks if a value is a non-empty string. Used for validating
|
|
5755
|
+
* repository information and other string inputs.
|
|
5756
|
+
*
|
|
5757
|
+
* @param value - Value to check
|
|
5758
|
+
* @returns True if value is a non-empty string
|
|
5759
|
+
*
|
|
5760
|
+
* @example
|
|
5761
|
+
* ```typescript
|
|
5762
|
+
* if (plugin.isValidString(value)) {
|
|
5763
|
+
* // value is definitely a non-empty string
|
|
5764
|
+
* console.log(value.toUpperCase());
|
|
5765
|
+
* }
|
|
5766
|
+
* ```
|
|
5767
|
+
*/
|
|
4893
5768
|
isValidString(value) {
|
|
4894
5769
|
return !!value && (0, import_isString.default)(value);
|
|
4895
5770
|
}
|
|
5771
|
+
/**
|
|
5772
|
+
* Creates a Git commit
|
|
5773
|
+
*
|
|
5774
|
+
* Creates a new Git commit with the specified message and optional
|
|
5775
|
+
* additional arguments. The message is automatically JSON-stringified
|
|
5776
|
+
* to handle special characters properly.
|
|
5777
|
+
*
|
|
5778
|
+
* @param message - Commit message
|
|
5779
|
+
* @param args - Additional Git commit arguments
|
|
5780
|
+
* @returns Promise resolving to command output
|
|
5781
|
+
*
|
|
5782
|
+
* @example Basic commit
|
|
5783
|
+
* ```typescript
|
|
5784
|
+
* await plugin.commit('feat: add new feature');
|
|
5785
|
+
* ```
|
|
5786
|
+
*
|
|
5787
|
+
* @example Commit with arguments
|
|
5788
|
+
* ```typescript
|
|
5789
|
+
* await plugin.commit('fix: update deps', ['--no-verify']);
|
|
5790
|
+
* ```
|
|
5791
|
+
*
|
|
5792
|
+
* @example Commit with special characters
|
|
5793
|
+
* ```typescript
|
|
5794
|
+
* await plugin.commit('fix: handle "quotes" & symbols');
|
|
5795
|
+
* // Message is automatically escaped
|
|
5796
|
+
* ```
|
|
5797
|
+
*/
|
|
4896
5798
|
commit(message, args = []) {
|
|
4897
5799
|
return this.context.shell.exec([
|
|
4898
5800
|
"git",
|
|
@@ -4927,14 +5829,50 @@ var CHANGELOG_ALL_FIELDS = [
|
|
|
4927
5829
|
"tag"
|
|
4928
5830
|
];
|
|
4929
5831
|
var GitChangelog = class {
|
|
5832
|
+
/**
|
|
5833
|
+
* Creates a new GitChangelog instance
|
|
5834
|
+
*
|
|
5835
|
+
* @param options - Configuration options including shell and logger
|
|
5836
|
+
*
|
|
5837
|
+
* @example
|
|
5838
|
+
* ```typescript
|
|
5839
|
+
* const changelog = new GitChangelog({
|
|
5840
|
+
* shell: new Shell(),
|
|
5841
|
+
* logger: new Logger(),
|
|
5842
|
+
* directory: 'packages/my-pkg',
|
|
5843
|
+
* noMerges: true
|
|
5844
|
+
* });
|
|
5845
|
+
* ```
|
|
5846
|
+
*/
|
|
4930
5847
|
constructor(options) {
|
|
4931
5848
|
this.options = options;
|
|
4932
5849
|
}
|
|
4933
5850
|
/**
|
|
4934
|
-
*
|
|
5851
|
+
* Retrieves Git commit history with specified options
|
|
5852
|
+
*
|
|
5853
|
+
* Fetches commit information between specified tags or commits,
|
|
5854
|
+
* with support for filtering and field selection.
|
|
5855
|
+
*
|
|
5856
|
+
* @param options - Configuration options for Git log retrieval
|
|
5857
|
+
* @returns Array of commit objects with requested fields
|
|
4935
5858
|
*
|
|
4936
|
-
* @
|
|
4937
|
-
*
|
|
5859
|
+
* @example Basic usage
|
|
5860
|
+
* ```typescript
|
|
5861
|
+
* const commits = await changelog.getGitLog({
|
|
5862
|
+
* from: 'v1.0.0',
|
|
5863
|
+
* to: 'v2.0.0',
|
|
5864
|
+
* directory: 'packages/my-pkg',
|
|
5865
|
+
* noMerges: true
|
|
5866
|
+
* });
|
|
5867
|
+
* ```
|
|
5868
|
+
*
|
|
5869
|
+
* @example Custom fields
|
|
5870
|
+
* ```typescript
|
|
5871
|
+
* const commits = await changelog.getGitLog({
|
|
5872
|
+
* fields: ['hash', 'subject', 'authorName'],
|
|
5873
|
+
* directory: 'src'
|
|
5874
|
+
* });
|
|
5875
|
+
* ```
|
|
4938
5876
|
*/
|
|
4939
5877
|
async getGitLog(options = {}) {
|
|
4940
5878
|
const { directory, noMerges = true, fields } = options;
|
|
@@ -4955,6 +5893,38 @@ var GitChangelog = class {
|
|
|
4955
5893
|
this.options.logger?.debug("GitChangelog commits", commits);
|
|
4956
5894
|
return commits;
|
|
4957
5895
|
}
|
|
5896
|
+
/**
|
|
5897
|
+
* Retrieves and parses Git commits with metadata
|
|
5898
|
+
*
|
|
5899
|
+
* Gets commit history and enhances it with parsed conventional
|
|
5900
|
+
* commit information and PR metadata.
|
|
5901
|
+
*
|
|
5902
|
+
* @param options - Configuration options for Git log retrieval
|
|
5903
|
+
* @returns Array of enhanced commit objects with parsed metadata
|
|
5904
|
+
*
|
|
5905
|
+
* @example Basic usage
|
|
5906
|
+
* ```typescript
|
|
5907
|
+
* const commits = await changelog.getCommits({
|
|
5908
|
+
* from: 'v1.0.0',
|
|
5909
|
+
* to: 'v2.0.0'
|
|
5910
|
+
* });
|
|
5911
|
+
* // [
|
|
5912
|
+
* // {
|
|
5913
|
+
* // base: { hash: '...', subject: '...' },
|
|
5914
|
+
* // commitlint: { type: 'feat', scope: 'api', ... },
|
|
5915
|
+
* // commits: []
|
|
5916
|
+
* // }
|
|
5917
|
+
* // ]
|
|
5918
|
+
* ```
|
|
5919
|
+
*
|
|
5920
|
+
* @example Filtered commits
|
|
5921
|
+
* ```typescript
|
|
5922
|
+
* const commits = await changelog.getCommits({
|
|
5923
|
+
* directory: 'packages/my-pkg',
|
|
5924
|
+
* noMerges: true
|
|
5925
|
+
* });
|
|
5926
|
+
* ```
|
|
5927
|
+
*/
|
|
4958
5928
|
async getCommits(options) {
|
|
4959
5929
|
const gitCommits = await this.getGitLog(options);
|
|
4960
5930
|
return gitCommits.map((commit) => {
|
|
@@ -4967,6 +5937,28 @@ var GitChangelog = class {
|
|
|
4967
5937
|
};
|
|
4968
5938
|
});
|
|
4969
5939
|
}
|
|
5940
|
+
/**
|
|
5941
|
+
* Creates a base commit object from message and optional data
|
|
5942
|
+
*
|
|
5943
|
+
* Utility method to create a standardized commit object with
|
|
5944
|
+
* basic metadata. Used internally for commit value creation.
|
|
5945
|
+
*
|
|
5946
|
+
* @param message - Commit message
|
|
5947
|
+
* @param target - Optional additional commit data
|
|
5948
|
+
* @returns Base commit object
|
|
5949
|
+
* @protected
|
|
5950
|
+
*
|
|
5951
|
+
* @example
|
|
5952
|
+
* ```typescript
|
|
5953
|
+
* const commit = changelog.createBaseCommit(
|
|
5954
|
+
* 'feat: new feature',
|
|
5955
|
+
* {
|
|
5956
|
+
* hash: 'abc123',
|
|
5957
|
+
* authorName: 'John Doe'
|
|
5958
|
+
* }
|
|
5959
|
+
* );
|
|
5960
|
+
* ```
|
|
5961
|
+
*/
|
|
4970
5962
|
createBaseCommit(message, target) {
|
|
4971
5963
|
return {
|
|
4972
5964
|
subject: message,
|
|
@@ -4976,16 +5968,66 @@ var GitChangelog = class {
|
|
|
4976
5968
|
};
|
|
4977
5969
|
}
|
|
4978
5970
|
/**
|
|
4979
|
-
*
|
|
5971
|
+
* Indents each line of a text block
|
|
5972
|
+
*
|
|
5973
|
+
* Adds specified number of spaces to the start of each line
|
|
5974
|
+
* in a multi-line string. Used for formatting commit body text.
|
|
4980
5975
|
*
|
|
4981
5976
|
* @since 2.3.2
|
|
4982
|
-
* @param body
|
|
4983
|
-
* @param size
|
|
4984
|
-
* @returns
|
|
5977
|
+
* @param body - Text to indent
|
|
5978
|
+
* @param size - Number of spaces to add (default: 2)
|
|
5979
|
+
* @returns Indented text
|
|
5980
|
+
*
|
|
5981
|
+
* @example
|
|
5982
|
+
* ```typescript
|
|
5983
|
+
* const text = changelog.tabify(
|
|
5984
|
+
* 'Line 1\nLine 2\nLine 3',
|
|
5985
|
+
* 4
|
|
5986
|
+
* );
|
|
5987
|
+
* // ' Line 1\n Line 2\n Line 3'
|
|
5988
|
+
* ```
|
|
4985
5989
|
*/
|
|
4986
5990
|
tabify(body, size = 2) {
|
|
4987
5991
|
return body.split("\n").map((line) => " ".repeat(size) + line.trim()).join("\n");
|
|
4988
5992
|
}
|
|
5993
|
+
/**
|
|
5994
|
+
* Parses a commit message into conventional commit format
|
|
5995
|
+
*
|
|
5996
|
+
* Extracts type, scope, message, and body from a commit message
|
|
5997
|
+
* following the conventional commit specification.
|
|
5998
|
+
*
|
|
5999
|
+
* Format: type(scope): message
|
|
6000
|
+
*
|
|
6001
|
+
* @param subject - Commit subject line
|
|
6002
|
+
* @param rawBody - Full commit message body
|
|
6003
|
+
* @returns Parsed conventional commit data
|
|
6004
|
+
*
|
|
6005
|
+
* @example Basic commit
|
|
6006
|
+
* ```typescript
|
|
6007
|
+
* const commit = changelog.parseCommitlint(
|
|
6008
|
+
* 'feat(api): add new endpoint'
|
|
6009
|
+
* );
|
|
6010
|
+
* // {
|
|
6011
|
+
* // type: 'feat',
|
|
6012
|
+
* // scope: 'api',
|
|
6013
|
+
* // message: 'add new endpoint'
|
|
6014
|
+
* // }
|
|
6015
|
+
* ```
|
|
6016
|
+
*
|
|
6017
|
+
* @example With body
|
|
6018
|
+
* ```typescript
|
|
6019
|
+
* const commit = changelog.parseCommitlint(
|
|
6020
|
+
* 'fix(core): memory leak',
|
|
6021
|
+
* 'Fixed memory leak in core module\n\nBREAKING CHANGE: API changed'
|
|
6022
|
+
* );
|
|
6023
|
+
* // {
|
|
6024
|
+
* // type: 'fix',
|
|
6025
|
+
* // scope: 'core',
|
|
6026
|
+
* // message: 'memory leak',
|
|
6027
|
+
* // body: ' Fixed memory leak in core module\n\n BREAKING CHANGE: API changed'
|
|
6028
|
+
* // }
|
|
6029
|
+
* ```
|
|
6030
|
+
*/
|
|
4989
6031
|
parseCommitlint(subject, rawBody = "") {
|
|
4990
6032
|
const [title] = subject.trim().split("\n");
|
|
4991
6033
|
const bodyLines = rawBody.startsWith(title) ? rawBody.replace(title, "") : rawBody;
|
|
@@ -5004,6 +6046,51 @@ var GitChangelog = class {
|
|
|
5004
6046
|
body: bodyLines ? this.tabify(bodyLines) : void 0
|
|
5005
6047
|
};
|
|
5006
6048
|
}
|
|
6049
|
+
/**
|
|
6050
|
+
* Creates a complete commit value object from hash and message
|
|
6051
|
+
*
|
|
6052
|
+
* Combines commit hash, parsed conventional commit data, and
|
|
6053
|
+
* PR information into a single commit value object.
|
|
6054
|
+
*
|
|
6055
|
+
* @param hash - Commit hash
|
|
6056
|
+
* @param message - Full commit message
|
|
6057
|
+
* @returns Complete commit value object
|
|
6058
|
+
*
|
|
6059
|
+
* @example Basic commit
|
|
6060
|
+
* ```typescript
|
|
6061
|
+
* const commit = changelog.toCommitValue(
|
|
6062
|
+
* 'abc123',
|
|
6063
|
+
* 'feat(api): new endpoint'
|
|
6064
|
+
* );
|
|
6065
|
+
* // {
|
|
6066
|
+
* // base: {
|
|
6067
|
+
* // hash: 'abc123',
|
|
6068
|
+
* // abbrevHash: 'abc123',
|
|
6069
|
+
* // subject: 'feat(api): new endpoint'
|
|
6070
|
+
* // },
|
|
6071
|
+
* // commitlint: {
|
|
6072
|
+
* // type: 'feat',
|
|
6073
|
+
* // scope: 'api',
|
|
6074
|
+
* // message: 'new endpoint'
|
|
6075
|
+
* // },
|
|
6076
|
+
* // commits: []
|
|
6077
|
+
* // }
|
|
6078
|
+
* ```
|
|
6079
|
+
*
|
|
6080
|
+
* @example PR commit
|
|
6081
|
+
* ```typescript
|
|
6082
|
+
* const commit = changelog.toCommitValue(
|
|
6083
|
+
* 'def456',
|
|
6084
|
+
* 'fix(core): memory leak (#123)'
|
|
6085
|
+
* );
|
|
6086
|
+
* // {
|
|
6087
|
+
* // base: { hash: 'def456', ... },
|
|
6088
|
+
* // commitlint: { type: 'fix', ... },
|
|
6089
|
+
* // commits: [],
|
|
6090
|
+
* // prNumber: '123'
|
|
6091
|
+
* // }
|
|
6092
|
+
* ```
|
|
6093
|
+
*/
|
|
5007
6094
|
toCommitValue(hash, message) {
|
|
5008
6095
|
const [title] = message.trim().split("\n");
|
|
5009
6096
|
const prMatch = title.match(/\(#(\d+)\)/);
|
|
@@ -5021,6 +6108,33 @@ var GitChangelog = class {
|
|
|
5021
6108
|
prNumber: prMatch?.[1]
|
|
5022
6109
|
};
|
|
5023
6110
|
}
|
|
6111
|
+
/**
|
|
6112
|
+
* Resolves a Git tag or reference to a valid commit reference
|
|
6113
|
+
*
|
|
6114
|
+
* Attempts to resolve a tag name to a valid Git reference.
|
|
6115
|
+
* Falls back to root commit or HEAD if tag doesn't exist.
|
|
6116
|
+
*
|
|
6117
|
+
* @param tag - Tag name to resolve
|
|
6118
|
+
* @param fallback - Fallback value ('root' or 'HEAD')
|
|
6119
|
+
* @returns Resolved Git reference
|
|
6120
|
+
* @protected
|
|
6121
|
+
*
|
|
6122
|
+
* @example Basic tag resolution
|
|
6123
|
+
* ```typescript
|
|
6124
|
+
* const ref = await changelog.resolveTag('v1.0.0');
|
|
6125
|
+
* // 'v1.0.0' if tag exists
|
|
6126
|
+
* // 'HEAD' if tag doesn't exist
|
|
6127
|
+
* ```
|
|
6128
|
+
*
|
|
6129
|
+
* @example Root commit fallback
|
|
6130
|
+
* ```typescript
|
|
6131
|
+
* const ref = await changelog.resolveTag(
|
|
6132
|
+
* 'non-existent-tag',
|
|
6133
|
+
* 'root'
|
|
6134
|
+
* );
|
|
6135
|
+
* // First commit hash if tag doesn't exist
|
|
6136
|
+
* ```
|
|
6137
|
+
*/
|
|
5024
6138
|
async resolveTag(tag, fallback) {
|
|
5025
6139
|
if (tag) {
|
|
5026
6140
|
try {
|
|
@@ -5041,9 +6155,75 @@ var import_scripts_context5 = require("@qlover/scripts-context");
|
|
|
5041
6155
|
var import_groupBy = __toESM(require_groupBy(), 1);
|
|
5042
6156
|
var DEFAULT_TEMPLATE = "\n- ${scopeHeader} ${commitlint.message} ${commitLink} ${prLink}";
|
|
5043
6157
|
var GitChangelogFormatter = class {
|
|
6158
|
+
/**
|
|
6159
|
+
* Creates a new GitChangelogFormatter instance
|
|
6160
|
+
*
|
|
6161
|
+
* @param options - Configuration options including shell interface
|
|
6162
|
+
*
|
|
6163
|
+
* @example
|
|
6164
|
+
* ```typescript
|
|
6165
|
+
* const formatter = new GitChangelogFormatter({
|
|
6166
|
+
* shell: new Shell(),
|
|
6167
|
+
* repoUrl: 'https://github.com/org/repo',
|
|
6168
|
+
* types: [
|
|
6169
|
+
* { type: 'feat', section: '### Features' }
|
|
6170
|
+
* ],
|
|
6171
|
+
* formatTemplate: '- ${commitlint.message}'
|
|
6172
|
+
* });
|
|
6173
|
+
* ```
|
|
6174
|
+
*/
|
|
5044
6175
|
constructor(options) {
|
|
5045
6176
|
this.options = options;
|
|
5046
6177
|
}
|
|
6178
|
+
/**
|
|
6179
|
+
* Formats an array of commits into changelog entries
|
|
6180
|
+
*
|
|
6181
|
+
* Groups commits by type and formats them according to the
|
|
6182
|
+
* configured template and options. Supports commit body
|
|
6183
|
+
* inclusion and type-based sections.
|
|
6184
|
+
*
|
|
6185
|
+
* @param commits - Array of commit values to format
|
|
6186
|
+
* @param options - Optional formatting options
|
|
6187
|
+
* @returns Array of formatted changelog lines
|
|
6188
|
+
*
|
|
6189
|
+
* @example Basic formatting
|
|
6190
|
+
* ```typescript
|
|
6191
|
+
* const changelog = formatter.format([
|
|
6192
|
+
* {
|
|
6193
|
+
* base: { hash: 'abc123' },
|
|
6194
|
+
* commitlint: {
|
|
6195
|
+
* type: 'feat',
|
|
6196
|
+
* scope: 'api',
|
|
6197
|
+
* message: 'new endpoint'
|
|
6198
|
+
* }
|
|
6199
|
+
* }
|
|
6200
|
+
* ]);
|
|
6201
|
+
* // [
|
|
6202
|
+
* // '### Features',
|
|
6203
|
+
* // '- **api:** new endpoint ([abc123](...))'
|
|
6204
|
+
* // ]
|
|
6205
|
+
* ```
|
|
6206
|
+
*
|
|
6207
|
+
* @example With commit body
|
|
6208
|
+
* ```typescript
|
|
6209
|
+
* const changelog = formatter.format(
|
|
6210
|
+
* [{
|
|
6211
|
+
* commitlint: {
|
|
6212
|
+
* type: 'fix',
|
|
6213
|
+
* message: 'memory leak',
|
|
6214
|
+
* body: 'Fixed memory allocation\nAdded cleanup'
|
|
6215
|
+
* }
|
|
6216
|
+
* }],
|
|
6217
|
+
* { commitBody: true }
|
|
6218
|
+
* );
|
|
6219
|
+
* // [
|
|
6220
|
+
* // '### Bug Fixes',
|
|
6221
|
+
* // '- memory leak',
|
|
6222
|
+
* // ' Fixed memory allocation',
|
|
6223
|
+
* // ' Added cleanup'
|
|
6224
|
+
* // ]
|
|
6225
|
+
* ```
|
|
6226
|
+
*/
|
|
5047
6227
|
format(commits, options) {
|
|
5048
6228
|
const { types = [], commitBody = false } = { ...this.options, ...options };
|
|
5049
6229
|
const changelog = [];
|
|
@@ -5070,6 +6250,41 @@ var GitChangelogFormatter = class {
|
|
|
5070
6250
|
});
|
|
5071
6251
|
return changelog;
|
|
5072
6252
|
}
|
|
6253
|
+
/**
|
|
6254
|
+
* Formats a single commit into a changelog entry
|
|
6255
|
+
*
|
|
6256
|
+
* Applies the configured template to a commit, including
|
|
6257
|
+
* scope formatting, PR links, and commit hash links.
|
|
6258
|
+
*
|
|
6259
|
+
* @param commit - Commit value to format
|
|
6260
|
+
* @param options - Optional formatting options
|
|
6261
|
+
* @returns Formatted changelog entry
|
|
6262
|
+
*
|
|
6263
|
+
* @example Basic formatting
|
|
6264
|
+
* ```typescript
|
|
6265
|
+
* const entry = formatter.formatCommit({
|
|
6266
|
+
* base: { hash: 'abc123' },
|
|
6267
|
+
* commitlint: {
|
|
6268
|
+
* type: 'feat',
|
|
6269
|
+
* scope: 'api',
|
|
6270
|
+
* message: 'new endpoint'
|
|
6271
|
+
* }
|
|
6272
|
+
* });
|
|
6273
|
+
* // '- **api:** new endpoint ([abc123](...))'
|
|
6274
|
+
* ```
|
|
6275
|
+
*
|
|
6276
|
+
* @example With PR number
|
|
6277
|
+
* ```typescript
|
|
6278
|
+
* const entry = formatter.formatCommit({
|
|
6279
|
+
* base: { hash: 'def456' },
|
|
6280
|
+
* commitlint: {
|
|
6281
|
+
* message: 'fix bug'
|
|
6282
|
+
* },
|
|
6283
|
+
* prNumber: '123'
|
|
6284
|
+
* });
|
|
6285
|
+
* // '- fix bug ([def456](...)) (#123)'
|
|
6286
|
+
* ```
|
|
6287
|
+
*/
|
|
5073
6288
|
formatCommit(commit, options) {
|
|
5074
6289
|
const {
|
|
5075
6290
|
commitlint,
|
|
@@ -5096,12 +6311,65 @@ var GitChangelogFormatter = class {
|
|
|
5096
6311
|
prLink
|
|
5097
6312
|
});
|
|
5098
6313
|
}
|
|
6314
|
+
/**
|
|
6315
|
+
* Formats a target string as a Markdown link
|
|
6316
|
+
*
|
|
6317
|
+
* Creates a Markdown-formatted link with optional URL.
|
|
6318
|
+
* If no URL is provided, formats as a plain reference.
|
|
6319
|
+
*
|
|
6320
|
+
* @param target - Text to display
|
|
6321
|
+
* @param url - Optional URL for the link
|
|
6322
|
+
* @returns Formatted Markdown link
|
|
6323
|
+
*
|
|
6324
|
+
* @example With URL
|
|
6325
|
+
* ```typescript
|
|
6326
|
+
* const link = formatter.foramtLink('abc123', 'https://github.com/org/repo/commit/abc123');
|
|
6327
|
+
* // '([abc123](https://github.com/org/repo/commit/abc123))'
|
|
6328
|
+
* ```
|
|
6329
|
+
*
|
|
6330
|
+
* @example Without URL
|
|
6331
|
+
* ```typescript
|
|
6332
|
+
* const link = formatter.foramtLink('abc123');
|
|
6333
|
+
* // '(abc123)'
|
|
6334
|
+
* ```
|
|
6335
|
+
*/
|
|
5099
6336
|
foramtLink(target, url) {
|
|
5100
6337
|
return url ? `([${target}](${url}))` : `(${target})`;
|
|
5101
6338
|
}
|
|
6339
|
+
/**
|
|
6340
|
+
* Formats a commit hash as a Markdown link
|
|
6341
|
+
*
|
|
6342
|
+
* @deprecated Use foramtLink instead
|
|
6343
|
+
* @param target - Commit hash to display
|
|
6344
|
+
* @param url - Optional URL to the commit
|
|
6345
|
+
* @returns Formatted Markdown link
|
|
6346
|
+
*
|
|
6347
|
+
* @example
|
|
6348
|
+
* ```typescript
|
|
6349
|
+
* const link = formatter.formatCommitLink(
|
|
6350
|
+
* 'abc123',
|
|
6351
|
+
* 'https://github.com/org/repo/commit/abc123'
|
|
6352
|
+
* );
|
|
6353
|
+
* // '([abc123](https://github.com/org/repo/commit/abc123))'
|
|
6354
|
+
* ```
|
|
6355
|
+
*/
|
|
5102
6356
|
formatCommitLink(target, url) {
|
|
5103
6357
|
return url ? `([${target}](${url}))` : `(${target})`;
|
|
5104
6358
|
}
|
|
6359
|
+
/**
|
|
6360
|
+
* Formats a commit scope in Markdown
|
|
6361
|
+
*
|
|
6362
|
+
* Wraps the scope in bold syntax and adds a colon.
|
|
6363
|
+
*
|
|
6364
|
+
* @param scope - Scope to format
|
|
6365
|
+
* @returns Formatted scope in Markdown
|
|
6366
|
+
*
|
|
6367
|
+
* @example
|
|
6368
|
+
* ```typescript
|
|
6369
|
+
* const scope = formatter.formatScope('api');
|
|
6370
|
+
* // '**api:**'
|
|
6371
|
+
* ```
|
|
6372
|
+
*/
|
|
5105
6373
|
formatScope(scope) {
|
|
5106
6374
|
return `**${scope}:**`;
|
|
5107
6375
|
}
|
|
@@ -5155,7 +6423,30 @@ var Pather = class {
|
|
|
5155
6423
|
return child[boundaryIndex] === import_node_path.sep;
|
|
5156
6424
|
}
|
|
5157
6425
|
/**
|
|
5158
|
-
*
|
|
6426
|
+
* Normalized path prefix check
|
|
6427
|
+
*
|
|
6428
|
+
* Checks if sourcePath starts with targetPath after normalization.
|
|
6429
|
+
* Handles cross-platform path separators and trailing separators.
|
|
6430
|
+
*
|
|
6431
|
+
* @param sourcePath - Path to check
|
|
6432
|
+
* @param targetPath - Prefix path to match
|
|
6433
|
+
* @returns True if sourcePath starts with targetPath
|
|
6434
|
+
*
|
|
6435
|
+
* @example Basic usage
|
|
6436
|
+
* ```typescript
|
|
6437
|
+
* const pather = new Pather();
|
|
6438
|
+
*
|
|
6439
|
+
* pather.startsWith('src/utils/file.ts', 'src') // true
|
|
6440
|
+
* pather.startsWith('src\\utils\\file.ts', 'src') // true
|
|
6441
|
+
* pather.startsWith('lib/utils/file.ts', 'src') // false
|
|
6442
|
+
* ```
|
|
6443
|
+
*
|
|
6444
|
+
* @example Trailing separators
|
|
6445
|
+
* ```typescript
|
|
6446
|
+
* pather.startsWith('src/utils', 'src/') // true
|
|
6447
|
+
* pather.startsWith('src/utils/', 'src') // true
|
|
6448
|
+
* pather.startsWith('src2/utils', 'src') // false
|
|
6449
|
+
* ```
|
|
5159
6450
|
*/
|
|
5160
6451
|
startsWith(sourcePath, targetPath) {
|
|
5161
6452
|
let src = this.toLocalPath(sourcePath);
|
|
@@ -5169,7 +6460,44 @@ var Pather = class {
|
|
|
5169
6460
|
return src.startsWith(tgt);
|
|
5170
6461
|
}
|
|
5171
6462
|
/**
|
|
5172
|
-
* Segment-aware containment check
|
|
6463
|
+
* Segment-aware path containment check
|
|
6464
|
+
*
|
|
6465
|
+
* Checks if sourcePath contains targetPath as a complete path segment.
|
|
6466
|
+
* Unlike simple substring matching, this ensures proper path boundaries.
|
|
6467
|
+
* For example, 'src/abc' does not contain 'src/a' even though 'src/a'
|
|
6468
|
+
* is a substring.
|
|
6469
|
+
*
|
|
6470
|
+
* Features:
|
|
6471
|
+
* - Cross-platform path handling
|
|
6472
|
+
* - Proper segment boundary checking
|
|
6473
|
+
* - Trailing separator normalization
|
|
6474
|
+
* - Exact match support
|
|
6475
|
+
*
|
|
6476
|
+
* @param sourcePath - Path to search in
|
|
6477
|
+
* @param targetPath - Path to search for
|
|
6478
|
+
* @returns True if sourcePath contains targetPath as a segment
|
|
6479
|
+
*
|
|
6480
|
+
* @example Basic usage
|
|
6481
|
+
* ```typescript
|
|
6482
|
+
* const pather = new Pather();
|
|
6483
|
+
*
|
|
6484
|
+
* pather.containsPath('src/utils/file.ts', 'utils') // true
|
|
6485
|
+
* pather.containsPath('src/utils/file.ts', 'src/utils') // true
|
|
6486
|
+
* pather.containsPath('src/utils/file.ts', 'til') // false
|
|
6487
|
+
* ```
|
|
6488
|
+
*
|
|
6489
|
+
* @example Segment boundaries
|
|
6490
|
+
* ```typescript
|
|
6491
|
+
* pather.containsPath('src/abc/file.ts', 'src/a') // false
|
|
6492
|
+
* pather.containsPath('src/abc/file.ts', 'src/abc') // true
|
|
6493
|
+
* ```
|
|
6494
|
+
*
|
|
6495
|
+
* @example Trailing separators
|
|
6496
|
+
* ```typescript
|
|
6497
|
+
* pather.containsPath('src/utils/', 'utils') // true
|
|
6498
|
+
* pather.containsPath('src/utils', 'utils/') // true
|
|
6499
|
+
* pather.containsPath('src/utils/', 'utils/') // true
|
|
6500
|
+
* ```
|
|
5173
6501
|
*/
|
|
5174
6502
|
containsPath(sourcePath, targetPath) {
|
|
5175
6503
|
let src = this.toLocalPath(sourcePath);
|
|
@@ -5195,18 +6523,49 @@ var Pather = class {
|
|
|
5195
6523
|
// src/plugins/githubPR/GithubChangelog.ts
|
|
5196
6524
|
var DOMAIN = "https://github.com";
|
|
5197
6525
|
var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
6526
|
+
/**
|
|
6527
|
+
* Creates a new GitHub changelog generator
|
|
6528
|
+
*
|
|
6529
|
+
* @param options - Changelog generation options
|
|
6530
|
+
* @param githubManager - GitHub API manager
|
|
6531
|
+
*
|
|
6532
|
+
* @example
|
|
6533
|
+
* ```typescript
|
|
6534
|
+
* const changelog = new GithubChangelog({
|
|
6535
|
+
* shell,
|
|
6536
|
+
* logger,
|
|
6537
|
+
* mergePRcommit: true,
|
|
6538
|
+
* githubRootPath: 'https://github.com/org/repo'
|
|
6539
|
+
* }, githubManager);
|
|
6540
|
+
* ```
|
|
6541
|
+
*/
|
|
5198
6542
|
constructor(options, githubManager) {
|
|
5199
6543
|
super(options);
|
|
5200
6544
|
this.options = options;
|
|
5201
6545
|
this.githubManager = githubManager;
|
|
5202
6546
|
}
|
|
6547
|
+
/** Path manipulation utility */
|
|
5203
6548
|
pather = new Pather();
|
|
5204
6549
|
/**
|
|
5205
|
-
*
|
|
5206
|
-
*
|
|
5207
|
-
*
|
|
5208
|
-
*
|
|
6550
|
+
* Filters commits by directory
|
|
6551
|
+
*
|
|
6552
|
+
* Filters commits based on whether they contain changes in
|
|
6553
|
+
* the specified directory. Uses GitHub API to get detailed
|
|
6554
|
+
* commit information.
|
|
6555
|
+
*
|
|
6556
|
+
* @param commits - Array of commits to filter
|
|
6557
|
+
* @param directory - Directory path to filter by
|
|
6558
|
+
* @returns Promise resolving to filtered commits
|
|
5209
6559
|
* @since 2.4.0
|
|
6560
|
+
*
|
|
6561
|
+
* @example
|
|
6562
|
+
* ```typescript
|
|
6563
|
+
* const commits = await changelog.filterCommitsByDirectory(
|
|
6564
|
+
* allCommits,
|
|
6565
|
+
* 'packages/pkg-a'
|
|
6566
|
+
* );
|
|
6567
|
+
* // Only commits that modified files in packages/pkg-a
|
|
6568
|
+
* ```
|
|
5210
6569
|
*/
|
|
5211
6570
|
async filterCommitsByDirectory(commits, directory) {
|
|
5212
6571
|
const result = [];
|
|
@@ -5224,6 +6583,41 @@ var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
|
5224
6583
|
}
|
|
5225
6584
|
return result;
|
|
5226
6585
|
}
|
|
6586
|
+
/**
|
|
6587
|
+
* Gets complete commit information with PR details
|
|
6588
|
+
*
|
|
6589
|
+
* Retrieves commits and enhances them with pull request
|
|
6590
|
+
* information. For commits associated with PRs, includes
|
|
6591
|
+
* all PR commits and filters by directory.
|
|
6592
|
+
*
|
|
6593
|
+
* Process:
|
|
6594
|
+
* 1. Get base commits
|
|
6595
|
+
* 2. Extract PR numbers
|
|
6596
|
+
* 3. Fetch PR commits
|
|
6597
|
+
* 4. Filter by directory
|
|
6598
|
+
* 5. Flatten results
|
|
6599
|
+
*
|
|
6600
|
+
* @param options - Changelog options
|
|
6601
|
+
* @returns Promise resolving to enhanced commits
|
|
6602
|
+
*
|
|
6603
|
+
* @example Basic usage
|
|
6604
|
+
* ```typescript
|
|
6605
|
+
* const commits = await changelog.getFullCommit({
|
|
6606
|
+
* from: 'v1.0.0',
|
|
6607
|
+
* directory: 'packages/pkg-a'
|
|
6608
|
+
* });
|
|
6609
|
+
* // Returns commits with PR information
|
|
6610
|
+
* ```
|
|
6611
|
+
*
|
|
6612
|
+
* @example With PR merging
|
|
6613
|
+
* ```typescript
|
|
6614
|
+
* const commits = await changelog.getFullCommit({
|
|
6615
|
+
* mergePRcommit: true,
|
|
6616
|
+
* directory: 'packages/pkg-a'
|
|
6617
|
+
* });
|
|
6618
|
+
* // Includes all PR commits
|
|
6619
|
+
* ```
|
|
6620
|
+
*/
|
|
5227
6621
|
async getFullCommit(options) {
|
|
5228
6622
|
const _options = { ...this.options, ...options };
|
|
5229
6623
|
const allCommits = await this.getCommits(_options);
|
|
@@ -5251,6 +6645,41 @@ var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
|
5251
6645
|
);
|
|
5252
6646
|
return newallCommits.flat();
|
|
5253
6647
|
}
|
|
6648
|
+
/**
|
|
6649
|
+
* Transforms workspaces with GitHub changelogs
|
|
6650
|
+
*
|
|
6651
|
+
* Processes each workspace to add GitHub-specific changelog
|
|
6652
|
+
* information. Includes:
|
|
6653
|
+
* - GitHub repository URL
|
|
6654
|
+
* - PR-aware commit history
|
|
6655
|
+
* - Formatted changelog with links
|
|
6656
|
+
*
|
|
6657
|
+
* Process:
|
|
6658
|
+
* 1. Build GitHub root path
|
|
6659
|
+
* 2. Configure changelog options
|
|
6660
|
+
* 3. Get commits for each workspace
|
|
6661
|
+
* 4. Format changelog with links
|
|
6662
|
+
* 5. Update workspace objects
|
|
6663
|
+
*
|
|
6664
|
+
* @param workspaces - Array of workspaces to process
|
|
6665
|
+
* @param context - Release context
|
|
6666
|
+
* @returns Promise resolving to updated workspaces
|
|
6667
|
+
*
|
|
6668
|
+
* @example
|
|
6669
|
+
* ```typescript
|
|
6670
|
+
* const workspaces = await changelog.transformWorkspace(
|
|
6671
|
+
* [
|
|
6672
|
+
* {
|
|
6673
|
+
* name: 'pkg-a',
|
|
6674
|
+
* path: 'packages/a',
|
|
6675
|
+
* lastTag: 'v1.0.0'
|
|
6676
|
+
* }
|
|
6677
|
+
* ],
|
|
6678
|
+
* context
|
|
6679
|
+
* );
|
|
6680
|
+
* // Returns workspaces with GitHub-formatted changelogs
|
|
6681
|
+
* ```
|
|
6682
|
+
*/
|
|
5254
6683
|
async transformWorkspace(workspaces, context) {
|
|
5255
6684
|
const githubRootPath = [
|
|
5256
6685
|
DOMAIN,
|
|
@@ -5300,6 +6729,26 @@ var import_scripts_context6 = require("@qlover/scripts-context");
|
|
|
5300
6729
|
var DEFAULT_RELEASE_NAME = "Release ${name} v${version}";
|
|
5301
6730
|
var DEFAULT_COMMIT_MESSAGE = "chore(tag): ${name} v${version}";
|
|
5302
6731
|
var GithubPR = class extends GitBase {
|
|
6732
|
+
/**
|
|
6733
|
+
* Creates a new GithubPR plugin instance
|
|
6734
|
+
*
|
|
6735
|
+
* Initializes the plugin with GitHub-specific configuration and
|
|
6736
|
+
* sets up release parameters and GitHub manager.
|
|
6737
|
+
*
|
|
6738
|
+
* @param context - Release context
|
|
6739
|
+
* @param props - Plugin configuration
|
|
6740
|
+
*
|
|
6741
|
+
* @example
|
|
6742
|
+
* ```typescript
|
|
6743
|
+
* const plugin = new GithubPR(context, {
|
|
6744
|
+
* releasePR: true,
|
|
6745
|
+
* releaseName: 'Release v${version}',
|
|
6746
|
+
* commitMessage: 'chore: release v${version}',
|
|
6747
|
+
* draft: false,
|
|
6748
|
+
* preRelease: false
|
|
6749
|
+
* });
|
|
6750
|
+
* ```
|
|
6751
|
+
*/
|
|
5303
6752
|
constructor(context, props) {
|
|
5304
6753
|
super(context, "githubPR", {
|
|
5305
6754
|
releaseName: DEFAULT_RELEASE_NAME,
|
|
@@ -5315,15 +6764,67 @@ var GithubPR = class extends GitBase {
|
|
|
5315
6764
|
}
|
|
5316
6765
|
releaseParams;
|
|
5317
6766
|
githubManager;
|
|
6767
|
+
/**
|
|
6768
|
+
* Determines if the plugin should be enabled
|
|
6769
|
+
*
|
|
6770
|
+
* Plugin is enabled unless explicitly skipped via configuration.
|
|
6771
|
+
* This allows for conditional PR creation and release publishing.
|
|
6772
|
+
*
|
|
6773
|
+
* @param _name - Plugin name (unused)
|
|
6774
|
+
* @returns True if plugin should be enabled
|
|
6775
|
+
*
|
|
6776
|
+
* @example
|
|
6777
|
+
* ```typescript
|
|
6778
|
+
* const plugin = new GithubPR(context, { skip: true });
|
|
6779
|
+
* plugin.enabled(); // false
|
|
6780
|
+
*
|
|
6781
|
+
* const plugin2 = new GithubPR(context, {});
|
|
6782
|
+
* plugin2.enabled(); // true
|
|
6783
|
+
* ```
|
|
6784
|
+
*/
|
|
5318
6785
|
enabled(_name) {
|
|
5319
6786
|
if (this.getConfig("skip")) {
|
|
5320
6787
|
return false;
|
|
5321
6788
|
}
|
|
5322
6789
|
return true;
|
|
5323
6790
|
}
|
|
6791
|
+
/**
|
|
6792
|
+
* Determines if the plugin is in publish mode
|
|
6793
|
+
*
|
|
6794
|
+
* In publish mode, the plugin publishes releases directly.
|
|
6795
|
+
* In non-publish mode (releasePR=true), it creates pull requests.
|
|
6796
|
+
*
|
|
6797
|
+
* @returns True if in publish mode
|
|
6798
|
+
*
|
|
6799
|
+
* @example
|
|
6800
|
+
* ```typescript
|
|
6801
|
+
* const plugin = new GithubPR(context, { releasePR: true });
|
|
6802
|
+
* plugin.isPublish; // false (PR mode)
|
|
6803
|
+
*
|
|
6804
|
+
* const plugin2 = new GithubPR(context, { releasePR: false });
|
|
6805
|
+
* plugin2.isPublish; // true (publish mode)
|
|
6806
|
+
* ```
|
|
6807
|
+
*/
|
|
5324
6808
|
get isPublish() {
|
|
5325
6809
|
return !this.getConfig("releasePR");
|
|
5326
6810
|
}
|
|
6811
|
+
/**
|
|
6812
|
+
* Checks if the current repository is a GitHub repository
|
|
6813
|
+
*
|
|
6814
|
+
* Verifies that the remote URL contains 'github.com' to ensure
|
|
6815
|
+
* GitHub-specific features can be used.
|
|
6816
|
+
*
|
|
6817
|
+
* @returns Promise resolving to true if GitHub repository
|
|
6818
|
+
*
|
|
6819
|
+
* @example
|
|
6820
|
+
* ```typescript
|
|
6821
|
+
* const isGithub = await plugin.isGithubRepository();
|
|
6822
|
+
* if (isGithub) {
|
|
6823
|
+
* // Use GitHub-specific features
|
|
6824
|
+
* }
|
|
6825
|
+
* ```
|
|
6826
|
+
* @private
|
|
6827
|
+
*/
|
|
5327
6828
|
async isGithubRepository() {
|
|
5328
6829
|
try {
|
|
5329
6830
|
const remoteUrl = await this.getRemoteUrl();
|
|
@@ -5332,6 +6833,24 @@ var GithubPR = class extends GitBase {
|
|
|
5332
6833
|
return false;
|
|
5333
6834
|
}
|
|
5334
6835
|
}
|
|
6836
|
+
/**
|
|
6837
|
+
* Plugin initialization hook
|
|
6838
|
+
*
|
|
6839
|
+
* Performs pre-execution setup:
|
|
6840
|
+
* 1. Verifies repository is on GitHub
|
|
6841
|
+
* 2. Runs parent class initialization
|
|
6842
|
+
* 3. Sets up NPM token for publishing
|
|
6843
|
+
*
|
|
6844
|
+
* @throws Error if not a GitHub repository
|
|
6845
|
+
* @throws Error if NPM_TOKEN missing in publish mode
|
|
6846
|
+
*
|
|
6847
|
+
* @example
|
|
6848
|
+
* ```typescript
|
|
6849
|
+
* const plugin = new GithubPR(context, {});
|
|
6850
|
+
* await plugin.onBefore();
|
|
6851
|
+
* // Throws if not GitHub repo or missing NPM token
|
|
6852
|
+
* ```
|
|
6853
|
+
*/
|
|
5335
6854
|
async onBefore() {
|
|
5336
6855
|
this.logger.debug("GithubPR onBefore");
|
|
5337
6856
|
const isGithub = await this.isGithubRepository();
|
|
@@ -5351,6 +6870,24 @@ var GithubPR = class extends GitBase {
|
|
|
5351
6870
|
);
|
|
5352
6871
|
}
|
|
5353
6872
|
}
|
|
6873
|
+
/**
|
|
6874
|
+
* Main plugin execution hook
|
|
6875
|
+
*
|
|
6876
|
+
* Processes changelogs for all workspaces using GitHub-specific
|
|
6877
|
+
* formatting and updates the context with the results.
|
|
6878
|
+
*
|
|
6879
|
+
* Process:
|
|
6880
|
+
* 1. Initialize GitHub changelog processor
|
|
6881
|
+
* 2. Transform workspace changelogs
|
|
6882
|
+
* 3. Update context with new workspace info
|
|
6883
|
+
*
|
|
6884
|
+
* @example
|
|
6885
|
+
* ```typescript
|
|
6886
|
+
* const plugin = new GithubPR(context, {});
|
|
6887
|
+
* await plugin.onExec();
|
|
6888
|
+
* // Transforms changelogs with GitHub links
|
|
6889
|
+
* ```
|
|
6890
|
+
*/
|
|
5354
6891
|
async onExec() {
|
|
5355
6892
|
const workspaces = this.context.workspaces;
|
|
5356
6893
|
const githubChangelog = new GithubChangelog(
|
|
@@ -5363,6 +6900,27 @@ var GithubPR = class extends GitBase {
|
|
|
5363
6900
|
});
|
|
5364
6901
|
this.context.setWorkspaces(newWorkspaces);
|
|
5365
6902
|
}
|
|
6903
|
+
/**
|
|
6904
|
+
* Success hook after plugin execution
|
|
6905
|
+
*
|
|
6906
|
+
* Handles either PR creation or release publishing based on
|
|
6907
|
+
* configuration. In publish mode, publishes to NPM and creates
|
|
6908
|
+
* GitHub releases. In PR mode, creates release pull requests.
|
|
6909
|
+
*
|
|
6910
|
+
* @example PR mode
|
|
6911
|
+
* ```typescript
|
|
6912
|
+
* const plugin = new GithubPR(context, { releasePR: true });
|
|
6913
|
+
* await plugin.onSuccess();
|
|
6914
|
+
* // Creates release PR
|
|
6915
|
+
* ```
|
|
6916
|
+
*
|
|
6917
|
+
* @example Publish mode
|
|
6918
|
+
* ```typescript
|
|
6919
|
+
* const plugin = new GithubPR(context, { releasePR: false });
|
|
6920
|
+
* await plugin.onSuccess();
|
|
6921
|
+
* // Publishes to NPM and creates GitHub release
|
|
6922
|
+
* ```
|
|
6923
|
+
*/
|
|
5366
6924
|
async onSuccess() {
|
|
5367
6925
|
if (this.isPublish) {
|
|
5368
6926
|
await this.publishPR(this.context.workspaces);
|
|
@@ -5370,6 +6928,28 @@ var GithubPR = class extends GitBase {
|
|
|
5370
6928
|
}
|
|
5371
6929
|
await this.releasePR(this.context.workspaces);
|
|
5372
6930
|
}
|
|
6931
|
+
/**
|
|
6932
|
+
* Creates a release pull request
|
|
6933
|
+
*
|
|
6934
|
+
* Handles the complete process of creating a release PR:
|
|
6935
|
+
* 1. Creates release commit
|
|
6936
|
+
* 2. Creates release branch
|
|
6937
|
+
* 3. Creates and configures pull request
|
|
6938
|
+
*
|
|
6939
|
+
* @param workspaces - Array of workspace configurations
|
|
6940
|
+
*
|
|
6941
|
+
* @example
|
|
6942
|
+
* ```typescript
|
|
6943
|
+
* const workspaces = [{
|
|
6944
|
+
* name: 'pkg-a',
|
|
6945
|
+
* version: '1.0.0',
|
|
6946
|
+
* changelog: '...'
|
|
6947
|
+
* }];
|
|
6948
|
+
*
|
|
6949
|
+
* await plugin.releasePR(workspaces);
|
|
6950
|
+
* // Creates PR with release changes
|
|
6951
|
+
* ```
|
|
6952
|
+
*/
|
|
5373
6953
|
async releasePR(workspaces) {
|
|
5374
6954
|
await this.step({
|
|
5375
6955
|
label: "Release Commit",
|
|
@@ -5381,6 +6961,28 @@ var GithubPR = class extends GitBase {
|
|
|
5381
6961
|
});
|
|
5382
6962
|
await this.releasePullRequest(workspaces, releaseBranchParams);
|
|
5383
6963
|
}
|
|
6964
|
+
/**
|
|
6965
|
+
* Publishes releases to NPM and GitHub
|
|
6966
|
+
*
|
|
6967
|
+
* In non-dry-run mode:
|
|
6968
|
+
* 1. Publishes packages to NPM
|
|
6969
|
+
* 2. Pushes tags to GitHub
|
|
6970
|
+
* 3. Creates GitHub releases
|
|
6971
|
+
*
|
|
6972
|
+
* @param workspaces - Array of workspace configurations
|
|
6973
|
+
*
|
|
6974
|
+
* @example
|
|
6975
|
+
* ```typescript
|
|
6976
|
+
* const workspaces = [{
|
|
6977
|
+
* name: 'pkg-a',
|
|
6978
|
+
* version: '1.0.0',
|
|
6979
|
+
* changelog: '...'
|
|
6980
|
+
* }];
|
|
6981
|
+
*
|
|
6982
|
+
* await plugin.publishPR(workspaces);
|
|
6983
|
+
* // Publishes to NPM and creates GitHub releases
|
|
6984
|
+
* ```
|
|
6985
|
+
*/
|
|
5384
6986
|
async publishPR(workspaces) {
|
|
5385
6987
|
if (!this.getConfig("dryRunCreatePR")) {
|
|
5386
6988
|
await this.context.runChangesetsCli("publish");
|
|
@@ -5396,6 +6998,34 @@ var GithubPR = class extends GitBase {
|
|
|
5396
6998
|
)
|
|
5397
6999
|
});
|
|
5398
7000
|
}
|
|
7001
|
+
/**
|
|
7002
|
+
* Creates release commit(s)
|
|
7003
|
+
*
|
|
7004
|
+
* Creates either a single commit for all workspaces or
|
|
7005
|
+
* individual commits per workspace. Uses configured commit
|
|
7006
|
+
* message template.
|
|
7007
|
+
*
|
|
7008
|
+
* @param workspaces - Array of workspace configurations
|
|
7009
|
+
*
|
|
7010
|
+
* @example Single workspace
|
|
7011
|
+
* ```typescript
|
|
7012
|
+
* await plugin.relesaeCommit([{
|
|
7013
|
+
* name: 'pkg-a',
|
|
7014
|
+
* version: '1.0.0'
|
|
7015
|
+
* }]);
|
|
7016
|
+
* // Creates: "chore(tag): pkg-a v1.0.0"
|
|
7017
|
+
* ```
|
|
7018
|
+
*
|
|
7019
|
+
* @example Multiple workspaces
|
|
7020
|
+
* ```typescript
|
|
7021
|
+
* await plugin.relesaeCommit([
|
|
7022
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
7023
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
7024
|
+
* ]);
|
|
7025
|
+
* // Creates: "chore(tag): pkg-a v1.0.0,pkg-b v2.0.0"
|
|
7026
|
+
* ```
|
|
7027
|
+
* @private
|
|
7028
|
+
*/
|
|
5399
7029
|
async relesaeCommit(workspaces) {
|
|
5400
7030
|
const commitArgs = this.getConfig("commitArgs", []);
|
|
5401
7031
|
if (workspaces.length === 1) {
|
|
@@ -5407,6 +7037,34 @@ var GithubPR = class extends GitBase {
|
|
|
5407
7037
|
const commitMessage = `chore(tag): ${workspaces.map((w) => `${w.name} v${w.version}`).join(",")}`;
|
|
5408
7038
|
await this.commit(commitMessage, commitArgs);
|
|
5409
7039
|
}
|
|
7040
|
+
/**
|
|
7041
|
+
* Creates and optionally merges a release pull request
|
|
7042
|
+
*
|
|
7043
|
+
* Creates a PR with release changes and handles auto-merge
|
|
7044
|
+
* if configured. Adds release and change labels to the PR.
|
|
7045
|
+
*
|
|
7046
|
+
* @param workspaces - Array of workspace configurations
|
|
7047
|
+
* @param releaseBranchParams - Branch and tag information
|
|
7048
|
+
*
|
|
7049
|
+
* @example Manual merge
|
|
7050
|
+
* ```typescript
|
|
7051
|
+
* await plugin.releasePullRequest(
|
|
7052
|
+
* workspaces,
|
|
7053
|
+
* { releaseBranch: 'release-v1.0.0', tagName: 'v1.0.0' }
|
|
7054
|
+
* );
|
|
7055
|
+
* // Creates PR for manual merge
|
|
7056
|
+
* ```
|
|
7057
|
+
*
|
|
7058
|
+
* @example Auto-merge
|
|
7059
|
+
* ```typescript
|
|
7060
|
+
* const plugin = new GithubPR(context, {
|
|
7061
|
+
* autoMergeReleasePR: true
|
|
7062
|
+
* });
|
|
7063
|
+
*
|
|
7064
|
+
* await plugin.releasePullRequest(workspaces, params);
|
|
7065
|
+
* // Creates and auto-merges PR
|
|
7066
|
+
* ```
|
|
7067
|
+
*/
|
|
5410
7068
|
async releasePullRequest(workspaces, releaseBranchParams) {
|
|
5411
7069
|
const prNumber = await this.step({
|
|
5412
7070
|
label: "Create Release PR",
|
|
@@ -5428,6 +7086,34 @@ var GithubPR = class extends GitBase {
|
|
|
5428
7086
|
`Please manually merge PR(#${prNumber}) and complete the publishing process afterwards`
|
|
5429
7087
|
);
|
|
5430
7088
|
}
|
|
7089
|
+
/**
|
|
7090
|
+
* Creates a commit for a single workspace
|
|
7091
|
+
*
|
|
7092
|
+
* Uses the configured commit message template to create a
|
|
7093
|
+
* commit for the workspace's changes.
|
|
7094
|
+
*
|
|
7095
|
+
* @param workspace - Workspace configuration
|
|
7096
|
+
* @param commitArgs - Additional Git commit arguments
|
|
7097
|
+
* @returns Promise resolving to commit output
|
|
7098
|
+
*
|
|
7099
|
+
* @example Basic commit
|
|
7100
|
+
* ```typescript
|
|
7101
|
+
* await plugin.commitWorkspace({
|
|
7102
|
+
* name: 'pkg-a',
|
|
7103
|
+
* version: '1.0.0'
|
|
7104
|
+
* });
|
|
7105
|
+
* // Creates: "chore(tag): pkg-a v1.0.0"
|
|
7106
|
+
* ```
|
|
7107
|
+
*
|
|
7108
|
+
* @example With arguments
|
|
7109
|
+
* ```typescript
|
|
7110
|
+
* await plugin.commitWorkspace(
|
|
7111
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
7112
|
+
* ['--no-verify']
|
|
7113
|
+
* );
|
|
7114
|
+
* ```
|
|
7115
|
+
* @private
|
|
7116
|
+
*/
|
|
5431
7117
|
async commitWorkspace(workspace, commitArgs = []) {
|
|
5432
7118
|
const commitMessage = import_scripts_context6.Shell.format(
|
|
5433
7119
|
this.getConfig("commitMessage", DEFAULT_COMMIT_MESSAGE),
|
|
@@ -5445,6 +7131,37 @@ var GithubPR = class extends GitBase {
|
|
|
5445
7131
|
*
|
|
5446
7132
|
* @returns The release branch.
|
|
5447
7133
|
*/
|
|
7134
|
+
/**
|
|
7135
|
+
* Creates a release branch for changes
|
|
7136
|
+
*
|
|
7137
|
+
* Creates a new branch from the current branch for release
|
|
7138
|
+
* changes. The branch name is generated from the configured
|
|
7139
|
+
* template and workspace information.
|
|
7140
|
+
*
|
|
7141
|
+
* Process:
|
|
7142
|
+
* 1. Generate branch parameters
|
|
7143
|
+
* 2. Fetch required branches
|
|
7144
|
+
* 3. Create and push release branch
|
|
7145
|
+
*
|
|
7146
|
+
* @param workspaces - Array of workspace configurations
|
|
7147
|
+
* @returns Promise resolving to branch parameters
|
|
7148
|
+
*
|
|
7149
|
+
* @example
|
|
7150
|
+
* ```typescript
|
|
7151
|
+
* const params = await plugin.createReleaseBranch([{
|
|
7152
|
+
* name: 'pkg-a',
|
|
7153
|
+
* version: '1.0.0'
|
|
7154
|
+
* }]);
|
|
7155
|
+
* // {
|
|
7156
|
+
* // tagName: 'pkg-a@1.0.0',
|
|
7157
|
+
* // releaseBranch: 'release-pkg-a-1.0.0'
|
|
7158
|
+
* // }
|
|
7159
|
+
* ```
|
|
7160
|
+
*
|
|
7161
|
+
* @throws Error if tag name is invalid
|
|
7162
|
+
* @throws Error if branch creation fails
|
|
7163
|
+
* @private
|
|
7164
|
+
*/
|
|
5448
7165
|
async createReleaseBranch(workspaces) {
|
|
5449
7166
|
const params = this.releaseParams.getReleaseBranchParams(
|
|
5450
7167
|
workspaces,
|
|
@@ -5487,6 +7204,42 @@ var GithubPR = class extends GitBase {
|
|
|
5487
7204
|
* @param releaseBranchParams - The release branch params.
|
|
5488
7205
|
* @returns The created pull request number.
|
|
5489
7206
|
*/
|
|
7207
|
+
/**
|
|
7208
|
+
* Creates a release pull request
|
|
7209
|
+
*
|
|
7210
|
+
* Creates a pull request with:
|
|
7211
|
+
* 1. Release label
|
|
7212
|
+
* 2. Change labels (if configured)
|
|
7213
|
+
* 3. Generated title and body
|
|
7214
|
+
* 4. Proper branch configuration
|
|
7215
|
+
*
|
|
7216
|
+
* @param workspaces - Array of workspace configurations
|
|
7217
|
+
* @param releaseBranchParams - Branch and tag information
|
|
7218
|
+
* @returns Promise resolving to PR number
|
|
7219
|
+
*
|
|
7220
|
+
* @example Basic PR
|
|
7221
|
+
* ```typescript
|
|
7222
|
+
* const prNumber = await plugin.createReleasePR(
|
|
7223
|
+
* workspaces,
|
|
7224
|
+
* { releaseBranch: 'release-v1.0.0', tagName: 'v1.0.0' }
|
|
7225
|
+
* );
|
|
7226
|
+
* // Creates PR with default labels
|
|
7227
|
+
* ```
|
|
7228
|
+
*
|
|
7229
|
+
* @example With change labels
|
|
7230
|
+
* ```typescript
|
|
7231
|
+
* const plugin = new GithubPR(context, {
|
|
7232
|
+
* pushChangeLabels: true
|
|
7233
|
+
* });
|
|
7234
|
+
*
|
|
7235
|
+
* const prNumber = await plugin.createReleasePR(
|
|
7236
|
+
* workspaces,
|
|
7237
|
+
* params
|
|
7238
|
+
* );
|
|
7239
|
+
* // Creates PR with release and change labels
|
|
7240
|
+
* ```
|
|
7241
|
+
* @private
|
|
7242
|
+
*/
|
|
5490
7243
|
async createReleasePR(workspaces, releaseBranchParams) {
|
|
5491
7244
|
const label = await this.githubManager.createReleasePRLabel();
|
|
5492
7245
|
let labels = [label.name];
|
|
@@ -5520,21 +7273,137 @@ var import_node_path2 = require("path");
|
|
|
5520
7273
|
|
|
5521
7274
|
// src/implments/ReleaseLabel.ts
|
|
5522
7275
|
var ReleaseLabel = class {
|
|
7276
|
+
/**
|
|
7277
|
+
* Creates a new ReleaseLabel instance
|
|
7278
|
+
*
|
|
7279
|
+
* @param options - Configuration options for label management
|
|
7280
|
+
*
|
|
7281
|
+
* @example
|
|
7282
|
+
* ```typescript
|
|
7283
|
+
* const label = new ReleaseLabel({
|
|
7284
|
+
* // Label template with ${name} placeholder
|
|
7285
|
+
* changePackagesLabel: 'changed:${name}',
|
|
7286
|
+
*
|
|
7287
|
+
* // Package directories to monitor
|
|
7288
|
+
* packagesDirectories: ['packages/a', 'packages/b'],
|
|
7289
|
+
*
|
|
7290
|
+
* // Optional custom comparison logic
|
|
7291
|
+
* compare: (file, pkg) => file.includes(pkg)
|
|
7292
|
+
* });
|
|
7293
|
+
* ```
|
|
7294
|
+
*/
|
|
5523
7295
|
constructor(options) {
|
|
5524
7296
|
this.options = options;
|
|
5525
7297
|
}
|
|
7298
|
+
/**
|
|
7299
|
+
* Compares a changed file path against a package path
|
|
7300
|
+
*
|
|
7301
|
+
* Uses custom comparison function if provided, otherwise
|
|
7302
|
+
* checks if the file path starts with the package path.
|
|
7303
|
+
*
|
|
7304
|
+
* @param changedFilePath - Path of the changed file
|
|
7305
|
+
* @param packagePath - Path of the package to check against
|
|
7306
|
+
* @returns True if the file belongs to the package
|
|
7307
|
+
*
|
|
7308
|
+
* @example
|
|
7309
|
+
* ```typescript
|
|
7310
|
+
* // Default comparison
|
|
7311
|
+
* label.compare('packages/a/src/index.ts', 'packages/a');
|
|
7312
|
+
* // true
|
|
7313
|
+
*
|
|
7314
|
+
* // Custom comparison
|
|
7315
|
+
* const label = new ReleaseLabel({
|
|
7316
|
+
* ...options,
|
|
7317
|
+
* compare: (file, pkg) => file.includes(pkg)
|
|
7318
|
+
* });
|
|
7319
|
+
* label.compare('src/packages/a/index.ts', 'packages/a');
|
|
7320
|
+
* // true
|
|
7321
|
+
* ```
|
|
7322
|
+
*/
|
|
5526
7323
|
compare(changedFilePath, packagePath) {
|
|
5527
7324
|
if (typeof this.options.compare === "function") {
|
|
5528
7325
|
return this.options.compare(changedFilePath, packagePath);
|
|
5529
7326
|
}
|
|
5530
7327
|
return changedFilePath.startsWith(packagePath);
|
|
5531
7328
|
}
|
|
7329
|
+
/**
|
|
7330
|
+
* Generates a change label for a single package
|
|
7331
|
+
*
|
|
7332
|
+
* Replaces ${name} placeholder in the label template with
|
|
7333
|
+
* the package path.
|
|
7334
|
+
*
|
|
7335
|
+
* @param packagePath - Path of the package
|
|
7336
|
+
* @param label - Optional custom label template
|
|
7337
|
+
* @returns Formatted change label
|
|
7338
|
+
*
|
|
7339
|
+
* @example
|
|
7340
|
+
* ```typescript
|
|
7341
|
+
* // Default label template
|
|
7342
|
+
* label.toChangeLabel('packages/a');
|
|
7343
|
+
* // 'changed:packages/a'
|
|
7344
|
+
*
|
|
7345
|
+
* // Custom label template
|
|
7346
|
+
* label.toChangeLabel('packages/a', 'modified:${name}');
|
|
7347
|
+
* // 'modified:packages/a'
|
|
7348
|
+
* ```
|
|
7349
|
+
*/
|
|
5532
7350
|
toChangeLabel(packagePath, label = this.options.changePackagesLabel) {
|
|
5533
7351
|
return label.replace("${name}", packagePath);
|
|
5534
7352
|
}
|
|
7353
|
+
/**
|
|
7354
|
+
* Generates change labels for multiple packages
|
|
7355
|
+
*
|
|
7356
|
+
* Maps each package path to a formatted change label.
|
|
7357
|
+
*
|
|
7358
|
+
* @param packages - Array of package paths
|
|
7359
|
+
* @param label - Optional custom label template
|
|
7360
|
+
* @returns Array of formatted change labels
|
|
7361
|
+
*
|
|
7362
|
+
* @example
|
|
7363
|
+
* ```typescript
|
|
7364
|
+
* // Default label template
|
|
7365
|
+
* label.toChangeLabels(['packages/a', 'packages/b']);
|
|
7366
|
+
* // ['changed:packages/a', 'changed:packages/b']
|
|
7367
|
+
*
|
|
7368
|
+
* // Custom label template
|
|
7369
|
+
* label.toChangeLabels(
|
|
7370
|
+
* ['packages/a', 'packages/b'],
|
|
7371
|
+
* 'modified:${name}'
|
|
7372
|
+
* );
|
|
7373
|
+
* // ['modified:packages/a', 'modified:packages/b']
|
|
7374
|
+
* ```
|
|
7375
|
+
*/
|
|
5535
7376
|
toChangeLabels(packages, label = this.options.changePackagesLabel) {
|
|
5536
7377
|
return packages.map((pkg) => this.toChangeLabel(pkg, label));
|
|
5537
7378
|
}
|
|
7379
|
+
/**
|
|
7380
|
+
* Identifies packages affected by changed files
|
|
7381
|
+
*
|
|
7382
|
+
* Checks each changed file against package paths to determine
|
|
7383
|
+
* which packages have been modified.
|
|
7384
|
+
*
|
|
7385
|
+
* @param changedFiles - Array or Set of changed file paths
|
|
7386
|
+
* @param packages - Optional array of package paths to check
|
|
7387
|
+
* @returns Array of affected package paths
|
|
7388
|
+
*
|
|
7389
|
+
* @example
|
|
7390
|
+
* ```typescript
|
|
7391
|
+
* // Check against default packages
|
|
7392
|
+
* label.pick(['packages/a/src/index.ts']);
|
|
7393
|
+
* // ['packages/a']
|
|
7394
|
+
*
|
|
7395
|
+
* // Check specific packages
|
|
7396
|
+
* label.pick(
|
|
7397
|
+
* ['packages/a/index.ts', 'packages/b/test.ts'],
|
|
7398
|
+
* ['packages/a', 'packages/c']
|
|
7399
|
+
* );
|
|
7400
|
+
* // ['packages/a']
|
|
7401
|
+
*
|
|
7402
|
+
* // Using Set of files
|
|
7403
|
+
* label.pick(new Set(['packages/a/index.ts']));
|
|
7404
|
+
* // ['packages/a']
|
|
7405
|
+
* ```
|
|
7406
|
+
*/
|
|
5538
7407
|
pick(changedFiles, packages = this.options.packagesDirectories) {
|
|
5539
7408
|
const result = [];
|
|
5540
7409
|
for (const pkgPath of packages) {
|
|
@@ -5900,6 +7769,31 @@ var import_fs2 = require("fs");
|
|
|
5900
7769
|
var import_scripts_context8 = require("@qlover/scripts-context");
|
|
5901
7770
|
var contentTmplate = "---\n'${name}': '${increment}'\n---\n\n${changelog}";
|
|
5902
7771
|
var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
7772
|
+
/**
|
|
7773
|
+
* Creates a new Changelog plugin instance
|
|
7774
|
+
*
|
|
7775
|
+
* Initializes the plugin with default configuration values and
|
|
7776
|
+
* merges them with provided options.
|
|
7777
|
+
*
|
|
7778
|
+
* Default values:
|
|
7779
|
+
* - increment: 'patch'
|
|
7780
|
+
* - changesetRoot: '.changeset'
|
|
7781
|
+
* - tagTemplate: '${name}@${version}'
|
|
7782
|
+
* - tagPrefix: '${name}'
|
|
7783
|
+
* - tagMatch: '${name}@*'
|
|
7784
|
+
*
|
|
7785
|
+
* @param context - Release context
|
|
7786
|
+
* @param props - Plugin configuration
|
|
7787
|
+
*
|
|
7788
|
+
* @example
|
|
7789
|
+
* ```typescript
|
|
7790
|
+
* const plugin = new Changelog(context, {
|
|
7791
|
+
* increment: 'minor',
|
|
7792
|
+
* changesetRoot: 'custom/changeset',
|
|
7793
|
+
* tagTemplate: 'v${version}'
|
|
7794
|
+
* });
|
|
7795
|
+
* ```
|
|
7796
|
+
*/
|
|
5903
7797
|
constructor(context, props) {
|
|
5904
7798
|
super(context, "changelog", {
|
|
5905
7799
|
increment: "patch",
|
|
@@ -5910,15 +7804,78 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
5910
7804
|
...props
|
|
5911
7805
|
});
|
|
5912
7806
|
}
|
|
7807
|
+
/**
|
|
7808
|
+
* Gets the absolute path to the changeset root directory
|
|
7809
|
+
*
|
|
7810
|
+
* Combines the project root path with the configured changeset
|
|
7811
|
+
* directory path.
|
|
7812
|
+
*
|
|
7813
|
+
* @returns Absolute path to changeset directory
|
|
7814
|
+
*
|
|
7815
|
+
* @example
|
|
7816
|
+
* ```typescript
|
|
7817
|
+
* const root = plugin.changesetRoot;
|
|
7818
|
+
* // '/path/to/project/.changeset'
|
|
7819
|
+
* ```
|
|
7820
|
+
*/
|
|
5913
7821
|
get changesetRoot() {
|
|
5914
7822
|
return (0, import_path2.join)(this.context.rootPath, this.getConfig("changesetRoot"));
|
|
5915
7823
|
}
|
|
7824
|
+
/**
|
|
7825
|
+
* Gets the path to the changeset configuration file
|
|
7826
|
+
*
|
|
7827
|
+
* Returns the absolute path to the config.json file in the
|
|
7828
|
+
* changeset directory.
|
|
7829
|
+
*
|
|
7830
|
+
* @returns Path to changeset config file
|
|
7831
|
+
*
|
|
7832
|
+
* @example
|
|
7833
|
+
* ```typescript
|
|
7834
|
+
* const configPath = plugin.changesetConfigPath;
|
|
7835
|
+
* // '/path/to/project/.changeset/config.json'
|
|
7836
|
+
* ```
|
|
7837
|
+
*/
|
|
5916
7838
|
get changesetConfigPath() {
|
|
5917
7839
|
return (0, import_path2.join)(this.changesetRoot, "config.json");
|
|
5918
7840
|
}
|
|
7841
|
+
/**
|
|
7842
|
+
* Determines if the plugin should be enabled
|
|
7843
|
+
*
|
|
7844
|
+
* Plugin is enabled unless explicitly skipped via configuration.
|
|
7845
|
+
* This allows for conditional changelog generation.
|
|
7846
|
+
*
|
|
7847
|
+
* @returns True if plugin should be enabled
|
|
7848
|
+
*
|
|
7849
|
+
* @example
|
|
7850
|
+
* ```typescript
|
|
7851
|
+
* const plugin = new Changelog(context, { skip: true });
|
|
7852
|
+
* plugin.enabled(); // false
|
|
7853
|
+
*
|
|
7854
|
+
* const plugin2 = new Changelog(context, {});
|
|
7855
|
+
* plugin2.enabled(); // true
|
|
7856
|
+
* ```
|
|
7857
|
+
*/
|
|
5919
7858
|
enabled() {
|
|
5920
7859
|
return !this.getConfig("skip");
|
|
5921
7860
|
}
|
|
7861
|
+
/**
|
|
7862
|
+
* Plugin initialization hook
|
|
7863
|
+
*
|
|
7864
|
+
* Verifies that the changeset directory exists before proceeding
|
|
7865
|
+
* with changelog generation.
|
|
7866
|
+
*
|
|
7867
|
+
* @throws Error if changeset directory does not exist
|
|
7868
|
+
*
|
|
7869
|
+
* @example
|
|
7870
|
+
* ```typescript
|
|
7871
|
+
* const plugin = new Changelog(context, {
|
|
7872
|
+
* changesetRoot: '.changeset'
|
|
7873
|
+
* });
|
|
7874
|
+
*
|
|
7875
|
+
* await plugin.onBefore();
|
|
7876
|
+
* // Throws if .changeset directory doesn't exist
|
|
7877
|
+
* ```
|
|
7878
|
+
*/
|
|
5922
7879
|
async onBefore() {
|
|
5923
7880
|
if (!(0, import_fs2.existsSync)(this.changesetRoot)) {
|
|
5924
7881
|
throw new Error(
|
|
@@ -5927,6 +7884,33 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
5927
7884
|
}
|
|
5928
7885
|
this.logger.debug(`${this.changesetRoot} exists`);
|
|
5929
7886
|
}
|
|
7887
|
+
/**
|
|
7888
|
+
* Updates workspace information with latest versions
|
|
7889
|
+
*
|
|
7890
|
+
* Reads the latest version information from each workspace's
|
|
7891
|
+
* package.json and updates the workspace objects with new
|
|
7892
|
+
* versions and tag names.
|
|
7893
|
+
*
|
|
7894
|
+
* @param workspaces - Array of workspace configurations
|
|
7895
|
+
* @returns Updated workspace configurations
|
|
7896
|
+
*
|
|
7897
|
+
* @example
|
|
7898
|
+
* ```typescript
|
|
7899
|
+
* const workspaces = [
|
|
7900
|
+
* { name: 'pkg-a', path: 'packages/a', version: '1.0.0' }
|
|
7901
|
+
* ];
|
|
7902
|
+
*
|
|
7903
|
+
* const updated = plugin.mergeWorkspaces(workspaces);
|
|
7904
|
+
* // [
|
|
7905
|
+
* // {
|
|
7906
|
+
* // name: 'pkg-a',
|
|
7907
|
+
* // path: 'packages/a',
|
|
7908
|
+
* // version: '1.1.0', // Updated version
|
|
7909
|
+
* // tagName: 'pkg-a@1.1.0'
|
|
7910
|
+
* // }
|
|
7911
|
+
* // ]
|
|
7912
|
+
* ```
|
|
7913
|
+
*/
|
|
5930
7914
|
mergeWorkspaces(workspaces) {
|
|
5931
7915
|
return workspaces.map((workspace) => {
|
|
5932
7916
|
const newPackgeJson = WorkspaceCreator.toWorkspace(
|
|
@@ -5943,6 +7927,25 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
5943
7927
|
return newWorkspace;
|
|
5944
7928
|
});
|
|
5945
7929
|
}
|
|
7930
|
+
/**
|
|
7931
|
+
* Main plugin execution hook
|
|
7932
|
+
*
|
|
7933
|
+
* Generates changelogs for all workspaces in parallel and updates
|
|
7934
|
+
* the context with the results.
|
|
7935
|
+
*
|
|
7936
|
+
* Process:
|
|
7937
|
+
* 1. Generate changelogs for each workspace
|
|
7938
|
+
* 2. Update context with new workspace information
|
|
7939
|
+
*
|
|
7940
|
+
* @param _context - Execution context
|
|
7941
|
+
*
|
|
7942
|
+
* @example
|
|
7943
|
+
* ```typescript
|
|
7944
|
+
* const plugin = new Changelog(context, {});
|
|
7945
|
+
* await plugin.onExec(execContext);
|
|
7946
|
+
* // Generates changelogs for all workspaces
|
|
7947
|
+
* ```
|
|
7948
|
+
*/
|
|
5946
7949
|
async onExec(_context) {
|
|
5947
7950
|
const workspaces = await this.step({
|
|
5948
7951
|
label: "Generate Changelogs",
|
|
@@ -5954,6 +7957,28 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
5954
7957
|
});
|
|
5955
7958
|
this.context.setWorkspaces(workspaces);
|
|
5956
7959
|
}
|
|
7960
|
+
/**
|
|
7961
|
+
* Success hook after plugin execution
|
|
7962
|
+
*
|
|
7963
|
+
* Handles post-changelog generation tasks:
|
|
7964
|
+
* 1. Creates changeset files (if not skipped)
|
|
7965
|
+
* 2. Updates package versions
|
|
7966
|
+
* 3. Restores unchanged packages (if configured)
|
|
7967
|
+
* 4. Updates workspace information
|
|
7968
|
+
*
|
|
7969
|
+
* @example
|
|
7970
|
+
* ```typescript
|
|
7971
|
+
* const plugin = new Changelog(context, {
|
|
7972
|
+
* skipChangeset: false,
|
|
7973
|
+
* ignoreNonUpdatedPackages: true
|
|
7974
|
+
* });
|
|
7975
|
+
*
|
|
7976
|
+
* await plugin.onSuccess();
|
|
7977
|
+
* // - Creates changeset files
|
|
7978
|
+
* // - Updates versions
|
|
7979
|
+
* // - Restores unchanged packages
|
|
7980
|
+
* ```
|
|
7981
|
+
*/
|
|
5957
7982
|
async onSuccess() {
|
|
5958
7983
|
const workspaces = this.context.workspaces;
|
|
5959
7984
|
if (!this.getConfig("skipChangeset")) {
|
|
@@ -5977,6 +8002,25 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
5977
8002
|
this.logger.debug("new workspaces", newWorkspaces);
|
|
5978
8003
|
this.context.setWorkspaces(newWorkspaces);
|
|
5979
8004
|
}
|
|
8005
|
+
/**
|
|
8006
|
+
* Restores unchanged packages to their original state
|
|
8007
|
+
*
|
|
8008
|
+
* When ignoreNonUpdatedPackages is enabled, this method:
|
|
8009
|
+
* 1. Identifies packages without changes
|
|
8010
|
+
* 2. Uses git restore to revert them to original state
|
|
8011
|
+
*
|
|
8012
|
+
* @example
|
|
8013
|
+
* ```typescript
|
|
8014
|
+
* // With changed and unchanged packages
|
|
8015
|
+
* context.options.workspaces = {
|
|
8016
|
+
* packages: ['pkg-a', 'pkg-b', 'pkg-c'],
|
|
8017
|
+
* changedPaths: ['pkg-a', 'pkg-b']
|
|
8018
|
+
* };
|
|
8019
|
+
*
|
|
8020
|
+
* await plugin.restoreIgnorePackages();
|
|
8021
|
+
* // Restores 'pkg-c' to original state
|
|
8022
|
+
* ```
|
|
8023
|
+
*/
|
|
5980
8024
|
async restoreIgnorePackages() {
|
|
5981
8025
|
const { changedPaths = [], packages = [] } = this.context.getOptions(
|
|
5982
8026
|
"workspaces"
|
|
@@ -5989,12 +8033,60 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
5989
8033
|
await this.shell.exec(["git", "restore", ...noChangedPackages]);
|
|
5990
8034
|
}
|
|
5991
8035
|
}
|
|
8036
|
+
/**
|
|
8037
|
+
* Gets the tag prefix for a workspace
|
|
8038
|
+
*
|
|
8039
|
+
* Formats the configured tag prefix template with workspace
|
|
8040
|
+
* information. Used for generating Git tag names.
|
|
8041
|
+
*
|
|
8042
|
+
* @param workspace - Workspace configuration
|
|
8043
|
+
* @returns Formatted tag prefix
|
|
8044
|
+
*
|
|
8045
|
+
* @example
|
|
8046
|
+
* ```typescript
|
|
8047
|
+
* const workspace = {
|
|
8048
|
+
* name: 'pkg-a',
|
|
8049
|
+
* version: '1.0.0'
|
|
8050
|
+
* };
|
|
8051
|
+
*
|
|
8052
|
+
* const prefix = plugin.getTagPrefix(workspace);
|
|
8053
|
+
* // With default template: 'pkg-a'
|
|
8054
|
+
* // With custom template: 'v1.0.0'
|
|
8055
|
+
* ```
|
|
8056
|
+
*/
|
|
5992
8057
|
getTagPrefix(workspace) {
|
|
5993
8058
|
return import_scripts_context8.Shell.format(
|
|
5994
8059
|
this.getConfig("tagPrefix"),
|
|
5995
8060
|
workspace
|
|
5996
8061
|
);
|
|
5997
8062
|
}
|
|
8063
|
+
/**
|
|
8064
|
+
* Generates a changelog for a workspace
|
|
8065
|
+
*
|
|
8066
|
+
* Creates a changelog by:
|
|
8067
|
+
* 1. Getting the appropriate tag name
|
|
8068
|
+
* 2. Retrieving commits since last tag
|
|
8069
|
+
* 3. Formatting commits into changelog entries
|
|
8070
|
+
*
|
|
8071
|
+
* @param workspace - Workspace configuration
|
|
8072
|
+
* @returns Updated workspace with changelog
|
|
8073
|
+
*
|
|
8074
|
+
* @example
|
|
8075
|
+
* ```typescript
|
|
8076
|
+
* const workspace = {
|
|
8077
|
+
* name: 'pkg-a',
|
|
8078
|
+
* path: 'packages/a',
|
|
8079
|
+
* version: '1.0.0'
|
|
8080
|
+
* };
|
|
8081
|
+
*
|
|
8082
|
+
* const updated = await plugin.generateChangelog(workspace);
|
|
8083
|
+
* // {
|
|
8084
|
+
* // ...workspace,
|
|
8085
|
+
* // lastTag: 'pkg-a@1.0.0',
|
|
8086
|
+
* // changelog: '- feat: new feature\n- fix: bug fix'
|
|
8087
|
+
* // }
|
|
8088
|
+
* ```
|
|
8089
|
+
*/
|
|
5998
8090
|
async generateChangelog(workspace) {
|
|
5999
8091
|
let tagName = await this.getTagName(workspace);
|
|
6000
8092
|
if (workspace.lastTag) {
|
|
@@ -6020,6 +8112,32 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
6020
8112
|
changelog: changelog.join("\n")
|
|
6021
8113
|
};
|
|
6022
8114
|
}
|
|
8115
|
+
/**
|
|
8116
|
+
* Generates a tag name for a workspace
|
|
8117
|
+
*
|
|
8118
|
+
* Uses the configured tag template to generate a tag name
|
|
8119
|
+
* for the workspace. Handles errors by providing a fallback.
|
|
8120
|
+
*
|
|
8121
|
+
* @param workspace - Workspace configuration
|
|
8122
|
+
* @returns Generated tag name
|
|
8123
|
+
*
|
|
8124
|
+
* @example
|
|
8125
|
+
* ```typescript
|
|
8126
|
+
* // With default template
|
|
8127
|
+
* const tag = plugin.generateTagName({
|
|
8128
|
+
* name: 'pkg-a',
|
|
8129
|
+
* version: '1.0.0'
|
|
8130
|
+
* });
|
|
8131
|
+
* // 'pkg-a@1.0.0'
|
|
8132
|
+
*
|
|
8133
|
+
* // With error (fallback)
|
|
8134
|
+
* const tag = plugin.generateTagName({
|
|
8135
|
+
* name: 'pkg-a'
|
|
8136
|
+
* });
|
|
8137
|
+
* // 'pkg-a-v0.0.0'
|
|
8138
|
+
* ```
|
|
8139
|
+
* @private
|
|
8140
|
+
*/
|
|
6023
8141
|
generateTagName(workspace) {
|
|
6024
8142
|
try {
|
|
6025
8143
|
const tagTemplate = this.getConfig("tagTemplate");
|
|
@@ -6032,6 +8150,38 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
6032
8150
|
return `${workspace.name}-v0.0.0`;
|
|
6033
8151
|
}
|
|
6034
8152
|
}
|
|
8153
|
+
/**
|
|
8154
|
+
* Gets the appropriate tag name for a workspace
|
|
8155
|
+
*
|
|
8156
|
+
* Attempts to find the latest tag for the workspace, falling back
|
|
8157
|
+
* to generating a new tag if none exists. Uses git commands to
|
|
8158
|
+
* find and sort tags by creation date.
|
|
8159
|
+
*
|
|
8160
|
+
* Process:
|
|
8161
|
+
* 1. Generate current tag pattern
|
|
8162
|
+
* 2. Search for existing tags matching pattern
|
|
8163
|
+
* 3. Return latest tag or generate new one
|
|
8164
|
+
*
|
|
8165
|
+
* @param workspace - Workspace configuration
|
|
8166
|
+
* @returns Promise resolving to tag name
|
|
8167
|
+
*
|
|
8168
|
+
* @example
|
|
8169
|
+
* ```typescript
|
|
8170
|
+
* // With existing tags
|
|
8171
|
+
* const tag = await plugin.getTagName({
|
|
8172
|
+
* name: 'pkg-a',
|
|
8173
|
+
* version: '1.0.0'
|
|
8174
|
+
* });
|
|
8175
|
+
* // Returns latest matching tag: 'pkg-a@0.9.0'
|
|
8176
|
+
*
|
|
8177
|
+
* // Without existing tags
|
|
8178
|
+
* const tag = await plugin.getTagName({
|
|
8179
|
+
* name: 'pkg-b',
|
|
8180
|
+
* version: '1.0.0'
|
|
8181
|
+
* });
|
|
8182
|
+
* // Returns new tag: 'pkg-b@1.0.0'
|
|
8183
|
+
* ```
|
|
8184
|
+
*/
|
|
6035
8185
|
async getTagName(workspace) {
|
|
6036
8186
|
try {
|
|
6037
8187
|
const currentTagPattern = this.generateTagName(workspace);
|
|
@@ -6058,6 +8208,31 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
6058
8208
|
return fallbackTag;
|
|
6059
8209
|
}
|
|
6060
8210
|
}
|
|
8211
|
+
/**
|
|
8212
|
+
* Determines the version increment type
|
|
8213
|
+
*
|
|
8214
|
+
* Checks for increment labels in the following order:
|
|
8215
|
+
* 1. 'increment:major' label
|
|
8216
|
+
* 2. 'increment:minor' label
|
|
8217
|
+
* 3. Configured increment value
|
|
8218
|
+
* 4. Default to 'patch'
|
|
8219
|
+
*
|
|
8220
|
+
* @returns Version increment type
|
|
8221
|
+
*
|
|
8222
|
+
* @example
|
|
8223
|
+
* ```typescript
|
|
8224
|
+
* // With labels
|
|
8225
|
+
* context.options.workspaces.changeLabels = ['increment:major'];
|
|
8226
|
+
* plugin.getIncrement(); // 'major'
|
|
8227
|
+
*
|
|
8228
|
+
* // With configuration
|
|
8229
|
+
* const plugin = new Changelog(context, { increment: 'minor' });
|
|
8230
|
+
* plugin.getIncrement(); // 'minor'
|
|
8231
|
+
*
|
|
8232
|
+
* // Default
|
|
8233
|
+
* plugin.getIncrement(); // 'patch'
|
|
8234
|
+
* ```
|
|
8235
|
+
*/
|
|
6061
8236
|
getIncrement() {
|
|
6062
8237
|
const lables = this.context.getOptions("workspaces.changeLabels");
|
|
6063
8238
|
if (Array.isArray(lables) && lables.length > 0) {
|
|
@@ -6071,6 +8246,43 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
6071
8246
|
const increment = this.getConfig("increment", "patch");
|
|
6072
8247
|
return increment;
|
|
6073
8248
|
}
|
|
8249
|
+
/**
|
|
8250
|
+
* Generates a changeset file for a workspace
|
|
8251
|
+
*
|
|
8252
|
+
* Creates a changeset file containing version increment
|
|
8253
|
+
* information and changelog content. Handles dry run mode
|
|
8254
|
+
* and existing files.
|
|
8255
|
+
*
|
|
8256
|
+
* File format:
|
|
8257
|
+
* ```yaml
|
|
8258
|
+
* ---
|
|
8259
|
+
* 'package-name': 'increment-type'
|
|
8260
|
+
* ---
|
|
8261
|
+
*
|
|
8262
|
+
* changelog content
|
|
8263
|
+
* ```
|
|
8264
|
+
*
|
|
8265
|
+
* @param workspace - Workspace configuration
|
|
8266
|
+
*
|
|
8267
|
+
* @example
|
|
8268
|
+
* ```typescript
|
|
8269
|
+
* const workspace = {
|
|
8270
|
+
* name: 'pkg-a',
|
|
8271
|
+
* version: '1.0.0',
|
|
8272
|
+
* changelog: '- feat: new feature'
|
|
8273
|
+
* };
|
|
8274
|
+
*
|
|
8275
|
+
* await plugin.generateChangesetFile(workspace);
|
|
8276
|
+
* // Creates .changeset/pkg-a-1.0.0.md
|
|
8277
|
+
* ```
|
|
8278
|
+
*
|
|
8279
|
+
* @example Dry run
|
|
8280
|
+
* ```typescript
|
|
8281
|
+
* context.dryRun = true;
|
|
8282
|
+
* await plugin.generateChangesetFile(workspace);
|
|
8283
|
+
* // Logs file content without creating file
|
|
8284
|
+
* ```
|
|
8285
|
+
*/
|
|
6074
8286
|
async generateChangesetFile(workspace) {
|
|
6075
8287
|
const { name, version: version2 } = workspace;
|
|
6076
8288
|
const changesetName = `${name}-${version2}`.replace(/[\/\\]/g, "_");
|
|
@@ -6104,15 +8316,89 @@ var innerTuples = [
|
|
|
6104
8316
|
];
|
|
6105
8317
|
var defaultName = "release";
|
|
6106
8318
|
var ReleaseTask = class {
|
|
8319
|
+
/**
|
|
8320
|
+
* Creates a new ReleaseTask instance
|
|
8321
|
+
*
|
|
8322
|
+
* Initializes the release context and sets up plugin configuration.
|
|
8323
|
+
* Supports custom executors and plugin configurations.
|
|
8324
|
+
*
|
|
8325
|
+
* @param options - Release context configuration
|
|
8326
|
+
* @param executor - Custom async executor (optional)
|
|
8327
|
+
* @param defaultTuples - Plugin configuration tuples (optional)
|
|
8328
|
+
*
|
|
8329
|
+
* @example
|
|
8330
|
+
* ```typescript
|
|
8331
|
+
* // Basic initialization
|
|
8332
|
+
* const task = new ReleaseTask({
|
|
8333
|
+
* rootPath: '/path/to/project',
|
|
8334
|
+
* sourceBranch: 'main'
|
|
8335
|
+
* });
|
|
8336
|
+
*
|
|
8337
|
+
* // With custom executor and plugins
|
|
8338
|
+
* const task = new ReleaseTask(
|
|
8339
|
+
* { rootPath: '/path/to/project' },
|
|
8340
|
+
* new AsyncExecutor(),
|
|
8341
|
+
* [tuple(CustomPlugin, { option: 'value' })]
|
|
8342
|
+
* );
|
|
8343
|
+
* ```
|
|
8344
|
+
*/
|
|
6107
8345
|
constructor(options = {}, executor = new import_fe_corekit.AsyncExecutor(), defaultTuples = innerTuples) {
|
|
6108
8346
|
this.executor = executor;
|
|
6109
8347
|
this.defaultTuples = defaultTuples;
|
|
6110
8348
|
this.context = new ReleaseContext(defaultName, options);
|
|
6111
8349
|
}
|
|
8350
|
+
/**
|
|
8351
|
+
* Release context instance
|
|
8352
|
+
* @protected
|
|
8353
|
+
*/
|
|
6112
8354
|
context;
|
|
8355
|
+
/**
|
|
8356
|
+
* Gets the current release context
|
|
8357
|
+
*
|
|
8358
|
+
* @returns Release context instance
|
|
8359
|
+
*
|
|
8360
|
+
* @example
|
|
8361
|
+
* ```typescript
|
|
8362
|
+
* const task = new ReleaseTask();
|
|
8363
|
+
* const context = task.getContext();
|
|
8364
|
+
*
|
|
8365
|
+
* console.log(context.releaseEnv);
|
|
8366
|
+
* console.log(context.sourceBranch);
|
|
8367
|
+
* ```
|
|
8368
|
+
*/
|
|
6113
8369
|
getContext() {
|
|
6114
8370
|
return this.context;
|
|
6115
8371
|
}
|
|
8372
|
+
/**
|
|
8373
|
+
* Loads and configures plugins for the release task
|
|
8374
|
+
*
|
|
8375
|
+
* Combines default and external plugins, initializes them with
|
|
8376
|
+
* the current context, and configures special cases like the
|
|
8377
|
+
* Workspaces plugin.
|
|
8378
|
+
*
|
|
8379
|
+
* Plugin Loading Process:
|
|
8380
|
+
* 1. Merge default and external plugins
|
|
8381
|
+
* 2. Initialize plugins with context
|
|
8382
|
+
* 3. Configure special plugins
|
|
8383
|
+
* 4. Add plugins to executor
|
|
8384
|
+
*
|
|
8385
|
+
* @param externalTuples - Additional plugin configurations
|
|
8386
|
+
* @returns Array of initialized plugins
|
|
8387
|
+
*
|
|
8388
|
+
* @example Basic usage
|
|
8389
|
+
* ```typescript
|
|
8390
|
+
* const task = new ReleaseTask();
|
|
8391
|
+
* const plugins = await task.usePlugins();
|
|
8392
|
+
* ```
|
|
8393
|
+
*
|
|
8394
|
+
* @example Custom plugins
|
|
8395
|
+
* ```typescript
|
|
8396
|
+
* const task = new ReleaseTask();
|
|
8397
|
+
* const plugins = await task.usePlugins([
|
|
8398
|
+
* tuple(CustomPlugin, { option: 'value' })
|
|
8399
|
+
* ]);
|
|
8400
|
+
* ```
|
|
8401
|
+
*/
|
|
6116
8402
|
async usePlugins(externalTuples) {
|
|
6117
8403
|
externalTuples = externalTuples || this.context.options.plugins || [];
|
|
6118
8404
|
const plugins = await loaderPluginsFromPluginTuples(this.context, [
|
|
@@ -6127,12 +8413,65 @@ var ReleaseTask = class {
|
|
|
6127
8413
|
});
|
|
6128
8414
|
return plugins;
|
|
6129
8415
|
}
|
|
8416
|
+
/**
|
|
8417
|
+
* Executes the release task
|
|
8418
|
+
*
|
|
8419
|
+
* Internal method that runs the task through the executor.
|
|
8420
|
+
* Preserves the context through the execution chain.
|
|
8421
|
+
*
|
|
8422
|
+
* @returns Execution result
|
|
8423
|
+
* @internal
|
|
8424
|
+
*/
|
|
6130
8425
|
async run() {
|
|
6131
8426
|
return this.executor.exec(
|
|
6132
8427
|
this.context,
|
|
6133
8428
|
(context) => Promise.resolve(context)
|
|
6134
8429
|
);
|
|
6135
8430
|
}
|
|
8431
|
+
/**
|
|
8432
|
+
* Main entry point for executing the release task
|
|
8433
|
+
*
|
|
8434
|
+
* Checks environment conditions, loads plugins, and executes
|
|
8435
|
+
* the release process. Supports additional plugin configuration
|
|
8436
|
+
* at execution time.
|
|
8437
|
+
*
|
|
8438
|
+
* Environment Control:
|
|
8439
|
+
* - Checks FE_RELEASE environment variable
|
|
8440
|
+
* - Skips release if FE_RELEASE=false
|
|
8441
|
+
*
|
|
8442
|
+
* @param externalTuples - Additional plugin configurations
|
|
8443
|
+
* @returns Execution result
|
|
8444
|
+
* @throws Error if release is skipped via environment variable
|
|
8445
|
+
*
|
|
8446
|
+
* @example Basic execution
|
|
8447
|
+
* ```typescript
|
|
8448
|
+
* const task = new ReleaseTask();
|
|
8449
|
+
* await task.exec();
|
|
8450
|
+
* ```
|
|
8451
|
+
*
|
|
8452
|
+
* @example With additional plugins
|
|
8453
|
+
* ```typescript
|
|
8454
|
+
* const task = new ReleaseTask();
|
|
8455
|
+
* await task.exec([
|
|
8456
|
+
* tuple(CustomPlugin, { option: 'value' })
|
|
8457
|
+
* ]);
|
|
8458
|
+
* ```
|
|
8459
|
+
*
|
|
8460
|
+
* @example Environment control
|
|
8461
|
+
* ```typescript
|
|
8462
|
+
* // Skip release
|
|
8463
|
+
* process.env.FE_RELEASE = 'false';
|
|
8464
|
+
*
|
|
8465
|
+
* const task = new ReleaseTask();
|
|
8466
|
+
* try {
|
|
8467
|
+
* await task.exec();
|
|
8468
|
+
* } catch (e) {
|
|
8469
|
+
* if (e.message === 'Skip Release') {
|
|
8470
|
+
* console.log('Release skipped via environment variable');
|
|
8471
|
+
* }
|
|
8472
|
+
* }
|
|
8473
|
+
* ```
|
|
8474
|
+
*/
|
|
6136
8475
|
async exec(externalTuples) {
|
|
6137
8476
|
if (this.context.env.get("FE_RELEASE") === "false") {
|
|
6138
8477
|
throw new Error("Skip Release");
|