@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.cjs
CHANGED
|
@@ -2414,6 +2414,31 @@ var BATCH_PR_BODY = "\n## ${name} ${version}\n${changelog}\n";
|
|
|
2414
2414
|
// src/implments/ReleaseContext.ts
|
|
2415
2415
|
var import_scripts_context = require("@qlover/scripts-context");
|
|
2416
2416
|
var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
2417
|
+
/**
|
|
2418
|
+
* Creates a new ReleaseContext instance
|
|
2419
|
+
*
|
|
2420
|
+
* Initializes the context with provided options and sets up
|
|
2421
|
+
* default values for required configuration:
|
|
2422
|
+
* - rootPath: Defaults to current working directory
|
|
2423
|
+
* - sourceBranch: Uses environment variables or default
|
|
2424
|
+
* - releaseEnv: Uses environment variables or 'development'
|
|
2425
|
+
*
|
|
2426
|
+
* Environment Variable Priority:
|
|
2427
|
+
* - sourceBranch: FE_RELEASE_BRANCH > FE_RELEASE_SOURCE_BRANCH > DEFAULT_SOURCE_BRANCH
|
|
2428
|
+
* - releaseEnv: FE_RELEASE_ENV > NODE_ENV > 'development'
|
|
2429
|
+
*
|
|
2430
|
+
* @param name - Unique identifier for this release context
|
|
2431
|
+
* @param options - Configuration options
|
|
2432
|
+
*
|
|
2433
|
+
* @example
|
|
2434
|
+
* ```typescript
|
|
2435
|
+
* const context = new ReleaseContext('web-app', {
|
|
2436
|
+
* rootPath: '/projects/web-app',
|
|
2437
|
+
* sourceBranch: 'main',
|
|
2438
|
+
* releaseEnv: 'production'
|
|
2439
|
+
* });
|
|
2440
|
+
* ```
|
|
2441
|
+
*/
|
|
2417
2442
|
constructor(name, options) {
|
|
2418
2443
|
super(name, options);
|
|
2419
2444
|
if (!this.options.rootPath) {
|
|
@@ -2430,27 +2455,124 @@ var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
|
2430
2455
|
});
|
|
2431
2456
|
}
|
|
2432
2457
|
}
|
|
2458
|
+
/**
|
|
2459
|
+
* Gets the root path of the project
|
|
2460
|
+
*
|
|
2461
|
+
* @returns Absolute path to project root
|
|
2462
|
+
*
|
|
2463
|
+
* @example
|
|
2464
|
+
* ```typescript
|
|
2465
|
+
* const root = context.rootPath;
|
|
2466
|
+
* // '/path/to/project'
|
|
2467
|
+
* ```
|
|
2468
|
+
*/
|
|
2433
2469
|
get rootPath() {
|
|
2434
2470
|
return this.getOptions("rootPath");
|
|
2435
2471
|
}
|
|
2472
|
+
/**
|
|
2473
|
+
* Gets the source branch for the release
|
|
2474
|
+
*
|
|
2475
|
+
* @returns Branch name to use as source
|
|
2476
|
+
*
|
|
2477
|
+
* @example
|
|
2478
|
+
* ```typescript
|
|
2479
|
+
* const branch = context.sourceBranch;
|
|
2480
|
+
* // 'main' or custom branch name
|
|
2481
|
+
* ```
|
|
2482
|
+
*/
|
|
2436
2483
|
get sourceBranch() {
|
|
2437
2484
|
return this.getOptions("sourceBranch");
|
|
2438
2485
|
}
|
|
2486
|
+
/**
|
|
2487
|
+
* Gets the release environment
|
|
2488
|
+
*
|
|
2489
|
+
* @returns Environment name (e.g., 'development', 'production')
|
|
2490
|
+
*
|
|
2491
|
+
* @example
|
|
2492
|
+
* ```typescript
|
|
2493
|
+
* const env = context.releaseEnv;
|
|
2494
|
+
* // 'development' or custom environment
|
|
2495
|
+
* ```
|
|
2496
|
+
*/
|
|
2439
2497
|
get releaseEnv() {
|
|
2440
2498
|
return this.getOptions("releaseEnv");
|
|
2441
2499
|
}
|
|
2500
|
+
/**
|
|
2501
|
+
* Gets all configured workspaces
|
|
2502
|
+
*
|
|
2503
|
+
* @returns Array of workspace configurations or undefined
|
|
2504
|
+
*
|
|
2505
|
+
* @example
|
|
2506
|
+
* ```typescript
|
|
2507
|
+
* const allWorkspaces = context.workspaces;
|
|
2508
|
+
* // [{ name: 'pkg-a', version: '1.0.0', ... }]
|
|
2509
|
+
* ```
|
|
2510
|
+
*/
|
|
2442
2511
|
get workspaces() {
|
|
2443
2512
|
return this.getOptions("workspaces.workspaces");
|
|
2444
2513
|
}
|
|
2514
|
+
/**
|
|
2515
|
+
* Gets the current active workspace
|
|
2516
|
+
*
|
|
2517
|
+
* @returns Current workspace configuration or undefined
|
|
2518
|
+
*
|
|
2519
|
+
* @example
|
|
2520
|
+
* ```typescript
|
|
2521
|
+
* const current = context.workspace;
|
|
2522
|
+
* // { name: 'pkg-a', version: '1.0.0', ... }
|
|
2523
|
+
* ```
|
|
2524
|
+
*/
|
|
2445
2525
|
get workspace() {
|
|
2446
2526
|
return this.getOptions("workspaces.workspace");
|
|
2447
2527
|
}
|
|
2528
|
+
/**
|
|
2529
|
+
* Sets the workspace configurations
|
|
2530
|
+
*
|
|
2531
|
+
* Updates the workspace list while preserving other workspace settings
|
|
2532
|
+
*
|
|
2533
|
+
* @param workspaces - Array of workspace configurations
|
|
2534
|
+
*
|
|
2535
|
+
* @example
|
|
2536
|
+
* ```typescript
|
|
2537
|
+
* context.setWorkspaces([{
|
|
2538
|
+
* name: 'pkg-a',
|
|
2539
|
+
* version: '1.0.0',
|
|
2540
|
+
* path: 'packages/a'
|
|
2541
|
+
* }]);
|
|
2542
|
+
* ```
|
|
2543
|
+
*/
|
|
2448
2544
|
setWorkspaces(workspaces) {
|
|
2449
2545
|
this.options.workspaces = {
|
|
2450
2546
|
...this.options.workspaces,
|
|
2451
2547
|
workspaces
|
|
2452
2548
|
};
|
|
2453
2549
|
}
|
|
2550
|
+
/**
|
|
2551
|
+
* Gets package.json data for the current workspace
|
|
2552
|
+
*
|
|
2553
|
+
* Provides type-safe access to package.json fields with optional
|
|
2554
|
+
* path and default value support.
|
|
2555
|
+
*
|
|
2556
|
+
* @param key - Optional dot-notation path to specific field
|
|
2557
|
+
* @param defaultValue - Default value if field not found
|
|
2558
|
+
* @returns Package data of type T
|
|
2559
|
+
* @throws Error if package.json not found
|
|
2560
|
+
*
|
|
2561
|
+
* @example Basic usage
|
|
2562
|
+
* ```typescript
|
|
2563
|
+
* // Get entire package.json
|
|
2564
|
+
* const pkg = context.getPkg();
|
|
2565
|
+
*
|
|
2566
|
+
* // Get specific field
|
|
2567
|
+
* const version = context.getPkg<string>('version');
|
|
2568
|
+
*
|
|
2569
|
+
* // Get nested field with default
|
|
2570
|
+
* const script = context.getPkg<string>(
|
|
2571
|
+
* 'scripts.build',
|
|
2572
|
+
* 'echo "No build script"'
|
|
2573
|
+
* );
|
|
2574
|
+
* ```
|
|
2575
|
+
*/
|
|
2454
2576
|
getPkg(key, defaultValue) {
|
|
2455
2577
|
const packageJson = this.workspace?.packageJson;
|
|
2456
2578
|
if (!packageJson) {
|
|
@@ -2461,6 +2583,28 @@ var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
|
2461
2583
|
}
|
|
2462
2584
|
return (0, import_get.default)(packageJson, key, defaultValue);
|
|
2463
2585
|
}
|
|
2586
|
+
/**
|
|
2587
|
+
* Generates template context for string interpolation
|
|
2588
|
+
*
|
|
2589
|
+
* Combines context options, workspace data, and specific paths
|
|
2590
|
+
* for use in template processing. Includes deprecated fields
|
|
2591
|
+
* for backward compatibility.
|
|
2592
|
+
*
|
|
2593
|
+
* @returns Combined template context
|
|
2594
|
+
*
|
|
2595
|
+
* @example
|
|
2596
|
+
* ```typescript
|
|
2597
|
+
* const context = releaseContext.getTemplateContext();
|
|
2598
|
+
* // {
|
|
2599
|
+
* // publishPath: 'packages/my-pkg',
|
|
2600
|
+
* // env: 'production', // deprecated
|
|
2601
|
+
* // branch: 'main', // deprecated
|
|
2602
|
+
* // releaseEnv: 'production', // use this instead
|
|
2603
|
+
* // sourceBranch: 'main', // use this instead
|
|
2604
|
+
* // ...other options
|
|
2605
|
+
* // }
|
|
2606
|
+
* ```
|
|
2607
|
+
*/
|
|
2464
2608
|
getTemplateContext() {
|
|
2465
2609
|
return {
|
|
2466
2610
|
...this.getOptions(),
|
|
@@ -2471,6 +2615,28 @@ var ReleaseContext = class extends import_scripts_context.ScriptContext {
|
|
|
2471
2615
|
branch: this.sourceBranch
|
|
2472
2616
|
};
|
|
2473
2617
|
}
|
|
2618
|
+
/**
|
|
2619
|
+
* Executes changeset CLI commands
|
|
2620
|
+
*
|
|
2621
|
+
* Automatically detects and uses appropriate package manager
|
|
2622
|
+
* (pnpm or npx) to run changeset commands.
|
|
2623
|
+
*
|
|
2624
|
+
* @param name - Changeset command name
|
|
2625
|
+
* @param args - Optional command arguments
|
|
2626
|
+
* @returns Command output
|
|
2627
|
+
*
|
|
2628
|
+
* @example Version bump
|
|
2629
|
+
* ```typescript
|
|
2630
|
+
* // Bump version with snapshot
|
|
2631
|
+
* await context.runChangesetsCli('version', ['--snapshot', 'alpha']);
|
|
2632
|
+
*
|
|
2633
|
+
* // Create new changeset
|
|
2634
|
+
* await context.runChangesetsCli('add');
|
|
2635
|
+
*
|
|
2636
|
+
* // Status check
|
|
2637
|
+
* await context.runChangesetsCli('status');
|
|
2638
|
+
* ```
|
|
2639
|
+
*/
|
|
2474
2640
|
async runChangesetsCli(name, args) {
|
|
2475
2641
|
let packageManager = "pnpm";
|
|
2476
2642
|
try {
|
|
@@ -2505,6 +2671,28 @@ var DEFAULT_RELEASE_CONFIG = {
|
|
|
2505
2671
|
batchTagName: "batch-${length}-packages-${timestamp}"
|
|
2506
2672
|
};
|
|
2507
2673
|
var ReleaseParams = class {
|
|
2674
|
+
/**
|
|
2675
|
+
* Creates a new ReleaseParams instance
|
|
2676
|
+
*
|
|
2677
|
+
* Initializes with logger for debug output and optional configuration
|
|
2678
|
+
* overrides. Uses default configuration values for any unspecified options.
|
|
2679
|
+
*
|
|
2680
|
+
* @param logger - Logger instance for debug output
|
|
2681
|
+
* @param config - Optional configuration overrides
|
|
2682
|
+
*
|
|
2683
|
+
* @example
|
|
2684
|
+
* ```typescript
|
|
2685
|
+
* // Basic initialization
|
|
2686
|
+
* const params = new ReleaseParams(logger);
|
|
2687
|
+
*
|
|
2688
|
+
* // With custom configuration
|
|
2689
|
+
* const params = new ReleaseParams(logger, {
|
|
2690
|
+
* maxWorkspace: 5,
|
|
2691
|
+
* multiWorkspaceSeparator: '-',
|
|
2692
|
+
* workspaceVersionSeparator: '#'
|
|
2693
|
+
* });
|
|
2694
|
+
* ```
|
|
2695
|
+
*/
|
|
2508
2696
|
constructor(logger, config = {}) {
|
|
2509
2697
|
this.logger = logger;
|
|
2510
2698
|
this.config = {
|
|
@@ -2512,7 +2700,49 @@ var ReleaseParams = class {
|
|
|
2512
2700
|
...config
|
|
2513
2701
|
};
|
|
2514
2702
|
}
|
|
2703
|
+
/**
|
|
2704
|
+
* Current configuration
|
|
2705
|
+
* @private
|
|
2706
|
+
*/
|
|
2515
2707
|
config;
|
|
2708
|
+
/**
|
|
2709
|
+
* Generates a release branch name for a single package
|
|
2710
|
+
*
|
|
2711
|
+
* Uses the branch name template from shared configuration or
|
|
2712
|
+
* falls back to the default template 'release-${tagName}'.
|
|
2713
|
+
* Supports variable interpolation in the template.
|
|
2714
|
+
*
|
|
2715
|
+
* Template Variables:
|
|
2716
|
+
* - ${pkgName}: Package name
|
|
2717
|
+
* - ${releaseName}: Release name (same as pkgName)
|
|
2718
|
+
* - ${tagName}: Release tag
|
|
2719
|
+
* - All shared config properties
|
|
2720
|
+
*
|
|
2721
|
+
* @param releaseName - Name of the package being released
|
|
2722
|
+
* @param tagName - Version tag for the release
|
|
2723
|
+
* @param shared - Shared configuration with branch template
|
|
2724
|
+
* @returns Formatted branch name
|
|
2725
|
+
* @throws Error if branch name template is not a string
|
|
2726
|
+
*
|
|
2727
|
+
* @example
|
|
2728
|
+
* ```typescript
|
|
2729
|
+
* // With default template
|
|
2730
|
+
* const branch = params.getReleaseBranchName(
|
|
2731
|
+
* 'my-pkg',
|
|
2732
|
+
* 'v1.0.0',
|
|
2733
|
+
* {}
|
|
2734
|
+
* );
|
|
2735
|
+
* // 'release-v1.0.0'
|
|
2736
|
+
*
|
|
2737
|
+
* // With custom template
|
|
2738
|
+
* const branch = params.getReleaseBranchName(
|
|
2739
|
+
* 'my-pkg',
|
|
2740
|
+
* 'v1.0.0',
|
|
2741
|
+
* { branchName: '${pkgName}-release-${tagName}' }
|
|
2742
|
+
* );
|
|
2743
|
+
* // 'my-pkg-release-v1.0.0'
|
|
2744
|
+
* ```
|
|
2745
|
+
*/
|
|
2516
2746
|
getReleaseBranchName(releaseName, tagName, shared) {
|
|
2517
2747
|
const branchNameTpl = shared.branchName || "release-${tagName}";
|
|
2518
2748
|
if (typeof branchNameTpl !== "string") {
|
|
@@ -2527,6 +2757,49 @@ var ReleaseParams = class {
|
|
|
2527
2757
|
...shared
|
|
2528
2758
|
});
|
|
2529
2759
|
}
|
|
2760
|
+
/**
|
|
2761
|
+
* Generates a release branch name for multiple packages
|
|
2762
|
+
*
|
|
2763
|
+
* Uses the batch branch name template from configuration.
|
|
2764
|
+
* Supports variable interpolation with additional batch-specific
|
|
2765
|
+
* variables.
|
|
2766
|
+
*
|
|
2767
|
+
* Template Variables:
|
|
2768
|
+
* - ${pkgName}: Package name
|
|
2769
|
+
* - ${releaseName}: Combined release name
|
|
2770
|
+
* - ${tagName}: Combined tag name
|
|
2771
|
+
* - ${length}: Number of packages
|
|
2772
|
+
* - ${timestamp}: Current timestamp
|
|
2773
|
+
* - All shared config properties
|
|
2774
|
+
*
|
|
2775
|
+
* @param releaseName - Combined name of packages
|
|
2776
|
+
* @param tagName - Combined version tag
|
|
2777
|
+
* @param shared - Shared configuration
|
|
2778
|
+
* @param length - Number of packages in batch
|
|
2779
|
+
* @returns Formatted batch branch name
|
|
2780
|
+
* @throws Error if branch name template is not a string
|
|
2781
|
+
*
|
|
2782
|
+
* @example
|
|
2783
|
+
* ```typescript
|
|
2784
|
+
* // With default template
|
|
2785
|
+
* const branch = params.getBatchReleaseBranchName(
|
|
2786
|
+
* 'pkg-a@1.0.0_pkg-b@2.0.0',
|
|
2787
|
+
* 'batch-2-packages-1234567890',
|
|
2788
|
+
* {},
|
|
2789
|
+
* 2
|
|
2790
|
+
* );
|
|
2791
|
+
* // 'batch-pkg-a@1.0.0_pkg-b@2.0.0-2-packages-1234567890'
|
|
2792
|
+
*
|
|
2793
|
+
* // With custom template
|
|
2794
|
+
* const branch = params.getBatchReleaseBranchName(
|
|
2795
|
+
* 'pkg-a@1.0.0_pkg-b@2.0.0',
|
|
2796
|
+
* 'v1.0.0',
|
|
2797
|
+
* {},
|
|
2798
|
+
* 2,
|
|
2799
|
+
* );
|
|
2800
|
+
* // Custom formatted branch name
|
|
2801
|
+
* ```
|
|
2802
|
+
*/
|
|
2530
2803
|
getBatchReleaseBranchName(releaseName, tagName, shared, length) {
|
|
2531
2804
|
const branchNameTpl = this.config.batchBranchName;
|
|
2532
2805
|
if (typeof branchNameTpl !== "string") {
|
|
@@ -2543,6 +2816,45 @@ var ReleaseParams = class {
|
|
|
2543
2816
|
timestamp: Date.now()
|
|
2544
2817
|
});
|
|
2545
2818
|
}
|
|
2819
|
+
/**
|
|
2820
|
+
* Generates a release name from workspace configurations
|
|
2821
|
+
*
|
|
2822
|
+
* For single packages, returns the package name.
|
|
2823
|
+
* For multiple packages, combines names and versions up to
|
|
2824
|
+
* the configured maximum number of workspaces.
|
|
2825
|
+
*
|
|
2826
|
+
* Format:
|
|
2827
|
+
* - Single: packageName
|
|
2828
|
+
* - Multiple: pkg1@1.0.0_pkg2@2.0.0_pkg3@3.0.0
|
|
2829
|
+
*
|
|
2830
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
2831
|
+
* @returns Formatted release name
|
|
2832
|
+
*
|
|
2833
|
+
* @example
|
|
2834
|
+
* ```typescript
|
|
2835
|
+
* // Single package
|
|
2836
|
+
* const name = params.getReleaseName([
|
|
2837
|
+
* { name: 'pkg-a', version: '1.0.0' }
|
|
2838
|
+
* ]);
|
|
2839
|
+
* // 'pkg-a'
|
|
2840
|
+
*
|
|
2841
|
+
* // Multiple packages
|
|
2842
|
+
* const name = params.getReleaseName([
|
|
2843
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2844
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
2845
|
+
* ]);
|
|
2846
|
+
* // 'pkg-a@1.0.0_pkg-b@2.0.0'
|
|
2847
|
+
*
|
|
2848
|
+
* // With max limit
|
|
2849
|
+
* const name = params.getReleaseName([
|
|
2850
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2851
|
+
* { name: 'pkg-b', version: '2.0.0' },
|
|
2852
|
+
* { name: 'pkg-c', version: '3.0.0' },
|
|
2853
|
+
* { name: 'pkg-d', version: '4.0.0' }
|
|
2854
|
+
* ]);
|
|
2855
|
+
* // Only first 3: 'pkg-a@1.0.0_pkg-b@2.0.0_pkg-c@3.0.0'
|
|
2856
|
+
* ```
|
|
2857
|
+
*/
|
|
2546
2858
|
getReleaseName(composeWorkspaces) {
|
|
2547
2859
|
if (composeWorkspaces.length === 1) {
|
|
2548
2860
|
return composeWorkspaces[0].name;
|
|
@@ -2552,6 +2864,36 @@ var ReleaseParams = class {
|
|
|
2552
2864
|
({ name, version }) => `${name}${workspaceVersionSeparator}${version}`
|
|
2553
2865
|
).join(multiWorkspaceSeparator);
|
|
2554
2866
|
}
|
|
2867
|
+
/**
|
|
2868
|
+
* Generates a tag name for the release
|
|
2869
|
+
*
|
|
2870
|
+
* For single packages, uses the package version.
|
|
2871
|
+
* For multiple packages, generates a batch tag name using
|
|
2872
|
+
* the configured template.
|
|
2873
|
+
*
|
|
2874
|
+
* Format:
|
|
2875
|
+
* - Single: version
|
|
2876
|
+
* - Multiple: batch-${length}-packages-${timestamp}
|
|
2877
|
+
*
|
|
2878
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
2879
|
+
* @returns Formatted tag name
|
|
2880
|
+
*
|
|
2881
|
+
* @example
|
|
2882
|
+
* ```typescript
|
|
2883
|
+
* // Single package
|
|
2884
|
+
* const tag = params.getReleaseTagName([
|
|
2885
|
+
* { name: 'pkg-a', version: '1.0.0' }
|
|
2886
|
+
* ]);
|
|
2887
|
+
* // '1.0.0'
|
|
2888
|
+
*
|
|
2889
|
+
* // Multiple packages
|
|
2890
|
+
* const tag = params.getReleaseTagName([
|
|
2891
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2892
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
2893
|
+
* ]);
|
|
2894
|
+
* // 'batch-2-packages-1234567890'
|
|
2895
|
+
* ```
|
|
2896
|
+
*/
|
|
2555
2897
|
getReleaseTagName(composeWorkspaces) {
|
|
2556
2898
|
if (composeWorkspaces.length === 1) {
|
|
2557
2899
|
return composeWorkspaces[0].version;
|
|
@@ -2562,6 +2904,44 @@ var ReleaseParams = class {
|
|
|
2562
2904
|
timestamp: Date.now()
|
|
2563
2905
|
});
|
|
2564
2906
|
}
|
|
2907
|
+
/**
|
|
2908
|
+
* Generates branch and tag parameters for the release
|
|
2909
|
+
*
|
|
2910
|
+
* Combines the generation of branch name and tag name into
|
|
2911
|
+
* a single operation. Handles both single and multi-package
|
|
2912
|
+
* releases appropriately.
|
|
2913
|
+
*
|
|
2914
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
2915
|
+
* @param shared - Shared configuration
|
|
2916
|
+
* @returns Object containing tag name and branch name
|
|
2917
|
+
*
|
|
2918
|
+
* @example Single package
|
|
2919
|
+
* ```typescript
|
|
2920
|
+
* const params = releaseParams.getReleaseBranchParams(
|
|
2921
|
+
* [{ name: 'pkg-a', version: '1.0.0' }],
|
|
2922
|
+
* { branchName: 'release-${tagName}' }
|
|
2923
|
+
* );
|
|
2924
|
+
* // {
|
|
2925
|
+
* // tagName: '1.0.0',
|
|
2926
|
+
* // releaseBranch: 'release-1.0.0'
|
|
2927
|
+
* // }
|
|
2928
|
+
* ```
|
|
2929
|
+
*
|
|
2930
|
+
* @example Multiple packages
|
|
2931
|
+
* ```typescript
|
|
2932
|
+
* const params = releaseParams.getReleaseBranchParams(
|
|
2933
|
+
* [
|
|
2934
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
2935
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
2936
|
+
* ],
|
|
2937
|
+
* {}
|
|
2938
|
+
* );
|
|
2939
|
+
* // {
|
|
2940
|
+
* // tagName: 'batch-2-packages-1234567890',
|
|
2941
|
+
* // releaseBranch: 'batch-pkg-a@1.0.0_pkg-b@2.0.0-2-packages-1234567890'
|
|
2942
|
+
* // }
|
|
2943
|
+
* ```
|
|
2944
|
+
*/
|
|
2565
2945
|
getReleaseBranchParams(composeWorkspaces, shared) {
|
|
2566
2946
|
const releaseTagName = this.getReleaseTagName(composeWorkspaces);
|
|
2567
2947
|
const releaseName = this.getReleaseName(composeWorkspaces);
|
|
@@ -2576,6 +2956,50 @@ var ReleaseParams = class {
|
|
|
2576
2956
|
releaseBranch: releaseBranchName
|
|
2577
2957
|
};
|
|
2578
2958
|
}
|
|
2959
|
+
/**
|
|
2960
|
+
* Generates a title for the release pull request
|
|
2961
|
+
*
|
|
2962
|
+
* Uses the configured PR title template or falls back to the default.
|
|
2963
|
+
* Supports variable interpolation with release parameters and context.
|
|
2964
|
+
*
|
|
2965
|
+
* Template Variables:
|
|
2966
|
+
* - ${tagName}: Release tag name
|
|
2967
|
+
* - ${pkgName}: Package/branch name
|
|
2968
|
+
* - All template context properties
|
|
2969
|
+
*
|
|
2970
|
+
* @param releaseBranchParams - Release branch parameters
|
|
2971
|
+
* @param context - Template context for variable interpolation
|
|
2972
|
+
* @returns Formatted PR title
|
|
2973
|
+
*
|
|
2974
|
+
* @example
|
|
2975
|
+
* ```typescript
|
|
2976
|
+
* // With default template
|
|
2977
|
+
* const title = params.getPRTitle(
|
|
2978
|
+
* {
|
|
2979
|
+
* tagName: '1.0.0',
|
|
2980
|
+
* releaseBranch: 'release-1.0.0'
|
|
2981
|
+
* },
|
|
2982
|
+
* {
|
|
2983
|
+
* env: 'production',
|
|
2984
|
+
* pkgName: 'my-package'
|
|
2985
|
+
* }
|
|
2986
|
+
* );
|
|
2987
|
+
* // 'Release production my-package 1.0.0'
|
|
2988
|
+
*
|
|
2989
|
+
* // With custom template
|
|
2990
|
+
* const title = params.getPRTitle(
|
|
2991
|
+
* {
|
|
2992
|
+
* tagName: '1.0.0',
|
|
2993
|
+
* releaseBranch: 'release-1.0.0'
|
|
2994
|
+
* },
|
|
2995
|
+
* {
|
|
2996
|
+
* env: 'staging',
|
|
2997
|
+
* pkgName: 'my-package'
|
|
2998
|
+
* }
|
|
2999
|
+
* );
|
|
3000
|
+
* // Custom formatted title
|
|
3001
|
+
* ```
|
|
3002
|
+
*/
|
|
2579
3003
|
getPRTitle(releaseBranchParams, context) {
|
|
2580
3004
|
const prTitleTpl = this.config.PRTitle || DEFAULT_PR_TITLE;
|
|
2581
3005
|
return import_scripts_context2.Shell.format(prTitleTpl, {
|
|
@@ -2585,10 +3009,67 @@ var ReleaseParams = class {
|
|
|
2585
3009
|
});
|
|
2586
3010
|
}
|
|
2587
3011
|
/**
|
|
2588
|
-
*
|
|
3012
|
+
* Generates the body content for the release pull request
|
|
3013
|
+
*
|
|
3014
|
+
* Handles both single and multi-package releases, combining
|
|
3015
|
+
* changelogs appropriately. For batch releases, formats each
|
|
3016
|
+
* package's changelog according to the batch template.
|
|
3017
|
+
*
|
|
3018
|
+
* Template Variables:
|
|
3019
|
+
* - ${tagName}: Release tag or combined workspace versions
|
|
3020
|
+
* - ${changelog}: Single changelog or combined batch changelogs
|
|
3021
|
+
* - All template context properties
|
|
3022
|
+
*
|
|
3023
|
+
* @param composeWorkspaces - Array of workspace configurations
|
|
3024
|
+
* @param releaseBranchParams - Release branch parameters
|
|
3025
|
+
* @param context - Template context for variable interpolation
|
|
3026
|
+
* @returns Formatted PR body content
|
|
2589
3027
|
*
|
|
2590
|
-
* @
|
|
2591
|
-
*
|
|
3028
|
+
* @example Single package
|
|
3029
|
+
* ```typescript
|
|
3030
|
+
* const body = params.getPRBody(
|
|
3031
|
+
* [{
|
|
3032
|
+
* name: 'pkg-a',
|
|
3033
|
+
* version: '1.0.0',
|
|
3034
|
+
* changelog: '- Feature: New functionality\n- Fix: Bug fix'
|
|
3035
|
+
* }],
|
|
3036
|
+
* {
|
|
3037
|
+
* tagName: '1.0.0',
|
|
3038
|
+
* releaseBranch: 'release-1.0.0'
|
|
3039
|
+
* },
|
|
3040
|
+
* context
|
|
3041
|
+
* );
|
|
3042
|
+
* // Custom formatted body with single changelog
|
|
3043
|
+
* ```
|
|
3044
|
+
*
|
|
3045
|
+
* @example Multiple packages
|
|
3046
|
+
* ```typescript
|
|
3047
|
+
* const body = params.getPRBody(
|
|
3048
|
+
* [
|
|
3049
|
+
* {
|
|
3050
|
+
* name: 'pkg-a',
|
|
3051
|
+
* version: '1.0.0',
|
|
3052
|
+
* changelog: '- Feature: Package A changes'
|
|
3053
|
+
* },
|
|
3054
|
+
* {
|
|
3055
|
+
* name: 'pkg-b',
|
|
3056
|
+
* version: '2.0.0',
|
|
3057
|
+
* changelog: '- Feature: Package B changes'
|
|
3058
|
+
* }
|
|
3059
|
+
* ],
|
|
3060
|
+
* {
|
|
3061
|
+
* tagName: 'batch-2-packages-1234567890',
|
|
3062
|
+
* releaseBranch: 'batch-release'
|
|
3063
|
+
* },
|
|
3064
|
+
* context
|
|
3065
|
+
* );
|
|
3066
|
+
* // Formatted body with combined changelogs:
|
|
3067
|
+
* // ## pkg-a 1.0.0
|
|
3068
|
+
* // - Feature: Package A changes
|
|
3069
|
+
* //
|
|
3070
|
+
* // ## pkg-b 2.0.0
|
|
3071
|
+
* // - Feature: Package B changes
|
|
3072
|
+
* ```
|
|
2592
3073
|
*/
|
|
2593
3074
|
getPRBody(composeWorkspaces, releaseBranchParams, context) {
|
|
2594
3075
|
const PRBodyTpl = this.config.PRBody;
|
|
@@ -2614,10 +3095,36 @@ var ReleaseParams = class {
|
|
|
2614
3095
|
var import_scripts_context3 = require("@qlover/scripts-context");
|
|
2615
3096
|
var import_rest = require("@octokit/rest");
|
|
2616
3097
|
var GithubManager = class {
|
|
3098
|
+
/**
|
|
3099
|
+
* Creates a new GithubManager instance
|
|
3100
|
+
*
|
|
3101
|
+
* @param context - Release context containing configuration
|
|
3102
|
+
*
|
|
3103
|
+
* @example
|
|
3104
|
+
* ```typescript
|
|
3105
|
+
* const manager = new GithubManager(context);
|
|
3106
|
+
* ```
|
|
3107
|
+
*/
|
|
2617
3108
|
constructor(context) {
|
|
2618
3109
|
this.context = context;
|
|
2619
3110
|
}
|
|
3111
|
+
/** Lazy-loaded Octokit instance */
|
|
2620
3112
|
_octokit = null;
|
|
3113
|
+
/**
|
|
3114
|
+
* Gets GitHub repository information
|
|
3115
|
+
*
|
|
3116
|
+
* Retrieves the owner and repository name from the context.
|
|
3117
|
+
* This information is required for most GitHub API operations.
|
|
3118
|
+
*
|
|
3119
|
+
* @returns Repository owner and name
|
|
3120
|
+
* @throws Error if owner or repo name is not set
|
|
3121
|
+
*
|
|
3122
|
+
* @example
|
|
3123
|
+
* ```typescript
|
|
3124
|
+
* const info = manager.getGitHubUserInfo();
|
|
3125
|
+
* // { owner: 'org-name', repo: 'repo-name' }
|
|
3126
|
+
* ```
|
|
3127
|
+
*/
|
|
2621
3128
|
getGitHubUserInfo() {
|
|
2622
3129
|
const { authorName, repoName } = this.context.getOptions();
|
|
2623
3130
|
if (!authorName || !repoName) {
|
|
@@ -2628,6 +3135,28 @@ var GithubManager = class {
|
|
|
2628
3135
|
repo: repoName
|
|
2629
3136
|
};
|
|
2630
3137
|
}
|
|
3138
|
+
/**
|
|
3139
|
+
* Gets GitHub API token
|
|
3140
|
+
*
|
|
3141
|
+
* Retrieves the GitHub API token from environment variables.
|
|
3142
|
+
* The token name can be configured via the tokenRef option.
|
|
3143
|
+
*
|
|
3144
|
+
* @returns GitHub API token
|
|
3145
|
+
* @throws Error if token is not set
|
|
3146
|
+
*
|
|
3147
|
+
* @example Default token
|
|
3148
|
+
* ```typescript
|
|
3149
|
+
* const token = manager.getToken();
|
|
3150
|
+
* // Uses GITHUB_TOKEN env var
|
|
3151
|
+
* ```
|
|
3152
|
+
*
|
|
3153
|
+
* @example Custom token
|
|
3154
|
+
* ```typescript
|
|
3155
|
+
* context.options.githubPR.tokenRef = 'CUSTOM_TOKEN';
|
|
3156
|
+
* const token = manager.getToken();
|
|
3157
|
+
* // Uses CUSTOM_TOKEN env var
|
|
3158
|
+
* ```
|
|
3159
|
+
*/
|
|
2631
3160
|
getToken() {
|
|
2632
3161
|
const { tokenRef = "GITHUB_TOKEN" } = this.context.getOptions("githubPR");
|
|
2633
3162
|
const token = this.context.env.get(tokenRef);
|
|
@@ -2638,6 +3167,24 @@ var GithubManager = class {
|
|
|
2638
3167
|
}
|
|
2639
3168
|
return token;
|
|
2640
3169
|
}
|
|
3170
|
+
/**
|
|
3171
|
+
* Gets Octokit instance
|
|
3172
|
+
*
|
|
3173
|
+
* Lazily initializes and returns an Octokit instance configured
|
|
3174
|
+
* with the GitHub token and timeout settings.
|
|
3175
|
+
*
|
|
3176
|
+
* @returns Configured Octokit instance
|
|
3177
|
+
* @throws Error if token retrieval fails
|
|
3178
|
+
*
|
|
3179
|
+
* @example
|
|
3180
|
+
* ```typescript
|
|
3181
|
+
* const octokit = manager.octokit;
|
|
3182
|
+
* await octokit.rest.issues.create({
|
|
3183
|
+
* ...manager.getGitHubUserInfo(),
|
|
3184
|
+
* title: 'Issue title'
|
|
3185
|
+
* });
|
|
3186
|
+
* ```
|
|
3187
|
+
*/
|
|
2641
3188
|
get octokit() {
|
|
2642
3189
|
if (this._octokit) {
|
|
2643
3190
|
return this._octokit;
|
|
@@ -2652,9 +3199,37 @@ var GithubManager = class {
|
|
|
2652
3199
|
this._octokit = new import_rest.Octokit(options);
|
|
2653
3200
|
return this._octokit;
|
|
2654
3201
|
}
|
|
3202
|
+
/**
|
|
3203
|
+
* Gets logger instance
|
|
3204
|
+
*
|
|
3205
|
+
* Provides access to the context's logger for consistent
|
|
3206
|
+
* logging across the manager.
|
|
3207
|
+
*
|
|
3208
|
+
* @returns Logger instance
|
|
3209
|
+
*
|
|
3210
|
+
* @example
|
|
3211
|
+
* ```typescript
|
|
3212
|
+
* manager.logger.info('Creating release...');
|
|
3213
|
+
* manager.logger.debug('API response:', response);
|
|
3214
|
+
* ```
|
|
3215
|
+
*/
|
|
2655
3216
|
get logger() {
|
|
2656
3217
|
return this.context.logger;
|
|
2657
3218
|
}
|
|
3219
|
+
/**
|
|
3220
|
+
* Gets shell interface
|
|
3221
|
+
*
|
|
3222
|
+
* Provides access to the context's shell interface for
|
|
3223
|
+
* executing Git commands and other shell operations.
|
|
3224
|
+
*
|
|
3225
|
+
* @returns Shell interface
|
|
3226
|
+
*
|
|
3227
|
+
* @example
|
|
3228
|
+
* ```typescript
|
|
3229
|
+
* await manager.shell.exec('git fetch origin');
|
|
3230
|
+
* await manager.shell.exec(['git', 'push', 'origin', 'main']);
|
|
3231
|
+
* ```
|
|
3232
|
+
*/
|
|
2658
3233
|
get shell() {
|
|
2659
3234
|
return this.context.shell;
|
|
2660
3235
|
}
|
|
@@ -2663,6 +3238,23 @@ var GithubManager = class {
|
|
|
2663
3238
|
*
|
|
2664
3239
|
* @default `squash`
|
|
2665
3240
|
*/
|
|
3241
|
+
/**
|
|
3242
|
+
* Gets auto-merge type for pull requests
|
|
3243
|
+
*
|
|
3244
|
+
* Determines how pull requests should be merged when
|
|
3245
|
+
* auto-merge is enabled. Defaults to 'squash'.
|
|
3246
|
+
*
|
|
3247
|
+
* @returns Auto-merge type ('merge', 'squash', or 'rebase')
|
|
3248
|
+
*
|
|
3249
|
+
* @example
|
|
3250
|
+
* ```typescript
|
|
3251
|
+
* const mergeType = manager.autoMergeType;
|
|
3252
|
+
* // 'squash' (default)
|
|
3253
|
+
*
|
|
3254
|
+
* context.options.autoMergeType = 'rebase';
|
|
3255
|
+
* manager.autoMergeType; // 'rebase'
|
|
3256
|
+
* ```
|
|
3257
|
+
*/
|
|
2666
3258
|
get autoMergeType() {
|
|
2667
3259
|
return this.context.getOptions().autoMergeType || DEFAULT_AUTO_MERGE_TYPE;
|
|
2668
3260
|
}
|
|
@@ -2671,6 +3263,25 @@ var GithubManager = class {
|
|
|
2671
3263
|
*
|
|
2672
3264
|
* @default `999999`
|
|
2673
3265
|
*/
|
|
3266
|
+
/**
|
|
3267
|
+
* Gets pull request number for dry runs
|
|
3268
|
+
*
|
|
3269
|
+
* Returns a placeholder PR number when running in dry-run mode.
|
|
3270
|
+
* This allows testing PR-related functionality without creating
|
|
3271
|
+
* actual pull requests.
|
|
3272
|
+
*
|
|
3273
|
+
* @returns Dry run PR number (default: '999999')
|
|
3274
|
+
*
|
|
3275
|
+
* @example
|
|
3276
|
+
* ```typescript
|
|
3277
|
+
* context.dryRun = true;
|
|
3278
|
+
* const prNumber = manager.dryRunPRNumber;
|
|
3279
|
+
* // '999999'
|
|
3280
|
+
*
|
|
3281
|
+
* context.options.githubPR.dryRunPRNumber = '123456';
|
|
3282
|
+
* manager.dryRunPRNumber; // '123456'
|
|
3283
|
+
* ```
|
|
3284
|
+
*/
|
|
2674
3285
|
get dryRunPRNumber() {
|
|
2675
3286
|
return this.context.getOptions("githubPR.dryRunPRNumber", "999999");
|
|
2676
3287
|
}
|
|
@@ -2679,6 +3290,23 @@ var GithubManager = class {
|
|
|
2679
3290
|
*
|
|
2680
3291
|
* @default `false`
|
|
2681
3292
|
*/
|
|
3293
|
+
/**
|
|
3294
|
+
* Gets auto-merge setting for release PRs
|
|
3295
|
+
*
|
|
3296
|
+
* Determines whether release pull requests should be
|
|
3297
|
+
* automatically merged after creation. Defaults to false.
|
|
3298
|
+
*
|
|
3299
|
+
* @returns True if auto-merge is enabled
|
|
3300
|
+
*
|
|
3301
|
+
* @example
|
|
3302
|
+
* ```typescript
|
|
3303
|
+
* const autoMerge = manager.autoMergeReleasePR;
|
|
3304
|
+
* // false (default)
|
|
3305
|
+
*
|
|
3306
|
+
* context.options.autoMergeReleasePR = true;
|
|
3307
|
+
* manager.autoMergeReleasePR; // true
|
|
3308
|
+
* ```
|
|
3309
|
+
*/
|
|
2682
3310
|
get autoMergeReleasePR() {
|
|
2683
3311
|
return this.context.getOptions("autoMergeReleasePR") || DEFAULT_AUTO_MERGE_RELEASE_PR;
|
|
2684
3312
|
}
|
|
@@ -2688,6 +3316,30 @@ var GithubManager = class {
|
|
|
2688
3316
|
* @param prNumber - The pull request number to merge.
|
|
2689
3317
|
* @param releaseBranch - The branch to merge into.
|
|
2690
3318
|
*/
|
|
3319
|
+
/**
|
|
3320
|
+
* Merges a pull request
|
|
3321
|
+
*
|
|
3322
|
+
* Merges the specified pull request using the configured
|
|
3323
|
+
* merge method. In dry-run mode, logs the merge action
|
|
3324
|
+
* without performing it.
|
|
3325
|
+
*
|
|
3326
|
+
* @param prNumber - Pull request number
|
|
3327
|
+
* @param releaseBranch - Branch to merge
|
|
3328
|
+
* @throws Error if merge fails
|
|
3329
|
+
*
|
|
3330
|
+
* @example Basic merge
|
|
3331
|
+
* ```typescript
|
|
3332
|
+
* await manager.mergePR('123', 'release-1.0.0');
|
|
3333
|
+
* // Merges PR #123 using configured merge method
|
|
3334
|
+
* ```
|
|
3335
|
+
*
|
|
3336
|
+
* @example Dry run
|
|
3337
|
+
* ```typescript
|
|
3338
|
+
* context.dryRun = true;
|
|
3339
|
+
* await manager.mergePR('123', 'release-1.0.0');
|
|
3340
|
+
* // Logs merge action without performing it
|
|
3341
|
+
* ```
|
|
3342
|
+
*/
|
|
2691
3343
|
async mergePR(prNumber, releaseBranch) {
|
|
2692
3344
|
if (!prNumber) {
|
|
2693
3345
|
this.logger.error("Failed to create Pull Request.", prNumber);
|
|
@@ -2707,6 +3359,24 @@ var GithubManager = class {
|
|
|
2707
3359
|
merge_method: mergeMethod
|
|
2708
3360
|
});
|
|
2709
3361
|
}
|
|
3362
|
+
/**
|
|
3363
|
+
* Gets commits from a pull request
|
|
3364
|
+
*
|
|
3365
|
+
* Retrieves all commits associated with the specified pull request.
|
|
3366
|
+
* Useful for generating changelogs or analyzing changes.
|
|
3367
|
+
*
|
|
3368
|
+
* @param prNumber - Pull request number
|
|
3369
|
+
* @returns Promise resolving to array of commit information
|
|
3370
|
+
* @throws Error if request fails
|
|
3371
|
+
*
|
|
3372
|
+
* @example
|
|
3373
|
+
* ```typescript
|
|
3374
|
+
* const commits = await manager.getPullRequestCommits(123);
|
|
3375
|
+
* commits.forEach(commit => {
|
|
3376
|
+
* console.log(commit.sha, commit.commit.message);
|
|
3377
|
+
* });
|
|
3378
|
+
* ```
|
|
3379
|
+
*/
|
|
2710
3380
|
async getPullRequestCommits(prNumber) {
|
|
2711
3381
|
const pr = await this.octokit.rest.pulls.listCommits({
|
|
2712
3382
|
...this.getGitHubUserInfo(),
|
|
@@ -2714,6 +3384,23 @@ var GithubManager = class {
|
|
|
2714
3384
|
});
|
|
2715
3385
|
return pr.data;
|
|
2716
3386
|
}
|
|
3387
|
+
/**
|
|
3388
|
+
* Gets detailed information about a commit
|
|
3389
|
+
*
|
|
3390
|
+
* Retrieves detailed information about a specific commit,
|
|
3391
|
+
* including files changed, author details, and commit message.
|
|
3392
|
+
*
|
|
3393
|
+
* @param commitSha - Commit SHA
|
|
3394
|
+
* @returns Promise resolving to commit information
|
|
3395
|
+
* @throws Error if request fails
|
|
3396
|
+
*
|
|
3397
|
+
* @example
|
|
3398
|
+
* ```typescript
|
|
3399
|
+
* const info = await manager.getCommitInfo('abc123');
|
|
3400
|
+
* console.log(info.commit.message);
|
|
3401
|
+
* console.log(info.files.map(f => f.filename));
|
|
3402
|
+
* ```
|
|
3403
|
+
*/
|
|
2717
3404
|
async getCommitInfo(commitSha) {
|
|
2718
3405
|
const pr = await this.octokit.rest.repos.getCommit({
|
|
2719
3406
|
...this.getGitHubUserInfo(),
|
|
@@ -2721,6 +3408,24 @@ var GithubManager = class {
|
|
|
2721
3408
|
});
|
|
2722
3409
|
return pr.data;
|
|
2723
3410
|
}
|
|
3411
|
+
/**
|
|
3412
|
+
* Gets pull request information
|
|
3413
|
+
*
|
|
3414
|
+
* Retrieves detailed information about a pull request,
|
|
3415
|
+
* including title, body, labels, and review status.
|
|
3416
|
+
*
|
|
3417
|
+
* @param prNumber - Pull request number
|
|
3418
|
+
* @returns Promise resolving to pull request information
|
|
3419
|
+
* @throws Error if request fails
|
|
3420
|
+
*
|
|
3421
|
+
* @example
|
|
3422
|
+
* ```typescript
|
|
3423
|
+
* const pr = await manager.getPullRequest(123);
|
|
3424
|
+
* console.log(pr.title);
|
|
3425
|
+
* console.log(pr.labels.map(l => l.name));
|
|
3426
|
+
* console.log(pr.mergeable_state);
|
|
3427
|
+
* ```
|
|
3428
|
+
*/
|
|
2724
3429
|
async getPullRequest(prNumber) {
|
|
2725
3430
|
const pr = await this.octokit.rest.pulls.get({
|
|
2726
3431
|
...this.getGitHubUserInfo(),
|
|
@@ -2734,6 +3439,27 @@ var GithubManager = class {
|
|
|
2734
3439
|
* @param prNumber - The pull request number to check.
|
|
2735
3440
|
* @param releaseBranch - The branch to check against.
|
|
2736
3441
|
*/
|
|
3442
|
+
/**
|
|
3443
|
+
* Checks pull request status and cleans up
|
|
3444
|
+
*
|
|
3445
|
+
* Verifies pull request status and deletes the release branch
|
|
3446
|
+
* if the PR has been merged. Used for post-merge cleanup.
|
|
3447
|
+
*
|
|
3448
|
+
* Process:
|
|
3449
|
+
* 1. Verify PR exists and status
|
|
3450
|
+
* 2. Delete release branch if PR merged
|
|
3451
|
+
* 3. Log cleanup results
|
|
3452
|
+
*
|
|
3453
|
+
* @param prNumber - Pull request number
|
|
3454
|
+
* @param releaseBranch - Branch to clean up
|
|
3455
|
+
* @throws Error if verification or cleanup fails
|
|
3456
|
+
*
|
|
3457
|
+
* @example
|
|
3458
|
+
* ```typescript
|
|
3459
|
+
* await manager.checkedPR('123', 'release-1.0.0');
|
|
3460
|
+
* // Verifies PR #123 and deletes release-1.0.0 if merged
|
|
3461
|
+
* ```
|
|
3462
|
+
*/
|
|
2737
3463
|
async checkedPR(prNumber, releaseBranch) {
|
|
2738
3464
|
try {
|
|
2739
3465
|
await this.getPullRequest(Number(prNumber));
|
|
@@ -2834,10 +3560,55 @@ var GithubManager = class {
|
|
|
2834
3560
|
throw error;
|
|
2835
3561
|
}
|
|
2836
3562
|
}
|
|
3563
|
+
/**
|
|
3564
|
+
* Truncates long PR/release body text
|
|
3565
|
+
*
|
|
3566
|
+
* GitHub has a limit on PR and release body length.
|
|
3567
|
+
* This method ensures the text stays within limits by
|
|
3568
|
+
* truncating if necessary.
|
|
3569
|
+
*
|
|
3570
|
+
* @param body - Body text to truncate
|
|
3571
|
+
* @returns Truncated text (if > 124000 chars)
|
|
3572
|
+
*
|
|
3573
|
+
* @example
|
|
3574
|
+
* ```typescript
|
|
3575
|
+
* const body = manager.truncateBody(veryLongText);
|
|
3576
|
+
* // Returns truncated text if > 124000 chars
|
|
3577
|
+
* // Adds '...' to indicate truncation
|
|
3578
|
+
* ```
|
|
3579
|
+
* @private
|
|
3580
|
+
*/
|
|
2837
3581
|
truncateBody(body) {
|
|
2838
3582
|
if (body && body.length >= 124e3) return body.substring(0, 124e3) + "...";
|
|
2839
3583
|
return body;
|
|
2840
3584
|
}
|
|
3585
|
+
/**
|
|
3586
|
+
* Builds GitHub release options
|
|
3587
|
+
*
|
|
3588
|
+
* Combines default release options with provided overrides
|
|
3589
|
+
* and context configuration. Handles formatting of release
|
|
3590
|
+
* name, body, and other settings.
|
|
3591
|
+
*
|
|
3592
|
+
* @param options - Override options for release
|
|
3593
|
+
* @returns Complete release options
|
|
3594
|
+
*
|
|
3595
|
+
* @example
|
|
3596
|
+
* ```typescript
|
|
3597
|
+
* const opts = manager.getOctokitReleaseOptions({
|
|
3598
|
+
* tag_name: 'v1.0.0',
|
|
3599
|
+
* body: 'Release notes...'
|
|
3600
|
+
* });
|
|
3601
|
+
* // Returns merged options with defaults:
|
|
3602
|
+
* // {
|
|
3603
|
+
* // name: 'Release v1.0.0',
|
|
3604
|
+
* // body: 'Release notes...',
|
|
3605
|
+
* // draft: false,
|
|
3606
|
+
* // prerelease: false,
|
|
3607
|
+
* // ...
|
|
3608
|
+
* // }
|
|
3609
|
+
* ```
|
|
3610
|
+
* @private
|
|
3611
|
+
*/
|
|
2841
3612
|
getOctokitReleaseOptions(options) {
|
|
2842
3613
|
const {
|
|
2843
3614
|
releaseName,
|
|
@@ -2863,6 +3634,37 @@ var GithubManager = class {
|
|
|
2863
3634
|
...this.getGitHubUserInfo()
|
|
2864
3635
|
};
|
|
2865
3636
|
}
|
|
3637
|
+
/**
|
|
3638
|
+
* Creates a GitHub release
|
|
3639
|
+
*
|
|
3640
|
+
* Creates a new GitHub release for a workspace with:
|
|
3641
|
+
* - Formatted release name
|
|
3642
|
+
* - Changelog as release notes
|
|
3643
|
+
* - Proper tag
|
|
3644
|
+
* - Configurable settings (draft, prerelease, etc.)
|
|
3645
|
+
*
|
|
3646
|
+
* Handles dry run mode and error cases gracefully.
|
|
3647
|
+
*
|
|
3648
|
+
* @param workspace - Workspace to create release for
|
|
3649
|
+
* @throws Error if tag name is missing or creation fails
|
|
3650
|
+
*
|
|
3651
|
+
* @example Basic release
|
|
3652
|
+
* ```typescript
|
|
3653
|
+
* await manager.createRelease({
|
|
3654
|
+
* name: 'pkg-a',
|
|
3655
|
+
* version: '1.0.0',
|
|
3656
|
+
* tagName: 'v1.0.0',
|
|
3657
|
+
* changelog: '...'
|
|
3658
|
+
* });
|
|
3659
|
+
* ```
|
|
3660
|
+
*
|
|
3661
|
+
* @example Dry run
|
|
3662
|
+
* ```typescript
|
|
3663
|
+
* context.dryRun = true;
|
|
3664
|
+
* await manager.createRelease(workspace);
|
|
3665
|
+
* // Logs release info without creating
|
|
3666
|
+
* ```
|
|
3667
|
+
*/
|
|
2866
3668
|
async createRelease(workspace) {
|
|
2867
3669
|
const meragedOptions = this.getOctokitReleaseOptions({
|
|
2868
3670
|
tag_name: workspace.tagName,
|
|
@@ -2902,6 +3704,30 @@ var GithubManager = class {
|
|
|
2902
3704
|
var import_isString = __toESM(require_isString(), 1);
|
|
2903
3705
|
var import_scripts_context4 = require("@qlover/scripts-context");
|
|
2904
3706
|
var GitBase = class extends import_scripts_context4.ScriptPlugin {
|
|
3707
|
+
/**
|
|
3708
|
+
* Plugin initialization hook
|
|
3709
|
+
*
|
|
3710
|
+
* Runs before plugin execution to set up repository context:
|
|
3711
|
+
* 1. Retrieves repository information
|
|
3712
|
+
* 2. Gets current branch
|
|
3713
|
+
* 3. Switches to current branch if needed
|
|
3714
|
+
* 4. Updates context with repository info
|
|
3715
|
+
*
|
|
3716
|
+
* @throws Error if repository information cannot be retrieved
|
|
3717
|
+
*
|
|
3718
|
+
* @example
|
|
3719
|
+
* ```typescript
|
|
3720
|
+
* class MyPlugin extends GitBase<GitBaseProps> {
|
|
3721
|
+
* async onExec() {
|
|
3722
|
+
* // onBefore has already:
|
|
3723
|
+
* // - Set up repository info
|
|
3724
|
+
* // - Switched to correct branch
|
|
3725
|
+
* // - Updated context
|
|
3726
|
+
* await this.doSomething();
|
|
3727
|
+
* }
|
|
3728
|
+
* }
|
|
3729
|
+
* ```
|
|
3730
|
+
*/
|
|
2905
3731
|
async onBefore() {
|
|
2906
3732
|
const repoInfo = await this.getUserInfo();
|
|
2907
3733
|
if (!repoInfo) {
|
|
@@ -2922,12 +3748,44 @@ var GitBase = class extends import_scripts_context4.ScriptPlugin {
|
|
|
2922
3748
|
currentBranch
|
|
2923
3749
|
});
|
|
2924
3750
|
}
|
|
3751
|
+
/**
|
|
3752
|
+
* Gets the current Git branch name
|
|
3753
|
+
*
|
|
3754
|
+
* Retrieves the name of the currently checked out Git branch.
|
|
3755
|
+
* Includes a small delay to ensure Git's internal state is updated.
|
|
3756
|
+
*
|
|
3757
|
+
* @returns Promise resolving to branch name
|
|
3758
|
+
* @throws Error if branch name cannot be retrieved
|
|
3759
|
+
*
|
|
3760
|
+
* @example
|
|
3761
|
+
* ```typescript
|
|
3762
|
+
* const branch = await plugin.getCurrentBranch();
|
|
3763
|
+
* // 'main' or 'feature/new-feature'
|
|
3764
|
+
* ```
|
|
3765
|
+
*/
|
|
2925
3766
|
async getCurrentBranch() {
|
|
2926
3767
|
await new Promise((resolve2) => setTimeout(resolve2, 100));
|
|
2927
3768
|
return this.context.shell.exec("git rev-parse --abbrev-ref HEAD", {
|
|
2928
3769
|
dryRun: false
|
|
2929
3770
|
});
|
|
2930
3771
|
}
|
|
3772
|
+
/**
|
|
3773
|
+
* Gets the Git remote URL
|
|
3774
|
+
*
|
|
3775
|
+
* Retrieves the URL of the 'origin' remote from Git configuration.
|
|
3776
|
+
* This URL is used to identify the GitHub repository.
|
|
3777
|
+
*
|
|
3778
|
+
* @returns Promise resolving to remote URL
|
|
3779
|
+
* @throws Error if remote URL cannot be retrieved
|
|
3780
|
+
*
|
|
3781
|
+
* @example
|
|
3782
|
+
* ```typescript
|
|
3783
|
+
* const url = await plugin.getRemoteUrl();
|
|
3784
|
+
* // 'https://github.com/org/repo.git'
|
|
3785
|
+
* // or
|
|
3786
|
+
* // 'git@github.com:org/repo.git'
|
|
3787
|
+
* ```
|
|
3788
|
+
*/
|
|
2931
3789
|
async getRemoteUrl() {
|
|
2932
3790
|
return (await this.context.shell.exec("git config --get remote.origin.url", {
|
|
2933
3791
|
dryRun: false
|
|
@@ -2981,9 +3839,53 @@ var GitBase = class extends import_scripts_context4.ScriptPlugin {
|
|
|
2981
3839
|
* @param value - The value to check.
|
|
2982
3840
|
* @returns True if the value is a valid string, otherwise false.
|
|
2983
3841
|
*/
|
|
3842
|
+
/**
|
|
3843
|
+
* Type guard for valid string values
|
|
3844
|
+
*
|
|
3845
|
+
* Checks if a value is a non-empty string. Used for validating
|
|
3846
|
+
* repository information and other string inputs.
|
|
3847
|
+
*
|
|
3848
|
+
* @param value - Value to check
|
|
3849
|
+
* @returns True if value is a non-empty string
|
|
3850
|
+
*
|
|
3851
|
+
* @example
|
|
3852
|
+
* ```typescript
|
|
3853
|
+
* if (plugin.isValidString(value)) {
|
|
3854
|
+
* // value is definitely a non-empty string
|
|
3855
|
+
* console.log(value.toUpperCase());
|
|
3856
|
+
* }
|
|
3857
|
+
* ```
|
|
3858
|
+
*/
|
|
2984
3859
|
isValidString(value) {
|
|
2985
3860
|
return !!value && (0, import_isString.default)(value);
|
|
2986
3861
|
}
|
|
3862
|
+
/**
|
|
3863
|
+
* Creates a Git commit
|
|
3864
|
+
*
|
|
3865
|
+
* Creates a new Git commit with the specified message and optional
|
|
3866
|
+
* additional arguments. The message is automatically JSON-stringified
|
|
3867
|
+
* to handle special characters properly.
|
|
3868
|
+
*
|
|
3869
|
+
* @param message - Commit message
|
|
3870
|
+
* @param args - Additional Git commit arguments
|
|
3871
|
+
* @returns Promise resolving to command output
|
|
3872
|
+
*
|
|
3873
|
+
* @example Basic commit
|
|
3874
|
+
* ```typescript
|
|
3875
|
+
* await plugin.commit('feat: add new feature');
|
|
3876
|
+
* ```
|
|
3877
|
+
*
|
|
3878
|
+
* @example Commit with arguments
|
|
3879
|
+
* ```typescript
|
|
3880
|
+
* await plugin.commit('fix: update deps', ['--no-verify']);
|
|
3881
|
+
* ```
|
|
3882
|
+
*
|
|
3883
|
+
* @example Commit with special characters
|
|
3884
|
+
* ```typescript
|
|
3885
|
+
* await plugin.commit('fix: handle "quotes" & symbols');
|
|
3886
|
+
* // Message is automatically escaped
|
|
3887
|
+
* ```
|
|
3888
|
+
*/
|
|
2987
3889
|
commit(message, args = []) {
|
|
2988
3890
|
return this.context.shell.exec([
|
|
2989
3891
|
"git",
|
|
@@ -3018,14 +3920,50 @@ var CHANGELOG_ALL_FIELDS = [
|
|
|
3018
3920
|
"tag"
|
|
3019
3921
|
];
|
|
3020
3922
|
var GitChangelog = class {
|
|
3923
|
+
/**
|
|
3924
|
+
* Creates a new GitChangelog instance
|
|
3925
|
+
*
|
|
3926
|
+
* @param options - Configuration options including shell and logger
|
|
3927
|
+
*
|
|
3928
|
+
* @example
|
|
3929
|
+
* ```typescript
|
|
3930
|
+
* const changelog = new GitChangelog({
|
|
3931
|
+
* shell: new Shell(),
|
|
3932
|
+
* logger: new Logger(),
|
|
3933
|
+
* directory: 'packages/my-pkg',
|
|
3934
|
+
* noMerges: true
|
|
3935
|
+
* });
|
|
3936
|
+
* ```
|
|
3937
|
+
*/
|
|
3021
3938
|
constructor(options) {
|
|
3022
3939
|
this.options = options;
|
|
3023
3940
|
}
|
|
3024
3941
|
/**
|
|
3025
|
-
*
|
|
3942
|
+
* Retrieves Git commit history with specified options
|
|
3943
|
+
*
|
|
3944
|
+
* Fetches commit information between specified tags or commits,
|
|
3945
|
+
* with support for filtering and field selection.
|
|
3946
|
+
*
|
|
3947
|
+
* @param options - Configuration options for Git log retrieval
|
|
3948
|
+
* @returns Array of commit objects with requested fields
|
|
3026
3949
|
*
|
|
3027
|
-
* @
|
|
3028
|
-
*
|
|
3950
|
+
* @example Basic usage
|
|
3951
|
+
* ```typescript
|
|
3952
|
+
* const commits = await changelog.getGitLog({
|
|
3953
|
+
* from: 'v1.0.0',
|
|
3954
|
+
* to: 'v2.0.0',
|
|
3955
|
+
* directory: 'packages/my-pkg',
|
|
3956
|
+
* noMerges: true
|
|
3957
|
+
* });
|
|
3958
|
+
* ```
|
|
3959
|
+
*
|
|
3960
|
+
* @example Custom fields
|
|
3961
|
+
* ```typescript
|
|
3962
|
+
* const commits = await changelog.getGitLog({
|
|
3963
|
+
* fields: ['hash', 'subject', 'authorName'],
|
|
3964
|
+
* directory: 'src'
|
|
3965
|
+
* });
|
|
3966
|
+
* ```
|
|
3029
3967
|
*/
|
|
3030
3968
|
async getGitLog(options = {}) {
|
|
3031
3969
|
const { directory, noMerges = true, fields } = options;
|
|
@@ -3046,6 +3984,38 @@ var GitChangelog = class {
|
|
|
3046
3984
|
this.options.logger?.debug("GitChangelog commits", commits);
|
|
3047
3985
|
return commits;
|
|
3048
3986
|
}
|
|
3987
|
+
/**
|
|
3988
|
+
* Retrieves and parses Git commits with metadata
|
|
3989
|
+
*
|
|
3990
|
+
* Gets commit history and enhances it with parsed conventional
|
|
3991
|
+
* commit information and PR metadata.
|
|
3992
|
+
*
|
|
3993
|
+
* @param options - Configuration options for Git log retrieval
|
|
3994
|
+
* @returns Array of enhanced commit objects with parsed metadata
|
|
3995
|
+
*
|
|
3996
|
+
* @example Basic usage
|
|
3997
|
+
* ```typescript
|
|
3998
|
+
* const commits = await changelog.getCommits({
|
|
3999
|
+
* from: 'v1.0.0',
|
|
4000
|
+
* to: 'v2.0.0'
|
|
4001
|
+
* });
|
|
4002
|
+
* // [
|
|
4003
|
+
* // {
|
|
4004
|
+
* // base: { hash: '...', subject: '...' },
|
|
4005
|
+
* // commitlint: { type: 'feat', scope: 'api', ... },
|
|
4006
|
+
* // commits: []
|
|
4007
|
+
* // }
|
|
4008
|
+
* // ]
|
|
4009
|
+
* ```
|
|
4010
|
+
*
|
|
4011
|
+
* @example Filtered commits
|
|
4012
|
+
* ```typescript
|
|
4013
|
+
* const commits = await changelog.getCommits({
|
|
4014
|
+
* directory: 'packages/my-pkg',
|
|
4015
|
+
* noMerges: true
|
|
4016
|
+
* });
|
|
4017
|
+
* ```
|
|
4018
|
+
*/
|
|
3049
4019
|
async getCommits(options) {
|
|
3050
4020
|
const gitCommits = await this.getGitLog(options);
|
|
3051
4021
|
return gitCommits.map((commit) => {
|
|
@@ -3058,6 +4028,28 @@ var GitChangelog = class {
|
|
|
3058
4028
|
};
|
|
3059
4029
|
});
|
|
3060
4030
|
}
|
|
4031
|
+
/**
|
|
4032
|
+
* Creates a base commit object from message and optional data
|
|
4033
|
+
*
|
|
4034
|
+
* Utility method to create a standardized commit object with
|
|
4035
|
+
* basic metadata. Used internally for commit value creation.
|
|
4036
|
+
*
|
|
4037
|
+
* @param message - Commit message
|
|
4038
|
+
* @param target - Optional additional commit data
|
|
4039
|
+
* @returns Base commit object
|
|
4040
|
+
* @protected
|
|
4041
|
+
*
|
|
4042
|
+
* @example
|
|
4043
|
+
* ```typescript
|
|
4044
|
+
* const commit = changelog.createBaseCommit(
|
|
4045
|
+
* 'feat: new feature',
|
|
4046
|
+
* {
|
|
4047
|
+
* hash: 'abc123',
|
|
4048
|
+
* authorName: 'John Doe'
|
|
4049
|
+
* }
|
|
4050
|
+
* );
|
|
4051
|
+
* ```
|
|
4052
|
+
*/
|
|
3061
4053
|
createBaseCommit(message, target) {
|
|
3062
4054
|
return {
|
|
3063
4055
|
subject: message,
|
|
@@ -3067,16 +4059,66 @@ var GitChangelog = class {
|
|
|
3067
4059
|
};
|
|
3068
4060
|
}
|
|
3069
4061
|
/**
|
|
3070
|
-
*
|
|
4062
|
+
* Indents each line of a text block
|
|
4063
|
+
*
|
|
4064
|
+
* Adds specified number of spaces to the start of each line
|
|
4065
|
+
* in a multi-line string. Used for formatting commit body text.
|
|
3071
4066
|
*
|
|
3072
4067
|
* @since 2.3.2
|
|
3073
|
-
* @param body
|
|
3074
|
-
* @param size
|
|
3075
|
-
* @returns
|
|
4068
|
+
* @param body - Text to indent
|
|
4069
|
+
* @param size - Number of spaces to add (default: 2)
|
|
4070
|
+
* @returns Indented text
|
|
4071
|
+
*
|
|
4072
|
+
* @example
|
|
4073
|
+
* ```typescript
|
|
4074
|
+
* const text = changelog.tabify(
|
|
4075
|
+
* 'Line 1\nLine 2\nLine 3',
|
|
4076
|
+
* 4
|
|
4077
|
+
* );
|
|
4078
|
+
* // ' Line 1\n Line 2\n Line 3'
|
|
4079
|
+
* ```
|
|
3076
4080
|
*/
|
|
3077
4081
|
tabify(body, size = 2) {
|
|
3078
4082
|
return body.split("\n").map((line) => " ".repeat(size) + line.trim()).join("\n");
|
|
3079
4083
|
}
|
|
4084
|
+
/**
|
|
4085
|
+
* Parses a commit message into conventional commit format
|
|
4086
|
+
*
|
|
4087
|
+
* Extracts type, scope, message, and body from a commit message
|
|
4088
|
+
* following the conventional commit specification.
|
|
4089
|
+
*
|
|
4090
|
+
* Format: type(scope): message
|
|
4091
|
+
*
|
|
4092
|
+
* @param subject - Commit subject line
|
|
4093
|
+
* @param rawBody - Full commit message body
|
|
4094
|
+
* @returns Parsed conventional commit data
|
|
4095
|
+
*
|
|
4096
|
+
* @example Basic commit
|
|
4097
|
+
* ```typescript
|
|
4098
|
+
* const commit = changelog.parseCommitlint(
|
|
4099
|
+
* 'feat(api): add new endpoint'
|
|
4100
|
+
* );
|
|
4101
|
+
* // {
|
|
4102
|
+
* // type: 'feat',
|
|
4103
|
+
* // scope: 'api',
|
|
4104
|
+
* // message: 'add new endpoint'
|
|
4105
|
+
* // }
|
|
4106
|
+
* ```
|
|
4107
|
+
*
|
|
4108
|
+
* @example With body
|
|
4109
|
+
* ```typescript
|
|
4110
|
+
* const commit = changelog.parseCommitlint(
|
|
4111
|
+
* 'fix(core): memory leak',
|
|
4112
|
+
* 'Fixed memory leak in core module\n\nBREAKING CHANGE: API changed'
|
|
4113
|
+
* );
|
|
4114
|
+
* // {
|
|
4115
|
+
* // type: 'fix',
|
|
4116
|
+
* // scope: 'core',
|
|
4117
|
+
* // message: 'memory leak',
|
|
4118
|
+
* // body: ' Fixed memory leak in core module\n\n BREAKING CHANGE: API changed'
|
|
4119
|
+
* // }
|
|
4120
|
+
* ```
|
|
4121
|
+
*/
|
|
3080
4122
|
parseCommitlint(subject, rawBody = "") {
|
|
3081
4123
|
const [title] = subject.trim().split("\n");
|
|
3082
4124
|
const bodyLines = rawBody.startsWith(title) ? rawBody.replace(title, "") : rawBody;
|
|
@@ -3095,6 +4137,51 @@ var GitChangelog = class {
|
|
|
3095
4137
|
body: bodyLines ? this.tabify(bodyLines) : void 0
|
|
3096
4138
|
};
|
|
3097
4139
|
}
|
|
4140
|
+
/**
|
|
4141
|
+
* Creates a complete commit value object from hash and message
|
|
4142
|
+
*
|
|
4143
|
+
* Combines commit hash, parsed conventional commit data, and
|
|
4144
|
+
* PR information into a single commit value object.
|
|
4145
|
+
*
|
|
4146
|
+
* @param hash - Commit hash
|
|
4147
|
+
* @param message - Full commit message
|
|
4148
|
+
* @returns Complete commit value object
|
|
4149
|
+
*
|
|
4150
|
+
* @example Basic commit
|
|
4151
|
+
* ```typescript
|
|
4152
|
+
* const commit = changelog.toCommitValue(
|
|
4153
|
+
* 'abc123',
|
|
4154
|
+
* 'feat(api): new endpoint'
|
|
4155
|
+
* );
|
|
4156
|
+
* // {
|
|
4157
|
+
* // base: {
|
|
4158
|
+
* // hash: 'abc123',
|
|
4159
|
+
* // abbrevHash: 'abc123',
|
|
4160
|
+
* // subject: 'feat(api): new endpoint'
|
|
4161
|
+
* // },
|
|
4162
|
+
* // commitlint: {
|
|
4163
|
+
* // type: 'feat',
|
|
4164
|
+
* // scope: 'api',
|
|
4165
|
+
* // message: 'new endpoint'
|
|
4166
|
+
* // },
|
|
4167
|
+
* // commits: []
|
|
4168
|
+
* // }
|
|
4169
|
+
* ```
|
|
4170
|
+
*
|
|
4171
|
+
* @example PR commit
|
|
4172
|
+
* ```typescript
|
|
4173
|
+
* const commit = changelog.toCommitValue(
|
|
4174
|
+
* 'def456',
|
|
4175
|
+
* 'fix(core): memory leak (#123)'
|
|
4176
|
+
* );
|
|
4177
|
+
* // {
|
|
4178
|
+
* // base: { hash: 'def456', ... },
|
|
4179
|
+
* // commitlint: { type: 'fix', ... },
|
|
4180
|
+
* // commits: [],
|
|
4181
|
+
* // prNumber: '123'
|
|
4182
|
+
* // }
|
|
4183
|
+
* ```
|
|
4184
|
+
*/
|
|
3098
4185
|
toCommitValue(hash, message) {
|
|
3099
4186
|
const [title] = message.trim().split("\n");
|
|
3100
4187
|
const prMatch = title.match(/\(#(\d+)\)/);
|
|
@@ -3112,6 +4199,33 @@ var GitChangelog = class {
|
|
|
3112
4199
|
prNumber: prMatch?.[1]
|
|
3113
4200
|
};
|
|
3114
4201
|
}
|
|
4202
|
+
/**
|
|
4203
|
+
* Resolves a Git tag or reference to a valid commit reference
|
|
4204
|
+
*
|
|
4205
|
+
* Attempts to resolve a tag name to a valid Git reference.
|
|
4206
|
+
* Falls back to root commit or HEAD if tag doesn't exist.
|
|
4207
|
+
*
|
|
4208
|
+
* @param tag - Tag name to resolve
|
|
4209
|
+
* @param fallback - Fallback value ('root' or 'HEAD')
|
|
4210
|
+
* @returns Resolved Git reference
|
|
4211
|
+
* @protected
|
|
4212
|
+
*
|
|
4213
|
+
* @example Basic tag resolution
|
|
4214
|
+
* ```typescript
|
|
4215
|
+
* const ref = await changelog.resolveTag('v1.0.0');
|
|
4216
|
+
* // 'v1.0.0' if tag exists
|
|
4217
|
+
* // 'HEAD' if tag doesn't exist
|
|
4218
|
+
* ```
|
|
4219
|
+
*
|
|
4220
|
+
* @example Root commit fallback
|
|
4221
|
+
* ```typescript
|
|
4222
|
+
* const ref = await changelog.resolveTag(
|
|
4223
|
+
* 'non-existent-tag',
|
|
4224
|
+
* 'root'
|
|
4225
|
+
* );
|
|
4226
|
+
* // First commit hash if tag doesn't exist
|
|
4227
|
+
* ```
|
|
4228
|
+
*/
|
|
3115
4229
|
async resolveTag(tag, fallback) {
|
|
3116
4230
|
if (tag) {
|
|
3117
4231
|
try {
|
|
@@ -3132,9 +4246,75 @@ var import_scripts_context5 = require("@qlover/scripts-context");
|
|
|
3132
4246
|
var import_groupBy = __toESM(require_groupBy(), 1);
|
|
3133
4247
|
var DEFAULT_TEMPLATE = "\n- ${scopeHeader} ${commitlint.message} ${commitLink} ${prLink}";
|
|
3134
4248
|
var GitChangelogFormatter = class {
|
|
4249
|
+
/**
|
|
4250
|
+
* Creates a new GitChangelogFormatter instance
|
|
4251
|
+
*
|
|
4252
|
+
* @param options - Configuration options including shell interface
|
|
4253
|
+
*
|
|
4254
|
+
* @example
|
|
4255
|
+
* ```typescript
|
|
4256
|
+
* const formatter = new GitChangelogFormatter({
|
|
4257
|
+
* shell: new Shell(),
|
|
4258
|
+
* repoUrl: 'https://github.com/org/repo',
|
|
4259
|
+
* types: [
|
|
4260
|
+
* { type: 'feat', section: '### Features' }
|
|
4261
|
+
* ],
|
|
4262
|
+
* formatTemplate: '- ${commitlint.message}'
|
|
4263
|
+
* });
|
|
4264
|
+
* ```
|
|
4265
|
+
*/
|
|
3135
4266
|
constructor(options) {
|
|
3136
4267
|
this.options = options;
|
|
3137
4268
|
}
|
|
4269
|
+
/**
|
|
4270
|
+
* Formats an array of commits into changelog entries
|
|
4271
|
+
*
|
|
4272
|
+
* Groups commits by type and formats them according to the
|
|
4273
|
+
* configured template and options. Supports commit body
|
|
4274
|
+
* inclusion and type-based sections.
|
|
4275
|
+
*
|
|
4276
|
+
* @param commits - Array of commit values to format
|
|
4277
|
+
* @param options - Optional formatting options
|
|
4278
|
+
* @returns Array of formatted changelog lines
|
|
4279
|
+
*
|
|
4280
|
+
* @example Basic formatting
|
|
4281
|
+
* ```typescript
|
|
4282
|
+
* const changelog = formatter.format([
|
|
4283
|
+
* {
|
|
4284
|
+
* base: { hash: 'abc123' },
|
|
4285
|
+
* commitlint: {
|
|
4286
|
+
* type: 'feat',
|
|
4287
|
+
* scope: 'api',
|
|
4288
|
+
* message: 'new endpoint'
|
|
4289
|
+
* }
|
|
4290
|
+
* }
|
|
4291
|
+
* ]);
|
|
4292
|
+
* // [
|
|
4293
|
+
* // '### Features',
|
|
4294
|
+
* // '- **api:** new endpoint ([abc123](...))'
|
|
4295
|
+
* // ]
|
|
4296
|
+
* ```
|
|
4297
|
+
*
|
|
4298
|
+
* @example With commit body
|
|
4299
|
+
* ```typescript
|
|
4300
|
+
* const changelog = formatter.format(
|
|
4301
|
+
* [{
|
|
4302
|
+
* commitlint: {
|
|
4303
|
+
* type: 'fix',
|
|
4304
|
+
* message: 'memory leak',
|
|
4305
|
+
* body: 'Fixed memory allocation\nAdded cleanup'
|
|
4306
|
+
* }
|
|
4307
|
+
* }],
|
|
4308
|
+
* { commitBody: true }
|
|
4309
|
+
* );
|
|
4310
|
+
* // [
|
|
4311
|
+
* // '### Bug Fixes',
|
|
4312
|
+
* // '- memory leak',
|
|
4313
|
+
* // ' Fixed memory allocation',
|
|
4314
|
+
* // ' Added cleanup'
|
|
4315
|
+
* // ]
|
|
4316
|
+
* ```
|
|
4317
|
+
*/
|
|
3138
4318
|
format(commits, options) {
|
|
3139
4319
|
const { types = [], commitBody = false } = { ...this.options, ...options };
|
|
3140
4320
|
const changelog = [];
|
|
@@ -3161,6 +4341,41 @@ var GitChangelogFormatter = class {
|
|
|
3161
4341
|
});
|
|
3162
4342
|
return changelog;
|
|
3163
4343
|
}
|
|
4344
|
+
/**
|
|
4345
|
+
* Formats a single commit into a changelog entry
|
|
4346
|
+
*
|
|
4347
|
+
* Applies the configured template to a commit, including
|
|
4348
|
+
* scope formatting, PR links, and commit hash links.
|
|
4349
|
+
*
|
|
4350
|
+
* @param commit - Commit value to format
|
|
4351
|
+
* @param options - Optional formatting options
|
|
4352
|
+
* @returns Formatted changelog entry
|
|
4353
|
+
*
|
|
4354
|
+
* @example Basic formatting
|
|
4355
|
+
* ```typescript
|
|
4356
|
+
* const entry = formatter.formatCommit({
|
|
4357
|
+
* base: { hash: 'abc123' },
|
|
4358
|
+
* commitlint: {
|
|
4359
|
+
* type: 'feat',
|
|
4360
|
+
* scope: 'api',
|
|
4361
|
+
* message: 'new endpoint'
|
|
4362
|
+
* }
|
|
4363
|
+
* });
|
|
4364
|
+
* // '- **api:** new endpoint ([abc123](...))'
|
|
4365
|
+
* ```
|
|
4366
|
+
*
|
|
4367
|
+
* @example With PR number
|
|
4368
|
+
* ```typescript
|
|
4369
|
+
* const entry = formatter.formatCommit({
|
|
4370
|
+
* base: { hash: 'def456' },
|
|
4371
|
+
* commitlint: {
|
|
4372
|
+
* message: 'fix bug'
|
|
4373
|
+
* },
|
|
4374
|
+
* prNumber: '123'
|
|
4375
|
+
* });
|
|
4376
|
+
* // '- fix bug ([def456](...)) (#123)'
|
|
4377
|
+
* ```
|
|
4378
|
+
*/
|
|
3164
4379
|
formatCommit(commit, options) {
|
|
3165
4380
|
const {
|
|
3166
4381
|
commitlint,
|
|
@@ -3187,12 +4402,65 @@ var GitChangelogFormatter = class {
|
|
|
3187
4402
|
prLink
|
|
3188
4403
|
});
|
|
3189
4404
|
}
|
|
4405
|
+
/**
|
|
4406
|
+
* Formats a target string as a Markdown link
|
|
4407
|
+
*
|
|
4408
|
+
* Creates a Markdown-formatted link with optional URL.
|
|
4409
|
+
* If no URL is provided, formats as a plain reference.
|
|
4410
|
+
*
|
|
4411
|
+
* @param target - Text to display
|
|
4412
|
+
* @param url - Optional URL for the link
|
|
4413
|
+
* @returns Formatted Markdown link
|
|
4414
|
+
*
|
|
4415
|
+
* @example With URL
|
|
4416
|
+
* ```typescript
|
|
4417
|
+
* const link = formatter.foramtLink('abc123', 'https://github.com/org/repo/commit/abc123');
|
|
4418
|
+
* // '([abc123](https://github.com/org/repo/commit/abc123))'
|
|
4419
|
+
* ```
|
|
4420
|
+
*
|
|
4421
|
+
* @example Without URL
|
|
4422
|
+
* ```typescript
|
|
4423
|
+
* const link = formatter.foramtLink('abc123');
|
|
4424
|
+
* // '(abc123)'
|
|
4425
|
+
* ```
|
|
4426
|
+
*/
|
|
3190
4427
|
foramtLink(target, url) {
|
|
3191
4428
|
return url ? `([${target}](${url}))` : `(${target})`;
|
|
3192
4429
|
}
|
|
4430
|
+
/**
|
|
4431
|
+
* Formats a commit hash as a Markdown link
|
|
4432
|
+
*
|
|
4433
|
+
* @deprecated Use foramtLink instead
|
|
4434
|
+
* @param target - Commit hash to display
|
|
4435
|
+
* @param url - Optional URL to the commit
|
|
4436
|
+
* @returns Formatted Markdown link
|
|
4437
|
+
*
|
|
4438
|
+
* @example
|
|
4439
|
+
* ```typescript
|
|
4440
|
+
* const link = formatter.formatCommitLink(
|
|
4441
|
+
* 'abc123',
|
|
4442
|
+
* 'https://github.com/org/repo/commit/abc123'
|
|
4443
|
+
* );
|
|
4444
|
+
* // '([abc123](https://github.com/org/repo/commit/abc123))'
|
|
4445
|
+
* ```
|
|
4446
|
+
*/
|
|
3193
4447
|
formatCommitLink(target, url) {
|
|
3194
4448
|
return url ? `([${target}](${url}))` : `(${target})`;
|
|
3195
4449
|
}
|
|
4450
|
+
/**
|
|
4451
|
+
* Formats a commit scope in Markdown
|
|
4452
|
+
*
|
|
4453
|
+
* Wraps the scope in bold syntax and adds a colon.
|
|
4454
|
+
*
|
|
4455
|
+
* @param scope - Scope to format
|
|
4456
|
+
* @returns Formatted scope in Markdown
|
|
4457
|
+
*
|
|
4458
|
+
* @example
|
|
4459
|
+
* ```typescript
|
|
4460
|
+
* const scope = formatter.formatScope('api');
|
|
4461
|
+
* // '**api:**'
|
|
4462
|
+
* ```
|
|
4463
|
+
*/
|
|
3196
4464
|
formatScope(scope) {
|
|
3197
4465
|
return `**${scope}:**`;
|
|
3198
4466
|
}
|
|
@@ -3246,7 +4514,30 @@ var Pather = class {
|
|
|
3246
4514
|
return child[boundaryIndex] === import_node_path.sep;
|
|
3247
4515
|
}
|
|
3248
4516
|
/**
|
|
3249
|
-
*
|
|
4517
|
+
* Normalized path prefix check
|
|
4518
|
+
*
|
|
4519
|
+
* Checks if sourcePath starts with targetPath after normalization.
|
|
4520
|
+
* Handles cross-platform path separators and trailing separators.
|
|
4521
|
+
*
|
|
4522
|
+
* @param sourcePath - Path to check
|
|
4523
|
+
* @param targetPath - Prefix path to match
|
|
4524
|
+
* @returns True if sourcePath starts with targetPath
|
|
4525
|
+
*
|
|
4526
|
+
* @example Basic usage
|
|
4527
|
+
* ```typescript
|
|
4528
|
+
* const pather = new Pather();
|
|
4529
|
+
*
|
|
4530
|
+
* pather.startsWith('src/utils/file.ts', 'src') // true
|
|
4531
|
+
* pather.startsWith('src\\utils\\file.ts', 'src') // true
|
|
4532
|
+
* pather.startsWith('lib/utils/file.ts', 'src') // false
|
|
4533
|
+
* ```
|
|
4534
|
+
*
|
|
4535
|
+
* @example Trailing separators
|
|
4536
|
+
* ```typescript
|
|
4537
|
+
* pather.startsWith('src/utils', 'src/') // true
|
|
4538
|
+
* pather.startsWith('src/utils/', 'src') // true
|
|
4539
|
+
* pather.startsWith('src2/utils', 'src') // false
|
|
4540
|
+
* ```
|
|
3250
4541
|
*/
|
|
3251
4542
|
startsWith(sourcePath, targetPath) {
|
|
3252
4543
|
let src = this.toLocalPath(sourcePath);
|
|
@@ -3260,7 +4551,44 @@ var Pather = class {
|
|
|
3260
4551
|
return src.startsWith(tgt);
|
|
3261
4552
|
}
|
|
3262
4553
|
/**
|
|
3263
|
-
* Segment-aware containment check
|
|
4554
|
+
* Segment-aware path containment check
|
|
4555
|
+
*
|
|
4556
|
+
* Checks if sourcePath contains targetPath as a complete path segment.
|
|
4557
|
+
* Unlike simple substring matching, this ensures proper path boundaries.
|
|
4558
|
+
* For example, 'src/abc' does not contain 'src/a' even though 'src/a'
|
|
4559
|
+
* is a substring.
|
|
4560
|
+
*
|
|
4561
|
+
* Features:
|
|
4562
|
+
* - Cross-platform path handling
|
|
4563
|
+
* - Proper segment boundary checking
|
|
4564
|
+
* - Trailing separator normalization
|
|
4565
|
+
* - Exact match support
|
|
4566
|
+
*
|
|
4567
|
+
* @param sourcePath - Path to search in
|
|
4568
|
+
* @param targetPath - Path to search for
|
|
4569
|
+
* @returns True if sourcePath contains targetPath as a segment
|
|
4570
|
+
*
|
|
4571
|
+
* @example Basic usage
|
|
4572
|
+
* ```typescript
|
|
4573
|
+
* const pather = new Pather();
|
|
4574
|
+
*
|
|
4575
|
+
* pather.containsPath('src/utils/file.ts', 'utils') // true
|
|
4576
|
+
* pather.containsPath('src/utils/file.ts', 'src/utils') // true
|
|
4577
|
+
* pather.containsPath('src/utils/file.ts', 'til') // false
|
|
4578
|
+
* ```
|
|
4579
|
+
*
|
|
4580
|
+
* @example Segment boundaries
|
|
4581
|
+
* ```typescript
|
|
4582
|
+
* pather.containsPath('src/abc/file.ts', 'src/a') // false
|
|
4583
|
+
* pather.containsPath('src/abc/file.ts', 'src/abc') // true
|
|
4584
|
+
* ```
|
|
4585
|
+
*
|
|
4586
|
+
* @example Trailing separators
|
|
4587
|
+
* ```typescript
|
|
4588
|
+
* pather.containsPath('src/utils/', 'utils') // true
|
|
4589
|
+
* pather.containsPath('src/utils', 'utils/') // true
|
|
4590
|
+
* pather.containsPath('src/utils/', 'utils/') // true
|
|
4591
|
+
* ```
|
|
3264
4592
|
*/
|
|
3265
4593
|
containsPath(sourcePath, targetPath) {
|
|
3266
4594
|
let src = this.toLocalPath(sourcePath);
|
|
@@ -3286,18 +4614,49 @@ var Pather = class {
|
|
|
3286
4614
|
// src/plugins/githubPR/GithubChangelog.ts
|
|
3287
4615
|
var DOMAIN = "https://github.com";
|
|
3288
4616
|
var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
4617
|
+
/**
|
|
4618
|
+
* Creates a new GitHub changelog generator
|
|
4619
|
+
*
|
|
4620
|
+
* @param options - Changelog generation options
|
|
4621
|
+
* @param githubManager - GitHub API manager
|
|
4622
|
+
*
|
|
4623
|
+
* @example
|
|
4624
|
+
* ```typescript
|
|
4625
|
+
* const changelog = new GithubChangelog({
|
|
4626
|
+
* shell,
|
|
4627
|
+
* logger,
|
|
4628
|
+
* mergePRcommit: true,
|
|
4629
|
+
* githubRootPath: 'https://github.com/org/repo'
|
|
4630
|
+
* }, githubManager);
|
|
4631
|
+
* ```
|
|
4632
|
+
*/
|
|
3289
4633
|
constructor(options, githubManager) {
|
|
3290
4634
|
super(options);
|
|
3291
4635
|
this.options = options;
|
|
3292
4636
|
this.githubManager = githubManager;
|
|
3293
4637
|
}
|
|
4638
|
+
/** Path manipulation utility */
|
|
3294
4639
|
pather = new Pather();
|
|
3295
4640
|
/**
|
|
3296
|
-
*
|
|
3297
|
-
*
|
|
3298
|
-
*
|
|
3299
|
-
*
|
|
4641
|
+
* Filters commits by directory
|
|
4642
|
+
*
|
|
4643
|
+
* Filters commits based on whether they contain changes in
|
|
4644
|
+
* the specified directory. Uses GitHub API to get detailed
|
|
4645
|
+
* commit information.
|
|
4646
|
+
*
|
|
4647
|
+
* @param commits - Array of commits to filter
|
|
4648
|
+
* @param directory - Directory path to filter by
|
|
4649
|
+
* @returns Promise resolving to filtered commits
|
|
3300
4650
|
* @since 2.4.0
|
|
4651
|
+
*
|
|
4652
|
+
* @example
|
|
4653
|
+
* ```typescript
|
|
4654
|
+
* const commits = await changelog.filterCommitsByDirectory(
|
|
4655
|
+
* allCommits,
|
|
4656
|
+
* 'packages/pkg-a'
|
|
4657
|
+
* );
|
|
4658
|
+
* // Only commits that modified files in packages/pkg-a
|
|
4659
|
+
* ```
|
|
3301
4660
|
*/
|
|
3302
4661
|
async filterCommitsByDirectory(commits, directory) {
|
|
3303
4662
|
const result = [];
|
|
@@ -3315,6 +4674,41 @@ var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
|
3315
4674
|
}
|
|
3316
4675
|
return result;
|
|
3317
4676
|
}
|
|
4677
|
+
/**
|
|
4678
|
+
* Gets complete commit information with PR details
|
|
4679
|
+
*
|
|
4680
|
+
* Retrieves commits and enhances them with pull request
|
|
4681
|
+
* information. For commits associated with PRs, includes
|
|
4682
|
+
* all PR commits and filters by directory.
|
|
4683
|
+
*
|
|
4684
|
+
* Process:
|
|
4685
|
+
* 1. Get base commits
|
|
4686
|
+
* 2. Extract PR numbers
|
|
4687
|
+
* 3. Fetch PR commits
|
|
4688
|
+
* 4. Filter by directory
|
|
4689
|
+
* 5. Flatten results
|
|
4690
|
+
*
|
|
4691
|
+
* @param options - Changelog options
|
|
4692
|
+
* @returns Promise resolving to enhanced commits
|
|
4693
|
+
*
|
|
4694
|
+
* @example Basic usage
|
|
4695
|
+
* ```typescript
|
|
4696
|
+
* const commits = await changelog.getFullCommit({
|
|
4697
|
+
* from: 'v1.0.0',
|
|
4698
|
+
* directory: 'packages/pkg-a'
|
|
4699
|
+
* });
|
|
4700
|
+
* // Returns commits with PR information
|
|
4701
|
+
* ```
|
|
4702
|
+
*
|
|
4703
|
+
* @example With PR merging
|
|
4704
|
+
* ```typescript
|
|
4705
|
+
* const commits = await changelog.getFullCommit({
|
|
4706
|
+
* mergePRcommit: true,
|
|
4707
|
+
* directory: 'packages/pkg-a'
|
|
4708
|
+
* });
|
|
4709
|
+
* // Includes all PR commits
|
|
4710
|
+
* ```
|
|
4711
|
+
*/
|
|
3318
4712
|
async getFullCommit(options) {
|
|
3319
4713
|
const _options = { ...this.options, ...options };
|
|
3320
4714
|
const allCommits = await this.getCommits(_options);
|
|
@@ -3342,6 +4736,41 @@ var GithubChangelog = class _GithubChangelog extends GitChangelog {
|
|
|
3342
4736
|
);
|
|
3343
4737
|
return newallCommits.flat();
|
|
3344
4738
|
}
|
|
4739
|
+
/**
|
|
4740
|
+
* Transforms workspaces with GitHub changelogs
|
|
4741
|
+
*
|
|
4742
|
+
* Processes each workspace to add GitHub-specific changelog
|
|
4743
|
+
* information. Includes:
|
|
4744
|
+
* - GitHub repository URL
|
|
4745
|
+
* - PR-aware commit history
|
|
4746
|
+
* - Formatted changelog with links
|
|
4747
|
+
*
|
|
4748
|
+
* Process:
|
|
4749
|
+
* 1. Build GitHub root path
|
|
4750
|
+
* 2. Configure changelog options
|
|
4751
|
+
* 3. Get commits for each workspace
|
|
4752
|
+
* 4. Format changelog with links
|
|
4753
|
+
* 5. Update workspace objects
|
|
4754
|
+
*
|
|
4755
|
+
* @param workspaces - Array of workspaces to process
|
|
4756
|
+
* @param context - Release context
|
|
4757
|
+
* @returns Promise resolving to updated workspaces
|
|
4758
|
+
*
|
|
4759
|
+
* @example
|
|
4760
|
+
* ```typescript
|
|
4761
|
+
* const workspaces = await changelog.transformWorkspace(
|
|
4762
|
+
* [
|
|
4763
|
+
* {
|
|
4764
|
+
* name: 'pkg-a',
|
|
4765
|
+
* path: 'packages/a',
|
|
4766
|
+
* lastTag: 'v1.0.0'
|
|
4767
|
+
* }
|
|
4768
|
+
* ],
|
|
4769
|
+
* context
|
|
4770
|
+
* );
|
|
4771
|
+
* // Returns workspaces with GitHub-formatted changelogs
|
|
4772
|
+
* ```
|
|
4773
|
+
*/
|
|
3345
4774
|
async transformWorkspace(workspaces, context) {
|
|
3346
4775
|
const githubRootPath = [
|
|
3347
4776
|
DOMAIN,
|
|
@@ -3391,6 +4820,26 @@ var import_scripts_context6 = require("@qlover/scripts-context");
|
|
|
3391
4820
|
var DEFAULT_RELEASE_NAME = "Release ${name} v${version}";
|
|
3392
4821
|
var DEFAULT_COMMIT_MESSAGE = "chore(tag): ${name} v${version}";
|
|
3393
4822
|
var GithubPR = class extends GitBase {
|
|
4823
|
+
/**
|
|
4824
|
+
* Creates a new GithubPR plugin instance
|
|
4825
|
+
*
|
|
4826
|
+
* Initializes the plugin with GitHub-specific configuration and
|
|
4827
|
+
* sets up release parameters and GitHub manager.
|
|
4828
|
+
*
|
|
4829
|
+
* @param context - Release context
|
|
4830
|
+
* @param props - Plugin configuration
|
|
4831
|
+
*
|
|
4832
|
+
* @example
|
|
4833
|
+
* ```typescript
|
|
4834
|
+
* const plugin = new GithubPR(context, {
|
|
4835
|
+
* releasePR: true,
|
|
4836
|
+
* releaseName: 'Release v${version}',
|
|
4837
|
+
* commitMessage: 'chore: release v${version}',
|
|
4838
|
+
* draft: false,
|
|
4839
|
+
* preRelease: false
|
|
4840
|
+
* });
|
|
4841
|
+
* ```
|
|
4842
|
+
*/
|
|
3394
4843
|
constructor(context, props) {
|
|
3395
4844
|
super(context, "githubPR", {
|
|
3396
4845
|
releaseName: DEFAULT_RELEASE_NAME,
|
|
@@ -3406,15 +4855,67 @@ var GithubPR = class extends GitBase {
|
|
|
3406
4855
|
}
|
|
3407
4856
|
releaseParams;
|
|
3408
4857
|
githubManager;
|
|
4858
|
+
/**
|
|
4859
|
+
* Determines if the plugin should be enabled
|
|
4860
|
+
*
|
|
4861
|
+
* Plugin is enabled unless explicitly skipped via configuration.
|
|
4862
|
+
* This allows for conditional PR creation and release publishing.
|
|
4863
|
+
*
|
|
4864
|
+
* @param _name - Plugin name (unused)
|
|
4865
|
+
* @returns True if plugin should be enabled
|
|
4866
|
+
*
|
|
4867
|
+
* @example
|
|
4868
|
+
* ```typescript
|
|
4869
|
+
* const plugin = new GithubPR(context, { skip: true });
|
|
4870
|
+
* plugin.enabled(); // false
|
|
4871
|
+
*
|
|
4872
|
+
* const plugin2 = new GithubPR(context, {});
|
|
4873
|
+
* plugin2.enabled(); // true
|
|
4874
|
+
* ```
|
|
4875
|
+
*/
|
|
3409
4876
|
enabled(_name) {
|
|
3410
4877
|
if (this.getConfig("skip")) {
|
|
3411
4878
|
return false;
|
|
3412
4879
|
}
|
|
3413
4880
|
return true;
|
|
3414
4881
|
}
|
|
4882
|
+
/**
|
|
4883
|
+
* Determines if the plugin is in publish mode
|
|
4884
|
+
*
|
|
4885
|
+
* In publish mode, the plugin publishes releases directly.
|
|
4886
|
+
* In non-publish mode (releasePR=true), it creates pull requests.
|
|
4887
|
+
*
|
|
4888
|
+
* @returns True if in publish mode
|
|
4889
|
+
*
|
|
4890
|
+
* @example
|
|
4891
|
+
* ```typescript
|
|
4892
|
+
* const plugin = new GithubPR(context, { releasePR: true });
|
|
4893
|
+
* plugin.isPublish; // false (PR mode)
|
|
4894
|
+
*
|
|
4895
|
+
* const plugin2 = new GithubPR(context, { releasePR: false });
|
|
4896
|
+
* plugin2.isPublish; // true (publish mode)
|
|
4897
|
+
* ```
|
|
4898
|
+
*/
|
|
3415
4899
|
get isPublish() {
|
|
3416
4900
|
return !this.getConfig("releasePR");
|
|
3417
4901
|
}
|
|
4902
|
+
/**
|
|
4903
|
+
* Checks if the current repository is a GitHub repository
|
|
4904
|
+
*
|
|
4905
|
+
* Verifies that the remote URL contains 'github.com' to ensure
|
|
4906
|
+
* GitHub-specific features can be used.
|
|
4907
|
+
*
|
|
4908
|
+
* @returns Promise resolving to true if GitHub repository
|
|
4909
|
+
*
|
|
4910
|
+
* @example
|
|
4911
|
+
* ```typescript
|
|
4912
|
+
* const isGithub = await plugin.isGithubRepository();
|
|
4913
|
+
* if (isGithub) {
|
|
4914
|
+
* // Use GitHub-specific features
|
|
4915
|
+
* }
|
|
4916
|
+
* ```
|
|
4917
|
+
* @private
|
|
4918
|
+
*/
|
|
3418
4919
|
async isGithubRepository() {
|
|
3419
4920
|
try {
|
|
3420
4921
|
const remoteUrl = await this.getRemoteUrl();
|
|
@@ -3423,6 +4924,24 @@ var GithubPR = class extends GitBase {
|
|
|
3423
4924
|
return false;
|
|
3424
4925
|
}
|
|
3425
4926
|
}
|
|
4927
|
+
/**
|
|
4928
|
+
* Plugin initialization hook
|
|
4929
|
+
*
|
|
4930
|
+
* Performs pre-execution setup:
|
|
4931
|
+
* 1. Verifies repository is on GitHub
|
|
4932
|
+
* 2. Runs parent class initialization
|
|
4933
|
+
* 3. Sets up NPM token for publishing
|
|
4934
|
+
*
|
|
4935
|
+
* @throws Error if not a GitHub repository
|
|
4936
|
+
* @throws Error if NPM_TOKEN missing in publish mode
|
|
4937
|
+
*
|
|
4938
|
+
* @example
|
|
4939
|
+
* ```typescript
|
|
4940
|
+
* const plugin = new GithubPR(context, {});
|
|
4941
|
+
* await plugin.onBefore();
|
|
4942
|
+
* // Throws if not GitHub repo or missing NPM token
|
|
4943
|
+
* ```
|
|
4944
|
+
*/
|
|
3426
4945
|
async onBefore() {
|
|
3427
4946
|
this.logger.debug("GithubPR onBefore");
|
|
3428
4947
|
const isGithub = await this.isGithubRepository();
|
|
@@ -3442,6 +4961,24 @@ var GithubPR = class extends GitBase {
|
|
|
3442
4961
|
);
|
|
3443
4962
|
}
|
|
3444
4963
|
}
|
|
4964
|
+
/**
|
|
4965
|
+
* Main plugin execution hook
|
|
4966
|
+
*
|
|
4967
|
+
* Processes changelogs for all workspaces using GitHub-specific
|
|
4968
|
+
* formatting and updates the context with the results.
|
|
4969
|
+
*
|
|
4970
|
+
* Process:
|
|
4971
|
+
* 1. Initialize GitHub changelog processor
|
|
4972
|
+
* 2. Transform workspace changelogs
|
|
4973
|
+
* 3. Update context with new workspace info
|
|
4974
|
+
*
|
|
4975
|
+
* @example
|
|
4976
|
+
* ```typescript
|
|
4977
|
+
* const plugin = new GithubPR(context, {});
|
|
4978
|
+
* await plugin.onExec();
|
|
4979
|
+
* // Transforms changelogs with GitHub links
|
|
4980
|
+
* ```
|
|
4981
|
+
*/
|
|
3445
4982
|
async onExec() {
|
|
3446
4983
|
const workspaces = this.context.workspaces;
|
|
3447
4984
|
const githubChangelog = new GithubChangelog(
|
|
@@ -3454,6 +4991,27 @@ var GithubPR = class extends GitBase {
|
|
|
3454
4991
|
});
|
|
3455
4992
|
this.context.setWorkspaces(newWorkspaces);
|
|
3456
4993
|
}
|
|
4994
|
+
/**
|
|
4995
|
+
* Success hook after plugin execution
|
|
4996
|
+
*
|
|
4997
|
+
* Handles either PR creation or release publishing based on
|
|
4998
|
+
* configuration. In publish mode, publishes to NPM and creates
|
|
4999
|
+
* GitHub releases. In PR mode, creates release pull requests.
|
|
5000
|
+
*
|
|
5001
|
+
* @example PR mode
|
|
5002
|
+
* ```typescript
|
|
5003
|
+
* const plugin = new GithubPR(context, { releasePR: true });
|
|
5004
|
+
* await plugin.onSuccess();
|
|
5005
|
+
* // Creates release PR
|
|
5006
|
+
* ```
|
|
5007
|
+
*
|
|
5008
|
+
* @example Publish mode
|
|
5009
|
+
* ```typescript
|
|
5010
|
+
* const plugin = new GithubPR(context, { releasePR: false });
|
|
5011
|
+
* await plugin.onSuccess();
|
|
5012
|
+
* // Publishes to NPM and creates GitHub release
|
|
5013
|
+
* ```
|
|
5014
|
+
*/
|
|
3457
5015
|
async onSuccess() {
|
|
3458
5016
|
if (this.isPublish) {
|
|
3459
5017
|
await this.publishPR(this.context.workspaces);
|
|
@@ -3461,6 +5019,28 @@ var GithubPR = class extends GitBase {
|
|
|
3461
5019
|
}
|
|
3462
5020
|
await this.releasePR(this.context.workspaces);
|
|
3463
5021
|
}
|
|
5022
|
+
/**
|
|
5023
|
+
* Creates a release pull request
|
|
5024
|
+
*
|
|
5025
|
+
* Handles the complete process of creating a release PR:
|
|
5026
|
+
* 1. Creates release commit
|
|
5027
|
+
* 2. Creates release branch
|
|
5028
|
+
* 3. Creates and configures pull request
|
|
5029
|
+
*
|
|
5030
|
+
* @param workspaces - Array of workspace configurations
|
|
5031
|
+
*
|
|
5032
|
+
* @example
|
|
5033
|
+
* ```typescript
|
|
5034
|
+
* const workspaces = [{
|
|
5035
|
+
* name: 'pkg-a',
|
|
5036
|
+
* version: '1.0.0',
|
|
5037
|
+
* changelog: '...'
|
|
5038
|
+
* }];
|
|
5039
|
+
*
|
|
5040
|
+
* await plugin.releasePR(workspaces);
|
|
5041
|
+
* // Creates PR with release changes
|
|
5042
|
+
* ```
|
|
5043
|
+
*/
|
|
3464
5044
|
async releasePR(workspaces) {
|
|
3465
5045
|
await this.step({
|
|
3466
5046
|
label: "Release Commit",
|
|
@@ -3472,6 +5052,28 @@ var GithubPR = class extends GitBase {
|
|
|
3472
5052
|
});
|
|
3473
5053
|
await this.releasePullRequest(workspaces, releaseBranchParams);
|
|
3474
5054
|
}
|
|
5055
|
+
/**
|
|
5056
|
+
* Publishes releases to NPM and GitHub
|
|
5057
|
+
*
|
|
5058
|
+
* In non-dry-run mode:
|
|
5059
|
+
* 1. Publishes packages to NPM
|
|
5060
|
+
* 2. Pushes tags to GitHub
|
|
5061
|
+
* 3. Creates GitHub releases
|
|
5062
|
+
*
|
|
5063
|
+
* @param workspaces - Array of workspace configurations
|
|
5064
|
+
*
|
|
5065
|
+
* @example
|
|
5066
|
+
* ```typescript
|
|
5067
|
+
* const workspaces = [{
|
|
5068
|
+
* name: 'pkg-a',
|
|
5069
|
+
* version: '1.0.0',
|
|
5070
|
+
* changelog: '...'
|
|
5071
|
+
* }];
|
|
5072
|
+
*
|
|
5073
|
+
* await plugin.publishPR(workspaces);
|
|
5074
|
+
* // Publishes to NPM and creates GitHub releases
|
|
5075
|
+
* ```
|
|
5076
|
+
*/
|
|
3475
5077
|
async publishPR(workspaces) {
|
|
3476
5078
|
if (!this.getConfig("dryRunCreatePR")) {
|
|
3477
5079
|
await this.context.runChangesetsCli("publish");
|
|
@@ -3487,6 +5089,34 @@ var GithubPR = class extends GitBase {
|
|
|
3487
5089
|
)
|
|
3488
5090
|
});
|
|
3489
5091
|
}
|
|
5092
|
+
/**
|
|
5093
|
+
* Creates release commit(s)
|
|
5094
|
+
*
|
|
5095
|
+
* Creates either a single commit for all workspaces or
|
|
5096
|
+
* individual commits per workspace. Uses configured commit
|
|
5097
|
+
* message template.
|
|
5098
|
+
*
|
|
5099
|
+
* @param workspaces - Array of workspace configurations
|
|
5100
|
+
*
|
|
5101
|
+
* @example Single workspace
|
|
5102
|
+
* ```typescript
|
|
5103
|
+
* await plugin.relesaeCommit([{
|
|
5104
|
+
* name: 'pkg-a',
|
|
5105
|
+
* version: '1.0.0'
|
|
5106
|
+
* }]);
|
|
5107
|
+
* // Creates: "chore(tag): pkg-a v1.0.0"
|
|
5108
|
+
* ```
|
|
5109
|
+
*
|
|
5110
|
+
* @example Multiple workspaces
|
|
5111
|
+
* ```typescript
|
|
5112
|
+
* await plugin.relesaeCommit([
|
|
5113
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
5114
|
+
* { name: 'pkg-b', version: '2.0.0' }
|
|
5115
|
+
* ]);
|
|
5116
|
+
* // Creates: "chore(tag): pkg-a v1.0.0,pkg-b v2.0.0"
|
|
5117
|
+
* ```
|
|
5118
|
+
* @private
|
|
5119
|
+
*/
|
|
3490
5120
|
async relesaeCommit(workspaces) {
|
|
3491
5121
|
const commitArgs = this.getConfig("commitArgs", []);
|
|
3492
5122
|
if (workspaces.length === 1) {
|
|
@@ -3498,6 +5128,34 @@ var GithubPR = class extends GitBase {
|
|
|
3498
5128
|
const commitMessage = `chore(tag): ${workspaces.map((w) => `${w.name} v${w.version}`).join(",")}`;
|
|
3499
5129
|
await this.commit(commitMessage, commitArgs);
|
|
3500
5130
|
}
|
|
5131
|
+
/**
|
|
5132
|
+
* Creates and optionally merges a release pull request
|
|
5133
|
+
*
|
|
5134
|
+
* Creates a PR with release changes and handles auto-merge
|
|
5135
|
+
* if configured. Adds release and change labels to the PR.
|
|
5136
|
+
*
|
|
5137
|
+
* @param workspaces - Array of workspace configurations
|
|
5138
|
+
* @param releaseBranchParams - Branch and tag information
|
|
5139
|
+
*
|
|
5140
|
+
* @example Manual merge
|
|
5141
|
+
* ```typescript
|
|
5142
|
+
* await plugin.releasePullRequest(
|
|
5143
|
+
* workspaces,
|
|
5144
|
+
* { releaseBranch: 'release-v1.0.0', tagName: 'v1.0.0' }
|
|
5145
|
+
* );
|
|
5146
|
+
* // Creates PR for manual merge
|
|
5147
|
+
* ```
|
|
5148
|
+
*
|
|
5149
|
+
* @example Auto-merge
|
|
5150
|
+
* ```typescript
|
|
5151
|
+
* const plugin = new GithubPR(context, {
|
|
5152
|
+
* autoMergeReleasePR: true
|
|
5153
|
+
* });
|
|
5154
|
+
*
|
|
5155
|
+
* await plugin.releasePullRequest(workspaces, params);
|
|
5156
|
+
* // Creates and auto-merges PR
|
|
5157
|
+
* ```
|
|
5158
|
+
*/
|
|
3501
5159
|
async releasePullRequest(workspaces, releaseBranchParams) {
|
|
3502
5160
|
const prNumber = await this.step({
|
|
3503
5161
|
label: "Create Release PR",
|
|
@@ -3519,6 +5177,34 @@ var GithubPR = class extends GitBase {
|
|
|
3519
5177
|
`Please manually merge PR(#${prNumber}) and complete the publishing process afterwards`
|
|
3520
5178
|
);
|
|
3521
5179
|
}
|
|
5180
|
+
/**
|
|
5181
|
+
* Creates a commit for a single workspace
|
|
5182
|
+
*
|
|
5183
|
+
* Uses the configured commit message template to create a
|
|
5184
|
+
* commit for the workspace's changes.
|
|
5185
|
+
*
|
|
5186
|
+
* @param workspace - Workspace configuration
|
|
5187
|
+
* @param commitArgs - Additional Git commit arguments
|
|
5188
|
+
* @returns Promise resolving to commit output
|
|
5189
|
+
*
|
|
5190
|
+
* @example Basic commit
|
|
5191
|
+
* ```typescript
|
|
5192
|
+
* await plugin.commitWorkspace({
|
|
5193
|
+
* name: 'pkg-a',
|
|
5194
|
+
* version: '1.0.0'
|
|
5195
|
+
* });
|
|
5196
|
+
* // Creates: "chore(tag): pkg-a v1.0.0"
|
|
5197
|
+
* ```
|
|
5198
|
+
*
|
|
5199
|
+
* @example With arguments
|
|
5200
|
+
* ```typescript
|
|
5201
|
+
* await plugin.commitWorkspace(
|
|
5202
|
+
* { name: 'pkg-a', version: '1.0.0' },
|
|
5203
|
+
* ['--no-verify']
|
|
5204
|
+
* );
|
|
5205
|
+
* ```
|
|
5206
|
+
* @private
|
|
5207
|
+
*/
|
|
3522
5208
|
async commitWorkspace(workspace, commitArgs = []) {
|
|
3523
5209
|
const commitMessage = import_scripts_context6.Shell.format(
|
|
3524
5210
|
this.getConfig("commitMessage", DEFAULT_COMMIT_MESSAGE),
|
|
@@ -3536,6 +5222,37 @@ var GithubPR = class extends GitBase {
|
|
|
3536
5222
|
*
|
|
3537
5223
|
* @returns The release branch.
|
|
3538
5224
|
*/
|
|
5225
|
+
/**
|
|
5226
|
+
* Creates a release branch for changes
|
|
5227
|
+
*
|
|
5228
|
+
* Creates a new branch from the current branch for release
|
|
5229
|
+
* changes. The branch name is generated from the configured
|
|
5230
|
+
* template and workspace information.
|
|
5231
|
+
*
|
|
5232
|
+
* Process:
|
|
5233
|
+
* 1. Generate branch parameters
|
|
5234
|
+
* 2. Fetch required branches
|
|
5235
|
+
* 3. Create and push release branch
|
|
5236
|
+
*
|
|
5237
|
+
* @param workspaces - Array of workspace configurations
|
|
5238
|
+
* @returns Promise resolving to branch parameters
|
|
5239
|
+
*
|
|
5240
|
+
* @example
|
|
5241
|
+
* ```typescript
|
|
5242
|
+
* const params = await plugin.createReleaseBranch([{
|
|
5243
|
+
* name: 'pkg-a',
|
|
5244
|
+
* version: '1.0.0'
|
|
5245
|
+
* }]);
|
|
5246
|
+
* // {
|
|
5247
|
+
* // tagName: 'pkg-a@1.0.0',
|
|
5248
|
+
* // releaseBranch: 'release-pkg-a-1.0.0'
|
|
5249
|
+
* // }
|
|
5250
|
+
* ```
|
|
5251
|
+
*
|
|
5252
|
+
* @throws Error if tag name is invalid
|
|
5253
|
+
* @throws Error if branch creation fails
|
|
5254
|
+
* @private
|
|
5255
|
+
*/
|
|
3539
5256
|
async createReleaseBranch(workspaces) {
|
|
3540
5257
|
const params = this.releaseParams.getReleaseBranchParams(
|
|
3541
5258
|
workspaces,
|
|
@@ -3578,6 +5295,42 @@ var GithubPR = class extends GitBase {
|
|
|
3578
5295
|
* @param releaseBranchParams - The release branch params.
|
|
3579
5296
|
* @returns The created pull request number.
|
|
3580
5297
|
*/
|
|
5298
|
+
/**
|
|
5299
|
+
* Creates a release pull request
|
|
5300
|
+
*
|
|
5301
|
+
* Creates a pull request with:
|
|
5302
|
+
* 1. Release label
|
|
5303
|
+
* 2. Change labels (if configured)
|
|
5304
|
+
* 3. Generated title and body
|
|
5305
|
+
* 4. Proper branch configuration
|
|
5306
|
+
*
|
|
5307
|
+
* @param workspaces - Array of workspace configurations
|
|
5308
|
+
* @param releaseBranchParams - Branch and tag information
|
|
5309
|
+
* @returns Promise resolving to PR number
|
|
5310
|
+
*
|
|
5311
|
+
* @example Basic PR
|
|
5312
|
+
* ```typescript
|
|
5313
|
+
* const prNumber = await plugin.createReleasePR(
|
|
5314
|
+
* workspaces,
|
|
5315
|
+
* { releaseBranch: 'release-v1.0.0', tagName: 'v1.0.0' }
|
|
5316
|
+
* );
|
|
5317
|
+
* // Creates PR with default labels
|
|
5318
|
+
* ```
|
|
5319
|
+
*
|
|
5320
|
+
* @example With change labels
|
|
5321
|
+
* ```typescript
|
|
5322
|
+
* const plugin = new GithubPR(context, {
|
|
5323
|
+
* pushChangeLabels: true
|
|
5324
|
+
* });
|
|
5325
|
+
*
|
|
5326
|
+
* const prNumber = await plugin.createReleasePR(
|
|
5327
|
+
* workspaces,
|
|
5328
|
+
* params
|
|
5329
|
+
* );
|
|
5330
|
+
* // Creates PR with release and change labels
|
|
5331
|
+
* ```
|
|
5332
|
+
* @private
|
|
5333
|
+
*/
|
|
3581
5334
|
async createReleasePR(workspaces, releaseBranchParams) {
|
|
3582
5335
|
const label = await this.githubManager.createReleasePRLabel();
|
|
3583
5336
|
let labels = [label.name];
|
|
@@ -3611,21 +5364,137 @@ var import_node_path2 = require("path");
|
|
|
3611
5364
|
|
|
3612
5365
|
// src/implments/ReleaseLabel.ts
|
|
3613
5366
|
var ReleaseLabel = class {
|
|
5367
|
+
/**
|
|
5368
|
+
* Creates a new ReleaseLabel instance
|
|
5369
|
+
*
|
|
5370
|
+
* @param options - Configuration options for label management
|
|
5371
|
+
*
|
|
5372
|
+
* @example
|
|
5373
|
+
* ```typescript
|
|
5374
|
+
* const label = new ReleaseLabel({
|
|
5375
|
+
* // Label template with ${name} placeholder
|
|
5376
|
+
* changePackagesLabel: 'changed:${name}',
|
|
5377
|
+
*
|
|
5378
|
+
* // Package directories to monitor
|
|
5379
|
+
* packagesDirectories: ['packages/a', 'packages/b'],
|
|
5380
|
+
*
|
|
5381
|
+
* // Optional custom comparison logic
|
|
5382
|
+
* compare: (file, pkg) => file.includes(pkg)
|
|
5383
|
+
* });
|
|
5384
|
+
* ```
|
|
5385
|
+
*/
|
|
3614
5386
|
constructor(options) {
|
|
3615
5387
|
this.options = options;
|
|
3616
5388
|
}
|
|
5389
|
+
/**
|
|
5390
|
+
* Compares a changed file path against a package path
|
|
5391
|
+
*
|
|
5392
|
+
* Uses custom comparison function if provided, otherwise
|
|
5393
|
+
* checks if the file path starts with the package path.
|
|
5394
|
+
*
|
|
5395
|
+
* @param changedFilePath - Path of the changed file
|
|
5396
|
+
* @param packagePath - Path of the package to check against
|
|
5397
|
+
* @returns True if the file belongs to the package
|
|
5398
|
+
*
|
|
5399
|
+
* @example
|
|
5400
|
+
* ```typescript
|
|
5401
|
+
* // Default comparison
|
|
5402
|
+
* label.compare('packages/a/src/index.ts', 'packages/a');
|
|
5403
|
+
* // true
|
|
5404
|
+
*
|
|
5405
|
+
* // Custom comparison
|
|
5406
|
+
* const label = new ReleaseLabel({
|
|
5407
|
+
* ...options,
|
|
5408
|
+
* compare: (file, pkg) => file.includes(pkg)
|
|
5409
|
+
* });
|
|
5410
|
+
* label.compare('src/packages/a/index.ts', 'packages/a');
|
|
5411
|
+
* // true
|
|
5412
|
+
* ```
|
|
5413
|
+
*/
|
|
3617
5414
|
compare(changedFilePath, packagePath) {
|
|
3618
5415
|
if (typeof this.options.compare === "function") {
|
|
3619
5416
|
return this.options.compare(changedFilePath, packagePath);
|
|
3620
5417
|
}
|
|
3621
5418
|
return changedFilePath.startsWith(packagePath);
|
|
3622
5419
|
}
|
|
5420
|
+
/**
|
|
5421
|
+
* Generates a change label for a single package
|
|
5422
|
+
*
|
|
5423
|
+
* Replaces ${name} placeholder in the label template with
|
|
5424
|
+
* the package path.
|
|
5425
|
+
*
|
|
5426
|
+
* @param packagePath - Path of the package
|
|
5427
|
+
* @param label - Optional custom label template
|
|
5428
|
+
* @returns Formatted change label
|
|
5429
|
+
*
|
|
5430
|
+
* @example
|
|
5431
|
+
* ```typescript
|
|
5432
|
+
* // Default label template
|
|
5433
|
+
* label.toChangeLabel('packages/a');
|
|
5434
|
+
* // 'changed:packages/a'
|
|
5435
|
+
*
|
|
5436
|
+
* // Custom label template
|
|
5437
|
+
* label.toChangeLabel('packages/a', 'modified:${name}');
|
|
5438
|
+
* // 'modified:packages/a'
|
|
5439
|
+
* ```
|
|
5440
|
+
*/
|
|
3623
5441
|
toChangeLabel(packagePath, label = this.options.changePackagesLabel) {
|
|
3624
5442
|
return label.replace("${name}", packagePath);
|
|
3625
5443
|
}
|
|
5444
|
+
/**
|
|
5445
|
+
* Generates change labels for multiple packages
|
|
5446
|
+
*
|
|
5447
|
+
* Maps each package path to a formatted change label.
|
|
5448
|
+
*
|
|
5449
|
+
* @param packages - Array of package paths
|
|
5450
|
+
* @param label - Optional custom label template
|
|
5451
|
+
* @returns Array of formatted change labels
|
|
5452
|
+
*
|
|
5453
|
+
* @example
|
|
5454
|
+
* ```typescript
|
|
5455
|
+
* // Default label template
|
|
5456
|
+
* label.toChangeLabels(['packages/a', 'packages/b']);
|
|
5457
|
+
* // ['changed:packages/a', 'changed:packages/b']
|
|
5458
|
+
*
|
|
5459
|
+
* // Custom label template
|
|
5460
|
+
* label.toChangeLabels(
|
|
5461
|
+
* ['packages/a', 'packages/b'],
|
|
5462
|
+
* 'modified:${name}'
|
|
5463
|
+
* );
|
|
5464
|
+
* // ['modified:packages/a', 'modified:packages/b']
|
|
5465
|
+
* ```
|
|
5466
|
+
*/
|
|
3626
5467
|
toChangeLabels(packages, label = this.options.changePackagesLabel) {
|
|
3627
5468
|
return packages.map((pkg) => this.toChangeLabel(pkg, label));
|
|
3628
5469
|
}
|
|
5470
|
+
/**
|
|
5471
|
+
* Identifies packages affected by changed files
|
|
5472
|
+
*
|
|
5473
|
+
* Checks each changed file against package paths to determine
|
|
5474
|
+
* which packages have been modified.
|
|
5475
|
+
*
|
|
5476
|
+
* @param changedFiles - Array or Set of changed file paths
|
|
5477
|
+
* @param packages - Optional array of package paths to check
|
|
5478
|
+
* @returns Array of affected package paths
|
|
5479
|
+
*
|
|
5480
|
+
* @example
|
|
5481
|
+
* ```typescript
|
|
5482
|
+
* // Check against default packages
|
|
5483
|
+
* label.pick(['packages/a/src/index.ts']);
|
|
5484
|
+
* // ['packages/a']
|
|
5485
|
+
*
|
|
5486
|
+
* // Check specific packages
|
|
5487
|
+
* label.pick(
|
|
5488
|
+
* ['packages/a/index.ts', 'packages/b/test.ts'],
|
|
5489
|
+
* ['packages/a', 'packages/c']
|
|
5490
|
+
* );
|
|
5491
|
+
* // ['packages/a']
|
|
5492
|
+
*
|
|
5493
|
+
* // Using Set of files
|
|
5494
|
+
* label.pick(new Set(['packages/a/index.ts']));
|
|
5495
|
+
* // ['packages/a']
|
|
5496
|
+
* ```
|
|
5497
|
+
*/
|
|
3629
5498
|
pick(changedFiles, packages = this.options.packagesDirectories) {
|
|
3630
5499
|
const result = [];
|
|
3631
5500
|
for (const pkgPath of packages) {
|
|
@@ -3991,6 +5860,31 @@ var import_fs2 = require("fs");
|
|
|
3991
5860
|
var import_scripts_context8 = require("@qlover/scripts-context");
|
|
3992
5861
|
var contentTmplate = "---\n'${name}': '${increment}'\n---\n\n${changelog}";
|
|
3993
5862
|
var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
5863
|
+
/**
|
|
5864
|
+
* Creates a new Changelog plugin instance
|
|
5865
|
+
*
|
|
5866
|
+
* Initializes the plugin with default configuration values and
|
|
5867
|
+
* merges them with provided options.
|
|
5868
|
+
*
|
|
5869
|
+
* Default values:
|
|
5870
|
+
* - increment: 'patch'
|
|
5871
|
+
* - changesetRoot: '.changeset'
|
|
5872
|
+
* - tagTemplate: '${name}@${version}'
|
|
5873
|
+
* - tagPrefix: '${name}'
|
|
5874
|
+
* - tagMatch: '${name}@*'
|
|
5875
|
+
*
|
|
5876
|
+
* @param context - Release context
|
|
5877
|
+
* @param props - Plugin configuration
|
|
5878
|
+
*
|
|
5879
|
+
* @example
|
|
5880
|
+
* ```typescript
|
|
5881
|
+
* const plugin = new Changelog(context, {
|
|
5882
|
+
* increment: 'minor',
|
|
5883
|
+
* changesetRoot: 'custom/changeset',
|
|
5884
|
+
* tagTemplate: 'v${version}'
|
|
5885
|
+
* });
|
|
5886
|
+
* ```
|
|
5887
|
+
*/
|
|
3994
5888
|
constructor(context, props) {
|
|
3995
5889
|
super(context, "changelog", {
|
|
3996
5890
|
increment: "patch",
|
|
@@ -4001,15 +5895,78 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4001
5895
|
...props
|
|
4002
5896
|
});
|
|
4003
5897
|
}
|
|
5898
|
+
/**
|
|
5899
|
+
* Gets the absolute path to the changeset root directory
|
|
5900
|
+
*
|
|
5901
|
+
* Combines the project root path with the configured changeset
|
|
5902
|
+
* directory path.
|
|
5903
|
+
*
|
|
5904
|
+
* @returns Absolute path to changeset directory
|
|
5905
|
+
*
|
|
5906
|
+
* @example
|
|
5907
|
+
* ```typescript
|
|
5908
|
+
* const root = plugin.changesetRoot;
|
|
5909
|
+
* // '/path/to/project/.changeset'
|
|
5910
|
+
* ```
|
|
5911
|
+
*/
|
|
4004
5912
|
get changesetRoot() {
|
|
4005
5913
|
return (0, import_path2.join)(this.context.rootPath, this.getConfig("changesetRoot"));
|
|
4006
5914
|
}
|
|
5915
|
+
/**
|
|
5916
|
+
* Gets the path to the changeset configuration file
|
|
5917
|
+
*
|
|
5918
|
+
* Returns the absolute path to the config.json file in the
|
|
5919
|
+
* changeset directory.
|
|
5920
|
+
*
|
|
5921
|
+
* @returns Path to changeset config file
|
|
5922
|
+
*
|
|
5923
|
+
* @example
|
|
5924
|
+
* ```typescript
|
|
5925
|
+
* const configPath = plugin.changesetConfigPath;
|
|
5926
|
+
* // '/path/to/project/.changeset/config.json'
|
|
5927
|
+
* ```
|
|
5928
|
+
*/
|
|
4007
5929
|
get changesetConfigPath() {
|
|
4008
5930
|
return (0, import_path2.join)(this.changesetRoot, "config.json");
|
|
4009
5931
|
}
|
|
5932
|
+
/**
|
|
5933
|
+
* Determines if the plugin should be enabled
|
|
5934
|
+
*
|
|
5935
|
+
* Plugin is enabled unless explicitly skipped via configuration.
|
|
5936
|
+
* This allows for conditional changelog generation.
|
|
5937
|
+
*
|
|
5938
|
+
* @returns True if plugin should be enabled
|
|
5939
|
+
*
|
|
5940
|
+
* @example
|
|
5941
|
+
* ```typescript
|
|
5942
|
+
* const plugin = new Changelog(context, { skip: true });
|
|
5943
|
+
* plugin.enabled(); // false
|
|
5944
|
+
*
|
|
5945
|
+
* const plugin2 = new Changelog(context, {});
|
|
5946
|
+
* plugin2.enabled(); // true
|
|
5947
|
+
* ```
|
|
5948
|
+
*/
|
|
4010
5949
|
enabled() {
|
|
4011
5950
|
return !this.getConfig("skip");
|
|
4012
5951
|
}
|
|
5952
|
+
/**
|
|
5953
|
+
* Plugin initialization hook
|
|
5954
|
+
*
|
|
5955
|
+
* Verifies that the changeset directory exists before proceeding
|
|
5956
|
+
* with changelog generation.
|
|
5957
|
+
*
|
|
5958
|
+
* @throws Error if changeset directory does not exist
|
|
5959
|
+
*
|
|
5960
|
+
* @example
|
|
5961
|
+
* ```typescript
|
|
5962
|
+
* const plugin = new Changelog(context, {
|
|
5963
|
+
* changesetRoot: '.changeset'
|
|
5964
|
+
* });
|
|
5965
|
+
*
|
|
5966
|
+
* await plugin.onBefore();
|
|
5967
|
+
* // Throws if .changeset directory doesn't exist
|
|
5968
|
+
* ```
|
|
5969
|
+
*/
|
|
4013
5970
|
async onBefore() {
|
|
4014
5971
|
if (!(0, import_fs2.existsSync)(this.changesetRoot)) {
|
|
4015
5972
|
throw new Error(
|
|
@@ -4018,6 +5975,33 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4018
5975
|
}
|
|
4019
5976
|
this.logger.debug(`${this.changesetRoot} exists`);
|
|
4020
5977
|
}
|
|
5978
|
+
/**
|
|
5979
|
+
* Updates workspace information with latest versions
|
|
5980
|
+
*
|
|
5981
|
+
* Reads the latest version information from each workspace's
|
|
5982
|
+
* package.json and updates the workspace objects with new
|
|
5983
|
+
* versions and tag names.
|
|
5984
|
+
*
|
|
5985
|
+
* @param workspaces - Array of workspace configurations
|
|
5986
|
+
* @returns Updated workspace configurations
|
|
5987
|
+
*
|
|
5988
|
+
* @example
|
|
5989
|
+
* ```typescript
|
|
5990
|
+
* const workspaces = [
|
|
5991
|
+
* { name: 'pkg-a', path: 'packages/a', version: '1.0.0' }
|
|
5992
|
+
* ];
|
|
5993
|
+
*
|
|
5994
|
+
* const updated = plugin.mergeWorkspaces(workspaces);
|
|
5995
|
+
* // [
|
|
5996
|
+
* // {
|
|
5997
|
+
* // name: 'pkg-a',
|
|
5998
|
+
* // path: 'packages/a',
|
|
5999
|
+
* // version: '1.1.0', // Updated version
|
|
6000
|
+
* // tagName: 'pkg-a@1.1.0'
|
|
6001
|
+
* // }
|
|
6002
|
+
* // ]
|
|
6003
|
+
* ```
|
|
6004
|
+
*/
|
|
4021
6005
|
mergeWorkspaces(workspaces) {
|
|
4022
6006
|
return workspaces.map((workspace) => {
|
|
4023
6007
|
const newPackgeJson = WorkspaceCreator.toWorkspace(
|
|
@@ -4034,6 +6018,25 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4034
6018
|
return newWorkspace;
|
|
4035
6019
|
});
|
|
4036
6020
|
}
|
|
6021
|
+
/**
|
|
6022
|
+
* Main plugin execution hook
|
|
6023
|
+
*
|
|
6024
|
+
* Generates changelogs for all workspaces in parallel and updates
|
|
6025
|
+
* the context with the results.
|
|
6026
|
+
*
|
|
6027
|
+
* Process:
|
|
6028
|
+
* 1. Generate changelogs for each workspace
|
|
6029
|
+
* 2. Update context with new workspace information
|
|
6030
|
+
*
|
|
6031
|
+
* @param _context - Execution context
|
|
6032
|
+
*
|
|
6033
|
+
* @example
|
|
6034
|
+
* ```typescript
|
|
6035
|
+
* const plugin = new Changelog(context, {});
|
|
6036
|
+
* await plugin.onExec(execContext);
|
|
6037
|
+
* // Generates changelogs for all workspaces
|
|
6038
|
+
* ```
|
|
6039
|
+
*/
|
|
4037
6040
|
async onExec(_context) {
|
|
4038
6041
|
const workspaces = await this.step({
|
|
4039
6042
|
label: "Generate Changelogs",
|
|
@@ -4045,6 +6048,28 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4045
6048
|
});
|
|
4046
6049
|
this.context.setWorkspaces(workspaces);
|
|
4047
6050
|
}
|
|
6051
|
+
/**
|
|
6052
|
+
* Success hook after plugin execution
|
|
6053
|
+
*
|
|
6054
|
+
* Handles post-changelog generation tasks:
|
|
6055
|
+
* 1. Creates changeset files (if not skipped)
|
|
6056
|
+
* 2. Updates package versions
|
|
6057
|
+
* 3. Restores unchanged packages (if configured)
|
|
6058
|
+
* 4. Updates workspace information
|
|
6059
|
+
*
|
|
6060
|
+
* @example
|
|
6061
|
+
* ```typescript
|
|
6062
|
+
* const plugin = new Changelog(context, {
|
|
6063
|
+
* skipChangeset: false,
|
|
6064
|
+
* ignoreNonUpdatedPackages: true
|
|
6065
|
+
* });
|
|
6066
|
+
*
|
|
6067
|
+
* await plugin.onSuccess();
|
|
6068
|
+
* // - Creates changeset files
|
|
6069
|
+
* // - Updates versions
|
|
6070
|
+
* // - Restores unchanged packages
|
|
6071
|
+
* ```
|
|
6072
|
+
*/
|
|
4048
6073
|
async onSuccess() {
|
|
4049
6074
|
const workspaces = this.context.workspaces;
|
|
4050
6075
|
if (!this.getConfig("skipChangeset")) {
|
|
@@ -4068,6 +6093,25 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4068
6093
|
this.logger.debug("new workspaces", newWorkspaces);
|
|
4069
6094
|
this.context.setWorkspaces(newWorkspaces);
|
|
4070
6095
|
}
|
|
6096
|
+
/**
|
|
6097
|
+
* Restores unchanged packages to their original state
|
|
6098
|
+
*
|
|
6099
|
+
* When ignoreNonUpdatedPackages is enabled, this method:
|
|
6100
|
+
* 1. Identifies packages without changes
|
|
6101
|
+
* 2. Uses git restore to revert them to original state
|
|
6102
|
+
*
|
|
6103
|
+
* @example
|
|
6104
|
+
* ```typescript
|
|
6105
|
+
* // With changed and unchanged packages
|
|
6106
|
+
* context.options.workspaces = {
|
|
6107
|
+
* packages: ['pkg-a', 'pkg-b', 'pkg-c'],
|
|
6108
|
+
* changedPaths: ['pkg-a', 'pkg-b']
|
|
6109
|
+
* };
|
|
6110
|
+
*
|
|
6111
|
+
* await plugin.restoreIgnorePackages();
|
|
6112
|
+
* // Restores 'pkg-c' to original state
|
|
6113
|
+
* ```
|
|
6114
|
+
*/
|
|
4071
6115
|
async restoreIgnorePackages() {
|
|
4072
6116
|
const { changedPaths = [], packages = [] } = this.context.getOptions(
|
|
4073
6117
|
"workspaces"
|
|
@@ -4080,12 +6124,60 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4080
6124
|
await this.shell.exec(["git", "restore", ...noChangedPackages]);
|
|
4081
6125
|
}
|
|
4082
6126
|
}
|
|
6127
|
+
/**
|
|
6128
|
+
* Gets the tag prefix for a workspace
|
|
6129
|
+
*
|
|
6130
|
+
* Formats the configured tag prefix template with workspace
|
|
6131
|
+
* information. Used for generating Git tag names.
|
|
6132
|
+
*
|
|
6133
|
+
* @param workspace - Workspace configuration
|
|
6134
|
+
* @returns Formatted tag prefix
|
|
6135
|
+
*
|
|
6136
|
+
* @example
|
|
6137
|
+
* ```typescript
|
|
6138
|
+
* const workspace = {
|
|
6139
|
+
* name: 'pkg-a',
|
|
6140
|
+
* version: '1.0.0'
|
|
6141
|
+
* };
|
|
6142
|
+
*
|
|
6143
|
+
* const prefix = plugin.getTagPrefix(workspace);
|
|
6144
|
+
* // With default template: 'pkg-a'
|
|
6145
|
+
* // With custom template: 'v1.0.0'
|
|
6146
|
+
* ```
|
|
6147
|
+
*/
|
|
4083
6148
|
getTagPrefix(workspace) {
|
|
4084
6149
|
return import_scripts_context8.Shell.format(
|
|
4085
6150
|
this.getConfig("tagPrefix"),
|
|
4086
6151
|
workspace
|
|
4087
6152
|
);
|
|
4088
6153
|
}
|
|
6154
|
+
/**
|
|
6155
|
+
* Generates a changelog for a workspace
|
|
6156
|
+
*
|
|
6157
|
+
* Creates a changelog by:
|
|
6158
|
+
* 1. Getting the appropriate tag name
|
|
6159
|
+
* 2. Retrieving commits since last tag
|
|
6160
|
+
* 3. Formatting commits into changelog entries
|
|
6161
|
+
*
|
|
6162
|
+
* @param workspace - Workspace configuration
|
|
6163
|
+
* @returns Updated workspace with changelog
|
|
6164
|
+
*
|
|
6165
|
+
* @example
|
|
6166
|
+
* ```typescript
|
|
6167
|
+
* const workspace = {
|
|
6168
|
+
* name: 'pkg-a',
|
|
6169
|
+
* path: 'packages/a',
|
|
6170
|
+
* version: '1.0.0'
|
|
6171
|
+
* };
|
|
6172
|
+
*
|
|
6173
|
+
* const updated = await plugin.generateChangelog(workspace);
|
|
6174
|
+
* // {
|
|
6175
|
+
* // ...workspace,
|
|
6176
|
+
* // lastTag: 'pkg-a@1.0.0',
|
|
6177
|
+
* // changelog: '- feat: new feature\n- fix: bug fix'
|
|
6178
|
+
* // }
|
|
6179
|
+
* ```
|
|
6180
|
+
*/
|
|
4089
6181
|
async generateChangelog(workspace) {
|
|
4090
6182
|
let tagName = await this.getTagName(workspace);
|
|
4091
6183
|
if (workspace.lastTag) {
|
|
@@ -4111,6 +6203,32 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4111
6203
|
changelog: changelog.join("\n")
|
|
4112
6204
|
};
|
|
4113
6205
|
}
|
|
6206
|
+
/**
|
|
6207
|
+
* Generates a tag name for a workspace
|
|
6208
|
+
*
|
|
6209
|
+
* Uses the configured tag template to generate a tag name
|
|
6210
|
+
* for the workspace. Handles errors by providing a fallback.
|
|
6211
|
+
*
|
|
6212
|
+
* @param workspace - Workspace configuration
|
|
6213
|
+
* @returns Generated tag name
|
|
6214
|
+
*
|
|
6215
|
+
* @example
|
|
6216
|
+
* ```typescript
|
|
6217
|
+
* // With default template
|
|
6218
|
+
* const tag = plugin.generateTagName({
|
|
6219
|
+
* name: 'pkg-a',
|
|
6220
|
+
* version: '1.0.0'
|
|
6221
|
+
* });
|
|
6222
|
+
* // 'pkg-a@1.0.0'
|
|
6223
|
+
*
|
|
6224
|
+
* // With error (fallback)
|
|
6225
|
+
* const tag = plugin.generateTagName({
|
|
6226
|
+
* name: 'pkg-a'
|
|
6227
|
+
* });
|
|
6228
|
+
* // 'pkg-a-v0.0.0'
|
|
6229
|
+
* ```
|
|
6230
|
+
* @private
|
|
6231
|
+
*/
|
|
4114
6232
|
generateTagName(workspace) {
|
|
4115
6233
|
try {
|
|
4116
6234
|
const tagTemplate = this.getConfig("tagTemplate");
|
|
@@ -4123,6 +6241,38 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4123
6241
|
return `${workspace.name}-v0.0.0`;
|
|
4124
6242
|
}
|
|
4125
6243
|
}
|
|
6244
|
+
/**
|
|
6245
|
+
* Gets the appropriate tag name for a workspace
|
|
6246
|
+
*
|
|
6247
|
+
* Attempts to find the latest tag for the workspace, falling back
|
|
6248
|
+
* to generating a new tag if none exists. Uses git commands to
|
|
6249
|
+
* find and sort tags by creation date.
|
|
6250
|
+
*
|
|
6251
|
+
* Process:
|
|
6252
|
+
* 1. Generate current tag pattern
|
|
6253
|
+
* 2. Search for existing tags matching pattern
|
|
6254
|
+
* 3. Return latest tag or generate new one
|
|
6255
|
+
*
|
|
6256
|
+
* @param workspace - Workspace configuration
|
|
6257
|
+
* @returns Promise resolving to tag name
|
|
6258
|
+
*
|
|
6259
|
+
* @example
|
|
6260
|
+
* ```typescript
|
|
6261
|
+
* // With existing tags
|
|
6262
|
+
* const tag = await plugin.getTagName({
|
|
6263
|
+
* name: 'pkg-a',
|
|
6264
|
+
* version: '1.0.0'
|
|
6265
|
+
* });
|
|
6266
|
+
* // Returns latest matching tag: 'pkg-a@0.9.0'
|
|
6267
|
+
*
|
|
6268
|
+
* // Without existing tags
|
|
6269
|
+
* const tag = await plugin.getTagName({
|
|
6270
|
+
* name: 'pkg-b',
|
|
6271
|
+
* version: '1.0.0'
|
|
6272
|
+
* });
|
|
6273
|
+
* // Returns new tag: 'pkg-b@1.0.0'
|
|
6274
|
+
* ```
|
|
6275
|
+
*/
|
|
4126
6276
|
async getTagName(workspace) {
|
|
4127
6277
|
try {
|
|
4128
6278
|
const currentTagPattern = this.generateTagName(workspace);
|
|
@@ -4149,6 +6299,31 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4149
6299
|
return fallbackTag;
|
|
4150
6300
|
}
|
|
4151
6301
|
}
|
|
6302
|
+
/**
|
|
6303
|
+
* Determines the version increment type
|
|
6304
|
+
*
|
|
6305
|
+
* Checks for increment labels in the following order:
|
|
6306
|
+
* 1. 'increment:major' label
|
|
6307
|
+
* 2. 'increment:minor' label
|
|
6308
|
+
* 3. Configured increment value
|
|
6309
|
+
* 4. Default to 'patch'
|
|
6310
|
+
*
|
|
6311
|
+
* @returns Version increment type
|
|
6312
|
+
*
|
|
6313
|
+
* @example
|
|
6314
|
+
* ```typescript
|
|
6315
|
+
* // With labels
|
|
6316
|
+
* context.options.workspaces.changeLabels = ['increment:major'];
|
|
6317
|
+
* plugin.getIncrement(); // 'major'
|
|
6318
|
+
*
|
|
6319
|
+
* // With configuration
|
|
6320
|
+
* const plugin = new Changelog(context, { increment: 'minor' });
|
|
6321
|
+
* plugin.getIncrement(); // 'minor'
|
|
6322
|
+
*
|
|
6323
|
+
* // Default
|
|
6324
|
+
* plugin.getIncrement(); // 'patch'
|
|
6325
|
+
* ```
|
|
6326
|
+
*/
|
|
4152
6327
|
getIncrement() {
|
|
4153
6328
|
const lables = this.context.getOptions("workspaces.changeLabels");
|
|
4154
6329
|
if (Array.isArray(lables) && lables.length > 0) {
|
|
@@ -4162,6 +6337,43 @@ var Changelog = class extends import_scripts_context8.ScriptPlugin {
|
|
|
4162
6337
|
const increment = this.getConfig("increment", "patch");
|
|
4163
6338
|
return increment;
|
|
4164
6339
|
}
|
|
6340
|
+
/**
|
|
6341
|
+
* Generates a changeset file for a workspace
|
|
6342
|
+
*
|
|
6343
|
+
* Creates a changeset file containing version increment
|
|
6344
|
+
* information and changelog content. Handles dry run mode
|
|
6345
|
+
* and existing files.
|
|
6346
|
+
*
|
|
6347
|
+
* File format:
|
|
6348
|
+
* ```yaml
|
|
6349
|
+
* ---
|
|
6350
|
+
* 'package-name': 'increment-type'
|
|
6351
|
+
* ---
|
|
6352
|
+
*
|
|
6353
|
+
* changelog content
|
|
6354
|
+
* ```
|
|
6355
|
+
*
|
|
6356
|
+
* @param workspace - Workspace configuration
|
|
6357
|
+
*
|
|
6358
|
+
* @example
|
|
6359
|
+
* ```typescript
|
|
6360
|
+
* const workspace = {
|
|
6361
|
+
* name: 'pkg-a',
|
|
6362
|
+
* version: '1.0.0',
|
|
6363
|
+
* changelog: '- feat: new feature'
|
|
6364
|
+
* };
|
|
6365
|
+
*
|
|
6366
|
+
* await plugin.generateChangesetFile(workspace);
|
|
6367
|
+
* // Creates .changeset/pkg-a-1.0.0.md
|
|
6368
|
+
* ```
|
|
6369
|
+
*
|
|
6370
|
+
* @example Dry run
|
|
6371
|
+
* ```typescript
|
|
6372
|
+
* context.dryRun = true;
|
|
6373
|
+
* await plugin.generateChangesetFile(workspace);
|
|
6374
|
+
* // Logs file content without creating file
|
|
6375
|
+
* ```
|
|
6376
|
+
*/
|
|
4165
6377
|
async generateChangesetFile(workspace) {
|
|
4166
6378
|
const { name, version } = workspace;
|
|
4167
6379
|
const changesetName = `${name}-${version}`.replace(/[\/\\]/g, "_");
|
|
@@ -4195,15 +6407,89 @@ var innerTuples = [
|
|
|
4195
6407
|
];
|
|
4196
6408
|
var defaultName = "release";
|
|
4197
6409
|
var ReleaseTask = class {
|
|
6410
|
+
/**
|
|
6411
|
+
* Creates a new ReleaseTask instance
|
|
6412
|
+
*
|
|
6413
|
+
* Initializes the release context and sets up plugin configuration.
|
|
6414
|
+
* Supports custom executors and plugin configurations.
|
|
6415
|
+
*
|
|
6416
|
+
* @param options - Release context configuration
|
|
6417
|
+
* @param executor - Custom async executor (optional)
|
|
6418
|
+
* @param defaultTuples - Plugin configuration tuples (optional)
|
|
6419
|
+
*
|
|
6420
|
+
* @example
|
|
6421
|
+
* ```typescript
|
|
6422
|
+
* // Basic initialization
|
|
6423
|
+
* const task = new ReleaseTask({
|
|
6424
|
+
* rootPath: '/path/to/project',
|
|
6425
|
+
* sourceBranch: 'main'
|
|
6426
|
+
* });
|
|
6427
|
+
*
|
|
6428
|
+
* // With custom executor and plugins
|
|
6429
|
+
* const task = new ReleaseTask(
|
|
6430
|
+
* { rootPath: '/path/to/project' },
|
|
6431
|
+
* new AsyncExecutor(),
|
|
6432
|
+
* [tuple(CustomPlugin, { option: 'value' })]
|
|
6433
|
+
* );
|
|
6434
|
+
* ```
|
|
6435
|
+
*/
|
|
4198
6436
|
constructor(options = {}, executor = new import_fe_corekit.AsyncExecutor(), defaultTuples = innerTuples) {
|
|
4199
6437
|
this.executor = executor;
|
|
4200
6438
|
this.defaultTuples = defaultTuples;
|
|
4201
6439
|
this.context = new ReleaseContext(defaultName, options);
|
|
4202
6440
|
}
|
|
6441
|
+
/**
|
|
6442
|
+
* Release context instance
|
|
6443
|
+
* @protected
|
|
6444
|
+
*/
|
|
4203
6445
|
context;
|
|
6446
|
+
/**
|
|
6447
|
+
* Gets the current release context
|
|
6448
|
+
*
|
|
6449
|
+
* @returns Release context instance
|
|
6450
|
+
*
|
|
6451
|
+
* @example
|
|
6452
|
+
* ```typescript
|
|
6453
|
+
* const task = new ReleaseTask();
|
|
6454
|
+
* const context = task.getContext();
|
|
6455
|
+
*
|
|
6456
|
+
* console.log(context.releaseEnv);
|
|
6457
|
+
* console.log(context.sourceBranch);
|
|
6458
|
+
* ```
|
|
6459
|
+
*/
|
|
4204
6460
|
getContext() {
|
|
4205
6461
|
return this.context;
|
|
4206
6462
|
}
|
|
6463
|
+
/**
|
|
6464
|
+
* Loads and configures plugins for the release task
|
|
6465
|
+
*
|
|
6466
|
+
* Combines default and external plugins, initializes them with
|
|
6467
|
+
* the current context, and configures special cases like the
|
|
6468
|
+
* Workspaces plugin.
|
|
6469
|
+
*
|
|
6470
|
+
* Plugin Loading Process:
|
|
6471
|
+
* 1. Merge default and external plugins
|
|
6472
|
+
* 2. Initialize plugins with context
|
|
6473
|
+
* 3. Configure special plugins
|
|
6474
|
+
* 4. Add plugins to executor
|
|
6475
|
+
*
|
|
6476
|
+
* @param externalTuples - Additional plugin configurations
|
|
6477
|
+
* @returns Array of initialized plugins
|
|
6478
|
+
*
|
|
6479
|
+
* @example Basic usage
|
|
6480
|
+
* ```typescript
|
|
6481
|
+
* const task = new ReleaseTask();
|
|
6482
|
+
* const plugins = await task.usePlugins();
|
|
6483
|
+
* ```
|
|
6484
|
+
*
|
|
6485
|
+
* @example Custom plugins
|
|
6486
|
+
* ```typescript
|
|
6487
|
+
* const task = new ReleaseTask();
|
|
6488
|
+
* const plugins = await task.usePlugins([
|
|
6489
|
+
* tuple(CustomPlugin, { option: 'value' })
|
|
6490
|
+
* ]);
|
|
6491
|
+
* ```
|
|
6492
|
+
*/
|
|
4207
6493
|
async usePlugins(externalTuples) {
|
|
4208
6494
|
externalTuples = externalTuples || this.context.options.plugins || [];
|
|
4209
6495
|
const plugins = await loaderPluginsFromPluginTuples(this.context, [
|
|
@@ -4218,12 +6504,65 @@ var ReleaseTask = class {
|
|
|
4218
6504
|
});
|
|
4219
6505
|
return plugins;
|
|
4220
6506
|
}
|
|
6507
|
+
/**
|
|
6508
|
+
* Executes the release task
|
|
6509
|
+
*
|
|
6510
|
+
* Internal method that runs the task through the executor.
|
|
6511
|
+
* Preserves the context through the execution chain.
|
|
6512
|
+
*
|
|
6513
|
+
* @returns Execution result
|
|
6514
|
+
* @internal
|
|
6515
|
+
*/
|
|
4221
6516
|
async run() {
|
|
4222
6517
|
return this.executor.exec(
|
|
4223
6518
|
this.context,
|
|
4224
6519
|
(context) => Promise.resolve(context)
|
|
4225
6520
|
);
|
|
4226
6521
|
}
|
|
6522
|
+
/**
|
|
6523
|
+
* Main entry point for executing the release task
|
|
6524
|
+
*
|
|
6525
|
+
* Checks environment conditions, loads plugins, and executes
|
|
6526
|
+
* the release process. Supports additional plugin configuration
|
|
6527
|
+
* at execution time.
|
|
6528
|
+
*
|
|
6529
|
+
* Environment Control:
|
|
6530
|
+
* - Checks FE_RELEASE environment variable
|
|
6531
|
+
* - Skips release if FE_RELEASE=false
|
|
6532
|
+
*
|
|
6533
|
+
* @param externalTuples - Additional plugin configurations
|
|
6534
|
+
* @returns Execution result
|
|
6535
|
+
* @throws Error if release is skipped via environment variable
|
|
6536
|
+
*
|
|
6537
|
+
* @example Basic execution
|
|
6538
|
+
* ```typescript
|
|
6539
|
+
* const task = new ReleaseTask();
|
|
6540
|
+
* await task.exec();
|
|
6541
|
+
* ```
|
|
6542
|
+
*
|
|
6543
|
+
* @example With additional plugins
|
|
6544
|
+
* ```typescript
|
|
6545
|
+
* const task = new ReleaseTask();
|
|
6546
|
+
* await task.exec([
|
|
6547
|
+
* tuple(CustomPlugin, { option: 'value' })
|
|
6548
|
+
* ]);
|
|
6549
|
+
* ```
|
|
6550
|
+
*
|
|
6551
|
+
* @example Environment control
|
|
6552
|
+
* ```typescript
|
|
6553
|
+
* // Skip release
|
|
6554
|
+
* process.env.FE_RELEASE = 'false';
|
|
6555
|
+
*
|
|
6556
|
+
* const task = new ReleaseTask();
|
|
6557
|
+
* try {
|
|
6558
|
+
* await task.exec();
|
|
6559
|
+
* } catch (e) {
|
|
6560
|
+
* if (e.message === 'Skip Release') {
|
|
6561
|
+
* console.log('Release skipped via environment variable');
|
|
6562
|
+
* }
|
|
6563
|
+
* }
|
|
6564
|
+
* ```
|
|
6565
|
+
*/
|
|
4227
6566
|
async exec(externalTuples) {
|
|
4228
6567
|
if (this.context.env.get("FE_RELEASE") === "false") {
|
|
4229
6568
|
throw new Error("Skip Release");
|