scripts-orchestrator 2.8.0 ā 2.9.0
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/README.md +55 -0
- package/index.js +11 -1
- package/lib/logger.js +13 -0
- package/lib/orchestrator.js +45 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -26,6 +26,7 @@ npm install --save-dev scripts-orchestrator
|
|
|
26
26
|
## Features
|
|
27
27
|
|
|
28
28
|
- **Parallel Execution**: Runs multiple commands concurrently for faster execution
|
|
29
|
+
- **Sequential Mode**: Option to run all commands sequentially for low CPU machines
|
|
29
30
|
- **Dependency Management**: Handles command dependencies and ensures proper execution order
|
|
30
31
|
- **Background Processes**: Supports running commands in the background with health checks
|
|
31
32
|
- **Retry Mechanism**: Configurable retry attempts for failed commands
|
|
@@ -256,6 +257,12 @@ The orchestrator doesn't care what the commands do - it just ensures they run (i
|
|
|
256
257
|
|
|
257
258
|
# Run with verbose logging
|
|
258
259
|
npm run scripts-orchestrator -- --verbose
|
|
260
|
+
|
|
261
|
+
# Run in sequential mode (for low CPU machines)
|
|
262
|
+
npm run scripts-orchestrator -- --sequential
|
|
263
|
+
|
|
264
|
+
# Specify a custom log folder
|
|
265
|
+
npm run scripts-orchestrator -- --logFolder ./custom-logs
|
|
259
266
|
```
|
|
260
267
|
|
|
261
268
|
### Starting from a Specific Phase
|
|
@@ -338,6 +345,29 @@ npm run scripts-orchestrator -- --phases "build,test,optional-e2e,optional-perfo
|
|
|
338
345
|
- The orchestrator validates that all specified phases exist
|
|
339
346
|
- Commands in skipped optional phases are marked as "skipped" in the final summary
|
|
340
347
|
|
|
348
|
+
### Sequential Mode
|
|
349
|
+
|
|
350
|
+
By default, the orchestrator runs commands within each phase in parallel for optimal performance. However, you can use the `--sequential` flag to run all commands sequentially, which is useful for low CPU machines or when you need to reduce resource consumption.
|
|
351
|
+
|
|
352
|
+
#### Usage
|
|
353
|
+
```bash
|
|
354
|
+
# Run all commands sequentially instead of in parallel
|
|
355
|
+
npm run scripts-orchestrator -- --sequential
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
When running in sequential mode:
|
|
359
|
+
- Commands within each phase are executed one at a time
|
|
360
|
+
- Phases still run sequentially (as they always do)
|
|
361
|
+
- If a command fails, the remaining commands in that phase are skipped
|
|
362
|
+
- Lower CPU and memory usage compared to parallel execution
|
|
363
|
+
- Longer total execution time
|
|
364
|
+
|
|
365
|
+
This is particularly useful for:
|
|
366
|
+
- CI/CD environments with limited resources
|
|
367
|
+
- Development machines with low CPU/memory
|
|
368
|
+
- Debugging individual command failures
|
|
369
|
+
- Avoiding resource contention between commands
|
|
370
|
+
|
|
341
371
|
## Error Handling
|
|
342
372
|
|
|
343
373
|
- The script tracks failed and skipped commands
|
|
@@ -348,10 +378,35 @@ npm run scripts-orchestrator -- --phases "build,test,optional-e2e,optional-perfo
|
|
|
348
378
|
## Logging
|
|
349
379
|
|
|
350
380
|
- Each command's output is logged to `scripts-orchestrator-logs/<command>.log` in the current working directory
|
|
381
|
+
- Main orchestrator logs are saved to `scripts-orchestrator-logs/orchestrator-main-<timestamp>.log`
|
|
351
382
|
- Git commit hash is cached in `scripts-orchestrator-logs/.git-hash-cache` for skip detection
|
|
352
383
|
- Provides real-time status updates during execution
|
|
353
384
|
- Summarizes results at the end of execution
|
|
354
385
|
|
|
386
|
+
### Custom Log Folder
|
|
387
|
+
|
|
388
|
+
You can customize the log folder location using either the command line or configuration file:
|
|
389
|
+
|
|
390
|
+
#### Method 1: Command Line Argument
|
|
391
|
+
```bash
|
|
392
|
+
# Use a custom log folder
|
|
393
|
+
npm run scripts-orchestrator -- --logFolder ./my-custom-logs
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
#### Method 2: Configuration File
|
|
397
|
+
```javascript
|
|
398
|
+
export default {
|
|
399
|
+
log_folder: './my-custom-logs', // Custom log folder
|
|
400
|
+
phases: [
|
|
401
|
+
// ... your phases
|
|
402
|
+
]
|
|
403
|
+
};
|
|
404
|
+
```
|
|
405
|
+
|
|
406
|
+
**Note**: Command line arguments take precedence over configuration file settings.
|
|
407
|
+
|
|
408
|
+
All logs (command logs, main orchestrator logs, and git cache) will be stored in the specified folder.
|
|
409
|
+
|
|
355
410
|
## Git-Based Caching
|
|
356
411
|
|
|
357
412
|
The orchestrator automatically tracks the git commit hash and repository state to optimize execution:
|
package/index.js
CHANGED
|
@@ -31,6 +31,10 @@ const argv = yargs(hideBin(process.argv))
|
|
|
31
31
|
type: 'string',
|
|
32
32
|
description: 'Specify the directory for log files',
|
|
33
33
|
})
|
|
34
|
+
.option('sequential', {
|
|
35
|
+
type: 'boolean',
|
|
36
|
+
description: 'Run all commands sequentially instead of in parallel (for low CPU machines)',
|
|
37
|
+
})
|
|
34
38
|
.help()
|
|
35
39
|
.alias('h', 'help')
|
|
36
40
|
.parse();
|
|
@@ -41,6 +45,7 @@ const configPath = args[0] || './scripts-orchestrator.config.js';
|
|
|
41
45
|
let startPhase = argv.phase;
|
|
42
46
|
let logFolder = argv.logFolder;
|
|
43
47
|
const phases = argv.phases ? argv.phases.split(',').map(p => p.trim()) : null;
|
|
48
|
+
const sequential = argv.sequential || false;
|
|
44
49
|
|
|
45
50
|
// Validate config file exists
|
|
46
51
|
if (!fs.existsSync(configPath)) {
|
|
@@ -64,8 +69,13 @@ if (!logFolder && commandsConfig.log_folder) {
|
|
|
64
69
|
logFolder = commandsConfig.log_folder;
|
|
65
70
|
}
|
|
66
71
|
|
|
72
|
+
// Set the log folder for the main orchestrator logs if specified
|
|
73
|
+
if (logFolder) {
|
|
74
|
+
log.setLogFolder(logFolder);
|
|
75
|
+
}
|
|
76
|
+
|
|
67
77
|
// Create and run the orchestrator
|
|
68
|
-
const orchestrator = new Orchestrator(commandsConfig, startPhase, logFolder, phases);
|
|
78
|
+
const orchestrator = new Orchestrator(commandsConfig, startPhase, logFolder, phases, sequential);
|
|
69
79
|
|
|
70
80
|
// Enhanced signal handlers
|
|
71
81
|
const handleSignal = async (signal) => {
|
package/lib/logger.js
CHANGED
|
@@ -66,6 +66,19 @@ class Logger {
|
|
|
66
66
|
}
|
|
67
67
|
}
|
|
68
68
|
|
|
69
|
+
setLogFolder(newLogFolder) {
|
|
70
|
+
// Close existing stream if it exists
|
|
71
|
+
if (this.logStream) {
|
|
72
|
+
this.logStream.end();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Update log folder
|
|
76
|
+
this.logFolder = newLogFolder;
|
|
77
|
+
|
|
78
|
+
// Reinitialize with new folder
|
|
79
|
+
this.initializeLogFile();
|
|
80
|
+
}
|
|
81
|
+
|
|
69
82
|
writeToFile(message) {
|
|
70
83
|
if (this.logStream) {
|
|
71
84
|
// Strip ANSI color codes for file output
|
package/lib/orchestrator.js
CHANGED
|
@@ -4,11 +4,12 @@ import { log } from './logger.js';
|
|
|
4
4
|
import { GitCache } from './git-cache.js';
|
|
5
5
|
|
|
6
6
|
export class Orchestrator {
|
|
7
|
-
constructor(config, startPhase = null, logFolder = null, phases = null) {
|
|
7
|
+
constructor(config, startPhase = null, logFolder = null, phases = null, sequential = false) {
|
|
8
8
|
this.config = config;
|
|
9
9
|
this.startPhase = startPhase;
|
|
10
10
|
this.logFolder = logFolder;
|
|
11
11
|
this.phases = phases;
|
|
12
|
+
this.sequential = sequential;
|
|
12
13
|
this.processManager = processManager;
|
|
13
14
|
this.healthCheck = healthCheck;
|
|
14
15
|
this.logger = log;
|
|
@@ -252,14 +253,31 @@ export class Orchestrator {
|
|
|
252
253
|
|
|
253
254
|
// Handle both old array format and new phases format
|
|
254
255
|
if (Array.isArray(this.config)) {
|
|
255
|
-
// Legacy: Run all commands in parallel
|
|
256
|
-
|
|
257
|
-
this.
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
256
|
+
// Legacy: Run all commands in parallel or sequential based on flag
|
|
257
|
+
if (this.sequential) {
|
|
258
|
+
this.logger.info('š Running in sequential mode');
|
|
259
|
+
const results = [];
|
|
260
|
+
for (const commandConfig of this.config) {
|
|
261
|
+
const result = await this.executeCommand(commandConfig);
|
|
262
|
+
results.push(result);
|
|
263
|
+
if (!result) {
|
|
264
|
+
hasFailures = true;
|
|
265
|
+
break; // Stop on first failure in sequential mode
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
} else {
|
|
269
|
+
const tasks = this.config.map((commandConfig) =>
|
|
270
|
+
this.executeCommand(commandConfig),
|
|
271
|
+
);
|
|
272
|
+
const results = await Promise.all(tasks);
|
|
273
|
+
hasFailures = results.some(result => !result);
|
|
274
|
+
}
|
|
261
275
|
} else if (this.config.phases) {
|
|
262
|
-
// New: Run phases sequentially, commands within phases in parallel
|
|
276
|
+
// New: Run phases sequentially, commands within phases in parallel or sequential based on flag
|
|
277
|
+
if (this.sequential) {
|
|
278
|
+
this.logger.info('š Running in sequential mode');
|
|
279
|
+
}
|
|
280
|
+
|
|
263
281
|
for (const phase of this.config.phases) {
|
|
264
282
|
// Check if we should start from this phase
|
|
265
283
|
if (this.startPhase && !startPhaseFound) {
|
|
@@ -298,11 +316,26 @@ export class Orchestrator {
|
|
|
298
316
|
|
|
299
317
|
this.logger.info(`\nš Starting phase: ${phase.name}`);
|
|
300
318
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
319
|
+
let results;
|
|
320
|
+
if (this.sequential) {
|
|
321
|
+
// Run commands sequentially
|
|
322
|
+
results = [];
|
|
323
|
+
for (const commandConfig of phase.parallel) {
|
|
324
|
+
const result = await this.executeCommand(commandConfig);
|
|
325
|
+
results.push(result);
|
|
326
|
+
if (!result) {
|
|
327
|
+
// In sequential mode, stop phase execution on first failure
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
// Run commands in parallel
|
|
333
|
+
const tasks = phase.parallel.map((commandConfig) =>
|
|
334
|
+
this.executeCommand(commandConfig),
|
|
335
|
+
);
|
|
336
|
+
results = await Promise.all(tasks);
|
|
337
|
+
}
|
|
304
338
|
|
|
305
|
-
const results = await Promise.all(tasks);
|
|
306
339
|
const phaseHasFailures = results.some(result => !result);
|
|
307
340
|
|
|
308
341
|
if (phaseHasFailures) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "scripts-orchestrator",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.9.0",
|
|
4
4
|
"description": "A powerful script orchestrator for running parallel commands with dependency management, background processes, and health checks",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"type": "module",
|