-
-
Notifications
You must be signed in to change notification settings - Fork 1.8k
feat(skills): Add backport-pr skill #22434
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
+215
−2
Merged
Changes from all commits
Commits
Show all changes
18 commits
Select commit
Hold shift + click to select a range
22b8cc7
feat(skills): Add backport-pr skill
andreiborza 0995b49
Fix verify/commit ordering and genericize branch prefix
andreiborza cc2b927
Stop prescribing a branch name
andreiborza bba78ba
Fix commit body instruction and scope-less title template
andreiborza 8ed66cb
Trim vague clause from skill description
andreiborza ffdf207
Drop cherry-pick trigger phrase from description
andreiborza 335dcd4
Accept a PR URL or number as input
andreiborza d98e6d2
Align PR arg hint with repo convention (number-or-url)
andreiborza 12ab735
Reword intro for clarity
andreiborza 2730e9d
Drop references to unwritten v9 convention
andreiborza dcc0800
Simplify working-branch note
andreiborza 582c9ea
Fix lint/staging steps and capture backport PR URL
andreiborza 4774fa7
Drop manual cross-link step; GitHub links via the Backport of: reference
andreiborza b22be60
Clarify amend behavior for multi-commit backports
andreiborza b0214ea
Split finalize step into single- and multi-commit cases
andreiborza 6ddfee2
Note ancestor check is not conclusive if commit was reverted
andreiborza 4f530d3
Apply oxfmt formatting
andreiborza 3516b72
Use git add -u during conflict resolution too
andreiborza File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,189 @@ | ||
| --- | ||
| name: backport-pr | ||
| description: Backport a merged PR to a maintenance major branch (v10 by default) in getsentry/sentry-javascript. Cherry-picks the PR's squash-merge commit onto the target branch, namespaces the commit/PR title scope (e.g. fix(core) -> fix(v10/core)), and opens a draft backport PR. Use when asked to backport a PR, or port a fix to v10 (or an older major like v9). Trigger phrases include "backport", "port to v10", "release this on v10". | ||
| argument-hint: '<pr-number-or-url> [target-major] # e.g. 18211 v10; target defaults to v10' | ||
| --- | ||
|
|
||
| # Backport a PR to a maintenance major branch | ||
|
|
||
| `develop` is the current major (v11). A change that also needs to ship on a still-maintained | ||
| older major has to land on that major's branch too (`v10` by default). This skill cherry-picks | ||
| a merged `develop` PR onto that branch and opens a draft backport PR. | ||
|
|
||
| ## Inputs | ||
|
|
||
| - **PR** (required): the already-merged PR on `develop` to backport, given as either a full | ||
| GitHub URL or a bare number. `gh pr view` accepts both, so pass whichever the user gave | ||
| through unchanged; `<PR>` in the commands below is that value. | ||
| - **Target major** (optional, default `v10`): the maintenance branch to backport onto. | ||
| Accept `v10`, `10`, `v9`, etc. Normalize to a branch name like `v10`. | ||
|
|
||
| If no PR is given, ask for it. Do not guess. | ||
|
|
||
| ## Convention | ||
|
|
||
| - **Base branch** = the target major branch (`v10`), which must already exist on `origin`. | ||
| - **Commit + PR title**: keep the original conventional-commit prefix but namespace the | ||
| scope with the major, e.g. | ||
| - `fix(core): Fix logs flush starvation` -> `fix(v10/core): Fix logs flush starvation` | ||
| - `feat(node): Add X` -> `feat(v10/node): Add X` | ||
| - If the original has no scope (e.g. `fix: ...`), use `fix(v10): ...`. | ||
| - For a multi-scope title, prefix the whole group once, not each scope: | ||
| `fix(cloudflare,deno,node): ...` -> `fix(v10/cloudflare,deno,node): ...`. | ||
| - **PR body** is a single line: `Backport of: #<original-pr-number>`. | ||
| - **PR is opened as a draft.** | ||
| - **Working branch**: branch off the target major and give it a descriptive name. | ||
| - The changes come from the PR's **squash-merge commit** on `develop` (one commit per PR), | ||
| so a single `git cherry-pick` normally covers the whole PR. | ||
|
|
||
| ## Steps | ||
|
|
||
| ### 1. Resolve the PR and target branch | ||
|
|
||
| ```bash | ||
| # Fetch PR metadata (title, merge commit, base branch) | ||
| gh pr view <PR> --json number,title,baseRefName,mergeCommit,state,url | ||
| ``` | ||
|
|
||
| Verify: | ||
|
|
||
| - The PR is **merged** (`state == "MERGED"`). If not, stop and tell the user. | ||
| - Its `baseRefName` is `develop` (or the expected parent major). If it targeted something | ||
| else, confirm with the user before continuing. | ||
|
|
||
| Grab `mergeCommit.oid` — this is the squash commit to cherry-pick. Also grab `number`: use | ||
| that bare number (not the raw input) wherever `#<PR>` appears below, so `Backport of:` reads | ||
| `Backport of: #18211` even when the user passed a URL. | ||
|
|
||
| Make sure the target branch exists and is up to date: | ||
|
|
||
| ```bash | ||
| git fetch origin <major> develop | ||
| git rev-parse --verify origin/<major> # errors if the branch doesn't exist | ||
| ``` | ||
|
|
||
| If `origin/<major>` doesn't exist, stop: the maintenance branch hasn't been created yet. | ||
|
|
||
| Then check whether the change is already on the target. A freshly cut major often still shares | ||
| history with `develop`, so a recent PR may already be present: | ||
|
|
||
| ```bash | ||
| git merge-base --is-ancestor <mergeCommit-oid> origin/<major> && echo "ALREADY ON <major>" | ||
| ``` | ||
|
|
||
| If it prints `ALREADY ON`, the commit is in the target's history — usually meaning nothing to | ||
| backport. It's not conclusive on its own, though: a commit that was later reverted on the | ||
| maintenance branch still shows as an ancestor. So treat this as a strong signal to stop and | ||
| tell the user, but if you have reason to think the change was reverted, confirm the fix is | ||
| actually present (e.g. `git log origin/<major> -- <a changed file>`, or grep for the change) | ||
| before deciding. The cherry-pick in step 3 is the real backstop — it comes up empty only when | ||
| the change is genuinely still applied. | ||
|
|
||
| ### 2. Create the backport branch off the target major | ||
|
|
||
| ```bash | ||
| git checkout -b <branch> origin/<major> | ||
| ``` | ||
|
|
||
| ### 3. Cherry-pick the merge commit | ||
|
|
||
| ```bash | ||
| git cherry-pick <mergeCommit-oid> | ||
|
andreiborza marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| - If git reports the pick is **empty** ("nothing to commit" / "the previous cherry-pick is | ||
| now empty"), the change is already on the target. Run `git cherry-pick --abort` and stop — | ||
| do not force it through with `--allow-empty`. This is the same situation the ancestor check | ||
| in step 1 guards against, caught here for changes that landed via a different commit. | ||
| - On **conflicts**: resolve them by consulting the original diff (`git show <oid>`). | ||
| The target major may lack refactors that landed on `develop`, so adapt the change to the | ||
| older code rather than force-porting it. Stage the resolved files with `git add -u` (tracked | ||
| files only, so stray untracked workspace files don't get baked in), then | ||
| `git cherry-pick --continue`. If the change can't be cleanly adapted, stop and surface the | ||
| conflict to the user instead of guessing. | ||
| - If the PR was **not** squash-merged (multiple commits, e.g. a merge commit), cherry-pick | ||
| each relevant commit in order, or use `git cherry-pick -m 1 <merge-oid>` for a merge commit. | ||
|
|
||
| ### 4. Build and verify | ||
|
|
||
| Run the repo's pre-commit checks. Do this **before** finalizing the commit in step 5, because | ||
| `yarn format` writes changes to the working tree — those fixes must end up inside the backport | ||
| commit, not left dangling after it (otherwise you'd push an unformatted tree and CI would fail | ||
| on a commit that doesn't match your local state). | ||
|
|
||
| ```bash | ||
| yarn format | ||
| yarn lint:fix | ||
| yarn build:dev | ||
| ``` | ||
|
|
||
| Use `lint:fix`, not `lint` — plain `yarn lint` only reports, so auto-fixable issues would | ||
| otherwise survive to fail CI. | ||
|
|
||
| Run tests scoped to the touched packages when possible (full `yarn test` if unsure). If the | ||
| target major's toolchain differs and a check fails for reasons unrelated to the change, note | ||
| it for the user rather than silently skipping. | ||
|
|
||
| ### 5. Finalize the commit (fold in verification changes) | ||
|
|
||
| First stage the format/lint fixes. Use `git add -u` so only tracked files the cherry-pick and | ||
| verification touched are staged, not unrelated local edits — sanity-check with `git status` | ||
| first if `yarn format` may have reformatted files outside the backport. | ||
|
|
||
| ```bash | ||
| git add -u | ||
| ``` | ||
|
|
||
| Then finalize, depending on how step 3 went: | ||
|
|
||
| **Single squash commit (the usual case)** — amend HEAD to both namespace the subject scope and | ||
| fold in the staged fixes. The message is the namespaced title plus the one-line `Backport of:` | ||
| body (this replaces the squash-merge body, matching the convention above). Do **not** add a | ||
| `Co-Authored-By` line — the backport commit mirrors an existing commit, not new authored work. | ||
|
|
||
| Build the title as in the convention: `<prefix>(<major>/<scope>):` when the original had a | ||
| scope, or `<prefix>(<major>):` when it didn't (never emit an empty `<major>/`). | ||
|
|
||
| ```bash | ||
| git commit --amend -m "<namespaced-title>" -m "Backport of: #<PR>" | ||
|
cursor[bot] marked this conversation as resolved.
cursor[bot] marked this conversation as resolved.
cursor[bot] marked this conversation as resolved.
|
||
| ``` | ||
|
|
||
| Example subject: `fix(v10/core): Fix logs flush timeout starvation with continuous logging` | ||
|
|
||
| **Multiple commits (non-squash merge)** — leave the individual commit messages as-is; the | ||
| namespaced title lives on the PR (step 6), not on each commit. Just fold the staged fixes into | ||
| HEAD without rewording: | ||
|
|
||
| ```bash | ||
| git commit --amend --no-edit | ||
| ``` | ||
|
|
||
| Confirm the tree is clean so nothing is left uncommitted before you push: | ||
|
|
||
| ```bash | ||
| git status --porcelain # expect no output | ||
| ``` | ||
|
|
||
| ### 6. Push and open the draft PR | ||
|
|
||
| The `Backport of: #<PR>` body references the original PR, so GitHub cross-links the two | ||
| automatically — no separate comment needed. | ||
|
|
||
| ```bash | ||
| git push -u origin <branch> | ||
|
|
||
| gh pr create \ | ||
| --draft \ | ||
| --base <major> \ | ||
| --title "<namespaced-title>" \ | ||
| --body "Backport of: #<PR>" | ||
| ``` | ||
|
|
||
| ## Notes | ||
|
|
||
| - Never push directly to `develop`, `master`, or the major branch. Work only on your | ||
| backport branch and open a PR. | ||
| - One PR per backport. If asked to backport several PRs, repeat the whole flow per PR (each | ||
| gets its own branch and draft PR). | ||
| - If asked to backport to multiple majors at once (e.g. v10 and v9), do them as separate | ||
| branches/PRs, each based off its own `origin/<major>`. | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.