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