build: guard against duplicate @wordpress package installs - #618
Open
dcalhoun wants to merge 2 commits into
Open
build: guard against duplicate @wordpress package installs#618dcalhoun wants to merge 2 commits into
dcalhoun wants to merge 2 commits into
Conversation
XCFramework BuildThis PR's XCFramework is available for testing. Add the following to your .package(url: "https://github.com/wordpress-mobile/GutenbergKit", branch: "pr-build/618")Built from aaf162a |
The editor exposes its @WordPress packages on `window.wp` as single instances, so they have to move together the way a Gutenberg release does. Bumping them one at a time leaves mismatched ranges that nest duplicate copies under the packages that moved ahead. Group them into a single pull request, scoped to production dependencies. Dev tooling -- eslint-plugin, env, prettier-config, and dependency-extraction-webpack-plugin -- never reaches the bundle, and since Dependabot ships a group atomically, a breaking tooling major would otherwise hold back every runtime bump alongside it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W7uwvhYJ8vzNFAZddFoxD2
dcalhoun
force-pushed
the
build/guard-wordpress-package-duplicates
branch
from
September 3, 2026 14:35
da8b7bc to
a916f90
Compare
Plugin scripts reach the bundled packages through `window.wp`, which only works while each package is a single module instance. `wordPressExternals()` rewrites source imports to `window.wp` but deliberately skips `node_modules`, so a copy nested under another dependency is bundled by path and becomes a second instance, carrying its own React contexts, data stores, and private APIs. Nothing at runtime reports the split. Add `make check-wp-packages`, which reads `package-lock.json` and fails when any production `@wordpress` package has more than one install. The lockfile is the source of truth rather than the installed tree: it describes what a fresh `npm ci` produces, needs no `node_modules`, and its `packages` keys are install paths, so two copies of the same version -- still two module instances -- are caught alongside mismatched versions. A lockfile that is unreadable, malformed, or free of `@wordpress` packages fails rather than reporting that nothing was wrong. `@wordpress/icons` currently resolves to two versions and is allowed through `KNOWN_DUPLICATES` as a warning, so the invariant is enforced going forward rather than blocked on a coordinated bump. An entry that no longer applies fails the check, so an allowance cannot outlive the mismatch it covers. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01W7uwvhYJ8vzNFAZddFoxD2
dcalhoun
force-pushed
the
build/guard-wordpress-package-duplicates
branch
from
September 3, 2026 14:38
a916f90 to
aaf162a
Compare
dcalhoun
commented
Sep 3, 2026
Member
Author
There was a problem hiding this comment.
I've never implemented or seen a check list this, but duplicates can cause cryptic failures so avoiding them is valuable. If this check proves problematic in the future, we can remove it.
dcalhoun
marked this pull request as ready for review
September 3, 2026 14:47
This file contains hidden or 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
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What?
Guard the single-instance requirement for
@wordpresspackages: group@wordpress/*Dependabot updates so they move together, and add a CI check that fails when any production@wordpresspackage has more than one install.Why?
Plugin scripts reach the bundled packages through
window.wp, mirroring WP Admin. That only works while each package is a single module instance. A second copy nested under another dependency brings its own React contexts, data stores, and private APIs, so a plugin receives a different instance than the editor's own components use, with nothing at runtime to signal the split.Nothing enforced this, and per-package Dependabot bumps have already broken it on
trunk:@wordpress/iconsresolves to both 11.8.0 and 12.1.0 becausecommands,components, andpreferenceswere bumped to versions requiring^12.1.0whileblock-editorandeditorstill require^11.8.0. Review of #614 raised the same risk for the new@wordpress/themedependency.How?
Prevention. Dependabot groups
@wordpress/*into a single pull request, scoped to production dependencies. Dev tooling —eslint-plugin,env,prettier-config,dependency-extraction-webpack-plugin— never reaches the bundle, and because a group ships atomically, a breaking tooling major would otherwise hold back every runtime bump alongside it.Detection.
bin/check-wordpress-package-duplicates.jsfails when any production@wordpresspackage has more than one install, exposed asmake check-wp-packagesand wired into Buildkite and the release target.package-lock.jsonis the source of truth rather than the installed tree. It describes what a freshnpm ciproduces, so the check needs nonode_modulesand cannot report on a stale one, and itspackageskeys are install paths — meaning two copies of the same version, still two module instances, are caught alongside mismatched versions. A lockfile that is unreadable, malformed, or free of@wordpresspackages fails rather than reporting that nothing was wrong.KNOWN_DUPLICATESlets a duplicate through as a warning for cases where the coordinated bump genuinely has to wait, such as a security advisory that moves one package alone. The failure output names the allowlist along with what accepting a split costs, so the exception is taken knowingly; an entry that no longer applies fails the check, so an allowance cannot outlive the mismatch it covers.docs/code/plugins.mddocuments the requirement, both safeguards, and the outstanding allowance.Known duplicate:
@wordpress/iconsThe only allowlisted entry. No single version satisfies the current tree:
block-editorandeditorrequire^11.8.0, whilecomponents,commands, andpreferencesrequire^12.1.0, so raising the direct pin would only flip which copy is nested. Every current latest release agrees on^15.5.0, so the first grouped Dependabot bump resolves it. That bump is a sizable upgrade (block-editor 15 → 17, components 32 → 40) and the five version-pinned patches underpatches/will need re-verifying, so it should be handled as its own pull request. Remove the allowlist entry there.Testing Instructions
make check-wp-packages. It passes, warning about the known@wordpress/iconsduplicate and naming each install path.@wordpress/iconsentry inKNOWN_DUPLICATEStofalseand rerun. It exits 1, reports the duplicate, and points at the allowlist.true, temporarily renamepackage-lock.json, and rerun. It exits 1 naming the unreadable lockfile rather than reporting that nothing was wrong.Accessibility Testing Instructions
N/A. No UI changes.
Screenshots or screencast
N/A
🤖 Generated with Claude Code
https://claude.ai/code/session_01W7uwvhYJ8vzNFAZddFoxD2