@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/index.js
CHANGED
|
@@ -2392,6 +2392,31 @@ import {
|
|
|
2392
2392
|
ScriptContext
|
|
2393
2393
|
} from "@qlover/scripts-context";
|
|
2394
2394
|
var ReleaseContext = class extends ScriptContext {
|
|
2395
|
+
/**
|
|
2396
|
+
* Creates a new ReleaseContext instance
|
|
2397
|
+
*
|
|
2398
|
+
* Initializes the context with provided options and sets up
|
|
2399
|
+
* default values for required configuration:
|
|
2400
|
+
* - rootPath: Defaults to current working directory
|
|
2401
|
+
* - sourceBranch: Uses environment variables or default
|
|
2402
|
+
* - releaseEnv: Uses environment variables or 'development'
|
|
2403
|
+
*
|
|
2404
|
+
* Environment Variable Priority:
|
|
2405
|
+
* - sourceBranch: FE_RELEASE_BRANCH > FE_RELEASE_SOURCE_BRANCH > DEFAULT_SOURCE_BRANCH
|
|
2406
|
+
* - releaseEnv: FE_RELEASE_ENV > NODE_ENV > 'development'
|
|
2407
|
+
*
|
|
2408
|
+
* @param name - Unique identifier for this release context
|
|
2409
|
+
* @param options - Configuration options
|
|
2410
|
+
*
|
|
2411
|
+
* @example
|
|
2412
|
+
* ```typescript
|
|
2413
|
+
* const context = new ReleaseContext('web-app', {
|
|
2414
|
+
* rootPath: '/projects/web-app',
|
|
2415
|
+
* sourceBranch: 'main',
|
|
2416
|
+
* releaseEnv: 'production'
|
|
2417
|
+
* });
|
|
2418
|
+
* ```
|
|
2419
|
+
*/
|
|
2395
2420
|
constructor(name, options) {
|
|
2396
2421
|
super(name, options);
|
|
2397
2422
|
if (!this.options.rootPath) {
|
|
@@ -2408,27 +2433,124 @@ var ReleaseContext = class extends ScriptContext {
|
|
|
2408
2433
|
});
|
|
2409
2434
|
}
|
|
2410
2435
|
}
|
|
2436
|
+
/**
|
|
2437
|
+
* Gets the root path of the project
|
|
2438
|
+
*
|
|
2439
|
+
* @returns Absolute path to project root
|
|
2440
|
+
*
|
|
2441
|
+
* @example
|
|
2442
|
+
* ```typescript
|
|
2443
|
+
* const root = context.rootPath;
|
|
2444
|
+
* // '/path/to/project'
|
|
2445
|
+
* ```
|
|
2446
|
+
*/
|
|
2411
2447
|
get rootPath() {
|
|
2412
2448
|
return this.getOptions("rootPath");
|
|
2413
2449
|
}
|
|
2450
|
+
/**
|
|
2451
|
+
* Gets the source branch for the release
|
|
2452
|
+
*
|
|
2453
|
+
* @returns Branch name to use as source
|
|
2454
|
+
*
|
|
2455
|
+
* @example
|
|
2456
|
+
* ```typescript
|
|
2457
|
+
* const branch = context.sourceBranch;
|
|
2458
|
+
* // 'main' or custom branch name
|
|
2459
|
+
* ```
|
|
2460
|
+
*/
|
|
2414
2461
|
get sourceBranch() {
|
|
2415
2462
|
return this.getOptions("sourceBranch");
|
|
2416
2463
|
}
|
|
2464
|
+
/**
|
|
2465
|
+
* Gets the release environment
|
|
2466
|
+
*
|
|
2467
|
+
* @returns Environment name (e.g., 'development', 'production')
|
|
2468
|
+
*
|
|
2469
|
+
* @example
|
|
2470
|
+
* ```typescript
|
|
2471
|
+
* const env = context.releaseEnv;
|
|
2472
|
+
* // 'development' or custom environment
|
|
2473
|
+
* ```
|
|
2474
|
+
*/
|
|
2417
2475
|
get releaseEnv() {
|
|
2418
2476
|
return this.getOptions("releaseEnv");
|
|
2419
2477
|
}
|
|
2478
|
+
/**
|
|
2479
|
+
* Gets all configured workspaces
|
|
2480
|
+
*
|
|
2481
|
+
* @returns Array of workspace configurations or undefined
|
|
2482
|
+
*
|
|
2483
|
+
* @example
|
|
2484
|
+
* ```typescript
|
|
2485
|
+
* const allWorkspaces = context.workspaces;
|
|
2486
|
+
* // [{ name: 'pkg-a', version: '1.0.0', ... }]
|
|
2487
|
+
* ```
|
|
2488
|
+
*/
|
|
2420
2489
|
get workspaces() {
|
|
2421
2490
|
return this.getOptions("workspaces.workspaces");
|
|
2422
2491
|
}
|
|
2492
|
+
/**
|
|
2493
|
+
* Gets the current active workspace
|
|
2494
|
+
*
|
|
2495
|
+
* @returns Current workspace configuration or undefined
|
|
2496
|
+
*
|
|
2497
|
+
* @example
|
|
2498
|
+
* ```typescript
|
|
2499
|
+
* const current = context.workspace;
|
|
2500
|
+
* // { name: 'pkg-a', version: '1.0.0', ... }
|
|
2501
|
+
* ```
|
|
2502
|
+
*/
|
|
2423
2503
|
get workspace() {
|
|
2424
2504
|
return this.getOptions("workspaces.workspace");
|
|
2425
2505
|
}
|
|
2506
|
+
/**
|
|
2507
|
+
* Sets the workspace configurations
|
|
2508
|
+
*
|
|
2509
|
+
* Updates the workspace list while preserving other workspace settings
|
|
2510
|
+
*
|
|
2511
|
+
* @param workspaces - Array of workspace configurations
|
|
2512
|
+
*
|
|
2513
|
+
* @example
|
|
2514
|
+
* ```typescript
|
|
2515
|
+
* context.setWorkspaces([{
|
|
2516
|
+
* name: 'pkg-a',
|
|
2517
|
+
* version: '1.0.0',
|
|
2518
|
+
* path: 'packages/a'
|
|
2519
|
+
* }]);
|
|
2520
|
+
* ```
|
|
2521
|
+
*/
|
|
2426
2522
|
setWorkspaces(workspaces) {
|
|
2427
2523
|
this.options.workspaces = {
|
|
2428
2524
|
...this.options.workspaces,
|
|
2429
2525
|
workspaces
|
|
2430
2526
|
};
|
|
2431
2527
|
}
|
|
2528
|
+
/**
|
|
2529
|
+
* Gets package.json data for the current workspace
|
|
2530
|
+
*
|
|
2531
|
+
* Provides type-safe access to package.json fields with optional
|
|
2532
|
+
* path and default value support.
|
|
2533
|
+
*
|
|
2534
|
+
* @param key - Optional dot-notation path to specific field
|
|
2535
|
+
* @param defaultValue - Default value if field not found
|
|
2536
|
+
* @returns Package data of type T
|
|
2537
|
+
* @throws Error if package.json not found
|
|
2538
|
+
*
|
|
2539
|
+
* @example Basic usage
|
|
2540
|
+
* ```typescript
|
|
2541
|
+
* // Get entire package.json
|
|
2542
|
+
* const pkg = context.getPkg();
|
|
2543
|
+
*
|
|
2544
|
+
* // Get specific field
|
|
2545
|
+
* const version = context.getPkg<string>('version');
|
|
2546
|
+
*
|
|
2547
|
+
* // Get nested field with default
|
|
2548
|
+
* const script = context.getPkg<string>(
|
|
2549
|
+
* 'scripts.build',
|
|
2550
|
+
* 'echo "No build script"'
|
|
2551
|
+
* );
|
|
2552
|
+
* ```
|
|
2553
|
+
*/
|
|
2432
2554
|
getPkg(key, defaultValue) {
|
|
2433
2555
|
const packageJson = this.workspace?.packageJson;
|
|
2434
2556
|
if (!packageJson) {
|
|
@@ -2439,6 +2561,28 @@ var ReleaseContext = class extends ScriptContext {
|
|
|
2439
2561
|
}
|
|
2440
2562
|
return (0, import_get.default)(packageJson, key, defaultValue);
|
|
2441
2563
|
}
|
|
2564
|
+
/**
|
|
2565
|
+
* Generates template context for string interpolation
|
|
2566
|
+
*
|
|
2567
|
+
* Combines context options, workspace data, and specific paths
|
|
2568
|
+
* for use in template processing. Includes deprecated fields
|
|
2569
|
+
* for backward compatibility.
|
|
2570
|
+
*
|
|
2571
|
+
* @returns Combined template context
|
|
2572
|
+
*
|
|
2573
|
+
* @example
|
|
2574
|
+
* ```typescript
|
|
2575
|
+
* const context = releaseContext.getTemplateContext();
|
|
2576
|
+
* // {
|
|
2577
|
+
* // publishPath: 'packages/my-pkg',
|
|
2578
|
+
* // env: 'production', // deprecated
|
|
2579
|
+
* // branch: 'main', // deprecated
|
|
2580
|
+
* // releaseEnv: 'production', // use this instead
|
|
2581
|
+
* // sourceBranch: 'main', // use this instead
|
|
2582
|
+
* // ...other options
|
|
2583
|
+
* // }
|
|
2584
|
+
* ```
|
|
2585
|
+
*/
|
|
2442
2586
|
getTemplateContext() {
|
|
2443
2587
|
return {
|
|
2444
2588
|
...this.getOptions(),
|
|
@@ -2449,6 +2593,28 @@ var ReleaseContext = class extends ScriptContext {
|
|
|
2449
2593
|
branch: this.sourceBranch
|
|
2450
2594
|
};
|
|
2451
2595
|
}
|
|
2596
|
+
/**
|
|
2597
|
+
* Executes changeset CLI commands
|
|
2598
|
+
*
|
|
2599
|
+
* Automatically detects and uses appropriate package manager
|
|
2600
|
+
* (pnpm or npx) to run changeset commands.
|
|
2601
|
+
*
|
|
2602
|
+
* @param name - Changeset command name
|
|
2603
|
+
* @param args - Optional command arguments
|
|
2604
|
+
* @returns Command output
|
|
2605
|
+
*
|
|
2606
|
+
* @example Version bump
|
|
2607
|
+
* ```typescript
|
|
2608
|
+
* // Bump version with snapshot
|
|
2609
|
+
* await context.runChangesetsCli('version', ['--snapshot', 'alpha']);
|
|
2610
|
+
*
|
|
2611
|
+
* // Create new changeset
|
|
2612
|
+
* await context.runChangesetsCli('add');
|
|
2613
|
+
*
|
|
2614
|
+
* // Status check
|
|
2615
|
+
* await context.runChangesetsCli('status');
|
|
2616
|
+
* ```
|
|
2617
|
+
*/
|
|
2452
2618
|
async runChangesetsCli(name, args) {
|
|
2453
2619
|
let packageManager = "pnpm";
|
|
2454
2620
|
try {
|
|
@@ -2483,6 +2649,28 @@ var DEFAULT_RELEASE_CONFIG = {
|
|
|
2483
2649
|
batchTagName: "batch-${length}-packages-${timestamp}"
|
|
2484
2650
|
};
|
|
2485
2651
|
var ReleaseParams = class {
|
|
2652
|
+
/**
|
|
2653
|
+
* Creates a new ReleaseParams instance
|
|
2654
|
+
*
|
|
2655
|
+
* Initializes with logger for debug output and optional configuration
|
|
2656
|
+
* overrides. Uses default configuration values for any unspecified options.
|
|
2657
|
+
*
|
|
2658
|
+
* @param logger - Logger instance for debug output
|
|
2659
|
+
* @param config - Optional configuration overrides
|
|
2660
|
+
*
|
|
2661
|
+
* @example
|
|
2662
|
+
* ```typescript
|
|
2663
|
+
* // Basic initialization
|
|
2664
|
+
* const params = new ReleaseParams(logger);
|
|
2665
|
+
*
|
|
2666
|
+
* // With custom configuration
|
|
2667
|
+
* const params = new ReleaseParams(logger, {
|
|
2668
|
+
* maxWorkspace: 5,
|
|
2669
|
+
* multiWorkspaceSeparator: '-',
|
|
2670
|
+
* workspaceVersionSeparator: '#'
|
|
2671
|
+
* });
|
|
2672
|
+
* ```
|
|
2673
|
+
*/
|
|
2486
2674
|
constructor(logger, config = {}) {
|
|
2487
2675
|
this.logger = logger;
|
|
2488
2676
|
this.config = {
|
|
@@ -2490,7 +2678,49 @@ var ReleaseParams = class {
|
|
|
2490
2678
|
...config
|
|
2491
2679
|
};
|
|
2492
2680
|
}
|
|
2681
|
+
/**
|
|
2682
|
+
* Current configuration
|
|
2683
|
+
* @private
|
|
2684
|
+
*/
|
|
2493
2685
|
config;
|
|
2686
|
+
/**
|
|
2687
|
+
* Generates a release branch name for a single package
|
|
2688
|
+
*
|
|
2689
|
+
* Uses the branch name template from shared configuration or
|
|
2690
|
+
* falls back to the default template 'release-${tagName}'.
|
|
2691
|
+
* Supports variable interpolation in the template.
|
|
2692
|
+
*
|
|
2693
|
+
* Template Variables:
|
|
2694
|
+
* - ${pkgName}: Package name
|
|
2695
|
+
* - ${releaseName}: Release name (same as pkgName)
|
|
2696
|
+
* - ${tagName}: Release tag
|
|
2697
|
+
* - All shared config properties
|
|
2698
|
+
*
|
|
2699
|
+
* @param releaseName - Name of the package being released
|
|
2700
|
+
* @param tagName - Version tag for the release
|
|
2701
|
+
* @param shared - Shared configuration with branch template
|
|
2702
|
+
* @returns Formatted branch name
|
|
2703
|
+
* @throws Error if branch name template is not a string
|
|
2704
|
+
*
|
|
2705
|
+
* @example
|
|
2706
|
+
* ```typescript
|
|
2707
|
+
* // With default template
|
|
2708
|
+
* const branch = params.getReleaseBranchName(
|
|
2709
|
+
* 'my-pkg',
|
|
2710
|
+
* 'v1.0.0',
|
|
2711
|
+
* {}
|
|
2712
|
+
* );
|
|
2713
|
+
* // 'release-v1.0.0'
|
|
2714
|
+
*
|
|
2715
|
+
* // With custom template
|
|
2716
|
+
* const branch = params.getReleaseBranchName(
|
|
2717
|
+
* 'my-pkg',
|
|
2718
|
+
* 'v1.0.0',
|
|
2719
|
+
* { branchName: '${pkgName}-release-${tagName}' }
|
|
2720
|
+
* );
|
|
2721
|
+
* // 'my-pkg-release-v1.0.0'
|
|
2722
|
+
* ```
|
|
2723
|
+
*/
|
|
2494
2724
|
getReleaseBranchName(releaseName, tagName, shared) {
|
|
2495
2725
|
const branchNameTpl = shared.branchName || "release-${tagName}";
|
|
2496
2726
|
if (typeof branchNameTpl !== "string") {
|
|
@@ -2505,6 +2735,49 @@ var ReleaseParams = class {
|
|
|
2505
2735
|
...shared
|
|
2506
2736
|
});
|
|
2507
2737
|
}
|
|
2738
|
+
/**
|
|
2739
|
+
* Generates a release branch name for multiple packages
|
|
2740
|
+
*
|
|
2741
|
+
* Uses the batch branch name template from configuration.
|
|
2742
|
+
* Supports variable interpolation with additional batch-specific
|
|
2743
|
+
* variables.
|
|
2744
|
+
*
|
|
2745
|
+
* Template Variables:
|
|
2746
|
+
* - ${pkgName}: Package name
|
|
2747
|
+
* - ${releaseName}: Combined release name
|
|
2748
|
+
* - ${tagName}: Combined tag name
|
|
2749
|
+
* - ${length}: Number of packages
|
|
2750
|
+
* - ${timestamp}: Current timestamp
|
|
2751
|
+
* - All shared config properties
|
|
2752
|
+
*
|
|
2753
|
+
* @param releaseName - Combined name of packages
|
|
2754
|
+
* @param tagName - Combined version tag
|
|
2755
|
+
* @param shared - Shared configuration
|
|
2756
|
+
* @param length - Number of packages in batch
|
|
2757
|
+
* @returns Formatted batch branch name
|
|
2758
|
+
* @throws Error if branch name template is not a string
|
|
2759
|
+
*
|
|
2760
|
+
* @example
|
|
2761
|
+
* ```typescript
|
|
2762
|
+
* // With default template
|
|
2763
|
+
* const branch = params.getBatchReleaseBranchName(
|
|
2764
|
+
* 'pkg-a@1.0.0_pkg-b@2.0.0',
|
|
2765
|
+
* 'batch-2-packages-1234567890',
|
|
2766
|
+
* {},
|
|
2767
|
+
* 2
|
|
2768
|
+
* );
|
|
2769
|
+
* // 'batch-pkg-a@1.0.0_pkg-b@2.0.0-2-packages-1234567890'
|
|
2770
|
+
*
|
|
2771
|
+
* // With custom template
|
|
2772
|
+
* const branch = params.getBatchReleaseBranchName(
|
|
2773
|
+
* 'pkg-a@1.0.0_pkg-b@2.0.0',
|
|
2774
|
+
* 'v1.0.0',
|
|
2775
|
+
* {},
|
|
2776
|
+
* 2,
|
|
2777
|
+
* );
|
|
2778
|
+
* // Custom formatted branch name
|
|
2779
|
+
* ```
|
|
2780
|
+
*/
|
|
2508
2781
|
getBatchReleaseBranchName(releaseName, tagName, shared, length) {
|
|
2509
2782
|
const branchNameTpl = this.config.batchBranchName;
|
|
2510
2783
|
if (typeof branchNameTpl !== "string") {
|
|
@@ -2521,6 +2794,45 @@ var ReleaseParams = class {
|
|
|
2521
2794
|
timestamp: Date.now()
|
|
2522
2795
|
});
|
|
2523
2796
|
}
|
|
2797
|
+
/**
|
|
2798
|
+
* Generates a release name from workspace configurations
|
|
2799
|
+
*
|
|
2800
|
+
* For single packages, returns the package name.
|
|
2801
|
+
* For multiple packages, combines names and versions up to
|
|
2802
|
+
* the configured maximum number of workspaces.
|
|
2803
|
+
*
|
|
2804
|
+
* Format:
|
|
2805
|
+
* - Single: packageName
|
|
2806
|
+
* - Multiple: pkg1@1.0.0_pkg2@2.0.0_pkg3@3.0.0
|
|
2807
|
+
*
|
|
2808
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
2809
|
+
* @returns Formatted release name
|
|
2810
|
+
*
|
|
2811
|
+
* @example
|
|
2812
|
+
* ```typescript
|
|
2813
|
+
* // Single package
|
|
2814
|
+
* const name = params.getReleaseName([
|
|
2815
|
+
* { name: 'pkg-a', version: '1.0.0' }
|
|
2816
|
+
* ]);
|
|
2817
|
+
* // 'pkg-a'
|
|
2818
|
+
*
|
|
2819
|
+
* // Multiple packages
|
|
2820
|
+
* const name = params.getReleaseName([
|
|
2821
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2822
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
2823
|
+
* ]);
|
|
2824
|
+
* // 'pkg-a@1.0.0_pkg-b@2.0.0'
|
|
2825
|
+
*
|
|
2826
|
+
* // With max limit
|
|
2827
|
+
* const name = params.getReleaseName([
|
|
2828
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2829
|
+
* { name: 'pkg-b', version: '2.0.0' },
|
|
2830
|
+
* { name: 'pkg-c', version: '3.0.0' },
|
|
2831
|
+
* { name: 'pkg-d', version: '4.0.0' }
|
|
2832
|
+
* ]);
|
|
2833
|
+
* // Only first 3: 'pkg-a@1.0.0_pkg-b@2.0.0_pkg-c@3.0.0'
|
|
2834
|
+
* ```
|
|
2835
|
+
*/
|
|
2524
2836
|
getReleaseName(composeWorkspaces) {
|
|
2525
2837
|
if (composeWorkspaces.length === 1) {
|
|
2526
2838
|
return composeWorkspaces[0].name;
|
|
@@ -2530,6 +2842,36 @@ var ReleaseParams = class {
|
|
|
2530
2842
|
({ name, version }) => `${name}${workspaceVersionSeparator}${version}`
|
|
2531
2843
|
).join(multiWorkspaceSeparator);
|
|
2532
2844
|
}
|
|
2845
|
+
/**
|
|
2846
|
+
* Generates a tag name for the release
|
|
2847
|
+
*
|
|
2848
|
+
* For single packages, uses the package version.
|
|
2849
|
+
* For multiple packages, generates a batch tag name using
|
|
2850
|
+
* the configured template.
|
|
2851
|
+
*
|
|
2852
|
+
* Format:
|
|
2853
|
+
* - Single: version
|
|
2854
|
+
* - Multiple: batch-${length}-packages-${timestamp}
|
|
2855
|
+
*
|
|
2856
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
2857
|
+
* @returns Formatted tag name
|
|
2858
|
+
*
|
|
2859
|
+
* @example
|
|
2860
|
+
* ```typescript
|
|
2861
|
+
* // Single package
|
|
2862
|
+
* const tag = params.getReleaseTagName([
|
|
2863
|
+
* { name: 'pkg-a', version: '1.0.0' }
|
|
2864
|
+
* ]);
|
|
2865
|
+
* // '1.0.0'
|
|
2866
|
+
*
|
|
2867
|
+
* // Multiple packages
|
|
2868
|
+
* const tag = params.getReleaseTagName([
|
|
2869
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2870
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
2871
|
+
* ]);
|
|
2872
|
+
* // 'batch-2-packages-1234567890'
|
|
2873
|
+
* ```
|
|
2874
|
+
*/
|
|
2533
2875
|
getReleaseTagName(composeWorkspaces) {
|
|
2534
2876
|
if (composeWorkspaces.length === 1) {
|
|
2535
2877
|
return composeWorkspaces[0].version;
|
|
@@ -2540,6 +2882,44 @@ var ReleaseParams = class {
|
|
|
2540
2882
|
timestamp: Date.now()
|
|
2541
2883
|
});
|
|
2542
2884
|
}
|
|
2885
|
+
/**
|
|
2886
|
+
* Generates branch and tag parameters for the release
|
|
2887
|
+
*
|
|
2888
|
+
* Combines the generation of branch name and tag name into
|
|
2889
|
+
* a single operation. Handles both single and multi-package
|
|
2890
|
+
* releases appropriately.
|
|
2891
|
+
*
|
|
2892
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
2893
|
+
* @param shared - Shared configuration
|
|
2894
|
+
* @returns Object containing tag name and branch name
|
|
2895
|
+
*
|
|
2896
|
+
* @example Single package
|
|
2897
|
+
* ```typescript
|
|
2898
|
+
* const params = releaseParams.getReleaseBranchParams(
|
|
2899
|
+
* [{ name: 'pkg-a', version: '1.0.0' }],
|
|
2900
|
+
* { branchName: 'release-${tagName}' }
|
|
2901
|
+
* );
|
|
2902
|
+
* // {
|
|
2903
|
+
* // tagName: '1.0.0',
|
|
2904
|
+
* // releaseBranch: 'release-1.0.0'
|
|
2905
|
+
* // }
|
|
2906
|
+
* ```
|
|
2907
|
+
*
|
|
2908
|
+
* @example Multiple packages
|
|
2909
|
+
* ```typescript
|
|
2910
|
+
* const params = releaseParams.getReleaseBranchParams(
|
|
2911
|
+
* [
|
|
2912
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2913
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
2914
|
+
* ],
|
|
2915
|
+
* {}
|
|
2916
|
+
* );
|
|
2917
|
+
* // {
|
|
2918
|
+
* // tagName: 'batch-2-packages-1234567890',
|
|
2919
|
+
* // releaseBranch: 'batch-pkg-a@1.0.0_pkg-b@2.0.0-2-packages-1234567890'
|
|
2920
|
+
* // }
|
|
2921
|
+
* ```
|
|
2922
|
+
*/
|
|
2543
2923
|
getReleaseBranchParams(composeWorkspaces, shared) {
|
|
2544
2924
|
const releaseTagName = this.getReleaseTagName(composeWorkspaces);
|
|
2545
2925
|
const releaseName = this.getReleaseName(composeWorkspaces);
|
|
@@ -2554,6 +2934,50 @@ var ReleaseParams = class {
|
|
|
2554
2934
|
releaseBranch: releaseBranchName
|
|
2555
2935
|
};
|
|
2556
2936
|
}
|
|
2937
|
+
/**
|
|
2938
|
+
* Generates a title for the release pull request
|
|
2939
|
+
*
|
|
2940
|
+
* Uses the configured PR title template or falls back to the default.
|
|
2941
|
+
* Supports variable interpolation with release parameters and context.
|
|
2942
|
+
*
|
|
2943
|
+
* Template Variables:
|
|
2944
|
+
* - ${tagName}: Release tag name
|
|
2945
|
+
* - ${pkgName}: Package/branch name
|
|
2946
|
+
* - All template context properties
|
|
2947
|
+
*
|
|
2948
|
+
* @param releaseBranchParams - Release branch parameters
|
|
2949
|
+
* @param context - Template context for variable interpolation
|
|
2950
|
+
* @returns Formatted PR title
|
|
2951
|
+
*
|
|
2952
|
+
* @example
|
|
2953
|
+
* ```typescript
|
|
2954
|
+
* // With default template
|
|
2955
|
+
* const title = params.getPRTitle(
|
|
2956
|
+
* {
|
|
2957
|
+
* tagName: '1.0.0',
|
|
2958
|
+
* releaseBranch: 'release-1.0.0'
|
|
2959
|
+
* },
|
|
2960
|
+
* {
|
|
2961
|
+
* env: 'production',
|
|
2962
|
+
* pkgName: 'my-package'
|
|
2963
|
+
* }
|
|
2964
|
+
* );
|
|
2965
|
+
* // 'Release production my-package 1.0.0'
|
|
2966
|
+
*
|
|
2967
|
+
* // With custom template
|
|
2968
|
+
* const title = params.getPRTitle(
|
|
2969
|
+
* {
|
|
2970
|
+
* tagName: '1.0.0',
|
|
2971
|
+
* releaseBranch: 'release-1.0.0'
|
|
2972
|
+
* },
|
|
2973
|
+
* {
|
|
2974
|
+
* env: 'staging',
|
|
2975
|
+
* pkgName: 'my-package'
|
|
2976
|
+
* }
|
|
2977
|
+
* );
|
|
2978
|
+
* // Custom formatted title
|
|
2979
|
+
* ```
|
|
2980
|
+
*/
|
|
2557
2981
|
getPRTitle(releaseBranchParams, context) {
|
|
2558
2982
|
const prTitleTpl = this.config.PRTitle || DEFAULT_PR_TITLE;
|
|
2559
2983
|
return Shell.format(prTitleTpl, {
|
|
@@ -2563,10 +2987,67 @@ var ReleaseParams = class {
|
|
|
2563
2987
|
});
|
|
2564
2988
|
}
|
|
2565
2989
|
/**
|
|
2566
|
-
*
|
|
2990
|
+
* Generates the body content for the release pull request
|
|
2991
|
+
*
|
|
2992
|
+
* Handles both single and multi-package releases, combining
|
|
2993
|
+
* changelogs appropriately. For batch releases, formats each
|
|
2994
|
+
* package's changelog according to the batch template.
|
|
2995
|
+
*
|
|
2996
|
+
* Template Variables:
|
|
2997
|
+
* - ${tagName}: Release tag or combined workspace versions
|
|
2998
|
+
* - ${changelog}: Single changelog or combined batch changelogs
|
|
2999
|
+
* - All template context properties
|
|
3000
|
+
*
|
|
3001
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
3002
|
+
* @param releaseBranchParams - Release branch parameters
|
|
3003
|
+
* @param context - Template context for variable interpolation
|
|
3004
|
+
* @returns Formatted PR body content
|
|
2567
3005
|
*
|
|
2568
|
-
* @
|
|
2569
|
-
*
|
|
3006
|
+
* @example Single package
|
|
3007
|
+
* ```typescript
|
|
3008
|
+
* const body = params.getPRBody(
|
|
3009
|
+
* [{
|
|
3010
|
+
* name: 'pkg-a',
|
|
3011
|
+
* version: '1.0.0',
|
|
3012
|
+
* changelog: '- Feature: New functionality\n- Fix: Bug fix'
|
|
3013
|
+
* }],
|
|
3014
|
+
* {
|
|
3015
|
+
* tagName: '1.0.0',
|
|
3016
|
+
* releaseBranch: 'release-1.0.0'
|
|
3017
|
+
* },
|
|
3018
|
+
* context
|
|
3019
|
+
* );
|
|
3020
|
+
* // Custom formatted body with single changelog
|
|
3021
|
+
* ```
|
|
3022
|
+
*
|
|
3023
|
+
* @example Multiple packages
|
|
3024
|
+
* ```typescript
|
|
3025
|
+
* const body = params.getPRBody(
|
|
3026
|
+
* [
|
|
3027
|
+
* {
|
|
3028
|
+
* name: 'pkg-a',
|
|
3029
|
+
* version: '1.0.0',
|
|
3030
|
+
* changelog: '- Feature: Package A changes'
|
|
3031
|
+
* },
|
|
3032
|
+
* {
|
|
3033
|
+
* name: 'pkg-b',
|
|
3034
|
+
* version: '2.0.0',
|
|
3035
|
+
* changelog: '- Feature: Package B changes'
|
|
3036
|
+
* }
|
|
3037
|
+
* ],
|
|
3038
|
+
* {
|
|
3039
|
+
* tagName: 'batch-2-packages-1234567890',
|
|
3040
|
+
* releaseBranch: 'batch-release'
|
|
3041
|
+
* },
|
|
3042
|
+
* context
|
|
3043
|
+
* );
|
|
3044
|
+
* // Formatted body with combined changelogs:
|
|
3045
|
+
* // ## pkg-a 1.0.0
|
|
3046
|
+
* // - Feature: Package A changes
|
|
3047
|
+
* //
|
|
3048
|
+
* // ## pkg-b 2.0.0
|
|
3049
|
+
* // - Feature: Package B changes
|
|
3050
|
+
* ```
|
|
2570
3051
|
*/
|
|
2571
3052
|
getPRBody(composeWorkspaces, releaseBranchParams, context) {
|
|
2572
3053
|
const PRBodyTpl = this.config.PRBody;
|
|
@@ -2592,10 +3073,36 @@ var ReleaseParams = class {
|
|
|
2592
3073
|
import { Shell as Shell2 } from "@qlover/scripts-context";
|
|
2593
3074
|
import { Octokit } from "@octokit/rest";
|
|
2594
3075
|
var GithubManager = class {
|
|
3076
|
+
/**
|
|
3077
|
+
* Creates a new GithubManager instance
|
|
3078
|
+
*
|
|
3079
|
+
* @param context - Release context containing configuration
|
|
3080
|
+
*
|
|
3081
|
+
* @example
|
|
3082
|
+
* ```typescript
|
|
3083
|
+
* const manager = new GithubManager(context);
|
|
3084
|
+
* ```
|
|
3085
|
+
*/
|
|
2595
3086
|
constructor(context) {
|
|
2596
3087
|
this.context = context;
|
|
2597
3088
|
}
|
|
3089
|
+
/** Lazy-loaded Octokit instance */
|
|
2598
3090
|
_octokit = null;
|
|
3091
|
+
/**
|
|
3092
|
+
* Gets GitHub repository information
|
|
3093
|
+
*
|
|
3094
|
+
* Retrieves the owner and repository name from the context.
|
|
3095
|
+
* This information is required for most GitHub API operations.
|
|
3096
|
+
*
|
|
3097
|
+
* @returns Repository owner and name
|
|
3098
|
+
* @throws Error if owner or repo name is not set
|
|
3099
|
+
*
|
|
3100
|
+
* @example
|
|
3101
|
+
* ```typescript
|
|
3102
|
+
* const info = manager.getGitHubUserInfo();
|
|
3103
|
+
* // { owner: 'org-name', repo: 'repo-name' }
|
|
3104
|
+
* ```
|
|
3105
|
+
*/
|
|
2599
3106
|
getGitHubUserInfo() {
|
|
2600
3107
|
const { authorName, repoName } = this.context.getOptions();
|
|
2601
3108
|
if (!authorName || !repoName) {
|
|
@@ -2606,6 +3113,28 @@ var GithubManager = class {
|
|
|
2606
3113
|
repo: repoName
|
|
2607
3114
|
};
|
|
2608
3115
|
}
|
|
3116
|
+
/**
|
|
3117
|
+
* Gets GitHub API token
|
|
3118
|
+
*
|
|
3119
|
+
* Retrieves the GitHub API token from environment variables.
|
|
3120
|
+
* The token name can be configured via the tokenRef option.
|
|
3121
|
+
*
|
|
3122
|
+
* @returns GitHub API token
|
|
3123
|
+
* @throws Error if token is not set
|
|
3124
|
+
*
|
|
3125
|
+
* @example Default token
|
|
3126
|
+
* ```typescript
|
|
3127
|
+
* const token = manager.getToken();
|
|
3128
|
+
* // Uses GITHUB_TOKEN env var
|
|
3129
|
+
* ```
|
|
3130
|
+
*
|
|
3131
|
+
* @example Custom token
|
|
3132
|
+
* ```typescript
|
|
3133
|
+
* context.options.githubPR.tokenRef = 'CUSTOM_TOKEN';
|
|
3134
|
+
* const token = manager.getToken();
|
|
3135
|
+
* // Uses CUSTOM_TOKEN env var
|
|
3136
|
+
* ```
|
|
3137
|
+
*/
|
|
2609
3138
|
getToken() {
|
|
2610
3139
|
const { tokenRef = "GITHUB_TOKEN" } = this.context.getOptions("githubPR");
|
|
2611
3140
|
const token = this.context.env.get(tokenRef);
|
|
@@ -2616,6 +3145,24 @@ var GithubManager = class {
|
|
|
2616
3145
|
}
|
|
2617
3146
|
return token;
|
|
2618
3147
|
}
|
|
3148
|
+
/**
|
|
3149
|
+
* Gets Octokit instance
|
|
3150
|
+
*
|
|
3151
|
+
* Lazily initializes and returns an Octokit instance configured
|
|
3152
|
+
* with the GitHub token and timeout settings.
|
|
3153
|
+
*
|
|
3154
|
+
* @returns Configured Octokit instance
|
|
3155
|
+
* @throws Error if token retrieval fails
|
|
3156
|
+
*
|
|
3157
|
+
* @example
|
|
3158
|
+
* ```typescript
|
|
3159
|
+
* const octokit = manager.octokit;
|
|
3160
|
+
* await octokit.rest.issues.create({
|
|
3161
|
+
* ...manager.getGitHubUserInfo(),
|
|
3162
|
+
* title: 'Issue title'
|
|
3163
|
+
* });
|
|
3164
|
+
* ```
|
|
3165
|
+
*/
|
|
2619
3166
|
get octokit() {
|
|
2620
3167
|
if (this._octokit) {
|
|
2621
3168
|
return this._octokit;
|
|
@@ -2630,9 +3177,37 @@ var GithubManager = class {
|
|
|
2630
3177
|
this._octokit = new Octokit(options);
|
|
2631
3178
|
return this._octokit;
|
|
2632
3179
|
}
|
|
3180
|
+
/**
|
|
3181
|
+
* Gets logger instance
|
|
3182
|
+
*
|
|
3183
|
+
* Provides access to the context's logger for consistent
|
|
3184
|
+
* logging across the manager.
|
|
3185
|
+
*
|
|
3186
|
+
* @returns Logger instance
|
|
3187
|
+
*
|
|
3188
|
+
* @example
|
|
3189
|
+
* ```typescript
|
|
3190
|
+
* manager.logger.info('Creating release...');
|
|
3191
|
+
* manager.logger.debug('API response:', response);
|
|
3192
|
+
* ```
|
|
3193
|
+
*/
|
|
2633
3194
|
get logger() {
|
|
2634
3195
|
return this.context.logger;
|
|
2635
3196
|
}
|
|
3197
|
+
/**
|
|
3198
|
+
* Gets shell interface
|
|
3199
|
+
*
|
|
3200
|
+
* Provides access to the context's shell interface for
|
|
3201
|
+
* executing Git commands and other shell operations.
|
|
3202
|
+
*
|
|
3203
|
+
* @returns Shell interface
|
|
3204
|
+
*
|
|
3205
|
+
* @example
|
|
3206
|
+
* ```typescript
|
|
3207
|
+
* await manager.shell.exec('git fetch origin');
|
|
3208
|
+
* await manager.shell.exec(['git', 'push', 'origin', 'main']);
|
|
3209
|
+
* ```
|
|
3210
|
+
*/
|
|
2636
3211
|
get shell() {
|
|
2637
3212
|
return this.context.shell;
|
|
2638
3213
|
}
|
|
@@ -2641,6 +3216,23 @@ var GithubManager = class {
|
|
|
2641
3216
|
*
|
|
2642
3217
|
* @default `squash`
|
|
2643
3218
|
*/
|
|
3219
|
+
/**
|
|
3220
|
+
* Gets auto-merge type for pull requests
|
|
3221
|
+
*
|
|
3222
|
+
* Determines how pull requests should be merged when
|
|
3223
|
+
* auto-merge is enabled. Defaults to 'squash'.
|
|
3224
|
+
*
|
|
3225
|
+
* @returns Auto-merge type ('merge', 'squash', or 'rebase')
|
|
3226
|
+
*
|
|
3227
|
+
* @example
|
|
3228
|
+
* ```typescript
|
|
3229
|
+
* const mergeType = manager.autoMergeType;
|
|
3230
|
+
* // 'squash' (default)
|
|
3231
|
+
*
|
|
3232
|
+
* context.options.autoMergeType = 'rebase';
|
|
3233
|
+
* manager.autoMergeType; // 'rebase'
|
|
3234
|
+
* ```
|
|
3235
|
+
*/
|
|
2644
3236
|
get autoMergeType() {
|
|
2645
3237
|
return this.context.getOptions().autoMergeType || DEFAULT_AUTO_MERGE_TYPE;
|
|
2646
3238
|
}
|
|
@@ -2649,6 +3241,25 @@ var GithubManager = class {
|
|
|
2649
3241
|
*
|
|
2650
3242
|
* @default `999999`
|
|
2651
3243
|
*/
|
|
3244
|
+
/**
|
|
3245
|
+
* Gets pull request number for dry runs
|
|
3246
|
+
*
|
|
3247
|
+
* Returns a placeholder PR number when running in dry-run mode.
|
|
3248
|
+
* This allows testing PR-related functionality without creating
|
|
3249
|
+
* actual pull requests.
|
|
3250
|
+
*
|
|
3251
|
+
* @returns Dry run PR number (default: '999999')
|
|
3252
|
+
*
|
|
3253
|
+
* @example
|
|
3254
|
+
* ```typescript
|
|
3255
|
+
* context.dryRun = true;
|
|
3256
|
+
* const prNumber = manager.dryRunPRNumber;
|
|
3257
|
+
* // '999999'
|
|
3258
|
+
*
|
|
3259
|
+
* context.options.githubPR.dryRunPRNumber = '123456';
|
|
3260
|
+
* manager.dryRunPRNumber; // '123456'
|
|
3261
|
+
* ```
|
|
3262
|
+
*/
|
|
2652
3263
|
get dryRunPRNumber() {
|
|
2653
3264
|
return this.context.getOptions("githubPR.dryRunPRNumber", "999999");
|
|
2654
3265
|
}
|
|
@@ -2657,6 +3268,23 @@ var GithubManager = class {
|
|
|
2657
3268
|
*
|
|
2658
3269
|
* @default `false`
|
|
2659
3270
|
*/
|
|
3271
|
+
/**
|
|
3272
|
+
* Gets auto-merge setting for release PRs
|
|
3273
|
+
*
|
|
3274
|
+
* Determines whether release pull requests should be
|
|
3275
|
+
* automatically merged after creation. Defaults to false.
|
|
3276
|
+
*
|
|
3277
|
+
* @returns True if auto-merge is enabled
|
|
3278
|
+
*
|
|
3279
|
+
* @example
|
|
3280
|
+
* ```typescript
|
|
3281
|
+
* const autoMerge = manager.autoMergeReleasePR;
|
|
3282
|
+
* // false (default)
|
|
3283
|
+
*
|
|
3284
|
+
* context.options.autoMergeReleasePR = true;
|
|
3285
|
+
* manager.autoMergeReleasePR; // true
|
|
3286
|
+
* ```
|
|
3287
|
+
*/
|
|
2660
3288
|
get autoMergeReleasePR() {
|
|
2661
3289
|
return this.context.getOptions("autoMergeReleasePR") || DEFAULT_AUTO_MERGE_RELEASE_PR;
|
|
2662
3290
|
}
|
|
@@ -2666,6 +3294,30 @@ var GithubManager = class {
|
|
|
2666
3294
|
* @param prNumber - The pull request number to merge.
|
|
2667
3295
|
* @param releaseBranch - The branch to merge into.
|
|
2668
3296
|
*/
|
|
3297
|
+
/**
|
|
3298
|
+
* Merges a pull request
|
|
3299
|
+
*
|
|
3300
|
+
* Merges the specified pull request using the configured
|
|
3301
|
+
* merge method. In dry-run mode, logs the merge action
|
|
3302
|
+
* without performing it.
|
|
3303
|
+
*
|
|
3304
|
+
* @param prNumber - Pull request number
|
|
3305
|
+
* @param releaseBranch - Branch to merge
|
|
3306
|
+
* @throws Error if merge fails
|
|
3307
|
+
*
|
|
3308
|
+
* @example Basic merge
|
|
3309
|
+
* ```typescript
|
|
3310
|
+
* await manager.mergePR('123', 'release-1.0.0');
|
|
3311
|
+
* // Merges PR #123 using configured merge method
|
|
3312
|
+
* ```
|
|
3313
|
+
*
|
|
3314
|
+
* @example Dry run
|
|
3315
|
+
* ```typescript
|
|
3316
|
+
* context.dryRun = true;
|
|
3317
|
+
* await manager.mergePR('123', 'release-1.0.0');
|
|
3318
|
+
* // Logs merge action without performing it
|
|
3319
|
+
* ```
|
|
3320
|
+
*/
|
|
2669
3321
|
async mergePR(prNumber, releaseBranch) {
|
|
2670
3322
|
if (!prNumber) {
|
|
2671
3323
|
this.logger.error("Failed to create Pull Request.", prNumber);
|
|
@@ -2685,6 +3337,24 @@ var GithubManager = class {
|
|
|
2685
3337
|
merge_method: mergeMethod
|
|
2686
3338
|
});
|
|
2687
3339
|
}
|
|
3340
|
+
/**
|
|
3341
|
+
* Gets commits from a pull request
|
|
3342
|
+
*
|
|
3343
|
+
* Retrieves all commits associated with the specified pull request.
|
|
3344
|
+
* Useful for generating changelogs or analyzing changes.
|
|
3345
|
+
*
|
|
3346
|
+
* @param prNumber - Pull request number
|
|
3347
|
+
* @returns Promise resolving to array of commit information
|
|
3348
|
+
* @throws Error if request fails
|
|
3349
|
+
*
|
|
3350
|
+
* @example
|
|
3351
|
+
* ```typescript
|
|
3352
|
+
* const commits = await manager.getPullRequestCommits(123);
|
|
3353
|
+
* commits.forEach(commit => {
|
|
3354
|
+
* console.log(commit.sha, commit.commit.message);
|
|
3355
|
+
* });
|
|
3356
|
+
* ```
|
|
3357
|
+
*/
|
|
2688
3358
|
async getPullRequestCommits(prNumber) {
|
|
2689
3359
|
const pr = await this.octokit.rest.pulls.listCommits({
|
|
2690
3360
|
...this.getGitHubUserInfo(),
|
|
@@ -2692,6 +3362,23 @@ var GithubManager = class {
|
|
|
2692
3362
|
});
|
|
2693
3363
|
return pr.data;
|
|
2694
3364
|
}
|
|
3365
|
+
/**
|
|
3366
|
+
* Gets detailed information about a commit
|
|
3367
|
+
*
|
|
3368
|
+
* Retrieves detailed information about a specific commit,
|
|
3369
|
+
* including files changed, author details, and commit message.
|
|
3370
|
+
*
|
|
3371
|
+
* @param commitSha - Commit SHA
|
|
3372
|
+
* @returns Promise resolving to commit information
|
|
3373
|
+
* @throws Error if request fails
|
|
3374
|
+
*
|
|
3375
|
+
* @example
|
|
3376
|
+
* ```typescript
|
|
3377
|
+
* const info = await manager.getCommitInfo('abc123');
|
|
3378
|
+
* console.log(info.commit.message);
|
|
3379
|
+
* console.log(info.files.map(f => f.filename));
|
|
3380
|
+
* ```
|
|
3381
|
+
*/
|
|
2695
3382
|
async getCommitInfo(commitSha) {
|
|
2696
3383
|
const pr = await this.octokit.rest.repos.getCommit({
|
|
2697
3384
|
...this.getGitHubUserInfo(),
|
|
@@ -2699,6 +3386,24 @@ var GithubManager = class {
|
|
|
2699
3386
|
});
|
|
2700
3387
|
return pr.data;
|
|
2701
3388
|
}
|
|
3389
|
+
/**
|
|
3390
|
+
* Gets pull request information
|
|
3391
|
+
*
|
|
3392
|
+
* Retrieves detailed information about a pull request,
|
|
3393
|
+
* including title, body, labels, and review status.
|
|
3394
|
+
*
|
|
3395
|
+
* @param prNumber - Pull request number
|
|
3396
|
+
* @returns Promise resolving to pull request information
|
|
3397
|
+
* @throws Error if request fails
|
|
3398
|
+
*
|
|
3399
|
+
* @example
|
|
3400
|
+
* ```typescript
|
|
3401
|
+
* const pr = await manager.getPullRequest(123);
|
|
3402
|
+
* console.log(pr.title);
|
|
3403
|
+
* console.log(pr.labels.map(l => l.name));
|
|
3404
|
+
* console.log(pr.mergeable_state);
|
|
3405
|
+
* ```
|
|
3406
|
+
*/
|
|
2702
3407
|
async getPullRequest(prNumber) {
|
|
2703
3408
|
const pr = await this.octokit.rest.pulls.get({
|
|
2704
3409
|
...this.getGitHubUserInfo(),
|
|
@@ -2712,6 +3417,27 @@ var GithubManager = class {
|
|
|
2712
3417
|
* @param prNumber - The pull request number to check.
|
|
2713
3418
|
* @param releaseBranch - The branch to check against.
|
|
2714
3419
|
*/
|
|
3420
|
+
/**
|
|
3421
|
+
* Checks pull request status and cleans up
|
|
3422
|
+
*
|
|
3423
|
+
* Verifies pull request status and deletes the release branch
|
|
3424
|
+
* if the PR has been merged. Used for post-merge cleanup.
|
|
3425
|
+
*
|
|
3426
|
+
* Process:
|
|
3427
|
+
* 1. Verify PR exists and status
|
|
3428
|
+
* 2. Delete release branch if PR merged
|
|
3429
|
+
* 3. Log cleanup results
|
|
3430
|
+
*
|
|
3431
|
+
* @param prNumber - Pull request number
|
|
3432
|
+
* @param releaseBranch - Branch to clean up
|
|
3433
|
+
* @throws Error if verification or cleanup fails
|
|
3434
|
+
*
|
|
3435
|
+
* @example
|
|
3436
|
+
* ```typescript
|
|
3437
|
+
* await manager.checkedPR('123', 'release-1.0.0');
|
|
3438
|
+
* // Verifies PR #123 and deletes release-1.0.0 if merged
|
|
3439
|
+
* ```
|
|
3440
|
+
*/
|
|
2715
3441
|
async checkedPR(prNumber, releaseBranch) {
|
|
2716
3442
|
try {
|
|
2717
3443
|
await this.getPullRequest(Number(prNumber));
|
|
@@ -2812,10 +3538,55 @@ var GithubManager = class {
|
|
|
2812
3538
|
throw error;
|
|
2813
3539
|
}
|
|
2814
3540
|
}
|
|
3541
|
+
/**
|
|
3542
|
+
* Truncates long PR/release body text
|
|
3543
|
+
*
|
|
3544
|
+
* GitHub has a limit on PR and release body length.
|
|
3545
|
+
* This method ensures the text stays within limits by
|
|
3546
|
+
* truncating if necessary.
|
|
3547
|
+
*
|
|
3548
|
+
* @param body - Body text to truncate
|
|
3549
|
+
* @returns Truncated text (if > 124000 chars)
|
|
3550
|
+
*
|
|
3551
|
+
* @example
|
|
3552
|
+
* ```typescript
|
|
3553
|
+
* const body = manager.truncateBody(veryLongText);
|
|
3554
|
+
* // Returns truncated text if > 124000 chars
|
|
3555
|
+
* // Adds '...' to indicate truncation
|
|
3556
|
+
* ```
|
|
3557
|
+
* @private
|
|
3558
|
+
*/
|
|
2815
3559
|
truncateBody(body) {
|
|
2816
3560
|
if (body && body.length >= 124e3) return body.substring(0, 124e3) + "...";
|
|
2817
3561
|
return body;
|
|
2818
3562
|
}
|
|
3563
|
+
/**
|
|
3564
|
+
* Builds GitHub release options
|
|
3565
|
+
*
|
|
3566
|
+
* Combines default release options with provided overrides
|
|
3567
|
+
* and context configuration. Handles formatting of release
|
|
3568
|
+
* name, body, and other settings.
|
|
3569
|
+
*
|
|
3570
|
+
* @param options - Override options for release
|
|
3571
|
+
* @returns Complete release options
|
|
3572
|
+
*
|
|
3573
|
+
* @example
|
|
3574
|
+
* ```typescript
|
|
3575
|
+
* const opts = manager.getOctokitReleaseOptions({
|
|
3576
|
+
* tag_name: 'v1.0.0',
|
|
3577
|
+
* body: 'Release notes...'
|
|
3578
|
+
* });
|
|
3579
|
+
* // Returns merged options with defaults:
|
|
3580
|
+
* // {
|
|
3581
|
+
* // name: 'Release v1.0.0',
|
|
3582
|
+
* // body: 'Release notes...',
|
|
3583
|
+
* // draft: false,
|
|
3584
|
+
* // prerelease: false,
|
|
3585
|
+
* // ...
|
|
3586
|
+
* // }
|
|
3587
|
+
* ```
|
|
3588
|
+
* @private
|
|
3589
|
+
*/
|
|
2819
3590
|
getOctokitReleaseOptions(options) {
|
|
2820
3591
|
const {
|
|
2821
3592
|
releaseName,
|
|
@@ -2841,6 +3612,37 @@ var GithubManager = class {
|
|
|
2841
3612
|
...this.getGitHubUserInfo()
|
|
2842
3613
|
};
|
|
2843
3614
|
}
|
|
3615
|
+
/**
|
|
3616
|
+
* Creates a GitHub release
|
|
3617
|
+
*
|
|
3618
|
+
* Creates a new GitHub release for a workspace with:
|
|
3619
|
+
* - Formatted release name
|
|
3620
|
+
* - Changelog as release notes
|
|
3621
|
+
* - Proper tag
|
|
3622
|
+
* - Configurable settings (draft, prerelease, etc.)
|
|
3623
|
+
*
|
|
3624
|
+
* Handles dry run mode and error cases gracefully.
|
|
3625
|
+
*
|
|
3626
|
+
* @param workspace - Workspace to create release for
|
|
3627
|
+
* @throws Error if tag name is missing or creation fails
|
|
3628
|
+
*
|
|
3629
|
+
* @example Basic release
|
|
3630
|
+
* ```typescript
|
|
3631
|
+
* await manager.createRelease({
|
|
3632
|
+
* name: 'pkg-a',
|
|
3633
|
+
* version: '1.0.0',
|
|
3634
|
+
* tagName: 'v1.0.0',
|
|
3635
|
+
* changelog: '...'
|
|
3636
|
+
* });
|
|
3637
|
+
* ```
|
|
3638
|
+
*
|
|
3639
|
+
* @example Dry run
|
|
3640
|
+
* ```typescript
|
|
3641
|
+
* context.dryRun = true;
|
|
3642
|
+
* await manager.createRelease(workspace);
|
|
3643
|
+
* // Logs release info without creating
|
|
3644
|
+
* ```
|
|
3645
|
+
*/
|
|
2844
3646
|
async createRelease(workspace) {
|
|
2845
3647
|
const meragedOptions = this.getOctokitReleaseOptions({
|
|
2846
3648
|
tag_name: workspace.tagName,
|
|
@@ -2880,6 +3682,30 @@ var GithubManager = class {
|
|
|
2880
3682
|
var import_isString = __toESM(require_isString(), 1);
|
|
2881
3683
|
import { ScriptPlugin } from "@qlover/scripts-context";
|
|
2882
3684
|
var GitBase = class extends ScriptPlugin {
|
|
3685
|
+
/**
|
|
3686
|
+
* Plugin initialization hook
|
|
3687
|
+
*
|
|
3688
|
+
* Runs before plugin execution to set up repository context:
|
|
3689
|
+
* 1. Retrieves repository information
|
|
3690
|
+
* 2. Gets current branch
|
|
3691
|
+
* 3. Switches to current branch if needed
|
|
3692
|
+
* 4. Updates context with repository info
|
|
3693
|
+
*
|
|
3694
|
+
* @throws Error if repository information cannot be retrieved
|
|
3695
|
+
*
|
|
3696
|
+
* @example
|
|
3697
|
+
* ```typescript
|
|
3698
|
+
* class MyPlugin extends GitBase<GitBaseProps> {
|
|
3699
|
+
* async onExec() {
|
|
3700
|
+
* // onBefore has already:
|
|
3701
|
+
* // - Set up repository info
|
|
3702
|
+
* // - Switched to correct branch
|
|
3703
|
+
* // - Updated context
|
|
3704
|
+
* await this.doSomething();
|
|
3705
|
+
* }
|
|
3706
|
+
* }
|
|
3707
|
+
* ```
|
|
3708
|
+
*/
|
|
2883
3709
|
async onBefore() {
|
|
2884
3710
|
const repoInfo = await this.getUserInfo();
|
|
2885
3711
|
if (!repoInfo) {
|
|
@@ -2900,12 +3726,44 @@ var GitBase = class extends ScriptPlugin {
|
|
|
2900
3726
|
currentBranch
|
|
2901
3727
|
});
|
|
2902
3728
|
}
|
|
3729
|
+
/**
|
|
3730
|
+
* Gets the current Git branch name
|
|
3731
|
+
*
|
|
3732
|
+
* Retrieves the name of the currently checked out Git branch.
|
|
3733
|
+
* Includes a small delay to ensure Git's internal state is updated.
|
|
3734
|
+
*
|
|
3735
|
+
* @returns Promise resolving to branch name
|
|
3736
|
+
* @throws Error if branch name cannot be retrieved
|
|
3737
|
+
*
|
|
3738
|
+
* @example
|
|
3739
|
+
* ```typescript
|
|
3740
|
+
* const branch = await plugin.getCurrentBranch();
|
|
3741
|
+
* // 'main' or 'feature/new-feature'
|
|
3742
|
+
* ```
|
|
3743
|
+
*/
|
|
2903
3744
|
async getCurrentBranch() {
|
|
2904
3745
|
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
2905
3746
|
return this.context.shell.exec("git rev-parse --abbrev-ref HEAD", {
|
|
2906
3747
|
dryRun: false
|
|
2907
3748
|
});
|
|
2908
3749
|
}
|
|
3750
|
+
/**
|
|
3751
|
+
* Gets the Git remote URL
|
|
3752
|
+
*
|
|
3753
|
+
* Retrieves the URL of the 'origin' remote from Git configuration.
|
|
3754
|
+
* This URL is used to identify the GitHub repository.
|
|
3755
|
+
*
|
|
3756
|
+
* @returns Promise resolving to remote URL
|
|
3757
|
+
* @throws Error if remote URL cannot be retrieved
|
|
3758
|
+
*
|
|
3759
|
+
* @example
|
|
3760
|
+
* ```typescript
|
|
3761
|
+
* const url = await plugin.getRemoteUrl();
|
|
3762
|
+
* // 'https://github.com/org/repo.git'
|
|
3763
|
+
* // or
|
|
3764
|
+
* // 'git@github.com:org/repo.git'
|
|
3765
|
+
* ```
|
|
3766
|
+
*/
|
|
2909
3767
|
async getRemoteUrl() {
|
|
2910
3768
|
return (await this.context.shell.exec("git config --get remote.origin.url", {
|
|
2911
3769
|
dryRun: false
|
|
@@ -2959,9 +3817,53 @@ var GitBase = class extends ScriptPlugin {
|
|
|
2959
3817
|
* @param value - The value to check.
|
|
2960
3818
|
* @returns True if the value is a valid string, otherwise false.
|
|
2961
3819
|
*/
|
|
3820
|
+
/**
|
|
3821
|
+
* Type guard for valid string values
|
|
3822
|
+
*
|
|
3823
|
+
* Checks if a value is a non-empty string. Used for validating
|
|
3824
|
+
* repository information and other string inputs.
|
|
3825
|
+
*
|
|
3826
|
+
* @param value - Value to check
|
|
3827
|
+
* @returns True if value is a non-empty string
|
|
3828
|
+
*
|
|
3829
|
+
* @example
|
|
3830
|
+
* ```typescript
|
|
3831
|
+
* if (plugin.isValidString(value)) {
|
|
3832
|
+
* // value is definitely a non-empty string
|
|
3833
|
+
* console.log(value.toUpperCase());
|
|
3834
|
+
* }
|
|
3835
|
+
* ```
|
|
3836
|
+
*/
|
|
2962
3837
|
isValidString(value) {
|
|
2963
3838
|
return !!value && (0, import_isString.default)(value);
|
|
2964
3839
|
}
|
|
3840
|
+
/**
|
|
3841
|
+
* Creates a Git commit
|
|
3842
|
+
*
|
|
3843
|
+
* Creates a new Git commit with the specified message and optional
|
|
3844
|
+
* additional arguments. The message is automatically JSON-stringified
|
|
3845
|
+
* to handle special characters properly.
|
|
3846
|
+
*
|
|
3847
|
+
* @param message - Commit message
|
|
3848
|
+
* @param args - Additional Git commit arguments
|
|
3849
|
+
* @returns Promise resolving to command output
|
|
3850
|
+
*
|
|
3851
|
+
* @example Basic commit
|
|
3852
|
+
* ```typescript
|
|
3853
|
+
* await plugin.commit('feat: add new feature');
|
|
3854
|
+
* ```
|
|
3855
|
+
*
|
|
3856
|
+
* @example Commit with arguments
|
|
3857
|
+
* ```typescript
|
|
3858
|
+
* await plugin.commit('fix: update deps', ['--no-verify']);
|
|
3859
|
+
* ```
|
|
3860
|
+
*
|
|
3861
|
+
* @example Commit with special characters
|
|
3862
|
+
* ```typescript
|
|
3863
|
+
* await plugin.commit('fix: handle "quotes" & symbols');
|
|
3864
|
+
* // Message is automatically escaped
|
|
3865
|
+
* ```
|
|
3866
|
+
*/
|
|
2965
3867
|
commit(message, args = []) {
|
|
2966
3868
|
return this.context.shell.exec([
|
|
2967
3869
|
"git",
|
|
@@ -2996,14 +3898,50 @@ var CHANGELOG_ALL_FIELDS = [
|
|
|
2996
3898
|
"tag"
|
|
2997
3899
|
];
|
|
2998
3900
|
var GitChangelog = class {
|
|
3901
|
+
/**
|
|
3902
|
+
* Creates a new GitChangelog instance
|
|
3903
|
+
*
|
|
3904
|
+
* @param options - Configuration options including shell and logger
|
|
3905
|
+
*
|
|
3906
|
+
* @example
|
|
3907
|
+
* ```typescript
|
|
3908
|
+
* const changelog = new GitChangelog({
|
|
3909
|
+
* shell: new Shell(),
|
|
3910
|
+
* logger: new Logger(),
|
|
3911
|
+
* directory: 'packages/my-pkg',
|
|
3912
|
+
* noMerges: true
|
|
3913
|
+
* });
|
|
3914
|
+
* ```
|
|
3915
|
+
*/
|
|
2999
3916
|
constructor(options) {
|
|
3000
3917
|
this.options = options;
|
|
3001
3918
|
}
|
|
3002
3919
|
/**
|
|
3003
|
-
*
|
|
3920
|
+
* Retrieves Git commit history with specified options
|
|
3921
|
+
*
|
|
3922
|
+
* Fetches commit information between specified tags or commits,
|
|
3923
|
+
* with support for filtering and field selection.
|
|
3924
|
+
*
|
|
3925
|
+
* @param options - Configuration options for Git log retrieval
|
|
3926
|
+
* @returns Array of commit objects with requested fields
|
|
3004
3927
|
*
|
|
3005
|
-
* @
|
|
3006
|
-
*
|
|
3928
|
+
* @example Basic usage
|
|
3929
|
+
* ```typescript
|
|
3930
|
+
* const commits = await changelog.getGitLog({
|
|
3931
|
+
* from: 'v1.0.0',
|
|
3932
|
+
* to: 'v2.0.0',
|
|
3933
|
+
* directory: 'packages/my-pkg',
|
|
3934
|
+
* noMerges: true
|
|
3935
|
+
* });
|
|
3936
|
+
* ```
|
|
3937
|
+
*
|
|
3938
|
+
* @example Custom fields
|
|
3939
|
+
* ```typescript
|
|
3940
|
+
* const commits = await changelog.getGitLog({
|
|
3941
|
+
* fields: ['hash', 'subject', 'authorName'],
|
|
3942
|
+
* directory: 'src'
|
|
3943
|
+
* });
|
|
3944
|
+
* ```
|
|
3007
3945
|
*/
|
|
3008
3946
|
async getGitLog(options = {}) {
|
|
3009
3947
|
const { directory, noMerges = true, fields } = options;
|
|
@@ -3024,6 +3962,38 @@ var GitChangelog = class {
|
|
|
3024
3962
|
this.options.logger?.debug("GitChangelog commits", commits);
|
|
3025
3963
|
return commits;
|
|
3026
3964
|
}
|
|
3965
|
+
/**
|
|
3966
|
+
* Retrieves and parses Git commits with metadata
|
|
3967
|
+
*
|
|
3968
|
+
* Gets commit history and enhances it with parsed conventional
|
|
3969
|
+
* commit information and PR metadata.
|
|
3970
|
+
*
|
|
3971
|
+
* @param options - Configuration options for Git log retrieval
|
|
3972
|
+
* @returns Array of enhanced commit objects with parsed metadata
|
|
3973
|
+
*
|
|
3974
|
+
* @example Basic usage
|
|
3975
|
+
* ```typescript
|
|
3976
|
+
* const commits = await changelog.getCommits({
|
|
3977
|
+
* from: 'v1.0.0',
|
|
3978
|
+
* to: 'v2.0.0'
|
|
3979
|
+
* });
|
|
3980
|
+
* // [
|
|
3981
|
+
* // {
|
|
3982
|
+
* // base: { hash: '...', subject: '...' },
|
|
3983
|
+
* // commitlint: { type: 'feat', scope: 'api', ... },
|
|
3984
|
+
* // commits: []
|
|
3985
|
+
* // }
|
|
3986
|
+
* // ]
|
|
3987
|
+
* ```
|
|
3988
|
+
*
|
|
3989
|
+
* @example Filtered commits
|
|
3990
|
+
* ```typescript
|
|
3991
|
+
* const commits = await changelog.getCommits({
|
|
3992
|
+
* directory: 'packages/my-pkg',
|
|
3993
|
+
* noMerges: true
|
|
3994
|
+
* });
|
|
3995
|
+
* ```
|
|
3996
|
+
*/
|
|
3027
3997
|
async getCommits(options) {
|
|
3028
3998
|
const gitCommits = await this.getGitLog(options);
|
|
3029
3999
|
return gitCommits.map((commit) => {
|
|
@@ -3036,6 +4006,28 @@ var GitChangelog = class {
|
|
|
3036
4006
|
};
|
|
3037
4007
|
});
|
|
3038
4008
|
}
|
|
4009
|
+
/**
|
|
4010
|
+
* Creates a base commit object from message and optional data
|
|
4011
|
+
*
|
|
4012
|
+
* Utility method to create a standardized commit object with
|
|
4013
|
+
* basic metadata. Used internally for commit value creation.
|
|
4014
|
+
*
|
|
4015
|
+
* @param message - Commit message
|
|
4016
|
+
* @param target - Optional additional commit data
|
|
4017
|
+
* @returns Base commit object
|
|
4018
|
+
* @protected
|
|
4019
|
+
*
|
|
4020
|
+
* @example
|
|
4021
|
+
* ```typescript
|
|
4022
|
+
* const commit = changelog.createBaseCommit(
|
|
4023
|
+
* 'feat: new feature',
|
|
4024
|
+
* {
|
|
4025
|
+
* hash: 'abc123',
|
|
4026
|
+
* authorName: 'John Doe'
|
|
4027
|
+
* }
|
|
4028
|
+
* );
|
|
4029
|
+
* ```
|
|
4030
|
+
*/
|
|
3039
4031
|
createBaseCommit(message, target) {
|
|
3040
4032
|
return {
|
|
3041
4033
|
subject: message,
|
|
@@ -3045,16 +4037,66 @@ var GitChangelog = class {
|
|
|
3045
4037
|
};
|
|
3046
4038
|
}
|
|
3047
4039
|
/**
|
|
3048
|
-
*
|
|
4040
|
+
* Indents each line of a text block
|
|
4041
|
+
*
|
|
4042
|
+
* Adds specified number of spaces to the start of each line
|
|
4043
|
+
* in a multi-line string. Used for formatting commit body text.
|
|
3049
4044
|
*
|
|
3050
4045
|
* @since 2.3.2
|
|
3051
|
-
* @param body
|
|
3052
|
-
* @param size
|
|
3053
|
-
* @returns
|
|
4046
|
+
* @param body - Text to indent
|
|
4047
|
+
* @param size - Number of spaces to add (default: 2)
|
|
4048
|
+
* @returns Indented text
|
|
4049
|
+
*
|
|
4050
|
+
* @example
|
|
4051
|
+
* ```typescript
|
|
4052
|
+
* const text = changelog.tabify(
|
|
4053
|
+
* 'Line 1\nLine 2\nLine 3',
|
|
4054
|
+
* 4
|
|
4055
|
+
* );
|
|
4056
|
+
* // ' Line 1\n Line 2\n Line 3'
|
|
4057
|
+
* ```
|
|
3054
4058
|
*/
|
|
3055
4059
|
tabify(body, size = 2) {
|
|
3056
4060
|
return body.split("\n").map((line) => " ".repeat(size) + line.trim()).join("\n");
|
|
3057
4061
|
}
|
|
4062
|
+
/**
|
|
4063
|
+
* Parses a commit message into conventional commit format
|
|
4064
|
+
*
|
|
4065
|
+
* Extracts type, scope, message, and body from a commit message
|
|
4066
|
+
* following the conventional commit specification.
|
|
4067
|
+
*
|
|
4068
|
+
* Format: type(scope): message
|
|
4069
|
+
*
|
|
4070
|
+
* @param subject - Commit subject line
|
|
4071
|
+
* @param rawBody - Full commit message body
|
|
4072
|
+
* @returns Parsed conventional commit data
|
|
4073
|
+
*
|
|
4074
|
+
* @example Basic commit
|
|
4075
|
+
* ```typescript
|
|
4076
|
+
* const commit = changelog.parseCommitlint(
|
|
4077
|
+
* 'feat(api): add new endpoint'
|
|
4078
|
+
* );
|
|
4079
|
+
* // {
|
|
4080
|
+
* // type: 'feat',
|
|
4081
|
+
* // scope: 'api',
|
|
4082
|
+
* // message: 'add new endpoint'
|
|
4083
|
+
* // }
|
|
4084
|
+
* ```
|
|
4085
|
+
*
|
|
4086
|
+
* @example With body
|
|
4087
|
+
* ```typescript
|
|
4088
|
+
* const commit = changelog.parseCommitlint(
|
|
4089
|
+
* 'fix(core): memory leak',
|
|
4090
|
+
* 'Fixed memory leak in core module\n\nBREAKING CHANGE: API changed'
|
|
4091
|
+
* );
|
|
4092
|
+
* // {
|
|
4093
|
+
* // type: 'fix',
|
|
4094
|
+
* // scope: 'core',
|
|
4095
|
+
* // message: 'memory leak',
|
|
4096
|
+
* // body: ' Fixed memory leak in core module\n\n BREAKING CHANGE: API changed'
|
|
4097
|
+
* // }
|
|
4098
|
+
* ```
|
|
4099
|
+
*/
|
|
3058
4100
|
parseCommitlint(subject, rawBody = "") {
|
|
3059
4101
|
const [title] = subject.trim().split("\n");
|
|
3060
4102
|
const bodyLines = rawBody.startsWith(title) ? rawBody.replace(title, "") : rawBody;
|
|
@@ -3073,6 +4115,51 @@ var GitChangelog = class {
|
|
|
3073
4115
|
body: bodyLines ? this.tabify(bodyLines) : void 0
|
|
3074
4116
|
};
|
|
3075
4117
|
}
|
|
4118
|
+
/**
|
|
4119
|
+
* Creates a complete commit value object from hash and message
|
|
4120
|
+
*
|
|
4121
|
+
* Combines commit hash, parsed conventional commit data, and
|
|
4122
|
+
* PR information into a single commit value object.
|
|
4123
|
+
*
|
|
4124
|
+
* @param hash - Commit hash
|
|
4125
|
+
* @param message - Full commit message
|
|
4126
|
+
* @returns Complete commit value object
|
|
4127
|
+
*
|
|
4128
|
+
* @example Basic commit
|
|
4129
|
+
* ```typescript
|
|
4130
|
+
* const commit = changelog.toCommitValue(
|
|
4131
|
+
* 'abc123',
|
|
4132
|
+
* 'feat(api): new endpoint'
|
|
4133
|
+
* );
|
|
4134
|
+
* // {
|
|
4135
|
+
* // base: {
|
|
4136
|
+
* // hash: 'abc123',
|
|
4137
|
+
* // abbrevHash: 'abc123',
|
|
4138
|
+
* // subject: 'feat(api): new endpoint'
|
|
4139
|
+
* // },
|
|
4140
|
+
* // commitlint: {
|
|
4141
|
+
* // type: 'feat',
|
|
4142
|
+
* // scope: 'api',
|
|
4143
|
+
* // message: 'new endpoint'
|
|
4144
|
+
* // },
|
|
4145
|
+
* // commits: []
|
|
4146
|
+
* // }
|
|
4147
|
+
* ```
|
|
4148
|
+
*
|
|
4149
|
+
* @example PR commit
|
|
4150
|
+
* ```typescript
|
|
4151
|
+
* const commit = changelog.toCommitValue(
|
|
4152
|
+
* 'def456',
|
|
4153
|
+
* 'fix(core): memory leak (#123)'
|
|
4154
|
+
* );
|
|
4155
|
+
* // {
|
|
4156
|
+
* // base: { hash: 'def456', ... },
|
|
4157
|
+
* // commitlint: { type: 'fix', ... },
|
|
4158
|
+
* // commits: [],
|
|
4159
|
+
* // prNumber: '123'
|
|
4160
|
+
* // }
|
|
4161
|
+
* ```
|
|
4162
|
+
*/
|
|
3076
4163
|
toCommitValue(hash, message) {
|
|
3077
4164
|
const [title] = message.trim().split("\n");
|
|
3078
4165
|
const prMatch = title.match(/\(#(\d+)\)/);
|
|
@@ -3090,6 +4177,33 @@ var GitChangelog = class {
|
|
|
3090
4177
|
prNumber: prMatch?.[1]
|
|
3091
4178
|
};
|
|
3092
4179
|
}
|
|
4180
|
+
/**
|
|
4181
|
+
* Resolves a Git tag or reference to a valid commit reference
|
|
4182
|
+
*
|
|
4183
|
+
* Attempts to resolve a tag name to a valid Git reference.
|
|
4184
|
+
* Falls back to root commit or HEAD if tag doesn't exist.
|
|
4185
|
+
*
|
|
4186
|
+
* @param tag - Tag name to resolve
|
|
4187
|
+
* @param fallback - Fallback value ('root' or 'HEAD')
|
|
4188
|
+
* @returns Resolved Git reference
|
|
4189
|
+
* @protected
|
|
4190
|
+
*
|
|
4191
|
+
* @example Basic tag resolution
|
|
4192
|
+
* ```typescript
|
|
4193
|
+
* const ref = await changelog.resolveTag('v1.0.0');
|
|
4194
|
+
* // 'v1.0.0' if tag exists
|
|
4195
|
+
* // 'HEAD' if tag doesn't exist
|
|
4196
|
+
* ```
|
|
4197
|
+
*
|
|
4198
|
+
* @example Root commit fallback
|
|
4199
|
+
* ```typescript
|
|
4200
|
+
* const ref = await changelog.resolveTag(
|
|
4201
|
+
* 'non-existent-tag',
|
|
4202
|
+
* 'root'
|
|
4203
|
+
* );
|
|
4204
|
+
* // First commit hash if tag doesn't exist
|
|
4205
|
+
* ```
|
|
4206
|
+
*/
|
|
3093
4207
|
async resolveTag(tag, fallback) {
|
|
3094
4208
|
if (tag) {
|
|
3095
4209
|
try {
|
|
@@ -3110,9 +4224,75 @@ var import_groupBy = __toESM(require_groupBy(), 1);
|
|
|
3110
4224
|
import { Shell as Shell3 } from "@qlover/scripts-context";
|
|
3111
4225
|
var DEFAULT_TEMPLATE = "\n- ${scopeHeader} ${commitlint.message} ${commitLink} ${prLink}";
|
|
3112
4226
|
var GitChangelogFormatter = class {
|
|
4227
|
+
/**
|
|
4228
|
+
* Creates a new GitChangelogFormatter instance
|
|
4229
|
+
*
|
|
4230
|
+
* @param options - Configuration options including shell interface
|
|
4231
|
+
*
|
|
4232
|
+
* @example
|
|
4233
|
+
* ```typescript
|
|
4234
|
+
* const formatter = new GitChangelogFormatter({
|
|
4235
|
+
* shell: new Shell(),
|
|
4236
|
+
* repoUrl: 'https://github.com/org/repo',
|
|
4237
|
+
* types: [
|
|
4238
|
+
* { type: 'feat', section: '### Features' }
|
|
4239
|
+
* ],
|
|
4240
|
+
* formatTemplate: '- ${commitlint.message}'
|
|
4241
|
+
* });
|
|
4242
|
+
* ```
|
|
4243
|
+
*/
|
|
3113
4244
|
constructor(options) {
|
|
3114
4245
|
this.options = options;
|
|
3115
4246
|
}
|
|
4247
|
+
/**
|
|
4248
|
+
* Formats an array of commits into changelog entries
|
|
4249
|
+
*
|
|
4250
|
+
* Groups commits by type and formats them according to the
|
|
4251
|
+
* configured template and options. Supports commit body
|
|
4252
|
+
* inclusion and type-based sections.
|
|
4253
|
+
*
|
|
4254
|
+
* @param commits - Array of commit values to format
|
|
4255
|
+
* @param options - Optional formatting options
|
|
4256
|
+
* @returns Array of formatted changelog lines
|
|
4257
|
+
*
|
|
4258
|
+
* @example Basic formatting
|
|
4259
|
+
* ```typescript
|
|
4260
|
+
* const changelog = formatter.format([
|
|
4261
|
+
* {
|
|
4262
|
+
* base: { hash: 'abc123' },
|
|
4263
|
+
* commitlint: {
|
|
4264
|
+
* type: 'feat',
|
|
4265
|
+
* scope: 'api',
|
|
4266
|
+
* message: 'new endpoint'
|
|
4267
|
+
* }
|
|
4268
|
+
* }
|
|
4269
|
+
* ]);
|
|
4270
|
+
* // [
|
|
4271
|
+
* // '### Features',
|
|
4272
|
+
* // '- **api:** new endpoint ([abc123](...))'
|
|
4273
|
+
* // ]
|
|
4274
|
+
* ```
|
|
4275
|
+
*
|
|
4276
|
+
* @example With commit body
|
|
4277
|
+
* ```typescript
|
|
4278
|
+
* const changelog = formatter.format(
|
|
4279
|
+
* [{
|
|
4280
|
+
* commitlint: {
|
|
4281
|
+
* type: 'fix',
|
|
4282
|
+
* message: 'memory leak',
|
|
4283
|
+
* body: 'Fixed memory allocation\nAdded cleanup'
|
|
4284
|
+
* }
|
|
4285
|
+
* }],
|
|
4286
|
+
* { commitBody: true }
|
|
4287
|
+
* );
|
|
4288
|
+
* // [
|
|
4289
|
+
* // '### Bug Fixes',
|
|
4290
|
+
* // '- memory leak',
|
|
4291
|
+
* // ' Fixed memory allocation',
|
|
4292
|
+
* // ' Added cleanup'
|
|
4293
|
+
* // ]
|
|
4294
|
+
* ```
|
|
4295
|
+
*/
|
|
3116
4296
|
format(commits, options) {
|
|
3117
4297
|
const { types = [], commitBody = false } = { ...this.options, ...options };
|
|
3118
4298
|
const changelog = [];
|
|
@@ -3139,6 +4319,41 @@ var GitChangelogFormatter = class {
|
|
|
3139
4319
|
});
|
|
3140
4320
|
return changelog;
|
|
3141
4321
|
}
|
|
4322
|
+
/**
|
|
4323
|
+
* Formats a single commit into a changelog entry
|
|
4324
|
+
*
|
|
4325
|
+
* Applies the configured template to a commit, including
|
|
4326
|
+
* scope formatting, PR links, and commit hash links.
|
|
4327
|
+
*
|
|
4328
|
+
* @param commit - Commit value to format
|
|
4329
|
+
* @param options - Optional formatting options
|
|
4330
|
+
* @returns Formatted changelog entry
|
|
4331
|
+
*
|
|
4332
|
+
* @example Basic formatting
|
|
4333
|
+
* ```typescript
|
|
4334
|
+
* const entry = formatter.formatCommit({
|
|
4335
|
+
* base: { hash: 'abc123' },
|
|
4336
|
+
* commitlint: {
|
|
4337
|
+
* type: 'feat',
|
|
4338
|
+
* scope: 'api',
|
|
4339
|
+
* message: 'new endpoint'
|
|
4340
|
+
* }
|
|
4341
|
+
* });
|
|
4342
|
+
* // '- **api:** new endpoint ([abc123](...))'
|
|
4343
|
+
* ```
|
|
4344
|
+
*
|
|
4345
|
+
* @example With PR number
|
|
4346
|
+
* ```typescript
|
|
4347
|
+
* const entry = formatter.formatCommit({
|
|
4348
|
+
* base: { hash: 'def456' },
|
|
4349
|
+
* commitlint: {
|
|
4350
|
+
* message: 'fix bug'
|
|
4351
|
+
* },
|
|
4352
|
+
* prNumber: '123'
|
|
4353
|
+
* });
|
|
4354
|
+
* // '- fix bug ([def456](...)) (#123)'
|
|
4355
|
+
* ```
|
|
4356
|
+
*/
|
|
3142
4357
|
formatCommit(commit, options) {
|
|
3143
4358
|
const {
|
|
3144
4359
|
commitlint,
|
|
@@ -3165,12 +4380,65 @@ var GitChangelogFormatter = class {
|
|
|
3165
4380
|
prLink
|
|
3166
4381
|
});
|
|
3167
4382
|
}
|
|
4383
|
+
/**
|
|
4384
|
+
* Formats a target string as a Markdown link
|
|
4385
|
+
*
|
|
4386
|
+
* Creates a Markdown-formatted link with optional URL.
|
|
4387
|
+
* If no URL is provided, formats as a plain reference.
|
|
4388
|
+
*
|
|
4389
|
+
* @param target - Text to display
|
|
4390
|
+
* @param url - Optional URL for the link
|
|
4391
|
+
* @returns Formatted Markdown link
|
|
4392
|
+
*
|
|
4393
|
+
* @example With URL
|
|
4394
|
+
* ```typescript
|
|
4395
|
+
* const link = formatter.foramtLink('abc123', 'https://github.com/org/repo/commit/abc123');
|
|
4396
|
+
* // '([abc123](https://github.com/org/repo/commit/abc123))'
|
|
4397
|
+
* ```
|
|
4398
|
+
*
|
|
4399
|
+
* @example Without URL
|
|
4400
|
+
* ```typescript
|
|
4401
|
+
* const link = formatter.foramtLink('abc123');
|
|
4402
|
+
* // '(abc123)'
|
|
4403
|
+
* ```
|
|
4404
|
+
*/
|
|
3168
4405
|
foramtLink(target, url) {
|
|
3169
4406
|
return url ? `([${target}](${url}))` : `(${target})`;
|
|
3170
4407
|
}
|
|
4408
|
+
/**
|
|
4409
|
+
* Formats a commit hash as a Markdown link
|
|
4410
|
+
*
|
|
4411
|
+
* @deprecated Use foramtLink instead
|
|
4412
|
+
* @param target - Commit hash to display
|
|
4413
|
+
* @param url - Optional URL to the commit
|
|
4414
|
+
* @returns Formatted Markdown link
|
|
4415
|
+
*
|
|
4416
|
+
* @example
|
|
4417
|
+
* ```typescript
|
|
4418
|
+
* const link = formatter.formatCommitLink(
|
|
4419
|
+
* 'abc123',
|
|
4420
|
+
* 'https://github.com/org/repo/commit/abc123'
|
|
4421
|
+
* );
|
|
4422
|
+
* // '([abc123](https://github.com/org/repo/commit/abc123))'
|
|
4423
|
+
* ```
|
|
4424
|
+
*/
|
|
3171
4425
|
formatCommitLink(target, url) {
|
|
3172
4426
|
return url ? `([${target}](${url}))` : `(${target})`;
|
|
3173
4427
|
}
|
|
4428
|
+
/**
|
|
4429
|
+
* Formats a commit scope in Markdown
|
|
4430
|
+
*
|
|
4431
|
+
* Wraps the scope in bold syntax and adds a colon.
|
|
4432
|
+
*
|
|
4433
|
+
* @param scope - Scope to format
|
|
4434
|
+
* @returns Formatted scope in Markdown
|
|
4435
|
+
*
|
|
4436
|
+
* @example
|
|
4437
|
+
* ```typescript
|
|
4438
|
+
* const scope = formatter.formatScope('api');
|
|
4439
|
+
* // '**api:**'
|
|
4440
|
+
* ```
|
|
4441
|
+
*/
|
|
3174
4442
|
formatScope(scope) {
|
|
3175
4443
|
return `**${scope}:**`;
|
|
3176
4444
|
}
|
|
@@ -3224,7 +4492,30 @@ var Pather = class {
|
|
|
3224
4492
|
return child[boundaryIndex] === sep;
|
|
3225
4493
|
}
|
|
3226
4494
|
/**
|
|
3227
|
-
*
|
|
4495
|
+
* Normalized path prefix check
|
|
4496
|
+
*
|
|
4497
|
+
* Checks if sourcePath starts with targetPath after normalization.
|
|
4498
|
+
* Handles cross-platform path separators and trailing separators.
|
|
4499
|
+
*
|
|
4500
|
+
* @param sourcePath - Path to check
|
|
4501
|
+
* @param targetPath - Prefix path to match
|
|
4502
|
+
* @returns True if sourcePath starts with targetPath
|
|
4503
|
+
*
|
|
4504
|
+
* @example Basic usage
|
|
4505
|
+
* ```typescript
|
|
4506
|
+
* const pather = new Pather();
|
|
4507
|
+
*
|
|
4508
|
+
* pather.startsWith('src/utils/file.ts', 'src') // true
|
|
4509
|
+
* pather.startsWith('src\\utils\\file.ts', 'src') // true
|
|
4510
|
+
* pather.startsWith('lib/utils/file.ts', 'src') // false
|
|
4511
|
+
* ```
|
|
4512
|
+
*
|
|
4513
|
+
* @example Trailing separators
|
|
4514
|
+
* ```typescript
|
|
4515
|
+
* pather.startsWith('src/utils', 'src/') // true
|
|
4516
|
+
* pather.startsWith('src/utils/', 'src') // true
|
|
4517
|
+
* pather.startsWith('src2/utils', 'src') // false
|
|
4518
|
+
* ```
|
|
3228
4519
|
*/
|
|
3229
4520
|
startsWith(sourcePath, targetPath) {
|
|
3230
4521
|
let src = this.toLocalPath(sourcePath);
|
|
@@ -3238,7 +4529,44 @@ var Pather = class {
|
|
|
3238
4529
|
return src.startsWith(tgt);
|
|
3239
4530
|
}
|
|
3240
4531
|
/**
|
|
3241
|
-
* Segment-aware containment check
|
|
4532
|
+
* Segment-aware path containment check
|
|
4533
|
+
*
|
|
4534
|
+
* Checks if sourcePath contains targetPath as a complete path segment.
|
|
4535
|
+
* Unlike simple substring matching, this ensures proper path boundaries.
|
|
4536
|
+
* For example, 'src/abc' does not contain 'src/a' even though 'src/a'
|
|
4537
|
+
* is a substring.
|
|
4538
|
+
*
|
|
4539
|
+
* Features:
|
|
4540
|
+
* - Cross-platform path handling
|
|
4541
|
+
* - Proper segment boundary checking
|
|
4542
|
+
* - Trailing separator normalization
|
|
4543
|
+
* - Exact match support
|
|
4544
|
+
*
|
|
4545
|
+
* @param sourcePath - Path to search in
|
|
4546
|
+
* @param targetPath - Path to search for
|
|
4547
|
+
* @returns True if sourcePath contains targetPath as a segment
|
|
4548
|
+
*
|
|
4549
|
+
* @example Basic usage
|
|
4550
|
+
* ```typescript
|
|
4551
|
+
* const pather = new Pather();
|
|
4552
|
+
*
|
|
4553
|
+
* pather.containsPath('src/utils/file.ts', 'utils') // true
|
|
4554
|
+
* pather.containsPath('src/utils/file.ts', 'src/utils') // true
|
|
4555
|
+
* pather.containsPath('src/utils/file.ts', 'til') // false
|
|
4556
|
+
* ```
|
|
4557
|
+
*
|
|
4558
|
+
* @example Segment boundaries
|
|
4559
|
+
* ```typescript
|
|
4560
|
+
* pather.containsPath('src/abc/file.ts', 'src/a') // false
|
|
4561
|
+
* pather.containsPath('src/abc/file.ts', 'src/abc') // true
|
|
4562
|
+
* ```
|
|
4563
|
+
*
|
|
4564
|
+
* @example Trailing separators
|
|
4565
|
+
* ```typescript
|
|
4566
|
+
* pather.containsPath('src/utils/', 'utils') // true
|
|
4567
|
+
* pather.containsPath('src/utils', 'utils/') // true
|
|
4568
|
+
* pather.containsPath('src/utils/', 'utils/') // true
|
|
4569
|
+
* ```
|
|
3242
4570
|
*/
|
|
3243
4571
|
containsPath(sourcePath, targetPath) {
|
|
3244
4572
|
let src = this.toLocalPath(sourcePath);
|
|
@@ -3264,18 +4592,49 @@ var Pather = class {
|
|
|
3264
4592
|
// src/plugins/githubPR/GithubChangelog.ts
|
|
3265
4593
|
var DOMAIN = "https://github.com";
|
|
3266
4594
|
var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
4595
|
+
/**
|
|
4596
|
+
* Creates a new GitHub changelog generator
|
|
4597
|
+
*
|
|
4598
|
+
* @param options - Changelog generation options
|
|
4599
|
+
* @param githubManager - GitHub API manager
|
|
4600
|
+
*
|
|
4601
|
+
* @example
|
|
4602
|
+
* ```typescript
|
|
4603
|
+
* const changelog = new GithubChangelog({
|
|
4604
|
+
* shell,
|
|
4605
|
+
* logger,
|
|
4606
|
+
* mergePRcommit: true,
|
|
4607
|
+
* githubRootPath: 'https://github.com/org/repo'
|
|
4608
|
+
* }, githubManager);
|
|
4609
|
+
* ```
|
|
4610
|
+
*/
|
|
3267
4611
|
constructor(options, githubManager) {
|
|
3268
4612
|
super(options);
|
|
3269
4613
|
this.options = options;
|
|
3270
4614
|
this.githubManager = githubManager;
|
|
3271
4615
|
}
|
|
4616
|
+
/** Path manipulation utility */
|
|
3272
4617
|
pather = new Pather();
|
|
3273
4618
|
/**
|
|
3274
|
-
*
|
|
3275
|
-
*
|
|
3276
|
-
*
|
|
3277
|
-
*
|
|
4619
|
+
* Filters commits by directory
|
|
4620
|
+
*
|
|
4621
|
+
* Filters commits based on whether they contain changes in
|
|
4622
|
+
* the specified directory. Uses GitHub API to get detailed
|
|
4623
|
+
* commit information.
|
|
4624
|
+
*
|
|
4625
|
+
* @param commits - Array of commits to filter
|
|
4626
|
+
* @param directory - Directory path to filter by
|
|
4627
|
+
* @returns Promise resolving to filtered commits
|
|
3278
4628
|
* @since 2.4.0
|
|
4629
|
+
*
|
|
4630
|
+
* @example
|
|
4631
|
+
* ```typescript
|
|
4632
|
+
* const commits = await changelog.filterCommitsByDirectory(
|
|
4633
|
+
* allCommits,
|
|
4634
|
+
* 'packages/pkg-a'
|
|
4635
|
+
* );
|
|
4636
|
+
* // Only commits that modified files in packages/pkg-a
|
|
4637
|
+
* ```
|
|
3279
4638
|
*/
|
|
3280
4639
|
async filterCommitsByDirectory(commits, directory) {
|
|
3281
4640
|
const result = [];
|
|
@@ -3293,6 +4652,41 @@ var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
|
3293
4652
|
}
|
|
3294
4653
|
return result;
|
|
3295
4654
|
}
|
|
4655
|
+
/**
|
|
4656
|
+
* Gets complete commit information with PR details
|
|
4657
|
+
*
|
|
4658
|
+
* Retrieves commits and enhances them with pull request
|
|
4659
|
+
* information. For commits associated with PRs, includes
|
|
4660
|
+
* all PR commits and filters by directory.
|
|
4661
|
+
*
|
|
4662
|
+
* Process:
|
|
4663
|
+
* 1. Get base commits
|
|
4664
|
+
* 2. Extract PR numbers
|
|
4665
|
+
* 3. Fetch PR commits
|
|
4666
|
+
* 4. Filter by directory
|
|
4667
|
+
* 5. Flatten results
|
|
4668
|
+
*
|
|
4669
|
+
* @param options - Changelog options
|
|
4670
|
+
* @returns Promise resolving to enhanced commits
|
|
4671
|
+
*
|
|
4672
|
+
* @example Basic usage
|
|
4673
|
+
* ```typescript
|
|
4674
|
+
* const commits = await changelog.getFullCommit({
|
|
4675
|
+
* from: 'v1.0.0',
|
|
4676
|
+
* directory: 'packages/pkg-a'
|
|
4677
|
+
* });
|
|
4678
|
+
* // Returns commits with PR information
|
|
4679
|
+
* ```
|
|
4680
|
+
*
|
|
4681
|
+
* @example With PR merging
|
|
4682
|
+
* ```typescript
|
|
4683
|
+
* const commits = await changelog.getFullCommit({
|
|
4684
|
+
* mergePRcommit: true,
|
|
4685
|
+
* directory: 'packages/pkg-a'
|
|
4686
|
+
* });
|
|
4687
|
+
* // Includes all PR commits
|
|
4688
|
+
* ```
|
|
4689
|
+
*/
|
|
3296
4690
|
async getFullCommit(options) {
|
|
3297
4691
|
const _options = { ...this.options, ...options };
|
|
3298
4692
|
const allCommits = await this.getCommits(_options);
|
|
@@ -3320,6 +4714,41 @@ var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
|
3320
4714
|
);
|
|
3321
4715
|
return newallCommits.flat();
|
|
3322
4716
|
}
|
|
4717
|
+
/**
|
|
4718
|
+
* Transforms workspaces with GitHub changelogs
|
|
4719
|
+
*
|
|
4720
|
+
* Processes each workspace to add GitHub-specific changelog
|
|
4721
|
+
* information. Includes:
|
|
4722
|
+
* - GitHub repository URL
|
|
4723
|
+
* - PR-aware commit history
|
|
4724
|
+
* - Formatted changelog with links
|
|
4725
|
+
*
|
|
4726
|
+
* Process:
|
|
4727
|
+
* 1. Build GitHub root path
|
|
4728
|
+
* 2. Configure changelog options
|
|
4729
|
+
* 3. Get commits for each workspace
|
|
4730
|
+
* 4. Format changelog with links
|
|
4731
|
+
* 5. Update workspace objects
|
|
4732
|
+
*
|
|
4733
|
+
* @param workspaces - Array of workspaces to process
|
|
4734
|
+
* @param context - Release context
|
|
4735
|
+
* @returns Promise resolving to updated workspaces
|
|
4736
|
+
*
|
|
4737
|
+
* @example
|
|
4738
|
+
* ```typescript
|
|
4739
|
+
* const workspaces = await changelog.transformWorkspace(
|
|
4740
|
+
* [
|
|
4741
|
+
* {
|
|
4742
|
+
* name: 'pkg-a',
|
|
4743
|
+
* path: 'packages/a',
|
|
4744
|
+
* lastTag: 'v1.0.0'
|
|
4745
|
+
* }
|
|
4746
|
+
* ],
|
|
4747
|
+
* context
|
|
4748
|
+
* );
|
|
4749
|
+
* // Returns workspaces with GitHub-formatted changelogs
|
|
4750
|
+
* ```
|
|
4751
|
+
*/
|
|
3323
4752
|
async transformWorkspace(workspaces, context) {
|
|
3324
4753
|
const githubRootPath = [
|
|
3325
4754
|
DOMAIN,
|
|
@@ -3369,6 +4798,26 @@ import { Shell as Shell4 } from "@qlover/scripts-context";
|
|
|
3369
4798
|
var DEFAULT_RELEASE_NAME = "Release ${name} v${version}";
|
|
3370
4799
|
var DEFAULT_COMMIT_MESSAGE = "chore(tag): ${name} v${version}";
|
|
3371
4800
|
var GithubPR = class extends GitBase {
|
|
4801
|
+
/**
|
|
4802
|
+
* Creates a new GithubPR plugin instance
|
|
4803
|
+
*
|
|
4804
|
+
* Initializes the plugin with GitHub-specific configuration and
|
|
4805
|
+
* sets up release parameters and GitHub manager.
|
|
4806
|
+
*
|
|
4807
|
+
* @param context - Release context
|
|
4808
|
+
* @param props - Plugin configuration
|
|
4809
|
+
*
|
|
4810
|
+
* @example
|
|
4811
|
+
* ```typescript
|
|
4812
|
+
* const plugin = new GithubPR(context, {
|
|
4813
|
+
* releasePR: true,
|
|
4814
|
+
* releaseName: 'Release v${version}',
|
|
4815
|
+
* commitMessage: 'chore: release v${version}',
|
|
4816
|
+
* draft: false,
|
|
4817
|
+
* preRelease: false
|
|
4818
|
+
* });
|
|
4819
|
+
* ```
|
|
4820
|
+
*/
|
|
3372
4821
|
constructor(context, props) {
|
|
3373
4822
|
super(context, "githubPR", {
|
|
3374
4823
|
releaseName: DEFAULT_RELEASE_NAME,
|
|
@@ -3384,15 +4833,67 @@ var GithubPR = class extends GitBase {
|
|
|
3384
4833
|
}
|
|
3385
4834
|
releaseParams;
|
|
3386
4835
|
githubManager;
|
|
4836
|
+
/**
|
|
4837
|
+
* Determines if the plugin should be enabled
|
|
4838
|
+
*
|
|
4839
|
+
* Plugin is enabled unless explicitly skipped via configuration.
|
|
4840
|
+
* This allows for conditional PR creation and release publishing.
|
|
4841
|
+
*
|
|
4842
|
+
* @param _name - Plugin name (unused)
|
|
4843
|
+
* @returns True if plugin should be enabled
|
|
4844
|
+
*
|
|
4845
|
+
* @example
|
|
4846
|
+
* ```typescript
|
|
4847
|
+
* const plugin = new GithubPR(context, { skip: true });
|
|
4848
|
+
* plugin.enabled(); // false
|
|
4849
|
+
*
|
|
4850
|
+
* const plugin2 = new GithubPR(context, {});
|
|
4851
|
+
* plugin2.enabled(); // true
|
|
4852
|
+
* ```
|
|
4853
|
+
*/
|
|
3387
4854
|
enabled(_name) {
|
|
3388
4855
|
if (this.getConfig("skip")) {
|
|
3389
4856
|
return false;
|
|
3390
4857
|
}
|
|
3391
4858
|
return true;
|
|
3392
4859
|
}
|
|
4860
|
+
/**
|
|
4861
|
+
* Determines if the plugin is in publish mode
|
|
4862
|
+
*
|
|
4863
|
+
* In publish mode, the plugin publishes releases directly.
|
|
4864
|
+
* In non-publish mode (releasePR=true), it creates pull requests.
|
|
4865
|
+
*
|
|
4866
|
+
* @returns True if in publish mode
|
|
4867
|
+
*
|
|
4868
|
+
* @example
|
|
4869
|
+
* ```typescript
|
|
4870
|
+
* const plugin = new GithubPR(context, { releasePR: true });
|
|
4871
|
+
* plugin.isPublish; // false (PR mode)
|
|
4872
|
+
*
|
|
4873
|
+
* const plugin2 = new GithubPR(context, { releasePR: false });
|
|
4874
|
+
* plugin2.isPublish; // true (publish mode)
|
|
4875
|
+
* ```
|
|
4876
|
+
*/
|
|
3393
4877
|
get isPublish() {
|
|
3394
4878
|
return !this.getConfig("releasePR");
|
|
3395
4879
|
}
|
|
4880
|
+
/**
|
|
4881
|
+
* Checks if the current repository is a GitHub repository
|
|
4882
|
+
*
|
|
4883
|
+
* Verifies that the remote URL contains 'github.com' to ensure
|
|
4884
|
+
* GitHub-specific features can be used.
|
|
4885
|
+
*
|
|
4886
|
+
* @returns Promise resolving to true if GitHub repository
|
|
4887
|
+
*
|
|
4888
|
+
* @example
|
|
4889
|
+
* ```typescript
|
|
4890
|
+
* const isGithub = await plugin.isGithubRepository();
|
|
4891
|
+
* if (isGithub) {
|
|
4892
|
+
* // Use GitHub-specific features
|
|
4893
|
+
* }
|
|
4894
|
+
* ```
|
|
4895
|
+
* @private
|
|
4896
|
+
*/
|
|
3396
4897
|
async isGithubRepository() {
|
|
3397
4898
|
try {
|
|
3398
4899
|
const remoteUrl = await this.getRemoteUrl();
|
|
@@ -3401,6 +4902,24 @@ var GithubPR = class extends GitBase {
|
|
|
3401
4902
|
return false;
|
|
3402
4903
|
}
|
|
3403
4904
|
}
|
|
4905
|
+
/**
|
|
4906
|
+
* Plugin initialization hook
|
|
4907
|
+
*
|
|
4908
|
+
* Performs pre-execution setup:
|
|
4909
|
+
* 1. Verifies repository is on GitHub
|
|
4910
|
+
* 2. Runs parent class initialization
|
|
4911
|
+
* 3. Sets up NPM token for publishing
|
|
4912
|
+
*
|
|
4913
|
+
* @throws Error if not a GitHub repository
|
|
4914
|
+
* @throws Error if NPM_TOKEN missing in publish mode
|
|
4915
|
+
*
|
|
4916
|
+
* @example
|
|
4917
|
+
* ```typescript
|
|
4918
|
+
* const plugin = new GithubPR(context, {});
|
|
4919
|
+
* await plugin.onBefore();
|
|
4920
|
+
* // Throws if not GitHub repo or missing NPM token
|
|
4921
|
+
* ```
|
|
4922
|
+
*/
|
|
3404
4923
|
async onBefore() {
|
|
3405
4924
|
this.logger.debug("GithubPR onBefore");
|
|
3406
4925
|
const isGithub = await this.isGithubRepository();
|
|
@@ -3420,6 +4939,24 @@ var GithubPR = class extends GitBase {
|
|
|
3420
4939
|
);
|
|
3421
4940
|
}
|
|
3422
4941
|
}
|
|
4942
|
+
/**
|
|
4943
|
+
* Main plugin execution hook
|
|
4944
|
+
*
|
|
4945
|
+
* Processes changelogs for all workspaces using GitHub-specific
|
|
4946
|
+
* formatting and updates the context with the results.
|
|
4947
|
+
*
|
|
4948
|
+
* Process:
|
|
4949
|
+
* 1. Initialize GitHub changelog processor
|
|
4950
|
+
* 2. Transform workspace changelogs
|
|
4951
|
+
* 3. Update context with new workspace info
|
|
4952
|
+
*
|
|
4953
|
+
* @example
|
|
4954
|
+
* ```typescript
|
|
4955
|
+
* const plugin = new GithubPR(context, {});
|
|
4956
|
+
* await plugin.onExec();
|
|
4957
|
+
* // Transforms changelogs with GitHub links
|
|
4958
|
+
* ```
|
|
4959
|
+
*/
|
|
3423
4960
|
async onExec() {
|
|
3424
4961
|
const workspaces = this.context.workspaces;
|
|
3425
4962
|
const githubChangelog = new GithubChangelog(
|
|
@@ -3432,6 +4969,27 @@ var GithubPR = class extends GitBase {
|
|
|
3432
4969
|
});
|
|
3433
4970
|
this.context.setWorkspaces(newWorkspaces);
|
|
3434
4971
|
}
|
|
4972
|
+
/**
|
|
4973
|
+
* Success hook after plugin execution
|
|
4974
|
+
*
|
|
4975
|
+
* Handles either PR creation or release publishing based on
|
|
4976
|
+
* configuration. In publish mode, publishes to NPM and creates
|
|
4977
|
+
* GitHub releases. In PR mode, creates release pull requests.
|
|
4978
|
+
*
|
|
4979
|
+
* @example PR mode
|
|
4980
|
+
* ```typescript
|
|
4981
|
+
* const plugin = new GithubPR(context, { releasePR: true });
|
|
4982
|
+
* await plugin.onSuccess();
|
|
4983
|
+
* // Creates release PR
|
|
4984
|
+
* ```
|
|
4985
|
+
*
|
|
4986
|
+
* @example Publish mode
|
|
4987
|
+
* ```typescript
|
|
4988
|
+
* const plugin = new GithubPR(context, { releasePR: false });
|
|
4989
|
+
* await plugin.onSuccess();
|
|
4990
|
+
* // Publishes to NPM and creates GitHub release
|
|
4991
|
+
* ```
|
|
4992
|
+
*/
|
|
3435
4993
|
async onSuccess() {
|
|
3436
4994
|
if (this.isPublish) {
|
|
3437
4995
|
await this.publishPR(this.context.workspaces);
|
|
@@ -3439,6 +4997,28 @@ var GithubPR = class extends GitBase {
|
|
|
3439
4997
|
}
|
|
3440
4998
|
await this.releasePR(this.context.workspaces);
|
|
3441
4999
|
}
|
|
5000
|
+
/**
|
|
5001
|
+
* Creates a release pull request
|
|
5002
|
+
*
|
|
5003
|
+
* Handles the complete process of creating a release PR:
|
|
5004
|
+
* 1. Creates release commit
|
|
5005
|
+
* 2. Creates release branch
|
|
5006
|
+
* 3. Creates and configures pull request
|
|
5007
|
+
*
|
|
5008
|
+
* @param workspaces - Array of workspace configurations
|
|
5009
|
+
*
|
|
5010
|
+
* @example
|
|
5011
|
+
* ```typescript
|
|
5012
|
+
* const workspaces = [{
|
|
5013
|
+
* name: 'pkg-a',
|
|
5014
|
+
* version: '1.0.0',
|
|
5015
|
+
* changelog: '...'
|
|
5016
|
+
* }];
|
|
5017
|
+
*
|
|
5018
|
+
* await plugin.releasePR(workspaces);
|
|
5019
|
+
* // Creates PR with release changes
|
|
5020
|
+
* ```
|
|
5021
|
+
*/
|
|
3442
5022
|
async releasePR(workspaces) {
|
|
3443
5023
|
await this.step({
|
|
3444
5024
|
label: "Release Commit",
|
|
@@ -3450,6 +5030,28 @@ var GithubPR = class extends GitBase {
|
|
|
3450
5030
|
});
|
|
3451
5031
|
await this.releasePullRequest(workspaces, releaseBranchParams);
|
|
3452
5032
|
}
|
|
5033
|
+
/**
|
|
5034
|
+
* Publishes releases to NPM and GitHub
|
|
5035
|
+
*
|
|
5036
|
+
* In non-dry-run mode:
|
|
5037
|
+
* 1. Publishes packages to NPM
|
|
5038
|
+
* 2. Pushes tags to GitHub
|
|
5039
|
+
* 3. Creates GitHub releases
|
|
5040
|
+
*
|
|
5041
|
+
* @param workspaces - Array of workspace configurations
|
|
5042
|
+
*
|
|
5043
|
+
* @example
|
|
5044
|
+
* ```typescript
|
|
5045
|
+
* const workspaces = [{
|
|
5046
|
+
* name: 'pkg-a',
|
|
5047
|
+
* version: '1.0.0',
|
|
5048
|
+
* changelog: '...'
|
|
5049
|
+
* }];
|
|
5050
|
+
*
|
|
5051
|
+
* await plugin.publishPR(workspaces);
|
|
5052
|
+
* // Publishes to NPM and creates GitHub releases
|
|
5053
|
+
* ```
|
|
5054
|
+
*/
|
|
3453
5055
|
async publishPR(workspaces) {
|
|
3454
5056
|
if (!this.getConfig("dryRunCreatePR")) {
|
|
3455
5057
|
await this.context.runChangesetsCli("publish");
|
|
@@ -3465,6 +5067,34 @@ var GithubPR = class extends GitBase {
|
|
|
3465
5067
|
)
|
|
3466
5068
|
});
|
|
3467
5069
|
}
|
|
5070
|
+
/**
|
|
5071
|
+
* Creates release commit(s)
|
|
5072
|
+
*
|
|
5073
|
+
* Creates either a single commit for all workspaces or
|
|
5074
|
+
* individual commits per workspace. Uses configured commit
|
|
5075
|
+
* message template.
|
|
5076
|
+
*
|
|
5077
|
+
* @param workspaces - Array of workspace configurations
|
|
5078
|
+
*
|
|
5079
|
+
* @example Single workspace
|
|
5080
|
+
* ```typescript
|
|
5081
|
+
* await plugin.relesaeCommit([{
|
|
5082
|
+
* name: 'pkg-a',
|
|
5083
|
+
* version: '1.0.0'
|
|
5084
|
+
* }]);
|
|
5085
|
+
* // Creates: "chore(tag): pkg-a v1.0.0"
|
|
5086
|
+
* ```
|
|
5087
|
+
*
|
|
5088
|
+
* @example Multiple workspaces
|
|
5089
|
+
* ```typescript
|
|
5090
|
+
* await plugin.relesaeCommit([
|
|
5091
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
5092
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
5093
|
+
* ]);
|
|
5094
|
+
* // Creates: "chore(tag): pkg-a v1.0.0,pkg-b v2.0.0"
|
|
5095
|
+
* ```
|
|
5096
|
+
* @private
|
|
5097
|
+
*/
|
|
3468
5098
|
async relesaeCommit(workspaces) {
|
|
3469
5099
|
const commitArgs = this.getConfig("commitArgs", []);
|
|
3470
5100
|
if (workspaces.length === 1) {
|
|
@@ -3476,6 +5106,34 @@ var GithubPR = class extends GitBase {
|
|
|
3476
5106
|
const commitMessage = `chore(tag): ${workspaces.map((w) => `${w.name} v${w.version}`).join(",")}`;
|
|
3477
5107
|
await this.commit(commitMessage, commitArgs);
|
|
3478
5108
|
}
|
|
5109
|
+
/**
|
|
5110
|
+
* Creates and optionally merges a release pull request
|
|
5111
|
+
*
|
|
5112
|
+
* Creates a PR with release changes and handles auto-merge
|
|
5113
|
+
* if configured. Adds release and change labels to the PR.
|
|
5114
|
+
*
|
|
5115
|
+
* @param workspaces - Array of workspace configurations
|
|
5116
|
+
* @param releaseBranchParams - Branch and tag information
|
|
5117
|
+
*
|
|
5118
|
+
* @example Manual merge
|
|
5119
|
+
* ```typescript
|
|
5120
|
+
* await plugin.releasePullRequest(
|
|
5121
|
+
* workspaces,
|
|
5122
|
+
* { releaseBranch: 'release-v1.0.0', tagName: 'v1.0.0' }
|
|
5123
|
+
* );
|
|
5124
|
+
* // Creates PR for manual merge
|
|
5125
|
+
* ```
|
|
5126
|
+
*
|
|
5127
|
+
* @example Auto-merge
|
|
5128
|
+
* ```typescript
|
|
5129
|
+
* const plugin = new GithubPR(context, {
|
|
5130
|
+
* autoMergeReleasePR: true
|
|
5131
|
+
* });
|
|
5132
|
+
*
|
|
5133
|
+
* await plugin.releasePullRequest(workspaces, params);
|
|
5134
|
+
* // Creates and auto-merges PR
|
|
5135
|
+
* ```
|
|
5136
|
+
*/
|
|
3479
5137
|
async releasePullRequest(workspaces, releaseBranchParams) {
|
|
3480
5138
|
const prNumber = await this.step({
|
|
3481
5139
|
label: "Create Release PR",
|
|
@@ -3497,6 +5155,34 @@ var GithubPR = class extends GitBase {
|
|
|
3497
5155
|
`Please manually merge PR(#${prNumber}) and complete the publishing process afterwards`
|
|
3498
5156
|
);
|
|
3499
5157
|
}
|
|
5158
|
+
/**
|
|
5159
|
+
* Creates a commit for a single workspace
|
|
5160
|
+
*
|
|
5161
|
+
* Uses the configured commit message template to create a
|
|
5162
|
+
* commit for the workspace's changes.
|
|
5163
|
+
*
|
|
5164
|
+
* @param workspace - Workspace configuration
|
|
5165
|
+
* @param commitArgs - Additional Git commit arguments
|
|
5166
|
+
* @returns Promise resolving to commit output
|
|
5167
|
+
*
|
|
5168
|
+
* @example Basic commit
|
|
5169
|
+
* ```typescript
|
|
5170
|
+
* await plugin.commitWorkspace({
|
|
5171
|
+
* name: 'pkg-a',
|
|
5172
|
+
* version: '1.0.0'
|
|
5173
|
+
* });
|
|
5174
|
+
* // Creates: "chore(tag): pkg-a v1.0.0"
|
|
5175
|
+
* ```
|
|
5176
|
+
*
|
|
5177
|
+
* @example With arguments
|
|
5178
|
+
* ```typescript
|
|
5179
|
+
* await plugin.commitWorkspace(
|
|
5180
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
5181
|
+
* ['--no-verify']
|
|
5182
|
+
* );
|
|
5183
|
+
* ```
|
|
5184
|
+
* @private
|
|
5185
|
+
*/
|
|
3500
5186
|
async commitWorkspace(workspace, commitArgs = []) {
|
|
3501
5187
|
const commitMessage = Shell4.format(
|
|
3502
5188
|
this.getConfig("commitMessage", DEFAULT_COMMIT_MESSAGE),
|
|
@@ -3514,6 +5200,37 @@ var GithubPR = class extends GitBase {
|
|
|
3514
5200
|
*
|
|
3515
5201
|
* @returns The release branch.
|
|
3516
5202
|
*/
|
|
5203
|
+
/**
|
|
5204
|
+
* Creates a release branch for changes
|
|
5205
|
+
*
|
|
5206
|
+
* Creates a new branch from the current branch for release
|
|
5207
|
+
* changes. The branch name is generated from the configured
|
|
5208
|
+
* template and workspace information.
|
|
5209
|
+
*
|
|
5210
|
+
* Process:
|
|
5211
|
+
* 1. Generate branch parameters
|
|
5212
|
+
* 2. Fetch required branches
|
|
5213
|
+
* 3. Create and push release branch
|
|
5214
|
+
*
|
|
5215
|
+
* @param workspaces - Array of workspace configurations
|
|
5216
|
+
* @returns Promise resolving to branch parameters
|
|
5217
|
+
*
|
|
5218
|
+
* @example
|
|
5219
|
+
* ```typescript
|
|
5220
|
+
* const params = await plugin.createReleaseBranch([{
|
|
5221
|
+
* name: 'pkg-a',
|
|
5222
|
+
* version: '1.0.0'
|
|
5223
|
+
* }]);
|
|
5224
|
+
* // {
|
|
5225
|
+
* // tagName: 'pkg-a@1.0.0',
|
|
5226
|
+
* // releaseBranch: 'release-pkg-a-1.0.0'
|
|
5227
|
+
* // }
|
|
5228
|
+
* ```
|
|
5229
|
+
*
|
|
5230
|
+
* @throws Error if tag name is invalid
|
|
5231
|
+
* @throws Error if branch creation fails
|
|
5232
|
+
* @private
|
|
5233
|
+
*/
|
|
3517
5234
|
async createReleaseBranch(workspaces) {
|
|
3518
5235
|
const params = this.releaseParams.getReleaseBranchParams(
|
|
3519
5236
|
workspaces,
|
|
@@ -3556,6 +5273,42 @@ var GithubPR = class extends GitBase {
|
|
|
3556
5273
|
* @param releaseBranchParams - The release branch params.
|
|
3557
5274
|
* @returns The created pull request number.
|
|
3558
5275
|
*/
|
|
5276
|
+
/**
|
|
5277
|
+
* Creates a release pull request
|
|
5278
|
+
*
|
|
5279
|
+
* Creates a pull request with:
|
|
5280
|
+
* 1. Release label
|
|
5281
|
+
* 2. Change labels (if configured)
|
|
5282
|
+
* 3. Generated title and body
|
|
5283
|
+
* 4. Proper branch configuration
|
|
5284
|
+
*
|
|
5285
|
+
* @param workspaces - Array of workspace configurations
|
|
5286
|
+
* @param releaseBranchParams - Branch and tag information
|
|
5287
|
+
* @returns Promise resolving to PR number
|
|
5288
|
+
*
|
|
5289
|
+
* @example Basic PR
|
|
5290
|
+
* ```typescript
|
|
5291
|
+
* const prNumber = await plugin.createReleasePR(
|
|
5292
|
+
* workspaces,
|
|
5293
|
+
* { releaseBranch: 'release-v1.0.0', tagName: 'v1.0.0' }
|
|
5294
|
+
* );
|
|
5295
|
+
* // Creates PR with default labels
|
|
5296
|
+
* ```
|
|
5297
|
+
*
|
|
5298
|
+
* @example With change labels
|
|
5299
|
+
* ```typescript
|
|
5300
|
+
* const plugin = new GithubPR(context, {
|
|
5301
|
+
* pushChangeLabels: true
|
|
5302
|
+
* });
|
|
5303
|
+
*
|
|
5304
|
+
* const prNumber = await plugin.createReleasePR(
|
|
5305
|
+
* workspaces,
|
|
5306
|
+
* params
|
|
5307
|
+
* );
|
|
5308
|
+
* // Creates PR with release and change labels
|
|
5309
|
+
* ```
|
|
5310
|
+
* @private
|
|
5311
|
+
*/
|
|
3559
5312
|
async createReleasePR(workspaces, releaseBranchParams) {
|
|
3560
5313
|
const label = await this.githubManager.createReleasePRLabel();
|
|
3561
5314
|
let labels = [label.name];
|
|
@@ -3589,21 +5342,137 @@ import { join as join2, resolve, relative } from "path";
|
|
|
3589
5342
|
|
|
3590
5343
|
// src/implments/ReleaseLabel.ts
|
|
3591
5344
|
var ReleaseLabel = class {
|
|
5345
|
+
/**
|
|
5346
|
+
* Creates a new ReleaseLabel instance
|
|
5347
|
+
*
|
|
5348
|
+
* @param options - Configuration options for label management
|
|
5349
|
+
*
|
|
5350
|
+
* @example
|
|
5351
|
+
* ```typescript
|
|
5352
|
+
* const label = new ReleaseLabel({
|
|
5353
|
+
* // Label template with ${name} placeholder
|
|
5354
|
+
* changePackagesLabel: 'changed:${name}',
|
|
5355
|
+
*
|
|
5356
|
+
* // Package directories to monitor
|
|
5357
|
+
* packagesDirectories: ['packages/a', 'packages/b'],
|
|
5358
|
+
*
|
|
5359
|
+
* // Optional custom comparison logic
|
|
5360
|
+
* compare: (file, pkg) => file.includes(pkg)
|
|
5361
|
+
* });
|
|
5362
|
+
* ```
|
|
5363
|
+
*/
|
|
3592
5364
|
constructor(options) {
|
|
3593
5365
|
this.options = options;
|
|
3594
5366
|
}
|
|
5367
|
+
/**
|
|
5368
|
+
* Compares a changed file path against a package path
|
|
5369
|
+
*
|
|
5370
|
+
* Uses custom comparison function if provided, otherwise
|
|
5371
|
+
* checks if the file path starts with the package path.
|
|
5372
|
+
*
|
|
5373
|
+
* @param changedFilePath - Path of the changed file
|
|
5374
|
+
* @param packagePath - Path of the package to check against
|
|
5375
|
+
* @returns True if the file belongs to the package
|
|
5376
|
+
*
|
|
5377
|
+
* @example
|
|
5378
|
+
* ```typescript
|
|
5379
|
+
* // Default comparison
|
|
5380
|
+
* label.compare('packages/a/src/index.ts', 'packages/a');
|
|
5381
|
+
* // true
|
|
5382
|
+
*
|
|
5383
|
+
* // Custom comparison
|
|
5384
|
+
* const label = new ReleaseLabel({
|
|
5385
|
+
* ...options,
|
|
5386
|
+
* compare: (file, pkg) => file.includes(pkg)
|
|
5387
|
+
* });
|
|
5388
|
+
* label.compare('src/packages/a/index.ts', 'packages/a');
|
|
5389
|
+
* // true
|
|
5390
|
+
* ```
|
|
5391
|
+
*/
|
|
3595
5392
|
compare(changedFilePath, packagePath) {
|
|
3596
5393
|
if (typeof this.options.compare === "function") {
|
|
3597
5394
|
return this.options.compare(changedFilePath, packagePath);
|
|
3598
5395
|
}
|
|
3599
5396
|
return changedFilePath.startsWith(packagePath);
|
|
3600
5397
|
}
|
|
5398
|
+
/**
|
|
5399
|
+
* Generates a change label for a single package
|
|
5400
|
+
*
|
|
5401
|
+
* Replaces ${name} placeholder in the label template with
|
|
5402
|
+
* the package path.
|
|
5403
|
+
*
|
|
5404
|
+
* @param packagePath - Path of the package
|
|
5405
|
+
* @param label - Optional custom label template
|
|
5406
|
+
* @returns Formatted change label
|
|
5407
|
+
*
|
|
5408
|
+
* @example
|
|
5409
|
+
* ```typescript
|
|
5410
|
+
* // Default label template
|
|
5411
|
+
* label.toChangeLabel('packages/a');
|
|
5412
|
+
* // 'changed:packages/a'
|
|
5413
|
+
*
|
|
5414
|
+
* // Custom label template
|
|
5415
|
+
* label.toChangeLabel('packages/a', 'modified:${name}');
|
|
5416
|
+
* // 'modified:packages/a'
|
|
5417
|
+
* ```
|
|
5418
|
+
*/
|
|
3601
5419
|
toChangeLabel(packagePath, label = this.options.changePackagesLabel) {
|
|
3602
5420
|
return label.replace("${name}", packagePath);
|
|
3603
5421
|
}
|
|
5422
|
+
/**
|
|
5423
|
+
* Generates change labels for multiple packages
|
|
5424
|
+
*
|
|
5425
|
+
* Maps each package path to a formatted change label.
|
|
5426
|
+
*
|
|
5427
|
+
* @param packages - Array of package paths
|
|
5428
|
+
* @param label - Optional custom label template
|
|
5429
|
+
* @returns Array of formatted change labels
|
|
5430
|
+
*
|
|
5431
|
+
* @example
|
|
5432
|
+
* ```typescript
|
|
5433
|
+
* // Default label template
|
|
5434
|
+
* label.toChangeLabels(['packages/a', 'packages/b']);
|
|
5435
|
+
* // ['changed:packages/a', 'changed:packages/b']
|
|
5436
|
+
*
|
|
5437
|
+
* // Custom label template
|
|
5438
|
+
* label.toChangeLabels(
|
|
5439
|
+
* ['packages/a', 'packages/b'],
|
|
5440
|
+
* 'modified:${name}'
|
|
5441
|
+
* );
|
|
5442
|
+
* // ['modified:packages/a', 'modified:packages/b']
|
|
5443
|
+
* ```
|
|
5444
|
+
*/
|
|
3604
5445
|
toChangeLabels(packages, label = this.options.changePackagesLabel) {
|
|
3605
5446
|
return packages.map((pkg) => this.toChangeLabel(pkg, label));
|
|
3606
5447
|
}
|
|
5448
|
+
/**
|
|
5449
|
+
* Identifies packages affected by changed files
|
|
5450
|
+
*
|
|
5451
|
+
* Checks each changed file against package paths to determine
|
|
5452
|
+
* which packages have been modified.
|
|
5453
|
+
*
|
|
5454
|
+
* @param changedFiles - Array or Set of changed file paths
|
|
5455
|
+
* @param packages - Optional array of package paths to check
|
|
5456
|
+
* @returns Array of affected package paths
|
|
5457
|
+
*
|
|
5458
|
+
* @example
|
|
5459
|
+
* ```typescript
|
|
5460
|
+
* // Check against default packages
|
|
5461
|
+
* label.pick(['packages/a/src/index.ts']);
|
|
5462
|
+
* // ['packages/a']
|
|
5463
|
+
*
|
|
5464
|
+
* // Check specific packages
|
|
5465
|
+
* label.pick(
|
|
5466
|
+
* ['packages/a/index.ts', 'packages/b/test.ts'],
|
|
5467
|
+
* ['packages/a', 'packages/c']
|
|
5468
|
+
* );
|
|
5469
|
+
* // ['packages/a']
|
|
5470
|
+
*
|
|
5471
|
+
* // Using Set of files
|
|
5472
|
+
* label.pick(new Set(['packages/a/index.ts']));
|
|
5473
|
+
* // ['packages/a']
|
|
5474
|
+
* ```
|
|
5475
|
+
*/
|
|
3607
5476
|
pick(changedFiles, packages = this.options.packagesDirectories) {
|
|
3608
5477
|
const result = [];
|
|
3609
5478
|
for (const pkgPath of packages) {
|
|
@@ -3972,6 +5841,31 @@ import {
|
|
|
3972
5841
|
} from "@qlover/scripts-context";
|
|
3973
5842
|
var contentTmplate = "---\n'${name}': '${increment}'\n---\n\n${changelog}";
|
|
3974
5843
|
var Changelog = class extends ScriptPlugin3 {
|
|
5844
|
+
/**
|
|
5845
|
+
* Creates a new Changelog plugin instance
|
|
5846
|
+
*
|
|
5847
|
+
* Initializes the plugin with default configuration values and
|
|
5848
|
+
* merges them with provided options.
|
|
5849
|
+
*
|
|
5850
|
+
* Default values:
|
|
5851
|
+
* - increment: 'patch'
|
|
5852
|
+
* - changesetRoot: '.changeset'
|
|
5853
|
+
* - tagTemplate: '${name}@${version}'
|
|
5854
|
+
* - tagPrefix: '${name}'
|
|
5855
|
+
* - tagMatch: '${name}@*'
|
|
5856
|
+
*
|
|
5857
|
+
* @param context - Release context
|
|
5858
|
+
* @param props - Plugin configuration
|
|
5859
|
+
*
|
|
5860
|
+
* @example
|
|
5861
|
+
* ```typescript
|
|
5862
|
+
* const plugin = new Changelog(context, {
|
|
5863
|
+
* increment: 'minor',
|
|
5864
|
+
* changesetRoot: 'custom/changeset',
|
|
5865
|
+
* tagTemplate: 'v${version}'
|
|
5866
|
+
* });
|
|
5867
|
+
* ```
|
|
5868
|
+
*/
|
|
3975
5869
|
constructor(context, props) {
|
|
3976
5870
|
super(context, "changelog", {
|
|
3977
5871
|
increment: "patch",
|
|
@@ -3982,15 +5876,78 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
3982
5876
|
...props
|
|
3983
5877
|
});
|
|
3984
5878
|
}
|
|
5879
|
+
/**
|
|
5880
|
+
* Gets the absolute path to the changeset root directory
|
|
5881
|
+
*
|
|
5882
|
+
* Combines the project root path with the configured changeset
|
|
5883
|
+
* directory path.
|
|
5884
|
+
*
|
|
5885
|
+
* @returns Absolute path to changeset directory
|
|
5886
|
+
*
|
|
5887
|
+
* @example
|
|
5888
|
+
* ```typescript
|
|
5889
|
+
* const root = plugin.changesetRoot;
|
|
5890
|
+
* // '/path/to/project/.changeset'
|
|
5891
|
+
* ```
|
|
5892
|
+
*/
|
|
3985
5893
|
get changesetRoot() {
|
|
3986
5894
|
return join4(this.context.rootPath, this.getConfig("changesetRoot"));
|
|
3987
5895
|
}
|
|
5896
|
+
/**
|
|
5897
|
+
* Gets the path to the changeset configuration file
|
|
5898
|
+
*
|
|
5899
|
+
* Returns the absolute path to the config.json file in the
|
|
5900
|
+
* changeset directory.
|
|
5901
|
+
*
|
|
5902
|
+
* @returns Path to changeset config file
|
|
5903
|
+
*
|
|
5904
|
+
* @example
|
|
5905
|
+
* ```typescript
|
|
5906
|
+
* const configPath = plugin.changesetConfigPath;
|
|
5907
|
+
* // '/path/to/project/.changeset/config.json'
|
|
5908
|
+
* ```
|
|
5909
|
+
*/
|
|
3988
5910
|
get changesetConfigPath() {
|
|
3989
5911
|
return join4(this.changesetRoot, "config.json");
|
|
3990
5912
|
}
|
|
5913
|
+
/**
|
|
5914
|
+
* Determines if the plugin should be enabled
|
|
5915
|
+
*
|
|
5916
|
+
* Plugin is enabled unless explicitly skipped via configuration.
|
|
5917
|
+
* This allows for conditional changelog generation.
|
|
5918
|
+
*
|
|
5919
|
+
* @returns True if plugin should be enabled
|
|
5920
|
+
*
|
|
5921
|
+
* @example
|
|
5922
|
+
* ```typescript
|
|
5923
|
+
* const plugin = new Changelog(context, { skip: true });
|
|
5924
|
+
* plugin.enabled(); // false
|
|
5925
|
+
*
|
|
5926
|
+
* const plugin2 = new Changelog(context, {});
|
|
5927
|
+
* plugin2.enabled(); // true
|
|
5928
|
+
* ```
|
|
5929
|
+
*/
|
|
3991
5930
|
enabled() {
|
|
3992
5931
|
return !this.getConfig("skip");
|
|
3993
5932
|
}
|
|
5933
|
+
/**
|
|
5934
|
+
* Plugin initialization hook
|
|
5935
|
+
*
|
|
5936
|
+
* Verifies that the changeset directory exists before proceeding
|
|
5937
|
+
* with changelog generation.
|
|
5938
|
+
*
|
|
5939
|
+
* @throws Error if changeset directory does not exist
|
|
5940
|
+
*
|
|
5941
|
+
* @example
|
|
5942
|
+
* ```typescript
|
|
5943
|
+
* const plugin = new Changelog(context, {
|
|
5944
|
+
* changesetRoot: '.changeset'
|
|
5945
|
+
* });
|
|
5946
|
+
*
|
|
5947
|
+
* await plugin.onBefore();
|
|
5948
|
+
* // Throws if .changeset directory doesn't exist
|
|
5949
|
+
* ```
|
|
5950
|
+
*/
|
|
3994
5951
|
async onBefore() {
|
|
3995
5952
|
if (!existsSync(this.changesetRoot)) {
|
|
3996
5953
|
throw new Error(
|
|
@@ -3999,6 +5956,33 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
3999
5956
|
}
|
|
4000
5957
|
this.logger.debug(`${this.changesetRoot} exists`);
|
|
4001
5958
|
}
|
|
5959
|
+
/**
|
|
5960
|
+
* Updates workspace information with latest versions
|
|
5961
|
+
*
|
|
5962
|
+
* Reads the latest version information from each workspace's
|
|
5963
|
+
* package.json and updates the workspace objects with new
|
|
5964
|
+
* versions and tag names.
|
|
5965
|
+
*
|
|
5966
|
+
* @param workspaces - Array of workspace configurations
|
|
5967
|
+
* @returns Updated workspace configurations
|
|
5968
|
+
*
|
|
5969
|
+
* @example
|
|
5970
|
+
* ```typescript
|
|
5971
|
+
* const workspaces = [
|
|
5972
|
+
* { name: 'pkg-a', path: 'packages/a', version: '1.0.0' }
|
|
5973
|
+
* ];
|
|
5974
|
+
*
|
|
5975
|
+
* const updated = plugin.mergeWorkspaces(workspaces);
|
|
5976
|
+
* // [
|
|
5977
|
+
* // {
|
|
5978
|
+
* // name: 'pkg-a',
|
|
5979
|
+
* // path: 'packages/a',
|
|
5980
|
+
* // version: '1.1.0', // Updated version
|
|
5981
|
+
* // tagName: 'pkg-a@1.1.0'
|
|
5982
|
+
* // }
|
|
5983
|
+
* // ]
|
|
5984
|
+
* ```
|
|
5985
|
+
*/
|
|
4002
5986
|
mergeWorkspaces(workspaces) {
|
|
4003
5987
|
return workspaces.map((workspace) => {
|
|
4004
5988
|
const newPackgeJson = WorkspaceCreator.toWorkspace(
|
|
@@ -4015,6 +5999,25 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4015
5999
|
return newWorkspace;
|
|
4016
6000
|
});
|
|
4017
6001
|
}
|
|
6002
|
+
/**
|
|
6003
|
+
* Main plugin execution hook
|
|
6004
|
+
*
|
|
6005
|
+
* Generates changelogs for all workspaces in parallel and updates
|
|
6006
|
+
* the context with the results.
|
|
6007
|
+
*
|
|
6008
|
+
* Process:
|
|
6009
|
+
* 1. Generate changelogs for each workspace
|
|
6010
|
+
* 2. Update context with new workspace information
|
|
6011
|
+
*
|
|
6012
|
+
* @param _context - Execution context
|
|
6013
|
+
*
|
|
6014
|
+
* @example
|
|
6015
|
+
* ```typescript
|
|
6016
|
+
* const plugin = new Changelog(context, {});
|
|
6017
|
+
* await plugin.onExec(execContext);
|
|
6018
|
+
* // Generates changelogs for all workspaces
|
|
6019
|
+
* ```
|
|
6020
|
+
*/
|
|
4018
6021
|
async onExec(_context) {
|
|
4019
6022
|
const workspaces = await this.step({
|
|
4020
6023
|
label: "Generate Changelogs",
|
|
@@ -4026,6 +6029,28 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4026
6029
|
});
|
|
4027
6030
|
this.context.setWorkspaces(workspaces);
|
|
4028
6031
|
}
|
|
6032
|
+
/**
|
|
6033
|
+
* Success hook after plugin execution
|
|
6034
|
+
*
|
|
6035
|
+
* Handles post-changelog generation tasks:
|
|
6036
|
+
* 1. Creates changeset files (if not skipped)
|
|
6037
|
+
* 2. Updates package versions
|
|
6038
|
+
* 3. Restores unchanged packages (if configured)
|
|
6039
|
+
* 4. Updates workspace information
|
|
6040
|
+
*
|
|
6041
|
+
* @example
|
|
6042
|
+
* ```typescript
|
|
6043
|
+
* const plugin = new Changelog(context, {
|
|
6044
|
+
* skipChangeset: false,
|
|
6045
|
+
* ignoreNonUpdatedPackages: true
|
|
6046
|
+
* });
|
|
6047
|
+
*
|
|
6048
|
+
* await plugin.onSuccess();
|
|
6049
|
+
* // - Creates changeset files
|
|
6050
|
+
* // - Updates versions
|
|
6051
|
+
* // - Restores unchanged packages
|
|
6052
|
+
* ```
|
|
6053
|
+
*/
|
|
4029
6054
|
async onSuccess() {
|
|
4030
6055
|
const workspaces = this.context.workspaces;
|
|
4031
6056
|
if (!this.getConfig("skipChangeset")) {
|
|
@@ -4049,6 +6074,25 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4049
6074
|
this.logger.debug("new workspaces", newWorkspaces);
|
|
4050
6075
|
this.context.setWorkspaces(newWorkspaces);
|
|
4051
6076
|
}
|
|
6077
|
+
/**
|
|
6078
|
+
* Restores unchanged packages to their original state
|
|
6079
|
+
*
|
|
6080
|
+
* When ignoreNonUpdatedPackages is enabled, this method:
|
|
6081
|
+
* 1. Identifies packages without changes
|
|
6082
|
+
* 2. Uses git restore to revert them to original state
|
|
6083
|
+
*
|
|
6084
|
+
* @example
|
|
6085
|
+
* ```typescript
|
|
6086
|
+
* // With changed and unchanged packages
|
|
6087
|
+
* context.options.workspaces = {
|
|
6088
|
+
* packages: ['pkg-a', 'pkg-b', 'pkg-c'],
|
|
6089
|
+
* changedPaths: ['pkg-a', 'pkg-b']
|
|
6090
|
+
* };
|
|
6091
|
+
*
|
|
6092
|
+
* await plugin.restoreIgnorePackages();
|
|
6093
|
+
* // Restores 'pkg-c' to original state
|
|
6094
|
+
* ```
|
|
6095
|
+
*/
|
|
4052
6096
|
async restoreIgnorePackages() {
|
|
4053
6097
|
const { changedPaths = [], packages = [] } = this.context.getOptions(
|
|
4054
6098
|
"workspaces"
|
|
@@ -4061,12 +6105,60 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4061
6105
|
await this.shell.exec(["git", "restore", ...noChangedPackages]);
|
|
4062
6106
|
}
|
|
4063
6107
|
}
|
|
6108
|
+
/**
|
|
6109
|
+
* Gets the tag prefix for a workspace
|
|
6110
|
+
*
|
|
6111
|
+
* Formats the configured tag prefix template with workspace
|
|
6112
|
+
* information. Used for generating Git tag names.
|
|
6113
|
+
*
|
|
6114
|
+
* @param workspace - Workspace configuration
|
|
6115
|
+
* @returns Formatted tag prefix
|
|
6116
|
+
*
|
|
6117
|
+
* @example
|
|
6118
|
+
* ```typescript
|
|
6119
|
+
* const workspace = {
|
|
6120
|
+
* name: 'pkg-a',
|
|
6121
|
+
* version: '1.0.0'
|
|
6122
|
+
* };
|
|
6123
|
+
*
|
|
6124
|
+
* const prefix = plugin.getTagPrefix(workspace);
|
|
6125
|
+
* // With default template: 'pkg-a'
|
|
6126
|
+
* // With custom template: 'v1.0.0'
|
|
6127
|
+
* ```
|
|
6128
|
+
*/
|
|
4064
6129
|
getTagPrefix(workspace) {
|
|
4065
6130
|
return Shell5.format(
|
|
4066
6131
|
this.getConfig("tagPrefix"),
|
|
4067
6132
|
workspace
|
|
4068
6133
|
);
|
|
4069
6134
|
}
|
|
6135
|
+
/**
|
|
6136
|
+
* Generates a changelog for a workspace
|
|
6137
|
+
*
|
|
6138
|
+
* Creates a changelog by:
|
|
6139
|
+
* 1. Getting the appropriate tag name
|
|
6140
|
+
* 2. Retrieving commits since last tag
|
|
6141
|
+
* 3. Formatting commits into changelog entries
|
|
6142
|
+
*
|
|
6143
|
+
* @param workspace - Workspace configuration
|
|
6144
|
+
* @returns Updated workspace with changelog
|
|
6145
|
+
*
|
|
6146
|
+
* @example
|
|
6147
|
+
* ```typescript
|
|
6148
|
+
* const workspace = {
|
|
6149
|
+
* name: 'pkg-a',
|
|
6150
|
+
* path: 'packages/a',
|
|
6151
|
+
* version: '1.0.0'
|
|
6152
|
+
* };
|
|
6153
|
+
*
|
|
6154
|
+
* const updated = await plugin.generateChangelog(workspace);
|
|
6155
|
+
* // {
|
|
6156
|
+
* // ...workspace,
|
|
6157
|
+
* // lastTag: 'pkg-a@1.0.0',
|
|
6158
|
+
* // changelog: '- feat: new feature\n- fix: bug fix'
|
|
6159
|
+
* // }
|
|
6160
|
+
* ```
|
|
6161
|
+
*/
|
|
4070
6162
|
async generateChangelog(workspace) {
|
|
4071
6163
|
let tagName = await this.getTagName(workspace);
|
|
4072
6164
|
if (workspace.lastTag) {
|
|
@@ -4092,6 +6184,32 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4092
6184
|
changelog: changelog.join("\n")
|
|
4093
6185
|
};
|
|
4094
6186
|
}
|
|
6187
|
+
/**
|
|
6188
|
+
* Generates a tag name for a workspace
|
|
6189
|
+
*
|
|
6190
|
+
* Uses the configured tag template to generate a tag name
|
|
6191
|
+
* for the workspace. Handles errors by providing a fallback.
|
|
6192
|
+
*
|
|
6193
|
+
* @param workspace - Workspace configuration
|
|
6194
|
+
* @returns Generated tag name
|
|
6195
|
+
*
|
|
6196
|
+
* @example
|
|
6197
|
+
* ```typescript
|
|
6198
|
+
* // With default template
|
|
6199
|
+
* const tag = plugin.generateTagName({
|
|
6200
|
+
* name: 'pkg-a',
|
|
6201
|
+
* version: '1.0.0'
|
|
6202
|
+
* });
|
|
6203
|
+
* // 'pkg-a@1.0.0'
|
|
6204
|
+
*
|
|
6205
|
+
* // With error (fallback)
|
|
6206
|
+
* const tag = plugin.generateTagName({
|
|
6207
|
+
* name: 'pkg-a'
|
|
6208
|
+
* });
|
|
6209
|
+
* // 'pkg-a-v0.0.0'
|
|
6210
|
+
* ```
|
|
6211
|
+
* @private
|
|
6212
|
+
*/
|
|
4095
6213
|
generateTagName(workspace) {
|
|
4096
6214
|
try {
|
|
4097
6215
|
const tagTemplate = this.getConfig("tagTemplate");
|
|
@@ -4104,6 +6222,38 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4104
6222
|
return `${workspace.name}-v0.0.0`;
|
|
4105
6223
|
}
|
|
4106
6224
|
}
|
|
6225
|
+
/**
|
|
6226
|
+
* Gets the appropriate tag name for a workspace
|
|
6227
|
+
*
|
|
6228
|
+
* Attempts to find the latest tag for the workspace, falling back
|
|
6229
|
+
* to generating a new tag if none exists. Uses git commands to
|
|
6230
|
+
* find and sort tags by creation date.
|
|
6231
|
+
*
|
|
6232
|
+
* Process:
|
|
6233
|
+
* 1. Generate current tag pattern
|
|
6234
|
+
* 2. Search for existing tags matching pattern
|
|
6235
|
+
* 3. Return latest tag or generate new one
|
|
6236
|
+
*
|
|
6237
|
+
* @param workspace - Workspace configuration
|
|
6238
|
+
* @returns Promise resolving to tag name
|
|
6239
|
+
*
|
|
6240
|
+
* @example
|
|
6241
|
+
* ```typescript
|
|
6242
|
+
* // With existing tags
|
|
6243
|
+
* const tag = await plugin.getTagName({
|
|
6244
|
+
* name: 'pkg-a',
|
|
6245
|
+
* version: '1.0.0'
|
|
6246
|
+
* });
|
|
6247
|
+
* // Returns latest matching tag: 'pkg-a@0.9.0'
|
|
6248
|
+
*
|
|
6249
|
+
* // Without existing tags
|
|
6250
|
+
* const tag = await plugin.getTagName({
|
|
6251
|
+
* name: 'pkg-b',
|
|
6252
|
+
* version: '1.0.0'
|
|
6253
|
+
* });
|
|
6254
|
+
* // Returns new tag: 'pkg-b@1.0.0'
|
|
6255
|
+
* ```
|
|
6256
|
+
*/
|
|
4107
6257
|
async getTagName(workspace) {
|
|
4108
6258
|
try {
|
|
4109
6259
|
const currentTagPattern = this.generateTagName(workspace);
|
|
@@ -4130,6 +6280,31 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4130
6280
|
return fallbackTag;
|
|
4131
6281
|
}
|
|
4132
6282
|
}
|
|
6283
|
+
/**
|
|
6284
|
+
* Determines the version increment type
|
|
6285
|
+
*
|
|
6286
|
+
* Checks for increment labels in the following order:
|
|
6287
|
+
* 1. 'increment:major' label
|
|
6288
|
+
* 2. 'increment:minor' label
|
|
6289
|
+
* 3. Configured increment value
|
|
6290
|
+
* 4. Default to 'patch'
|
|
6291
|
+
*
|
|
6292
|
+
* @returns Version increment type
|
|
6293
|
+
*
|
|
6294
|
+
* @example
|
|
6295
|
+
* ```typescript
|
|
6296
|
+
* // With labels
|
|
6297
|
+
* context.options.workspaces.changeLabels = ['increment:major'];
|
|
6298
|
+
* plugin.getIncrement(); // 'major'
|
|
6299
|
+
*
|
|
6300
|
+
* // With configuration
|
|
6301
|
+
* const plugin = new Changelog(context, { increment: 'minor' });
|
|
6302
|
+
* plugin.getIncrement(); // 'minor'
|
|
6303
|
+
*
|
|
6304
|
+
* // Default
|
|
6305
|
+
* plugin.getIncrement(); // 'patch'
|
|
6306
|
+
* ```
|
|
6307
|
+
*/
|
|
4133
6308
|
getIncrement() {
|
|
4134
6309
|
const lables = this.context.getOptions("workspaces.changeLabels");
|
|
4135
6310
|
if (Array.isArray(lables) && lables.length > 0) {
|
|
@@ -4143,6 +6318,43 @@ var Changelog = class extends ScriptPlugin3 {
|
|
|
4143
6318
|
const increment = this.getConfig("increment", "patch");
|
|
4144
6319
|
return increment;
|
|
4145
6320
|
}
|
|
6321
|
+
/**
|
|
6322
|
+
* Generates a changeset file for a workspace
|
|
6323
|
+
*
|
|
6324
|
+
* Creates a changeset file containing version increment
|
|
6325
|
+
* information and changelog content. Handles dry run mode
|
|
6326
|
+
* and existing files.
|
|
6327
|
+
*
|
|
6328
|
+
* File format:
|
|
6329
|
+
* ```yaml
|
|
6330
|
+
* ---
|
|
6331
|
+
* 'package-name': 'increment-type'
|
|
6332
|
+
* ---
|
|
6333
|
+
*
|
|
6334
|
+
* changelog content
|
|
6335
|
+
* ```
|
|
6336
|
+
*
|
|
6337
|
+
* @param workspace - Workspace configuration
|
|
6338
|
+
*
|
|
6339
|
+
* @example
|
|
6340
|
+
* ```typescript
|
|
6341
|
+
* const workspace = {
|
|
6342
|
+
* name: 'pkg-a',
|
|
6343
|
+
* version: '1.0.0',
|
|
6344
|
+
* changelog: '- feat: new feature'
|
|
6345
|
+
* };
|
|
6346
|
+
*
|
|
6347
|
+
* await plugin.generateChangesetFile(workspace);
|
|
6348
|
+
* // Creates .changeset/pkg-a-1.0.0.md
|
|
6349
|
+
* ```
|
|
6350
|
+
*
|
|
6351
|
+
* @example Dry run
|
|
6352
|
+
* ```typescript
|
|
6353
|
+
* context.dryRun = true;
|
|
6354
|
+
* await plugin.generateChangesetFile(workspace);
|
|
6355
|
+
* // Logs file content without creating file
|
|
6356
|
+
* ```
|
|
6357
|
+
*/
|
|
4146
6358
|
async generateChangesetFile(workspace) {
|
|
4147
6359
|
const { name, version } = workspace;
|
|
4148
6360
|
const changesetName = `${name}-${version}`.replace(/[\/\\]/g, "_");
|
|
@@ -4176,15 +6388,89 @@ var innerTuples = [
|
|
|
4176
6388
|
];
|
|
4177
6389
|
var defaultName = "release";
|
|
4178
6390
|
var ReleaseTask = class {
|
|
6391
|
+
/**
|
|
6392
|
+
* Creates a new ReleaseTask instance
|
|
6393
|
+
*
|
|
6394
|
+
* Initializes the release context and sets up plugin configuration.
|
|
6395
|
+
* Supports custom executors and plugin configurations.
|
|
6396
|
+
*
|
|
6397
|
+
* @param options - Release context configuration
|
|
6398
|
+
* @param executor - Custom async executor (optional)
|
|
6399
|
+
* @param defaultTuples - Plugin configuration tuples (optional)
|
|
6400
|
+
*
|
|
6401
|
+
* @example
|
|
6402
|
+
* ```typescript
|
|
6403
|
+
* // Basic initialization
|
|
6404
|
+
* const task = new ReleaseTask({
|
|
6405
|
+
* rootPath: '/path/to/project',
|
|
6406
|
+
* sourceBranch: 'main'
|
|
6407
|
+
* });
|
|
6408
|
+
*
|
|
6409
|
+
* // With custom executor and plugins
|
|
6410
|
+
* const task = new ReleaseTask(
|
|
6411
|
+
* { rootPath: '/path/to/project' },
|
|
6412
|
+
* new AsyncExecutor(),
|
|
6413
|
+
* [tuple(CustomPlugin, { option: 'value' })]
|
|
6414
|
+
* );
|
|
6415
|
+
* ```
|
|
6416
|
+
*/
|
|
4179
6417
|
constructor(options = {}, executor = new AsyncExecutor(), defaultTuples = innerTuples) {
|
|
4180
6418
|
this.executor = executor;
|
|
4181
6419
|
this.defaultTuples = defaultTuples;
|
|
4182
6420
|
this.context = new ReleaseContext(defaultName, options);
|
|
4183
6421
|
}
|
|
6422
|
+
/**
|
|
6423
|
+
* Release context instance
|
|
6424
|
+
* @protected
|
|
6425
|
+
*/
|
|
4184
6426
|
context;
|
|
6427
|
+
/**
|
|
6428
|
+
* Gets the current release context
|
|
6429
|
+
*
|
|
6430
|
+
* @returns Release context instance
|
|
6431
|
+
*
|
|
6432
|
+
* @example
|
|
6433
|
+
* ```typescript
|
|
6434
|
+
* const task = new ReleaseTask();
|
|
6435
|
+
* const context = task.getContext();
|
|
6436
|
+
*
|
|
6437
|
+
* console.log(context.releaseEnv);
|
|
6438
|
+
* console.log(context.sourceBranch);
|
|
6439
|
+
* ```
|
|
6440
|
+
*/
|
|
4185
6441
|
getContext() {
|
|
4186
6442
|
return this.context;
|
|
4187
6443
|
}
|
|
6444
|
+
/**
|
|
6445
|
+
* Loads and configures plugins for the release task
|
|
6446
|
+
*
|
|
6447
|
+
* Combines default and external plugins, initializes them with
|
|
6448
|
+
* the current context, and configures special cases like the
|
|
6449
|
+
* Workspaces plugin.
|
|
6450
|
+
*
|
|
6451
|
+
* Plugin Loading Process:
|
|
6452
|
+
* 1. Merge default and external plugins
|
|
6453
|
+
* 2. Initialize plugins with context
|
|
6454
|
+
* 3. Configure special plugins
|
|
6455
|
+
* 4. Add plugins to executor
|
|
6456
|
+
*
|
|
6457
|
+
* @param externalTuples - Additional plugin configurations
|
|
6458
|
+
* @returns Array of initialized plugins
|
|
6459
|
+
*
|
|
6460
|
+
* @example Basic usage
|
|
6461
|
+
* ```typescript
|
|
6462
|
+
* const task = new ReleaseTask();
|
|
6463
|
+
* const plugins = await task.usePlugins();
|
|
6464
|
+
* ```
|
|
6465
|
+
*
|
|
6466
|
+
* @example Custom plugins
|
|
6467
|
+
* ```typescript
|
|
6468
|
+
* const task = new ReleaseTask();
|
|
6469
|
+
* const plugins = await task.usePlugins([
|
|
6470
|
+
* tuple(CustomPlugin, { option: 'value' })
|
|
6471
|
+
* ]);
|
|
6472
|
+
* ```
|
|
6473
|
+
*/
|
|
4188
6474
|
async usePlugins(externalTuples) {
|
|
4189
6475
|
externalTuples = externalTuples || this.context.options.plugins || [];
|
|
4190
6476
|
const plugins = await loaderPluginsFromPluginTuples(this.context, [
|
|
@@ -4199,12 +6485,65 @@ var ReleaseTask = class {
|
|
|
4199
6485
|
});
|
|
4200
6486
|
return plugins;
|
|
4201
6487
|
}
|
|
6488
|
+
/**
|
|
6489
|
+
* Executes the release task
|
|
6490
|
+
*
|
|
6491
|
+
* Internal method that runs the task through the executor.
|
|
6492
|
+
* Preserves the context through the execution chain.
|
|
6493
|
+
*
|
|
6494
|
+
* @returns Execution result
|
|
6495
|
+
* @internal
|
|
6496
|
+
*/
|
|
4202
6497
|
async run() {
|
|
4203
6498
|
return this.executor.exec(
|
|
4204
6499
|
this.context,
|
|
4205
6500
|
(context) => Promise.resolve(context)
|
|
4206
6501
|
);
|
|
4207
6502
|
}
|
|
6503
|
+
/**
|
|
6504
|
+
* Main entry point for executing the release task
|
|
6505
|
+
*
|
|
6506
|
+
* Checks environment conditions, loads plugins, and executes
|
|
6507
|
+
* the release process. Supports additional plugin configuration
|
|
6508
|
+
* at execution time.
|
|
6509
|
+
*
|
|
6510
|
+
* Environment Control:
|
|
6511
|
+
* - Checks FE_RELEASE environment variable
|
|
6512
|
+
* - Skips release if FE_RELEASE=false
|
|
6513
|
+
*
|
|
6514
|
+
* @param externalTuples - Additional plugin configurations
|
|
6515
|
+
* @returns Execution result
|
|
6516
|
+
* @throws Error if release is skipped via environment variable
|
|
6517
|
+
*
|
|
6518
|
+
* @example Basic execution
|
|
6519
|
+
* ```typescript
|
|
6520
|
+
* const task = new ReleaseTask();
|
|
6521
|
+
* await task.exec();
|
|
6522
|
+
* ```
|
|
6523
|
+
*
|
|
6524
|
+
* @example With additional plugins
|
|
6525
|
+
* ```typescript
|
|
6526
|
+
* const task = new ReleaseTask();
|
|
6527
|
+
* await task.exec([
|
|
6528
|
+
* tuple(CustomPlugin, { option: 'value' })
|
|
6529
|
+
* ]);
|
|
6530
|
+
* ```
|
|
6531
|
+
*
|
|
6532
|
+
* @example Environment control
|
|
6533
|
+
* ```typescript
|
|
6534
|
+
* // Skip release
|
|
6535
|
+
* process.env.FE_RELEASE = 'false';
|
|
6536
|
+
*
|
|
6537
|
+
* const task = new ReleaseTask();
|
|
6538
|
+
* try {
|
|
6539
|
+
* await task.exec();
|
|
6540
|
+
* } catch (e) {
|
|
6541
|
+
* if (e.message === 'Skip Release') {
|
|
6542
|
+
* console.log('Release skipped via environment variable');
|
|
6543
|
+
* }
|
|
6544
|
+
* }
|
|
6545
|
+
* ```
|
|
6546
|
+
*/
|
|
4208
6547
|
async exec(externalTuples) {
|
|
4209
6548
|
if (this.context.env.get("FE_RELEASE") === "false") {
|
|
4210
6549
|
throw new Error("Skip Release");
|