forked from facebook/react-native
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat(react-native-github): a script to automate patch version bumping…
… of packages (facebook#35767) Summary: Pull Request resolved: facebook#35767 Changelog: [Internal] Introducing a script, which can be used to identify all packages inside `/packages`, which contain any changes after the last time its version was changed How it works step by step: ``` check that no git changes are present for each package: if package is private -> skip grep id of the last commit that changed package grep id of the last commit that changed version of the package if these ids are different: bump package patch version commit changes if required ``` Can be executed only in git environment and by running: `node ./scripts/bump-all-updated-packages` --- Also adding a separate script `align-package-versions.js`, which can be used to update versions of packages inside consumer packages ``` check that no git changes are present for each package x: for each package y: if y has x as dependency: validate that y uses the latest version of x if some changes were made: run yarn ``` --- Q: Why `run_yarn` step was removed from CircleCI flow? A: For *-stable branches, there are no yarn workspaces and all packages are specified as direct dependencies, so if we update `react-native/assets-registry` to the next version, we won't be able to run `yarn` for react-native root package, because updated version is not yet published to npm To avoid this, we first need publish new versions and then update them in consumer packages --- The final flow: 1. Developer uses `node ./scripts/bump-all-updated-packages` to bump versions of all updated packages. 2. Commit created from step 1 being merged or directly pushed to `main` or `*-stable` branches 3. A workflow from CircleCI publishes all updated versions to npm 4. Developer can use `align-package-versions.js` script to create required changes to align all packages versions Reviewed By: cortinico Differential Revision: D42295344 fbshipit-source-id: 54b667adb3ee5f28d19ee9c7991570451549aac2
- Loading branch information
Showing
9 changed files
with
516 additions
and
31 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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', | ||
); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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(); |
52 changes: 52 additions & 0 deletions
52
scripts/monorepo/bump-all-updated-packages/bump-package-version.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
/** | ||
* 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 {writeFileSync} = require('fs'); | ||
const path = require('path'); | ||
|
||
const getIncrementedVersion = (version, increment) => | ||
version | ||
.split('.') | ||
.map((token, index) => { | ||
const indexOfVersionToIncrement = increment === 'minor' ? 1 : 2; | ||
|
||
if (index === indexOfVersionToIncrement) { | ||
return parseInt(token, 10) + 1; | ||
} | ||
|
||
if (index > indexOfVersionToIncrement) { | ||
return 0; | ||
} | ||
|
||
return token; | ||
}) | ||
.join('.'); | ||
|
||
const bumpPackageVersion = ( | ||
packageAbsolutePath, | ||
packageManifest, | ||
increment = 'patch', | ||
) => { | ||
const updatedVersion = getIncrementedVersion( | ||
packageManifest.version, | ||
increment, | ||
); | ||
|
||
// Not using simple `npm version patch` because it updates dependencies and yarn.lock file | ||
writeFileSync( | ||
path.join(packageAbsolutePath, 'package.json'), | ||
JSON.stringify({...packageManifest, version: updatedVersion}, null, 2) + | ||
'\n', | ||
'utf-8', | ||
); | ||
|
||
return updatedVersion; | ||
}; | ||
|
||
module.exports = bumpPackageVersion; |
Oops, something went wrong.