diff --git a/.agents/skills/dependencies/SKILL.md b/.agents/skills/dependencies/SKILL.md index 13737db8fcbb..ebc1a789f7c2 100644 --- a/.agents/skills/dependencies/SKILL.md +++ b/.agents/skills/dependencies/SKILL.md @@ -33,14 +33,14 @@ Exceptions, keeping explicit versions: Two checks enforce it: - `pnpm lint:syncpack`: dependencies must use a catalog. -- `pnpm lint:catalogs` (`admin/scripts/lintCatalogs.js`): catalog entries are used and in the right catalog, templates and overrides match the catalogs, and dependency group members use the same version. +- `pnpm lint:catalogs` (`admin/scripts/lintCatalogs.js`): catalog entries are used and in the right catalog, templates and overrides match the catalogs, and dependency group members use matching versions. ## Dependency groups -Some packages must always use the same version. They are declared as `groups` in `.github/dependabot.yml`: +Some packages must always be upgraded together. They are declared as `groups` in `.github/dependabot.yml`: - Dependabot upgrades them atomically in a single PR, instead of opening broken intermediate PRs. -- `pnpm lint:catalogs` fails if their catalog versions differ. +- `pnpm lint:catalogs` fails if their catalog versions differ (only their major versions for the `babel` group, see `admin/scripts/lintCatalogs.js`). Packages belong to a group when, for example: diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 7e307f9bfc61..dca962e7a064 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -68,3 +68,9 @@ updates: svgr: patterns: - '@svgr/*' + # Babel packages depend on each other + # Upgrading them independently duplicates Babel packages in the lockfile + # See https://github.com/facebook/docusaurus/pull/12704 + babel: + patterns: + - '@babel/*' diff --git a/admin/scripts/lintCatalogs.js b/admin/scripts/lintCatalogs.js index 6124f22b27a7..bcc5b78e9f87 100644 --- a/admin/scripts/lintCatalogs.js +++ b/admin/scripts/lintCatalogs.js @@ -25,6 +25,9 @@ const RuntimeDependencyTypes = [ ]; const AllDependencyTypes = [...RuntimeDependencyTypes, 'devDependencies']; +// Babel only publishes the packages that changed: their versions differ +const SameMajorVersionDependencyGroups = ['babel']; + async function main() { const monorepo = await loadMonorepo(); @@ -216,7 +219,7 @@ function checkOverridesMatchCatalogs({catalogs, overrides}) { /** * The packages of a Dependabot group must be upgraded together, and must - * use the same version. + * use the same version, or the same major version for some groups. * @param {Monorepo} monorepo * @returns {string[]} */ @@ -227,15 +230,25 @@ function checkDependencyGroups({catalogs, dependencyGroups}) { const members = catalogEntries.filter(([name]) => matchesSomePattern(name, group.patterns), ); - const versions = new Set(members.map(([, version]) => version)); + const sameMajorVersion = SameMajorVersionDependencyGroups.includes( + group.name, + ); + const versions = new Set( + members.map(([, version]) => + sameMajorVersion ? getMajorVersion(version) : version, + ), + ); if (versions.size <= 1) { return []; } const membersDescription = members .map(([name, version]) => `${name}@${version}`) .join(', '); + const expectedVersion = sameMajorVersion + ? 'the same major version' + : 'the same version'; return [ - `pnpm-workspace.yaml: the packages of the "${group.name}" Dependabot group must use the same version: ${membersDescription}`, + `pnpm-workspace.yaml: the packages of the "${group.name}" Dependabot group must use ${expectedVersion}: ${membersDescription}`, ]; }); } @@ -270,6 +283,11 @@ function differsFromCatalogs(catalogs, name, version) { return catalogVersion !== undefined && catalogVersion !== version; } +// "^7.29.7" => "7" +function getMajorVersion(version) { + return version.match(/\d+/)?.[0]; +} + // Dependabot patterns only support the "*" wildcard function matchesSomePattern(name, patterns) { return patterns.some((pattern) => {