@grunnverk/tree-execution 1.5.0 → 1.5.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/context/PackageExecutionContext.d.ts +62 -0
- package/dist/context/PackageExecutionContext.d.ts.map +1 -0
- package/dist/context/PackageExecutionContext.js +106 -0
- package/dist/context/PackageExecutionContext.js.map +1 -0
- package/dist/execution/DependencyChecker.d.ts +2 -0
- package/dist/execution/DependencyChecker.d.ts.map +1 -1
- package/dist/execution/DependencyChecker.js +5 -2
- package/dist/execution/DependencyChecker.js.map +1 -1
- package/dist/execution/DynamicTaskPool.d.ts +1 -0
- package/dist/execution/DynamicTaskPool.d.ts.map +1 -1
- package/dist/execution/DynamicTaskPool.js +27 -4
- package/dist/execution/DynamicTaskPool.js.map +1 -1
- package/dist/execution/TreeExecutionAdapter.d.ts +3 -2
- package/dist/execution/TreeExecutionAdapter.d.ts.map +1 -1
- package/dist/execution/TreeExecutionAdapter.js +25 -5
- package/dist/execution/TreeExecutionAdapter.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/tree.d.ts +2 -1
- package/dist/tree.d.ts.map +1 -1
- package/dist/tree.js +49 -21
- package/dist/tree.js.map +1 -1
- package/dist/types/parallelExecution.d.ts +1 -0
- package/dist/types/parallelExecution.d.ts.map +1 -1
- package/dist/util/shellEscape.d.ts +34 -0
- package/dist/util/shellEscape.d.ts.map +1 -0
- package/dist/util/shellEscape.js +41 -0
- package/dist/util/shellEscape.js.map +1 -0
- package/package.json +5 -5
package/dist/tree.d.ts
CHANGED
|
@@ -2,11 +2,12 @@
|
|
|
2
2
|
import type { TreeExecutionConfig } from './types/config.js';
|
|
3
3
|
import type { PackageInfo } from '@grunnverk/tree-core';
|
|
4
4
|
export declare const __resetGlobalState: () => void;
|
|
5
|
-
export declare const executePackage: (packageName: string, packageInfo: PackageInfo, commandToRun: string, runConfig: TreeExecutionConfig, isDryRun: boolean, index: number, total: number, allPackageNames: Set<string>, isBuiltInCommand?: boolean) => Promise<{
|
|
5
|
+
export declare const executePackage: (packageName: string, packageInfo: PackageInfo, commandToRun: string, runConfig: TreeExecutionConfig, isDryRun: boolean, index: number, total: number, allPackageNames: Set<string>, isBuiltInCommand?: boolean, context?: any) => Promise<{
|
|
6
6
|
success: boolean;
|
|
7
7
|
error?: any;
|
|
8
8
|
isTimeoutError?: boolean;
|
|
9
9
|
skippedNoChanges?: boolean;
|
|
10
|
+
skipReason?: "no-changes" | "already-published" | "other";
|
|
10
11
|
logFile?: string;
|
|
11
12
|
}>;
|
|
12
13
|
export declare const execute: (runConfig: TreeExecutionConfig) => Promise<string>;
|
package/dist/tree.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":";AAwCA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,KAAK,EACR,WAAW,EAEd,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"tree.d.ts","sourceRoot":"","sources":["../src/tree.ts"],"names":[],"mappings":";AAwCA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,mBAAmB,CAAC;AAE7D,OAAO,KAAK,EACR,WAAW,EAEd,MAAM,sBAAsB,CAAC;AA8D9B,eAAO,MAAM,kBAAkB,YAG9B,CAAC;AAimBF,eAAO,MAAM,cAAc,GACvB,aAAa,MAAM,EACnB,aAAa,WAAW,EACxB,cAAc,MAAM,EACpB,WAAW,mBAAmB,EAC9B,UAAU,OAAO,EACjB,OAAO,MAAM,EACb,OAAO,MAAM,EACb,iBAAiB,GAAG,CAAC,MAAM,CAAC,EAC5B,mBAAkB,OAAe,EACjC,UAAU,GAAG,KACd,OAAO,CAAC;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,GAAG,CAAC;IAAC,cAAc,CAAC,EAAE,OAAO,CAAC;IAAC,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAAC,UAAU,CAAC,EAAE,YAAY,GAAG,mBAAmB,GAAG,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE,CAsc9K,CAAC;AA4HF,eAAO,MAAM,OAAO,GAAU,WAAW,mBAAmB,KAAG,OAAO,CAAC,MAAM,CA2oD5E,CAAC"}
|
package/dist/tree.js
CHANGED
|
@@ -45,6 +45,7 @@ import { getOutputPath, PerformanceTimer, isInGitRepository, runGitWithLock, opt
|
|
|
45
45
|
// Built-in commands - using stubs for now
|
|
46
46
|
// TODO: Refactor to use callbacks/dependency injection
|
|
47
47
|
import { Updates, Commit, Link, Unlink } from './util/commandStubs.js';
|
|
48
|
+
import { escapeShellArg } from './util/shellEscape.js';
|
|
48
49
|
// Define constants locally
|
|
49
50
|
const DEFAULT_OUTPUT_DIRECTORY = 'output/kodrdriv';
|
|
50
51
|
// Global state to track published versions during tree execution - protected by mutex
|
|
@@ -567,7 +568,8 @@ const formatSubprojectError = (packageName, error, _packageInfo, _position, _tot
|
|
|
567
568
|
// Note: PackageInfo, DependencyGraph, scanForPackageJsonFiles, parsePackageJson,
|
|
568
569
|
// buildDependencyGraph, and topologicalSort are now imported from ../util/dependencyGraph
|
|
569
570
|
// Execute a single package and return execution result
|
|
570
|
-
export const executePackage = async (packageName, packageInfo, commandToRun, runConfig, isDryRun, index, total, allPackageNames, isBuiltInCommand = false
|
|
571
|
+
export const executePackage = async (packageName, packageInfo, commandToRun, runConfig, isDryRun, index, total, allPackageNames, isBuiltInCommand = false, context // PackageExecutionContext - optional for backward compatibility
|
|
572
|
+
) => {
|
|
571
573
|
const packageLogger = createPackageLogger(packageName, index + 1, total, isDryRun);
|
|
572
574
|
const packageDir = packageInfo.path;
|
|
573
575
|
const logger = getLogger();
|
|
@@ -609,6 +611,7 @@ export const executePackage = async (packageName, packageInfo, commandToRun, run
|
|
|
609
611
|
}
|
|
610
612
|
// Track if publish was skipped due to no changes
|
|
611
613
|
let publishWasSkipped = false;
|
|
614
|
+
let publishSkipReason = 'no-changes';
|
|
612
615
|
// Track execution timing
|
|
613
616
|
const executionTimer = new PerformanceTimer(`Package ${packageName} execution`);
|
|
614
617
|
let executionDuration;
|
|
@@ -789,7 +792,20 @@ export const executePackage = async (packageName, packageInfo, commandToRun, run
|
|
|
789
792
|
else {
|
|
790
793
|
commandTimeoutMs = 300000; // 5 minutes default for other commands
|
|
791
794
|
}
|
|
792
|
-
|
|
795
|
+
// Pass context through environment variables for parallel execution isolation
|
|
796
|
+
const contextEnv = {};
|
|
797
|
+
if (context) {
|
|
798
|
+
contextEnv.KODRDRIV_CONTEXT_PACKAGE_NAME = context.packageName;
|
|
799
|
+
contextEnv.KODRDRIV_CONTEXT_REPOSITORY_URL = context.repositoryUrl;
|
|
800
|
+
contextEnv.KODRDRIV_CONTEXT_REPOSITORY_OWNER = context.repositoryOwner;
|
|
801
|
+
contextEnv.KODRDRIV_CONTEXT_REPOSITORY_NAME = context.repositoryName;
|
|
802
|
+
contextEnv.KODRDRIV_CONTEXT_GIT_REMOTE = context.gitRemote;
|
|
803
|
+
if (runConfig.debug) {
|
|
804
|
+
packageLogger.debug(`Using isolated execution context for ${context.packageName}`);
|
|
805
|
+
packageLogger.debug(` Repository: ${context.repositoryOwner}/${context.repositoryName}`);
|
|
806
|
+
}
|
|
807
|
+
}
|
|
808
|
+
const commandPromise = runWithLogging(effectiveCommand, packageLogger, contextEnv, showOutput, logFilePath);
|
|
793
809
|
const commandTimeoutPromise = new Promise((_, reject) => {
|
|
794
810
|
setTimeout(() => reject(new Error(`Command timed out after ${commandTimeoutMs / 60000} minutes`)), commandTimeoutMs);
|
|
795
811
|
});
|
|
@@ -804,6 +820,11 @@ export const executePackage = async (packageName, packageInfo, commandToRun, run
|
|
|
804
820
|
(stderr && stderr.includes('KODRDRIV_PUBLISH_SKIPPED')))) {
|
|
805
821
|
packageLogger.info('Publish skipped for this package; will not record or propagate a version.');
|
|
806
822
|
publishWasSkipped = true;
|
|
823
|
+
// Parse skip reason if available
|
|
824
|
+
const reasonMatch = (stdout || stderr || '').match(/KODRDRIV_PUBLISH_SKIP_REASON:(\S+)/);
|
|
825
|
+
if (reasonMatch) {
|
|
826
|
+
publishSkipReason = reasonMatch[1];
|
|
827
|
+
}
|
|
807
828
|
}
|
|
808
829
|
}
|
|
809
830
|
catch (error) {
|
|
@@ -904,7 +925,8 @@ export const executePackage = async (packageName, packageInfo, commandToRun, run
|
|
|
904
925
|
// Show completion status (for publish/commit commands, this supplements the timing message above)
|
|
905
926
|
if (runConfig.debug || runConfig.verbose) {
|
|
906
927
|
if (publishWasSkipped) {
|
|
907
|
-
|
|
928
|
+
const reasonText = publishSkipReason === 'already-published' ? 'already published' : 'no code changes';
|
|
929
|
+
packageLogger.info(`⊘ Skipped (${reasonText})`);
|
|
908
930
|
}
|
|
909
931
|
else {
|
|
910
932
|
packageLogger.info(`✅ Completed successfully`);
|
|
@@ -915,7 +937,8 @@ export const executePackage = async (packageName, packageInfo, commandToRun, run
|
|
|
915
937
|
// Include timing if available
|
|
916
938
|
const timeStr = executionDuration !== undefined ? ` (${(executionDuration / 1000).toFixed(1)}s)` : '';
|
|
917
939
|
if (publishWasSkipped) {
|
|
918
|
-
|
|
940
|
+
const reasonText = publishSkipReason === 'already-published' ? 'already published' : 'no code changes';
|
|
941
|
+
logger.info(`[${index + 1}/${total}] ${packageName}: ⊘ Skipped (${reasonText})`);
|
|
919
942
|
}
|
|
920
943
|
else {
|
|
921
944
|
logger.info(`[${index + 1}/${total}] ${packageName}: ✅ Completed${timeStr}`);
|
|
@@ -925,7 +948,12 @@ export const executePackage = async (packageName, packageInfo, commandToRun, run
|
|
|
925
948
|
if (executionDuration === undefined) {
|
|
926
949
|
executionDuration = executionTimer.end();
|
|
927
950
|
}
|
|
928
|
-
return {
|
|
951
|
+
return {
|
|
952
|
+
success: true,
|
|
953
|
+
skippedNoChanges: publishWasSkipped,
|
|
954
|
+
skipReason: publishWasSkipped ? publishSkipReason : undefined,
|
|
955
|
+
logFile: logFilePath
|
|
956
|
+
};
|
|
929
957
|
}
|
|
930
958
|
catch (error) {
|
|
931
959
|
// Record timing even on error
|
|
@@ -2011,19 +2039,19 @@ export const execute = async (runConfig) => {
|
|
|
2011
2039
|
globalOptions.push('--overrides');
|
|
2012
2040
|
// Propagate global options with values
|
|
2013
2041
|
if (runConfig.model)
|
|
2014
|
-
globalOptions.push(`--model
|
|
2042
|
+
globalOptions.push(`--model ${escapeShellArg(runConfig.model)}`);
|
|
2015
2043
|
if (runConfig.configDirectory)
|
|
2016
|
-
globalOptions.push(`--config-dir
|
|
2044
|
+
globalOptions.push(`--config-dir ${escapeShellArg(runConfig.configDirectory)}`);
|
|
2017
2045
|
if (runConfig.outputDirectory)
|
|
2018
|
-
globalOptions.push(`--output-dir
|
|
2046
|
+
globalOptions.push(`--output-dir ${escapeShellArg(runConfig.outputDirectory)}`);
|
|
2019
2047
|
if (runConfig.preferencesDirectory)
|
|
2020
|
-
globalOptions.push(`--preferences-dir
|
|
2048
|
+
globalOptions.push(`--preferences-dir ${escapeShellArg(runConfig.preferencesDirectory)}`);
|
|
2021
2049
|
// Build the command with global options
|
|
2022
2050
|
const optionsString = globalOptions.length > 0 ? ` ${globalOptions.join(' ')}` : '';
|
|
2023
2051
|
// Add package argument for link/unlink/updates commands
|
|
2024
2052
|
const packageArg = runConfig.tree?.packageArgument;
|
|
2025
2053
|
const packageArgString = (packageArg && (builtInCommand === 'link' || builtInCommand === 'unlink' || builtInCommand === 'updates'))
|
|
2026
|
-
? `
|
|
2054
|
+
? ` ${escapeShellArg(packageArg)}`
|
|
2027
2055
|
: '';
|
|
2028
2056
|
// Add command-specific options
|
|
2029
2057
|
let commandSpecificOptions = '';
|
|
@@ -2063,15 +2091,15 @@ export const execute = async (runConfig) => {
|
|
|
2063
2091
|
commandSpecificOptions += ` --max-diff-bytes ${runConfig.commit.maxDiffBytes}`;
|
|
2064
2092
|
}
|
|
2065
2093
|
if (runConfig.commit?.direction) {
|
|
2066
|
-
commandSpecificOptions += ` --direction
|
|
2094
|
+
commandSpecificOptions += ` --direction ${escapeShellArg(runConfig.commit.direction)}`;
|
|
2067
2095
|
}
|
|
2068
2096
|
if (runConfig.commit?.context) {
|
|
2069
|
-
commandSpecificOptions += ` --context
|
|
2097
|
+
commandSpecificOptions += ` --context ${escapeShellArg(runConfig.commit.context)}`;
|
|
2070
2098
|
}
|
|
2071
2099
|
// Push option can be boolean or string (remote name)
|
|
2072
2100
|
if (runConfig.commit?.push) {
|
|
2073
2101
|
if (typeof runConfig.commit.push === 'string') {
|
|
2074
|
-
commandSpecificOptions += ` --push
|
|
2102
|
+
commandSpecificOptions += ` --push ${escapeShellArg(runConfig.commit.push)}`;
|
|
2075
2103
|
}
|
|
2076
2104
|
else {
|
|
2077
2105
|
commandSpecificOptions += ' --push';
|
|
@@ -2079,7 +2107,7 @@ export const execute = async (runConfig) => {
|
|
|
2079
2107
|
}
|
|
2080
2108
|
// Model-specific options for commit
|
|
2081
2109
|
if (runConfig.commit?.model) {
|
|
2082
|
-
commandSpecificOptions += ` --model
|
|
2110
|
+
commandSpecificOptions += ` --model ${escapeShellArg(runConfig.commit.model)}`;
|
|
2083
2111
|
}
|
|
2084
2112
|
if (runConfig.commit?.openaiReasoning) {
|
|
2085
2113
|
commandSpecificOptions += ` --openai-reasoning ${runConfig.commit.openaiReasoning}`;
|
|
@@ -2103,16 +2131,16 @@ export const execute = async (runConfig) => {
|
|
|
2103
2131
|
commandSpecificOptions += ' --interactive';
|
|
2104
2132
|
}
|
|
2105
2133
|
if (runConfig.release?.from) {
|
|
2106
|
-
commandSpecificOptions += ` --from
|
|
2134
|
+
commandSpecificOptions += ` --from ${escapeShellArg(runConfig.release.from)}`;
|
|
2107
2135
|
}
|
|
2108
2136
|
if (runConfig.release?.to) {
|
|
2109
|
-
commandSpecificOptions += ` --to
|
|
2137
|
+
commandSpecificOptions += ` --to ${escapeShellArg(runConfig.release.to)}`;
|
|
2110
2138
|
}
|
|
2111
2139
|
if (runConfig.release?.focus) {
|
|
2112
|
-
commandSpecificOptions += ` --focus
|
|
2140
|
+
commandSpecificOptions += ` --focus ${escapeShellArg(runConfig.release.focus)}`;
|
|
2113
2141
|
}
|
|
2114
2142
|
if (runConfig.release?.context) {
|
|
2115
|
-
commandSpecificOptions += ` --context
|
|
2143
|
+
commandSpecificOptions += ` --context ${escapeShellArg(runConfig.release.context)}`;
|
|
2116
2144
|
}
|
|
2117
2145
|
if (runConfig.release?.messageLimit) {
|
|
2118
2146
|
commandSpecificOptions += ` --message-limit ${runConfig.release.messageLimit}`;
|
|
@@ -2128,7 +2156,7 @@ export const execute = async (runConfig) => {
|
|
|
2128
2156
|
}
|
|
2129
2157
|
// Model-specific options for release
|
|
2130
2158
|
if (runConfig.release?.model) {
|
|
2131
|
-
commandSpecificOptions += ` --model
|
|
2159
|
+
commandSpecificOptions += ` --model ${escapeShellArg(runConfig.release.model)}`;
|
|
2132
2160
|
}
|
|
2133
2161
|
if (runConfig.release?.openaiReasoning) {
|
|
2134
2162
|
commandSpecificOptions += ` --openai-reasoning ${runConfig.release.openaiReasoning}`;
|
|
@@ -2157,7 +2185,7 @@ export const execute = async (runConfig) => {
|
|
|
2157
2185
|
}
|
|
2158
2186
|
// Link/Unlink externals
|
|
2159
2187
|
if ((builtInCommand === 'link' || builtInCommand === 'unlink') && runConfig.tree?.externals && runConfig.tree.externals.length > 0) {
|
|
2160
|
-
commandSpecificOptions += ` --externals ${runConfig.tree.externals.join(' ')}`;
|
|
2188
|
+
commandSpecificOptions += ` --externals ${runConfig.tree.externals.map(e => escapeShellArg(e)).join(' ')}`;
|
|
2161
2189
|
}
|
|
2162
2190
|
commandToRun = `kodrdriv ${builtInCommand}${optionsString}${packageArgString}${commandSpecificOptions}`;
|
|
2163
2191
|
isBuiltInCommand = true;
|
|
@@ -2354,7 +2382,7 @@ export const execute = async (runConfig) => {
|
|
|
2354
2382
|
// Execute
|
|
2355
2383
|
const result = await adapter.execute();
|
|
2356
2384
|
// Format and return result
|
|
2357
|
-
const formattedResult = formatParallelResult(result);
|
|
2385
|
+
const formattedResult = formatParallelResult(result, commandToRun);
|
|
2358
2386
|
return formattedResult;
|
|
2359
2387
|
}
|
|
2360
2388
|
// Sequential execution
|