Skip to content
Merged
44 changes: 32 additions & 12 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,18 @@ references:
attach_workspace:
at: *hermes_workspace_root

main_only: &main_only
filters:
branches:
only: main
main_or_stable_only: &main_or_stable_only
filters:
branches:
only:
- main
- /0\.[0-9]+[\.[0-9]+]?-stable/


# -------------------------
# Dependency Anchors
# -------------------------
Expand Down Expand Up @@ -817,10 +829,7 @@ jobs:
command: |
REPO_ROOT=$(pwd)
node ./scripts/set-rn-template-version.js "file:$REPO_ROOT/build/$(cat build/react-native-package-version)"
node cli.js init $PROJECT_NAME --directory "/tmp/$PROJECT_NAME" --template $REPO_ROOT --verbose --skip-install
cd /tmp/$PROJECT_NAME
yarn

node ./scripts/template/initialize.js --reactNativeRootPath $REPO_ROOT --templateName $PROJECT_NAME --templateConfigPath $REPO_ROOT --directory "/tmp/$PROJECT_NAME"
- run:
name: Build the template application for << parameters.flavor >> with Architecture set to << parameters.architecture >>, and using the << parameters.jsengine>> JS engine.
command: |
Expand Down Expand Up @@ -923,13 +932,11 @@ jobs:
PACKAGE=$(cat build/react-native-package-version)
PATH_TO_PACKAGE="$REPO_ROOT/build/$PACKAGE"
node ./scripts/set-rn-template-version.js "file:$PATH_TO_PACKAGE"
node cli.js init $PROJECT_NAME --directory "/tmp/$PROJECT_NAME" --template $REPO_ROOT --verbose --skip-install
node ./scripts/template/initialize.js --reactNativeRootPath $REPO_ROOT --templateName $PROJECT_NAME --templateConfigPath $REPO_ROOT --directory "/tmp/$PROJECT_NAME"
- run:
name: Install iOS dependencies - Configuration << parameters.flavor >>; New Architecture << parameters.architecture >>; JS Engine << parameters.jsengine>>; Flipper << parameters.flipper >>
command: |
cd /tmp/$PROJECT_NAME
yarn install
cd ios
cd /tmp/$PROJECT_NAME/ios

bundle install

Expand Down Expand Up @@ -1570,6 +1577,17 @@ jobs:
command: |
echo "Nightly build run"

find_and_publish_bumped_packages:
executor: reactnativeandroid
steps:
- checkout
- run:
name: Set NPM auth token
command: echo "//registry.npmjs.org/:_authToken=${CIRCLE_NPM_TOKEN}" > ~/.npmrc
- run:
name: Find and publish all bumped packages
command: node ./scripts/monorepo/find-and-publish-all-bumped-packages.js


# -------------------------
# PIPELINE PARAMETERS
Expand Down Expand Up @@ -1758,11 +1776,8 @@ workflows:
unless: << pipeline.parameters.run_package_release_workflow_only >>
triggers:
- schedule:
<<: *main_only
cron: "0 20 * * *"
filters:
branches:
only:
- main
jobs:
- nightly_job

Expand All @@ -1785,3 +1800,8 @@ workflows:
- build_hermesc_linux
- build_hermes_macos
- build_hermesc_windows

publish_bumped_packages:
jobs:
- find_and_publish_bumped_packages:
<<: *main_or_stable_only
4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,9 @@
"test-e2e-local-clean": "node ./scripts/test-e2e-local-clean.js",
"test-ios": "./scripts/objc-test.sh test",
"test-typescript": "dtslint types",
"test-typescript-offline": "dtslint --localTs node_modules/typescript/lib types"
"test-typescript-offline": "dtslint --localTs node_modules/typescript/lib types",
"bump-all-updated-packages": "node ./scripts/monorepo/bump-all-updated-packages",
"align-package-versions": "node ./scripts/monorepo/align-package-versions.js"
},
"peerDependencies": {
"react": "18.2.0"
Expand Down
39 changes: 39 additions & 0 deletions scripts/monorepo/__tests__/bump-package-version-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/**
* 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 path = require('path');
const {writeFileSync} = require('fs');

const bumpPackageVersion = require('../bump-all-updated-packages/bump-package-version');

jest.mock('fs', () => ({
writeFileSync: jest.fn(),
readFileSync: jest.fn(() => '{}'),
}));

jest.mock('../for-each-package', () => callback => {});

describe('bumpPackageVersionTest', () => {
it('updates patch version of the package', () => {
const mockedPackageLocation = '~/packages/assets';
const mockedPackageManifest = {
name: '@react-native/test',
version: '1.2.3',
};

bumpPackageVersion(mockedPackageLocation, mockedPackageManifest);

expect(writeFileSync).toHaveBeenCalledWith(
path.join(mockedPackageLocation, 'package.json'),
JSON.stringify({...mockedPackageManifest, version: '1.2.4'}, null, 2) +
'\n',
'utf-8',
);
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/**
* 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 {spawnSync} = require('child_process');

const {BUMP_COMMIT_MESSAGE} = require('../constants');
const forEachPackage = require('../for-each-package');
const findAndPublishAllBumpedPackages = require('../find-and-publish-all-bumped-packages');

jest.mock('child_process', () => ({spawnSync: jest.fn()}));
jest.mock('../for-each-package', () => jest.fn());

describe('findAndPublishAllBumpedPackages', () => {
it('throws an error if updated version is not 0.x.y', () => {
const mockedPackageNewVersion = '1.0.0';

forEachPackage.mockImplementationOnce(callback => {
callback('absolute/path/to/package', 'to/package', {
version: mockedPackageNewVersion,
});
});

spawnSync.mockImplementationOnce(() => ({
stdout: `- "version": "0.72.0"\n+ "version": "${mockedPackageNewVersion}"\n`,
}));

spawnSync.mockImplementationOnce(() => ({
stdout: BUMP_COMMIT_MESSAGE,
}));

expect(() => findAndPublishAllBumpedPackages()).toThrow(
`Package version expected to be 0.x.y, but received ${mockedPackageNewVersion}`,
);
});
});
51 changes: 51 additions & 0 deletions scripts/monorepo/__tests__/for-each-package-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
/**
* 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 path = require('path');
const {readdirSync, readFileSync} = require('fs');

const forEachPackage = require('../for-each-package');

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', () => {
const callback = jest.fn();
readdirSync.mockImplementationOnce(() => [
{name: 'react-native', isDirectory: () => true},
]);

forEachPackage(callback);

expect(callback).not.toHaveBeenCalled();
});
});
146 changes: 146 additions & 0 deletions scripts/monorepo/align-package-versions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,146 @@
/**
* 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 {spawnSync} = require('child_process');
const {writeFileSync, readFileSync} = require('fs');
const path = require('path');

const checkForGitChanges = require('./check-for-git-changes');
const forEachPackage = require('./for-each-package');

const ROOT_LOCATION = path.join(__dirname, '..', '..');
const TEMPLATE_LOCATION = path.join(ROOT_LOCATION, 'template');
const REPO_CONFIG_LOCATION = path.join(ROOT_LOCATION, 'repo-config');

const readJSONFile = pathToFile => JSON.parse(readFileSync(pathToFile));

const checkIfShouldUpdateDependencyPackageVersion = (
consumerPackageAbsolutePath,
updatedPackageName,
updatedPackageVersion,
) => {
const consumerPackageManifestPath = path.join(
consumerPackageAbsolutePath,
'package.json',
);
const consumerPackageManifest = readJSONFile(consumerPackageManifestPath);

const dependencyVersion =
consumerPackageManifest.dependencies?.[updatedPackageName];

if (dependencyVersion && dependencyVersion !== '*') {
const updatedDependencyVersion = dependencyVersion.startsWith('^')
? `^${updatedPackageVersion}`
: updatedPackageVersion;

if (updatedDependencyVersion !== dependencyVersion) {
console.log(
`\uD83D\uDCA1 ${consumerPackageManifest.name} was updated: now using version ${updatedPackageVersion} of ${updatedPackageName}`,
);

const updatedPackageManifest = {
...consumerPackageManifest,
dependencies: {
...consumerPackageManifest.dependencies,
[updatedPackageName]: updatedDependencyVersion,
},
};

writeFileSync(
consumerPackageManifestPath,
JSON.stringify(updatedPackageManifest, null, 2) + '\n',
'utf-8',
);
}
}

const devDependencyVersion =
consumerPackageManifest.devDependencies?.[updatedPackageName];

if (devDependencyVersion && devDependencyVersion !== '*') {
const updatedDependencyVersion = devDependencyVersion.startsWith('^')
? `^${updatedPackageVersion}`
: updatedPackageVersion;

if (updatedDependencyVersion !== devDependencyVersion) {
console.log(
`\uD83D\uDCA1 ${consumerPackageManifest.name} was updated: now using version ${updatedPackageVersion} of ${updatedPackageName}`,
);

const updatedPackageManifest = {
...consumerPackageManifest,
devDependencies: {
...consumerPackageManifest.devDependencies,
[updatedPackageName]: updatedDependencyVersion,
},
};

writeFileSync(
consumerPackageManifestPath,
JSON.stringify(updatedPackageManifest, null, 2) + '\n',
'utf-8',
);
}
}
};

const alignPackageVersions = () => {
if (checkForGitChanges()) {
console.log(
'\u274c Found uncommitted changes. Please commit or stash them before running this script',
);

process.exit(1);
}

forEachPackage((packageAbsolutePath, _, packageManifest) => {
checkIfShouldUpdateDependencyPackageVersion(
ROOT_LOCATION,
packageManifest.name,
packageManifest.version,
);

checkIfShouldUpdateDependencyPackageVersion(
TEMPLATE_LOCATION,
packageManifest.name,
packageManifest.version,
);

checkIfShouldUpdateDependencyPackageVersion(
REPO_CONFIG_LOCATION,
packageManifest.name,
packageManifest.version,
);

forEachPackage(pathToPackage =>
checkIfShouldUpdateDependencyPackageVersion(
pathToPackage,
packageManifest.name,
packageManifest.version,
),
);
});

if (!checkForGitChanges()) {
console.log(
'\u2705 There were no changes. Every consumer package uses the actual version of dependency package.',
);
return;
}

console.log('Running yarn to update lock file...');
spawnSync('yarn', ['install'], {
cwd: ROOT_LOCATION,
shell: true,
stdio: 'inherit',
encoding: 'utf-8',
});
};

alignPackageVersions();
Loading