Skip to content

chore: make the dependency consistency constraint auto-fixable - #10225

Merged
cryptodev-2s merged 1 commit into
mainfrom
fix/auto-align-inconsistent-dependency-ranges
Sep 14, 2026
Merged

chore: make the dependency consistency constraint auto-fixable#10225
cryptodev-2s merged 1 commit into
mainfrom
fix/auto-align-inconsistent-dependency-ranges

Conversation

@cryptodev-2s

@cryptodev-2s cryptodev-2s commented Sep 14, 2026

Copy link
Copy Markdown
Contributor

Explanation

expectConsistentDependenciesAndDevDependencies requires every workspace to use the same version range for a dependency, but it reports through dependency.error(), which Yarn has no way to repair. So yarn constraints --fix does nothing for it and a human has to hand edit every manifest.

That mostly hurts on Dependabot PRs. Dependabot's security updates walk manifests one at a time rather than treating the Yarn workspace as one project, so they routinely bump a dependency in some packages and not others. The result is a red build on a change nobody actually has to think about. PR #10147 is a good example: it bumped uuid in 22 packages, uuid is declared in 24, and the two stragglers fail constraints. Same story on #10157, #10177 and #9369, which is a large part of why uuid alone accounts for 25 of our open Dependabot alerts.

This makes the rule fixable. When every conflicting range is plain semver, the one permitting the highest minimum version wins and dependency.update() aligns the rest, so yarn constraints --fix (which yarn lint:fix already runs) repairs a partial bump on its own.

The previous docstring said it is impossible to compare NPM version ranges, so let the user decide. That is still true in general, and the fallback is unchanged: anything that is not a plain semver range, so aliases like npm:foo@^1.0.0, protocols like workspace:^, or dist tags, still produces the original "Pick one" error with the same wording. The narrower claim here is only that semver.minVersion() is comparable when every range has one, and getHighestRange bails out the moment one doesn't.

Nothing else in the file changes. ALLOWED_INCONSISTENT_DEPENDENCIES and its filter behave exactly as before.

Verification

There is no test harness for yarn.config.cjs, so I verified against the monorepo itself:

Case Result
Clean tree exit 0, no manifests modified
uuid bumped in one package only --fix aligned all 25 manifests, re-check clean
One range set to npm:uuid@^14.0.2 errors with "Pick one", modifies nothing
One package downgraded to ^8.0.0 pulled back up to ^9.0.1, not propagated down

The last one is the safety property worth calling out: a wrong range in one manifest gets corrected upward rather than dragging every other package backwards.

Worth knowing that --fix also reaches the root package.json, which declares some of these dependencies too.

Trade off

Aligning to the highest range is a real dependency change, not a formatting fix. One bump in one package can move the rest onto a new major, and yarn lint:fix will do that locally without asking. The argument for it is that the constraint already requires these to move together, so the only open question was who performs the alignment and in which direction, and aligning downward would mean reverting security fixes.

References

Part of WPC-1161. This is the first step toward dropping the @metamask/* allowlist in .github/dependabot.yml so we can bump everything, not just MetaMask packages. The follow up is a workflow on bot PRs that runs yarn constraints --fix, yarn dedupe and yarn changelog:validate --checkDeps --fix, modelled on the one snaps already has in update-pull-request.yml.

Related to #10147, #10157, #10177, #9369.

Checklist

  • I've updated the test suite for new or updated code as appropriate (no harness exists for yarn.config.cjs, see Verification above)
  • I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate
  • I've communicated my changes to consumers by updating changelogs for packages I've changed (no published package is touched)
  • I've introduced breaking changes in this PR and have prepared draft pull requests for clients and consumer packages to resolve them

@cryptodev-2s
cryptodev-2s deployed to default-branch September 14, 2026 11:58 — with GitHub Actions Active
@cryptodev-2s cryptodev-2s self-assigned this Sep 14, 2026
@cryptodev-2s
cryptodev-2s force-pushed the fix/auto-align-inconsistent-dependency-ranges branch from d3c0649 to f3d6043 Compare September 14, 2026 12:11
@cryptodev-2s
cryptodev-2s requested a review from a team September 14, 2026 12:19
@cryptodev-2s
cryptodev-2s added this pull request to the merge queue Sep 14, 2026
Merged via the queue into main with commit b6160e5 Sep 14, 2026
338 checks passed
@cryptodev-2s
cryptodev-2s deleted the fix/auto-align-inconsistent-dependency-ranges branch September 14, 2026 12:34
cryptodev-2s added a commit to cryptodev-2s/core that referenced this pull request Sep 14, 2026
## Explanation

Follow up to MetaMask#10225, addressing review feedback on it.

MetaMask#10225 made the dependency range consistency constraint auto-fixable,
which also made it fixable from `yarn lint:fix`. That risks a team
hitting a constraints error, reaching for `yarn lint:fix` to clear it,
and folding a monorepo-wide dependency bump into an unrelated pull
request. Upgrades should stay in their own Dependabot pull requests.

This makes the alignment opt in and off by default. Every local
invocation now behaves exactly as it did before MetaMask#10225, same error, same
wording. Only CI repairing a bot's pull request will opt in.

The mechanism is an environment variable rather than a flag because
`yarn constraints` is a Yarn builtin and rejects anything other than
`--fix` and `--json`:

```
$ yarn constraints --fix --align
Unknown Syntax Error: Unsupported option name ("--align").
```

There is deliberately no package script wrapping it. A convenient front
door is what would tempt someone into bundling an upgrade into unrelated
work, which is the thing being fixed.

## Verification

| Case | Result |
| --- | --- |
| Default, one package bumped | errors with "Pick one", no other
manifest rewritten |
| `ALIGN_DEPENDENCY_RANGES=true` | aligns all 25 manifests, exit 0 |
| Clean tree, either mode | passes, nothing modified |
| Incomparable range (`npm:uuid@^14.0.2`) | errors regardless of the
variable |

## References

Follows MetaMask#10225. Part of WPC-1161.

## Checklist

- [ ] I've updated the test suite for new or updated code as appropriate
(no harness exists for `yarn.config.cjs`)
- [x] I've updated documentation (JSDoc, Markdown, etc.) for new or
updated code as appropriate
- [ ] I've communicated my changes to consumers by [updating changelogs
for packages I've
changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md)
(no published package is touched)
- [ ] I've introduced [breaking
changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md)
in this PR and have prepared draft pull requests for clients and
consumer packages to resolve them

<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Only changes Yarn constraint fix behavior for monorepo manifest
consistency; no runtime package code or published APIs.
> 
> **Overview**
> Reverts the post-MetaMask#10225 behavior where **`yarn constraints --fix`**
(including via **`yarn lint:fix`**) could automatically align mismatched
semver ranges across workspaces to the highest range. **By default**,
inconsistent dependency ranges again surface only the existing **"Pick
one"** error with no manifest rewrites.
> 
> **Opt-in auto-alignment** is gated on
**`ALIGN_DEPENDENCY_RANGES=true`**, intended for CI that repairs
Dependabot PRs—not a CLI flag (Yarn’s builtin rejects extra options) and
not a package script. **Non-comparable ranges** (aliases, protocols,
dist tags) still always error, with or without the env var.
> 
> <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit
cb57bdb. Bugbot is set up for automated
code reviews on this repo. Configure
[here](https://www.cursor.com/dashboard/bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants