@formigio/fazemos-cli 0.10.19 → 0.10.20

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/index.js CHANGED
@@ -12,6 +12,7 @@ import { printFindings, printJson } from './yaml/format.js';
12
12
  import { validateManifest } from './manifest/checks.js';
13
13
  import { findLocalRegistry, resolveRole, buildInboxFile, writeInboxFile, writeInboxFileAtPath, buildRolesSyncPayload, findUnprocessedInboxFiles, computeFileHash, gitCommitInboxFile, } from './dispatch.js';
14
14
  import { execSync } from 'child_process';
15
+ import { parseExecutionsJson, resolveWaitOptions, waitForPipelines, buildAwsCommand, validateExecutionEntry, } from './wait-for-pipeline.js';
15
16
  import { readFileSync, readdirSync, writeFileSync, mkdirSync, existsSync, statSync } from 'fs';
16
17
  import { fileURLToPath } from 'url';
17
18
  import { dirname, resolve, basename } from 'path';
@@ -4475,6 +4476,70 @@ pipelines
4475
4476
  process.exit(1);
4476
4477
  }
4477
4478
  });
4479
+ // ── P8/I55 — deploy-completion gate ──
4480
+ // Poll one or more CodePipeline executions until each reaches a terminal state.
4481
+ // Shells out to the `aws` CLI via execSync (no @aws-sdk dependency, consistent
4482
+ // with the existing CLI pattern); credentials arrive via the ECS task-role
4483
+ // metadata service inside the agent container. Exit-code contract (spec §3.3):
4484
+ // 0 Succeeded (or empty map) · 2 Failed/Stopped · 3 Superseded · 4 timeout · 5 aws-call-failure.
4485
+ pipelines
4486
+ .command('wait-for-pipeline')
4487
+ .description('Poll CodePipeline execution(s) until terminal; exit 0 on Succeeded, non-zero with a structured diagnostic otherwise (deploy-completion gate)')
4488
+ .argument('[execution-id]', 'CodePipeline pipeline-execution-id (single-pair form; requires --pipeline). Omit when using --executions-json.')
4489
+ .option('--pipeline <name>', 'CodePipeline name (required with the single-pair form; execution-id is only unique within a pipeline)')
4490
+ .option('--executions-json <json>', 'Bulk form: JSON map of {pipelineName: executionId}. Empty/{} is a documented no-op (exit 0).')
4491
+ .option('--timeout <duration>', 'Total wall-clock budget (15m, 900s, or 900). Default 15m.')
4492
+ .option('--poll-interval <duration>', 'Per-poll sleep (floor 60s; values below are clamped + warned). Default 60s.')
4493
+ .option('--region <region>', 'AWS region (reads AWS_REGION/AWS_DEFAULT_REGION, else us-west-2). Passed explicitly to every aws call.')
4494
+ .action(async (executionId, opts) => {
4495
+ try {
4496
+ // Build the (pipeline, executionId) list from whichever form was used.
4497
+ let executions;
4498
+ if (opts.executionsJson !== undefined) {
4499
+ if (executionId || opts.pipeline) {
4500
+ console.error(chalk.red('wait-for-pipeline: pass EITHER --executions-json OR an execution-id + --pipeline, not both'));
4501
+ process.exit(1);
4502
+ }
4503
+ executions = parseExecutionsJson(opts.executionsJson);
4504
+ }
4505
+ else {
4506
+ if (!executionId) {
4507
+ console.error(chalk.red('wait-for-pipeline: an execution-id (with --pipeline) or --executions-json is required'));
4508
+ process.exit(1);
4509
+ }
4510
+ if (!opts.pipeline) {
4511
+ console.error(chalk.red('wait-for-pipeline: --pipeline <name> is required with the single-pair form (execution-id is only unique within a pipeline)'));
4512
+ process.exit(1);
4513
+ }
4514
+ validateExecutionEntry(opts.pipeline, executionId);
4515
+ executions = [{ pipeline: opts.pipeline, executionId }];
4516
+ }
4517
+ const waitOptions = resolveWaitOptions({
4518
+ timeout: opts.timeout,
4519
+ pollInterval: opts.pollInterval,
4520
+ region: opts.region,
4521
+ });
4522
+ // AwsRunner: shell out to the aws CLI, capturing stdout. On non-zero exit
4523
+ // execSync throws an Error carrying .stderr — the gate logic reads it.
4524
+ const aws = (args) => {
4525
+ const cmd = buildAwsCommand(args);
4526
+ return execSync(cmd, {
4527
+ encoding: 'utf-8',
4528
+ stdio: ['ignore', 'pipe', 'pipe'],
4529
+ // Default 1MB can spuriously throw on a large get-pipeline-state
4530
+ // response; that would map to AWS_CALL_FAILED (exit 5) incorrectly.
4531
+ maxBuffer: 10 * 1024 * 1024,
4532
+ });
4533
+ };
4534
+ const exitCode = await waitForPipelines(executions, waitOptions, { aws });
4535
+ process.exit(exitCode);
4536
+ }
4537
+ catch (err) {
4538
+ // Configuration / parse errors (bad --executions-json, bad --timeout, etc.)
4539
+ console.error(chalk.red(err.message));
4540
+ process.exit(1);
4541
+ }
4542
+ });
4478
4543
  const step = pipelines.command('step').description('Pipeline step commands');
4479
4544
  step
4480
4545
  .command('list')