From 63cf0ac1190b3490ce2a64fd07e6210fe4bf234b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ma=C3=ABl=20Nison?= Date: Wed, 29 Sep 2021 16:11:39 +0200 Subject: [PATCH] Updates 'set version' to shell out to Yarn 2 when requested --- src/cli/commands/policies.js | 99 ++++++++++++++++++++++++++++++++---- 1 file changed, 90 insertions(+), 9 deletions(-) diff --git a/src/cli/commands/policies.js b/src/cli/commands/policies.js index 7c64dda693..78be35b9c8 100644 --- a/src/cli/commands/policies.js +++ b/src/cli/commands/policies.js @@ -2,10 +2,19 @@ import type {Reporter} from '../../reporters/index.js'; import type Config from '../../config.js'; +import {version} from '../../util/yarn-version.js'; +import * as child from '../../util/child.js'; import buildSubCommands from './_build-sub-commands.js'; import {getRcConfigForFolder} from '../../rc.js'; import * as fs from '../../util/fs.js'; import {stringify} from '../../lockfile'; +import {satisfiesWithPrereleases} from '../../util/semver.js'; +import {NODE_BIN_PATH} from '../../constants'; + +const V2_NAMES = ['stable', 'berry', 'stable', 'canary', 'v2', '2']; + +const isLocalFile = (version: string) => version.match(/^\.{0,2}[\\/]/) || path.isAbsolute(version); +const isV2Version = (version: string) => satisfiesWithPrereleases(version, '>=2.0.0'); const chalk = require('chalk'); const invariant = require('invariant'); @@ -49,6 +58,7 @@ async function fetchReleases( ): Promise> { const token = process.env.GITHUB_TOKEN; const tokenUrlParameter = token ? `?access_token=${token}` : ''; + const request: Array = await config.requestManager.request({ url: `https://api.github.com/repos/yarnpkg/yarn/releases${tokenUrlParameter}`, json: true, @@ -98,32 +108,103 @@ export function hasWrapper(flags: Object, args: Array): boolean { const {run, setFlags, examples} = buildSubCommands('policies', { async setVersion(config: Config, reporter: Reporter, flags: Object, args: Array): Promise { - let range = args[0] || 'latest'; - let allowRc = flags.rc; + const initialRange = args[0] || 'latest'; + let range = initialRange; - reporter.log(`Resolving ${chalk.yellow(range)} to a url...`); + let allowRc = flags.rc; if (range === 'rc') { - range = 'latest'; + reporter.log( + `${chalk.yellow( + `Warning:`, + )} Your current Yarn binary is currently Yarn ${version}; to avoid potential breaking changes, 'set version rc' won't receive upgrades past the 1.22.x branch.\n To upgrade to the latest versions, run ${chalk.cyan( + `yarn set version`, + )} ${chalk.yellow.underline(`canary`)} instead. Sorry for the inconvenience.\n`, + ); + + range = '*'; allowRc = true; } if (range === 'latest') { + reporter.log( + `${chalk.yellow( + `Warning:`, + )} Your current Yarn binary is currently Yarn ${version}; to avoid potential breaking changes, 'set version latest' won't receive upgrades past the 1.22.x branch.\n To upgrade to the latest versions, run ${chalk.cyan( + `yarn set version`, + )} ${chalk.yellow.underline(`stable`)} instead. Sorry for the inconvenience.\n`, + ); + + range = '*'; + } + + if (range === 'classic') { range = '*'; } let bundleUrl; let bundleVersion; - let isV2 = false; + const isV2 = false; if (range === 'nightly' || range === 'nightlies') { + reporter.log( + `${chalk.yellow( + `Warning:`, + )} Nightlies only exist for Yarn 1.x; starting from 2.x onwards, you should use 'canary' instead`, + ); + bundleUrl = 'https://nightly.yarnpkg.com/latest.js'; bundleVersion = 'nightly'; - } else if (range === 'berry' || range === 'v2' || range === '2') { - bundleUrl = 'https://github.com/yarnpkg/berry/raw/master/packages/berry-cli/bin/berry.js'; - bundleVersion = 'berry'; - isV2 = true; + } else if (V2_NAMES.includes(range) || isLocalFile(range) || isV2Version(range)) { + const normalizedRange = range === `canary` ? `canary` : `stable`; + + if (process.env.COREPACK_ROOT) { + await child.spawn( + NODE_BIN_PATH, + [ + path.join(process.env.COREPACK_ROOT, 'dist/corepack.js'), + `yarn@${normalizedRange}`, + `set`, + `version`, + normalizedRange, + ], + { + stdio: 'inherit', + cwd: config.cwd, + }, + ); + + return; + } else { + const bundle = await fetchBundle( + config, + 'https://github.com/yarnpkg/berry/raw/master/packages/yarnpkg-cli/bin/yarn.js', + ); + + const yarnPath = path.resolve(config.lockfileFolder, `.yarn/releases/yarn-stable-temp.cjs`); + await fs.mkdirp(path.dirname(yarnPath)); + await fs.writeFile(yarnPath, bundle); + await fs.chmod(yarnPath, 0o755); + + try { + await child.spawn(NODE_BIN_PATH, [yarnPath, 'set', 'version', range], { + stdio: 'inherit', + cwd: config.lockfileFolder, + env: { + ...process.env, + YARN_IGNORE_PATH: `1`, + }, + }); + } catch (err) { + // eslint-disable-next-line no-process-exit + process.exit(1); + } + + return; + } } else { + reporter.log(`Resolving ${chalk.yellow(initialRange)} to a url...`); + let releases = []; try {