mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
05ec058ac5
Summary: Working on releases, I'm often looking for the name of our monorepo packages (as sometimes the name doesn't align with the directory) and also getting a list of the versions of everything, as well as if its private/public -- which I've interpreted to mean that we publish it or we don't. I thought this might be convenient to add. ## Changelog: [Internal] - Add `print-packages` as a command to print our monorepo packages (including react-native) Pull Request resolved: https://github.com/facebook/react-native/pull/41959 Test Plan: ``` ❯ yarn print-packages yarn run v1.22.19 $ node ./scripts/monorepo/print ┌─────────┬─────────┬─────────────────────────────────────────┬────────────────┐ │ (index) │ Public? │ Name │ Version (main) │ ├─────────┼─────────┼─────────────────────────────────────────┼────────────────┤ │ 0 │ '✅' │ 'react-native/assets-registry' │ '0.74.0' │ │ 1 │ '✅' │ 'react-native/babel-plugin-codegen' │ '0.74.0' │ │ 2 │ '✅' │ 'react-native/community-cli-plugin' │ '0.74.0' │ │ 3 │ '✅' │ 'react-native/debugger-frontend' │ '0.74.0' │ │ 4 │ '✅' │ 'react-native/dev-middleware' │ '0.74.0' │ │ 5 │ '✅' │ 'react-native/eslint-config' │ '0.74.0' │ │ 6 │ '✅' │ 'react-native/eslint-plugin' │ '0.74.0' │ │ 7 │ '✅' │ 'react-native/eslint-plugin-specs' │ '0.74.0' │ │ 8 │ '❌' │ 'react-native/hermes-inspector-msggen' │ '0.72.0' │ │ 9 │ '✅' │ 'react-native/metro-config' │ '0.74.0' │ │ 10 │ '✅' │ 'react-native/normalize-colors' │ '0.74.1' │ │ 11 │ '✅' │ 'react-native/js-polyfills' │ '0.74.0' │ │ 12 │ '✅' │ 'react-native' │ '1000.0.0' │ │ 13 │ '✅' │ 'react-native/babel-preset' │ '0.74.0' │ │ 14 │ '✅' │ 'react-native/metro-babel-transformer' │ '0.74.0' │ │ 15 │ '❌' │ 'react-native/bots' │ '0.0.0' │ │ 16 │ '✅' │ 'react-native/codegen' │ '0.74.0' │ │ 17 │ '❌' │ 'react-native/codegen-typescript-test' │ '0.0.1' │ │ 18 │ '✅' │ 'react-native/gradle-plugin' │ '0.74.0' │ │ 19 │ '❌' │ 'react-native/tester' │ '0.0.1' │ │ 20 │ '❌' │ 'react-native/tester-e2e' │ '0.0.1' │ │ 21 │ '✅' │ 'react-native/typescript-config' │ '0.74.0' │ │ 22 │ '✅' │ 'react-native/virtualized-lists' │ '0.74.0' │ └─────────┴─────────┴─────────────────────────────────────────┴────────────────┘ ✨ Done in 0.55s. ``` Also added filter flag for private/public ``` ❯ yarn print-packages --type private yarn run v1.22.19 $ node ./scripts/monorepo/print --type private ┌─────────┬─────────┬─────────────────────────────────────────┬────────────────┐ │ (index) │ Public? │ Name │ Version (main) │ ├─────────┼─────────┼─────────────────────────────────────────┼────────────────┤ │ 0 │ '❌' │ 'react-native/hermes-inspector-msggen' │ '0.72.0' │ │ 1 │ '❌' │ 'react-native/bots' │ '0.0.0' │ │ 2 │ '❌' │ 'react-native/codegen-typescript-test' │ '0.0.1' │ │ 3 │ '❌' │ 'react-native/tester' │ '0.0.1' │ │ 4 │ '❌' │ 'react-native/tester-e2e' │ '0.0.1' │ └─────────┴─────────┴─────────────────────────────────────────┴────────────────┘ ✨ Done in 0.16s. ``` Also added a npm query where you can see the latest published version of a minor ``` ❯ yarn print-packages --type public --minor 72 yarn run v1.22.19 $ node ./scripts/monorepo/print --type public --minor 72 ┌─────────┬─────────┬─────────────────────────────────────────┬────────────────┬──────────────────────────────────────┐ │ (index) │ Public? │ Name │ Version (main) │ Version (72) │ ├─────────┼─────────┼─────────────────────────────────────────┼────────────────┼──────────────────────────────────────┤ │ 0 │ '✅' │ 'react-native/assets-registry' │ '0.74.0' │ '0.72.0' │ │ 1 │ '✅' │ 'react-native/babel-plugin-codegen' │ '0.74.0' │ '0.72.3' │ │ 2 │ '✅' │ 'react-native/community-cli-plugin' │ '0.74.0' │ 'No match found for version ^0.72.0' │ │ 3 │ '✅' │ 'react-native/debugger-frontend' │ '0.74.0' │ 'No match found for version ^0.72.0' │ │ 4 │ '✅' │ 'react-native/dev-middleware' │ '0.74.0' │ 'No match found for version ^0.72.0' │ │ 5 │ '✅' │ 'react-native/eslint-config' │ '0.74.0' │ '0.72.2' │ │ 6 │ '✅' │ 'react-native/eslint-plugin' │ '0.74.0' │ '0.72.0' │ │ 7 │ '✅' │ 'react-native/eslint-plugin-specs' │ '0.74.0' │ '0.72.4' │ │ 8 │ '✅' │ 'react-native/metro-config' │ '0.74.0' │ '0.72.11' │ │ 9 │ '✅' │ 'react-native/normalize-colors' │ '0.74.1' │ '0.72.0' │ │ 10 │ '✅' │ 'react-native/js-polyfills' │ '0.74.0' │ '0.72.1' │ │ 11 │ '✅' │ 'react-native' │ '1000.0.0' │ '0.72.8' │ │ 12 │ '✅' │ 'react-native/babel-preset' │ '0.74.0' │ 'No match found for version ^0.72.0' │ │ 13 │ '✅' │ 'react-native/metro-babel-transformer' │ '0.74.0' │ 'No match found for version ^0.72.0' │ │ 14 │ '✅' │ 'react-native/codegen' │ '0.74.0' │ '0.72.8' │ │ 15 │ '✅' │ 'react-native/gradle-plugin' │ '0.74.0' │ '0.72.11' │ │ 16 │ '✅' │ 'react-native/typescript-config' │ '0.74.0' │ 'No match found for version ^0.72.0' │ │ 17 │ '✅' │ 'react-native/virtualized-lists' │ '0.74.0' │ '0.72.8' │ └─────────┴─────────┴─────────────────────────────────────────┴────────────────┴──────────────────────────────────────┘ ``` Reviewed By: cortinico Differential Revision: D52347140 Pulled By: lunaleaps fbshipit-source-id: 75811730e1afd5aae2d9fba4e437cd0d3d424a90
227 lines
6.2 KiB
JavaScript
227 lines
6.2 KiB
JavaScript
/**
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*
|
|
* @format
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const {
|
|
exitIfNotOnGit,
|
|
getCurrentCommit,
|
|
isTaggedLatest,
|
|
} = require('./scm-utils');
|
|
const {parseVersion} = require('./version-utils');
|
|
const {exec} = require('shelljs');
|
|
|
|
// Get `next` version from npm and +1 on the minor for `main` version
|
|
function getMainVersion() {
|
|
const versionStr = getPackageVersionStrByTag('react-native', 'next');
|
|
const {major, minor} = parseVersion(versionStr, 'release');
|
|
return `${major}.${parseInt(minor, 10) + 1}.0`;
|
|
}
|
|
|
|
function getNpmInfo(buildType) {
|
|
const currentCommit = getCurrentCommit();
|
|
const shortCommit = currentCommit.slice(0, 9);
|
|
|
|
if (buildType === 'dry-run') {
|
|
return {
|
|
version: `1000.0.0-${shortCommit}`,
|
|
tag: null, // We never end up publishing this
|
|
};
|
|
}
|
|
|
|
if (buildType === 'nightly') {
|
|
const mainVersion = getMainVersion();
|
|
const dateIdentifier = new Date()
|
|
.toISOString()
|
|
.slice(0, -14)
|
|
.replace(/[-]/g, '');
|
|
return {
|
|
version: `${mainVersion}-nightly-${dateIdentifier}-${shortCommit}`,
|
|
tag: 'nightly',
|
|
};
|
|
}
|
|
|
|
if (buildType === 'prealpha') {
|
|
const mainVersion = '0.0.0';
|
|
// Date in the format of YYYYMMDDHH.
|
|
// This is a progressive int that can track subsequent
|
|
// releases and it is smaller of 2^32-1.
|
|
// It is unlikely that we can trigger two prealpha in less
|
|
// than an hour given that nightlies take ~ 1 hr to complete.
|
|
const dateIdentifier = new Date()
|
|
.toISOString()
|
|
.slice(0, -10)
|
|
.replace(/[-T:]/g, '');
|
|
|
|
return {
|
|
version: `${mainVersion}-prealpha-${dateIdentifier}`,
|
|
tag: 'prealpha',
|
|
};
|
|
}
|
|
|
|
const {version, major, minor, prerelease} = parseVersion(
|
|
process.env.CIRCLE_TAG,
|
|
buildType,
|
|
);
|
|
|
|
// See if releaser indicated that this version should be tagged "latest"
|
|
// Set in `trigger-react-native-release`
|
|
const isLatest = exitIfNotOnGit(
|
|
() => isTaggedLatest(currentCommit),
|
|
'Not in git. We do not want to publish anything',
|
|
);
|
|
|
|
const releaseBranchTag = `${major}.${minor}-stable`;
|
|
|
|
// npm will automatically tag the version as `latest` if no tag is set when we publish
|
|
// To prevent this, use `releaseBranchTag` when we don't want that (ex. releasing a patch on older release)
|
|
const tag =
|
|
prerelease != null ? 'next' : isLatest ? 'latest' : releaseBranchTag;
|
|
|
|
return {
|
|
version,
|
|
tag,
|
|
};
|
|
}
|
|
|
|
function publishPackage(packagePath, packageOptions, execOptions) {
|
|
const {tag, otp} = packageOptions;
|
|
const tagFlag = tag ? ` --tag ${tag}` : '';
|
|
const otpFlag = otp ? ` --otp ${otp}` : '';
|
|
const options = execOptions
|
|
? {...execOptions, cwd: packagePath}
|
|
: {cwd: packagePath};
|
|
|
|
return exec(`npm publish${tagFlag}${otpFlag}`, options);
|
|
}
|
|
|
|
function diffPackages(packageSpecA, packageSpecB, options) {
|
|
const result = exec(
|
|
`npm diff --diff=${packageSpecA} --diff=${packageSpecB} --diff-name-only`,
|
|
options,
|
|
);
|
|
|
|
if (result.code) {
|
|
throw new Error(
|
|
`Failed to diff ${packageSpecA} and ${packageSpecB}\n${result.stderr}`,
|
|
);
|
|
}
|
|
|
|
return result.stdout;
|
|
}
|
|
|
|
function pack(packagePath) {
|
|
const result = exec('npm pack', {
|
|
cwd: packagePath,
|
|
});
|
|
|
|
if (result.code !== 0) {
|
|
throw new Error(result.stderr);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* `package` is an object form of package.json
|
|
* `dependencies` is a map of dependency to version string
|
|
*
|
|
* This replaces both dependencies and devDependencies in package.json
|
|
*/
|
|
function applyPackageVersions(originalPackageJson, packageVersions) {
|
|
const packageJson = {...originalPackageJson};
|
|
|
|
for (const name of Object.keys(packageVersions)) {
|
|
if (
|
|
packageJson.dependencies != null &&
|
|
packageJson.dependencies[name] != null
|
|
) {
|
|
packageJson.dependencies[name] = packageVersions[name];
|
|
}
|
|
|
|
if (
|
|
packageJson.devDependencies != null &&
|
|
packageJson.devDependencies[name] != null
|
|
) {
|
|
packageJson.devDependencies[name] = packageVersions[name];
|
|
}
|
|
}
|
|
return packageJson;
|
|
}
|
|
|
|
/**
|
|
* `packageName`: name of npm package
|
|
* `tag`: npm tag like `latest` or `next`
|
|
*
|
|
* This will fetch version of `packageName` with npm tag specified
|
|
*/
|
|
function getPackageVersionStrByTag(packageName, tag) {
|
|
const npmString = tag
|
|
? `npm view ${packageName}@${tag} version`
|
|
: `npm view ${packageName} version`;
|
|
const result = exec(npmString, {silent: true});
|
|
|
|
if (result.code) {
|
|
throw new Error(`Failed to get ${tag} version from npm\n${result.stderr}`);
|
|
}
|
|
return result.stdout.trim();
|
|
}
|
|
|
|
/**
|
|
* `packageName`: name of npm package
|
|
* `spec`: spec range ex. '^0.72.0'
|
|
*
|
|
* Return an array of versions of the specified spec range or throw an error
|
|
*/
|
|
function getVersionsBySpec(packageName, spec) {
|
|
const npmString = `npm view ${packageName}@'${spec}' version --json`;
|
|
const result = exec(npmString, {silent: true});
|
|
|
|
if (result.code) {
|
|
// Special handling if no such package spec exists
|
|
if (result.stderr.includes('npm ERR! code E404')) {
|
|
/**
|
|
* npm ERR! code E404
|
|
* npm ERR! 404 No match found for version ^0.72.0
|
|
* npm ERR! 404
|
|
* npm ERR! 404 '@react-native/community-cli-plugin@^0.72.0' is not in this registry.
|
|
* npm ERR! 404
|
|
* npm ERR! 404 Note that you can also install from a
|
|
* npm ERR! 404 tarball, folder, http url, or git url.
|
|
* {
|
|
* "error": {
|
|
* "code": "E404",
|
|
* "summary": "No match found for version ^0.72.0",
|
|
* "detail": "\n '@react-native/community-cli-plugin@^0.72.0' is not in this registry.\n\nNote that you can also install from a\ntarball, folder, http url, or git url."
|
|
* }
|
|
* }
|
|
*/
|
|
const error = JSON.parse(
|
|
result.stderr
|
|
.split('\n')
|
|
.filter(line => !line.includes('npm ERR'))
|
|
.join(''),
|
|
).error;
|
|
throw new Error(error.summary);
|
|
} else {
|
|
throw new Error(`Failed: ${npmString}`);
|
|
}
|
|
}
|
|
const versions = JSON.parse(result.stdout.trim());
|
|
return !Array.isArray(versions) ? [versions] : versions;
|
|
}
|
|
|
|
module.exports = {
|
|
applyPackageVersions,
|
|
getNpmInfo,
|
|
getPackageVersionStrByTag,
|
|
getVersionsBySpec,
|
|
publishPackage,
|
|
diffPackages,
|
|
pack,
|
|
};
|