Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 32 additions & 10 deletions yarn.config.cjs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,23 @@ const { inspect } = require('util');
*/
const ALLOWED_INCONSISTENT_DEPENDENCIES = {};

/**
* Whether `yarn constraints --fix` may resolve a dependency range disagreement
* on its own by aligning every workspace to the highest range.
*
* Off by default, so `yarn lint:fix` never turns an unrelated change into a
* monorepo-wide dependency bump. Dependency upgrades belong in their own pull
* requests, so this is set only by the workflow that repairs Dependabot pull
* requests. It is deliberately not exposed as a package script: a convenient
* front door is precisely what would tempt someone into bundling an upgrade
* into unrelated work.
*
* Note that this cannot be a command line flag: `yarn constraints` is a Yarn
* builtin and rejects any option other than `--fix` and `--json`.
*/
// eslint-disable-next-line n/no-process-env
const ALIGN_DEPENDENCY_RANGES = process.env.ALIGN_DEPENDENCY_RANGES === 'true';

/**
* These packages are allowed as peer dependencies without requiring installation as
* devDependencies.
Expand Down Expand Up @@ -1012,14 +1029,19 @@ function getHighestRange(ranges) {
* and `devDependencies` for the same dependency are the same (as long as it is
* not a dependency on a workspace package).
*
* Where every conflicting range is plain semver, the one permitting the highest
* minimum version wins and `yarn constraints --fix` will align the rest. That
* keeps a partial dependency bump from blocking a pull request on a change
* nobody has to think about. Dependabot security updates produce exactly this,
* since they walk manifests one at a time rather than as a workspace.
* By default a disagreement is an error for a human to resolve, so that routine
* use of `yarn lint:fix` cannot quietly fold a dependency bump into an
* unrelated pull request.
*
* Ranges that cannot be compared (aliases, protocols, dist tags) still fall
* through to an error for a human to resolve.
* Under `ALIGN_DEPENDENCY_RANGES` (see above) the rule instead becomes
* fixable: where every conflicting range is plain semver, the one permitting
* the highest minimum version wins and `yarn constraints --fix` aligns the
* rest. That is meant for the workflow that repairs Dependabot pull requests,
* whose security updates walk manifests one at a time rather than as a
* workspace and so routinely leave ranges disagreeing.
*
* Ranges that cannot be compared (aliases, protocols, dist tags) are always an
* error, opted in or not.
*
* @param {Yarn} Yarn - The Yarn "global".
*/
Expand Down Expand Up @@ -1048,16 +1070,16 @@ function expectConsistentDependenciesAndDevDependencies(Yarn) {

for (const dependencies of dependenciesToConsider.values()) {
for (const dependency of dependencies) {
if (highestRange === null) {
if (highestRange !== null && ALIGN_DEPENDENCY_RANGES) {
dependency.update(highestRange);
} else {
dependency.error(
`Expected version range for ${dependencyIdent} (in ${
dependency.type
}) to be consistent across monorepo. Pick one: ${inspect(
dependencyRanges,
)}`,
);
} else {
dependency.update(highestRange);
}
}
}
Expand Down