scripts-orchestrator 2.4.2 → 2.6.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
@@ -165,8 +165,41 @@ The orchestrator doesn't care what the commands do - it just ensures they run (i
165
165
 
166
166
  # Or specify a custom config file
167
167
  npm run scripts-orchestrator -- ./path/to/your/config.js
168
+
169
+ # Start from a specific phase
170
+ npm run scripts-orchestrator -- --phase "unit tests"
171
+
172
+ # Start from a specific phase with custom config
173
+ npm run scripts-orchestrator -- ./path/to/your/config.js --phase "playwright"
168
174
  ```
169
175
 
176
+ ### Starting from a Specific Phase
177
+
178
+ You can start the orchestrator from a specific phase instead of running all phases from the beginning. This is useful for debugging or when you want to skip earlier phases that have already been completed.
179
+
180
+ #### Method 1: Command Line Argument
181
+ ```bash
182
+ # Start from the "unit tests" phase
183
+ npm run scripts-orchestrator -- --phase "unit tests"
184
+ ```
185
+
186
+ #### Method 2: Configuration File
187
+ ```javascript
188
+ export default {
189
+ start_phase: "unit tests", // Start from this phase
190
+ phases: [
191
+ // ... your phases
192
+ ]
193
+ };
194
+ ```
195
+
196
+ **Note**: Command line arguments take precedence over configuration file settings.
197
+
198
+ When starting from a specific phase:
199
+ - All phases before the specified phase are skipped
200
+ - Commands in skipped phases are marked as "skipped" in the final summary
201
+ - The orchestrator validates that the specified phase exists and shows available phases if not found
202
+
170
203
  ## Error Handling
171
204
 
172
205
  - The script tracks failed and skipped commands
package/index.js CHANGED
@@ -10,13 +10,32 @@ import fs from 'fs';
10
10
  import { Orchestrator } from './lib/index.js';
11
11
  import { log } from './lib/logger.js';
12
12
 
13
- // Get config file path from command line arguments
14
- const configPath = process.argv[2] || './scripts-orchestrator.config.js';
13
+ // Parse command line arguments
14
+ const args = process.argv.slice(2);
15
+ let configPath = './scripts-orchestrator.config.js';
16
+ let startPhase = null;
17
+ let logFolder = null;
18
+
19
+ // Parse arguments
20
+ for (let i = 0; i < args.length; i++) {
21
+ const arg = args[i];
22
+
23
+ if (arg === '--phase' && i + 1 < args.length) {
24
+ startPhase = args[i + 1];
25
+ i++; // Skip the next argument since we consumed it
26
+ } else if (arg === '--logFolder' && i + 1 < args.length) {
27
+ logFolder = args[i + 1];
28
+ i++; // Skip the next argument since we consumed it
29
+ } else if (!arg.startsWith('--') && !configPath) {
30
+ // First non-flag argument is the config path
31
+ configPath = arg;
32
+ }
33
+ }
15
34
 
16
35
  // Validate config file exists
17
36
  if (!fs.existsSync(configPath)) {
18
37
  log.error(`Error: Config file not found at ${configPath}`);
19
- log.error('Usage: scripts-orchestrator [path-to-config-file]');
38
+ log.error('Usage: scripts-orchestrator [path-to-config-file] [--phase <phase-name>] [--logFolder <log-directory>]');
20
39
  process.exit(1);
21
40
  }
22
41
 
@@ -25,8 +44,18 @@ const configFilePath = path.resolve(process.cwd(), configPath);
25
44
  const fileUrl = new URL(`file://${configFilePath}`).href;
26
45
  const commandsConfig = (await import(fileUrl)).default;
27
46
 
47
+ // Check for start_phase in config if not provided via command line
48
+ if (!startPhase && commandsConfig.start_phase) {
49
+ startPhase = commandsConfig.start_phase;
50
+ }
51
+
52
+ // Check for log_folder in config if not provided via command line
53
+ if (!logFolder && commandsConfig.log_folder) {
54
+ logFolder = commandsConfig.log_folder;
55
+ }
56
+
28
57
  // Create and run the orchestrator
29
- const orchestrator = new Orchestrator(commandsConfig);
58
+ const orchestrator = new Orchestrator(commandsConfig, startPhase, logFolder);
30
59
 
31
60
  // Enhanced signal handlers
32
61
  const handleSignal = async (signal) => {
package/lib/logger.js CHANGED
@@ -8,6 +8,14 @@ const argv = yargs(hideBin(process.argv))
8
8
  type: 'boolean',
9
9
  description: 'Run with verbose logging',
10
10
  })
11
+ .option('phase', {
12
+ type: 'string',
13
+ description: 'Start execution from a specific phase',
14
+ })
15
+ .option('logFolder', {
16
+ type: 'string',
17
+ description: 'Specify the directory for log files',
18
+ })
11
19
  .parse();
12
20
 
13
21
  class Logger {
@@ -3,8 +3,10 @@ import { healthCheck } from './health-check.js';
3
3
  import { log } from './logger.js';
4
4
 
5
5
  export class Orchestrator {
6
- constructor(config) {
6
+ constructor(config, startPhase = null, logFolder = null) {
7
7
  this.config = config;
8
+ this.startPhase = startPhase;
9
+ this.logFolder = logFolder;
8
10
  this.processManager = processManager;
9
11
  this.healthCheck = healthCheck;
10
12
  this.logger = log;
@@ -12,6 +14,11 @@ export class Orchestrator {
12
14
  this.skippedCommands = [];
13
15
  this.commandTimings = new Map();
14
16
 
17
+ // Set the log folder in process manager
18
+ if (logFolder) {
19
+ this.processManager.setLogFolder(logFolder);
20
+ }
21
+
15
22
  // Flatten commands for easier tracking
16
23
  this.allCommands = this.flattenCommands(config);
17
24
  }
@@ -226,6 +233,7 @@ export class Orchestrator {
226
233
  try {
227
234
  let hasFailures = false;
228
235
  let phaseFailed = false;
236
+ let startPhaseFound = false;
229
237
 
230
238
  // Handle both old array format and new phases format
231
239
  if (Array.isArray(this.config)) {
@@ -238,6 +246,21 @@ export class Orchestrator {
238
246
  } else if (this.config.phases) {
239
247
  // New: Run phases sequentially, commands within phases in parallel
240
248
  for (const phase of this.config.phases) {
249
+ // Check if we should start from this phase
250
+ if (this.startPhase && !startPhaseFound) {
251
+ if (phase.name === this.startPhase) {
252
+ startPhaseFound = true;
253
+ this.logger.info(`\nšŸŽÆ Starting from phase: ${phase.name}`);
254
+ } else {
255
+ // Mark all commands in previous phases as skipped
256
+ phase.parallel.forEach(({ command }) => {
257
+ this.skippedCommands.push(command);
258
+ this.commandTimings.set(command, 0);
259
+ });
260
+ continue;
261
+ }
262
+ }
263
+
241
264
  if (phaseFailed) {
242
265
  // Mark all commands in remaining phases as skipped
243
266
  phase.parallel.forEach(({ command }) => {
@@ -266,6 +289,13 @@ export class Orchestrator {
266
289
  }
267
290
  }
268
291
 
292
+ // Validate start phase if specified
293
+ if (this.startPhase && !startPhaseFound) {
294
+ const availablePhases = this.config.phases.map(p => p.name).join(', ');
295
+ this.logger.error(`āŒ Start phase "${this.startPhase}" not found. Available phases: ${availablePhases}`);
296
+ process.exit(1);
297
+ }
298
+
269
299
  // Check final status
270
300
  hasFailures = hasFailures ||
271
301
  this.failedCommands.length > 0 ||
@@ -10,6 +10,12 @@ export class ProcessManager {
10
10
  this.logger = log;
11
11
  this.backgroundProcesses = [];
12
12
  this.backgroundProcessesDetails = [];
13
+ this.logFolder = 'scripts-orchestrator-logs'; // Default log folder
14
+ }
15
+
16
+ setLogFolder(logFolder) {
17
+ this.logFolder = logFolder;
18
+ this.logger.verbose(`Log folder set to: ${logFolder}`);
13
19
  }
14
20
 
15
21
  addBackgroundProcess({ command, url, startedByScript, process_tracking, kill_command }) {
@@ -24,7 +30,8 @@ export class ProcessManager {
24
30
  }
25
31
 
26
32
  async runCommand({ cmd, logFile, background = false, healthCheck = null, kill_command = null, isRetry = false }) {
27
- const LOGS_DIR = path.resolve(process.cwd(), 'scripts-orchestrator-logs');
33
+ const baseDir = this.logFolder ? path.resolve(this.logFolder) : process.cwd();
34
+ const LOGS_DIR = path.join(baseDir, 'scripts-orchestrator-logs');
28
35
  const LOG_FILE = logFile || path.join(LOGS_DIR, `${cmd}.log`);
29
36
 
30
37
  try {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "scripts-orchestrator",
3
- "version": "2.4.2",
3
+ "version": "2.6.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",