| name | qv-devops-pr-create |
| description | Generate PR titles and descriptions for DevOps surfaces (CI/CD, composite actions, automation scripts, IaC) following the devops.md PR template and commit/PR format rule. Use when creating a DevOps PR or invoking /qv-devops-pr-create. |
| disable-model-invocation | true |
DevOps PR Creation
Generate PR titles and descriptions for DevOps changes (CI/CD workflows, composite actions, repo-wide automation scripts, IaC), following the DevOps pod's format rule and PR template.
When to use this skill
Applies to PRs whose changes are dominated by paths in .github/teams/devops.json's ownedPaths: .github/workflows/, .github/actions/, .github/scripts/, scripts/. Also applies to repo-level configuration changes (.github/CODEOWNERS, .github/dependabot.yml, top-level Dockerfiles, IaC under top-level terraform/, ansible/, k8s/).
Use when:
- Creating a PR for any DevOps change
- User asks to generate a DevOps PR description
- User invokes
/qv-devops-pr-create
If the touched paths are dominated by a non-DevOps pod (e.g., packages/sdk/**), use that pod's *-pr-create skill instead. If a PR mixes DevOps + package changes, prefer the package's pod skill and call out the cross-pod touches in the PR body.
Prerequisites
gh CLI installed and authenticated (gh auth status)
- Branch is pushed to a fork (or the upstream when the user has write access to
tetherto/qvac)
- Local branch tracks the remote being PR'd from
Workflow
-
Confirm base and current branch — note whether the base is main (default) or a release-* branch (uncommon for DevOps; treat as user-provided).
-
Collect commits/diff from <base>...origin/<branch>.
-
Infer ticket, prefix, and tag from changes (see Inference Strategy).
-
Detect trigger sections (action pinning / permissions / plan-dry-run / breaking) and only ask the user for input when inference confidence is low.
-
Generate title: TICKET prefix[tag]?: subject.
-
Fill template sections based on changes and detected triggers.
-
Validate tag requirements ([bc]).
-
Save the assembled PR body to /tmp/pr-body.md so subsequent steps and any gh pr create invocation can read it back without re-rendering. Print the body in chat for inspection AND keep the file canonical (the gh-CLI step below reads from it).
-
Print the paste-ready commands alongside the in-chat preview — both for direct paste into the GitHub PR-create form and for clipboard tools:
pbcopy < /tmp/pr-body.md
xclip -selection clipboard < /tmp/pr-body.md
wl-copy < /tmp/pr-body.md
-
Optionally create the PR via gh (see "gh CLI Integration" below).
Inference Strategy
Infer first, ask only if uncertain.
Ticket number:
- Extract from branch name pattern:
QVAC-\d+, SDK-\d+, etc.
- Extract from commit messages if referenced.
- ASK only if no ticket found (offer
[notask] as the alternative).
Prefix (infra / feat / fix / chore / doc / test):
- Extract from branch name prefix when present (e.g.
infra/, fix/, chore/).
- Use majority prefix from existing commit messages.
- If no conventional commits, infer from diff:
.github/workflows/**, .github/actions/**, .github/scripts/**, scripts/**, IaC files, Dockerfiles, runner config → infra
- New skill / new workflow type / new composite action →
feat
- Bug-related changes (commit messages mention "fix", "broken", "regression"; reverts) →
fix
- Only
.md / docs files → doc
- Only test files (
.github/actions/*-test/**, *.test.*, tests/**) → test
- Pure dependency bumps / deprecations / lockfile churn →
chore
- ASK only on mixed signals.
Tag ([bc] / [notask] / [skiplog] — not combinable):
[bc] (breaking change) when the diff:
- Renames a job whose name is referenced by a branch protection ruleset (status check rename)
- Changes a reusable workflow's
inputs: / outputs: shape (workflow_call signature)
- Changes a composite action's
inputs: / outputs: shape (.github/actions/<name>/action.yml)
- Changes a
workflow_call secrets: or permissions: contract
- Removes a slash command / public surface from a skill that other teams consume
[notask] (PRs only): when no ticket — minor automation hygiene. Ask the user before applying.
[skiplog]: only when the user explicitly asks (this repo uses [skiplog] to opt out of changelog generation; not the default for DevOps).
ASK if [bc] is ambiguous.
Trigger detection (drives required template sections)
Walk the diff before assembling the body. For each trigger detected, the corresponding section is REQUIRED in the PR body.
| Trigger | Detection signal | Required section |
|---|
| Third-party action added / bumped / repinned | git diff shows a uses: <vendor>/<action>@<sha> change in any .github/workflows/** or .github/actions/**/action.yml | "🔐 Action pinning" with before/after SHA + version |
Top-level or per-job permissions: block added / modified / removed | git diff shows ^[+-].*permissions: or `^[+-]\s+(contents | pull-requests |
| State-changing op | Any of: terraform/** *.tf, ansible/** *.yml, k8s/** *.yaml, gh ruleset edit invocations, branch-protection patches | "📋 Plan / dry-run output" — paste the plan/diff |
| Breaking change | [bc] tag set per Inference Strategy | "💥 Breaking changes" with BEFORE/AFTER YAML blocks |
Sections that are NOT triggered MUST be deleted (per the template's "Delete this section if not applicable" markers).
Format References
Fill the template based on the diff analysis. Delete sections that don't apply.
Output Format
ALWAYS output the PR in this copy-ready format, even when making corrections:
## PR Title
```
TICKET prefix[tag]?: subject
```
## PR Body
```markdown
## 🎯 What problem does this PR solve?
...
```
Validation
No pr-validation-devops.yml workflow exists yet (the SDK-pod validator is paths-scoped to packages/<pkg>/). This skill MUST validate the title client-side before pushing or invoking gh pr create. Refuse and ask for correction if any of these fail:
- Title regex:
^([A-Z]+-\d+ )?(infra|feat|fix|chore|doc|test)(\[(bc|notask|skiplog)\])?: \S.+$
- Lowercase prefix and lowercase subject (sentence case allowed; the first word may be capitalized for proper nouns)
- A ticket prefix (
QVAC-\d+) is present unless [notask] is used
- For
[bc]: body contains a "💥 Breaking changes" section with BEFORE/AFTER fenced blocks
- For an action-pinning trigger: body contains a "🔐 Action pinning" section
- For a permissions trigger: body contains a "🛡️ Permissions changes" section
- For an IaC/state-changing trigger: body contains a "📋 Plan / dry-run output" section
gh CLI Integration
After generating the PR description, check for gh and offer to create the PR:
which gh — confirm CLI is installed
git remote -v — identify whether origin is the upstream (tetherto/qvac) or a fork
- Ask the user: "Create PR now with gh CLI?" [Yes / No / Preview first]
- If yes, ensure changes are committed and pushed first
- Create PR with explicit base/head; for fork workflows, pass
--repo, --base, --head:
gh pr create \
--repo tetherto/qvac \
--base main \
--head <fork-owner>:<branch> \
--title "TICKET infra: subject" \
--body "$(cat /tmp/pr-body.md)"
For direct-push workflows (the user has write to tetherto/qvac):
gh pr create \
--base main \
--title "TICKET infra: subject" \
--body "$(cat /tmp/pr-body.md)"
- Print the resulting PR URL as a clickable hyperlink.
Never run gh pr create --web for this skill — --web does not actually create the PR; it only opens the browser. The body we generated would be lost.
Quality Checklist
Before outputting, verify:
References