@eldrforge/kodrdriv 1.2.6 → 1.2.8

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.
@@ -3,13 +3,13 @@ import { execute as execute$1 } from './commit.js';
3
3
  import { hasStagedChanges } from '../content/diff.js';
4
4
  import { execute as execute$2 } from './release.js';
5
5
  import { getDryRunLogger, getLogger } from '../logging.js';
6
- import { runWithDryRunSupport, run, validateGitRef, runSecure } from '../util/child.js';
6
+ import { run, runSecure, runWithDryRunSupport, validateGitRef } from '../util/child.js';
7
7
  import { getCurrentBranchName, findOpenPullRequestByHeadRef, createPullRequest, waitForPullRequestChecks, mergePullRequest, createRelease, closeMilestoneForVersion, getWorkflowsTriggeredByRelease, waitForReleaseWorkflows } from '../util/github.js';
8
8
  import { create } from '../util/storage.js';
9
- import { calculateTargetVersion, checkIfTagExists, confirmVersionInteractively, getOutputPath } from '../util/general.js';
9
+ import { calculateBranchDependentVersion, calculateTargetVersion, checkIfTagExists, confirmVersionInteractively, getOutputPath } from '../util/general.js';
10
10
  import { DEFAULT_OUTPUT_DIRECTORY, KODRDRIV_DEFAULTS } from '../constants.js';
11
11
  import { safeJsonParse, validatePackageJson } from '../util/validation.js';
12
- import { safeSyncBranchWithRemote, localBranchExists, isBranchInSyncWithRemote } from '../util/git.js';
12
+ import { localBranchExists, safeSyncBranchWithRemote, isBranchInSyncWithRemote } from '../util/git.js';
13
13
 
14
14
  const scanNpmrcForEnvVars = async (storage)=>{
15
15
  const logger = getLogger();
@@ -55,7 +55,7 @@ const validateEnvironmentVariables = (requiredEnvVars, isDryRun)=>{
55
55
  }
56
56
  }
57
57
  };
58
- const runPrechecks = async (runConfig)=>{
58
+ const runPrechecks = async (runConfig, targetBranch)=>{
59
59
  var _runConfig_publish, _runConfig_publish1;
60
60
  const isDryRun = runConfig.dryRun || false;
61
61
  const logger = getDryRunLogger(isDryRun);
@@ -95,28 +95,29 @@ const runPrechecks = async (runConfig)=>{
95
95
  throw new Error(`Failed to check git status: ${originalMessage}. Please ensure you are in a valid git repository and try again.`);
96
96
  }
97
97
  }
98
+ // Use the passed target branch or fallback to config/default
99
+ const effectiveTargetBranch = targetBranch || ((_runConfig_publish = runConfig.publish) === null || _runConfig_publish === void 0 ? void 0 : _runConfig_publish.targetBranch) || 'main';
98
100
  // Check that we're not running from the target branch
99
101
  logger.info('Checking current branch...');
100
- const targetBranch = ((_runConfig_publish = runConfig.publish) === null || _runConfig_publish === void 0 ? void 0 : _runConfig_publish.targetBranch) || 'main';
101
102
  if (isDryRun) {
102
- logger.info(`Would verify current branch is not the target branch (${targetBranch})`);
103
+ logger.info(`Would verify current branch is not the target branch (${effectiveTargetBranch})`);
103
104
  } else {
104
105
  const currentBranch = await getCurrentBranchName();
105
- if (currentBranch === targetBranch) {
106
- throw new Error(`Cannot run publish from the target branch '${targetBranch}'. Please switch to a different branch before running publish.`);
106
+ if (currentBranch === effectiveTargetBranch) {
107
+ throw new Error(`Cannot run publish from the target branch '${effectiveTargetBranch}'. Please switch to a different branch before running publish.`);
107
108
  }
108
109
  }
109
110
  // Check target branch sync with remote
110
- logger.info(`Checking target branch '${targetBranch}' sync with remote...`);
111
+ logger.info(`Checking target branch '${effectiveTargetBranch}' sync with remote...`);
111
112
  if (isDryRun) {
112
- logger.info(`Would verify target branch '${targetBranch}' is in sync with remote origin`);
113
+ logger.info(`Would verify target branch '${effectiveTargetBranch}' is in sync with remote origin`);
113
114
  } else {
114
115
  // Only check if local target branch exists (it's okay if it doesn't exist locally)
115
- const targetBranchExists = await localBranchExists(targetBranch);
116
+ const targetBranchExists = await localBranchExists(effectiveTargetBranch);
116
117
  if (targetBranchExists) {
117
- const syncStatus = await isBranchInSyncWithRemote(targetBranch);
118
+ const syncStatus = await isBranchInSyncWithRemote(effectiveTargetBranch);
118
119
  if (!syncStatus.inSync) {
119
- logger.error(`❌ Target branch '${targetBranch}' is not in sync with remote.`);
120
+ logger.error(`❌ Target branch '${effectiveTargetBranch}' is not in sync with remote.`);
120
121
  logger.error('');
121
122
  if (syncStatus.error) {
122
123
  logger.error(` Error: ${syncStatus.error}`);
@@ -126,18 +127,18 @@ const runPrechecks = async (runConfig)=>{
126
127
  }
127
128
  logger.error('');
128
129
  logger.error('📋 To resolve this issue:');
129
- logger.error(` 1. Switch to the target branch: git checkout ${targetBranch}`);
130
- logger.error(` 2. Pull the latest changes: git pull origin ${targetBranch}`);
130
+ logger.error(` 1. Switch to the target branch: git checkout ${effectiveTargetBranch}`);
131
+ logger.error(` 2. Pull the latest changes: git pull origin ${effectiveTargetBranch}`);
131
132
  logger.error(' 3. Resolve any merge conflicts if they occur');
132
133
  logger.error(' 4. Switch back to your feature branch and re-run publish');
133
134
  logger.error('');
134
135
  logger.error('💡 Alternatively, run "kodrdriv publish --sync-target" to attempt automatic sync.');
135
- throw new Error(`Target branch '${targetBranch}' is not in sync with remote. Please sync the branch before running publish.`);
136
+ throw new Error(`Target branch '${effectiveTargetBranch}' is not in sync with remote. Please sync the branch before running publish.`);
136
137
  } else {
137
- logger.info(`✅ Target branch '${targetBranch}' is in sync with remote.`);
138
+ logger.info(`✅ Target branch '${effectiveTargetBranch}' is in sync with remote.`);
138
139
  }
139
140
  } else {
140
- logger.info(`ℹ️ Target branch '${targetBranch}' does not exist locally - will be created when needed.`);
141
+ logger.info(`ℹ️ Target branch '${effectiveTargetBranch}' does not exist locally - will be created when needed.`);
141
142
  }
142
143
  }
143
144
  // Check if prepublishOnly script exists in package.json
@@ -208,6 +209,22 @@ const isReleaseNecessaryComparedToTarget = async (targetBranch, isDryRun)=>{
208
209
  const logger = getDryRunLogger(isDryRun);
209
210
  // We compare current HEAD branch to the provided target branch
210
211
  const currentBranch = await getCurrentBranchName();
212
+ // Check if target branch exists before trying to compare
213
+ try {
214
+ // Validate target branch exists and is accessible
215
+ await runSecure('git', [
216
+ 'rev-parse',
217
+ '--verify',
218
+ targetBranch
219
+ ]);
220
+ } catch (error) {
221
+ // Target branch doesn't exist or isn't accessible
222
+ logger.verbose(`Target branch '${targetBranch}' does not exist or is not accessible. Proceeding with publish.`);
223
+ return {
224
+ necessary: true,
225
+ reason: `Target branch '${targetBranch}' does not exist; first release to this branch`
226
+ };
227
+ }
211
228
  // If branches are identical, nothing to release
212
229
  const { stdout: namesStdout } = await runSecure('git', [
213
230
  'diff',
@@ -268,11 +285,9 @@ const isReleaseNecessaryComparedToTarget = async (targetBranch, isDryRun)=>{
268
285
  };
269
286
  }
270
287
  };
271
- const handleTargetBranchSyncRecovery = async (runConfig)=>{
272
- var _runConfig_publish;
288
+ const handleTargetBranchSyncRecovery = async (runConfig, targetBranch)=>{
273
289
  const isDryRun = runConfig.dryRun || false;
274
290
  const logger = getDryRunLogger(isDryRun);
275
- const targetBranch = ((_runConfig_publish = runConfig.publish) === null || _runConfig_publish === void 0 ? void 0 : _runConfig_publish.targetBranch) || 'main';
276
291
  logger.info(`🔄 Attempting to sync target branch '${targetBranch}' with remote...`);
277
292
  if (isDryRun) {
278
293
  logger.info(`Would attempt to sync '${targetBranch}' with remote`);
@@ -304,14 +319,105 @@ const execute = async (runConfig)=>{
304
319
  const storage = create({
305
320
  log: logger.info
306
321
  });
307
- const targetBranch = ((_runConfig_publish = runConfig.publish) === null || _runConfig_publish === void 0 ? void 0 : _runConfig_publish.targetBranch) || 'main';
322
+ // Get current branch for branch-dependent targeting
323
+ let currentBranch;
324
+ if (isDryRun) {
325
+ currentBranch = 'mock-branch';
326
+ } else {
327
+ currentBranch = await getCurrentBranchName();
328
+ // Fetch latest remote information to avoid conflicts
329
+ logger.info('📡 Fetching latest remote information to avoid conflicts...');
330
+ try {
331
+ await run('git fetch origin');
332
+ logger.info('✅ Fetched latest remote information');
333
+ } catch (error) {
334
+ logger.warn(`⚠️ Could not fetch from remote: ${error.message}`);
335
+ }
336
+ // Sync current branch with remote to avoid conflicts
337
+ logger.info(`🔄 Syncing ${currentBranch} with remote to avoid conflicts...`);
338
+ try {
339
+ const remoteExists = await run(`git ls-remote --exit-code --heads origin ${currentBranch}`).then(()=>true).catch(()=>false);
340
+ if (remoteExists) {
341
+ await run(`git pull origin ${currentBranch} --no-edit`);
342
+ logger.info(`✅ Synced ${currentBranch} with remote`);
343
+ } else {
344
+ logger.info(`ℹ️ No remote ${currentBranch} branch found, will be created on first push`);
345
+ }
346
+ } catch (error) {
347
+ if (error.message && error.message.includes('CONFLICT')) {
348
+ logger.error(`❌ Merge conflicts detected when syncing ${currentBranch} with remote`);
349
+ logger.error(` Please resolve the conflicts manually and then run:`);
350
+ logger.error(` 1. Resolve conflicts in the files`);
351
+ logger.error(` 2. git add <resolved-files>`);
352
+ logger.error(` 3. git commit`);
353
+ logger.error(` 4. kodrdriv publish (to continue)`);
354
+ throw new Error(`Merge conflicts detected when syncing ${currentBranch} with remote. Please resolve conflicts manually.`);
355
+ } else {
356
+ logger.warn(`⚠️ Could not sync with remote ${currentBranch}: ${error.message}`);
357
+ }
358
+ }
359
+ }
360
+ // Determine target branch and version strategy based on branch configuration
361
+ let targetBranch = ((_runConfig_publish = runConfig.publish) === null || _runConfig_publish === void 0 ? void 0 : _runConfig_publish.targetBranch) || 'main';
362
+ let branchDependentVersioning = false;
363
+ // Check for branches configuration
364
+ if (runConfig.branches && runConfig.branches[currentBranch]) {
365
+ branchDependentVersioning = true;
366
+ const branchConfig = runConfig.branches[currentBranch];
367
+ if (branchConfig.targetBranch) {
368
+ targetBranch = branchConfig.targetBranch;
369
+ }
370
+ logger.info(`🎯 Branch-dependent targeting enabled:`);
371
+ logger.info(` Source branch: ${currentBranch}`);
372
+ logger.info(` Target branch: ${targetBranch}`);
373
+ // Look at target branch config to show version strategy
374
+ const targetBranchConfig = runConfig.branches[targetBranch];
375
+ if (targetBranchConfig === null || targetBranchConfig === void 0 ? void 0 : targetBranchConfig.version) {
376
+ const versionType = targetBranchConfig.version.type;
377
+ const versionTag = targetBranchConfig.version.tag;
378
+ const versionIncrement = targetBranchConfig.version.increment;
379
+ logger.info(` Target branch version strategy: ${versionType}${versionTag ? ` (tag: ${versionTag})` : ''}${versionIncrement ? ' with increment' : ''}`);
380
+ }
381
+ } else {
382
+ logger.debug(`No branch-specific targeting configured for '${currentBranch}', using default target: ${targetBranch}`);
383
+ }
308
384
  // Handle --sync-target flag
309
385
  if ((_runConfig_publish1 = runConfig.publish) === null || _runConfig_publish1 === void 0 ? void 0 : _runConfig_publish1.syncTarget) {
310
- await handleTargetBranchSyncRecovery(runConfig);
386
+ await handleTargetBranchSyncRecovery(runConfig, targetBranch);
311
387
  return; // Exit after sync operation
312
388
  }
389
+ // Check if target branch exists and create it if needed
390
+ logger.info(`Checking if target branch '${targetBranch}' exists...`);
391
+ if (isDryRun) {
392
+ logger.info(`Would check if target branch '${targetBranch}' exists and create if needed`);
393
+ } else {
394
+ const targetBranchExists = await localBranchExists(targetBranch);
395
+ if (!targetBranchExists) {
396
+ logger.info(`🌟 Target branch '${targetBranch}' does not exist, creating it from current branch...`);
397
+ try {
398
+ // Create the target branch from the current HEAD
399
+ await runSecure('git', [
400
+ 'branch',
401
+ targetBranch,
402
+ 'HEAD'
403
+ ]);
404
+ logger.info(`✅ Created target branch: ${targetBranch}`);
405
+ // Push the new branch to origin
406
+ await runSecure('git', [
407
+ 'push',
408
+ 'origin',
409
+ targetBranch
410
+ ]);
411
+ logger.info(`✅ Pushed new target branch to origin: ${targetBranch}`);
412
+ } catch (error) {
413
+ throw new Error(`Failed to create target branch '${targetBranch}': ${error.message}`);
414
+ }
415
+ } else {
416
+ logger.info(`✅ Target branch '${targetBranch}' already exists`);
417
+ }
418
+ }
313
419
  // Run prechecks before starting any work
314
- await runPrechecks(runConfig);
420
+ await runPrechecks(runConfig, targetBranch);
315
421
  // Early check: determine if a release is necessary compared to target branch
316
422
  logger.info('Evaluating if a release is necessary compared to target branch...');
317
423
  try {
@@ -377,20 +483,36 @@ const execute = async (runConfig)=>{
377
483
  logger.info('Would determine target version and update package.json');
378
484
  newVersion = '1.0.0'; // Mock version for dry run
379
485
  } else {
380
- var _runConfig_publish8, _runConfig_publish9;
486
+ var _runConfig_publish8;
381
487
  const packageJsonContents = await storage.readFile('package.json', 'utf-8');
382
488
  const parsed = safeJsonParse(packageJsonContents, 'package.json');
383
489
  const packageJson = validatePackageJson(parsed, 'package.json');
384
490
  const currentVersion = packageJson.version;
385
- const targetVersionInput = ((_runConfig_publish8 = runConfig.publish) === null || _runConfig_publish8 === void 0 ? void 0 : _runConfig_publish8.targetVersion) || 'patch';
386
- const proposedVersion = calculateTargetVersion(currentVersion, targetVersionInput);
491
+ let proposedVersion;
492
+ let finalTargetBranch = targetBranch;
493
+ if (branchDependentVersioning && runConfig.branches) {
494
+ // Use branch-dependent versioning logic
495
+ const branchDependentResult = await calculateBranchDependentVersion(currentVersion, currentBranch, runConfig.branches, targetBranch);
496
+ proposedVersion = branchDependentResult.version;
497
+ finalTargetBranch = branchDependentResult.targetBranch;
498
+ logger.info(`🎯 Branch-dependent version calculated: ${currentVersion} → ${proposedVersion}`);
499
+ logger.info(`🎯 Final target branch: ${finalTargetBranch}`);
500
+ // Update targetBranch for the rest of the function
501
+ targetBranch = finalTargetBranch;
502
+ } else {
503
+ var _runConfig_publish9;
504
+ // Use existing logic for backward compatibility
505
+ const targetVersionInput = ((_runConfig_publish9 = runConfig.publish) === null || _runConfig_publish9 === void 0 ? void 0 : _runConfig_publish9.targetVersion) || 'patch';
506
+ proposedVersion = calculateTargetVersion(currentVersion, targetVersionInput);
507
+ }
387
508
  const targetTagName = `v${proposedVersion}`;
388
509
  const tagExists = await checkIfTagExists(targetTagName);
389
510
  if (tagExists) {
390
511
  throw new Error(`Tag ${targetTagName} already exists. Please choose a different version or delete the existing tag.`);
391
512
  }
392
- if ((_runConfig_publish9 = runConfig.publish) === null || _runConfig_publish9 === void 0 ? void 0 : _runConfig_publish9.interactive) {
393
- newVersion = await confirmVersionInteractively(currentVersion, proposedVersion, targetVersionInput);
513
+ if ((_runConfig_publish8 = runConfig.publish) === null || _runConfig_publish8 === void 0 ? void 0 : _runConfig_publish8.interactive) {
514
+ var _runConfig_publish10;
515
+ newVersion = await confirmVersionInteractively(currentVersion, proposedVersion, (_runConfig_publish10 = runConfig.publish) === null || _runConfig_publish10 === void 0 ? void 0 : _runConfig_publish10.targetVersion);
394
516
  const confirmedTagName = `v${newVersion}`;
395
517
  const confirmedTagExists = await checkIfTagExists(confirmedTagName);
396
518
  if (confirmedTagExists) {
@@ -460,8 +582,8 @@ const execute = async (runConfig)=>{
460
582
  }
461
583
  logger.info('Pushing to origin...');
462
584
  // Get current branch name and push explicitly to avoid pushing to wrong remote/branch
463
- const currentBranch = await getCurrentBranchName();
464
- await runWithDryRunSupport(`git push origin ${currentBranch}`, isDryRun);
585
+ const branchName = await getCurrentBranchName();
586
+ await runWithDryRunSupport(`git push origin ${branchName}`, isDryRun);
465
587
  logger.info('Creating pull request...');
466
588
  if (isDryRun) {
467
589
  logger.info('Would get commit title and create PR with GitHub API');
@@ -472,21 +594,21 @@ const execute = async (runConfig)=>{
472
594
  };
473
595
  } else {
474
596
  const { stdout: commitTitle } = await run('git log -1 --pretty=%B');
475
- pr = await createPullRequest(commitTitle, 'Automated release PR.', await getCurrentBranchName());
597
+ pr = await createPullRequest(commitTitle, 'Automated release PR.', branchName, targetBranch);
476
598
  if (!pr) {
477
599
  throw new Error('Failed to create pull request.');
478
600
  }
479
- logger.info(`Pull request created: ${pr.html_url}`);
601
+ logger.info(`Pull request created: ${pr.html_url} (${branchName} → ${targetBranch})`);
480
602
  }
481
603
  }
482
604
  logger.info(`Waiting for PR #${pr.number} checks to complete...`);
483
605
  if (!isDryRun) {
484
- var _runConfig_publish10, _runConfig_publish11, _runConfig_publish12;
606
+ var _runConfig_publish11, _runConfig_publish12, _runConfig_publish13;
485
607
  // Configure timeout and user confirmation behavior
486
- const timeout = ((_runConfig_publish10 = runConfig.publish) === null || _runConfig_publish10 === void 0 ? void 0 : _runConfig_publish10.checksTimeout) || KODRDRIV_DEFAULTS.publish.checksTimeout;
487
- const senditMode = ((_runConfig_publish11 = runConfig.publish) === null || _runConfig_publish11 === void 0 ? void 0 : _runConfig_publish11.sendit) || false;
608
+ const timeout = ((_runConfig_publish11 = runConfig.publish) === null || _runConfig_publish11 === void 0 ? void 0 : _runConfig_publish11.checksTimeout) || KODRDRIV_DEFAULTS.publish.checksTimeout;
609
+ const senditMode = ((_runConfig_publish12 = runConfig.publish) === null || _runConfig_publish12 === void 0 ? void 0 : _runConfig_publish12.sendit) || false;
488
610
  // sendit flag overrides skipUserConfirmation - if sendit is true, skip confirmation
489
- const skipUserConfirmation = senditMode || ((_runConfig_publish12 = runConfig.publish) === null || _runConfig_publish12 === void 0 ? void 0 : _runConfig_publish12.skipUserConfirmation) || false;
611
+ const skipUserConfirmation = senditMode || ((_runConfig_publish13 = runConfig.publish) === null || _runConfig_publish13 === void 0 ? void 0 : _runConfig_publish13.skipUserConfirmation) || false;
490
612
  await waitForPullRequestChecks(pr.number, {
491
613
  timeout,
492
614
  skipUserConfirmation
@@ -518,9 +640,58 @@ const execute = async (runConfig)=>{
518
640
  }
519
641
  // Switch to target branch and pull latest changes
520
642
  logger.info(`Checking out target branch: ${targetBranch}...`);
643
+ // Check for uncommitted changes and stash them if necessary
644
+ let hasStashedChanges = false;
645
+ if (!isDryRun) {
646
+ const { stdout: statusOutput } = await runSecure('git', [
647
+ 'status',
648
+ '--porcelain'
649
+ ]);
650
+ if (statusOutput.trim()) {
651
+ logger.info('📦 Stashing uncommitted changes before checkout...');
652
+ await runSecure('git', [
653
+ 'stash',
654
+ 'push',
655
+ '-m',
656
+ 'kodrdriv: stash before checkout target branch'
657
+ ]);
658
+ hasStashedChanges = true;
659
+ logger.info('✅ Successfully stashed uncommitted changes');
660
+ }
661
+ }
521
662
  try {
522
663
  await runWithDryRunSupport(`git checkout ${targetBranch}`, isDryRun);
523
- await runWithDryRunSupport(`git pull origin ${targetBranch}`, isDryRun);
664
+ // Sync target branch with remote to avoid conflicts during PR creation
665
+ if (!isDryRun) {
666
+ logger.info(`🔄 Syncing ${targetBranch} with remote to avoid PR conflicts...`);
667
+ try {
668
+ const remoteExists = await run(`git ls-remote --exit-code --heads origin ${targetBranch}`).then(()=>true).catch(()=>false);
669
+ if (remoteExists) {
670
+ await run(`git pull origin ${targetBranch} --no-edit`);
671
+ logger.info(`✅ Synced ${targetBranch} with remote`);
672
+ } else {
673
+ logger.info(`ℹ️ No remote ${targetBranch} branch found, will be created on first push`);
674
+ }
675
+ } catch (syncError) {
676
+ if (syncError.message && syncError.message.includes('CONFLICT')) {
677
+ logger.error(`❌ Merge conflicts detected when syncing ${targetBranch} with remote`);
678
+ logger.error(` Please resolve the conflicts manually:`);
679
+ logger.error(` 1. git checkout ${targetBranch}`);
680
+ logger.error(` 2. git pull origin ${targetBranch}`);
681
+ logger.error(` 3. Resolve conflicts in the files`);
682
+ logger.error(` 4. git add <resolved-files>`);
683
+ logger.error(` 5. git commit`);
684
+ logger.error(` 6. git checkout ${currentBranch}`);
685
+ logger.error(` 7. kodrdriv publish (to continue)`);
686
+ throw syncError;
687
+ } else {
688
+ logger.warn(`⚠️ Could not sync ${targetBranch} with remote: ${syncError.message}`);
689
+ // Continue with publish process, but log the warning
690
+ }
691
+ }
692
+ } else {
693
+ logger.info(`Would sync ${targetBranch} with remote to avoid PR conflicts`);
694
+ }
524
695
  } catch (error) {
525
696
  // Check if this is a merge conflict or sync issue
526
697
  if (!isDryRun && (error.message.includes('conflict') || error.message.includes('CONFLICT') || error.message.includes('diverged') || error.message.includes('non-fast-forward'))) {
@@ -541,6 +712,20 @@ const execute = async (runConfig)=>{
541
712
  throw error;
542
713
  }
543
714
  }
715
+ // Restore stashed changes if we stashed them
716
+ if (hasStashedChanges) {
717
+ logger.info('📦 Restoring previously stashed changes...');
718
+ try {
719
+ await runSecure('git', [
720
+ 'stash',
721
+ 'pop'
722
+ ]);
723
+ logger.info('✅ Successfully restored stashed changes');
724
+ } catch (stashError) {
725
+ logger.warn(`⚠️ Warning: Could not restore stashed changes: ${stashError.message}`);
726
+ logger.warn(' Your changes are still available in the git stash. Run "git stash list" to see them.');
727
+ }
728
+ }
544
729
  // Now create and push the tag on the target branch
545
730
  logger.info('Creating release tag...');
546
731
  let tagName;
@@ -624,9 +809,9 @@ const execute = async (runConfig)=>{
624
809
  }
625
810
  logger.info('Creating GitHub release...');
626
811
  if (isDryRun) {
627
- var _runConfig_publish13;
812
+ var _runConfig_publish14;
628
813
  logger.info('Would read package.json version and create GitHub release with retry logic');
629
- const milestonesEnabled = !((_runConfig_publish13 = runConfig.publish) === null || _runConfig_publish13 === void 0 ? void 0 : _runConfig_publish13.noMilestones);
814
+ const milestonesEnabled = !((_runConfig_publish14 = runConfig.publish) === null || _runConfig_publish14 === void 0 ? void 0 : _runConfig_publish14.noMilestones);
630
815
  if (milestonesEnabled) {
631
816
  logger.info('Would close milestone for released version');
632
817
  } else {
@@ -642,11 +827,11 @@ const execute = async (runConfig)=>{
642
827
  let retries = 3;
643
828
  while(retries > 0){
644
829
  try {
645
- var _runConfig_publish14;
830
+ var _runConfig_publish15;
646
831
  await createRelease(tagName, releaseTitle, releaseNotesContent);
647
832
  logger.info(`GitHub release created successfully for tag: ${tagName}`);
648
833
  // Close milestone for this version if enabled
649
- const milestonesEnabled = !((_runConfig_publish14 = runConfig.publish) === null || _runConfig_publish14 === void 0 ? void 0 : _runConfig_publish14.noMilestones);
834
+ const milestonesEnabled = !((_runConfig_publish15 = runConfig.publish) === null || _runConfig_publish15 === void 0 ? void 0 : _runConfig_publish15.noMilestones);
650
835
  if (milestonesEnabled) {
651
836
  logger.info('🏁 Closing milestone for released version...');
652
837
  const version = tagName.replace(/^v/, ''); // Remove 'v' prefix if present
@@ -679,12 +864,12 @@ const execute = async (runConfig)=>{
679
864
  if (isDryRun) {
680
865
  logger.info('Would monitor GitHub Actions workflows triggered by release');
681
866
  } else {
682
- var _runConfig_publish15, _runConfig_publish16, _runConfig_publish17, _runConfig_publish18;
683
- const workflowTimeout = ((_runConfig_publish15 = runConfig.publish) === null || _runConfig_publish15 === void 0 ? void 0 : _runConfig_publish15.releaseWorkflowsTimeout) || KODRDRIV_DEFAULTS.publish.releaseWorkflowsTimeout;
684
- const senditMode = ((_runConfig_publish16 = runConfig.publish) === null || _runConfig_publish16 === void 0 ? void 0 : _runConfig_publish16.sendit) || false;
685
- const skipUserConfirmation = senditMode || ((_runConfig_publish17 = runConfig.publish) === null || _runConfig_publish17 === void 0 ? void 0 : _runConfig_publish17.skipUserConfirmation) || false;
867
+ var _runConfig_publish16, _runConfig_publish17, _runConfig_publish18, _runConfig_publish19;
868
+ const workflowTimeout = ((_runConfig_publish16 = runConfig.publish) === null || _runConfig_publish16 === void 0 ? void 0 : _runConfig_publish16.releaseWorkflowsTimeout) || KODRDRIV_DEFAULTS.publish.releaseWorkflowsTimeout;
869
+ const senditMode = ((_runConfig_publish17 = runConfig.publish) === null || _runConfig_publish17 === void 0 ? void 0 : _runConfig_publish17.sendit) || false;
870
+ const skipUserConfirmation = senditMode || ((_runConfig_publish18 = runConfig.publish) === null || _runConfig_publish18 === void 0 ? void 0 : _runConfig_publish18.skipUserConfirmation) || false;
686
871
  // Get workflow names - either from config or auto-detect
687
- let workflowNames = (_runConfig_publish18 = runConfig.publish) === null || _runConfig_publish18 === void 0 ? void 0 : _runConfig_publish18.releaseWorkflowNames;
872
+ let workflowNames = (_runConfig_publish19 = runConfig.publish) === null || _runConfig_publish19 === void 0 ? void 0 : _runConfig_publish19.releaseWorkflowNames;
688
873
  if (!workflowNames || workflowNames.length === 0) {
689
874
  logger.info('No specific workflow names configured, auto-detecting workflows triggered by release events...');
690
875
  try {