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 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
@@ -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
- const tasks = this.config.map((commandConfig) =>
257
- this.executeCommand(commandConfig),
258
- );
259
- const results = await Promise.all(tasks);
260
- hasFailures = results.some(result => !result);
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
- const tasks = phase.parallel.map((commandConfig) =>
302
- this.executeCommand(commandConfig),
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.8.0",
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",