diff --git a/.github/skills/cherry-pick-to-release/SKILL.md b/.github/skills/cherry-pick-to-release/SKILL.md new file mode 100644 index 0000000000..b4062eb72a --- /dev/null +++ b/.github/skills/cherry-pick-to-release/SKILL.md @@ -0,0 +1,245 @@ +--- +name: cherry-pick-to-release +description: 'Cherry-pick a merged main-branch PR onto a MsQuic release branch (release/X.Y).' +--- + +# Cherry-Pick to MsQuic Release Branch + +You are helping a maintainer back-port a fix from `main` to one or more +MsQuic release branches (`release/2.4`, `release/2.5`, etc.). + +This skill encodes the patterns the project uses. + +## When This Skill Activates + +The user asks to cherry-pick / back-port / "CP" a PR or commit from `main` +onto a release branch. Typical requests: + +- "Cherry-pick #5942 to release/2.4 and release/2.5" +- "Back-port the ACK underflow fix to 2.5" +- "CP this commit to the 2.4 release branch" + +## Inputs You Need + +Before doing anything, make sure you know: + +1. **Source**: a PR number on `main` (preferred) or a commit SHA on `origin/main`. +2. **Target release branch(es)**: e.g. `release/2.4`, `release/2.5`. If the + user is ambiguous (e.g. "to the release branches"), ask whether they want + one branch or both, and which. +3. **Whether to push / open a PR**. You must never push a branch or open a PR + without explicit permission. Stop and ask before any `git push` or `gh pr create`. + +If anything is missing, ask before proceeding. + +## Project Conventions (must follow) + +### PR Title + +``` +[CP] (#) +``` + +Examples actually used on the release branches: + +- `[CP] Fix underflow in ACK frame parsing #5942` (→ PR #5943 on 2.5, #5944 on 2.4) +- `[CP] Fix SAL annotation placement on function templates (#5895)` +- `[CP] Free AES 256 GCM algorithm handle on cleanup (#5526)` +- `[CP] Fix double deref in connection pool error path (#5597)` + +When the same fix targets multiple release branches, the title is identical +across PRs; only the target branch differs. After squash-merge, GitHub +appends the new PR number, producing commits like +`[CP] Fix underflow in ACK frame parsing #5942 (#5943)` on the release +branch — this is expected and required (it makes traceability trivial). + +Do **not** invent new prefixes; stick to `[CP]` unless asked. + +### PR Body + +**Use the exact body of the original PR, verbatim**, including the +`## Description`, `## Testing`, and `## Documentation` sections as the +original author wrote them. Do **not** rewrite, summarize, or augment them +with cherry-pick commentary. + +No additions or modification of the original description is acceptable. + +### Branch Naming + +Project convention (observed on most recent cherry-pick PRs): + +``` +/cp___copilot +``` + +The `` is a snake_case summary of the fix, mirroring +prior branches like `cp_conn_pool_deref`, `cp_free_aes_256_gcm_handle`, +`underflow_fix_cp`. + +Use one branch per target release branch (do not try to land both +release branches from a single branch / PR). + +### Commits Inside the PR + +- Almost always **one commit** — the cherry-picked commit, with its + original message preserved. +- Occasionally a **second commit** is acceptable if needed to make the + release branch build/pass tests (merge conflict resolutions and build fixes). + Keep these tightly scoped to enabling the cherry-pick; do **not** sneak in unrelated changes. +- Squash-merge erases the multi-commit structure on the release branch. +- Do **not** add `(cherry picked from commit X)` trailers — the project + doesn't use `git cherry-pick -x`; traceability comes from the PR title + containing the original PR number. + +## Workflow + +Follow these steps in order. Do not skip a phase. + +### Phase 1 — Identify the source commit on main + +1. If given a PR number, find its squash-merge commit on `origin/main`: + ```powershell + gh pr view --repo microsoft/msquic --json mergeCommit,state,title,body,baseRefName + ``` + Verify `state == MERGED` and `baseRefName == main`. If not merged, stop and tell the user — never cherry-pick an unmerged change. +2. If given a SHA, confirm it is reachable from `origin/main`: + ```powershell + git --no-pager log -1 --format="%H %s" + git --no-pager branch -r --contains | Select-String "origin/main" + ``` +3. Capture the original PR title and body — you'll reuse them. + +### Phase 2 — Prepare the local branch + +Repeat for each target release branch. + +1. Make sure the working tree is clean (`git status`). If not, stop and ask. +2. Fetch latest refs: `git fetch origin --prune`. +3. Create the branch from the tip of the release branch: + ```powershell + git checkout -b /cp__2_5_copilot origin/release/2.5 + ``` + +### Phase 3 — Apply the cherry-pick + +1. Run `git cherry-pick ` (no `-x`). +2. **On conflicts**: + - Resolve them, keeping the spirit of the original fix. + - If the conflict is non-trivial, briefly summarize the resolution in the PR body under `## Description` so reviewers know what differs from `main`. + - If the fix depends on code that doesn't exist on the release branch, **stop and ask the user** how to proceed (skip, adapt, or pull in additional commits) — do not silently rewrite the fix. + +### Phase 4 — Regenerate derived files (only if applicable) + +Check whether the cherry-pick touches things that require regeneration. CI +will fail otherwise (`check-clog.yml`, `check-dotnet.yml`). + +- **Trace / log macro changes** (`QuicTraceLogInfo`, `QuicTraceEvent`, + etc., or anything under `src/manifest/`): + ```powershell + ./scripts/update-sidecar.ps1 + ``` + Commit any changes under `src/generated/` and `src/manifest/clog.sidecar` as part of the same commit (or amend). + +- **Public C API surface changes** (anything under `src/inc/`, especially `msquic.h`): + ```powershell + ./scripts/generate-dotnet.ps1 + ``` + Commit any changes under `src/cs/`. + +If neither applies, skip this phase. + +### Phase 5 — Build and run tests locally (REQUIRED) + +Build and run tests locally before pushing. This is **required for every +cherry-pick**, regardless of whether the `git cherry-pick` was clean or +required conflict resolution. Do not skip this phase. + +1. **Build** with the default TLS provider for the platform you're on: + ```powershell + ./scripts/build.ps1 -Tls schannel # Windows + pwsh ./scripts/build.ps1 -Tls openssl # Linux + ``` + +2. **Run the tests that exercise the cherry-picked code.** Use a + GoogleTest `--Filter` to keep the runtime short: + ```powershell + ./scripts/test.ps1 -Tls schannel -Filter '.*' + ``` + At minimum, run: + - the tests that were added or modified by the cherry-pick, and + - the tests directly covering the changed code paths (e.g. + `TlsTest.*` for `src/platform/tls_*`, `ApiTest.*` for `src/inc/` + surface changes, `HandshakeTest.*` for `src/core/` handshake logic). + +3. If the build or the relevant tests fail on the release branch but + pass on `main`, **stop and ask the user** — do not push a broken + cherry-pick. Likely causes: missing prerequisite commits, API drift + between branches, or test infra changes that didn't get back-ported. + +Capture the build and test outcome (pass/fail, number of tests run) to +mention briefly when you ask for permission to push. + +### Phase 6 — Push and open the PR (gated on explicit user permission) + +Stop here and show a summary of the cherry-pick to the user: +original PR, target branch, branch name, PR title, build and test status. +Confirm with the user before pushing. Then: + +1. Push the branch: + ```powershell + git push -u origin /cp__2_5_copilot + ``` +2. Open the PR as a **draft** (per the user's standing rule, unless they say otherwise): + ```powershell + gh pr create --repo microsoft/msquic ` + --base release/2.5 ` + --head /cp__2_5_copilot ` + --draft ` + --title "[CP] (#)" ` + --body-file + ``` + - `--base` must be the release branch (`release/2.4`, `release/2.5`, …), **not** `main`. +3. If cherry-picking to multiple release branches, repeat phases 2–6 for each branch. Open one PR per branch; mention the sibling PR number in each body so reviewers can correlate them (e.g. `Companion PR for release/2.4: #5944`). + +## Self-Verification Checklist + +Before telling the user the cherry-pick is ready: + +- [ ] PR `--base` is the correct `release/X.Y` branch (never `main`). +- [ ] PR title is `[CP] (#)` (or an explicitly approved variant). +- [ ] PR body uses the **exact body of the original PR verbatim** with no additions. +- [ ] Branch name follows `/cp___copilot`. +- [ ] PR is opened as a draft. +- [ ] Only the cherry-picked commit (+ optional minimal build-fix commits) is on the branch — no unrelated changes. +- [ ] **Local build succeeded** on the release branch with the cherry-pick applied (Phase 5). +- [ ] **Relevant tests were run locally and pass** (Phase 5). The exact test filter and result are mentioned when asking the user for permission to push. +- [ ] If trace/log macros were touched → `scripts/update-sidecar.ps1` was run and generated files committed. +- [ ] If `src/inc/` public headers were touched → `scripts/generate-dotnet.ps1` was run and generated files committed. +- [ ] You obtained explicit user permission before pushing and opening the PR. + +## Anti-Patterns to Avoid + +- **Don't** cherry-pick a PR that isn't merged on `main` yet. +- **Don't** use `git cherry-pick -x` — the project doesn't include + `(cherry picked from commit X)` trailers in the final commit message. +- **Don't** bundle unrelated fixes into the same cherry-pick PR. If you + see a related-but-distinct issue, open a separate cherry-pick. +- **Don't** invent a new title prefix (e.g. `[BACKPORT 2.5]`) — stick to + `[CP]` to stay consistent with the last ~2 years of cherry-pick PRs. +- **Don't** silently drop test changes. +- **Don't** rewrite, summarize, or paraphrase the original PR's + description. The body must contain the original PR's body verbatim without additions. +- **Don't** skip the local build / test step (Phase 5), even when the + cherry-pick applied with no conflicts. Auto-merged hunks can still + produce subtly wrong code. +- **Don't** push or open a PR without explicit user permission. +- **Don't** bump the version number as part of a cherry-pick PR — + version bumps (`Bump version to v2.5.X`) are separate PRs done at + release time. + +## Non-Goals + +- Triaging whether a fix *should* be cherry-picked. The user decides + that; this skill just executes the cherry-pick cleanly. +- Releasing / tagging / publishing artifacts. Those are separate + processes handled outside this skill.