mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
set unified version (#42776)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/42776 Changelog: [Internal] set all monorepo packages (including react-native) to one version and update all inter-dependencies (including the template) Reviewed By: huntie Differential Revision: D53251917 fbshipit-source-id: 95330ca66dcb7234a3f09752ecc3ed9087ced4bf
This commit is contained in:
committed by
Facebook GitHub Bot
parent
6a8a28b80f
commit
ebc2831d5b
@@ -48,6 +48,7 @@ module.exports = {
|
||||
'<rootDir>/packages/react-native/jest/ReactNativeInternalFeatureFlagsMock.js',
|
||||
},
|
||||
moduleFileExtensions: ['fb.js'].concat(defaults.moduleFileExtensions),
|
||||
modulePathIgnorePatterns: ['scripts/.*/__fixtures__/'],
|
||||
unmockedModulePathPatterns: [
|
||||
'node_modules/react/',
|
||||
'packages/react-native/Libraries/Renderer',
|
||||
|
||||
@@ -4,48 +4,54 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
*/
|
||||
|
||||
const {readdirSync, readFileSync} = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
const ROOT_LOCATION = path.join(__dirname, '..', '..');
|
||||
const PACKAGES_LOCATION = path.join(ROOT_LOCATION, 'packages');
|
||||
const REPO_ROOT = path.join(path.dirname(__filename), '..', '..');
|
||||
const PACKAGES_LOCATION = path.join(REPO_ROOT, 'packages');
|
||||
|
||||
const DEFAULT_OPTIONS = {includeReactNative: false};
|
||||
const DEFAULT_OPTIONS /*: Options */ = {includeReactNative: false};
|
||||
|
||||
/*::
|
||||
type PackageJSON = {
|
||||
name: string,
|
||||
private?: ?boolean,
|
||||
version: string,
|
||||
dependencies: {[string]: string},
|
||||
devDependencies: {[string]: string},
|
||||
...
|
||||
};
|
||||
|
||||
type Options = {
|
||||
includeReactNative?: ?boolean,
|
||||
};
|
||||
*/
|
||||
|
||||
/**
|
||||
* Function, which returns an array of all directories inside specified location
|
||||
*
|
||||
* @param {string} source Path to directory, where this should be executed
|
||||
* @returns {string[]} List of directories names
|
||||
*/
|
||||
const getDirectories = source =>
|
||||
const getDirectories = (source /*: string */) /*: Array<string> */ =>
|
||||
readdirSync(source, {withFileTypes: true})
|
||||
.filter(file => file.isDirectory())
|
||||
.map(directory => directory.name);
|
||||
|
||||
/**
|
||||
* @callback forEachPackageCallback
|
||||
* @param {string} packageAbsolutePath
|
||||
* @param {string} packageRelativePathFromRoot
|
||||
* @param {Object} packageManifest
|
||||
*/
|
||||
|
||||
.map(directory => directory.name.toString());
|
||||
/**
|
||||
* Iterate through every package inside /packages (ignoring react-native) and call provided callback for each of them
|
||||
*
|
||||
* @param {forEachPackageCallback} callback The callback which will be called for each package
|
||||
* @param {{includeReactNative: (boolean|undefined)}} [options={}] description
|
||||
*/
|
||||
const forEachPackage = (callback, options = DEFAULT_OPTIONS) => {
|
||||
const forEachPackage = (
|
||||
callback /*: (string, string, PackageJSON) => void */,
|
||||
options /*: Options */ = DEFAULT_OPTIONS,
|
||||
) => {
|
||||
const {includeReactNative} = options;
|
||||
|
||||
// We filter react-native package on purpose, so that no CI's script will be executed for this package in future
|
||||
// Unless includeReactNative options is provided
|
||||
const packagesDirectories = getDirectories(PACKAGES_LOCATION).filter(
|
||||
directoryName => directoryName !== 'react-native' || includeReactNative,
|
||||
directoryName =>
|
||||
directoryName !== 'react-native' || includeReactNative === true,
|
||||
);
|
||||
|
||||
packagesDirectories.forEach(packageDirectory => {
|
||||
@@ -53,7 +59,7 @@ const forEachPackage = (callback, options = DEFAULT_OPTIONS) => {
|
||||
const packageRelativePathFromRoot = path.join('packages', packageDirectory);
|
||||
|
||||
const packageManifest = JSON.parse(
|
||||
readFileSync(path.join(packageAbsolutePath, 'package.json')),
|
||||
readFileSync(path.join(packageAbsolutePath, 'package.json')).toString(),
|
||||
);
|
||||
|
||||
callback(packageAbsolutePath, packageRelativePathFromRoot, packageManifest);
|
||||
|
||||
@@ -54,7 +54,7 @@ type PackageMetadata = {|
|
||||
* is an object that contains the absolute path to the package and the packageJson.
|
||||
*/
|
||||
function getPackagesToPublish() /*: PackageMap */ {
|
||||
let packages = {};
|
||||
let packages /*: PackageMap */ = {};
|
||||
|
||||
forEachPackage(
|
||||
(packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => {
|
||||
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "@monorepo/pkg-a",
|
||||
"version": "0.0.1",
|
||||
"description": "@monorepo/pkg-a",
|
||||
"dependencies": {
|
||||
"@monorepo/pkg-b": "0.0.1",
|
||||
"@monorepo/other": "0.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@monorepo/pkg-c": "0.0.1"
|
||||
}
|
||||
}
|
||||
+10
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"name": "@monorepo/pkg-b",
|
||||
"version": "0.0.2",
|
||||
"description": "@monorepo/pkg-b",
|
||||
"dependencies": {
|
||||
"@monorepo/pkg-c": "0.0.1",
|
||||
"metro-config": "^0.80.3",
|
||||
"metro-runtime": "^0.80.3"
|
||||
}
|
||||
}
|
||||
+9
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"name": "@monorepo/pkg-c",
|
||||
"version": "0.0.3",
|
||||
"description": "@monorepo/pkg-c",
|
||||
"dependencies": {
|
||||
"metro-config": "^0.80.3",
|
||||
"metro-runtime": "^0.80.3"
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"name": "react-native",
|
||||
"version": "0.0.0",
|
||||
"description": "fake react native package",
|
||||
"dependencies": {
|
||||
"@monorepo/pkg-a": "0.0.1",
|
||||
"@monorepo/pkg-b": "0.0.1",
|
||||
"@monorepo/pkg-c": "0.0.1",
|
||||
"metro-config": "^0.80.3",
|
||||
"metro-runtime": "^0.80.3"
|
||||
}
|
||||
}
|
||||
+15
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"name": "react-native-test-template",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"react": "18.2.0",
|
||||
"react-native": "0.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@monorepo/pkg-a": "0.0.1",
|
||||
"@monorepo/pkg-c": "0.0.0",
|
||||
"@types/react": "^18.2.6",
|
||||
"@types/react-test-renderer": "^18.0.0"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`setVersion updates all public packages to version: monorepo-pkg-a 1`] = `
|
||||
"{
|
||||
\\"name\\": \\"@monorepo/pkg-a\\",
|
||||
\\"version\\": \\"0.80.0\\",
|
||||
\\"description\\": \\"@monorepo/pkg-a\\",
|
||||
\\"dependencies\\": {
|
||||
\\"@monorepo/pkg-b\\": \\"0.80.0\\",
|
||||
\\"@monorepo/other\\": \\"0.0.1\\"
|
||||
},
|
||||
\\"devDependencies\\": {
|
||||
\\"@monorepo/pkg-c\\": \\"0.80.0\\"
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`setVersion updates all public packages to version: monorepo-pkg-b 1`] = `
|
||||
"{
|
||||
\\"name\\": \\"@monorepo/pkg-b\\",
|
||||
\\"version\\": \\"0.80.0\\",
|
||||
\\"description\\": \\"@monorepo/pkg-b\\",
|
||||
\\"dependencies\\": {
|
||||
\\"@monorepo/pkg-c\\": \\"0.80.0\\",
|
||||
\\"metro-config\\": \\"^0.80.3\\",
|
||||
\\"metro-runtime\\": \\"^0.80.3\\"
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`setVersion updates all public packages to version: monorepo-pkg-c 1`] = `
|
||||
"{
|
||||
\\"name\\": \\"@monorepo/pkg-c\\",
|
||||
\\"version\\": \\"0.80.0\\",
|
||||
\\"description\\": \\"@monorepo/pkg-c\\",
|
||||
\\"dependencies\\": {
|
||||
\\"metro-config\\": \\"^0.80.3\\",
|
||||
\\"metro-runtime\\": \\"^0.80.3\\"
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`setVersion updates all public packages to version: react-native 1`] = `
|
||||
"{
|
||||
\\"name\\": \\"react-native\\",
|
||||
\\"version\\": \\"0.80.0\\",
|
||||
\\"description\\": \\"fake react native package\\",
|
||||
\\"dependencies\\": {
|
||||
\\"@monorepo/pkg-a\\": \\"0.80.0\\",
|
||||
\\"@monorepo/pkg-b\\": \\"0.80.0\\",
|
||||
\\"@monorepo/pkg-c\\": \\"0.80.0\\",
|
||||
\\"metro-config\\": \\"^0.80.3\\",
|
||||
\\"metro-runtime\\": \\"^0.80.3\\"
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
|
||||
exports[`setVersion updates all public packages to version: template 1`] = `
|
||||
"{
|
||||
\\"name\\": \\"react-native-test-template\\",
|
||||
\\"version\\": \\"0.0.1\\",
|
||||
\\"private\\": true,
|
||||
\\"dependencies\\": {
|
||||
\\"react\\": \\"18.2.0\\",
|
||||
\\"react-native\\": \\"0.80.0\\"
|
||||
},
|
||||
\\"devDependencies\\": {
|
||||
\\"@monorepo/pkg-a\\": \\"0.80.0\\",
|
||||
\\"@monorepo/pkg-c\\": \\"0.80.0\\",
|
||||
\\"@types/react\\": \\"^18.2.6\\",
|
||||
\\"@types/react-test-renderer\\": \\"^18.0.0\\"
|
||||
}
|
||||
}
|
||||
"
|
||||
`;
|
||||
@@ -0,0 +1,46 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
*/
|
||||
|
||||
const setVersion = require('../index');
|
||||
const path = require('path');
|
||||
|
||||
describe('setVersion', () => {
|
||||
beforeAll(() => {
|
||||
jest.mock('path', () => {
|
||||
// $FlowIgnore[underconstrained-implicit-instantiation]
|
||||
const originalPath = jest.requireActual('path');
|
||||
return {
|
||||
...originalPath,
|
||||
dirname: () => originalPath.join(__dirname, '__fixtures__/two/levels'),
|
||||
};
|
||||
});
|
||||
|
||||
jest.mock('fs', () => {
|
||||
// $FlowIgnore[underconstrained-implicit-instantiation]
|
||||
const originalFs = jest.requireActual('fs');
|
||||
|
||||
return {
|
||||
...originalFs,
|
||||
writeFileSync: (packagePath, content) => {
|
||||
expect(content).toMatchSnapshot(
|
||||
path.basename(path.join(packagePath, '..')),
|
||||
);
|
||||
},
|
||||
};
|
||||
});
|
||||
});
|
||||
test('updates all public packages to version', () => {
|
||||
setVersion('0.80.0');
|
||||
});
|
||||
afterAll(() => {
|
||||
jest.unmock('path');
|
||||
jest.unmock('fs');
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,122 @@
|
||||
/**
|
||||
* 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.
|
||||
*
|
||||
* @flow strict-local
|
||||
* @format
|
||||
* @oncall react-native
|
||||
*/
|
||||
|
||||
'use strict';
|
||||
|
||||
const forEachPackage = require('../../monorepo/for-each-package');
|
||||
const {readFileSync, writeFileSync} = require('fs');
|
||||
const path = require('path');
|
||||
const yargs = require('yargs');
|
||||
|
||||
function getPublicPackages() {
|
||||
// eslint-disable-next-line func-call-spacing
|
||||
const packages = new Set /*::<string>*/();
|
||||
forEachPackage(
|
||||
(_, __, packageJson) => {
|
||||
if (packageJson.private !== true) {
|
||||
packages.add(packageJson.name);
|
||||
}
|
||||
},
|
||||
{includeReactNative: true},
|
||||
);
|
||||
return packages;
|
||||
}
|
||||
|
||||
function setVersion(version /*: string */) {
|
||||
const publicPackages = getPublicPackages();
|
||||
|
||||
forEachPackage(
|
||||
(packageAbsolutePath, _, packageJson) => {
|
||||
if (packageJson.private === true) {
|
||||
return;
|
||||
}
|
||||
|
||||
packageJson.version = version;
|
||||
|
||||
if (packageJson.dependencies != null) {
|
||||
for (const dependency of Object.keys(packageJson.dependencies)) {
|
||||
if (publicPackages.has(dependency)) {
|
||||
packageJson.dependencies[dependency] = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (packageJson.devDependencies != null) {
|
||||
for (const devDependency of Object.keys(packageJson.devDependencies)) {
|
||||
if (publicPackages.has(devDependency)) {
|
||||
packageJson.devDependencies[devDependency] = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
writeFileSync(
|
||||
path.join(packageAbsolutePath, 'package.json'),
|
||||
JSON.stringify(packageJson, null, 2) + '\n',
|
||||
'utf-8',
|
||||
);
|
||||
|
||||
// Update template package.json
|
||||
if (packageJson.name === 'react-native') {
|
||||
const templatePackageJsonPath = path.join(
|
||||
packageAbsolutePath,
|
||||
'template',
|
||||
'package.json',
|
||||
);
|
||||
const templatePackageJson = JSON.parse(
|
||||
readFileSync(templatePackageJsonPath).toString(),
|
||||
);
|
||||
if (templatePackageJson.dependencies != null) {
|
||||
for (const dependency of Object.keys(
|
||||
templatePackageJson.dependencies,
|
||||
)) {
|
||||
if (publicPackages.has(dependency)) {
|
||||
templatePackageJson.dependencies[dependency] = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (templatePackageJson.devDependencies != null) {
|
||||
for (const devDependency of Object.keys(
|
||||
templatePackageJson.devDependencies,
|
||||
)) {
|
||||
if (publicPackages.has(devDependency)) {
|
||||
templatePackageJson.devDependencies[devDependency] = version;
|
||||
}
|
||||
}
|
||||
}
|
||||
writeFileSync(
|
||||
templatePackageJsonPath,
|
||||
JSON.stringify(templatePackageJson, null, 2) + '\n',
|
||||
'utf-8',
|
||||
);
|
||||
}
|
||||
},
|
||||
{includeReactNative: true},
|
||||
);
|
||||
}
|
||||
|
||||
module.exports = setVersion;
|
||||
|
||||
if (require.main === module) {
|
||||
const {toVersion} = yargs(process.argv.slice(2))
|
||||
.command(
|
||||
'$0 <to-version>',
|
||||
'Update all monorepo packages to <to-version>',
|
||||
args =>
|
||||
args.positional('to-version', {
|
||||
type: 'string',
|
||||
description: 'Set the version of all packages to this value',
|
||||
required: true,
|
||||
}),
|
||||
)
|
||||
.parseSync();
|
||||
setVersion(toVersion);
|
||||
}
|
||||
Reference in New Issue
Block a user