mirror of
https://github.com/facebook/react-native.git
synced 2024-11-21 22:10:14 +00:00
Refactor remaining forEachPackage call sites (#43112)
Summary: Pull Request resolved: https://github.com/facebook/react-native/pull/43112 Changelog: [Internal] Reviewed By: cipolleschi Differential Revision: D53942028 fbshipit-source-id: 335bff3c3a31026bae7140fac1d1a6aae23a0f1e
This commit is contained in:
parent
4ecf57ead2
commit
d6bf51cad9
@ -13,7 +13,7 @@
|
||||
|
||||
const {retry} = require('../circleci/retry');
|
||||
const {REPO_ROOT} = require('../consts');
|
||||
const forEachPackage = require('../monorepo/for-each-package');
|
||||
const {getPackages} = require('../utils/monorepo');
|
||||
const {
|
||||
VERDACCIO_SERVER_URL,
|
||||
VERDACCIO_STORAGE_PATH,
|
||||
@ -22,6 +22,7 @@ const {
|
||||
const {parseArgs} = require('@pkgjs/parseargs');
|
||||
const chalk = require('chalk');
|
||||
const {execSync} = require('child_process');
|
||||
const path = require('path');
|
||||
|
||||
const config = {
|
||||
options: {
|
||||
@ -86,26 +87,28 @@ async function initNewProjectFromSource(
|
||||
console.log('\nDone ✅');
|
||||
|
||||
console.log('Publishing packages to local npm proxy\n');
|
||||
forEachPackage(
|
||||
(packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => {
|
||||
if (packageManifest.private) {
|
||||
return;
|
||||
}
|
||||
const packages = await getPackages({
|
||||
includeReactNative: false,
|
||||
includePrivate: false,
|
||||
});
|
||||
|
||||
const desc = `${packageManifest.name} (${packageRelativePathFromRoot})`;
|
||||
process.stdout.write(
|
||||
`${desc} ${chalk.dim('.').repeat(Math.max(0, 72 - desc.length))} `,
|
||||
);
|
||||
execSync(
|
||||
`npm publish --registry ${VERDACCIO_SERVER_URL} --access public`,
|
||||
{
|
||||
cwd: packageAbsolutePath,
|
||||
stdio: verbose ? 'inherit' : [process.stderr],
|
||||
},
|
||||
);
|
||||
process.stdout.write(chalk.reset.inverse.bold.green(' DONE ') + '\n');
|
||||
},
|
||||
);
|
||||
for (const {path: packagePath, packageJson} of Object.values(packages)) {
|
||||
const desc = `${packageJson.name} (${path.relative(
|
||||
REPO_ROOT,
|
||||
packagePath,
|
||||
)})`;
|
||||
process.stdout.write(
|
||||
`${desc} ${chalk.dim('.').repeat(Math.max(0, 72 - desc.length))} `,
|
||||
);
|
||||
execSync(
|
||||
`npm publish --registry ${VERDACCIO_SERVER_URL} --access public`,
|
||||
{
|
||||
cwd: packagePath,
|
||||
stdio: verbose ? 'inherit' : [process.stderr],
|
||||
},
|
||||
);
|
||||
process.stdout.write(chalk.reset.inverse.bold.green(' DONE ') + '\n');
|
||||
}
|
||||
console.log('\nDone ✅');
|
||||
|
||||
console.log('Running react-native init without install');
|
||||
|
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
const {REACT_NATIVE_PACKAGE_DIR, REPO_ROOT, SCRIPTS_DIR} = require('../consts');
|
||||
const forEachPackage = require('../monorepo/for-each-package');
|
||||
const {getPackages} = require('../utils/monorepo');
|
||||
const tryExecNTimes = require('./utils/try-n-times');
|
||||
const {setupVerdaccio} = require('./utils/verdaccio');
|
||||
const {execFileSync, spawn} = require('child_process');
|
||||
@ -47,275 +47,282 @@ function describe(message /*: string */) {
|
||||
echo(`\n\n>>>>> ${message}\n\n\n`);
|
||||
}
|
||||
|
||||
try {
|
||||
if (argv.android) {
|
||||
describe('Compile Android binaries');
|
||||
async function main() {
|
||||
try {
|
||||
if (argv.android) {
|
||||
describe('Compile Android binaries');
|
||||
if (
|
||||
exec(
|
||||
'./gradlew publishAllToMavenTempLocal -Pjobs=1 -Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Failed to compile Android binaries');
|
||||
}
|
||||
}
|
||||
|
||||
describe('Create react-native package');
|
||||
if (
|
||||
exec(
|
||||
'./gradlew publishAllToMavenTempLocal -Pjobs=1 -Dorg.gradle.jvmargs="-Xmx512m -XX:+HeapDumpOnOutOfMemoryError"',
|
||||
'node ./scripts/releases/set-rn-version.js --to-version 1000.0.0 --build-type dry-run',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Failed to compile Android binaries');
|
||||
throw new Error(
|
||||
'Failed to set version and update package.json ready for release',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
describe('Create react-native package');
|
||||
if (
|
||||
exec(
|
||||
'node ./scripts/releases/set-rn-version.js --to-version 1000.0.0 --build-type dry-run',
|
||||
).code
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to set version and update package.json ready for release',
|
||||
if (exec('npm pack', {cwd: REACT_NATIVE_PACKAGE_DIR}).code) {
|
||||
throw new Error('Failed to pack react-native');
|
||||
}
|
||||
|
||||
const REACT_NATIVE_PACKAGE = path.join(
|
||||
REACT_NATIVE_PACKAGE_DIR,
|
||||
'react-native-*.tgz',
|
||||
);
|
||||
}
|
||||
|
||||
if (exec('npm pack', {cwd: REACT_NATIVE_PACKAGE_DIR}).code) {
|
||||
throw new Error('Failed to pack react-native');
|
||||
}
|
||||
describe('Set up Verdaccio');
|
||||
VERDACCIO_PID = setupVerdaccio();
|
||||
|
||||
const REACT_NATIVE_PACKAGE = path.join(
|
||||
REACT_NATIVE_PACKAGE_DIR,
|
||||
'react-native-*.tgz',
|
||||
);
|
||||
describe('Build and publish packages');
|
||||
exec('node ./scripts/build/build.js', {cwd: REPO_ROOT});
|
||||
|
||||
describe('Set up Verdaccio');
|
||||
VERDACCIO_PID = setupVerdaccio();
|
||||
|
||||
describe('Build and publish packages');
|
||||
exec('node ./scripts/build/build.js', {cwd: REPO_ROOT});
|
||||
|
||||
forEachPackage(
|
||||
(packageAbsolutePath, packageRelativePathFromRoot, packageManifest) => {
|
||||
if (packageManifest.private) {
|
||||
return;
|
||||
}
|
||||
const packages = await getPackages({
|
||||
includeReactNative: false,
|
||||
includePrivate: false,
|
||||
});
|
||||
|
||||
for (const {path: packageAbsolutePath} of Object.values(packages)) {
|
||||
exec(
|
||||
'npm publish --registry http://localhost:4873 --yes --access public',
|
||||
{cwd: packageAbsolutePath},
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
describe('Scaffold a basic React Native app from template');
|
||||
execFileSync('rsync', [
|
||||
'-a',
|
||||
`${REPO_ROOT}/packages/react-native/template`,
|
||||
REACT_NATIVE_TEMP_DIR,
|
||||
]);
|
||||
cd(REACT_NATIVE_APP_DIR);
|
||||
|
||||
mv('_bundle', '.bundle');
|
||||
mv('_eslintrc.js', '.eslintrc.js');
|
||||
mv('_prettierrc.js', '.prettierrc.js');
|
||||
mv('_watchmanconfig', '.watchmanconfig');
|
||||
fs.writeFileSync('.npmrc', 'registry=http://localhost:4873');
|
||||
|
||||
describe('Install React Native package');
|
||||
exec(`npm install ${REACT_NATIVE_PACKAGE}`);
|
||||
|
||||
describe('Install node_modules');
|
||||
if (
|
||||
tryExecNTimes(
|
||||
() => {
|
||||
return exec('npm install').code;
|
||||
},
|
||||
numberOfRetries,
|
||||
() => exec('sleep 10s'),
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to execute npm install. Most common reason is npm registry connectivity, try again',
|
||||
);
|
||||
}
|
||||
exec('rm -rf ./node_modules/react-native/template');
|
||||
|
||||
if (argv.android) {
|
||||
describe('Install end-to-end framework');
|
||||
if (
|
||||
tryExecNTimes(
|
||||
() =>
|
||||
exec(
|
||||
'yarn add --dev appium@1.11.1 mocha@2.4.5 wd@1.11.1 colors@1.0.3 pretty-data2@0.40.1',
|
||||
{silent: true},
|
||||
).code,
|
||||
numberOfRetries,
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to install appium. Most common reason is npm registry connectivity, try again.',
|
||||
);
|
||||
}
|
||||
cp(`${SCRIPTS_DIR}/android-e2e-test.js`, 'android-e2e-test.js');
|
||||
cd('android');
|
||||
describe('Download Maven deps');
|
||||
exec('./gradlew :app:copyDownloadableDepsToLibs');
|
||||
cd('..');
|
||||
|
||||
describe('Generate key');
|
||||
exec('rm android/app/debug.keystore');
|
||||
if (
|
||||
exec(
|
||||
'keytool -genkey -v -keystore android/app/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US"',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Key could not be generated');
|
||||
}
|
||||
|
||||
// $FlowFixMe[incompatible-type]
|
||||
describe(`Start appium server, ${APPIUM_PID}`);
|
||||
const appiumProcess = spawn('node', ['./node_modules/.bin/appium']);
|
||||
APPIUM_PID = appiumProcess.pid;
|
||||
describe('Scaffold a basic React Native app from template');
|
||||
execFileSync('rsync', [
|
||||
'-a',
|
||||
`${REPO_ROOT}/packages/react-native/template`,
|
||||
REACT_NATIVE_TEMP_DIR,
|
||||
]);
|
||||
cd(REACT_NATIVE_APP_DIR);
|
||||
|
||||
describe('Build the app');
|
||||
if (exec('react-native run-android').code) {
|
||||
throw new Error('Could not execute react-native run-android');
|
||||
}
|
||||
mv('_bundle', '.bundle');
|
||||
mv('_eslintrc.js', '.eslintrc.js');
|
||||
mv('_prettierrc.js', '.prettierrc.js');
|
||||
mv('_watchmanconfig', '.watchmanconfig');
|
||||
fs.writeFileSync('.npmrc', 'registry=http://localhost:4873');
|
||||
|
||||
// $FlowFixMe[incompatible-type]
|
||||
describe(`Start Metro, ${SERVER_PID}`);
|
||||
// shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn
|
||||
const packagerProcess = spawn('yarn', ['start', '--max-workers 1']);
|
||||
SERVER_PID = packagerProcess.pid;
|
||||
// wait a bit to allow packager to startup
|
||||
exec('sleep 15s');
|
||||
describe('Test: Android end-to-end test');
|
||||
describe('Install React Native package');
|
||||
exec(`npm install ${REACT_NATIVE_PACKAGE}`);
|
||||
|
||||
describe('Install node_modules');
|
||||
if (
|
||||
tryExecNTimes(
|
||||
() => {
|
||||
return exec('node node_modules/.bin/_mocha android-e2e-test.js').code;
|
||||
return exec('npm install').code;
|
||||
},
|
||||
numberOfRetries,
|
||||
() => exec('sleep 10s'),
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to run Android end-to-end tests. Most likely the code is broken.',
|
||||
'Failed to execute npm install. Most common reason is npm registry connectivity, try again',
|
||||
);
|
||||
}
|
||||
}
|
||||
exec('rm -rf ./node_modules/react-native/template');
|
||||
|
||||
if (argv.ios) {
|
||||
cd('ios');
|
||||
// shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn
|
||||
const packagerEnv = Object.create(process.env);
|
||||
// $FlowFixMe[prop-missing]
|
||||
packagerEnv.REACT_NATIVE_MAX_WORKERS = 1;
|
||||
describe('Start Metro');
|
||||
const packagerProcess = spawn('yarn', ['start'], {
|
||||
stdio: 'inherit',
|
||||
env: packagerEnv,
|
||||
});
|
||||
SERVER_PID = packagerProcess.pid;
|
||||
exec('sleep 15s');
|
||||
// prepare cache to reduce chances of possible red screen "Can't find variable __fbBatchedBridge..."
|
||||
exec(
|
||||
'response=$(curl --write-out %{http_code} --silent --output /dev/null localhost:8081/index.bundle?platform=ios&dev=true)',
|
||||
);
|
||||
echo(`Metro is running, ${SERVER_PID}`);
|
||||
if (argv.android) {
|
||||
describe('Install end-to-end framework');
|
||||
if (
|
||||
tryExecNTimes(
|
||||
() =>
|
||||
exec(
|
||||
'yarn add --dev appium@1.11.1 mocha@2.4.5 wd@1.11.1 colors@1.0.3 pretty-data2@0.40.1',
|
||||
{silent: true},
|
||||
).code,
|
||||
numberOfRetries,
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to install appium. Most common reason is npm registry connectivity, try again.',
|
||||
);
|
||||
}
|
||||
cp(`${SCRIPTS_DIR}/android-e2e-test.js`, 'android-e2e-test.js');
|
||||
cd('android');
|
||||
describe('Download Maven deps');
|
||||
exec('./gradlew :app:copyDownloadableDepsToLibs');
|
||||
cd('..');
|
||||
|
||||
describe('Install CocoaPod dependencies');
|
||||
exec('bundle exec pod install');
|
||||
describe('Generate key');
|
||||
exec('rm android/app/debug.keystore');
|
||||
if (
|
||||
exec(
|
||||
'keytool -genkey -v -keystore android/app/debug.keystore -storepass android -alias androiddebugkey -keypass android -keyalg RSA -keysize 2048 -validity 10000 -dname "CN=Android Debug,O=Android,C=US"',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Key could not be generated');
|
||||
}
|
||||
|
||||
describe('Test: iOS end-to-end test');
|
||||
if (
|
||||
// TODO: Get target OS and simulator from .tests.env
|
||||
tryExecNTimes(
|
||||
() => {
|
||||
return exec(
|
||||
[
|
||||
'xcodebuild',
|
||||
'-workspace',
|
||||
'"HelloWorld.xcworkspace"',
|
||||
'-destination',
|
||||
'"platform=iOS Simulator,name=iPhone 8,OS=13.3"',
|
||||
'-scheme',
|
||||
'"HelloWorld"',
|
||||
'-sdk',
|
||||
'iphonesimulator',
|
||||
'-UseModernBuildSystem=NO',
|
||||
'test',
|
||||
].join(' ') +
|
||||
' | ' +
|
||||
// $FlowFixMe[incompatible-type]
|
||||
describe(`Start appium server, ${APPIUM_PID}`);
|
||||
const appiumProcess = spawn('node', ['./node_modules/.bin/appium']);
|
||||
APPIUM_PID = appiumProcess.pid;
|
||||
|
||||
describe('Build the app');
|
||||
if (exec('react-native run-android').code) {
|
||||
throw new Error('Could not execute react-native run-android');
|
||||
}
|
||||
|
||||
// $FlowFixMe[incompatible-type]
|
||||
describe(`Start Metro, ${SERVER_PID}`);
|
||||
// shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn
|
||||
const packagerProcess = spawn('yarn', ['start', '--max-workers 1']);
|
||||
SERVER_PID = packagerProcess.pid;
|
||||
// wait a bit to allow packager to startup
|
||||
exec('sleep 15s');
|
||||
describe('Test: Android end-to-end test');
|
||||
if (
|
||||
tryExecNTimes(
|
||||
() => {
|
||||
return exec('node node_modules/.bin/_mocha android-e2e-test.js')
|
||||
.code;
|
||||
},
|
||||
numberOfRetries,
|
||||
() => exec('sleep 10s'),
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to run Android end-to-end tests. Most likely the code is broken.',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (argv.ios) {
|
||||
cd('ios');
|
||||
// shelljs exec('', {async: true}) does not emit stdout events, so we rely on good old spawn
|
||||
const packagerEnv = Object.create(process.env);
|
||||
// $FlowFixMe[prop-missing]
|
||||
packagerEnv.REACT_NATIVE_MAX_WORKERS = 1;
|
||||
describe('Start Metro');
|
||||
const packagerProcess = spawn('yarn', ['start'], {
|
||||
stdio: 'inherit',
|
||||
env: packagerEnv,
|
||||
});
|
||||
SERVER_PID = packagerProcess.pid;
|
||||
exec('sleep 15s');
|
||||
// prepare cache to reduce chances of possible red screen "Can't find variable __fbBatchedBridge..."
|
||||
exec(
|
||||
'response=$(curl --write-out %{http_code} --silent --output /dev/null localhost:8081/index.bundle?platform=ios&dev=true)',
|
||||
);
|
||||
echo(`Metro is running, ${SERVER_PID}`);
|
||||
|
||||
describe('Install CocoaPod dependencies');
|
||||
exec('bundle exec pod install');
|
||||
|
||||
describe('Test: iOS end-to-end test');
|
||||
if (
|
||||
// TODO: Get target OS and simulator from .tests.env
|
||||
tryExecNTimes(
|
||||
() => {
|
||||
return exec(
|
||||
[
|
||||
'xcbeautify',
|
||||
'--report',
|
||||
'junit',
|
||||
'--reportPath',
|
||||
'"~/react-native/reports/junit/iOS-e2e/results.xml"',
|
||||
'xcodebuild',
|
||||
'-workspace',
|
||||
'"HelloWorld.xcworkspace"',
|
||||
'-destination',
|
||||
'"platform=iOS Simulator,name=iPhone 8,OS=13.3"',
|
||||
'-scheme',
|
||||
'"HelloWorld"',
|
||||
'-sdk',
|
||||
'iphonesimulator',
|
||||
'-UseModernBuildSystem=NO',
|
||||
'test',
|
||||
].join(' ') +
|
||||
' && exit ${PIPESTATUS[0]}',
|
||||
).code;
|
||||
},
|
||||
numberOfRetries,
|
||||
() => exec('sleep 10s'),
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to run iOS end-to-end tests. Most likely the code is broken.',
|
||||
);
|
||||
}
|
||||
cd('..');
|
||||
}
|
||||
|
||||
if (argv.js) {
|
||||
// Check the packager produces a bundle (doesn't throw an error)
|
||||
describe('Test: Verify packager can generate an Android bundle');
|
||||
if (
|
||||
exec(
|
||||
'yarn react-native bundle --verbose --entry-file index.js --platform android --dev true --bundle-output android-bundle.js --max-workers 1',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Could not build Android bundle');
|
||||
' | ' +
|
||||
[
|
||||
'xcbeautify',
|
||||
'--report',
|
||||
'junit',
|
||||
'--reportPath',
|
||||
'"~/react-native/reports/junit/iOS-e2e/results.xml"',
|
||||
].join(' ') +
|
||||
' && exit ${PIPESTATUS[0]}',
|
||||
).code;
|
||||
},
|
||||
numberOfRetries,
|
||||
() => exec('sleep 10s'),
|
||||
)
|
||||
) {
|
||||
throw new Error(
|
||||
'Failed to run iOS end-to-end tests. Most likely the code is broken.',
|
||||
);
|
||||
}
|
||||
cd('..');
|
||||
}
|
||||
|
||||
describe('Test: Verify packager can generate an iOS bundle');
|
||||
if (
|
||||
exec(
|
||||
'yarn react-native bundle --entry-file index.js --platform ios --dev true --bundle-output ios-bundle.js --max-workers 1',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Could not build iOS bundle');
|
||||
}
|
||||
if (argv.js) {
|
||||
// Check the packager produces a bundle (doesn't throw an error)
|
||||
describe('Test: Verify packager can generate an Android bundle');
|
||||
if (
|
||||
exec(
|
||||
'yarn react-native bundle --verbose --entry-file index.js --platform android --dev true --bundle-output android-bundle.js --max-workers 1',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Could not build Android bundle');
|
||||
}
|
||||
|
||||
describe('Test: TypeScript typechecking');
|
||||
if (exec('yarn tsc').code) {
|
||||
throw new Error('Typechecking errors were found');
|
||||
}
|
||||
describe('Test: Verify packager can generate an iOS bundle');
|
||||
if (
|
||||
exec(
|
||||
'yarn react-native bundle --entry-file index.js --platform ios --dev true --bundle-output ios-bundle.js --max-workers 1',
|
||||
).code
|
||||
) {
|
||||
throw new Error('Could not build iOS bundle');
|
||||
}
|
||||
|
||||
describe('Test: Jest tests');
|
||||
if (exec('yarn test').code) {
|
||||
throw new Error('Jest tests failed');
|
||||
}
|
||||
describe('Test: TypeScript typechecking');
|
||||
if (exec('yarn tsc').code) {
|
||||
throw new Error('Typechecking errors were found');
|
||||
}
|
||||
|
||||
// TODO: ESLint infinitely hangs when running in the environment created by
|
||||
// this script, but not projects generated by `react-native init`.
|
||||
/*
|
||||
describe('Test: Jest tests');
|
||||
if (exec('yarn test').code) {
|
||||
throw new Error('Jest tests failed');
|
||||
}
|
||||
|
||||
// TODO: ESLint infinitely hangs when running in the environment created by
|
||||
// this script, but not projects generated by `react-native init`.
|
||||
/*
|
||||
describe('Test: ESLint/Prettier linting and formatting');
|
||||
if (exec('yarn lint').code) {
|
||||
echo('linting errors were found');
|
||||
exitCode = 1;
|
||||
throw Error(exitCode);
|
||||
}*/
|
||||
}
|
||||
exitCode = 0;
|
||||
} finally {
|
||||
describe('Clean up');
|
||||
if (SERVER_PID) {
|
||||
echo(`Killing packager ${SERVER_PID}`);
|
||||
exec(`kill -9 ${SERVER_PID}`);
|
||||
// this is quite drastic but packager starts a daemon that we can't kill by killing the parent process
|
||||
// it will be fixed in April (quote David Aurelio), so until then we will kill the zombie by the port number
|
||||
exec("lsof -i tcp:8081 | awk 'NR!=1 {print $2}' | xargs kill");
|
||||
}
|
||||
if (APPIUM_PID) {
|
||||
echo(`Killing appium ${APPIUM_PID}`);
|
||||
exec(`kill -9 ${APPIUM_PID}`);
|
||||
}
|
||||
if (VERDACCIO_PID) {
|
||||
echo(`Killing verdaccio ${VERDACCIO_PID}`);
|
||||
exec(`kill -9 ${VERDACCIO_PID}`);
|
||||
}
|
||||
}
|
||||
exitCode = 0;
|
||||
} finally {
|
||||
describe('Clean up');
|
||||
if (SERVER_PID) {
|
||||
echo(`Killing packager ${SERVER_PID}`);
|
||||
exec(`kill -9 ${SERVER_PID}`);
|
||||
// this is quite drastic but packager starts a daemon that we can't kill by killing the parent process
|
||||
// it will be fixed in April (quote David Aurelio), so until then we will kill the zombie by the port number
|
||||
exec("lsof -i tcp:8081 | awk 'NR!=1 {print $2}' | xargs kill");
|
||||
}
|
||||
if (APPIUM_PID) {
|
||||
echo(`Killing appium ${APPIUM_PID}`);
|
||||
exec(`kill -9 ${APPIUM_PID}`);
|
||||
}
|
||||
if (VERDACCIO_PID) {
|
||||
echo(`Killing verdaccio ${VERDACCIO_PID}`);
|
||||
exec(`kill -9 ${VERDACCIO_PID}`);
|
||||
}
|
||||
exit(exitCode);
|
||||
}
|
||||
|
||||
if (require.main === module) {
|
||||
// eslint-disable-next-line no-void
|
||||
void main();
|
||||
}
|
||||
exit(exitCode);
|
||||
|
@ -16,8 +16,6 @@ jest.mock('fs', () => ({
|
||||
readFileSync: jest.fn(() => '{}'),
|
||||
}));
|
||||
|
||||
jest.mock('../for-each-package', () => callback => {});
|
||||
|
||||
describe('bumpPackageVersionTest', () => {
|
||||
it('updates patch version of the package', () => {
|
||||
const mockedPackageLocation = '~/packages/assets';
|
||||
|
@ -1,70 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
const forEachPackage = require('../for-each-package');
|
||||
const {readdirSync, readFileSync} = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
jest.mock('fs', () => ({
|
||||
readdirSync: jest.fn(),
|
||||
readFileSync: jest.fn(),
|
||||
}));
|
||||
|
||||
describe('forEachPackage', () => {
|
||||
it('executes callback call with parameters', () => {
|
||||
const callback = jest.fn();
|
||||
const mockedPackageManifest = '{"name": "my-new-package"}';
|
||||
const mockedParsedPackageManifest = JSON.parse(mockedPackageManifest);
|
||||
const mockedPackageName = 'my-new-package';
|
||||
|
||||
readdirSync.mockImplementationOnce(() => [
|
||||
{name: mockedPackageName, isDirectory: () => true},
|
||||
]);
|
||||
readFileSync.mockImplementationOnce(() => mockedPackageManifest);
|
||||
|
||||
forEachPackage(callback);
|
||||
|
||||
expect(callback).toHaveBeenCalledWith(
|
||||
path.join(__dirname, '..', '..', '..', 'packages', mockedPackageName),
|
||||
path.join('packages', mockedPackageName),
|
||||
mockedParsedPackageManifest,
|
||||
);
|
||||
});
|
||||
|
||||
it('filters react-native folder by default', () => {
|
||||
const callback = jest.fn();
|
||||
readdirSync.mockImplementationOnce(() => [
|
||||
{name: 'react-native', isDirectory: () => true},
|
||||
]);
|
||||
|
||||
forEachPackage(callback);
|
||||
|
||||
expect(callback).not.toHaveBeenCalled();
|
||||
});
|
||||
|
||||
it('includes react-native, if such option is provided', () => {
|
||||
const callback = jest.fn();
|
||||
const mockedPackageManifest = '{"name": "react-native"}';
|
||||
const mockedParsedPackageManifest = JSON.parse(mockedPackageManifest);
|
||||
const mockedPackageName = 'react-native';
|
||||
|
||||
readdirSync.mockImplementationOnce(() => [
|
||||
{name: 'react-native', isDirectory: () => true},
|
||||
]);
|
||||
readFileSync.mockImplementationOnce(() => mockedPackageManifest);
|
||||
|
||||
forEachPackage(callback, {includeReactNative: true});
|
||||
|
||||
expect(callback).toHaveBeenCalledWith(
|
||||
path.join(__dirname, '..', '..', '..', 'packages', mockedPackageName),
|
||||
path.join('packages', mockedPackageName),
|
||||
mockedParsedPackageManifest,
|
||||
);
|
||||
});
|
||||
});
|
@ -4,10 +4,16 @@
|
||||
* This source code is licensed under the MIT license found in the
|
||||
* LICENSE file in the root directory of this source tree.
|
||||
*
|
||||
* @flow
|
||||
* @format
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
const forEachPackage = require('./for-each-package');
|
||||
/*::
|
||||
import type {PackageJson} from '../utils/monorepo';
|
||||
*/
|
||||
|
||||
const {getPackages} = require('../utils/monorepo');
|
||||
const {readFileSync, writeFileSync} = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
@ -19,12 +25,13 @@ const TEMPLATE_LOCATION = path.join(
|
||||
'template',
|
||||
);
|
||||
|
||||
const readJSONFile = pathToFile => JSON.parse(readFileSync(pathToFile));
|
||||
const readJSONFile = (pathToFile /*: string */) /*: PackageJson */ =>
|
||||
JSON.parse(readFileSync(pathToFile, 'utf-8'));
|
||||
|
||||
const checkIfShouldUpdateDependencyPackageVersion = (
|
||||
consumerPackageAbsolutePath,
|
||||
updatedPackageName,
|
||||
updatedPackageVersion,
|
||||
consumerPackageAbsolutePath /*: string */,
|
||||
updatedPackageName /*: string */,
|
||||
updatedPackageVersion /*: string */,
|
||||
) => {
|
||||
const consumerPackageManifestPath = path.join(
|
||||
consumerPackageAbsolutePath,
|
||||
@ -91,8 +98,18 @@ const checkIfShouldUpdateDependencyPackageVersion = (
|
||||
}
|
||||
};
|
||||
|
||||
const alignPackageVersions = () => {
|
||||
forEachPackage((_, __, packageManifest) => {
|
||||
async function alignPackageVersions() {
|
||||
const allPackages = await getPackages({
|
||||
includeReactNative: true,
|
||||
includePrivate: true,
|
||||
});
|
||||
const packagesExcludingReactNative = Object.keys(allPackages).filter(
|
||||
packageName => packageName !== 'react-native',
|
||||
);
|
||||
|
||||
for (const packageName of packagesExcludingReactNative) {
|
||||
const {packageJson: packageManifest} = allPackages[packageName];
|
||||
|
||||
checkIfShouldUpdateDependencyPackageVersion(
|
||||
ROOT_LOCATION,
|
||||
packageManifest.name,
|
||||
@ -105,16 +122,14 @@ const alignPackageVersions = () => {
|
||||
packageManifest.version,
|
||||
);
|
||||
|
||||
forEachPackage(
|
||||
pathToPackage =>
|
||||
checkIfShouldUpdateDependencyPackageVersion(
|
||||
pathToPackage,
|
||||
packageManifest.name,
|
||||
packageManifest.version,
|
||||
),
|
||||
{includeReactNative: true},
|
||||
);
|
||||
});
|
||||
};
|
||||
for (const {path: pathToPackage} of Object.values(allPackages)) {
|
||||
checkIfShouldUpdateDependencyPackageVersion(
|
||||
pathToPackage,
|
||||
packageManifest.name,
|
||||
packageManifest.version,
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = alignPackageVersions;
|
||||
|
@ -9,12 +9,14 @@
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
const {REPO_ROOT} = require('../../consts');
|
||||
const {getPackageVersionStrByTag} = require('../../npm-utils');
|
||||
const {
|
||||
isReleaseBranch,
|
||||
parseVersion,
|
||||
} = require('../../releases/utils/version-utils');
|
||||
const {getBranchName} = require('../../scm-utils');
|
||||
const {getPackages} = require('../../utils/monorepo');
|
||||
const alignPackageVersions = require('../align-package-versions');
|
||||
const checkForGitChanges = require('../check-for-git-changes');
|
||||
const {
|
||||
@ -24,7 +26,6 @@ const {
|
||||
NO_COMMIT_CHOICE,
|
||||
PUBLISH_PACKAGES_TAG,
|
||||
} = require('../constants');
|
||||
const forEachPackage = require('../for-each-package');
|
||||
const bumpPackageVersion = require('./bump-package-version');
|
||||
const detectPackageUnreleasedChanges = require('./bump-utils');
|
||||
const chalk = require('chalk');
|
||||
@ -33,8 +34,6 @@ const inquirer = require('inquirer');
|
||||
const path = require('path');
|
||||
const {echo, exec, exit} = require('shelljs');
|
||||
|
||||
const ROOT_LOCATION = path.join(__dirname, '..', '..', '..');
|
||||
|
||||
const buildExecutor =
|
||||
(
|
||||
packageAbsolutePath /*: string */,
|
||||
@ -53,7 +52,7 @@ const buildExecutor =
|
||||
!detectPackageUnreleasedChanges(
|
||||
packageRelativePathFromRoot,
|
||||
packageName,
|
||||
ROOT_LOCATION,
|
||||
REPO_ROOT,
|
||||
)
|
||||
) {
|
||||
return;
|
||||
@ -99,16 +98,6 @@ const buildExecutor =
|
||||
});
|
||||
};
|
||||
|
||||
const buildAllExecutors = () => {
|
||||
const executors = [];
|
||||
|
||||
forEachPackage((...params) => {
|
||||
executors.push(buildExecutor(...params));
|
||||
});
|
||||
|
||||
return executors;
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
if (checkForGitChanges()) {
|
||||
echo(
|
||||
@ -119,8 +108,18 @@ const main = async () => {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
const executors = buildAllExecutors();
|
||||
for (const executor of executors) {
|
||||
const packages = await getPackages({
|
||||
includeReactNative: false,
|
||||
includePrivate: true,
|
||||
});
|
||||
|
||||
for (const pkg of Object.values(packages)) {
|
||||
const executor = buildExecutor(
|
||||
pkg.path,
|
||||
path.relative(REPO_ROOT, pkg.path),
|
||||
pkg.packageJson,
|
||||
);
|
||||
|
||||
await executor()
|
||||
.catch(() => exit(1))
|
||||
.then(() => echo());
|
||||
@ -132,7 +131,7 @@ const main = async () => {
|
||||
}
|
||||
|
||||
echo('Aligning new versions across monorepo...');
|
||||
alignPackageVersions();
|
||||
await alignPackageVersions();
|
||||
echo(chalk.green('Done!\n'));
|
||||
|
||||
// Figure out the npm dist-tags we want for all monorepo packages we're bumping
|
||||
@ -219,7 +218,7 @@ const main = async () => {
|
||||
|
||||
case COMMIT_WITH_GENERIC_MESSAGE_CHOICE: {
|
||||
exec(`git commit -am "${GENERIC_COMMIT_MESSAGE}${tagString}"`, {
|
||||
cwd: ROOT_LOCATION,
|
||||
cwd: REPO_ROOT,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
@ -229,17 +228,17 @@ const main = async () => {
|
||||
case COMMIT_WITH_CUSTOM_MESSAGE_CHOICE: {
|
||||
// exec from shelljs currently does not support interactive input
|
||||
// https://github.com/shelljs/shelljs/wiki/FAQ#running-interactive-programs-with-exec
|
||||
execSync('git commit -a', {cwd: ROOT_LOCATION, stdio: 'inherit'});
|
||||
execSync('git commit -a', {cwd: REPO_ROOT, stdio: 'inherit'});
|
||||
|
||||
const enteredCommitMessage = exec('git log -n 1 --format=format:%B', {
|
||||
cwd: ROOT_LOCATION,
|
||||
cwd: REPO_ROOT,
|
||||
silent: true,
|
||||
}).stdout.trim();
|
||||
const commitMessageWithTag =
|
||||
enteredCommitMessage + `\n\n${PUBLISH_PACKAGES_TAG}${tagString}`;
|
||||
|
||||
exec(`git commit --amend -m "${commitMessageWithTag}"`, {
|
||||
cwd: ROOT_LOCATION,
|
||||
cwd: REPO_ROOT,
|
||||
silent: true,
|
||||
});
|
||||
|
||||
|
@ -1,69 +0,0 @@
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
const {PACKAGES_DIR} = require('../consts');
|
||||
const {readdirSync, readFileSync} = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
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
|
||||
*/
|
||||
const getDirectories = (source /*: string */) /*: Array<string> */ =>
|
||||
readdirSync(source, {withFileTypes: true})
|
||||
.filter(file => file.isDirectory())
|
||||
.map(directory => directory.name.toString());
|
||||
/**
|
||||
* Iterate through every package inside /packages (ignoring react-native) and call provided callback for each of them
|
||||
*
|
||||
* @deprecated Use scripts/releases/utils/monorepo.js#getPackages instead
|
||||
*/
|
||||
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_DIR).filter(
|
||||
directoryName =>
|
||||
directoryName !== 'react-native' || includeReactNative === true,
|
||||
);
|
||||
|
||||
packagesDirectories.forEach(packageDirectory => {
|
||||
const packageAbsolutePath = path.join(PACKAGES_DIR, packageDirectory);
|
||||
const packageRelativePathFromRoot = path.join('packages', packageDirectory);
|
||||
|
||||
const packageManifest = JSON.parse(
|
||||
readFileSync(path.join(packageAbsolutePath, 'package.json')).toString(),
|
||||
);
|
||||
|
||||
callback(packageAbsolutePath, packageRelativePathFromRoot, packageManifest);
|
||||
});
|
||||
};
|
||||
|
||||
module.exports = forEachPackage;
|
@ -8,7 +8,7 @@
|
||||
*/
|
||||
|
||||
const {getVersionsBySpec} = require('../../npm-utils');
|
||||
const forEachPackage = require('../for-each-package');
|
||||
const {getPackages} = require('../../utils/monorepo');
|
||||
const {exit} = require('shelljs');
|
||||
const yargs = require('yargs');
|
||||
|
||||
@ -41,40 +41,46 @@ function reversePatchComp(semverA, semverB) {
|
||||
return patchB - patchA;
|
||||
}
|
||||
|
||||
const main = () => {
|
||||
async function main() {
|
||||
const data = [];
|
||||
forEachPackage(
|
||||
(_packageAbsolutePath, _packageRelativePathFromRoot, packageManifest) => {
|
||||
const isPublic = !packageManifest.private;
|
||||
if (
|
||||
type === 'all' ||
|
||||
(type === 'private' && !isPublic) ||
|
||||
(type === 'public' && isPublic)
|
||||
) {
|
||||
const packageInfo = {
|
||||
'Public?': isPublic ? '\u{2705}' : '\u{274C}',
|
||||
Name: packageManifest.name,
|
||||
'Version (main)': packageManifest.version,
|
||||
};
|
||||
const packages = await getPackages({
|
||||
includeReactNative: true,
|
||||
includePrivate: true,
|
||||
});
|
||||
|
||||
if (isPublic && minor !== 0) {
|
||||
try {
|
||||
const versions = getVersionsBySpec(
|
||||
packageManifest.name,
|
||||
`^0.${minor}.0`,
|
||||
).sort(reversePatchComp);
|
||||
packageInfo[`Version (${minor})`] = versions[0];
|
||||
} catch (e) {
|
||||
packageInfo[`Version (${minor})`] = e.message;
|
||||
}
|
||||
for (const {packageJson} of Object.values(packages)) {
|
||||
const isPublic = !packageJson.private;
|
||||
if (
|
||||
type === 'all' ||
|
||||
(type === 'private' && !isPublic) ||
|
||||
(type === 'public' && isPublic)
|
||||
) {
|
||||
const packageInfo = {
|
||||
'Public?': isPublic ? '\u{2705}' : '\u{274C}',
|
||||
Name: packageJson.name,
|
||||
'Version (main)': packageJson.version,
|
||||
};
|
||||
|
||||
if (isPublic && minor !== 0) {
|
||||
try {
|
||||
const versions = getVersionsBySpec(
|
||||
packageJson.name,
|
||||
`^0.${minor}.0`,
|
||||
).sort(reversePatchComp);
|
||||
packageInfo[`Version (${minor})`] = versions[0];
|
||||
} catch (e) {
|
||||
packageInfo[`Version (${minor})`] = e.message;
|
||||
}
|
||||
data.push(packageInfo);
|
||||
}
|
||||
},
|
||||
{includeReactNative: true},
|
||||
);
|
||||
data.push(packageInfo);
|
||||
}
|
||||
}
|
||||
|
||||
console.table(data);
|
||||
exit(0);
|
||||
};
|
||||
}
|
||||
|
||||
main();
|
||||
if (require.main === module) {
|
||||
// eslint-disable-next-line no-void
|
||||
void main();
|
||||
}
|
||||
|
@ -121,14 +121,14 @@ describe('publish-npm', () => {
|
||||
|
||||
describe("publishNpm('nightly')", () => {
|
||||
beforeAll(() => {
|
||||
jest.mock('../../releases/utils/monorepo', () => ({
|
||||
...jest.requireActual('../../releases/utils/monorepo'),
|
||||
jest.mock('../../utils/monorepo', () => ({
|
||||
...jest.requireActual('../../utils/monorepo'),
|
||||
getPackages: getPackagesMock,
|
||||
}));
|
||||
});
|
||||
|
||||
afterAll(() => {
|
||||
jest.unmock('../../releases/utils/monorepo');
|
||||
jest.unmock('../../utils/monorepo');
|
||||
});
|
||||
|
||||
it('should publish', async () => {
|
||||
|
@ -21,7 +21,7 @@ const fetchMock = jest.fn();
|
||||
|
||||
jest.mock('child_process', () => ({execSync}));
|
||||
jest.mock('shelljs', () => ({exec: execMock}));
|
||||
jest.mock('../../releases/utils/monorepo', () => ({
|
||||
jest.mock('../../utils/monorepo', () => ({
|
||||
getPackages: getPackagesMock,
|
||||
}));
|
||||
// $FlowIgnore[cannot-write]
|
||||
|
@ -20,11 +20,11 @@ const {getNpmInfo, publishPackage} = require('../npm-utils');
|
||||
const {removeNewArchFlags} = require('../releases/remove-new-arch-flags');
|
||||
const {setReactNativeVersion} = require('../releases/set-rn-version');
|
||||
const setVersion = require('../releases/set-version');
|
||||
const {getPackages} = require('../releases/utils/monorepo');
|
||||
const {
|
||||
generateAndroidArtifacts,
|
||||
publishAndroidArtifactsToMaven,
|
||||
} = require('../releases/utils/release-utils');
|
||||
const {getPackages} = require('../utils/monorepo');
|
||||
const path = require('path');
|
||||
const yargs = require('yargs');
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
|
||||
const {PUBLISH_PACKAGES_TAG} = require('../monorepo/constants');
|
||||
const {publishPackage} = require('../npm-utils');
|
||||
const {getPackages} = require('../releases/utils/monorepo');
|
||||
const {getPackages} = require('../utils/monorepo');
|
||||
const {parseArgs} = require('@pkgjs/parseargs');
|
||||
const {execSync} = require('child_process');
|
||||
|
||||
|
@ -14,15 +14,16 @@
|
||||
const {REPO_ROOT} = require('../consts');
|
||||
const detectPackageUnreleasedChanges = require('../monorepo/bump-all-updated-packages/bump-utils.js');
|
||||
const checkForGitChanges = require('../monorepo/check-for-git-changes');
|
||||
const forEachPackage = require('../monorepo/for-each-package');
|
||||
const {failIfTagExists} = require('../releases/utils/release-utils');
|
||||
const {
|
||||
isReleaseBranch,
|
||||
parseVersion,
|
||||
} = require('../releases/utils/version-utils');
|
||||
const {exitIfNotOnGit, getBranchName} = require('../scm-utils');
|
||||
const {getPackages} = require('../utils/monorepo');
|
||||
const chalk = require('chalk');
|
||||
const inquirer = require('inquirer');
|
||||
const path = require('path');
|
||||
const request = require('request');
|
||||
const {echo, exit} = require('shelljs');
|
||||
const yargs = require('yargs');
|
||||
@ -92,22 +93,22 @@ const buildExecutor =
|
||||
}
|
||||
};
|
||||
|
||||
const buildAllExecutors = () => {
|
||||
const executors = [];
|
||||
|
||||
forEachPackage((...params) => {
|
||||
executors.push(buildExecutor(...params));
|
||||
});
|
||||
|
||||
return executors;
|
||||
};
|
||||
|
||||
async function exitIfUnreleasedPackages() {
|
||||
// use the other script to verify that there's no packages in the monorepo
|
||||
// that have changes that haven't been released
|
||||
|
||||
const executors = buildAllExecutors();
|
||||
for (const executor of executors) {
|
||||
const packages = await getPackages({
|
||||
includeReactNative: false,
|
||||
includePrivate: true,
|
||||
});
|
||||
|
||||
for (const pkg of Object.values(packages)) {
|
||||
const executor = buildExecutor(
|
||||
pkg.path,
|
||||
path.relative(REPO_ROOT, pkg.path),
|
||||
pkg.packageJson,
|
||||
);
|
||||
|
||||
await executor().catch(error => {
|
||||
echo(chalk.red(error));
|
||||
// need to throw upward
|
||||
|
@ -12,11 +12,11 @@
|
||||
'use strict';
|
||||
|
||||
/*::
|
||||
import type {PackageJson} from '../utils/monorepo';
|
||||
import type {PackageJson} from '../../utils/monorepo';
|
||||
*/
|
||||
|
||||
const {getPackages} = require('../../utils/monorepo');
|
||||
const {setReactNativeVersion} = require('../set-rn-version');
|
||||
const {getPackages} = require('../utils/monorepo');
|
||||
const {promises: fs} = require('fs');
|
||||
const path = require('path');
|
||||
const yargs = require('yargs');
|
||||
|
@ -9,7 +9,7 @@
|
||||
* @oncall react_native
|
||||
*/
|
||||
|
||||
const {REPO_ROOT} = require('../../consts');
|
||||
const {REPO_ROOT} = require('../consts');
|
||||
const fs = require('fs');
|
||||
const glob = require('glob');
|
||||
const path = require('path');
|
||||
@ -67,7 +67,7 @@ async function getPackages(
|
||||
})
|
||||
.map(async packageJsonPath => {
|
||||
const packagePath = path.dirname(packageJsonPath);
|
||||
const packageJson = JSON.parse(
|
||||
const packageJson /*: PackageJson */ = JSON.parse(
|
||||
await fs.promises.readFile(packageJsonPath, 'utf-8'),
|
||||
);
|
||||
|
||||
@ -84,7 +84,7 @@ async function getPackages(
|
||||
|
||||
return Object.fromEntries(
|
||||
packagesEntries.filter(
|
||||
([_, {packageJson}]) => !packageJson.private || includePrivate,
|
||||
([_, {packageJson}]) => packageJson.private !== true || includePrivate,
|
||||
),
|
||||
);
|
||||
}
|
Loading…
Reference in New Issue
Block a user