1import { Command } from '@expo/commander';
2import { Config, Versions } from '@expo/xdl';
3import chalk from 'chalk';
4import inquirer from 'inquirer';
5import * as jsondiffpatch from 'jsondiffpatch';
6
7import { STAGING_API_HOST, PRODUCTION_API_HOST } from '../Constants';
8
9async function action() {
10  // Get from staging
11  Config.api.host = STAGING_API_HOST;
12  const versionsStaging = await Versions.versionsAsync();
13
14  // since there is only one versions cache, we need to wait a small
15  // amount of time so that the cache is invalidated before fetching from prod
16  await new Promise((resolve) => setTimeout(resolve, 10));
17
18  Config.api.host = PRODUCTION_API_HOST;
19  const versionsProd = await Versions.versionsAsync();
20  const delta = jsondiffpatch.diff(versionsProd, versionsStaging);
21
22  if (!delta) {
23    console.log(chalk.yellow('There are no changes to apply in the configuration.'));
24    return;
25  }
26
27  console.log(`Here is the diff from ${chalk.green('staging')} -> ${chalk.green('production')}:`);
28  console.log(jsondiffpatch.formatters.console.format(delta, versionsProd));
29
30  const { isCorrect } = await inquirer.prompt<{ isCorrect: boolean }>([
31    {
32      type: 'confirm',
33      name: 'isCorrect',
34      message: `Does this look correct? Type \`y\` to update ${chalk.green('production')} config.`,
35      default: false,
36    },
37  ]);
38
39  if (isCorrect) {
40    // Promote staging configuration to production.
41    await Versions.setVersionsAsync(versionsStaging);
42
43    console.log(
44      chalk.green('\nSuccessfully updated production config. You can check it out on'),
45      chalk.blue(`https://${PRODUCTION_API_HOST}/--/api/v2/versions`)
46    );
47  } else {
48    console.log(chalk.yellow('Canceled'));
49  }
50}
51
52export default (program: Command) => {
53  program
54    .command('promote-versions-to-production')
55    .alias('promote-versions-to-prod', 'promote-versions')
56    .description('Promotes the latest versions config from staging to production.')
57    .asyncAction(action);
58};
59