Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion packages/compat/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
},
Expand Down
54 changes: 41 additions & 13 deletions skills/maintainer/ui5wc-upgrade/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -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*)
Expand All @@ -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.

---

Expand All @@ -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

Expand All @@ -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.

---

Expand Down
Original file line number Diff line number Diff line change
@@ -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)

Expand Down Expand Up @@ -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"
}
```

Expand All @@ -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.
62 changes: 62 additions & 0 deletions skills/maintainer/ui5wc-upgrade/scripts/verify-peer-deps.mjs
Original file line number Diff line number Diff line change
@@ -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 <major.minor.patch>');
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] ?? '<missing>'}; 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}).`,
);
2 changes: 1 addition & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
Loading