text: "use strict";
  var __importDefault = (this && this.__importDefault) || function (mod) {
      return (mod && mod.__esModule) ? mod : { "default": mod };
  };
  Object.defineProperty(exports, "__esModule", { value: true });
  exports.createRelease = void 0;
  const fs_extra_1 = require("fs-extra");
  const inquirer_1 = __importDefault(require("inquirer"));
  const semver_1 = require("semver");
  const standard_version_1 = __importDefault(require("standard-version"));
  const git_1 = require("../utils/git");
  const github_1 = require("../utils/github");
  const npm_1 = require("../utils/npm");
  const semver_2 = require("../utils/semver");
  const spawn_1 = require("../utils/spawn");
  /**
   * Returns the default config to be passed to 'standard-version'.
   */
  async function getStandardVersionConfig(nextVersion, overrides = {}) {
      const config = {
          header: '# Changelog',
          noVerify: true,
          tagPrefix: '',
          types: [
              { type: 'feat', section: 'Features' },
              { type: 'fix', section: 'Bug Fixes' },
              { type: 'deprecation', section: 'Deprecations' },
              { type: 'build', hidden: true },
              { type: 'ci', hidden: true },
              { type: 'chore', hidden: true },
              { type: 'docs', hidden: true },
              { type: 'style', hidden: true },
              { type: 'refactor', hidden: true },
              { type: 'revert', hidden: true },
              { type: 'perf', hidden: true },
              { type: 'test', hidden: true },
          ],
      };
      const prerelease = (0, semver_2.isPrerelease)(nextVersion);
      if (prerelease) {
          config.prerelease = prerelease;
      }
      return { ...config, ...overrides };
  }
  /**
   * Returns the bumped version generated by 'standard-version' utility.
   */
  async function getNextVersion(currentVersion) {
      const args = [
          '--dry-run',
          '--skip.tag',
          '--skip.changelog',
          '--skip.commit',
          '--tagPrefix=""',
      ];
      const prerelease = (0, semver_2.isPrerelease)(currentVersion);
      if (prerelease) {
          args.push(`--prerelease=${prerelease}`);
      }
      // The 'standard-version' API does not provide a way to derive the bumped version programmatically.
      // As a workaround, we'll read the "dry run" output from the console.
      const result = await (0, spawn_1.getCommandOutput)('./node_modules/.bin/standard-version', args);
      const matches = result.trim().match(/[0-9]+\.[0-9]+\.[0-9]+(-(\w*\.)?\d+)?$/);
      if (!matches) {
          throw new Error('A new version could not be derived from the `standard-version` output.');
      }
      const nextVersion = matches[0];
      return nextVersion;
  }
  /**
   * Prompts the developer to confirm the final push of the tag/commit to origin.
   */
  async function promptPushOrigin(version, baseBranch) {
      const answer = await inquirer_1.default.prompt([
          {
              type: 'confirm',
              name: 'pushOrigin',
              message: `Push to origin to trigger release?`,
              default: true,
          },
      ]);
      if (!answer.pushOrigin) {
          // Reset the commit and delete the tag.
          await (0, spawn_1.runCommand)('git', ['reset', '--soft', 'HEAD~1']);
          await (0, spawn_1.runCommand)('git', ['tag', '-d', version]);
          console.log('Release aborted. Thanks for playing!');
          process.exit(0);
      }
      await (0, spawn_1.runCommand)('git', ['push', '--follow-tags', 'origin', baseBranch]);
      console.log('Successfully pushed tag and commits to origin.');
  }
  /**
   * Throws an error if the provided version does not satisfy the allowed semver range.
   * @param {string} version
   */
  async function validateVersion(version, allowedSemverRange) {
      if ((0, semver_1.outside)(version, allowedSemverRange, '<') ||
          (0, semver_1.outside)(version, allowedSemverRange, '>')) {
          throw new Error(` ✘ The version (${version}) does not satisfy the allowed semver range (${allowedSemverRange}) provided in .skyuxdev.json.\n` +
              "To proceed, create a pull request that adjusts the 'allowedSemverRange' to accept the new version.");
      }
      console.log(` ✔ The version (${version}) satisfies the allowed semver range (${allowedSemverRange}). OK.`);
  }
  async function createRelease(options) {
      console.log('Preparing workspace for release...');
      const buildStatus = await (0, github_1.getBranchBuildStatus)(options.baseBranch);
      if (buildStatus !== 'completed') {
          throw new Error(`The '${options.baseBranch}' branch has a build status of '${buildStatus}'. ` +
              'Wait until the workflow completes before creating a release.');
      }
      else {
          console.log(`The '${options.baseBranch}' branch has a build status of '${buildStatus}'. OK.`);
      }
      // Ensure releases are executed against the default branch.
      if ((await (0, git_1.getCurrentBranch)()) !== options.baseBranch) {
          throw new Error(`Releases can only be triggered on the '${options.baseBranch}' branch. ` +
              'Checkout that branch and try again.');
      }
      // Ensure local git is clean.
      if (!(await (0, git_1.isClean)({ compareAgainstRemote: true }))) {
          throw new Error('Your local branch does not match the remote. ' +
              'Please pull any changes from the remote (or stash any local changes) before creating a release.');
      }
      const packageJson = await (0, fs_extra_1.readJson)('package.json');
      const currentVersion = packageJson.version;
      const versionExists = await (0, npm_1.checkVersionExists)('@skyux/core', // 'core' is arbitrary since all packages have the same version
      currentVersion);
      let nextVersion;
      if (versionExists) {
          nextVersion = await getNextVersion(currentVersion);
      }
      else {
          nextVersion = currentVersion;
          console.warn(`[!] The current version (${currentVersion}) was not found on the registry. ` +
              'Aborting version bump and assuming first release.');
      }
      await validateVersion(nextVersion, options.allowedSemverRange);
      const answer = await inquirer_1.default.prompt([
          {
              type: 'confirm',
              name: 'proceed',
              message: `This command will generate a tag and release notes for version (${nextVersion}). Proceed?`,
              default: true,
          },
      ]);
      if (!answer.proceed) {
          console.log('Release aborted.');
          process.exit(0);
      }
      console.log('Generating release artifacts...');
      const standardVersionConfig = await getStandardVersionConfig(nextVersion, {
          firstRelease: !versionExists,
          scripts: {
              // Run prettier on the changelog.
              postchangelog: 'npx prettier --write CHANGELOG.md',
          },
      });
      // Bump version and create changelog.
      await (0, standard_version_1.default)(standardVersionConfig);
      await promptPushOrigin(nextVersion, options.baseBranch);
  }
  exports.createRelease = createRelease;
  