Files
actual/yarn.config.cjs
Matiss Janis Aboltins c4ee71409e [AI] Add Yarn constraints to enforce consistent dependency versions (#7229)
* [AI] Add yarn constraints to enforce consistent dependency versions

Adds a `yarn.config.cjs` that uses Yarn 4's built-in constraints feature
to detect when the same dependency is declared with different version
ranges across workspaces. Workspace protocol references and
peerDependencies are excluded from the check.

Also adds a `yarn constraints` convenience script and the `@yarnpkg/types`
dev dependency for type-checked constraint authoring.

https://claude.ai/code/session_01B1xRjZXn6b18anZjo8cbqb

* Add release notes for PR #7229

* Add constraints job to GitHub Actions workflow

* Fix constraints

---------

Co-authored-by: Claude <noreply@anthropic.com>
Co-authored-by: github-actions[bot] <github-actions[bot]@users.noreply.github.com>
2026-03-17 16:00:34 +00:00

55 lines
1.7 KiB
JavaScript

// @ts-check
/** @type {import('@yarnpkg/types')} */
const { defineConfig } = require('@yarnpkg/types');
/**
* Enforce that all workspaces use the same version of any shared dependency.
* Workspace protocol references (workspace:*) and peerDependencies are
* excluded since they intentionally use different/wider ranges.
*
* @param {import('@yarnpkg/types').Yarn.Constraints.Context} context
*/
function enforceConsistentDependencies({ Yarn }) {
/** @type {Map<string, Map<string, Array<import('@yarnpkg/types').Yarn.Constraints.Workspace>>>} */
const dependencyVersions = new Map();
for (const workspace of Yarn.workspaces()) {
for (const type of ['dependencies', 'devDependencies']) {
for (const dep of Yarn.dependencies({ workspace, type })) {
if (dep.range.startsWith('workspace:')) continue;
if (!dependencyVersions.has(dep.ident)) {
dependencyVersions.set(dep.ident, new Map());
}
const versions = dependencyVersions.get(dep.ident);
if (!versions.has(dep.range)) {
versions.set(dep.range, []);
}
versions.get(dep.range).push(workspace);
}
}
}
for (const [ident, versions] of dependencyVersions) {
if (versions.size <= 1) continue;
const rangeList = [...versions.keys()].join(', ');
for (const [, workspaces] of versions) {
for (const workspace of workspaces) {
workspace.error(
`Package "${ident}" has inconsistent versions across workspaces (${rangeList}). ` +
`All workspaces must use the same version range.`,
);
}
}
}
}
module.exports = defineConfig({
async constraints(ctx) {
enforceConsistentDependencies(ctx);
},
});