diff --git a/packages/compat/package.json b/packages/compat/package.json index 2de0f6153c6..fb6c21a64a7 100644 --- a/packages/compat/package.json +++ b/packages/compat/package.json @@ -94,7 +94,7 @@ "@types/react": "*", "@types/react-dom": "*", "@ui5/webcomponents-compat": "~2.28.1", - "@ui5/webcomponents-react": "~2.28.1", + "@ui5/webcomponents-react": "~2.28.0", "react": "^18 || ^19", "react-dom": "^18 || ^19" }, diff --git a/skills/maintainer/ui5wc-upgrade/SKILL.md b/skills/maintainer/ui5wc-upgrade/SKILL.md index fc4ecc60e31..e3c4baaec22 100644 --- a/skills/maintainer/ui5wc-upgrade/SKILL.md +++ b/skills/maintainer/ui5wc-upgrade/SKILL.md @@ -4,6 +4,7 @@ description: Guide a complete UI5 Web Components version upgrade in the ui5-webc disable-model-invocation: true argument-hint: target version (e.g. 2.22.0) allowed-tools: + - Bash(node skills/maintainer/ui5wc-upgrade/scripts/verify-peer-deps.mjs*) - Bash(yarn create-webcomponents-wrapper*) - Bash(yarn create-webcomponents-wrapper-ai*) - Bash(yarn create-webcomponents-wrapper-compat*) @@ -28,10 +29,18 @@ Ensure the working tree is clean before starting (`git status` should show no un ## Initialization 1. Parse the **target version** from the argument (e.g. `2.25.0` or `2.25.1`). -2. Derive the **tilde range** `~TARGET_VERSION` for peerDependencies (e.g. `~2.25.1`). +2. Derive two peerDependency ranges: + - **Upstream range:** `~TARGET_VERSION` (e.g. `~2.25.1`) for `@ui5/webcomponents*` packages. + - **React wrapper range:** `~TARGET_MAJOR.TARGET_MINOR.0` (e.g. `~2.25.0`) for the + `@ui5/webcomponents-react` peer in the compat package. The wrapper release version is + aligned to the UI5 Web Components minor, but it does not necessarily share the upstream + patch version. 3. Read the **current version** from root `package.json` → `dependencies["@ui5/webcomponents"]`. -4. If current matches target, ask if the user wants to re-run wrapper generation only (skip to Step 2). -5. Check if Renovate already updated root deps — if `dependencies["@ui5/webcomponents"]` already matches target, note that Step 1a can be skipped. +4. Check if Renovate already updated root deps — if `dependencies["@ui5/webcomponents"]` already matches target, + note that Step 1a can be skipped. **Do not skip Step 1b:** Renovate updating the root does not prove that + package peerDependencies are correct. +5. If the whole upgrade may already have been applied, still reconcile and verify Step 1b before deciding + whether wrapper generation needs to be re-run. --- @@ -51,17 +60,19 @@ Update to the exact target version: ### 1b. Package peerDependencies -Update tilde ranges to `~TARGET_VERSION` in all sub-packages. See `references/package-json-peer-deps.md` for the exact map. Summary: +Update the upstream tilde ranges to `~TARGET_VERSION` and the compat package's internal React +wrapper peer to `~TARGET_MAJOR.TARGET_MINOR.0`. See `references/package-json-peer-deps.md` for +the exact map. Summary: -| File | Keys to update | -| ---------------------------------------- | ------------------------------------------------------- | -| `packages/main/package.json` | `@ui5/webcomponents`, `-base`, `-fiori`, `-icons` | -| `packages/base/package.json` | `@ui5/webcomponents-base` | -| `packages/ai/package.json` | `@ui5/webcomponents-ai` | -| `packages/compat/package.json` | `@ui5/webcomponents-compat`, `@ui5/webcomponents-react` | -| `packages/cypress-commands/package.json` | `@ui5/webcomponents`, `-base` | +| File | Keys to update | +| ---------------------------------------- | ---------------------------------------------------------------------------------------------- | +| `packages/main/package.json` | `@ui5/webcomponents`, `-base`, `-fiori`, `-icons` | +| `packages/base/package.json` | `@ui5/webcomponents-base` | +| `packages/ai/package.json` | `@ui5/webcomponents-ai` | +| `packages/compat/package.json` | `@ui5/webcomponents-compat` → upstream range; `@ui5/webcomponents-react` → React wrapper range | +| `packages/cypress-commands/package.json` | `@ui5/webcomponents`, `-base` | -> **Note:** `packages/charts/package.json` uses caret ranges (`^`) and does **not** need updating for minor version bumps. +> **Note:** `packages/charts/package.json` keeps its established `^2.21.0` compatibility floor and does **not** need updating for minor version bumps. The validator confirms that it was not accidentally narrowed. ### 1c. Install @@ -71,11 +82,28 @@ yarn install ### Verify +Run the exact-value validator (replace the example with the real target): + +```bash +node skills/maintainer/ui5wc-upgrade/scripts/verify-peer-deps.mjs 2.25.1 +``` + +It verifies every mapped key against the correct range. Checking only for the old range is not +sufficient, because it cannot detect an incorrect upstream patch applied to the internal React peer. +For target `2.25.1`, these values must coexist in compat: + +```json +"@ui5/webcomponents-compat": "~2.25.1", +"@ui5/webcomponents-react": "~2.25.0" +``` + +Also confirm that no old minor range remains: + ```bash grep -r "~OLD_MINOR" packages/*/package.json ``` -Must return zero results (replace OLD_MINOR with the previous minor version tilde range). +The validator and the old-range check must both pass before continuing. --- diff --git a/skills/maintainer/ui5wc-upgrade/references/package-json-peer-deps.md b/skills/maintainer/ui5wc-upgrade/references/package-json-peer-deps.md index 80acd5ef0e7..a96ad2eeca1 100644 --- a/skills/maintainer/ui5wc-upgrade/references/package-json-peer-deps.md +++ b/skills/maintainer/ui5wc-upgrade/references/package-json-peer-deps.md @@ -1,6 +1,12 @@ # Package peerDependency Map for UI5 WC Upgrades -When upgrading to a target version, update tilde ranges to `~TARGET_VERSION` in these files. +When upgrading to a target version, use two distinct ranges: + +- Upstream UI5 Web Components packages: `~TARGET_VERSION`. +- Internal React wrapper peers: `~TARGET_MAJOR.TARGET_MINOR.0`. + +For example, target `2.25.1` means upstream peers use `~2.25.1`, while the compat +package's `@ui5/webcomponents-react` peer uses `~2.25.0`. ## Root package.json (dependencies, NOT peerDeps) @@ -55,18 +61,24 @@ Update to exact target version (e.g. `2.25.1`): ```json "peerDependencies": { "@ui5/webcomponents-compat": "~X.Y.Z", - "@ui5/webcomponents-react": "~X.Y.Z" + "@ui5/webcomponents-react": "~X.Y.0" } ``` +These ranges deliberately differ when the upstream target is a patch release. +`@ui5/webcomponents-compat` tracks the exact upstream target, while +`@ui5/webcomponents-react` tracks the wrapper release line. + ## packages/charts/package.json -Charts uses **caret ranges** (`^`), so its peerDependencies do **not** need updating for minor version bumps. +Charts uses **caret ranges** (`^`) with an established `2.21.0` compatibility floor, so its +peerDependencies do **not** change during UI5 Web Components upgrades. Only change this floor +when charts itself stops supporting older wrapper versions. ```json "peerDependencies": { - "@ui5/webcomponents-react": "^X.Y.Z", - "@ui5/webcomponents-react-base": "^X.Y.Z" + "@ui5/webcomponents-react": "^2.21.0", + "@ui5/webcomponents-react-base": "^2.21.0" } ``` @@ -83,7 +95,7 @@ Charts uses **caret ranges** (`^`), so its peerDependencies do **not** need upda ## Important Notes -- `charts` and `compat` reference `@ui5/webcomponents-react` (the React wrapper), not the upstream `@ui5/webcomponents` packages directly. +- `charts` and `compat` reference `@ui5/webcomponents-react` (the React wrapper), not the upstream `@ui5/webcomponents` packages directly. Never copy the upstream patch version into these internal wrapper peer ranges. - `@ui5/webcomponents-react-base` in `charts` tracks the monorepo version, which since v2.4.0 aligns with the UI5 WC minor version. - `peerDependenciesMeta` sections do NOT need updating — they only mark deps as optional and contain no version info. - Non-UI5 peer deps (`react`, `react-dom`, `@types/react`, `cypress`) are NOT touched during upgrades. diff --git a/skills/maintainer/ui5wc-upgrade/scripts/verify-peer-deps.mjs b/skills/maintainer/ui5wc-upgrade/scripts/verify-peer-deps.mjs new file mode 100644 index 00000000000..bb60d4ea425 --- /dev/null +++ b/skills/maintainer/ui5wc-upgrade/scripts/verify-peer-deps.mjs @@ -0,0 +1,62 @@ +import { readFileSync } from 'node:fs'; +import process from 'node:process'; + +const targetVersion = process.argv[2]; +const match = /^(\d+)\.(\d+)\.(\d+)$/.exec(targetVersion ?? ''); + +if (!match) { + console.error('Usage: node verify-peer-deps.mjs '); + process.exit(1); +} + +const [, major, minor] = match; +const upstreamRange = `~${targetVersion}`; +const reactWrapperRange = `~${major}.${minor}.0`; +const expected = { + 'packages/main/package.json': { + '@ui5/webcomponents': upstreamRange, + '@ui5/webcomponents-base': upstreamRange, + '@ui5/webcomponents-fiori': upstreamRange, + '@ui5/webcomponents-icons': upstreamRange, + }, + 'packages/base/package.json': { + '@ui5/webcomponents-base': upstreamRange, + }, + 'packages/ai/package.json': { + '@ui5/webcomponents-ai': upstreamRange, + }, + 'packages/compat/package.json': { + '@ui5/webcomponents-compat': upstreamRange, + '@ui5/webcomponents-react': reactWrapperRange, + }, + 'packages/cypress-commands/package.json': { + '@ui5/webcomponents': upstreamRange, + '@ui5/webcomponents-base': upstreamRange, + }, + 'packages/charts/package.json': { + '@ui5/webcomponents-react': '^2.21.0', + '@ui5/webcomponents-react-base': '^2.21.0', + }, +}; + +const errors = []; + +for (const [file, expectedPeers] of Object.entries(expected)) { + const manifest = JSON.parse(readFileSync(file, 'utf8')); + const actualPeers = manifest.peerDependencies ?? {}; + + for (const [name, expectedRange] of Object.entries(expectedPeers)) { + if (actualPeers[name] !== expectedRange) { + errors.push(`${file}: ${name} is ${actualPeers[name] ?? ''}; expected ${expectedRange}`); + } + } +} + +if (errors.length > 0) { + console.error(errors.join('\n')); + process.exit(1); +} + +console.log( + `Peer dependencies match target ${targetVersion} (upstream ${upstreamRange}, React wrapper ${reactWrapperRange}).`, +); diff --git a/yarn.lock b/yarn.lock index 03b8291beac..360317d4ec2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -5761,7 +5761,7 @@ __metadata: "@types/react": "*" "@types/react-dom": "*" "@ui5/webcomponents-compat": ~2.28.1 - "@ui5/webcomponents-react": ~2.28.1 + "@ui5/webcomponents-react": ~2.28.0 react: ^18 || ^19 react-dom: ^18 || ^19 peerDependenciesMeta: