-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
ci(release): add sync-peer-deps step
- Loading branch information
Showing
4 changed files
with
160 additions
and
6 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -26,6 +26,7 @@ on: | |
|
||
env: | ||
HUSKY: 0 | ||
FORCE_COLOR: 3 | ||
|
||
jobs: | ||
ci_release: | ||
|
@@ -39,3 +40,23 @@ jobs: | |
working-directory: 'projects/${{ inputs.package }}' | ||
dry-run: ${{ inputs.dry-run }} | ||
release: true | ||
|
||
ci_sync_peer_deps: | ||
needs: ci_release | ||
runs-on: 'ubuntu-latest' | ||
steps: | ||
- name: Checkout sources | ||
uses: actions/checkout@v4 | ||
with: | ||
persist-credentials: false | ||
|
||
- name: Synchronize peer dependencies | ||
working-directory: 'scripts' | ||
env: | ||
GITHUB_TOKEN: ${{ secrets.DSI_HUG_BOT_GITHUB_TOKEN }} | ||
run: | | ||
git config user.name 'dsi-hug-bot' | ||
git config user.email '[email protected]' | ||
git remote set-url origin https://x-access-token:${{ secrets.DSI_HUG_BOT_GITHUB_TOKEN }}@github.com/${{ github.repository }} | ||
npm --prefix . i chalk | ||
node ./sync-peer-deps.mjs |
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 |
---|---|---|
|
@@ -45,4 +45,4 @@ | |
"dependencies": { | ||
"tslib": "^2.6.3" | ||
} | ||
} | ||
} |
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,97 @@ | ||
/** | ||
* Automated script that ensures consistent versioning across interdependent packages in a monorepo. | ||
* | ||
* This script reads the current version of each package and updates any other packages that reference | ||
* it in their `peerDependencies` to maintain version synchronization. | ||
* | ||
* @example: $ node ./sync-peer-deps.mjs [--dry-run] | ||
* | ||
* TODO: remove this script if one day this feature is supported by `nx release` directly | ||
* @see https://github.com/nrwl/nx/issues/22776 | ||
* @see https://github.com/nrwl/nx/discussions/23388 | ||
*/ | ||
|
||
import chalk from 'chalk'; | ||
import { spawnSync } from 'node:child_process'; | ||
import { readFileSync, writeFileSync } from 'node:fs'; | ||
import { dirname, resolve } from 'node:path'; | ||
import { fileURLToPath } from 'node:url'; | ||
|
||
const { yellow, blue, red, green, gray, white, bgBlue, bgWhite } = chalk; | ||
|
||
const __dirname = dirname(fileURLToPath(import.meta.url)); | ||
const rootPath = resolve(__dirname, '..'); | ||
|
||
const dryRun = (process.argv[2] === '--dry-run'); | ||
|
||
const execCommand = (command, args) => { | ||
console.log(`\n${command} ${args.join(' ')}`); | ||
if (!dryRun) { | ||
const result = spawnSync(command, args, { stdio: 'inherit' }); | ||
if (result.error) { | ||
throw result.error; | ||
} | ||
if (result.status !== 0) { | ||
throw new Error(`Command failed with exit code ${result.status}`); | ||
} | ||
} | ||
}; | ||
|
||
const getWorkspaces = () => { | ||
const rootPackageJson = JSON.parse(readFileSync(resolve(rootPath, 'package.json'), 'utf8')); | ||
if (!rootPackageJson.workspaces) { | ||
console.error(red('No workspaces found in package.json')); | ||
} | ||
return (rootPackageJson.workspaces || []).map(workspace => ({ | ||
packageJsonPath: resolve(rootPath, workspace, 'package.json'), | ||
packageJson: JSON.parse(readFileSync(resolve(rootPath, workspace, 'package.json'), 'utf8')) | ||
})); | ||
}; | ||
|
||
(() => { | ||
console.log(`\n${bgBlue(' > ')} Synchronizing peer dependencies`); | ||
let changesDetected = false; | ||
const workspaces = getWorkspaces(); | ||
workspaces.forEach(workspace => { | ||
workspaces.forEach(workspace2 => { | ||
const peerDependencies = workspace2.packageJson.peerDependencies || {}; | ||
if (Object.hasOwn(peerDependencies, workspace.packageJson.name)) { | ||
const version = peerDependencies[workspace.packageJson.name]; | ||
if (!version.includes(workspace.packageJson.version)) { | ||
changesDetected = true; | ||
|
||
const versionRange = version.match(/(^[^\d]*)\d.*/)[1]; | ||
const newVersion = `${versionRange}${workspace.packageJson.version}`; | ||
|
||
console.log(blue.bold(`\n[${workspace2.packageJson.name}]`)); | ||
console.log(`\n${bgWhite(' > ')} ${white('UPDATE')} ${workspace2.packageJsonPath}${dryRun ? yellow(' [dry-run]') : ''}\n`); | ||
console.log(gray(' "peerDependencies": {')); | ||
console.log(red(`- "${workspace.packageJson.name}": "${version}"`)); | ||
console.log(green(`+ "${workspace.packageJson.name}": "${newVersion}"`)); | ||
console.log(gray(' }')); | ||
if (!dryRun) { | ||
workspace2.packageJson.peerDependencies[workspace.packageJson.name] = newVersion; | ||
writeFileSync(workspace2.packageJsonPath, JSON.stringify(workspace2.packageJson, null, 4), { encoding: 'utf8' }); | ||
} | ||
|
||
console.log(`\n${bgWhite(' > ')} Staging changed files with git${dryRun ? yellow(' [dry-run]') : ''}`); | ||
execCommand('git', ['add', workspace2.packageJsonPath]); | ||
|
||
console.log(`\n${bgWhite(' > ')} Committing changes with git${dryRun ? yellow(' [dry-run]') : ''}`); | ||
execCommand('git', ['commit', '--message', `chore(deps): upgrade ${workspace.packageJson.name} to v${workspace.packageJson.version}`]); | ||
} | ||
} | ||
}); | ||
}); | ||
|
||
if (changesDetected) { | ||
console.log(`\n${bgWhite(' > ')} Pushing to git remote${dryRun ? yellow(' [dry-run]') : ''}`); | ||
execCommand('git', ['push', '--follow-tags', '--no-verify', '--atomic']); | ||
} else { | ||
console.log('\nNo changes were needed, versions already in sync.'); | ||
} | ||
|
||
if (dryRun) { | ||
console.log(yellow('\nNOTE: The "--dry-run" flag means no changes were made.\n')); | ||
} | ||
})(); |