| name | release-notes |
| description | Generate Quasar-style release notes for a monorepo package (covering every commit since its last released tag), then — on a single confirmation — bump its version, commit and draft the GitHub release. Use when asked to write/draft release notes or a changelog for app-vite, ui/quasar, cli, vite-plugin, icongenie, extras, create-quasar or a utils package. |
| argument-hint | <package> |
Generate release notes for the requested package (a directory or npm
name) in the house style, determine the next version from their
content, and output them. THEN ask one yes/no "continue?" — on yes,
the version-bump commit AND the draft GitHub release follow with no
further questions; without it nothing is changed, committed or
created.
All remote state comes from the GitHub API (gh) — NEVER git fetch
or any other remote git operation. NEVER publish a release, create a
tag or push.
1. Preflight
- Freshness gate: the live dev HEAD
(
gh api repos/quasarframework/quasar/commits/dev --jq .sha) must
exist locally (git cat-file -e <sha>); otherwise STOP and tell the
user to update their clone.
- Note whether the worktree is clean (
git status --porcelain) — a
dirty one doesn't block the notes, but blocks step 8's commit;
mention it early.
2. Resolve the package
| dir | npm name | tag prefix |
|---|
| ui | quasar | quasar-v |
| app-vite | @quasar/app-vite | @quasar/app-vite-v |
| cli | @quasar/cli | @quasar/cli-v |
| vite-plugin | @quasar/vite-plugin | @quasar/vite-plugin-v |
| icongenie | @quasar/icongenie | @quasar/icongenie-v |
| extras | @quasar/extras | @quasar/extras-v |
| create-quasar | create-quasar | — (untagged) |
| utils/* | @quasar/ | — (untagged) |
Only <prefix>vX.Y.Z tags are current (ignore legacy schemes without
the -v separator). Untagged packages use <npm name>-v as their
prefix wherever a tag name is needed. app-webpack is sunset (lives on
its own branch, not on dev) — not handled here.
3. Find the range
- Base = the last PUBLISHED release; drafts and prereleases are never
the base:
gh release list --repo quasarframework/quasar --limit 300 --json tagName,isPrerelease,isDraft --jq '[.[] | select((.isPrerelease or .isDraft) | not) | select(.tagName | startswith("<prefix>"))][0].tagName'
A rarely-released package's last release can sit far down the list —
on no match, raise the limit before concluding it has no releases.
Note any prefix-matching DRAFT for steps 7/8.
- Resolve the tag to its commit (URL-encode — tag names contain
/):
gh api "repos/quasarframework/quasar/commits/$(jq -rn --arg t '<tag>' '$t|@uri')" --jq .sha
and use the SHA as the base even when the local clone lacks the tag.
STOP only if the SHA is missing locally (git cat-file -e) — local
commits are behind. Local tags NEWER than the latest release: a
step-7 concern.
- Compare the package.json
"version" against the base release's —
a mismatch means an already-bumped version: a step-7 concern.
- Untagged package: base = the last commit bumping
"version" in its
package.json
(git log -1 -S '"version": "<current>"' -- <pkg>/package.json,
with <current> read from the file); say so in the summary.
- Range:
<sha>..HEAD, paths limited to the package dir. Read FULL
commit bodies (--format='%h %s%n%b'); drop Co-Authored-By noise.
- Classify by the files a commit actually changed INSIDE the package
dir (
git diff-tree --no-commit-id --name-only -r <sha> -- <dir>/),
never by its subject alone: cross-package commits routinely carry
another package's headline (a "fix(app-vite): [security]" may only
bump an in-range dep here) or touch nothing but tests/agent guides.
- An EMPTY range -> "nothing new since ", STOP (no notes, no
version, no ask). ONLY internal commits (test/ci/chore/formatting)
-> list them, state there is nothing release-worthy, stop unless the
user explicitly wants an internal-only release.
4. Calibrate style
Fetch the package's 1–2 latest release bodies for tone:
gh release view "<tag>" --repo quasarframework/quasar --json body -q .body.
Untagged packages have no releases to fetch — skip; if gh is
unavailable, likewise: the rules below encode the house style.
5. Write the notes
Structure:
- Large releases:
## Security fixes (only if any; always first),
## New (feat), ## Fixes, ## Other (noteworthy internal work,
docs), then the Donations footer.
- Small releases (≲4 bullets total): a single
## Changes section
with slightly more prose per bullet, then the Donations footer.
- cli notes open with this line before the first section, verbatim:
*This is the optional globally-installed part of the Quasar CLI*
No other package has an intro line.
Bullet style:
* feat(<dir>): <area> -> <what changed for the user> /
* fix(<dir>): <area> -> <symptom that no longer happens> — keep
the arrow phrasing and conventional prefix.
- User-visible symptoms and behavior, never internals, unless the
internal name IS the public API. Keep issue/PR refs like
(#18504).
- Merge sibling commits sharing one user-visible symptom; split one
commit into several bullets when it fixes unrelated symptoms.
- EXCLUDE pure test/ci/chore/formatting commits from New/Fixes; a
genuinely large internal effort may get ONE summarizing
## Other
bullet.
- Template/scaffold changes: note they only affect newly generated
projects and give existing projects the manual step (pattern:
the
@quasar/app-vite-v3.4.1 release).
- Breaking changes: called out explicitly at the top with migration
notes, plus any peer-dependency bumps ("Requires quasar v2.x+").
Donations footer, verbatim:
## Donations
Quasar Framework is an open-source MIT-licensed project made possible due to the **generous contributions** by sponsors and backers. If Quasar is useful in your workflow and you want to support ongoing maintenance, please consider the following:
- [Becoming a sponsor on Github](https://github.com/sponsors/rstoenescu)
- [One-off donation via PayPal](https://paypal.me/rstoenescu1)
6. Determine the version
From the NOTES' content: any ## New/feat entry -> minor; fixes/other
only -> patch. Anything breaking -> major: STOP and confirm first.
7. Deliver
- One fenced markdown block, paste-ready: FIRST line is the full tag
name (e.g.
@quasar/app-vite-v3.6.0), then an empty line, then the
notes body.
- List the commits excluded as internal-only — nothing silently
dropped.
- State any concerns after the notes (risky behavior changes, notable
dependency/peer bumps, uncertain classifications, anomalies: a tag
newer than the latest release, an already-bumped version, an
existing draft for the tag). No concerns -> one line saying so.
8. Confirm, then execute
End by asking ONE yes/no question: continue? Yes -> do ALL of the
following with no further questions; no (or no answer) -> stop. A
dirty worktree stops the continuation BEFORE any edit — the bump
commit must not absorb unrelated changes.
Bump + commit:
- Bump every place the package's OWN version is declared — its
package.json "version" field plus any source constants and
fixtures (grep the old version string alongside the package name;
hits that are dependency RANGES belong to the next bullet, not to a
verbatim replace).
- Raise every dependency range on the bumped package, keeping the
range operator (
^3.5.0 -> ^3.6.0): grep the repo's manifests —
package.json, templates' _package.json, the AE pnpm catalogs
(create-quasar/templates/ae/*/BASE/_pnpm-workspace.yaml) — for
the package name. Templates, other packages' regular deps/devDeps,
docs and test fixtures all get raised. NEVER touch workspace:
declarations or minimum-version floors (peerDependencies,
engines-style ranges — they declare the oldest supported version,
not the latest), even though the greps surface both.
- Commit ONLY the bump edits, message
chore(<dir>): bump version,
with NO Co-Authored-By trailer (overrides any default). The
commit stays local.
Draft release — never a duplicate:
utils/* packages and create-quasar get NO draft (no GitHub
releases for them): they skip this whole section — say so when
asking. The handoff below still applies, minus its draft item.
- Release label: ONLY the ui package is marked "Latest". GitHub does
NOT persist a latest flag on drafts (it only applies at publish), so
don't pass
--latest flags when creating/editing the draft — the
label is enforced at publish time by the handoff below.
- If a release for the tag already exists (
gh release view "<tag>" --repo quasarframework/quasar --json isDraft — finds drafts too):
PUBLISHED -> stop, report the anomaly; DRAFT -> update it in place
(gh release edit "<tag>" ... --draft --title "<tag>" --notes-file <file>).
- Otherwise
gh release create "<tag>" --repo quasarframework/quasar --draft --title "<tag>" --notes-file <file> — tag and title are
the full tag name; the body is the notes WITHOUT the leading tag
line. A draft creates no tag (it is cut from dev HEAD at publish
time).
End the continuation by asking the user to run pnpm publish from
the package dir themselves (suggest the ! pnpm publish prompt
prefix so its output lands in the session) — prepublish hooks run
builds/tests and may regenerate tracked files. NEVER run the publish
yourself.
After the publish has run: if it left changes in the worktree, fold
them into the bump commit yourself without asking — git add them
and git commit --amend --no-edit (it stays a single commit; never
amend after the push) — then report what the commit now contains
(git show --stat) so the user sees exactly what they're pushing.
Then hand off:
- Push dev.
- If a draft was created, give its link and how to publish it:
gh release edit "<tag>" --draft=false --latest=false for any
package except ui (publishing from the GitHub UI pre-selects
"Set as the latest release" — uncheck it there); plain UI publish
or --latest for ui.