
Description
Automate the full PR workflow for rhdh-plugins and community-plugins monorepos: detect workspace, build, generate changeset, commit, push, and create the GitHub PR. Auto-detects which repo you're in. Supports --a auto-approve mode to skip all approval gates. Accepts an optional Jira key/URL or GitHub issue URL to link the PR to a tracked issue (adds comments, transitions, and auto-close links). Use when asked to "raise a PR", "create a PR", "submit a PR", "open a PR", "push my changes", "make a PR for this plugin", or "PR workflow". Also use when user says "raise pr", "/pr", or mentions creating a pull request in rhdh-plugins or community-plugins.
SKILL.md
<essential_principles>
</essential_principles>
Prerequisites
ghCLI — GitHub CLI must be installed and authenticated (gh auth statusshould show logged in). Install: https://cli.github.com/- Jira MCP — The Atlassian Rovo MCP server must be configured in your agent environment for Jira comment updates. Setup guide: https://support.atlassian.com/atlassian-rovo-mcp-server/docs/getting-started-with-the-atlassian-remote-mcp-server/
- If not configured, the skill will skip Jira updates and log a warning.
- Working checkout of
rhdh-plugins(orcommunity-plugins) yarnavailable on PATH
Mode: check for --a flag
Check if the user invoked this skill with --a (auto-approve mode).
--apresent: All approval gates (Steps 4, 8, and 9) are skipped — proceed automatically.--aabsent (default): Approval gates require user confirmation before proceeding.
Step 1 — Detect repo profile
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).
If no profile matches, ask the user which repo they are targeting before proceeding.
Store the profile values for use in Steps 5, 6, and 10.
Step 1.5 — Resolve issue context
Determine whether the PR is linked to a Jira issue, GitHub issue, or neither.
Source 1: Caller context (highest priority)
If another skill (e.g., bug-fix) provides caller context with issue_source, use it directly:
issue_source=jira: Usejira_key,jira_url,jira_summaryfrom caller context. Skip detection.issue_source=github: Usegithub_issue_number,github_issue_url,github_issue_repo,github_issue_titlefrom caller context. Skip detection.
Source 2: User argument
If no caller context, parse the user's argument:
Jira patterns (read references/jira-input.md):
- If input matches
(RHIDP|RHDHBUGS|RHDHPLAN|RHDHSUPP)-\d+anywhere in the string, extract that as the key. - If input contains
atlassian.net/browse/, extract everything after/browse/as the key. - Construct:
jira_url = https://redhat.atlassian.net/browse/<jira_key> - Set
issue_source = jira.
GitHub patterns (read bug-fix/references/github-input.md):
- If input contains
github.com/.../issues/<N>, extract owner/repo and number. - If input matches
#\d+, resolve repo fromgit remote -v. - Construct:
github_issue_url = https://github.com/<owner>/<repo>/issues/<N> - Set
issue_source = github.
Source 3: Branch name
If no argument matched, check the current branch name:
- Jira key pattern:
fix/RHDHBUGS-1934-keyboard-nav→ extractRHDHBUGS-1934, setissue_source = jira. - GitHub issue pattern:
fix/607-report-portal-crash→ extract#607only if combined with repo context fromgit remote -v, setissue_source = github.
Source 4: Prompt
Ask: "Issue key, URL, or #number? (enter to skip)".
Fetch summary (if not provided by caller)
- Jira: Use the Jira REST API per
references/jira-input.mdto fetch the issue summary. If auth is not configured or the fetch fails, storejira_summary = nulland continue. - GitHub:
gh issue view <N> --repo <repo> --json title -q .title. If fetch fails, storegithub_issue_title = nulland continue.
Store
Set issue_source = jira, github, or null. If null, all issue-specific behavior in later steps is skipped.
Step 2 — Detect workspace(s) from staged changes
- Run
git diff --cached --name-onlyto list all staged files. - If no files are staged, stop: "No staged changes found. Stage your changes with
git addbefore running this command." - Extract workspace names from staged file paths. The workspace is the second path segment (e.g.,
workspaces/bulk-import/plugins/foo/src/index.ts→ workspacebulk-import, pathworkspaces/bulk-import). - 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. - Store the workspace names and paths for later steps.
Step 3 — Capture baseline snapshot
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.
Step 4 — Create branch (only if on main) APPROVAL GATE
- Run
git branch --show-current. - If on
main: a. Analyze the staged diff (git diff --cached) to understand the changes. b. Generate a branch name:- If
jira_keyis set:fix/<workspace>-<JIRA-KEY>-<short-slug>(e.g.,fix/adoption-insights-RHDHBUGS-1934-keyboard-nav-dropdown). This matches the existing repo convention and enables auto-linking in the Jira Development panel. - If no Jira key:
feat/<workspace>-<short-description>(usefix/for bug fixes). For multiple workspaces, use a general description. c. If NOT auto-approve: present the proposed branch name and a one-line summary. Wait for approval. If auto-approve: proceed immediately. d. Rungit checkout -b <branch-name>.
- If
- If NOT on
main: skip branch creation. Inform the user: "Already on branch<name>, skipping branch creation."
Step 5 — Build and validate each workspace
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.
5.0 — Pre-build cleanup
Remove stale dist/ directories that may contain root-owned files from previous Docker or sudo builds:
rm -rf plugins/*/dist packages/*/dist
If EACCES permission error occurs: Set a flag SKIP_BUILD_ALL=true. Log a warning with the permanent fix:
echo "⚠️ Skipping yarn build:all — dist/ has root-owned files. Run 'sudo chown -R $(whoami) .' to fix ownership, then re-run."
Never use sudo in the skill itself — just tell the user how to fix it.
5.1–5.6 — Build pipeline
Run in order:
yarn— install dependenciesyarn prettier:fix— format codeyarn tsc:full— full TypeScript type checkyarn build:all— build all packages. Skip this step ifSKIP_BUILD_ALL=true(from 5.0 fallback).yarn test --watchAll=false— run tests (disable Jest watch mode)yarn build:api-reports:only— generate/update API reports (depends ontsc:full, always runs)
Step 6 — Generate changeset per workspace
For each workspace from Step 2, generate a changeset programmatically. Use the npm scope from the detected repo profile (Step 1).
- From the staged diff (
git diff --cached), determine:- Which plugins under this workspace are affected (look at
plugins/*only — ignorepackages/*). - Within each plugin, only include it if changes touch published paths (
src/, rootindex.ts,config.d.ts,package.json). Skip plugins with changes only indev/,tests/,__fixtures__/, or stories. - Read each affected plugin's
package.jsonfor its npm package name. - Infer the semver bump:
patchfor fixes,minorfor features,majorfor breaking changes. - If no plugins have published-source changes, skip changeset generation for this workspace.
- Which plugins under this workspace are affected (look at
- Generate a short summary (1-2 sentences).
- Generate a random changeset ID:
<adjective>-<noun>-<verb>pattern, lowercase, 5-8 chars per word. Each workspace gets a unique ID. - Write the changeset file to
<workspace>/.changeset/<random-id>.md:
---
'<package-name>': <bump-type>
---
<summary>
If multiple packages are affected, list each on its own YAML line.
Do NOT run yarn changeset interactively. Create files programmatically.
Step 7 — Identify build-generated files
- Run
git status --porcelainfor the current snapshot. - Compare against the baseline snapshot from Step 3.
- Files only in the current snapshot are build-generated (created by Step 5 builds or Step 6 changesets).
- Files already in the baseline are pre-existing — exclude them from staging.
Step 8 — Stage build-generated files APPROVAL GATE
- Present the filtered list of build-generated files from Step 7.
- If NOT auto-approve: ask the user for approval before staging. If auto-approve: stage all automatically.
- Run
git addfor each approved file.
Step 9 — Commit APPROVAL GATE
- Run
git diff --cached --statto review all staged changes. - Generate a commit message in conventional commit format:
<type>(<workspace>): <short description>(e.g.,feat(bulk-import): add batch repository import support). - If
issue_sourceis set, append aFixes:trailer in the commit body — but only if the issue type is allowed for this repo profile:- rhdh-plugins: Both Jira and GitHub issue URLs are allowed.
- community-plugins: Only GitHub issue URLs are allowed. If
issue_source = jira, do NOT add aFixes:trailer (Jira info must never appear in community-plugins git history).
Examples:- rhdh-plugins + Jira:
Fixes: https://redhat.atlassian.net/browse/RHDHBUGS-1934 - rhdh-plugins + GitHub:
Fixes: https://github.com/redhat-developer/rhdh-plugins/issues/607 - community-plugins + GitHub:
Fixes: https://github.com/backstage/community-plugins/issues/3574 - community-plugins + Jira: no trailer (omit entirely)
fix(adoption-insights): enable keyboard navigation in header date-range dropdown
Fixes: <issue_url>
- If NOT auto-approve: present the commit message and staged file summary. Wait for approval. If auto-approve: commit immediately.
- Commit with the
-sflag (Signed-off-by):
git commit -s -m "<subject>" -m "Fixes: <issue_url>"
Where <issue_url> is jira_url or github_issue_url depending on issue_source. If issue_source is null, or if the profile is community-plugins and issue_source is jira, omit the second -m flag.
Step 10 — Push and create PR
- Push the branch:
git push -u origin HEAD
- Upload recording GIFs to dedicated
screenrecordingsbranch HARD GATE whenrecordingsis provided:
Skip this sub-step ONLY ifrecordingscaller context is NOT provided. WhenrecordingsIS provided, this sub-step is MANDATORY — do NOT skip, defer, or substitute with placeholder URLs.
GIFs are uploaded to a dedicatedscreenrecordingsbranch on the user's fork — NOT the feature branch. This keeps the GIFs out of the PR diff and prevents them from landing on upstreammainwhen the PR merges.
a. Verify both local GIF files exist before proceeding:ls -la <recordings.before> <recordings.after>
If either file is missing, STOP and inform the user.
b. Determine the fork owner and repo name from theoriginremote URL (e.g.,its-mitesh-kumar/rhdh-plugins). c. Build the issue-specific upload path to avoid filename collisions across bug fixes:- If
issue_source = jira:ISSUE_ID = <jira_key>(e.g.,RHDHBUGS-2911) - If
issue_source = github:ISSUE_ID = <github_issue_number>(e.g.,9834) - If no issue context:
ISSUE_ID = $(date +%Y%m%d-%H%M%S)
Upload path:screenrecordings/<workspace>-<ISSUE_ID>/before-fix.gifand.../after-fix.gif.
d. Ensure thescreenrecordingsbranch exists on the fork. Check and create if needed:TOKEN=$(gh auth token) # Check if branch exists HTTP_STATUS=$(curl -s -o /dev/null -w "%{http_code}" \ -H "Authorization: token $TOKEN" \ "https://api.github.com/repos/<fork-owner>/<repo-name>/git/ref/heads/screenrecordings") if [ "$HTTP_STATUS" != "200" ]; then # Get the SHA of the default branch HEAD DEFAULT_SHA=$(curl -s -H "Authorization: token $TOKEN" \ "https://api.github.com/repos/<fork-owner>/<repo-name>/git/ref/heads/main" | \ python3 -c "import sys,json; print(json.load(sys.stdin)['object']['sha'])") # Create the branch curl -s -X POST \ -H "Authorization: token $TOKEN" \ -H "Accept: application/vnd.github+json" \ -d '{"ref":"refs/heads/screenrecordings","sha":"'"$DEFAULT_SHA"'"}' \ "https://api.github.com/repos/<fork-owner>/<repo-name>/git/refs" fi
e. For each GIF file (recordings.beforeandrecordings.after), upload to thescreenrecordingsbranch via the GitHub Contents API:GIF_B64=$(base64 -i <local-gif-path>) RESPONSE=$(curl -s -X PUT \ -H "Authorization: token $TOKEN" \ -H "Accept: application/vnd.github+json" \ -d '{"message":"docs: add <before|after>-fix recording for <workspace>-<ISSUE_ID>","content":"'"$GIF_B64"'","branch":"screenrecordings"}' \ "https://api.github.com/repos/<fork-owner>/<repo-name>/contents/screenrecordings/<workspace>-<ISSUE_ID>/<before|after>-fix.gif") echo "$RESPONSE" | python3 -c "import sys,json; d=json.load(sys.stdin); url=d.get('content',{}).get('download_url',''); print('download_url:', url); exit(0 if url.startswith('https://raw.githubusercontent.com') else 1)"
f. Extract thedownload_urlfrom the JSON response — this is theraw.githubusercontent.comURL. Verify that the URL starts withhttps://raw.githubusercontent.com/— if it does not, the upload failed. g. Store both URLs:before_gif_url,after_gif_url. h. Echo a verification banner:echo "✅ GIF upload verified: before=$before_gif_url after=$after_gif_url"
If upload fails: Retry once. If the retry also fails, log a warning and inform the user to manually drag GIFs into the PR description on GitHub. Use placeholder text_(Recording upload failed — drag GIF manually)_in the PR body instead of a broken image link. NEVER fabricate a URL that looks real but does not resolve. - If
- Generate a PR title from the commit subject line.
- Build the PR body from the detected repo profile template (Step 1). The body has conditional sections:
## Fixed— repo-dependent:- rhdh-plugins: include if
issue_sourceis set. Jira:- [<JIRA-KEY>](<jira_url>) — <jira_summary>. GitHub:- Fixes <github_issue_url>. - community-plugins: include ONLY if
issue_source = github. Use- Fixes <github_issue_url>(triggers auto-close). NEVER include Jira info — omit## Fixedentirely whenissue_source = jira.
- rhdh-plugins: include if
## UI before changes/## UI after changes— include only ifrecordingsare provided in caller context. Use theraw.githubusercontent.comURLs from sub-step 2 in the markdown:/. CRITICAL: Both URLs MUST have been obtained from the GitHub Contents API response in sub-step 2. NEVER construct, guess, or fabricate these URLs. If sub-step 2 failed and you have no valid URLs, use the placeholder text from the failure path instead of a broken image link.pr_description_extra— if provided by caller context (e.g., root cause analysis frombug-fix), insert it after the generated description paragraph.## Test Plan— include only iftest_planis provided in caller context. Insert the markdown checklist as-is.## Checklist— always present.## Note— include wheneverissue_sourceis present in caller context (indicatingbug-fixinvokedraise-pr). Contains the skill attribution disclaimer. Omit for standaloneraise-prinvocations.
- Create the PR using
gh pr createwith the repo-appropriate template. Use the upstream repo value for--repoandmainfor--base. Pass the body via HEREDOC:
gh pr create --repo <upstream-repo> --base main --title "<title>" --body "$(cat <<'EOF'
<assembled PR body>
EOF
)"
- Capture and store the PR URL for Step 11.
- Display the PR URL.
Step 11 — Post-PR issue updates
Skip this step entirely if issue_source is null.
If issue_source = jira
- Comment on the Jira issue documenting the PR submission:
Use the Jira MCP `add_jira_comment` tool: issueKey: "<jira_key>" body: "PR submitted: <PR_URL>" - Transition the issue status to "Review" (if ACLI is available):
acli jira workitem transition --key "<jira_key>" --status "Review" --yes
Query available transitions first:acli jira workitem getTransitions --key "<jira_key>". If "Review" is not available, skip the transition and log a warning. - Add web link — add the PR URL as a remote link on the Jira issue (if REST auth is available):
POST /rest/api/3/issue/<jira_key>/remotelink { "object": { "url": "<PR_URL>", "title": "GitHub PR: <PR_title>" } }
Seereferences/jira-input.mdfor REST API patterns.
If any Jira call fails: Log a warning and continue — the PR has been created successfully:
echo "⚠️ Could not update <jira_key>. Add manually: <PR_URL>"
If issue_source = github
- Comment on the GitHub issue:
gh issue comment <github_issue_number> --repo <github_issue_repo> --body "Fix submitted: <PR_URL>" - Auto-close — no explicit action needed. The
Fixes <github_issue_url>in the PR body (Step 10) causes GitHub to automatically close the issue when the PR merges.
If the comment fails: Log a warning and continue:
echo "⚠️ Could not comment on #<github_issue_number>. Add manually: <PR_URL>"
Gotchas
- Fork workflows: The user may have
originpointing to their fork andupstreamto the canonical repo. Detection checks all remotes, not justorigin. The--repoflag ongh pr createtargets the canonical upstream regardless of which remoteoriginpoints to. - 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.
- 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.
Caller Context (optional)
When another skill chains into raise-pr, it may provide a caller context with pre-resolved values. If present, these override the defaults — skip detection for any field that is already provided.
| Field | Type | Used in | Description |
|---|---|---|---|
issue_source | string | Steps 1.5, 9, 10, 11 | "jira" or "github" — determines which issue-specific logic to follow |
jira_key | string | Steps 1.5, 4, 9, 10, 11 | Pre-resolved Jira issue key (skip Step 1.5 detection). Jira only. |
jira_url | string | Steps 9, 10, 11 | Full Jira browse URL. Jira only. |
jira_summary | string | Step 10 | Issue summary for the PR body ## Fixed section. Jira only. |
github_issue_number | number | Steps 1.5, 10, 11 | GitHub issue number. GitHub only. |
github_issue_url | string | Steps 9, 10, 11 | Full GitHub issue URL (e.g., https://github.com/redhat-developer/rhdh-plugins/issues/607). GitHub only. |
github_issue_repo | string | Steps 10, 11 | owner/repo (e.g., redhat-developer/rhdh-plugins). GitHub only. |
github_issue_title | string | Step 10 | Issue title for the PR body ## Fixed section. GitHub only. |
recordings | object | Step 10 | { before: "<local-gif-path>", after: "<local-gif-path>" } — local GIF paths; raise-pr uploads them to the branch via GitHub Contents API and uses the resulting raw.githubusercontent.com URLs in the PR body. null in no-e2e mode. |
pr_description_extra | string | Step 10 | Extra text inserted after the description (e.g., root cause analysis) |
test_plan | string | Step 10 | Markdown checklist for the ## Test Plan section (e.g., "- [ ] Open menu\n- [ ] Verify scrollbar on hover") |
Skills that chain into raise-pr:
bug-fix— providesissue_sourceplus the relevant issue fields, optionallyrecordings(full-e2e mode only),pr_description_extra, andtest_plan.
<reference_index>
Reference Index
| Reference | Load when... |
|---|---|
references/repo-profiles.md | Always — at the start of every invocation (Step 1) |
references/jira-input.md | When resolving Jira context (Step 1.5, issue_source = jira) |
bug-fix/references/github-input.md | When resolving GitHub issue context (Step 1.5, issue_source = github) |
</reference_index>
More skills from the rhdh-skill repository
View all 24 skillsagent-ready
assess repository readiness for AI agents
Jul 16AgentsCode AnalysisEngineeringbackstage-upgrade
upgrade Backstage dependencies
Jul 16EngineeringMaintenanceMigrationbase-images-and-rpms
update base images and lockfiles
Jul 16AutomationConfigurationContainersDeploymentbug-fix
diagnose and fix plugin bugs
Jul 29DebuggingQATestingcompute-plugin-package-overlay-cve-list
generate CVE management reports
Jul 29ComplianceEngineeringReportingSecuritycreate-plugin
scaffold and package RHDH dynamic plugins
Jul 16DeploymentPlugin Development
More from Red Hat Developer
View publishercursor-mcp-auth
authenticate Atlassian MCP for Jira
rhdh-skill
Jul 29AuthJiraMCPOAuthkonflux-release-data-rpa
update release tags in konflux-release-data
rhdh-skill
Jul 16AutomationDeploymentGitLabkonflux-tekton-updates
update Konflux Tekton task digests
rhdh-skill
Jul 16AutomationCI/CDDeploymentEngineeringlifecycle
check Red Hat product lifecycle status
rhdh-skill
Jul 16ComplianceMaintenanceOperationsnfs-migration
migrate plugins to New Frontend System
rhdh-skill
Jul 16EngineeringFrontendMigrationoverlay
manage RHDH plugin export overlays
rhdh-skill
Jul 16AutomationCode ReviewDeploymentEngineering