en un clic
patch-backstage
// Workflow to backport Backstage changes into RHDH by syncing a downstream maintenance branch and generating yarn patches.
// Workflow to backport Backstage changes into RHDH by syncing a downstream maintenance branch and generating yarn patches.
Workflow to backport Backstage changes into RHDH by syncing a downstream maintenance branch and generating yarn patches.
Deploy RHDH to an OpenShift cluster using local-run.sh for E2E test execution, with autonomous error recovery for deployment failures
Analyze a failing E2E test, determine root cause, and fix it using Playwright Test Agents and RHDH project conventions
Parse a Prow CI job URL or Jira ticket to extract E2E test failure details including test name, spec file, release branch, platform, and error messages
Run a specific failing E2E test against a deployed RHDH instance to confirm the failure and determine if it is consistent or flaky
Create a PR for an E2E test fix, trigger Qodo agentic review, address review comments, and monitor CI results
| name | patch-backstage |
| description | Workflow to backport Backstage changes into RHDH by syncing a downstream maintenance branch and generating yarn patches. |
Ship a fix on an RHDH release-* line without bumping published Backstage versions by adding Yarn patches (.yarn/patches/, package.json resolutions, lockfiles).
COMMITS: SHAs on backstage/backstage that are on master (merged fixes). Fetch master from BACKSTAGE_UPSTREAM_REMOTE so those objects exist in the maintenance clone for git show / cherry-pick.patch/release-<VERSION> only (not a separate upstream checkout).| Repo | Role |
|---|---|
| redhat-developer/rhdh | Patches live here. Sync release-<VERSION>; run yarn patch here (root and/or dynamic-plugins/). |
| redhat-developer/backstage | Maintenance fork: patch/release-<VERSION>, optional cherry-pick, yarn build per package cd, copy dist/ into RHDH patch temps. PRs from your fork. |
| backstage/backstage | Upstream object source only: remote on the same maintenance clone, git fetch for COMMITS. Do not use a second upstream checkout as the build tree. |
| Name | Required | Notes |
|---|---|---|
RHDH_VERSION | Yes | e.g. 1.9 → release-1.9, patch/release-1.9. Do not infer from the current branch. |
RHDH_ROOT | No | Absolute path to the RHDH repo root (appears as <RHDH_ROOT> in examples). Inferred from context if omitted. |
COMMITS | Typical | Upstream SHAs (oldest first for cherry-pick). If no SHAs, manual dist / patch only. |
PACKAGES | If unclear | @backstage/... names. Derive from COMMITS (below) when paths map cleanly. |
Path map: @backstage/plugin-<id> → plugins/<id>/; other @backstage/<id> → packages/<id>/.
PACKAGES from COMMITSIn the maintenance clone, after git fetch <BACKSTAGE_UPSTREAM_REMOTE> master so COMMITS exist locally: git show --name-only --pretty=format: <SHA> (union for multiple SHAs). Map plugins/* and packages/* roots; read each package.json name; dedupe. Ignore-only changes (root lockfile, .changeset/, docs/, version-only package.json) → ask which packages to patch.
Example: 66e08b08f94a31cbf28b416c89b61549bc3b64a2 → @backstage/cli-common, @backstage/backend-plugin-api, @backstage/plugin-techdocs-node.
Map remotes by URL in each clone (git remote -v); never assume upstream means a given org.
release-*): URL redhat-developer/rhdh → RHDH_CORE_REMOTE.patch/release-*, fork push): URL redhat-developer/backstage + usually your fork as origin.COMMITS only): URL backstage/backstage → BACKSTAGE_UPSTREAM_REMOTE.Exact maintenance tip:
git fetch https://github.com/redhat-developer/backstage.git patch/release-<RHDH_VERSION>
then HUSKY=0 git checkout -B patch/release-<RHDH_VERSION> FETCH_HEAD when Husky would otherwise run on checkout.
Silencing hooks: For branch sync only (Steps 1–2: fetch/checkout/pull/checkout -B, and git cherry-pick when you are not relying on hook side effects), prefix with HUSKY=0. Omit HUSKY=0 on git commit if you want lint-staged locally.
cd <RHDH_ROOT> && HUSKY=0 git fetch <RHDH_CORE_REMOTE> release-<V> && HUSKY=0 git checkout release-<V> && HUSKY=0 git pull <RHDH_CORE_REMOTE> release-<V>
Rulesync: Edit SKILL.md only under .rulesync/skills/patch-backstage/ (rulesync expects one directory per skill with SKILL.md inside; a flat *.md at skills/ root is ignored). With "skills" and "simulateSkills": true in rulesync.jsonc, yarn rulesync:generate writes both .claude/skills/ and .cursor/skills/ from that tree (rulesync treats Cursor skill output as “simulated”). Stage and commit generated paths with .rulesync/ after edits.
&& and cd <RHDH_ROOT>; cwd may not persist between tool calls. Use network / git_write / all as needed (all for rm/cp into Yarn patch temps or stubborn sandboxes).RHDH_VERSION, COMMITS, clone paths, or workspace ownership is missing or ambiguous—not for a second confirmation when the user already asked for yarn patches for given SHAs (see Pre-check → patch-only).find; do run steps this doc names (git remote -v, yarn why, etc.).yarn patch overlays dist/ on the version RHDH already resolves (lockfile), so PACKAGE_VERSION must come from yarn why, not from “what Backstage released.”patch/release-<RHDH_VERSION> after fetching that ref from redhat-developer (local/fork tips can diverge by name).RHDH_CORE_REMOTE, BACKSTAGE_UPSTREAM_REMOTE, optional FORK_REMOTE (your Backstage fork for PRs).HUSKY=0 fetch/checkout/pull release-<RHDH_VERSION>.patch/release-* from redhat-developer; HUSKY=0 checkout -B; git fetch <BACKSTAGE_UPSTREAM_REMOTE> master (upstream integration branch for COMMITS); pre-check; cherry-pick or patch-only path; yarn build per PACKAGES (cd + yarn build, not root yarn workspace … build)..patch + resolutions for targets; yarn why → versions; yarn patch / replace dist / patch-commit; clean up resolutions; yarn install (root and dynamic-plugins/ as needed).@patch: in each relevant yarn.lock; yarn why shows via patch:; commit artifacts.Pre-flight (both repos): git status clean in RHDH and the maintenance Backstage clone (stash WIP or git merge --abort / git rebase --abort as needed). Do not run the workflow mid-conflict.
git remote -v → RHDH_CORE_REMOTE = remote for redhat-developer/rhdh.HUSKY=0 git fetch … release-<RHDH_VERSION> && HUSKY=0 git checkout … && HUSKY=0 git pull …. Fail if the branch is missing.MAINTENANCE_BRANCH = patch/release-<RHDH_VERSION> (used when opening a Backstage PR).One clone with redhat-developer/backstage + backstage/backstage remotes.
patch/release-*git fetch https://github.com/redhat-developer/backstage.git patch/release-<RHDH_VERSION> \
&& HUSKY=0 git checkout -B patch/release-<RHDH_VERSION> FETCH_HEAD
Then git fetch <BACKSTAGE_UPSTREAM_REMOTE> master. backstage/backstage lands merged work on master; COMMITS should be reachable from master. Do not check out upstream as the build tree.
For each SHA in COMMITS (oldest first):
git show --name-only --pretty=format: <SHA>package.json, CHANGELOG.md, package package.json version-only edits, .changeset/, docs/, lockfiles, etc. Keep src/, tests, fixtures tied to the fix.git diff <SHA> HEAD -- <kept paths> (union paths if multiple SHAs).Empty diff → maintenance already has the functional fix; do not cherry-pick (avoids changelog/version noise).
COMMITS on this release-*: empty pre-check → go to 2.6 Build and RHDH Steps 3–5; note in the Final summary that cherry-pick was skipped.git cherry-pick <SHA> (oldest first) onto patch/release-*.
Conflicts: Prefer the cherry-picked commit’s content for conflicted src/ (during cherry-pick, git checkout --theirs -- <path> refers to that commit). If fixing conflicts would drop the functional fix, or conflicts are only changelog/version noise you should not merge, git cherry-pick --abort, note it in the Final summary, and coordinate with the user. Do not push a broken maintenance branch.
Push to FORK_REMOTE and open a PR to redhat-developer/backstage base MAINTENANCE_BRANCH (no direct push to redhat-developer).
PACKAGESFor each package: cd plugins/<id>/ or packages/<id>/ → yarn build. If dist-types or build fails: maintenance repo root yarn install / yarn tsc, then retry per-package yarn build.
dynamic-plugins/ is a separate Yarn project: its yarn.lock and resolutions are independent of the root.
.patch files and matching resolutions entries for the packages you are refreshing (search both root and dynamic-plugins/package.json).yarn why @backstage/<pkg> from RHDH root; if empty, run from dynamic-plugins/. Record PACKAGE_VERSION for Step 4.Run from RHDH root or dynamic-plugins/ depending on where the dependency resolves.
Temp folder: Each yarn patch … prints a new path—use it immediately for rm, cp, yarn patch-commit -s (same shell or paste path). Do not reuse an old temp. Sandboxes may need all for cp into system temp.
Per package:
yarn patch <package>@npm:<PACKAGE_VERSION>rm -rf <PATCH_TEMP>/dist && cp -r <backstage-clone>/<plugins|packages>/.../dist <PATCH_TEMP>/distyarn patch-commit -s <PATCH_TEMP> in that workspace.If a package resolves in both trees at the same version, patch both places (or mirror the patch: resolution into dynamic-plugins/package.json and run yarn install there too).
yarn patch-commit (cleanup — required)"@backstage/foo": "1.2.3" in resolutions with the single patch: locator Yarn printed—do not leave bare semver beside new patch keys (patch may not apply; Step 5 will show plain @npm:).patch-commit added (e.g. @backstage/foo@^1.6.0 → patch built from @npm:1.5.0), which mis-resolve other workspaces (dynamic-plugins/ may need @backstage/backend-plugin-api@1.6.0 untouched by root).yarn install at root and/or dynamic-plugins/;Incomplete until every patched package shows a patch locator in yarn.lock and yarn why.
yarn install in each touched project.grep '@backstage/<pkg>@patch' yarn.lock (run inside dynamic-plugins/ for packages resolved only there).yarn why @backstage/<pkg> in the same directory: must include via patch: / @…@patch:, not only via npm:<version>.Optional: Spot-check node_modules/@backstage/<pkg>/dist/.
Commit: .yarn/patches/*.patch, package.json resolutions, yarn.lock (root and/or dynamic-plugins/); PR to RHDH.
https://github.com/backstage/backstage/commit/<SHA> for each COMMITS entry.PACKAGES, patch locations (root vs dynamic-plugins/), notable resolutions keys.MAINTENANCE_BRANCH, optional Backstage PR link; RHDH PR intent.RHDH_VERSION.patch/release-* if missing on redhat-developer/backstage.| Symptom | What to do |
|---|---|
| Wrong maintenance tip | Fetch https://github.com/redhat-developer/backstage.git patch/release-<V>, checkout -B … FETCH_HEAD |
bad object on cherry-pick / show | git fetch <BACKSTAGE_UPSTREAM_REMOTE> master |
| Checkout/pull fails after Yarn / Husky | HUSKY=0 on those git commands |
yarn why / lockfile: no @patch: | Remove bare semver resolutions for that pkg; use one patch: locator; drop wrong range keys; reinstall |
| Build fails (missing types) | Maintenance root yarn install / yarn tsc, then cd package yarn build |
| Patch wrong version | Use yarn why version, not RHDH meta-version |
| Skill not in Cursor | .rulesync/skills/ may not sync to .cursor/—see Rulesync / Cursor |