Skip to content

Commit 7ffc6a9

Browse files
feat: add raise-pr skill for automated PR workflows (v0.7.0)
Signed-off-by: its-mitesh-kumar <itsmiteshkumar98@gmail.com>
1 parent 1540a7d commit 7ffc6a9

7 files changed

Lines changed: 279 additions & 5 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
},
66
"metadata": {
77
"description": "Orchestrator skill for RHDH plugin development - onboard, update, and maintain plugins in the Extensions Catalog",
8-
"version": "0.6.1"
8+
"version": "0.7.0"
99
},
1010
"plugins": [
1111
{
1212
"name": "rhdh",
1313
"source": "./",
1414
"description": "Skills for RHDH plugin lifecycle management",
15-
"version": "0.6.1",
15+
"version": "0.7.0",
1616
"strict": true
1717
}
1818
]

.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "rhdh",
33
"description": "All-in-one toolkit for Red Hat Developer Hub (RHDH). Covers plugin development, overlay management, environment setup, version compatibility, CI/CD, and RHDH ecosystem navigation.",
4-
"version": "0.6.1",
4+
"version": "0.7.0",
55
"author": {
66
"name": "RHDH Store Manager"
77
},

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,12 @@ Track work across the four RHDH Jira projects.
9494
- **[to-issue](./skills/rhdh-jira/references/to-issue.md)** — Create a Story, Task, Bug, or Spike with automatic type inference. Grills on implementation details and story points.
9595
- **[update-jira-status](./skills/rhdh-jira/references/update-jira-status.md)** — Update an issue with session progress. Detects the related issue, adds a status comment, proposes transitions, and checks upward cascade to parent Epic/Feature.
9696

97+
### PR Workflow
98+
99+
Automate the full PR lifecycle — build, changeset, commit, push, and create — for plugin monorepos.
100+
101+
- **[raise-pr](./skills/raise-pr/SKILL.md)** — Full PR workflow for `rhdh-plugins` and `community-plugins`: detect workspace from staged changes, run build/validation, generate changesets, commit with sign-off, push, and create the GitHub PR. Auto-detects which repo you're in. Supports `--a` auto-approve mode to skip all approval gates.
102+
97103
### PR Review
98104

99105
- **[rhdh-pr-review](./skills/rhdh-pr-review/SKILL.md)** — PR code review with inline comments (GitHub, GitLab planned) and live cluster testing for rhdh-operator PRs. Layered architecture: fetch → analyze → post.

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[project]
22
name = "rhdh-skill"
3-
version = "0.6.1"
3+
version = "0.7.0"
44
description = "Claude Code skill for RHDH plugin development"
55
readme = "README.md"
66
license = "Apache-2.0"

skills/raise-pr/SKILL.md

Lines changed: 201 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,201 @@
1+
---
2+
name: raise-pr
3+
description: >
4+
Automate the full PR workflow for rhdh-plugins and community-plugins monorepos:
5+
detect workspace, build, generate changeset, commit, push, and create the GitHub PR.
6+
Auto-detects which repo you're in. Supports --a auto-approve mode to skip all
7+
approval gates. Use when asked to "raise a PR", "create a PR", "submit a PR",
8+
"open a PR", "push my changes", "make a PR for this plugin", or "PR workflow".
9+
Also use when user says "raise pr", "/pr", or mentions creating a pull request
10+
in rhdh-plugins or community-plugins.
11+
---
12+
13+
<essential_principles>
14+
15+
<principle name="scoped_dist_cleanup">
16+
Pre-build cleanup uses `rm -rf plugins/*/dist packages/*/dist` scoped to the workspace directory. If permission errors occur, escalate to `sudo`. Never use `find -name dist` or any broad recursive search — that deletes `dist/` inside `node_modules` and breaks everything.
17+
</principle>
18+
19+
<principle name="changesets_skip_packages">
20+
Only plugins under `plugins/*` with published-source changes need changesets. Always ignore `packages/*` — those are private app/backend packages that are never published. Within each plugin, only include it if changes touch `src/` or other published paths (root `index.ts`, `config.d.ts`, `package.json`). Changes only in `dev/`, `tests/`, `__fixtures__/`, or storybook stories do not require a changeset.
21+
</principle>
22+
23+
<principle name="baseline_diffing">
24+
Capture `git status --porcelain` before builds as the baseline. After builds, only stage files that are new relative to that baseline. Pre-existing dirty files (local config overrides, dev fixtures) must never be staged.
25+
</principle>
26+
27+
</essential_principles>
28+
29+
## Mode: check for `--a` flag
30+
31+
Check if the user invoked this skill with `--a` (auto-approve mode).
32+
33+
- **`--a` present:** All approval gates (Steps 4, 8, and 9) are skipped — proceed automatically.
34+
- **`--a` absent (default):** Approval gates require user confirmation before proceeding.
35+
36+
---
37+
38+
## Step 1 — Detect repo profile
39+
40+
Read `references/repo-profiles.md` and follow the detection logic. Run `git remote -v`, match the remote URLs, and load the matching profile (upstream repo, npm scope, PR body template, changeset docs link).
41+
42+
If no profile matches, ask the user which repo they are targeting before proceeding.
43+
44+
Store the profile values for use in Steps 5, 6, and 10.
45+
46+
---
47+
48+
## Step 2 — Detect workspace(s) from staged changes
49+
50+
1. Run `git diff --cached --name-only` to list all staged files.
51+
2. If no files are staged, stop: "No staged changes found. Stage your changes with `git add` before running this command."
52+
3. Extract workspace names from staged file paths. The workspace is the second path segment (e.g., `workspaces/bulk-import/plugins/foo/src/index.ts` → workspace `bulk-import`, path `workspaces/bulk-import`).
53+
4. If staged files span **multiple** workspaces, inform the user: "Changes detected in **N** workspace(s): `<list>`. Proceed? (Yes/No)". Wait for confirmation. If declined, stop.
54+
5. Store the workspace names and paths for later steps.
55+
56+
---
57+
58+
## Step 3 — Capture baseline snapshot
59+
60+
Run `git status --porcelain` and save the full output as the **baseline snapshot**. This captures all files that were already dirty or untracked before any build commands run. Used in Step 7 to filter out pre-existing changes.
61+
62+
---
63+
64+
## Step 4 — Create branch (only if on `main`) [APPROVAL GATE]
65+
66+
1. Run `git branch --show-current`.
67+
2. **If on `main`:**
68+
a. Analyze the staged diff (`git diff --cached`) to understand the changes.
69+
b. Generate a branch name: `feat/<workspace>-<short-description>` (use `fix/` for bug fixes). For multiple workspaces, use a general description.
70+
c. **If NOT auto-approve:** present the proposed branch name and a one-line summary. Wait for approval. **If auto-approve:** proceed immediately.
71+
d. Run `git checkout -b <branch-name>`.
72+
3. **If NOT on `main`:** skip branch creation. Inform the user: "Already on branch `<name>`, skipping branch creation."
73+
74+
---
75+
76+
## Step 5 — Build and validate each workspace
77+
78+
For **each** workspace from Step 2, run the following commands **sequentially** inside the workspace directory (e.g., `workspaces/bulk-import`). If any command fails, **stop immediately** and report the error with the failing command, workspace, and output.
79+
80+
### 5.0 — Pre-build cleanup
81+
82+
Remove stale `dist/` directories that may contain root-owned files from previous Docker or sudo builds:
83+
84+
```
85+
rm -rf plugins/*/dist packages/*/dist
86+
```
87+
88+
If this fails with a permission error (`EACCES`), escalate to:
89+
90+
```
91+
sudo rm -rf plugins/*/dist packages/*/dist
92+
```
93+
94+
### 5.1–5.6 — Build pipeline
95+
96+
Run in order:
97+
98+
1. `yarn` — install dependencies
99+
2. `yarn prettier:fix` — format code
100+
3. `yarn tsc:full` — full TypeScript type check
101+
4. `yarn build:all` — build all packages
102+
5. `yarn test --watchAll=false` — run tests (disable Jest watch mode)
103+
6. `yarn build:api-reports:only` — generate/update API reports
104+
105+
---
106+
107+
## Step 6 — Generate changeset per workspace
108+
109+
For **each** workspace from Step 2, generate a changeset programmatically. Use the npm scope from the detected repo profile (Step 1).
110+
111+
1. From the staged diff (`git diff --cached`), determine:
112+
- Which **plugins** under this workspace are affected (look at `plugins/*` only — **ignore `packages/*`**).
113+
- Within each plugin, only include it if changes touch published paths (`src/`, root `index.ts`, `config.d.ts`, `package.json`). Skip plugins with changes only in `dev/`, `tests/`, `__fixtures__/`, or stories.
114+
- Read each affected plugin's `package.json` for its npm package name.
115+
- Infer the semver bump: `patch` for fixes, `minor` for features, `major` for breaking changes.
116+
- **If no plugins have published-source changes, skip changeset generation for this workspace.**
117+
2. Generate a short summary (1-2 sentences).
118+
3. Generate a random changeset ID: `<adjective>-<noun>-<verb>` pattern, lowercase, 5-8 chars per word. Each workspace gets a unique ID.
119+
4. Write the changeset file to `<workspace>/.changeset/<random-id>.md`:
120+
121+
```
122+
---
123+
'<package-name>': <bump-type>
124+
---
125+
126+
<summary>
127+
```
128+
129+
If multiple packages are affected, list each on its own YAML line.
130+
131+
**Do NOT run `yarn changeset` interactively.** Create files programmatically.
132+
133+
---
134+
135+
## Step 7 — Identify build-generated files
136+
137+
1. Run `git status --porcelain` for the **current snapshot**.
138+
2. Compare against the **baseline snapshot** from Step 3.
139+
3. Files only in the current snapshot are build-generated (created by Step 5 builds or Step 6 changesets).
140+
4. Files already in the baseline are pre-existing — exclude them from staging.
141+
142+
---
143+
144+
## Step 8 — Stage build-generated files [APPROVAL GATE]
145+
146+
1. Present the filtered list of build-generated files from Step 7.
147+
2. **If NOT auto-approve:** ask the user for approval before staging. **If auto-approve:** stage all automatically.
148+
3. Run `git add` for each approved file.
149+
150+
---
151+
152+
## Step 9 — Commit [APPROVAL GATE]
153+
154+
1. Run `git diff --cached --stat` to review all staged changes.
155+
2. Generate a commit message in conventional commit format: `<type>(<workspace>): <short description>` (e.g., `feat(bulk-import): add batch repository import support`).
156+
3. **If NOT auto-approve:** present the commit message and staged file summary. Wait for approval. **If auto-approve:** commit immediately.
157+
4. Commit with the **`-s` flag** (Signed-off-by):
158+
159+
```
160+
git commit -s -m "<message>"
161+
```
162+
163+
---
164+
165+
## Step 10 — Push and create PR
166+
167+
1. Push the branch:
168+
169+
```
170+
git push -u origin HEAD
171+
```
172+
173+
2. Generate a PR title from the commit message.
174+
3. Create the PR using `gh pr create` with the repo-appropriate template from the detected profile (Step 1). Use the upstream repo value for `--repo` and `main` for `--base`. Pass the body via HEREDOC:
175+
176+
```
177+
gh pr create --repo <upstream-repo> --base main --title "<title>" --body "$(cat <<'EOF'
178+
<PR body from detected profile — fill in generated description>
179+
EOF
180+
)"
181+
```
182+
183+
4. Display the PR URL as the final output.
184+
185+
---
186+
187+
## Gotchas
188+
189+
- **Fork workflows:** The user may have `origin` pointing to their fork and `upstream` to the canonical repo. Detection checks all remotes, not just `origin`. The `--repo` flag on `gh pr create` targets the canonical upstream regardless of which remote `origin` points to.
190+
- **Multiple workspaces:** Each workspace gets its own build cycle (Step 5) and changeset (Step 6). The commit (Step 9) bundles everything into one commit. If the user prefers separate PRs per workspace, they should stage and run the skill once per workspace.
191+
- **Changeset ID collisions:** Each workspace must get a unique random ID. If generating for multiple workspaces in one run, track used IDs and avoid duplicates.
192+
193+
<reference_index>
194+
195+
## Reference Index
196+
197+
| Reference | Load when... |
198+
|-----------|-------------|
199+
| `references/repo-profiles.md` | Always — at the start of every invocation (Step 1) |
200+
201+
</reference_index>
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
# Repo Profiles
2+
3+
Auto-detect which repository you are in and load the matching profile. Read this file at the start of every `raise-pr` invocation.
4+
5+
## Detection
6+
7+
Run `git remote -v` and inspect all remote URLs (fetch lines). Match against the patterns below. If multiple remotes exist (e.g. `origin` pointing to a fork and `upstream` pointing to the canonical repo), prefer the canonical match.
8+
9+
| URL pattern | Profile |
10+
|-------------|---------|
11+
| Contains `rhdh-plugins` (but NOT `community-plugins`) | **rhdh-plugins** |
12+
| Contains `community-plugins` | **community-plugins** |
13+
| Neither matches | Ask the user: "Which repo are you targeting? (1) rhdh-plugins (2) community-plugins" |
14+
15+
## Profile: rhdh-plugins
16+
17+
| Field | Value |
18+
|-------|-------|
19+
| Upstream repo | `redhat-developer/rhdh-plugins` |
20+
| npm scope | `@red-hat-developer-hub` |
21+
| Changeset `fixed` group | `["@red-hat-developer-hub/*"]` |
22+
| Changeset docs link | `https://github.com/redhat-developer/rhdh-plugins/blob/main/CONTRIBUTING.md#creating-changesets` |
23+
| PR base branch | `main` |
24+
| Commit signing | `-s` (Signed-off-by) |
25+
26+
### PR body template (rhdh-plugins)
27+
28+
```
29+
## Description
30+
<generated description — 2-4 sentences explaining what changed and why>
31+
32+
## Fixed
33+
- <Jira link — ask the user, or leave as TODO>
34+
35+
## Checklist
36+
- [x] A changeset describing the change and affected packages. ([more info](https://github.com/redhat-developer/rhdh-plugins/blob/main/CONTRIBUTING.md#creating-changesets))
37+
- [ ] Added or Updated documentation
38+
- [ ] Tests for new functionality and regression tests for bug fixes
39+
- [ ] Screenshots attached (for UI changes)
40+
```
41+
42+
## Profile: community-plugins
43+
44+
| Field | Value |
45+
|-------|-------|
46+
| Upstream repo | `backstage/community-plugins` |
47+
| npm scope | `@backstage-community` |
48+
| Changeset `fixed` group | `[]` (no fixed versioning) |
49+
| Changeset docs link | `https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#creating-changesets` |
50+
| PR base branch | `main` |
51+
| Commit signing | `-s` (Signed-off-by — DCO required) |
52+
53+
### PR body template (community-plugins)
54+
55+
```
56+
## Hey, I just made a Pull Request!
57+
58+
<generated description — 2-4 sentences explaining what changed and why>
59+
60+
#### Checklist
61+
62+
- [x] A changeset describing the change and affected packages. ([more info](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#creating-changesets))
63+
- [ ] Added or updated documentation
64+
- [ ] Tests for new functionality and regression tests for bug fixes
65+
- [ ] Screenshots attached (for UI changes)
66+
- [x] All your commits have a `Signed-off-by` line in the message. ([more info](https://github.com/backstage/backstage/blob/master/CONTRIBUTING.md#developer-certificate-of-origin))
67+
```

uv.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)