text: const {
    getChangedServices,
    getRegion,
    getNotDeployedServices,
    getDeployedServices,
    getPackages,
    batchDeployCommand,
    batchE2ETestCommand,
    batchRemoveCommand,
    CICD,
  } = require('./deployUtils');
  const { error, warning, info, log } = require('./log');
  const yargs = require('yargs');
  
  const deploy = async (stage, commitId, forceAll) => {
    try {
      log(
        'Received deploy arguments:',
        `stage=${stage}, commitId=${commitId}, forceAll=${forceAll}`,
      );
  
      const region = await getRegion(stage);
  
      let toDeploy = [];
      const packages = await getPackages();
  
      if (forceAll) {
        toDeploy = packages.map(({ name }) => name);
      } else {
        const changed = getChangedServices(commitId);
  
        info('Changed services:', JSON.stringify(changed));
  
        const notDeployed = await getNotDeployedServices(stage, region);
  
        info('Not deployed services:', JSON.stringify(notDeployed));
  
        if (changed.includes(CICD) || notDeployed.includes(CICD)) {
          warning(
            `If you've made changes to ${CICD} service make sure to setup it again (as a one time setup)`,
          );
        }
  
        toDeploy = [...new Set([...changed, ...notDeployed])];
      }
  
      toDeploy = toDeploy.filter((service) => service !== CICD);
  
      if (toDeploy.length > 0) {
        info('Services to deploy:', JSON.stringify(toDeploy));
        await batchDeployCommand(packages, toDeploy, stage);
  
        if (stage !== 'prod') {
          await batchE2ETestCommand(packages, toDeploy, stage);
        } else {
          info('Not running e2e tests for stage:', stage);
        }
      } else {
        info('No services to deploy');
      }
    } catch (e) {
      error(e.message);
      process.exit(1);
    }
  };
  
  const remove = async (stage) => {
    try {
      log('Received remove arguments:', `stage=${stage}`);
  
      const region = await getRegion(stage);
  
      const deployed = await getDeployedServices(stage, region);
  
      info('Deployed services:', JSON.stringify(deployed));
  
      if (deployed.length > 0) {
        const packages = await getPackages();
        await batchRemoveCommand(packages, deployed, stage);
      } else {
        info('No services to remove');
      }
    } catch (e) {
      error(e.message);
      process.exit(1);
    }
  };
  
  yargs
    .command({
      command: 'deploy',
      aliases: ['d'],
      desc: 'Deploy services',
      builder: (yargs) =>
        yargs
          .option('stage', {
            alias: 's',
            describe: 'Stage',
            demandOption: true,
            string: true,
            requiresArg: true,
          })
          .option('forceAll', {
            alias: 'f',
            describe: 'Force deploy of all services',
            demandOption: false,
            boolean: true,
            requiresArg: true,
            default: false,
          })
          .option('commitId', {
            alias: 'c',
            describe: 'Commit Id',
            demandOption: true,
            string: true,
            requiresArg: true,
          })
          .check(({ commitId }) => {
            if (!commitId.match(/\b[0-9a-f]{5,40}\b/)) {
              throw new Error(`'${commitId}' must be a valid commitId`);
            }
            return true;
          }),
      handler: async ({ stage, commitId, forceAll }) => {
        await deploy(stage, commitId, forceAll);
      },
    })
    .command({
      command: 'remove',
      aliases: ['r'],
      desc: 'Remove all services',
      builder: (yargs) =>
        yargs.option('stage', {
          alias: 's',
          describe: 'Stage',
          demandOption: true,
          string: true,
          requiresArg: true,
        }),
      handler: async ({ stage }) => {
        await remove(stage);
      },
    })
    .demandCommand(1)
    .help()
    .strict()
    .version('0.0.1').argv;
  