release.js 5.28 KB
Newer Older
dengxiaofeng's avatar
dengxiaofeng committed
1
const { utils } = require('umi');
邓晓峰's avatar
邓晓峰 committed
2
const { join, relative, resolve, sep } = require('path');
dengxiaofeng's avatar
dengxiaofeng committed
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
const exec = require('./utils/exec');
const getPackages = require('./utils/getPackages');
const isNextVersion = require('./utils/isNextVersion');

const { yParser, execa, chalk } = utils;
const cwd = process.cwd();
const args = yParser(process.argv);
const lernaCli = require.resolve('lerna/cli');

function printErrorAndExit(message) {
  console.error(chalk.red(message));
  process.exit(1);
}

function logStep(name) {
  console.log(`${chalk.gray('>> Release:')} ${chalk.magenta.bold(name)}`);
}

function packageExists({ name, version }) {
  const { stdout } = execa.sync('npm', ['info', `${name}@${version}`]);
  return stdout.length > 0;
}

async function release() {
邓晓峰's avatar
邓晓峰 committed
27 28 29 30 31
  let pkgList = execa.sync(lernaCli, ['list', '--json']).stdout;
  pkgList = JSON.parse(pkgList);
  const locMap = {};
  pkgList.forEach((item) => {
    const location = item.location.split(sep);
邓晓峰's avatar
邓晓峰 committed
32 33
    const componentName = item.name.split('/')[1];
    locMap[componentName] = `${location[location.length - 2]}/${location[location.length - 1]}`;
邓晓峰's avatar
邓晓峰 committed
34
  });
dengxiaofeng's avatar
dengxiaofeng committed
35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
  // Check git status
  if (!args.skipGitStatusCheck) {
    const gitStatus = execa.sync('git', ['status', '--porcelain']).stdout;
    if (gitStatus.length) {
      printErrorAndExit(`Your git status is not clean. Aborting.`);
    }
  } else {
    logStep('git status check is skipped, since --skip-git-status-check is supplied');
  }

  // Check npm registry
  logStep('check npm registry');
  const userRegistry = execa.sync('npm', ['config', 'get', 'registry']).stdout;
  if (userRegistry.includes('https://registry.yarnpkg.com/')) {
    printErrorAndExit(`Release failed, please use ${chalk.blue('npm run release')}.`);
  }
51
  // https://g.civnet.cn:4873
邓晓峰's avatar
邓晓峰 committed
52 53 54 55 56 57 58
  // if (!userRegistry.includes('https://registry.npmjs.org/')) {
  //   const registry = chalk.blue('https://registry.npmjs.org/');
  //   printErrorAndExit(`Release failed, npm registry must be ${registry}.`);
  // }

  if (!userRegistry.includes('https://g.civnet.cn:4873/')) {
    const registry = chalk.blue('https://g.civnet.cn:4873/');
dengxiaofeng's avatar
dengxiaofeng committed
59 60 61 62 63 64 65 66
    printErrorAndExit(`Release failed, npm registry must be ${registry}.`);
  }
  let updated = null;

  if (!args.publishOnly) {
    // Get updated packages
    logStep('check updated packages');
    const updatedStdout = execa.sync(lernaCli, ['changed']).stdout;
邓晓峰's avatar
邓晓峰 committed
67
    console.log('updatedStdout', updatedStdout);
dengxiaofeng's avatar
dengxiaofeng committed
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
    updated = updatedStdout
      .split('\n')
      .map((pkg) => {
        return pkg.split('/')[1];
      })
      .filter(Boolean);
    if (!updated.length) {
      printErrorAndExit('Release failed, no updated package is updated.');
    }

    // Clean
    logStep('clean');

    // Build
    if (!args.skipBuild) {
      logStep('build');
叶飞's avatar
叶飞 committed
84 85
      try {
        await exec('npm', ['run', 'build']);
叶飞's avatar
叶飞 committed
86 87
      } catch (error) {
        console.log(error);
叶飞's avatar
叶飞 committed
88
      }
dengxiaofeng's avatar
dengxiaofeng committed
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
    } else {
      logStep('build is skipped, since args.skipBuild is supplied');
    }

    // Bump version
    // Commit
    // Git Tag
    // Push
    logStep('bump version with lerna version');
    const conventionalGraduate = args.conventionalGraduate
      ? ['--conventional-graduate'].concat(
          Array.isArray(args.conventionalGraduate) ? args.conventionalGraduate.join(',') : [],
        )
      : [];
    const conventionalPrerelease = args.conventionalPrerelease
      ? ['--conventional-prerelease'].concat(
          Array.isArray(args.conventionalPrerelease) ? args.conventionalPrerelease.join(',') : [],
        )
      : [];
    await exec(
      lernaCli,
      [
        'version',
        '--exact',
        // '--no-commit-hooks',
        // '--no-git-tag-version',
        // '--no-push',
        '--message',
        '🎨 chore(release): Publish',
        '--conventional-commits',
      ]
        .concat(conventionalGraduate)
        .concat(conventionalPrerelease),
    );
  }

  // Publish
  // Umi must be the latest.
  const pkgs = args.publishOnly ? getPackages() : updated;
  logStep(`publish packages: ${chalk.blue(pkgs.join(', '))}`);

130 131
  // eslint-disable-next-line consistent-return,array-callback-return
  const publishList = pkgs.map((pkg, index) => {
邓晓峰's avatar
邓晓峰 committed
132 133
    const pkgMap = locMap[pkg];
    const [p, shortName] = pkgMap.split('/');
134 135
    const pkgPath = join(cwd, 'packages', p, shortName.replace('pro-', ''));
    // eslint-disable-next-line global-require,import/no-dynamic-require
dengxiaofeng's avatar
dengxiaofeng committed
136
    const { name, version } = require(join(pkgPath, 'package.json'));
李纪文's avatar
李纪文 committed
137
    if (name === 'parseform') return false;
dengxiaofeng's avatar
dengxiaofeng committed
138 139 140 141 142 143 144 145 146 147 148 149
    const isNext = isNextVersion(version);
    let isPackageExist = null;
    if (args.publishOnly) {
      isPackageExist = packageExists({ name, version });
      if (isPackageExist) {
        console.log(`package ${name}@${version} is already exists on npm, skip.`);
      }
    }
    if (!args.publishOnly || !isPackageExist) {
      console.log(
        `[${index + 1}/${pkgs.length}] Publish package ${name} ${isNext ? 'with next tag' : ''}`,
      );
150 151
      const cliArgs = isNext ? ['publish', '--tag', 'next'] : ['publish', '--tag', 'beta'];
      return execa('npm', cliArgs, {
dengxiaofeng's avatar
dengxiaofeng committed
152 153 154 155 156
        cwd: pkgPath,
      });
    }
  });

157 158 159
  console.log(`发布中${pkgs.join('/')}`);
  await Promise.all(publishList);
  console.log('发布成功! ');
dengxiaofeng's avatar
dengxiaofeng committed
160 161 162 163 164 165 166 167
  await exec('npm', ['run', 'prettier']);

  logStep('done');
}

release().catch((err) => {
  console.error(err);
  process.exit(1);
邓晓峰's avatar
邓晓峰 committed
168
});