|
| 1 | +--- |
| 2 | +name: release-pr |
| 3 | +description: > |
| 4 | + Open a release PR: bumps versions in melos.yaml and pubspecs, finalises CHANGELOGs, opens a PR with auto-generated |
| 5 | + release notes against master (stable) or v10.0.0 (beta). |
| 6 | +disable-model-invocation: true |
| 7 | +argument-hint: "[version]" |
| 8 | +arguments: [version] |
| 9 | +allowed-tools: |
| 10 | + - Bash(git *) |
| 11 | + - Bash(gh *) |
| 12 | + - Bash(melos *) |
| 13 | + - Bash(which *) |
| 14 | + - Bash(grep *) |
| 15 | + - Read |
| 16 | + - Edit |
| 17 | + - Write |
| 18 | +--- |
| 19 | + |
| 20 | +# release-pr |
| 21 | + |
| 22 | +Opens a release PR for stream-chat-flutter. Branch `release/v<X.Y.Z>` → base `master` (stable) or `v10.0.0` (beta) → |
| 23 | +title `chore(repo): release v<X.Y.Z>`. |
| 24 | + |
| 25 | +**This skill only opens the PR.** After merge, tagging and pub.dev publishing happen via `release_tag.yml` + |
| 26 | +`release_publish.yml` (stable: automatic; beta/named: maintainer pushes the tag manually). |
| 27 | + |
| 28 | +If `$version` is provided (e.g. `/release-pr 9.24.0`), use it. Strip any leading `v`. Otherwise ask the user. |
| 29 | + |
| 30 | +## Release types |
| 31 | + |
| 32 | +| Type | Base | Version shape | Tagging | |
| 33 | +|---|---|---|---| |
| 34 | +| **Stable** | `master` | `X.Y.Z` | Auto via `release_tag.yml` on merge | |
| 35 | +| **Beta** | `v10.0.0` | `X.Y.Z-beta.N` | Manual (`release_tag.yml` only watches master) | |
| 36 | +| **Named pre-release** | feature branch | `X.Y.Z-<name>.N` | Manual; same as beta | |
| 37 | + |
| 38 | +`distribute_internal.yml` builds sample apps for branches like `feat/design-refresh` — **not** a release. Don't use |
| 39 | +this skill for those. |
| 40 | + |
| 41 | +## Inputs |
| 42 | + |
| 43 | +1. **Version** (`X.Y.Z` or `X.Y.Z-suffix`). Use `$version` if supplied, otherwise ask. Don't infer. |
| 44 | +2. **Base branch** — auto-derive from `$version`: |
| 45 | + - No suffix (`X.Y.Z`) → `master`. Stable release. |
| 46 | + - `-beta.N` suffix → `v10.0.0`. Verify it exists: `git ls-remote --heads origin v10.0.0`. |
| 47 | + - Any other suffix (`-alpha.N`, `-rc.N`, `-design-refresh.N`, …) → ask the user which feature branch to target. |
| 48 | +3. **Previous tag** for the release-notes diff. Run `gh release list --limit 10`; pick the most recent tag of the same |
| 49 | + train (stable = no hyphen in tag; beta = matches `-beta.`; named = matches the same suffix prefix). |
| 50 | + |
| 51 | +## Pre-flight |
| 52 | + |
| 53 | +Run these checks. **If any fail, stop the skill, surface the failing check to the user, and do not try to auto-fix** |
| 54 | +(no stashing uncommitted work, no force-pulling, no killing processes). |
| 55 | + |
| 56 | +- `git status --short -uno` clean after `git checkout <base>` + `git pull --ff-only`. |
| 57 | +- `which melos` succeeds. |
| 58 | +- `gh auth status` succeeds. |
| 59 | +- `gh pr list --head release/v<version> --state all --json number` returns `[]`. |
| 60 | +- Latest CI on the base-branch tip is green: `gh run list --branch <base> --limit 5` — no failures on the most |
| 61 | + recent runs. |
| 62 | + |
| 63 | +## Steps |
| 64 | + |
| 65 | +### 1. Branch off the chosen base |
| 66 | + |
| 67 | +Pre-flight already left you on `<base>` with latest. Just create the release branch: |
| 68 | + |
| 69 | +```bash |
| 70 | +git checkout -b release/v<version> |
| 71 | +``` |
| 72 | + |
| 73 | +### 2. Bump versions |
| 74 | + |
| 75 | +Edit two sets of files by hand, then let `melos bs` propagate the rest. |
| 76 | + |
| 77 | +**Edit:** |
| 78 | + |
| 79 | +- `melos.yaml` — in the `command.bootstrap.environment.dependencies` block, bump all five `stream_chat*: ^<version>` |
| 80 | + entries. Locate with `grep -n "^ stream_chat" melos.yaml`. |
| 81 | +- Each `packages/*/pubspec.yaml` (5 files) — set `version: <version>`. Do **not** touch |
| 82 | + `packages/*/example/pubspec.yaml` or `sample_app/pubspec.yaml` `version:` fields; their deps are synced by |
| 83 | + `melos bs`. |
| 84 | + |
| 85 | +**Then run:** |
| 86 | + |
| 87 | +```bash |
| 88 | +melos bs |
| 89 | +``` |
| 90 | + |
| 91 | +`melos bs` does the rest: |
| 92 | + |
| 93 | +- Propagates the `melos.yaml` deps block into every workspace pubspec, including each package's intra-monorepo dep |
| 94 | + constraints, every `packages/*/example/pubspec.yaml`, and `sample_app/pubspec.yaml`. |
| 95 | +- Fires the `command.bootstrap.hooks.post: melos run version:update` hook, which runs `tools/generate_version.dart` |
| 96 | + and regenerates `packages/stream_chat/lib/version.dart` from the new pubspec version. |
| 97 | + |
| 98 | +Do **not** run `./tools/version.sh`. It calls `melos version` which leaves `melos.yaml`'s deps block stale — the next |
| 99 | +`melos bs` would re-write every pubspec dep constraint back to the old version. |
| 100 | + |
| 101 | +Verify the diff shape matches the previous release PR. Find its number with: |
| 102 | + |
| 103 | +```bash |
| 104 | +gh pr list --search "chore(repo): release in:title" --state merged --limit 5 --json number,title |
| 105 | +``` |
| 106 | + |
| 107 | +Then compare: |
| 108 | + |
| 109 | +```bash |
| 110 | +git diff --stat |
| 111 | +gh pr diff <prev-release-pr-number> --name-only # for comparison |
| 112 | +``` |
| 113 | + |
| 114 | +### 3. Finalise the CHANGELOGs |
| 115 | + |
| 116 | +Five files: `packages/{stream_chat, stream_chat_flutter, stream_chat_flutter_core, stream_chat_localizations, |
| 117 | +stream_chat_persistence}/CHANGELOG.md`. |
| 118 | + |
| 119 | +For each, **apply the first matching rule below** — it's a decision tree, not a sequence: |
| 120 | + |
| 121 | +1. **Top section is `## Upcoming Changes` or `## Upcoming`** → rename to `## <version>`. Keep bullets. |
| 122 | +2. **User-facing changes since `v<prev>`** — new APIs, bug fixes users would notice, deprecations. Check with |
| 123 | + `git log v<prev>..HEAD --oneline -- packages/<pkg>`. Add a `## <version>` header with bullets in the existing |
| 124 | + emoji-prefixed sections only (`✅ Added`, `🚀 Performance`, `🐞 Fixed`, `🔄 Changed`). Don't invent new |
| 125 | + section names. |
| 126 | +3. **Only `stream_chat` dep bump** (no in-package changes, but depends on `stream_chat`) → add the dep-bump line: |
| 127 | + ``` |
| 128 | + ## <version> |
| 129 | +
|
| 130 | + - Updated `stream_chat` dependency to [`<version>`](https://pub.dev/packages/stream_chat/changelog). |
| 131 | + ``` |
| 132 | +4. **Anything else** (internal-only changes, test fixes, refactors, or truly nothing) → add `## <version>` + |
| 133 | + `- Minor bug fixes and improvements`. |
| 134 | + |
| 135 | +**Every package gets a `## <version>` header**, even if it's only a dep-bump line. Empty version sections and |
| 136 | +missing headers both fail pana. |
| 137 | + |
| 138 | +### 4. Sanity-check |
| 139 | + |
| 140 | +```bash |
| 141 | +melos run analyze |
| 142 | +melos run lint:pub |
| 143 | +``` |
| 144 | + |
| 145 | +If either fails, surface to the user and stop. |
| 146 | + |
| 147 | +### 5. Commit and push |
| 148 | + |
| 149 | +```bash |
| 150 | +git add -A |
| 151 | +git commit -m "chore(repo): release v<version>" |
| 152 | +git push -u origin release/v<version> |
| 153 | +``` |
| 154 | + |
| 155 | +Single commit. The message format is load-bearing: `release_tag.yml` parses `vX.Y.Z` from it after merge. |
| 156 | + |
| 157 | +### 6. Generate the PR body |
| 158 | + |
| 159 | +The body **must be exactly what GitHub's release UI produces when you click "Generate release notes"** — no template |
| 160 | +wrapper, no extra description, no CLA checkboxes. The "New Contributors" block GitHub auto-appends stays in; that's |
| 161 | +part of the convention. |
| 162 | + |
| 163 | +```bash |
| 164 | +gh api repos/GetStream/stream-chat-flutter/releases/generate-notes \ |
| 165 | + -f tag_name=v<version> \ |
| 166 | + -f previous_tag_name=v<previous> \ |
| 167 | + -f target_commitish=<base> \ |
| 168 | + --jq .body > /tmp/release-notes.md |
| 169 | +``` |
| 170 | + |
| 171 | +- `tag_name`: the tag we'll create (need not exist yet). |
| 172 | +- `previous_tag_name`: most recent tag of the same train (stable or beta). |
| 173 | +- `target_commitish`: the **base branch** (`master` or `v10.0.0`), not the release branch — the notes should cover |
| 174 | + every commit between `previous_tag_name` and where the tag will land after merge. |
| 175 | + |
| 176 | +Read the file once to skim. If a PR title looks wrong, fix it on the originating PR upstream and re-run the API |
| 177 | +call; don't hand-edit `/tmp/release-notes.md`. |
| 178 | + |
| 179 | +### 7. Open the PR |
| 180 | + |
| 181 | +```bash |
| 182 | +gh pr create \ |
| 183 | + --base <base> \ |
| 184 | + --head release/v<version> \ |
| 185 | + --title "chore(repo): release v<version>" \ |
| 186 | + --body-file /tmp/release-notes.md |
| 187 | +``` |
| 188 | + |
| 189 | +Return the PR URL. |
| 190 | + |
| 191 | +**If this is a beta or named pre-release**, also include this reminder in your message to the user: |
| 192 | + |
| 193 | +> After this PR merges, manually create and push the tag — `release_tag.yml` only fires on `master`: |
| 194 | +> ```bash |
| 195 | +> git checkout <base> |
| 196 | +> git pull --ff-only |
| 197 | +> git tag v<version> |
| 198 | +> git push origin v<version> |
| 199 | +> ``` |
| 200 | +
|
| 201 | +For stable releases (base `master`), no reminder needed — `release_tag.yml` handles it on merge. |
| 202 | +
|
| 203 | +## After merge (FYI) |
| 204 | +
|
| 205 | +Stable (base `master`): `release_tag.yml` extracts `vX.Y.Z` from the commit, creates and pushes the tag. |
| 206 | +`release_publish.yml` runs `melos run release:pub` and creates the GitHub release. |
| 207 | +
|
| 208 | +Beta / named pre-release: maintainer runs the tag commands surfaced at the end of step 7. |
| 209 | +
|
| 210 | +## Don't |
| 211 | +
|
| 212 | +- **Never create a GitHub release** (`gh release create`, `POST /repos/.../releases`). Step 6 uses |
| 213 | + `generate-notes`, which is read-only. The release itself is created by `release_publish.yml` after the tag is |
| 214 | + pushed. |
| 215 | +- **Never push a tag.** Stable is automatic on merge; beta/named is the maintainer's manual step. |
| 216 | +- **Never run `melos run release:pub`.** That's the publish step, triggered by the workflow on tag push. Even if the |
| 217 | + user asks, refuse — running it locally publishes from an unreviewed working tree. |
| 218 | +- **Never merge the PR.** Return the URL and stop. |
0 commit comments