@grunnverk/commands-publish 1.5.7-dev.20260131223731.750cd33 → 1.5.7-dev.20260131231507.728276
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/index.js
CHANGED
|
@@ -4,13 +4,13 @@ import { createStorage, calculateTargetVersion, incrementPatchVersion as increme
|
|
|
4
4
|
import { scanForPackageJsonFiles } from '@grunnverk/tree-core';
|
|
5
5
|
import * as GitHub from '@grunnverk/github-tools';
|
|
6
6
|
import { getOctokit } from '@grunnverk/github-tools';
|
|
7
|
-
import fs, { readFile } from 'fs/promises';
|
|
7
|
+
import fs, { readFile, access } from 'fs/promises';
|
|
8
8
|
import * as path from 'path';
|
|
9
9
|
import path__default from 'path';
|
|
10
10
|
import * as Commit from '@grunnverk/commands-git';
|
|
11
11
|
import { Formatter } from '@kjerneverk/riotprompt';
|
|
12
12
|
import 'dotenv/config';
|
|
13
|
-
import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice, STANDARD_CHOICES, getLLMFeedbackInEditor, editContentInEditor, createCompletionWithRetry, createReleasePrompt
|
|
13
|
+
import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice, STANDARD_CHOICES, getLLMFeedbackInEditor, editContentInEditor, createCompletionWithRetry, createReleasePrompt } from '@grunnverk/ai-service';
|
|
14
14
|
|
|
15
15
|
/**
|
|
16
16
|
* Create retroactive working branch tags for past releases
|
|
@@ -537,6 +537,80 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
537
537
|
'examples/',
|
|
538
538
|
'test-*/'
|
|
539
539
|
];
|
|
540
|
+
/**
|
|
541
|
+
* Checks if .gitignore contains required patterns to prevent publishing
|
|
542
|
+
* development artifacts and sensitive files.
|
|
543
|
+
*/ async function checkGitignorePatterns$1(directory, checks) {
|
|
544
|
+
const logger = getLogger();
|
|
545
|
+
const gitignorePath = path.join(directory, '.gitignore');
|
|
546
|
+
// Required patterns that must be present in .gitignore
|
|
547
|
+
const requiredPatterns = [
|
|
548
|
+
'node_modules',
|
|
549
|
+
'dist',
|
|
550
|
+
'package-lock.json',
|
|
551
|
+
'.env',
|
|
552
|
+
'output/',
|
|
553
|
+
'coverage',
|
|
554
|
+
'.kodrdriv*'
|
|
555
|
+
];
|
|
556
|
+
// Check if .gitignore exists
|
|
557
|
+
try {
|
|
558
|
+
await access(gitignorePath);
|
|
559
|
+
} catch {
|
|
560
|
+
checks.gitignore.passed = false;
|
|
561
|
+
checks.gitignore.issues.push('.gitignore file not found');
|
|
562
|
+
checks.gitignore.issues.push(`Create .gitignore with patterns: ${requiredPatterns.join(', ')}`);
|
|
563
|
+
return;
|
|
564
|
+
}
|
|
565
|
+
// Read .gitignore content
|
|
566
|
+
let gitignoreContent;
|
|
567
|
+
try {
|
|
568
|
+
gitignoreContent = await readFile(gitignorePath, 'utf-8');
|
|
569
|
+
} catch (error) {
|
|
570
|
+
checks.gitignore.passed = false;
|
|
571
|
+
checks.gitignore.issues.push(`Failed to read .gitignore: ${error.message}`);
|
|
572
|
+
return;
|
|
573
|
+
}
|
|
574
|
+
// Parse .gitignore into lines, ignoring comments and empty lines
|
|
575
|
+
const gitignoreLines = gitignoreContent.split('\n').map((line)=>line.trim()).filter((line)=>line && !line.startsWith('#'));
|
|
576
|
+
// Check for missing patterns
|
|
577
|
+
const missingPatterns = [];
|
|
578
|
+
for (const pattern of requiredPatterns){
|
|
579
|
+
// Check if the pattern exists in any of the gitignore lines
|
|
580
|
+
const found = gitignoreLines.some((line)=>{
|
|
581
|
+
// Exact match
|
|
582
|
+
if (line === pattern) return true;
|
|
583
|
+
// Pattern with wildcard - check if the pattern or any matching line exists
|
|
584
|
+
if (pattern.includes('*')) {
|
|
585
|
+
const basePattern = pattern.replace('*', '');
|
|
586
|
+
// Accept exact wildcard pattern, base pattern, or any line starting with base
|
|
587
|
+
return line === pattern || line === basePattern || line.startsWith(basePattern);
|
|
588
|
+
}
|
|
589
|
+
// Pattern with trailing slash - check both with and without slash
|
|
590
|
+
if (pattern.endsWith('/')) {
|
|
591
|
+
const basePattern = pattern.slice(0, -1);
|
|
592
|
+
return line === basePattern || line === pattern || line.startsWith(pattern);
|
|
593
|
+
}
|
|
594
|
+
// Line with trailing slash - check if it matches the pattern (e.g., "node_modules/" matches "node_modules")
|
|
595
|
+
if (line.endsWith('/')) {
|
|
596
|
+
const lineBase = line.slice(0, -1);
|
|
597
|
+
return lineBase === pattern || line.startsWith(pattern + '/');
|
|
598
|
+
}
|
|
599
|
+
return false;
|
|
600
|
+
});
|
|
601
|
+
if (!found) {
|
|
602
|
+
missingPatterns.push(pattern);
|
|
603
|
+
}
|
|
604
|
+
}
|
|
605
|
+
// Report missing patterns (relaxed check - allow variations)
|
|
606
|
+
const criticalMissing = missingPatterns.filter((p)=>!p.includes('coverage') && p !== 'package-lock.json');
|
|
607
|
+
if (criticalMissing.length > 0) {
|
|
608
|
+
checks.gitignore.passed = false;
|
|
609
|
+
checks.gitignore.issues.push(`Missing required patterns: ${criticalMissing.join(', ')}`);
|
|
610
|
+
checks.gitignore.issues.push('These patterns prevent committing build artifacts and sensitive files');
|
|
611
|
+
}
|
|
612
|
+
logger.debug(`Gitignore check: ${checks.gitignore.passed ? 'passed' : 'failed'}`);
|
|
613
|
+
}
|
|
540
614
|
/**
|
|
541
615
|
* Execute check-development command
|
|
542
616
|
*/ async function execute$2(config) {
|
|
@@ -564,6 +638,10 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
564
638
|
const isTree = packageJsonFiles.length > 1;
|
|
565
639
|
logger.info(`Detected ${isTree ? 'tree' : 'single package'} with ${packageJsonFiles.length} package(s)`);
|
|
566
640
|
const checks = {
|
|
641
|
+
gitignore: {
|
|
642
|
+
passed: true,
|
|
643
|
+
issues: []
|
|
644
|
+
},
|
|
567
645
|
branch: {
|
|
568
646
|
passed: true,
|
|
569
647
|
issues: []
|
|
@@ -600,6 +678,8 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
600
678
|
const packagesToCheck = isTree ? packageJsonFiles : [
|
|
601
679
|
path.join(directory, 'package.json')
|
|
602
680
|
];
|
|
681
|
+
// Check .gitignore patterns (required for publish to succeed)
|
|
682
|
+
await checkGitignorePatterns$1(directory, checks);
|
|
603
683
|
// Build a set of all local package names for link status checking
|
|
604
684
|
const localPackageNames = new Set();
|
|
605
685
|
for (const pkgJsonPath of packagesToCheck){
|
|
@@ -683,7 +763,7 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
683
763
|
// Ignore - there might not be a merge to abort if it was a fast-forward
|
|
684
764
|
}
|
|
685
765
|
} catch (mergeError) {
|
|
686
|
-
var _mergeError_message, _mergeError_stderr;
|
|
766
|
+
var _mergeError_message, _mergeError_stderr, _mergeError_stdout;
|
|
687
767
|
// Abort any partial merge
|
|
688
768
|
try {
|
|
689
769
|
await run('git merge --abort', {
|
|
@@ -694,7 +774,7 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
694
774
|
// Ignore abort errors
|
|
695
775
|
}
|
|
696
776
|
// If merge failed, there are likely conflicts
|
|
697
|
-
if (((_mergeError_message = mergeError.message) === null || _mergeError_message === void 0 ? void 0 : _mergeError_message.includes('CONFLICT')) || ((_mergeError_stderr = mergeError.stderr) === null || _mergeError_stderr === void 0 ? void 0 : _mergeError_stderr.includes('CONFLICT'))) {
|
|
777
|
+
if (((_mergeError_message = mergeError.message) === null || _mergeError_message === void 0 ? void 0 : _mergeError_message.includes('CONFLICT')) || ((_mergeError_stderr = mergeError.stderr) === null || _mergeError_stderr === void 0 ? void 0 : _mergeError_stderr.includes('CONFLICT')) || ((_mergeError_stdout = mergeError.stdout) === null || _mergeError_stdout === void 0 ? void 0 : _mergeError_stdout.includes('CONFLICT'))) {
|
|
698
778
|
checks.mergeConflicts.passed = false;
|
|
699
779
|
checks.mergeConflicts.issues.push(`${pkgName}: Merge conflicts detected with ${targetBranch} branch`);
|
|
700
780
|
} else {
|
|
@@ -841,7 +921,7 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
841
921
|
// Build summary - linkStatus and releaseWorkflow are not included in allPassed (recommendations)
|
|
842
922
|
// mergeConflicts is ALWAYS checked (critical for preventing post-merge failures)
|
|
843
923
|
// openPRs is only checked when validateRelease is true
|
|
844
|
-
const allPassed = checks.branch.passed && checks.remoteSync.passed && checks.mergeConflicts.passed && checks.devVersion.passed && (validateRelease ? checks.openPRs.passed : true);
|
|
924
|
+
const allPassed = checks.gitignore.passed && checks.branch.passed && checks.remoteSync.passed && checks.mergeConflicts.passed && checks.devVersion.passed && (validateRelease ? checks.openPRs.passed : true);
|
|
845
925
|
const hasWarnings = checks.linkStatus.warnings.length > 0 || checks.mergeConflicts.warnings.length > 0 || checks.openPRs.warnings.length > 0 || checks.releaseWorkflow.warnings.length > 0;
|
|
846
926
|
// Log results
|
|
847
927
|
let summary = `\n${'='.repeat(60)}\n`;
|
|
@@ -852,6 +932,7 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
852
932
|
if (allPassed) {
|
|
853
933
|
summary += `✅ Status: READY FOR DEVELOPMENT\n\n`;
|
|
854
934
|
summary += `All required checks passed:\n`;
|
|
935
|
+
summary += ` ✓ Gitignore patterns\n`;
|
|
855
936
|
summary += ` ✓ Branch status\n`;
|
|
856
937
|
summary += ` ✓ Remote sync\n`;
|
|
857
938
|
summary += ` ✓ No merge conflicts with main\n`;
|
|
@@ -864,6 +945,11 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
864
945
|
}
|
|
865
946
|
} else {
|
|
866
947
|
summary += `⚠️ Status: NOT READY\n\n`;
|
|
948
|
+
if (!checks.gitignore.passed) {
|
|
949
|
+
summary += `❌ Gitignore Issues:\n`;
|
|
950
|
+
checks.gitignore.issues.forEach((issue)=>summary += ` - ${issue}\n`);
|
|
951
|
+
summary += `\n`;
|
|
952
|
+
}
|
|
867
953
|
if (!checks.branch.passed) {
|
|
868
954
|
summary += `❌ Branch Issues:\n`;
|
|
869
955
|
checks.branch.issues.forEach((issue)=>summary += ` - ${issue}\n`);
|
|
@@ -878,6 +964,13 @@ import { runAgenticRelease, requireTTY, generateReflectionReport, getUserChoice,
|
|
|
878
964
|
summary += `❌ Merge Conflict Issues:\n`;
|
|
879
965
|
checks.mergeConflicts.issues.forEach((issue)=>summary += ` - ${issue}\n`);
|
|
880
966
|
summary += `\n`;
|
|
967
|
+
summary += ` To resolve merge conflicts:\n`;
|
|
968
|
+
summary += ` 1. Fetch latest: git fetch origin main\n`;
|
|
969
|
+
summary += ` 2. Merge main into your branch: git merge origin/main\n`;
|
|
970
|
+
summary += ` 3. Resolve conflicts in your editor\n`;
|
|
971
|
+
summary += ` 4. Commit the merge: git add . && git commit\n`;
|
|
972
|
+
summary += ` 5. Run check-development again to verify\n`;
|
|
973
|
+
summary += `\n`;
|
|
881
974
|
}
|
|
882
975
|
if (!checks.devVersion.passed) {
|
|
883
976
|
summary += `❌ Dev Version Issues:\n`;
|
|
@@ -1536,7 +1629,6 @@ const runPrechecks = async (runConfig, targetBranch)=>{
|
|
|
1536
1629
|
if (targetBranchExists) {
|
|
1537
1630
|
const syncStatus = await isBranchInSyncWithRemote(effectiveTargetBranch);
|
|
1538
1631
|
if (!syncStatus.inSync) {
|
|
1539
|
-
var _runConfig_publish2;
|
|
1540
1632
|
logger.error(`BRANCH_SYNC_FAILED: Target branch not synchronized with remote | Branch: ${effectiveTargetBranch} | Status: out-of-sync | Impact: Cannot proceed with publish`);
|
|
1541
1633
|
logger.error('');
|
|
1542
1634
|
if (syncStatus.error) {
|
|
@@ -1544,48 +1636,6 @@ const runPrechecks = async (runConfig, targetBranch)=>{
|
|
|
1544
1636
|
} else if (syncStatus.localSha && syncStatus.remoteSha) {
|
|
1545
1637
|
logger.error(`BRANCH_SYNC_DIVERGENCE: Local and remote commits differ | Local SHA: ${syncStatus.localSha.substring(0, 8)} | Remote SHA: ${syncStatus.remoteSha.substring(0, 8)}`);
|
|
1546
1638
|
}
|
|
1547
|
-
// Check if agentic publish is enabled
|
|
1548
|
-
if ((_runConfig_publish2 = runConfig.publish) === null || _runConfig_publish2 === void 0 ? void 0 : _runConfig_publish2.agenticPublish) {
|
|
1549
|
-
logger.info('');
|
|
1550
|
-
logger.info('AGENTIC_PUBLISH_STARTING: Attempting automatic diagnosis and fix | Mode: agentic | Feature: AI-powered recovery');
|
|
1551
|
-
try {
|
|
1552
|
-
var _syncStatus_localSha, _syncStatus_remoteSha, _runConfig_publish3;
|
|
1553
|
-
const currentBranch = await GitHub.getCurrentBranchName();
|
|
1554
|
-
const agenticResult = await runAgenticPublish({
|
|
1555
|
-
targetBranch: effectiveTargetBranch,
|
|
1556
|
-
sourceBranch: currentBranch,
|
|
1557
|
-
issue: 'branch_sync',
|
|
1558
|
-
issueDetails: syncStatus.error || `Local SHA: ${(_syncStatus_localSha = syncStatus.localSha) === null || _syncStatus_localSha === void 0 ? void 0 : _syncStatus_localSha.substring(0, 8)}, Remote SHA: ${(_syncStatus_remoteSha = syncStatus.remoteSha) === null || _syncStatus_remoteSha === void 0 ? void 0 : _syncStatus_remoteSha.substring(0, 8)}`,
|
|
1559
|
-
workingDirectory: process.cwd(),
|
|
1560
|
-
maxIterations: ((_runConfig_publish3 = runConfig.publish) === null || _runConfig_publish3 === void 0 ? void 0 : _runConfig_publish3.agenticPublishMaxIterations) || 10,
|
|
1561
|
-
storage,
|
|
1562
|
-
logger,
|
|
1563
|
-
dryRun: runConfig.dryRun
|
|
1564
|
-
});
|
|
1565
|
-
// Display the formatted result
|
|
1566
|
-
const formattedResult = formatAgenticPublishResult(agenticResult);
|
|
1567
|
-
logger.info(formattedResult);
|
|
1568
|
-
if (agenticResult.success) {
|
|
1569
|
-
logger.info('AGENTIC_PUBLISH_SUCCESS: Issue resolved automatically | Status: ready-to-retry | Action: Re-running prechecks');
|
|
1570
|
-
// Re-run the sync check to verify it was fixed
|
|
1571
|
-
const reSyncStatus = await isBranchInSyncWithRemote(effectiveTargetBranch);
|
|
1572
|
-
if (reSyncStatus.inSync) {
|
|
1573
|
-
logger.info(`BRANCH_SYNC_VERIFIED: Target branch is now synchronized with remote | Branch: ${effectiveTargetBranch} | Status: in-sync`);
|
|
1574
|
-
return; // Continue with publish
|
|
1575
|
-
} else {
|
|
1576
|
-
logger.warn('AGENTIC_PUBLISH_VERIFICATION_FAILED: Branch still not in sync after agentic fix | Status: needs-attention');
|
|
1577
|
-
}
|
|
1578
|
-
}
|
|
1579
|
-
if (agenticResult.requiresManualIntervention) {
|
|
1580
|
-
throw new Error(`Target branch '${effectiveTargetBranch}' requires manual intervention. Please see the steps above.`);
|
|
1581
|
-
} else {
|
|
1582
|
-
throw new Error(`Agentic publish could not resolve the issue automatically. Please see the analysis above.`);
|
|
1583
|
-
}
|
|
1584
|
-
} catch (agenticError) {
|
|
1585
|
-
logger.warn(`AGENTIC_PUBLISH_FAILED: Agentic recovery failed | Error: ${agenticError.message} | Fallback: Manual steps`);
|
|
1586
|
-
// Fall through to manual steps
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
1639
|
logger.error('');
|
|
1590
1640
|
logger.error('RESOLUTION_STEPS: Manual intervention required to sync branches:');
|
|
1591
1641
|
logger.error(` Step 1: Switch to target branch | Command: git checkout ${effectiveTargetBranch}`);
|
|
@@ -1594,7 +1644,6 @@ const runPrechecks = async (runConfig, targetBranch)=>{
|
|
|
1594
1644
|
logger.error(' Step 4: Return to feature branch and retry publish');
|
|
1595
1645
|
logger.error('');
|
|
1596
1646
|
logger.error(`ALTERNATIVE_OPTION: Automatic sync available | Command: kodrdriv publish --sync-target | Branch: ${effectiveTargetBranch}`);
|
|
1597
|
-
logger.error(`ALTERNATIVE_OPTION_AI: AI-powered recovery available | Command: kodrdriv publish --agentic-publish | Branch: ${effectiveTargetBranch}`);
|
|
1598
1647
|
throw new Error(`Target branch '${effectiveTargetBranch}' is not in sync with remote. Please sync the branch before running publish.`);
|
|
1599
1648
|
} else {
|
|
1600
1649
|
logger.info(`BRANCH_SYNC_VERIFIED: Target branch is synchronized with remote | Branch: ${effectiveTargetBranch} | Status: in-sync`);
|
|
@@ -1972,8 +2021,19 @@ const execute = async (runConfig)=>{
|
|
|
1972
2021
|
}
|
|
1973
2022
|
if (pr) {
|
|
1974
2023
|
logger.info(`PR_FOUND: Existing pull request detected for current branch | URL: ${pr.html_url} | Status: open`);
|
|
2024
|
+
// Even when PR exists, we need to determine the version for tagging later
|
|
2025
|
+
logger.info('VERSION_DETERMINATION: Determining version from current package.json | Purpose: Tag creation after merge');
|
|
2026
|
+
if (!isDryRun) {
|
|
2027
|
+
const packageJsonContents = await storage.readFile('package.json', 'utf-8');
|
|
2028
|
+
const parsed = safeJsonParse(packageJsonContents, 'package.json');
|
|
2029
|
+
const packageJson = validatePackageJson(parsed, 'package.json');
|
|
2030
|
+
newVersion = packageJson.version;
|
|
2031
|
+
logger.info(`VERSION_DETECTED: Version determined from package.json | Version: ${newVersion} | Source: current working branch`);
|
|
2032
|
+
} else {
|
|
2033
|
+
newVersion = '1.0.0'; // Mock version for dry run
|
|
2034
|
+
}
|
|
1975
2035
|
} else {
|
|
1976
|
-
var _runConfig_publish4, _runConfig_publish5, _runConfig_publish6, _runConfig_publish7, _runConfig_publish8, _runConfig_publish9, _runConfig_publish10, _runConfig_publish11, _runConfig_publish12,
|
|
2036
|
+
var _runConfig_publish4, _runConfig_publish5, _runConfig_publish6, _runConfig_publish7, _runConfig_publish8, _runConfig_publish9, _runConfig_publish10, _runConfig_publish11, _runConfig_publish12, _releaseConfig_release;
|
|
1977
2037
|
logger.info('PR_NOT_FOUND: No open pull request exists for current branch | Action: Starting new release publishing process | Next: Prepare dependencies and version');
|
|
1978
2038
|
// STEP 1: Prepare for release (update dependencies and run prepublish checks) with NO version bump yet
|
|
1979
2039
|
logger.verbose('RELEASE_PREP_STARTING: Preparing for release | Phase: dependency management | Action: Switch from workspace to remote dependencies | Version Bump: Not yet applied');
|
|
@@ -2033,121 +2093,20 @@ const execute = async (runConfig)=>{
|
|
|
2033
2093
|
logger.verbose('DEPS_COMMIT_SKIPPED: No dependency changes to commit | Files: ' + filesToStage + ' | Action: Skipping commit step');
|
|
2034
2094
|
}
|
|
2035
2095
|
}
|
|
2036
|
-
// STEP 3:
|
|
2037
|
-
|
|
2038
|
-
|
|
2039
|
-
|
|
2040
|
-
|
|
2041
|
-
|
|
2042
|
-
|
|
2043
|
-
logger.info(`Would merge ${targetBranch} into current branch`);
|
|
2044
|
-
} else {
|
|
2045
|
-
// Wrap entire merge process with git lock (involves fetch, merge, checkout, add, commit)
|
|
2046
|
-
await runGitWithLock(process.cwd(), async ()=>{
|
|
2047
|
-
// Fetch the latest target branch
|
|
2048
|
-
try {
|
|
2049
|
-
await run(`git fetch origin ${targetBranch}:${targetBranch}`);
|
|
2050
|
-
logger.info(`TARGET_BRANCH_FETCHED: Successfully fetched latest target branch | Branch: ${targetBranch} | Remote: origin/${targetBranch} | Purpose: Pre-merge sync`);
|
|
2051
|
-
} catch (fetchError) {
|
|
2052
|
-
logger.warn(`TARGET_BRANCH_FETCH_FAILED: Unable to fetch target branch | Branch: ${targetBranch} | Error: ${fetchError.message} | Impact: Proceeding without merge, PR may have conflicts`);
|
|
2053
|
-
logger.warn('MERGE_SKIPPED_NO_FETCH: Continuing without pre-merge | Reason: Target branch fetch failed | Impact: PR may require manual conflict resolution');
|
|
2054
|
-
}
|
|
2055
|
-
// Check if merge is needed (avoid unnecessary merge commits)
|
|
2056
|
-
try {
|
|
2057
|
-
const { stdout: mergeBase } = await run(`git merge-base HEAD ${targetBranch}`);
|
|
2058
|
-
const { stdout: targetCommit } = await run(`git rev-parse ${targetBranch}`);
|
|
2059
|
-
if (mergeBase.trim() === targetCommit.trim()) {
|
|
2060
|
-
logger.info(`MERGE_NOT_NEEDED: Current branch already up-to-date with target | Branch: ${targetBranch} | Status: in-sync | Action: Skipping merge`);
|
|
2061
|
-
} else {
|
|
2062
|
-
// Try to merge target branch into current branch
|
|
2063
|
-
let mergeSucceeded = false;
|
|
2064
|
-
try {
|
|
2065
|
-
await run(`git merge ${targetBranch} --no-edit -m "Merge ${targetBranch} to sync before version bump"`);
|
|
2066
|
-
logger.info(`MERGE_SUCCESS: Successfully merged target branch into current branch | Target: ${targetBranch} | Purpose: Sync before version bump`);
|
|
2067
|
-
mergeSucceeded = true;
|
|
2068
|
-
} catch (mergeError) {
|
|
2069
|
-
// If merge conflicts occur, check if they're only in version-related files
|
|
2070
|
-
const errorText = [
|
|
2071
|
-
mergeError.message || '',
|
|
2072
|
-
mergeError.stdout || '',
|
|
2073
|
-
mergeError.stderr || ''
|
|
2074
|
-
].join(' ');
|
|
2075
|
-
if (errorText.includes('CONFLICT')) {
|
|
2076
|
-
logger.warn(`MERGE_CONFLICTS_DETECTED: Merge conflicts found, attempting automatic resolution | Target: ${targetBranch} | Strategy: Auto-resolve version files`);
|
|
2077
|
-
// Get list of conflicted files
|
|
2078
|
-
const { stdout: conflictedFiles } = await run('git diff --name-only --diff-filter=U');
|
|
2079
|
-
const conflicts = conflictedFiles.trim().split('\n').filter(Boolean);
|
|
2080
|
-
logger.verbose(`MERGE_CONFLICTS_LIST: Conflicted files detected | Files: ${conflicts.join(', ')} | Count: ${conflicts.length}`);
|
|
2081
|
-
// Check if conflicts are only in package.json (package-lock.json is gitignored)
|
|
2082
|
-
const versionFiles = [
|
|
2083
|
-
'package.json'
|
|
2084
|
-
];
|
|
2085
|
-
const nonVersionConflicts = conflicts.filter((f)=>!versionFiles.includes(f));
|
|
2086
|
-
if (nonVersionConflicts.length > 0) {
|
|
2087
|
-
logger.error(`MERGE_AUTO_RESOLVE_FAILED: Cannot auto-resolve conflicts in non-version files | Files: ${nonVersionConflicts.join(', ')} | Count: ${nonVersionConflicts.length} | Resolution: Manual intervention required`);
|
|
2088
|
-
logger.error('');
|
|
2089
|
-
logger.error('CONFLICT_RESOLUTION_REQUIRED: Manual steps to resolve conflicts:');
|
|
2090
|
-
logger.error(' Step 1: Resolve conflicts in the files listed above');
|
|
2091
|
-
logger.error(' Step 2: Stage resolved files | Command: git add <resolved-files>');
|
|
2092
|
-
logger.error(' Step 3: Complete merge commit | Command: git commit');
|
|
2093
|
-
logger.error(' Step 4: Resume publish process | Command: kodrdriv publish');
|
|
2094
|
-
logger.error('');
|
|
2095
|
-
throw new Error(`Merge conflicts in non-version files. Please resolve manually.`);
|
|
2096
|
-
}
|
|
2097
|
-
// Auto-resolve version conflicts by accepting current branch versions
|
|
2098
|
-
// (keep our working branch's version, which is likely already updated)
|
|
2099
|
-
logger.info(`MERGE_AUTO_RESOLVING: Automatically resolving version conflicts | Strategy: Keep current branch versions | Files: ${versionFiles.join(', ')}`);
|
|
2100
|
-
for (const file of conflicts){
|
|
2101
|
-
if (versionFiles.includes(file)) {
|
|
2102
|
-
await run(`git checkout --ours ${file}`);
|
|
2103
|
-
await run(`git add ${file}`);
|
|
2104
|
-
logger.verbose(`MERGE_FILE_RESOLVED: Resolved file using current branch version | File: ${file} | Strategy: checkout --ours`);
|
|
2105
|
-
}
|
|
2106
|
-
}
|
|
2107
|
-
// Complete the merge
|
|
2108
|
-
await run(`git commit --no-edit -m "Merge ${targetBranch} to sync before version bump (auto-resolved version conflicts)"`);
|
|
2109
|
-
logger.info(`MERGE_AUTO_RESOLVE_SUCCESS: Successfully auto-resolved version conflicts and completed merge | Target: ${targetBranch} | Files: ${versionFiles.join(', ')}`);
|
|
2110
|
-
mergeSucceeded = true;
|
|
2111
|
-
} else {
|
|
2112
|
-
// Not a conflict error, re-throw
|
|
2113
|
-
throw mergeError;
|
|
2114
|
-
}
|
|
2115
|
-
}
|
|
2116
|
-
// Only run npm install if merge actually happened
|
|
2117
|
-
if (mergeSucceeded) {
|
|
2118
|
-
// Run npm install to update package-lock.json based on merged package.json
|
|
2119
|
-
logger.info('POST_MERGE_NPM_INSTALL: Running npm install after merge | Purpose: Update package-lock.json based on merged package.json | Command: npm install');
|
|
2120
|
-
await run('npm install');
|
|
2121
|
-
logger.info('POST_MERGE_NPM_COMPLETE: npm install completed successfully | Status: Dependencies synchronized');
|
|
2122
|
-
// Commit any changes from npm install (e.g., package-lock.json updates)
|
|
2123
|
-
const { stdout: mergeChangesStatus } = await run('git status --porcelain');
|
|
2124
|
-
if (mergeChangesStatus.trim()) {
|
|
2125
|
-
logger.verbose('POST_MERGE_CHANGES_DETECTED: Changes detected after npm install | Action: Staging for commit | Command: git add');
|
|
2126
|
-
// Skip package-lock.json as it's in .gitignore to avoid private registry refs
|
|
2127
|
-
const filesToStagePostMerge = 'package.json';
|
|
2128
|
-
await run(`git add ${filesToStagePostMerge}`);
|
|
2129
|
-
if (await Diff.hasStagedChanges()) {
|
|
2130
|
-
logger.verbose('POST_MERGE_COMMIT: Committing post-merge changes | Files: ' + filesToStagePostMerge + ' | Purpose: Finalize merge');
|
|
2131
|
-
await Commit.commit(runConfig);
|
|
2132
|
-
}
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
}
|
|
2136
|
-
} catch (error) {
|
|
2137
|
-
// Only catch truly unexpected errors here
|
|
2138
|
-
logger.error(`MERGE_UNEXPECTED_ERROR: Unexpected error during merge process | Error: ${error.message} | Target: ${targetBranch} | Action: Aborting publish`);
|
|
2139
|
-
throw error;
|
|
2140
|
-
}
|
|
2141
|
-
}, `merge ${targetBranch} into current branch`);
|
|
2142
|
-
}
|
|
2143
|
-
}
|
|
2096
|
+
// STEP 3: Pre-merge target into working (REMOVED)
|
|
2097
|
+
// This step was previously used to merge target branch into working before creating PR.
|
|
2098
|
+
// It's no longer needed because:
|
|
2099
|
+
// 1. check-development already ensures branches are in sync
|
|
2100
|
+
// 2. Post-publish sync handles branch synchronization
|
|
2101
|
+
// 3. Squash merge workflow makes pre-merge unnecessary
|
|
2102
|
+
// If branches have diverged, the PR will show conflicts that need manual resolution.
|
|
2144
2103
|
// STEP 4: Determine and set target version AFTER checks, dependency commit, and target branch merge
|
|
2145
2104
|
logger.info('Determining target version...');
|
|
2146
2105
|
if (isDryRun) {
|
|
2147
2106
|
logger.info('Would determine target version and update package.json');
|
|
2148
2107
|
newVersion = '1.0.0'; // Mock version for dry run
|
|
2149
2108
|
} else {
|
|
2150
|
-
var
|
|
2109
|
+
var _runConfig_publish13;
|
|
2151
2110
|
const packageJsonContents = await storage.readFile('package.json', 'utf-8');
|
|
2152
2111
|
const parsed = safeJsonParse(packageJsonContents, 'package.json');
|
|
2153
2112
|
const packageJson = validatePackageJson(parsed, 'package.json');
|
|
@@ -2164,9 +2123,9 @@ const execute = async (runConfig)=>{
|
|
|
2164
2123
|
// Update targetBranch for the rest of the function
|
|
2165
2124
|
targetBranch = finalTargetBranch;
|
|
2166
2125
|
} else {
|
|
2167
|
-
var
|
|
2126
|
+
var _runConfig_publish14;
|
|
2168
2127
|
// Use existing logic for backward compatibility
|
|
2169
|
-
const targetVersionInput = ((
|
|
2128
|
+
const targetVersionInput = ((_runConfig_publish14 = runConfig.publish) === null || _runConfig_publish14 === void 0 ? void 0 : _runConfig_publish14.targetVersion) || 'patch';
|
|
2170
2129
|
proposedVersion = calculateTargetVersion(currentVersion, targetVersionInput);
|
|
2171
2130
|
}
|
|
2172
2131
|
const targetTagName = `v${proposedVersion}`;
|
|
@@ -2179,7 +2138,7 @@ const execute = async (runConfig)=>{
|
|
|
2179
2138
|
const npmVersion = await getNpmPublishedVersion(packageJson.name);
|
|
2180
2139
|
const tagInfo = await getTagInfo(targetTagName);
|
|
2181
2140
|
if (npmVersion === proposedVersion) {
|
|
2182
|
-
var
|
|
2141
|
+
var _runConfig_publish15;
|
|
2183
2142
|
// Version is already published on npm
|
|
2184
2143
|
logger.info(`VERSION_ALREADY_PUBLISHED: Version already published on npm registry | Version: ${proposedVersion} | Status: published | Action: Skipping`);
|
|
2185
2144
|
logger.info(`PUBLISH_SKIPPED_DUPLICATE: Skipping publish operation | Reason: Package already at target version | Version: ${proposedVersion}`);
|
|
@@ -2188,7 +2147,7 @@ const execute = async (runConfig)=>{
|
|
|
2188
2147
|
logger.info(` Option 1: Bump version | Command: npm version patch (or minor/major)`);
|
|
2189
2148
|
logger.info(` Option 2: Re-run publish | Command: kodrdriv publish`);
|
|
2190
2149
|
logger.info('');
|
|
2191
|
-
if ((
|
|
2150
|
+
if ((_runConfig_publish15 = runConfig.publish) === null || _runConfig_publish15 === void 0 ? void 0 : _runConfig_publish15.skipAlreadyPublished) {
|
|
2192
2151
|
logger.info('PUBLISH_SKIPPED_FLAG: Skipping package due to flag | Flag: --skip-already-published | Version: ' + proposedVersion + ' | Status: skipped');
|
|
2193
2152
|
// Emit skip marker for tree mode detection with reason
|
|
2194
2153
|
// eslint-disable-next-line no-console
|
|
@@ -2200,7 +2159,7 @@ const execute = async (runConfig)=>{
|
|
|
2200
2159
|
throw new Error(`Version ${proposedVersion} already published. Use --skip-already-published to continue.`);
|
|
2201
2160
|
}
|
|
2202
2161
|
} else {
|
|
2203
|
-
var _tagInfo_commit,
|
|
2162
|
+
var _tagInfo_commit, _runConfig_publish16;
|
|
2204
2163
|
// Tag exists but version not on npm - likely failed previous publish
|
|
2205
2164
|
logger.warn('');
|
|
2206
2165
|
logger.warn('PUBLISH_SITUATION_ANALYSIS: Analyzing publish conflict situation | Tag: ' + targetTagName + ' | npm: ' + (npmVersion || 'not published'));
|
|
@@ -2215,7 +2174,7 @@ const execute = async (runConfig)=>{
|
|
|
2215
2174
|
logger.warn(` Command: git tag -d ${targetTagName}`);
|
|
2216
2175
|
logger.warn(` Command: git push origin :refs/tags/${targetTagName}`);
|
|
2217
2176
|
logger.warn('');
|
|
2218
|
-
if ((
|
|
2177
|
+
if ((_runConfig_publish16 = runConfig.publish) === null || _runConfig_publish16 === void 0 ? void 0 : _runConfig_publish16.forceRepublish) {
|
|
2219
2178
|
logger.info('PUBLISH_FORCE_REPUBLISH: Force republish mode enabled | Action: Deleting existing tag | Tag: ' + targetTagName + ' | Purpose: Allow republish');
|
|
2220
2179
|
if (!isDryRun) {
|
|
2221
2180
|
const { runSecure } = await import('@grunnverk/git-tools');
|
|
@@ -2250,18 +2209,18 @@ const execute = async (runConfig)=>{
|
|
|
2250
2209
|
}
|
|
2251
2210
|
}
|
|
2252
2211
|
}
|
|
2253
|
-
if ((
|
|
2254
|
-
var
|
|
2255
|
-
newVersion = await confirmVersionInteractively(currentVersion, proposedVersion, (
|
|
2212
|
+
if ((_runConfig_publish13 = runConfig.publish) === null || _runConfig_publish13 === void 0 ? void 0 : _runConfig_publish13.interactive) {
|
|
2213
|
+
var _runConfig_publish17;
|
|
2214
|
+
newVersion = await confirmVersionInteractively(currentVersion, proposedVersion, (_runConfig_publish17 = runConfig.publish) === null || _runConfig_publish17 === void 0 ? void 0 : _runConfig_publish17.targetVersion);
|
|
2256
2215
|
const confirmedTagName = `v${newVersion}`;
|
|
2257
2216
|
const confirmedTagExists = await checkIfTagExists(confirmedTagName);
|
|
2258
2217
|
if (confirmedTagExists) {
|
|
2259
|
-
var
|
|
2218
|
+
var _runConfig_publish18;
|
|
2260
2219
|
const { getNpmPublishedVersion } = await import('@grunnverk/core');
|
|
2261
2220
|
const npmVersion = await getNpmPublishedVersion(packageJson.name);
|
|
2262
2221
|
if (npmVersion === newVersion) {
|
|
2263
2222
|
throw new Error(`Tag ${confirmedTagName} already exists and version is published on npm. Please choose a different version.`);
|
|
2264
|
-
} else if (!((
|
|
2223
|
+
} else if (!((_runConfig_publish18 = runConfig.publish) === null || _runConfig_publish18 === void 0 ? void 0 : _runConfig_publish18.forceRepublish)) {
|
|
2265
2224
|
throw new Error(`Tag ${confirmedTagName} already exists. Use --force-republish to override.`);
|
|
2266
2225
|
}
|
|
2267
2226
|
// If forceRepublish is set, we'll continue (tag will be deleted later)
|
|
@@ -2305,23 +2264,23 @@ const execute = async (runConfig)=>{
|
|
|
2305
2264
|
...runConfig.release,
|
|
2306
2265
|
currentBranch: currentBranch,
|
|
2307
2266
|
version: newVersion,
|
|
2308
|
-
...((
|
|
2267
|
+
...((_runConfig_publish7 = runConfig.publish) === null || _runConfig_publish7 === void 0 ? void 0 : _runConfig_publish7.from) && {
|
|
2309
2268
|
from: runConfig.publish.from
|
|
2310
2269
|
},
|
|
2311
|
-
...((
|
|
2270
|
+
...((_runConfig_publish8 = runConfig.publish) === null || _runConfig_publish8 === void 0 ? void 0 : _runConfig_publish8.interactive) && {
|
|
2312
2271
|
interactive: runConfig.publish.interactive
|
|
2313
2272
|
},
|
|
2314
|
-
...((
|
|
2273
|
+
...((_runConfig_publish9 = runConfig.publish) === null || _runConfig_publish9 === void 0 ? void 0 : _runConfig_publish9.fromMain) && {
|
|
2315
2274
|
fromMain: runConfig.publish.fromMain
|
|
2316
2275
|
}
|
|
2317
2276
|
};
|
|
2318
|
-
if ((
|
|
2277
|
+
if ((_runConfig_publish10 = runConfig.publish) === null || _runConfig_publish10 === void 0 ? void 0 : _runConfig_publish10.from) {
|
|
2319
2278
|
logger.verbose(`Using custom 'from' reference for release notes: ${runConfig.publish.from}`);
|
|
2320
2279
|
}
|
|
2321
|
-
if ((
|
|
2280
|
+
if ((_runConfig_publish11 = runConfig.publish) === null || _runConfig_publish11 === void 0 ? void 0 : _runConfig_publish11.interactive) {
|
|
2322
2281
|
logger.verbose('Interactive mode enabled for release notes generation');
|
|
2323
2282
|
}
|
|
2324
|
-
if ((
|
|
2283
|
+
if ((_runConfig_publish12 = runConfig.publish) === null || _runConfig_publish12 === void 0 ? void 0 : _runConfig_publish12.fromMain) {
|
|
2325
2284
|
logger.verbose('Forcing comparison against main branch for release notes');
|
|
2326
2285
|
}
|
|
2327
2286
|
// Log self-reflection settings for debugging
|
|
@@ -2386,12 +2345,12 @@ const execute = async (runConfig)=>{
|
|
|
2386
2345
|
logger.debug(`Could not verify workflow configuration for wait skip: ${error.message}`);
|
|
2387
2346
|
}
|
|
2388
2347
|
if (!shouldSkipWait) {
|
|
2389
|
-
var _runConfig_publish20, _runConfig_publish21
|
|
2348
|
+
var _runConfig_publish19, _runConfig_publish20, _runConfig_publish21;
|
|
2390
2349
|
// Configure timeout and user confirmation behavior
|
|
2391
|
-
const timeout = ((
|
|
2392
|
-
const senditMode = ((
|
|
2350
|
+
const timeout = ((_runConfig_publish19 = runConfig.publish) === null || _runConfig_publish19 === void 0 ? void 0 : _runConfig_publish19.checksTimeout) || KODRDRIV_DEFAULTS.publish.checksTimeout;
|
|
2351
|
+
const senditMode = ((_runConfig_publish20 = runConfig.publish) === null || _runConfig_publish20 === void 0 ? void 0 : _runConfig_publish20.sendit) || false;
|
|
2393
2352
|
// sendit flag overrides skipUserConfirmation - if sendit is true, skip confirmation
|
|
2394
|
-
const skipUserConfirmation = senditMode || ((
|
|
2353
|
+
const skipUserConfirmation = senditMode || ((_runConfig_publish21 = runConfig.publish) === null || _runConfig_publish21 === void 0 ? void 0 : _runConfig_publish21.skipUserConfirmation) || false;
|
|
2395
2354
|
await GitHub.waitForPullRequestChecks(pr.number, {
|
|
2396
2355
|
timeout,
|
|
2397
2356
|
skipUserConfirmation
|
|
@@ -2516,50 +2475,15 @@ const execute = async (runConfig)=>{
|
|
|
2516
2475
|
logger.warn('PUBLISH_STASH_AVAILABLE: Changes available in git stash | Command: git stash list | Purpose: View and restore manually');
|
|
2517
2476
|
}
|
|
2518
2477
|
}
|
|
2519
|
-
//
|
|
2520
|
-
//
|
|
2478
|
+
// Read the version from target branch for tag creation
|
|
2479
|
+
// After squash merge, this should match the version we set on the working branch
|
|
2521
2480
|
if (!isDryRun) {
|
|
2522
|
-
logger.info(`PUBLISH_VERSION_UPDATE_TARGET: Updating package.json on target branch to release version | Version: ${newVersion} | Branch: ${targetBranch}`);
|
|
2523
|
-
// Read current package.json on target branch
|
|
2524
2481
|
const targetPackageJsonContents = await storage.readFile('package.json', 'utf-8');
|
|
2525
2482
|
const targetPackageJson = safeJsonParse(targetPackageJsonContents, 'package.json');
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
targetPackageJson.version = newVersion;
|
|
2531
|
-
await storage.writeFile('package.json', JSON.stringify(targetPackageJson, null, 2) + '\n', 'utf-8');
|
|
2532
|
-
logger.info(`PUBLISH_VERSION_UPDATED: Updated package.json version on target branch | Version: ${newVersion} | Branch: ${targetBranch}`);
|
|
2533
|
-
// Stage and commit the version update
|
|
2534
|
-
await runGitWithLock(process.cwd(), async ()=>{
|
|
2535
|
-
await runSecure('git', [
|
|
2536
|
-
'add',
|
|
2537
|
-
'package.json'
|
|
2538
|
-
]);
|
|
2539
|
-
}, 'stage version update on target');
|
|
2540
|
-
// Check if there are staged changes before committing
|
|
2541
|
-
if (await Diff.hasStagedChanges()) {
|
|
2542
|
-
logger.info('PUBLISH_VERSION_COMMITTING: Committing version update to target branch | Purpose: Ensure tag points to correct version');
|
|
2543
|
-
await runGitWithLock(process.cwd(), async ()=>{
|
|
2544
|
-
await Commit.commit(runConfig);
|
|
2545
|
-
}, 'commit version update on target');
|
|
2546
|
-
logger.info('PUBLISH_VERSION_COMMITTED: Version update committed successfully');
|
|
2547
|
-
// Push the version update to remote
|
|
2548
|
-
logger.info(`PUBLISH_VERSION_PUSHING: Pushing version update to remote | Branch: ${targetBranch} | Remote: origin`);
|
|
2549
|
-
await runGitWithLock(process.cwd(), async ()=>{
|
|
2550
|
-
await runSecure('git', [
|
|
2551
|
-
'push',
|
|
2552
|
-
'origin',
|
|
2553
|
-
targetBranch
|
|
2554
|
-
]);
|
|
2555
|
-
}, `push version update to ${targetBranch}`);
|
|
2556
|
-
logger.info('PUBLISH_VERSION_PUSHED: Version update pushed to remote successfully');
|
|
2557
|
-
} else {
|
|
2558
|
-
logger.verbose('PUBLISH_VERSION_NO_CHANGES: No changes to commit (version already correct)');
|
|
2559
|
-
}
|
|
2560
|
-
} else {
|
|
2561
|
-
logger.info(`PUBLISH_VERSION_CORRECT: Version already correct on target branch | Version: ${newVersion} | Branch: ${targetBranch}`);
|
|
2562
|
-
}
|
|
2483
|
+
const targetVersion = targetPackageJson.version;
|
|
2484
|
+
logger.info(`PUBLISH_VERSION_TARGET: Version on target branch after merge | Version: ${targetVersion} | Branch: ${targetBranch}`);
|
|
2485
|
+
// Use the version from target branch for tagging (should match newVersion from working branch)
|
|
2486
|
+
newVersion = targetVersion;
|
|
2563
2487
|
}
|
|
2564
2488
|
// Now create and push the tag on the target branch
|
|
2565
2489
|
logger.info('Creating release tag...');
|
|
@@ -2650,9 +2574,9 @@ const execute = async (runConfig)=>{
|
|
|
2650
2574
|
}
|
|
2651
2575
|
logger.info('Creating GitHub release...');
|
|
2652
2576
|
if (isDryRun) {
|
|
2653
|
-
var
|
|
2577
|
+
var _runConfig_publish22;
|
|
2654
2578
|
logger.info('Would read package.json version and create GitHub release with retry logic');
|
|
2655
|
-
const milestonesEnabled = !((
|
|
2579
|
+
const milestonesEnabled = !((_runConfig_publish22 = runConfig.publish) === null || _runConfig_publish22 === void 0 ? void 0 : _runConfig_publish22.noMilestones);
|
|
2656
2580
|
if (milestonesEnabled) {
|
|
2657
2581
|
logger.info('Would close milestone for released version');
|
|
2658
2582
|
} else {
|
|
@@ -2668,11 +2592,11 @@ const execute = async (runConfig)=>{
|
|
|
2668
2592
|
let retries = 3;
|
|
2669
2593
|
while(retries > 0){
|
|
2670
2594
|
try {
|
|
2671
|
-
var
|
|
2595
|
+
var _runConfig_publish23;
|
|
2672
2596
|
await GitHub.createRelease(tagName, releaseTitle, releaseNotesContent);
|
|
2673
2597
|
logger.info(`GitHub release created successfully for tag: ${tagName}`);
|
|
2674
2598
|
// Close milestone for this version if enabled
|
|
2675
|
-
const milestonesEnabled = !((
|
|
2599
|
+
const milestonesEnabled = !((_runConfig_publish23 = runConfig.publish) === null || _runConfig_publish23 === void 0 ? void 0 : _runConfig_publish23.noMilestones);
|
|
2676
2600
|
if (milestonesEnabled) {
|
|
2677
2601
|
logger.info('PUBLISH_MILESTONE_CLOSING: Closing milestone for released version | Action: Close GitHub milestone | Purpose: Mark release complete');
|
|
2678
2602
|
const version = tagName.replace(/^v/, ''); // Remove 'v' prefix if present
|
|
@@ -2705,12 +2629,12 @@ const execute = async (runConfig)=>{
|
|
|
2705
2629
|
if (isDryRun) {
|
|
2706
2630
|
logger.info('Would monitor GitHub Actions workflows triggered by release');
|
|
2707
2631
|
} else {
|
|
2708
|
-
var _runConfig_publish25, _runConfig_publish26, _runConfig_publish27
|
|
2709
|
-
const workflowTimeout = ((
|
|
2710
|
-
const senditMode = ((
|
|
2711
|
-
const skipUserConfirmation = senditMode || ((
|
|
2632
|
+
var _runConfig_publish24, _runConfig_publish25, _runConfig_publish26, _runConfig_publish27;
|
|
2633
|
+
const workflowTimeout = ((_runConfig_publish24 = runConfig.publish) === null || _runConfig_publish24 === void 0 ? void 0 : _runConfig_publish24.releaseWorkflowsTimeout) || KODRDRIV_DEFAULTS.publish.releaseWorkflowsTimeout;
|
|
2634
|
+
const senditMode = ((_runConfig_publish25 = runConfig.publish) === null || _runConfig_publish25 === void 0 ? void 0 : _runConfig_publish25.sendit) || false;
|
|
2635
|
+
const skipUserConfirmation = senditMode || ((_runConfig_publish26 = runConfig.publish) === null || _runConfig_publish26 === void 0 ? void 0 : _runConfig_publish26.skipUserConfirmation) || false;
|
|
2712
2636
|
// Get workflow names - either from config or auto-detect
|
|
2713
|
-
let workflowNames = (
|
|
2637
|
+
let workflowNames = (_runConfig_publish27 = runConfig.publish) === null || _runConfig_publish27 === void 0 ? void 0 : _runConfig_publish27.releaseWorkflowNames;
|
|
2714
2638
|
if (!workflowNames || workflowNames.length === 0) {
|
|
2715
2639
|
logger.info('No specific workflow names configured, auto-detecting workflows triggered by release events...');
|
|
2716
2640
|
try {
|
|
@@ -2753,8 +2677,12 @@ const execute = async (runConfig)=>{
|
|
|
2753
2677
|
try {
|
|
2754
2678
|
// Verify that remote working branch is ancestor of main (safety check)
|
|
2755
2679
|
try {
|
|
2756
|
-
await run(`git fetch origin ${currentBranch}
|
|
2757
|
-
|
|
2680
|
+
await run(`git fetch origin ${currentBranch}`, {
|
|
2681
|
+
suppressErrorLogging: true
|
|
2682
|
+
});
|
|
2683
|
+
await run(`git merge-base --is-ancestor origin/${currentBranch} ${targetBranch}`, {
|
|
2684
|
+
suppressErrorLogging: true
|
|
2685
|
+
});
|
|
2758
2686
|
logger.verbose(`✓ Safety check passed: origin/${currentBranch} is ancestor of ${targetBranch}`);
|
|
2759
2687
|
} catch {
|
|
2760
2688
|
// Remote branch might not exist yet, or already in sync - both OK
|