update-dist-tag.ts 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. /* -----------------------------------------------------------------------------
  2. | Copyright (c) Jupyter Development Team.
  3. | Distributed under the terms of the Modified BSD License.
  4. |----------------------------------------------------------------------------*/
  5. import * as path from 'path';
  6. import * as utils from './utils';
  7. import packageJson from 'package-json';
  8. import commander from 'commander';
  9. import semver from 'semver';
  10. /**
  11. * Handle an individual package on the path - update the dependency.
  12. */
  13. export async function handlePackage(packagePath: string): Promise<string[]> {
  14. const cmds: string[] = [];
  15. // Read in the package.json.
  16. packagePath = path.join(packagePath, 'package.json');
  17. let data: any;
  18. try {
  19. data = utils.readJSONFile(packagePath);
  20. } catch (e) {
  21. console.debug('Skipping package ' + packagePath);
  22. return cmds;
  23. }
  24. if (data.private) {
  25. return cmds;
  26. }
  27. const pkg = data.name;
  28. const npmData = await packageJson(pkg, { allVersions: true });
  29. const versions = Object.keys(npmData.versions).sort(semver.rcompare);
  30. const tags = npmData['dist-tags'];
  31. // Go through the versions. The latest prerelease is 'next', the latest
  32. // non-prerelease should be 'stable'.
  33. const next = semver.prerelease(versions[0]) ? versions[0] : undefined;
  34. const latest = versions.find(i => !semver.prerelease(i));
  35. if (latest && latest !== tags.latest) {
  36. cmds.push(`npm dist-tag add ${pkg}@${latest} latest`);
  37. }
  38. // If next is defined, but not supposed to be, remove it. If next is supposed
  39. // to be defined, but is not the same as the current next, change it.
  40. if (!next && tags.next) {
  41. cmds.push(`npm dist-tag rm ${pkg} next`);
  42. } else if (next && next !== tags.next) {
  43. cmds.push(`npm dist-tag add ${pkg}@${next} next`);
  44. }
  45. return cmds;
  46. }
  47. function flatten(a: any[]) {
  48. return a.reduce((acc, val) => acc.concat(val), []);
  49. }
  50. commander
  51. .description(
  52. `Print out commands to update npm 'latest' and 'next' dist-tags
  53. so that 'latest' points to the latest stable release and 'next'
  54. points to the latest prerelease after it.`
  55. )
  56. .option('--lerna', 'Update dist-tags in all lerna packages')
  57. .option('--path [path]', 'Path to package or monorepo to update')
  58. .action(async (args: any) => {
  59. const basePath = path.resolve(args.path || '.');
  60. let cmds: string[][] = [];
  61. let paths: string[] = [];
  62. if (args.lerna) {
  63. paths = utils.getLernaPaths(basePath).sort();
  64. cmds = await Promise.all(paths.map(handlePackage));
  65. }
  66. cmds.push(await handlePackage(basePath));
  67. const out = flatten(cmds).join('\n');
  68. if (out) {
  69. console.debug(out);
  70. }
  71. });
  72. if (require.main === module) {
  73. commander.parse(process.argv);
  74. }