export async function main()

in packages/@aws-cdk/integ-runner/lib/cli.ts [101:204]


export async function main(args: string[]) {
  const options = parseCliArgs(args);

  const testsFromArgs = await new IntegrationTests(path.resolve(options.directory)).fromCliOptions(options);

  // List only prints the discovered tests
  if (options.list) {
    process.stdout.write(testsFromArgs.map(t => t.discoveryRelativeFileName).join('\n') + '\n');
    return;
  }

  const pool = workerpool.pool(path.join(__dirname, '..', 'lib', 'workers', 'extract', 'index.js'), {
    maxWorkers: options.watch ? 1 : options.maxWorkers,
  });

  const testsToRun: IntegTestWorkerConfig[] = [];
  let destructiveChanges: boolean = false;
  let failedSnapshots: IntegTestWorkerConfig[] = [];
  let testsSucceeded = false;
  validateWatchArgs({
    ...options,
    testRegions: options.originalRegions,
    tests: testsFromArgs,
  });

  try {
    if (!options.watch) {
      // always run snapshot tests, but if '--force' is passed then
      // run integration tests on all failed tests, not just those that
      // failed snapshot tests
      failedSnapshots = await runSnapshotTests(pool, testsFromArgs, {
        retain: options.inspectFailures,
        verbose: options.verbose,
      });
      for (const failure of failedSnapshots) {
        logger.warning(`Failed: ${failure.fileName}`);
        if (failure.destructiveChanges && failure.destructiveChanges.length > 0) {
          printDestructiveChanges(failure.destructiveChanges);
          destructiveChanges = true;
        }
      }
      if (!options.force) {
        testsToRun.push(...failedSnapshots);
      } else {
        // if any of the test failed snapshot tests, keep those results
        // and merge with the rest of the tests from args
        testsToRun.push(...mergeTests(testsFromArgs.map(t => t.info), failedSnapshots));
      }
    } else {
      testsToRun.push(...testsFromArgs.map(t => t.info));
    }

    // run integration tests if `--update-on-failed` OR `--force` is used
    if (options.runUpdateOnFailed || options.force) {
      const { success, metrics } = await runIntegrationTests({
        pool,
        tests: testsToRun,
        regions: options.testRegions,
        profiles: options.profiles,
        clean: options.clean,
        dryRun: options.dryRun,
        verbosity: options.verbosity,
        updateWorkflow: !options.disableUpdateWorkflow,
        watch: options.watch,
      });
      testsSucceeded = success;

      if (options.clean === false) {
        logger.warning('Not cleaning up stacks since "--no-clean" was used');
      }

      if (Boolean(options.verbose)) {
        printMetrics(metrics);
      }

      if (!success) {
        throw new Error('Some integration tests failed!');
      }
    } else if (options.watch) {
      await watchIntegrationTest(pool, {
        watch: true,
        verbosity: options.verbosity,
        ...testsToRun[0],
        profile: options.profiles ? options.profiles[0] : undefined,
        region: options.testRegions[0],
      });
    }
  } finally {
    void pool.terminate();
  }

  if (destructiveChanges) {
    throw new Error('Some changes were destructive!');
  }
  if (failedSnapshots.length > 0) {
    let message = '';
    if (!options.runUpdateOnFailed) {
      message = 'To re-run failed tests run: integ-runner --update-on-failed';
    }
    if (!testsSucceeded) {
      throw new Error(`Some tests failed!\n${message}`);
    }
  }
}