@eldrforge/kodrdriv 1.2.1 → 1.2.3
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/application.js +7 -19
- package/dist/application.js.map +1 -1
- package/dist/arguments.js +345 -96
- package/dist/arguments.js.map +1 -1
- package/dist/commands/clean.js +1 -1
- package/dist/commands/clean.js.map +1 -1
- package/dist/commands/commit.js +59 -14
- package/dist/commands/commit.js.map +1 -1
- package/dist/commands/link.js +200 -11
- package/dist/commands/link.js.map +1 -1
- package/dist/commands/release.js +9 -3
- package/dist/commands/release.js.map +1 -1
- package/dist/commands/review.js +356 -145
- package/dist/commands/review.js.map +1 -1
- package/dist/commands/tree.js +111 -250
- package/dist/commands/tree.js.map +1 -1
- package/dist/commands/unlink.js +238 -10
- package/dist/commands/unlink.js.map +1 -1
- package/dist/constants.js +28 -12
- package/dist/constants.js.map +1 -1
- package/dist/content/issues.js +1 -1
- package/dist/error/CommandErrors.js +8 -1
- package/dist/error/CommandErrors.js.map +1 -1
- package/dist/prompt/commit.js +6 -0
- package/dist/prompt/commit.js.map +1 -1
- package/dist/prompt/instructions/review.md +13 -3
- package/dist/util/openai.js +70 -9
- package/dist/util/openai.js.map +1 -1
- package/dist/util/validation.js +24 -1
- package/dist/util/validation.js.map +1 -1
- package/package.json +2 -2
- package/test-external-unlink/package.json +16 -0
- package/test-externals/package.json +8 -0
- package/test-review-flow.sh +15 -0
- package/test-sort-files/alpha.md +3 -0
- package/test-sort-files/middle.txt +3 -0
- package/test-sort-files/zebra.txt +3 -0
- package/test_output.txt +161 -0
- package/dist/types.js +0 -140
- package/dist/types.js.map +0 -1
package/dist/commands/tree.js
CHANGED
|
@@ -8,7 +8,9 @@ import { create } from '../util/storage.js';
|
|
|
8
8
|
import { safeJsonParse, validatePackageJson } from '../util/validation.js';
|
|
9
9
|
import { getOutputPath } from '../util/general.js';
|
|
10
10
|
import { DEFAULT_OUTPUT_DIRECTORY } from '../constants.js';
|
|
11
|
-
import { execute as execute$
|
|
11
|
+
import { execute as execute$3 } from './commit.js';
|
|
12
|
+
import { execute as execute$1 } from './link.js';
|
|
13
|
+
import { execute as execute$2 } from './unlink.js';
|
|
12
14
|
import { getGloballyLinkedPackages, getGitStatusSummary, getLinkedDependencies, getLinkCompatibilityProblems } from '../util/git.js';
|
|
13
15
|
|
|
14
16
|
function _define_property(obj, key, value) {
|
|
@@ -495,61 +497,6 @@ const topologicalSort = (graph)=>{
|
|
|
495
497
|
logger.verbose(`Topological sort completed. Build order determined for ${result.length} packages.`);
|
|
496
498
|
return result;
|
|
497
499
|
};
|
|
498
|
-
// Group packages into dependency levels for parallel execution
|
|
499
|
-
const groupPackagesByDependencyLevels = (graph, buildOrder, runConfig)=>{
|
|
500
|
-
const logger = getLogger();
|
|
501
|
-
const { edges } = graph;
|
|
502
|
-
const levels = [];
|
|
503
|
-
const packageLevels = new Map();
|
|
504
|
-
// Calculate the dependency level for each package
|
|
505
|
-
const calculateLevel = (packageName)=>{
|
|
506
|
-
if (packageLevels.has(packageName)) {
|
|
507
|
-
return packageLevels.get(packageName);
|
|
508
|
-
}
|
|
509
|
-
const deps = edges.get(packageName) || new Set();
|
|
510
|
-
if (deps.size === 0) {
|
|
511
|
-
// No dependencies - this is level 0
|
|
512
|
-
packageLevels.set(packageName, 0);
|
|
513
|
-
if (runConfig === null || runConfig === void 0 ? void 0 : runConfig.debug) {
|
|
514
|
-
logger.debug(`${packageName}: Level 0 (no local dependencies)`);
|
|
515
|
-
}
|
|
516
|
-
return 0;
|
|
517
|
-
}
|
|
518
|
-
// Level is 1 + max level of dependencies
|
|
519
|
-
let maxDepLevel = -1;
|
|
520
|
-
for (const dep of deps){
|
|
521
|
-
const depLevel = calculateLevel(dep);
|
|
522
|
-
maxDepLevel = Math.max(maxDepLevel, depLevel);
|
|
523
|
-
}
|
|
524
|
-
const level = maxDepLevel + 1;
|
|
525
|
-
packageLevels.set(packageName, level);
|
|
526
|
-
if (runConfig === null || runConfig === void 0 ? void 0 : runConfig.debug) {
|
|
527
|
-
const depsList = Array.from(deps).join(', ');
|
|
528
|
-
logger.debug(`${packageName}: Level ${level} (depends on: ${depsList})`);
|
|
529
|
-
}
|
|
530
|
-
return level;
|
|
531
|
-
};
|
|
532
|
-
// Calculate levels for all packages
|
|
533
|
-
for (const packageName of buildOrder){
|
|
534
|
-
calculateLevel(packageName);
|
|
535
|
-
}
|
|
536
|
-
// Group packages by their levels
|
|
537
|
-
for (const packageName of buildOrder){
|
|
538
|
-
const level = packageLevels.get(packageName);
|
|
539
|
-
while(levels.length <= level){
|
|
540
|
-
levels.push([]);
|
|
541
|
-
}
|
|
542
|
-
levels[level].push(packageName);
|
|
543
|
-
}
|
|
544
|
-
// Only show grouping info if verbose or debug mode is enabled
|
|
545
|
-
if ((runConfig === null || runConfig === void 0 ? void 0 : runConfig.verbose) || (runConfig === null || runConfig === void 0 ? void 0 : runConfig.debug)) {
|
|
546
|
-
logger.verbose(`Packages grouped into ${levels.length} dependency levels for parallel execution`);
|
|
547
|
-
for(let i = 0; i < levels.length; i++){
|
|
548
|
-
logger.verbose(` Level ${i}: ${levels[i].join(', ')}`);
|
|
549
|
-
}
|
|
550
|
-
}
|
|
551
|
-
return levels;
|
|
552
|
-
};
|
|
553
500
|
// Execute a single package and return execution result
|
|
554
501
|
const executePackage = async (packageName, packageInfo, commandToRun, runConfig, isDryRun, index, total, allPackageNames, isBuiltInCommand = false)=>{
|
|
555
502
|
const packageLogger = createPackageLogger(packageName, index + 1, total, isDryRun);
|
|
@@ -573,7 +520,7 @@ const executePackage = async (packageName, packageInfo, commandToRun, runConfig,
|
|
|
573
520
|
logger.info(`[${index + 1}/${total}] ${packageName}: Running ${commandToRun}...`);
|
|
574
521
|
}
|
|
575
522
|
try {
|
|
576
|
-
if (isDryRun) {
|
|
523
|
+
if (isDryRun && !isBuiltInCommand) {
|
|
577
524
|
// Handle inter-project dependency updates for publish commands in dry run mode
|
|
578
525
|
if (isBuiltInCommand && commandToRun.includes('publish') && publishedVersions.length > 0) {
|
|
579
526
|
let mutexLocked = false;
|
|
@@ -617,15 +564,15 @@ const executePackage = async (packageName, packageInfo, commandToRun, runConfig,
|
|
|
617
564
|
if (runConfig.debug) {
|
|
618
565
|
packageLogger.debug(`Changed to directory: ${packageDir}`);
|
|
619
566
|
}
|
|
620
|
-
// Handle inter-project dependency updates for publish commands before executing
|
|
621
|
-
if (isBuiltInCommand && commandToRun.includes('publish') && publishedVersions.length > 0) {
|
|
567
|
+
// Handle inter-project dependency updates for publish commands before executing (skip during dry run)
|
|
568
|
+
if (!isDryRun && isBuiltInCommand && commandToRun.includes('publish') && publishedVersions.length > 0) {
|
|
622
569
|
packageLogger.info('Updating inter-project dependencies based on previously published packages...');
|
|
623
570
|
const hasUpdates = await updateInterProjectDependencies(packageDir, publishedVersions, allPackageNames, packageLogger, isDryRun);
|
|
624
571
|
if (hasUpdates) {
|
|
625
572
|
// Commit the dependency updates using kodrdriv commit
|
|
626
573
|
packageLogger.info('Committing inter-project dependency updates...');
|
|
627
574
|
try {
|
|
628
|
-
await execute$
|
|
575
|
+
await execute$3({
|
|
629
576
|
...runConfig,
|
|
630
577
|
dryRun: false
|
|
631
578
|
});
|
|
@@ -651,14 +598,16 @@ const executePackage = async (packageName, packageInfo, commandToRun, runConfig,
|
|
|
651
598
|
if (runConfig.debug) {
|
|
652
599
|
packageLogger.debug(`Shelling out to separate kodrdriv process for ${builtInCommandName} command`);
|
|
653
600
|
}
|
|
601
|
+
// Ensure dry-run propagates to subprocess even during overall dry-run mode
|
|
602
|
+
const effectiveCommand = runConfig.dryRun && !commandToRun.includes('--dry-run') ? `${commandToRun} --dry-run` : commandToRun;
|
|
654
603
|
// Use runWithLogging for built-in commands to capture all output
|
|
655
|
-
await runWithLogging(
|
|
604
|
+
await runWithLogging(effectiveCommand, packageLogger, {}, showOutput);
|
|
656
605
|
} else {
|
|
657
606
|
// For custom commands, use the existing logic
|
|
658
607
|
await runWithLogging(commandToRun, packageLogger, {}, showOutput);
|
|
659
608
|
}
|
|
660
|
-
// Track published version after successful publish
|
|
661
|
-
if (isBuiltInCommand && commandToRun.includes('publish')) {
|
|
609
|
+
// Track published version after successful publish (skip during dry run)
|
|
610
|
+
if (!isDryRun && isBuiltInCommand && commandToRun.includes('publish')) {
|
|
662
611
|
const publishedVersion = await extractPublishedVersion(packageDir, packageLogger);
|
|
663
612
|
if (publishedVersion) {
|
|
664
613
|
let mutexLocked = false;
|
|
@@ -717,7 +666,7 @@ const executePackage = async (packageName, packageInfo, commandToRun, runConfig,
|
|
|
717
666
|
}
|
|
718
667
|
};
|
|
719
668
|
const execute = async (runConfig)=>{
|
|
720
|
-
var _runConfig_tree, _runConfig_tree1, _runConfig_tree2;
|
|
669
|
+
var _runConfig_tree, _runConfig_tree1, _runConfig_tree2, _runConfig_tree3, _runConfig_tree4;
|
|
721
670
|
const logger = getLogger();
|
|
722
671
|
const isDryRun = runConfig.dryRun || false;
|
|
723
672
|
const isContinue = ((_runConfig_tree = runConfig.tree) === null || _runConfig_tree === void 0 ? void 0 : _runConfig_tree.continue) || false;
|
|
@@ -772,32 +721,72 @@ const execute = async (runConfig)=>{
|
|
|
772
721
|
throw new Error(`Unsupported built-in command: ${builtInCommand}. Supported commands: ${supportedBuiltInCommands.join(', ')}`);
|
|
773
722
|
}
|
|
774
723
|
// Determine the target directories - either specified or current working directory
|
|
775
|
-
const
|
|
724
|
+
const directories = ((_runConfig_tree2 = runConfig.tree) === null || _runConfig_tree2 === void 0 ? void 0 : _runConfig_tree2.directories) || [
|
|
776
725
|
process.cwd()
|
|
777
726
|
];
|
|
778
|
-
|
|
779
|
-
|
|
727
|
+
// Handle link status subcommand
|
|
728
|
+
if (builtInCommand === 'link' && ((_runConfig_tree3 = runConfig.tree) === null || _runConfig_tree3 === void 0 ? void 0 : _runConfig_tree3.packageArgument) === 'status') {
|
|
729
|
+
// For tree link status, we want to show status across all packages
|
|
730
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Running link status across workspace...`);
|
|
731
|
+
// Create a config that will be passed to the link command
|
|
732
|
+
const linkConfig = {
|
|
733
|
+
...runConfig,
|
|
734
|
+
tree: {
|
|
735
|
+
...runConfig.tree,
|
|
736
|
+
directories: directories
|
|
737
|
+
}
|
|
738
|
+
};
|
|
739
|
+
try {
|
|
740
|
+
const result = await execute$1(linkConfig, 'status');
|
|
741
|
+
return result;
|
|
742
|
+
} catch (error) {
|
|
743
|
+
logger.error(`Link status failed: ${error.message}`);
|
|
744
|
+
throw error;
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
// Handle unlink status subcommand
|
|
748
|
+
if (builtInCommand === 'unlink' && ((_runConfig_tree4 = runConfig.tree) === null || _runConfig_tree4 === void 0 ? void 0 : _runConfig_tree4.packageArgument) === 'status') {
|
|
749
|
+
// For tree unlink status, we want to show status across all packages
|
|
750
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Running unlink status across workspace...`);
|
|
751
|
+
// Create a config that will be passed to the unlink command
|
|
752
|
+
const unlinkConfig = {
|
|
753
|
+
...runConfig,
|
|
754
|
+
tree: {
|
|
755
|
+
...runConfig.tree,
|
|
756
|
+
directories: directories
|
|
757
|
+
}
|
|
758
|
+
};
|
|
759
|
+
try {
|
|
760
|
+
const result = await execute$2(unlinkConfig, 'status');
|
|
761
|
+
return result;
|
|
762
|
+
} catch (error) {
|
|
763
|
+
logger.error(`Unlink status failed: ${error.message}`);
|
|
764
|
+
throw error;
|
|
765
|
+
}
|
|
766
|
+
}
|
|
767
|
+
if (directories.length === 1) {
|
|
768
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Analyzing workspace at: ${directories[0]}`);
|
|
780
769
|
} else {
|
|
781
|
-
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Analyzing workspaces at: ${
|
|
770
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Analyzing workspaces at: ${directories.join(', ')}`);
|
|
782
771
|
}
|
|
783
772
|
try {
|
|
784
|
-
var
|
|
773
|
+
var _runConfig_tree5, _runConfig_tree6, _runConfig_tree7, _runConfig_tree8;
|
|
785
774
|
// Get exclusion patterns from config, fallback to empty array
|
|
786
|
-
const excludedPatterns = ((
|
|
775
|
+
const excludedPatterns = ((_runConfig_tree5 = runConfig.tree) === null || _runConfig_tree5 === void 0 ? void 0 : _runConfig_tree5.exclude) || [];
|
|
787
776
|
if (excludedPatterns.length > 0) {
|
|
788
777
|
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Using exclusion patterns: ${excludedPatterns.join(', ')}`);
|
|
789
778
|
}
|
|
790
779
|
// Scan for package.json files across all directories
|
|
791
780
|
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Scanning for package.json files...`);
|
|
792
781
|
let allPackageJsonPaths = [];
|
|
793
|
-
for (const targetDirectory of
|
|
782
|
+
for (const targetDirectory of directories){
|
|
794
783
|
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Scanning directory: ${targetDirectory}`);
|
|
795
784
|
const packageJsonPaths = await scanForPackageJsonFiles(targetDirectory, excludedPatterns);
|
|
796
785
|
allPackageJsonPaths = allPackageJsonPaths.concat(packageJsonPaths);
|
|
797
786
|
}
|
|
798
787
|
const packageJsonPaths = allPackageJsonPaths;
|
|
799
788
|
if (packageJsonPaths.length === 0) {
|
|
800
|
-
const directoriesStr =
|
|
789
|
+
const directoriesStr = directories.join(', ');
|
|
801
790
|
const message = `No package.json files found in subdirectories of: ${directoriesStr}`;
|
|
802
791
|
logger.warn(message);
|
|
803
792
|
return message;
|
|
@@ -810,7 +799,7 @@ const execute = async (runConfig)=>{
|
|
|
810
799
|
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Determining build order...`);
|
|
811
800
|
let buildOrder = topologicalSort(dependencyGraph);
|
|
812
801
|
// Handle start-from functionality if specified
|
|
813
|
-
const startFrom = (
|
|
802
|
+
const startFrom = (_runConfig_tree6 = runConfig.tree) === null || _runConfig_tree6 === void 0 ? void 0 : _runConfig_tree6.startFrom;
|
|
814
803
|
if (startFrom) {
|
|
815
804
|
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Looking for start package: ${startFrom}`);
|
|
816
805
|
// Find the package that matches the startFrom directory name
|
|
@@ -822,7 +811,7 @@ const execute = async (runConfig)=>{
|
|
|
822
811
|
if (startIndex === -1) {
|
|
823
812
|
// Check if the package exists but was excluded across all directories
|
|
824
813
|
let allPackageJsonPathsForCheck = [];
|
|
825
|
-
for (const targetDirectory of
|
|
814
|
+
for (const targetDirectory of directories){
|
|
826
815
|
const packageJsonPaths = await scanForPackageJsonFiles(targetDirectory, []); // No exclusions
|
|
827
816
|
allPackageJsonPathsForCheck = allPackageJsonPathsForCheck.concat(packageJsonPaths);
|
|
828
817
|
}
|
|
@@ -860,7 +849,7 @@ const execute = async (runConfig)=>{
|
|
|
860
849
|
}
|
|
861
850
|
}
|
|
862
851
|
// Handle stop-at functionality if specified
|
|
863
|
-
const stopAt = (
|
|
852
|
+
const stopAt = (_runConfig_tree7 = runConfig.tree) === null || _runConfig_tree7 === void 0 ? void 0 : _runConfig_tree7.stopAt;
|
|
864
853
|
if (stopAt) {
|
|
865
854
|
logger.verbose(`${isDryRun ? 'DRY RUN: ' : ''}Looking for stop package: ${stopAt}`);
|
|
866
855
|
// Find the package that matches the stopAt directory name
|
|
@@ -872,7 +861,7 @@ const execute = async (runConfig)=>{
|
|
|
872
861
|
if (stopIndex === -1) {
|
|
873
862
|
// Check if the package exists but was excluded across all directories
|
|
874
863
|
let allPackageJsonPathsForCheck = [];
|
|
875
|
-
for (const targetDirectory of
|
|
864
|
+
for (const targetDirectory of directories){
|
|
876
865
|
const packageJsonPaths = await scanForPackageJsonFiles(targetDirectory, []); // No exclusions
|
|
877
866
|
allPackageJsonPathsForCheck = allPackageJsonPathsForCheck.concat(packageJsonPaths);
|
|
878
867
|
}
|
|
@@ -1219,13 +1208,12 @@ const execute = async (runConfig)=>{
|
|
|
1219
1208
|
returnOutput = `\nBuild order: ${buildOrder.join(' → ')}\n`;
|
|
1220
1209
|
}
|
|
1221
1210
|
// Execute command if provided (custom command or built-in command)
|
|
1222
|
-
const cmd = (
|
|
1223
|
-
const useParallel = ((_runConfig_tree7 = runConfig.tree) === null || _runConfig_tree7 === void 0 ? void 0 : _runConfig_tree7.parallel) || false;
|
|
1211
|
+
const cmd = (_runConfig_tree8 = runConfig.tree) === null || _runConfig_tree8 === void 0 ? void 0 : _runConfig_tree8.cmd;
|
|
1224
1212
|
// Determine command to execute
|
|
1225
1213
|
let commandToRun;
|
|
1226
1214
|
let isBuiltInCommand = false;
|
|
1227
1215
|
if (builtInCommand) {
|
|
1228
|
-
var
|
|
1216
|
+
var _runConfig_tree9, _runConfig_tree10, _runConfig_tree11;
|
|
1229
1217
|
// Built-in command mode: shell out to kodrdriv subprocess
|
|
1230
1218
|
// Build command with propagated global options
|
|
1231
1219
|
const globalOptions = [];
|
|
@@ -1242,13 +1230,16 @@ const execute = async (runConfig)=>{
|
|
|
1242
1230
|
// Build the command with global options
|
|
1243
1231
|
const optionsString = globalOptions.length > 0 ? ` ${globalOptions.join(' ')}` : '';
|
|
1244
1232
|
// Add package argument for link/unlink commands
|
|
1245
|
-
const packageArg = (
|
|
1233
|
+
const packageArg = (_runConfig_tree9 = runConfig.tree) === null || _runConfig_tree9 === void 0 ? void 0 : _runConfig_tree9.packageArgument;
|
|
1246
1234
|
const packageArgString = packageArg && (builtInCommand === 'link' || builtInCommand === 'unlink') ? ` "${packageArg}"` : '';
|
|
1247
1235
|
// Add command-specific options
|
|
1248
1236
|
let commandSpecificOptions = '';
|
|
1249
|
-
if (builtInCommand === 'unlink' && ((
|
|
1237
|
+
if (builtInCommand === 'unlink' && ((_runConfig_tree10 = runConfig.tree) === null || _runConfig_tree10 === void 0 ? void 0 : _runConfig_tree10.cleanNodeModules)) {
|
|
1250
1238
|
commandSpecificOptions += ' --clean-node-modules';
|
|
1251
1239
|
}
|
|
1240
|
+
if ((builtInCommand === 'link' || builtInCommand === 'unlink') && ((_runConfig_tree11 = runConfig.tree) === null || _runConfig_tree11 === void 0 ? void 0 : _runConfig_tree11.externals) && runConfig.tree.externals.length > 0) {
|
|
1241
|
+
commandSpecificOptions += ` --externals ${runConfig.tree.externals.join(' ')}`;
|
|
1242
|
+
}
|
|
1252
1243
|
commandToRun = `kodrdriv ${builtInCommand}${optionsString}${packageArgString}${commandSpecificOptions}`;
|
|
1253
1244
|
isBuiltInCommand = true;
|
|
1254
1245
|
} else if (cmd) {
|
|
@@ -1277,8 +1268,7 @@ const execute = async (runConfig)=>{
|
|
|
1277
1268
|
// Add spacing before command execution
|
|
1278
1269
|
logger.info('');
|
|
1279
1270
|
const executionDescription = isBuiltInCommand ? `built-in command "${builtInCommand}"` : `"${commandToRun}"`;
|
|
1280
|
-
|
|
1281
|
-
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Executing ${executionDescription} in ${buildOrder.length} packages${parallelInfo}...`);
|
|
1271
|
+
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Executing ${executionDescription} in ${buildOrder.length} packages...`);
|
|
1282
1272
|
// Show info for publish commands
|
|
1283
1273
|
if (isBuiltInCommand && builtInCommand === 'publish') {
|
|
1284
1274
|
logger.info('Inter-project dependencies will be automatically updated before each publish.');
|
|
@@ -1287,176 +1277,47 @@ const execute = async (runConfig)=>{
|
|
|
1287
1277
|
let failedPackage = null;
|
|
1288
1278
|
// If continuing, start from where we left off
|
|
1289
1279
|
const startIndex = isContinue && executionContext ? executionContext.completedPackages.length : 0;
|
|
1290
|
-
|
|
1291
|
-
|
|
1292
|
-
const
|
|
1293
|
-
if (
|
|
1294
|
-
|
|
1295
|
-
|
|
1296
|
-
|
|
1297
|
-
logger.debug(` Level ${i + 1}: ${level.join(', ')} ${level.length > 1 ? '(parallel)' : '(sequential)'}`);
|
|
1298
|
-
}
|
|
1280
|
+
// Sequential execution
|
|
1281
|
+
for(let i = startIndex; i < buildOrder.length; i++){
|
|
1282
|
+
const packageName = buildOrder[i];
|
|
1283
|
+
// Skip if already completed (in continue mode)
|
|
1284
|
+
if (executionContext && executionContext.completedPackages.includes(packageName)) {
|
|
1285
|
+
successCount++;
|
|
1286
|
+
continue;
|
|
1299
1287
|
}
|
|
1300
|
-
|
|
1301
|
-
|
|
1302
|
-
|
|
1303
|
-
|
|
1304
|
-
|
|
1305
|
-
|
|
1306
|
-
|
|
1307
|
-
|
|
1308
|
-
|
|
1309
|
-
|
|
1310
|
-
|
|
1311
|
-
if (currentLevel.length === 1) {
|
|
1312
|
-
const packageName = currentLevel[0];
|
|
1313
|
-
logger.verbose(`Level ${levelIndex + 1}: Executing ${packageName}...`);
|
|
1314
|
-
} else {
|
|
1315
|
-
logger.verbose(`Level ${levelIndex + 1}: Executing ${currentLevel.length} packages in parallel: ${currentLevel.join(', ')}...`);
|
|
1316
|
-
}
|
|
1317
|
-
} else {
|
|
1318
|
-
// Basic level info
|
|
1319
|
-
if (currentLevel.length === 1) {
|
|
1320
|
-
const packageName = currentLevel[0];
|
|
1321
|
-
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Level ${levelIndex + 1}: Executing ${packageName}...`);
|
|
1322
|
-
} else {
|
|
1323
|
-
logger.info(`${isDryRun ? 'DRY RUN: ' : ''}Level ${levelIndex + 1}: Executing ${currentLevel.length} packages in parallel: ${currentLevel.join(', ')}...`);
|
|
1324
|
-
}
|
|
1325
|
-
}
|
|
1326
|
-
// Execute all packages in this level in parallel
|
|
1327
|
-
const levelPromises = currentLevel.map((packageName)=>{
|
|
1328
|
-
const packageInfo = dependencyGraph.packages.get(packageName);
|
|
1329
|
-
const globalIndex = buildOrder.indexOf(packageName);
|
|
1330
|
-
return executePackage(packageName, packageInfo, commandToRun, runConfig, isDryRun, globalIndex, buildOrder.length, allPackageNames, isBuiltInCommand);
|
|
1331
|
-
});
|
|
1332
|
-
// Wait for all packages in this level to complete
|
|
1333
|
-
const results = await Promise.allSettled(levelPromises);
|
|
1334
|
-
// Check results and handle errors
|
|
1335
|
-
for(let i = 0; i < results.length; i++){
|
|
1336
|
-
const result = results[i];
|
|
1337
|
-
const packageName = currentLevel[i];
|
|
1338
|
-
const globalIndex = buildOrder.indexOf(packageName);
|
|
1339
|
-
const packageLogger = createPackageLogger(packageName, globalIndex + 1, buildOrder.length, isDryRun);
|
|
1340
|
-
if (result.status === 'fulfilled') {
|
|
1341
|
-
if (result.value.success) {
|
|
1342
|
-
successCount++;
|
|
1343
|
-
// Add spacing between packages (except after the last one in the level)
|
|
1344
|
-
if (i < currentLevel.length - 1) {
|
|
1345
|
-
logger.info('');
|
|
1346
|
-
logger.info('');
|
|
1347
|
-
}
|
|
1348
|
-
} else {
|
|
1349
|
-
// Package failed
|
|
1350
|
-
failedPackage = packageName;
|
|
1351
|
-
const formattedError = formatSubprojectError(packageName, result.value.error);
|
|
1352
|
-
if (!isDryRun) {
|
|
1353
|
-
packageLogger.error(`Execution failed`);
|
|
1354
|
-
logger.error(formattedError);
|
|
1355
|
-
logger.error(`Failed after ${successCount} successful packages.`);
|
|
1356
|
-
const packageDir = dependencyGraph.packages.get(packageName).path;
|
|
1357
|
-
const packageDirName = path__default.basename(packageDir);
|
|
1358
|
-
logger.error(`To resume from this package, run:`);
|
|
1359
|
-
if (isBuiltInCommand) {
|
|
1360
|
-
logger.error(` kodrdriv tree ${builtInCommand} --start-from ${packageDirName}`);
|
|
1361
|
-
} else {
|
|
1362
|
-
logger.error(` kodrdriv tree --start-from ${packageDirName} --cmd "${commandToRun}"`);
|
|
1363
|
-
}
|
|
1364
|
-
throw new Error(`Command failed in package ${packageName}`);
|
|
1365
|
-
}
|
|
1366
|
-
break;
|
|
1367
|
-
}
|
|
1368
|
-
} else {
|
|
1369
|
-
// Promise was rejected
|
|
1370
|
-
failedPackage = packageName;
|
|
1371
|
-
if (!isDryRun) {
|
|
1372
|
-
packageLogger.error(`Unexpected error: ${result.reason}`);
|
|
1373
|
-
logger.error(`Failed after ${successCount} successful packages.`);
|
|
1374
|
-
const packageDir = dependencyGraph.packages.get(packageName).path;
|
|
1375
|
-
const packageDirName = path__default.basename(packageDir);
|
|
1376
|
-
logger.error(`To resume from this package, run:`);
|
|
1377
|
-
if (isBuiltInCommand) {
|
|
1378
|
-
logger.error(` kodrdriv tree ${builtInCommand} --start-from ${packageDirName}`);
|
|
1379
|
-
} else {
|
|
1380
|
-
logger.error(` kodrdriv tree --start-from ${packageDirName} --cmd "${commandToRun}"`);
|
|
1381
|
-
}
|
|
1382
|
-
throw new Error(`Unexpected error in package ${packageName}`);
|
|
1383
|
-
}
|
|
1384
|
-
break;
|
|
1385
|
-
}
|
|
1386
|
-
}
|
|
1387
|
-
// If any package failed, stop execution
|
|
1388
|
-
if (failedPackage) {
|
|
1389
|
-
break;
|
|
1390
|
-
}
|
|
1391
|
-
// Level completion logging
|
|
1392
|
-
if (runConfig.debug) {
|
|
1393
|
-
if (currentLevel.length > 1) {
|
|
1394
|
-
logger.debug(`✅ Level ${levelIndex + 1} completed: all ${currentLevel.length} packages finished successfully`);
|
|
1395
|
-
logger.debug(` Completed packages: ${currentLevel.join(', ')}`);
|
|
1396
|
-
} else if (currentLevel.length === 1 && successCount > 0) {
|
|
1397
|
-
const packageName = currentLevel[0];
|
|
1398
|
-
logger.debug(`✅ Level ${levelIndex + 1} completed: ${packageName} finished successfully`);
|
|
1399
|
-
}
|
|
1400
|
-
} else if (runConfig.verbose) {
|
|
1401
|
-
if (currentLevel.length > 1) {
|
|
1402
|
-
logger.verbose(`✅ Level ${levelIndex + 1} completed: all ${currentLevel.length} packages finished successfully`);
|
|
1403
|
-
} else if (currentLevel.length === 1 && successCount > 0) {
|
|
1404
|
-
const packageName = currentLevel[0];
|
|
1405
|
-
logger.verbose(`✅ Level ${levelIndex + 1} completed: ${packageName} finished successfully`);
|
|
1406
|
-
}
|
|
1407
|
-
} else {
|
|
1408
|
-
// Basic completion info
|
|
1409
|
-
if (currentLevel.length > 1) {
|
|
1410
|
-
logger.info(`✅ Level ${levelIndex + 1} completed: all ${currentLevel.length} packages finished successfully`);
|
|
1411
|
-
} else if (currentLevel.length === 1 && successCount > 0) {
|
|
1412
|
-
const packageName = currentLevel[0];
|
|
1413
|
-
logger.info(`✅ Level ${levelIndex + 1} completed: ${packageName} finished successfully`);
|
|
1414
|
-
}
|
|
1288
|
+
const packageInfo = dependencyGraph.packages.get(packageName);
|
|
1289
|
+
const packageLogger = createPackageLogger(packageName, i + 1, buildOrder.length, isDryRun);
|
|
1290
|
+
const result = await executePackage(packageName, packageInfo, commandToRun, runConfig, isDryRun, i, buildOrder.length, allPackageNames, isBuiltInCommand);
|
|
1291
|
+
if (result.success) {
|
|
1292
|
+
successCount++;
|
|
1293
|
+
// Update context
|
|
1294
|
+
if (executionContext && isBuiltInCommand && builtInCommand === 'publish' && !isDryRun) {
|
|
1295
|
+
executionContext.completedPackages.push(packageName);
|
|
1296
|
+
executionContext.publishedVersions = publishedVersions;
|
|
1297
|
+
executionContext.lastUpdateTime = new Date();
|
|
1298
|
+
await saveExecutionContext(executionContext, runConfig.outputDirectory);
|
|
1415
1299
|
}
|
|
1416
|
-
|
|
1417
|
-
|
|
1418
|
-
|
|
1419
|
-
|
|
1420
|
-
const packageName = buildOrder[i];
|
|
1421
|
-
// Skip if already completed (in continue mode)
|
|
1422
|
-
if (executionContext && executionContext.completedPackages.includes(packageName)) {
|
|
1423
|
-
successCount++;
|
|
1424
|
-
continue;
|
|
1300
|
+
// Add spacing between packages (except after the last one)
|
|
1301
|
+
if (i < buildOrder.length - 1) {
|
|
1302
|
+
logger.info('');
|
|
1303
|
+
logger.info('');
|
|
1425
1304
|
}
|
|
1426
|
-
|
|
1427
|
-
|
|
1428
|
-
const
|
|
1429
|
-
if (
|
|
1430
|
-
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1434
|
-
|
|
1435
|
-
|
|
1436
|
-
|
|
1437
|
-
|
|
1438
|
-
// Add spacing between packages (except after the last one)
|
|
1439
|
-
if (i < buildOrder.length - 1) {
|
|
1440
|
-
logger.info('');
|
|
1441
|
-
logger.info('');
|
|
1442
|
-
}
|
|
1443
|
-
} else {
|
|
1444
|
-
failedPackage = packageName;
|
|
1445
|
-
const formattedError = formatSubprojectError(packageName, result.error);
|
|
1446
|
-
if (!isDryRun) {
|
|
1447
|
-
packageLogger.error(`Execution failed`);
|
|
1448
|
-
logger.error(formattedError);
|
|
1449
|
-
logger.error(`Failed after ${successCount} successful packages.`);
|
|
1450
|
-
logger.error(`To resume from this point, run:`);
|
|
1451
|
-
if (isBuiltInCommand) {
|
|
1452
|
-
logger.error(` kodrdriv tree ${builtInCommand} --continue`);
|
|
1453
|
-
} else {
|
|
1454
|
-
logger.error(` kodrdriv tree --continue --cmd "${commandToRun}"`);
|
|
1455
|
-
}
|
|
1456
|
-
throw new Error(`Command failed in package ${packageName}`);
|
|
1305
|
+
} else {
|
|
1306
|
+
failedPackage = packageName;
|
|
1307
|
+
const formattedError = formatSubprojectError(packageName, result.error);
|
|
1308
|
+
if (!isDryRun) {
|
|
1309
|
+
packageLogger.error(`Execution failed`);
|
|
1310
|
+
logger.error(formattedError);
|
|
1311
|
+
logger.error(`Failed after ${successCount} successful packages.`);
|
|
1312
|
+
logger.error(`To resume from this point, run:`);
|
|
1313
|
+
if (isBuiltInCommand) {
|
|
1314
|
+
logger.error(` kodrdriv tree ${builtInCommand} --continue`);
|
|
1315
|
+
} else {
|
|
1316
|
+
logger.error(` kodrdriv tree --continue --cmd "${commandToRun}"`);
|
|
1457
1317
|
}
|
|
1458
|
-
|
|
1318
|
+
throw new Error(`Command failed in package ${packageName}`);
|
|
1459
1319
|
}
|
|
1320
|
+
break;
|
|
1460
1321
|
}
|
|
1461
1322
|
}
|
|
1462
1323
|
if (!failedPackage) {
|
|
@@ -1475,8 +1336,8 @@ const execute = async (runConfig)=>{
|
|
|
1475
1336
|
logger.error(errorMessage);
|
|
1476
1337
|
throw new Error(errorMessage);
|
|
1477
1338
|
} finally{
|
|
1478
|
-
|
|
1479
|
-
|
|
1339
|
+
// Intentionally preserve the mutex across executions to support multiple runs in the same process (e.g., test suite)
|
|
1340
|
+
// Do not destroy here; the process lifecycle will clean up resources.
|
|
1480
1341
|
}
|
|
1481
1342
|
};
|
|
1482
1343
|
|