From dc18192b60ff072e3ee5f2faa25a960eeef960aa Mon Sep 17 00:00:00 2001 From: Nico <32375741+nulmete@users.noreply.github.com> Date: Tue, 7 Apr 2026 13:49:12 -0300 Subject: [PATCH] Add cherry-pick skill (#43111) Usage: - `/cherry-pick 43082`: auto-picks the latest RC branch - `/cherry-pick 43082 rc-minor-fleet-v4.84.0`: targets a specific RC branch Sample PR I opened with the skill: https://github.com/fleetdm/fleet/pull/43110 --- .claude/README.md | 4 +- .claude/skills/cherry-pick/SKILL.md | 77 +++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 1 deletion(-) create mode 100644 .claude/skills/cherry-pick/SKILL.md diff --git a/.claude/README.md b/.claude/README.md index 3674d54c8a..a22650212c 100644 --- a/.claude/README.md +++ b/.claude/README.md @@ -167,7 +167,8 @@ Your local settings override project settings, so you can always customize witho │ ├── new-endpoint/ # /new-endpoint │ ├── new-migration/ # /new-migration │ ├── bump-migration/ # /bump-migration -│ └── spec-story/ # /spec-story +│ ├── spec-story/ # /spec-story +│ └── cherry-pick/ # /cherry-pick [RC_BRANCH] ├── agents/ # Specialized AI agents │ ├── go-reviewer.md # Go reviewer (proactive, sonnet) │ ├── frontend-reviewer.md # Frontend reviewer (proactive, sonnet) @@ -196,6 +197,7 @@ Several skills use the `gh` CLI for GitHub operations (PR review, CI diagnosis, | `/bump-migration` | `/bump-migration YYYYMMDDHHMMSS_Name.go` | Bumps a migration's timestamp to current time when it conflicts with a migration already merged to main. Renames files and updates function names in both migration and test files. | | `/spec-story` | `/spec-story 12345` | Breaks down a GitHub story into implementable sub-issues: maps codebase impact, decomposes into atomic tasks per layer (migration/datastore/service/API/frontend), and writes specs with acceptance criteria and a dependency graph. Requires `gh`. | | `/lint` | `/lint` or `/lint go` | Runs the appropriate linters (golangci-lint, eslint, prettier) on recently changed files. Accepts `go`, `frontend`, or a file path to narrow scope. | +| `/cherry-pick` | `/cherry-pick 43082` or `/cherry-pick 43082 rc-minor-fleet-v4.83.0` | Cherry-picks a merged PR into an RC branch. Auto-detects the latest `rc-minor-fleet-v*` or `rc-patch-fleet-v*` branch, or accepts an explicit target. Handles squash-merged and merge commits. Requires `gh`. | ### Using `/project` for workstream context diff --git a/.claude/skills/cherry-pick/SKILL.md b/.claude/skills/cherry-pick/SKILL.md new file mode 100644 index 0000000000..87064c3bc7 --- /dev/null +++ b/.claude/skills/cherry-pick/SKILL.md @@ -0,0 +1,77 @@ +--- +name: cherry-pick +description: Cherry-pick a merged PR into the current RC branch. Use when asked to "cherry-pick", "cp into RC", or after merging a PR that needs to go into the current release. +allowed-tools: Bash(git *), Bash(gh pr *), Bash(gh api *), Read, Grep, Glob +effort: low +--- + +Cherry-pick a merged PR into the current RC branch. Arguments: $ARGUMENTS + +Usage: `/cherry-pick [RC_BRANCH]` + +- `PR_NUMBER` (required): The PR number to cherry-pick (e.g. `43078`). If not provided, ask the user. +- `RC_BRANCH` (optional): The target RC branch name (e.g. `rc-minor-fleet-v4.83.0`). If not provided, auto-detect the most recent one. + +## Step 1: Ensure main is up to date + +1. `git fetch origin` +2. `git checkout main` +3. `git pull origin main` + +## Step 2: Identify the RC branch + +If an RC branch was provided as the second argument, use it (but still confirm with the user before proceeding). + +Otherwise, auto-detect by listing both minor and patch RC branches: + +``` +git for-each-ref 'refs/remotes/origin/rc-minor-fleet-v*' 'refs/remotes/origin/rc-patch-fleet-v*' --format='%(refname:strip=3)' | grep -E '^rc-(minor|patch)-fleet-v[0-9]+\.[0-9]+\.[0-9]+$' | sort -V +``` + +From the results, suggest the most recent `rc-minor-fleet-v*` branch as the default. If patch branches also exist, mention them as alternatives. **Always ask the user to confirm the target RC branch before proceeding.** + +## Step 3: Get the merge commit and GitHub username + +1. Get the PR title: + ``` + gh pr view --json title --jq .title + ``` +2. Get the merge commit SHA: + ``` + gh pr view --json mergeCommit --jq .mergeCommit.oid + ``` + If this returns `null` or an empty value, the PR is not yet merged. Tell the user and stop. +3. Get the GitHub username: `gh api user --jq .login` + +## Step 4: Cherry-pick onto a new branch + +1. Create a new branch off the RC branch: + ``` + git checkout -b /-cp origin/ + ``` + Derive `` from the PR title (lowercase, hyphens, keep it short — 3-5 words max). +2. Check whether the commit is a merge commit by inspecting its parents: + ``` + git rev-list --parents -n 1 + ``` + If the commit has multiple parents, run: + ``` + git cherry-pick -m 1 + ``` + Otherwise (squash-merged or rebased), run: + ``` + git cherry-pick + ``` +3. If there are conflicts, stop and tell the user which files conflict. Do NOT attempt to resolve them automatically. + +## Step 5: Push and open PR + +1. Push the branch: `git push -u origin HEAD` +2. Open a PR targeting the RC branch (NOT main): + ``` + gh pr create --base --title "Cherry-pick #: " --body "$(cat <<'EOF' + Cherry-pick of # into the RC branch. + EOF + )" + ``` +3. Report the PR URL to the user.