DevOps PR Creation

SkillCloud & infra

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.

Available today. Use it from your connected AI after setup.

Connect ahel once, and every AI you use reads what you have installed.

Then ask your AI: use the DevOps PR Creation skill

What this skill tells your AI

The instructions your AI receives, as published by tetherto/qvac in .agents/skills/qv-devops-pr-create/SKILL.md and read by ahel’s review.

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

  1. Confirm base and current branch — note whether the base is main (default) or a release-* branch (uncommon for DevOps; treat as user-provided).

  2. Collect commits/diff from <base>...origin/<branch>.

  3. Infer ticket, prefix, and tag from changes (see Inference Strategy).

  4. Detect trigger sections (action pinning / permissions / plan-dry-run / breaking) and only ask the user for input when inference confidence is low.

  5. Generate title: TICKET prefix[tag]?: subject.

  6. Fill template sections based on changes and detected triggers.

  7. Validate tag requirements ([bc]).

  8. 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).

  9. 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   # macOS
    xclip -selection clipboard < /tmp/pr-body.md   # Linux
    wl-copy < /tmp/pr-body.md   # Wayland
    
  10. 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.

TriggerDetection signalRequired section
Third-party action added / bumped / repinnedgit 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 / removedgit diff shows ^[+-].*permissions: or `^[+-]\s+(contentspull-requests
State-changing opAny 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

  • PR title format: see the Validation regex below — ^([A-Z]+-\d+ )?(infra|feat|fix|chore|doc|test)(\[(bc|notask|skiplog)\])?: \S.+$
  • PR body template: .github/PULL_REQUEST_TEMPLATE/devops.md
  • GitHub and CI guidance (including conventions that drive "How was it tested?" content): .github/AGENTS.md

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:

  1. which gh — confirm CLI is installed
  2. git remote -v — identify whether origin is the upstream (tetherto/qvac) or a fork
  3. Ask the user: "Create PR now with gh CLI?" [Yes / No / Preview first]
  4. If yes, ensure changes are committed and pushed first
  5. 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)"
  1. 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:

  • Title matches the regex above
  • "What problem" describes operator/user impact, not implementation
  • "How it solves" is high-level approach, not line-by-line
  • "How was it tested?" lists concrete validation steps (actionlint clean, workflow_dispatch test run, terraform plan output, kubectl diff output, etc.)
  • Untriggered template sections are deleted
  • [bc] body has BEFORE/AFTER YAML blocks
  • Action-pinning trigger → action-pinning section present
  • Permissions trigger → permissions section present
  • State-changing trigger → plan/dry-run section present

References

Signals

GitHub stars
601
Forks
111
Last commit
Sep 2026
Advanced
Catalog kind
skill
Gateway key
qv-devops-pr-create
Source
github.com/tetherto/qvac