Skip to content
Open
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 CONTRIBUTING-SKILLS.md
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ Every skill or agent must live in a plugin. Pick the one that matches your skill
| **code-review** | Review code for quality | Does this help me review code for quality? | |
| **design-audit** | Validate existing code/designs against PF standards | Does this check whether existing code or designs follow PF standards? | `pf-code-token-check`, `pf-color-scan`, `pf-figma-check` |
| **design-guide** | Choose the right PF components and patterns when building | Does this help me choose the right PF components and patterns when building? | `pf-ai-guide`, `pf-figma-design-mode` |
| **migration** | Upgrade PatternFly versions | Does this help me upgrade PF versions? | `pf-css-migration-scan`, `pf-react-migration-scan` |
| **migration** | Upgrade PatternFly versions | Does this help me upgrade PF versions? | `pf-css-migration-scan`, `pf-react-migration-scan`, `pf-release-candidate-update` |
| **patternfly-mcp** | Connect AI tools to PatternFly documentation and component data | | |
| **pf-workshop** | Team tools and skill incubation | Is this a team workflow tool, or a new skill that isn't ready for a consumer plugin yet? | `analytics-repo-pruning`, `duplicate-epic`, `figma-diff` |
| **react** | Develop and test React components | Does this help me write or test a React component? | `pf-component-check`, `pf-deploy`, `pf-design-comments-setup` |
Expand Down
2 changes: 1 addition & 1 deletion PLUGINS.md
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ PF version migration — breaking change detection, class scanning, upgrade plan
|-------|-------------|
| `pf-css-migration-scan` | Scan code for legacy PatternFly CSS classes and recommend PF6-safe replacements. |
| `pf-react-migration-scan` | Scan code for @patternfly/react-* API breaking changes and produce a markdown report. |

| `pf-release-candidate-update` | Update a project's PatternFly npm dependencies to the latest release candidate versions, install, build, test, and fix failures. |

<br>

Expand Down
1 change: 1 addition & 0 deletions plugins/migration/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ PF version migration — breaking change detection, class scanning, upgrade plan

- **PF CSS Migration Scan** (`/migration:pf-css-migration-scan`) — Scan code for legacy PatternFly CSS classes and recommend PF6-safe replacements.
- **PF React Migration Scan** (`/migration:pf-react-migration-scan`) — Scan code for @patternfly/react-* API breaking changes and produce a markdown report.
- **PF Release Candidate Update** (`/migration:pf-release-candidate-update`) — Update a project's PatternFly npm dependencies to the latest release candidate versions, install, build, test, and fix failures.

## Sources

Expand Down
160 changes: 160 additions & 0 deletions plugins/migration/skills/pf-release-candidate-update/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
---
name: pf-release-candidate-update
description: >-

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Skill descriptions get loaded into a limited context window alongside every other installed skill — longer descriptions are more likely to get cut off. Would a shorter version keep the trigger words intact? e.g., Update @patternfly/* npm dependencies to the latest release candidate versions. Use when testing the next PF release or bumping to RC packages.

Update @patternfly/* npm dependencies to the latest release candidate versions.
Use when testing the next PF release or bumping to RC packages.
disable-model-invocation: true
---

# PatternFly Release Candidate Update

Update a consumer project's `package.json` to the latest PatternFly release candidates on npm, install dependencies, verify the project builds and tests pass, and fix any failures introduced by the upgrade.

## Requirements

**Node.js** is required to run the bundled script (for JSON parsing and `package.json` updates).

```bash
command -v node >/dev/null 2>&1 || { echo "Error: This skill requires Node.js." >&2; exit 1; }
```

## Prerequisites

- Run from the **target project root** (the repo with `package.json`), not from `ai-helpers`.
- Network access for `npm view` and package install.
- Invoke the skill script via `$CLAUDE_SKILL_DIR/scripts/latest-release-candidates.sh`.

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## Workflow checklist

```
- [ ] Step 1: Resolve latest release candidate versions
- [ ] Step 2: Update package.json
- [ ] Step 3: Install dependencies
- [ ] Step 4: Build
- [ ] Step 5: Run tests
- [ ] Step 6: Fix build/test failures (loop until green)
- [ ] Step 7: Summarize changes
```

## Step 1: Resolve versions

Run the script to fetch the latest release candidate for each canonical PatternFly package:

```bash
bash "$CLAUDE_SKILL_DIR/scripts/latest-release-candidates.sh" --json
```

The script queries npm's `prerelease` dist-tag (PatternFly's release candidate channel), then falls back to the highest published candidate version (any version containing `-`). Packages covered:

`@patternfly/patternfly`, `@patternfly/react-charts`, `@patternfly/react-code-editor`, `@patternfly/react-core`, `@patternfly/react-drag-drop`, `@patternfly/react-icons`, `@patternfly/react-styles`, `@patternfly/react-table`, `@patternfly/react-templates`, `@patternfly/react-tokens`, `@patternfly/react-topology`, `@patternfly/react-virtualized-extension`, `@patternfly/quickstarts`, `@patternfly/react-user-feedback`, `@patternfly/react-console`, `@patternfly/react-log-viewer`, `@patternfly/react-catalog-view-extension`, `@patternfly/react-component-groups`, `@patternfly/react-data-view`, `@patternfly/chatbot`

**If the user provided specific versions**, use those instead and skip the script.

## Step 2: Update package.json

Update only PatternFly packages. Do not change unrelated dependencies.

### Sections to update

In every `package.json` at the project root (and in workspaces if the repo is a monorepo):

- `dependencies`
- `devDependencies`
- `peerDependencies`
- `optionalDependencies`
- `resolutions` (Yarn)
- `overrides` (npm)

For each `@patternfly/*` entry that appears in the canonical list above, set the version to the resolved release candidate. Leave version prefixes (`^`, `~`) off — use exact candidate versions (e.g. `"6.6.0-prerelease.16"`).

**Automated update** (root `package.json` only):

```bash
bash "$CLAUDE_SKILL_DIR/scripts/latest-release-candidates.sh" --update package.json
```

For monorepos, run `--update` on each workspace `package.json` that contains PatternFly deps, or update them manually using the `--json` output.

**Do not** add packages the project does not already use unless the user explicitly asks.

## Step 3: Install

Detect the package manager from lockfiles:

| Lockfile | Install command |
|----------|-----------------|
| `pnpm-lock.yaml` | `pnpm install` |
| `yarn.lock` | `yarn install` |
| `package-lock.json` | `npm install` |
| none | `npm install` |

If install fails on peer dependency conflicts, retry with the project's usual workaround (`--legacy-peer-deps` for npm, `yarn install --ignore-engines` only if the project already uses it). Prefer fixing version alignment over forcing installs.

## Step 4: Build

Run the project's build script:

```bash
npm run build # or yarn build / pnpm build
```

If there is no `build` script, run whatever compile step the project uses (`tsc`, `vite build`, `webpack`, etc.) and note the command used.

**Build must pass before moving on.**

## Step 5: Run tests

```bash
npm test # or yarn test / pnpm test
```

If the project separates unit and integration tests, run the full suite the CI runs (check `.github/workflows` or `package.json` scripts).

**All tests must pass before finishing.**

## Step 6: Fix failures

When build or tests fail after the upgrade, fix the project code — do not pin back to older versions unless the failure is an upstream bug with no workaround.

### Diagnosis order

1. **Read the error output** — note the first failing file and whether it is a type error, import error, or runtime/test failure.
2. **Import paths** — scan for invalid `@patternfly/*` import paths (charts, chatbot, component-groups dynamic paths, missing CSS).
3. **Deprecated APIs** — query the PatternFly MCP server for current component APIs and migration guidance.
4. **CSS classes / tokens** — scan for legacy `pf-c-*`, `pf-v5-*`, or hardcoded values.
5. **Component structure** — audit component nesting and layout for hierarchy violations exposed by stricter types or DOM changes.
6. **Snapshot / visual tests** — update snapshots only when the visual change is intentional from the PF upgrade.

### Fix loop

```
build → fail? → fix → build
test → fail? → fix → test
```

Repeat until both build and tests pass. Keep fixes minimal and scoped to what the upgrade broke.

## Step 7: Summarize

Report to the user:

- Previous and new versions for each updated `@patternfly/*` package
- Package manager and commands run
- Any code changes made to fix build/test failures
- Remaining risks (e.g. packages that fell back to stable because no release candidate exists)

## Monorepo notes

- Update every workspace `package.json` that lists PatternFly deps; keep versions consistent across workspaces.
- Run install once at the root.
- Build/test from the root if the repo uses workspace scripts; otherwise build/test each affected package.

## Common issues

| Symptom | Likely fix |
|---------|------------|
| `Module not found: @patternfly/...` | Wrong import path; scan for invalid `@patternfly/*` import paths |
| Peer dependency warnings on install | Align all `@patternfly/*` packages to the same release candidate set |
| Type errors on removed props | Check PatternFly MCP for replacement props/APIs |
| CSS/layout regressions | Verify `base.css` and feature CSS imports; scan for legacy classes |
| Test snapshot failures | Review diff; update only if PF change is expected |
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
#!/usr/bin/env bash
# Resolve the latest release candidate version for each PatternFly package on npm.
# Usage:
# ./latest-release-candidates.sh # one line per package: "@patternfly/pkg": "x.y.z",
# ./latest-release-candidates.sh --json # JSON object of package -> version
# ./latest-release-candidates.sh --update [package.json] # update PF deps in package.json

set -euo pipefail

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The fallback path (line 44) and --update mode (line 91) both call node -e, but the script doesn't check for Node.js first. Would a command -v node guard near the top help? CONTRIBUTING-SKILLS.md L234–237 shows the pattern. The SKILL.md would also need a ## Requirements section noting the Node.js dependency.


command -v node >/dev/null 2>&1 || { echo "Error: This skill requires Node.js." >&2; exit 1; }

PACKAGES=(
"@patternfly/patternfly"
"@patternfly/react-charts"
"@patternfly/react-code-editor"
"@patternfly/react-core"
"@patternfly/react-drag-drop"
"@patternfly/react-icons"
"@patternfly/react-styles"
"@patternfly/react-table"
"@patternfly/react-templates"
"@patternfly/react-tokens"
"@patternfly/react-topology"
"@patternfly/react-virtualized-extension"
"@patternfly/quickstarts"
"@patternfly/react-user-feedback"
"@patternfly/react-console"
"@patternfly/react-log-viewer"
"@patternfly/react-catalog-view-extension"
"@patternfly/react-component-groups"
"@patternfly/react-data-view"
"@patternfly/chatbot"
)

resolve_release_candidate() {
local pkg="$1"
local version tag

# PatternFly publishes release candidates under npm's "prerelease" dist-tag.
tag=$(npm view "$pkg" dist-tags.prerelease 2>/dev/null || true)
if [[ -n "$tag" && "$tag" != "undefined" && "$tag" == *-* ]]; then
echo "$tag"
return 0
fi

version=$(npm view "$pkg" versions --json 2>/dev/null | node -e "
const versions = JSON.parse(require('fs').readFileSync(0, 'utf8'));
const candidates = versions.filter((v) => v.includes('-'));
if (candidates.length === 0) {
process.stderr.write('warning: no release candidate found for ${pkg}; using latest stable\n');
console.log(versions[versions.length - 1]);
} else {
console.log(candidates[candidates.length - 1]);
}
")

echo "$version"
}

output_json() {
local first=true
echo -n "{"
for pkg in "${PACKAGES[@]}"; do
version=$(resolve_release_candidate "$pkg")
if [ "$first" = true ]; then
first=false
else
echo -n ","
fi
printf '\n "%s": "%s"' "$pkg" "$version"
done
echo
echo "}"
}

output_lines() {
for pkg in "${PACKAGES[@]}"; do
version=$(resolve_release_candidate "$pkg")
echo "\"$pkg\": \"$version\","
done
}

update_package_json() {
local file="${1:-package.json}"
if [ ! -f "$file" ]; then
echo "error: $file not found" >&2
exit 1
fi

local versions_json
versions_json=$(output_json)

node -e "
const fs = require('fs');
const path = process.argv[1];
const versions = JSON.parse(process.argv[2]);
const pkg = JSON.parse(fs.readFileSync(path, 'utf8'));

const sections = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
let updated = 0;

for (const section of sections) {
if (!pkg[section]) continue;
for (const name of Object.keys(pkg[section])) {
if (versions[name]) {
pkg[section][name] = versions[name];
updated++;
}
}
}

for (const section of ['resolutions', 'overrides']) {
if (!pkg[section]) continue;
for (const name of Object.keys(pkg[section])) {
if (versions[name]) {
pkg[section][name] = versions[name];
updated++;
}
}
}

fs.writeFileSync(path, JSON.stringify(pkg, null, 2) + '\n');
console.log('Updated ' + updated + ' PatternFly entries in ' + path);
" "$file" "$versions_json"
}

mode="${1:---lines}"
case "$mode" in
--json)
output_json
;;
--update)
update_package_json "${2:-package.json}"
;;
--lines|"")
output_lines
;;
-h|--help)
echo "Usage: $0 [--json | --update [package.json] | --lines]"
;;
*)
echo "error: unknown option $mode" >&2
exit 1
;;
esac