|
| 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> |
0 commit comments