diff --git a/RELEASING.md b/RELEASING.md new file mode 100644 index 0000000..932d85a --- /dev/null +++ b/RELEASING.md @@ -0,0 +1,94 @@ +# Releasing + +Manual release flow for claude-code-chat-browser. A release is a git tag plus a GitHub Release with notes. No CI publish workflow, and no wheel, npm package, or other artifact. + +`v0.1.0` (2026-06-18) and `v0.2.0` (2026-07-30) are the shipped tags so far. The steps below apply to the next cut. + +## Version source + +The release version is `__version__` in `app.py` line 3. There is no `pyproject.toml` version field. + +`SECURITY.md` line 5 names the latest shipped release in its supported-versions blurb, so update it when a tag ships, not on the `.dev0` bumps in between. `README.md` points readers at that page. + +Between tagged releases, `master` may use a `.dev0` suffix (for example `0.3.0.dev0` while the next release is in flight). The shipped tag drops `.dev0`. + +## Pre-release checklist + +1. Confirm `master` is green in GitHub Actions (`.github/workflows/ci.yml`). +2. Decide the semver bump using [docs/deprecation-policy.md](docs/deprecation-policy.md#versioning) (pre-1.0: patch for safe fixes, minor for additive work and deprecations). +3. If the release removes or renames a documented API field, confirm the [two-release deprecation window](docs/deprecation-policy.md#removal-criteria) is satisfied. + +## Release checklist + +Do the changelog in one PR and the version bump in a second PR, or combine them on a `release/vX.Y.Z` branch. For `v0.2.0` we used two PRs: changelog first (`docs/changelog-0-2-0`), then the bump (`release/v0.2.0`). + +1. Edit [CHANGELOG.md](CHANGELOG.md) ([Keep a Changelog](https://keepachangelog.com/en/1.1.0/)): + - Move everything under `## [Unreleased]` into a new `## [X.Y.Z] - YYYY-MM-DD` section with `### Added`, `### Changed`, `### Deprecated`, `### Fixed`, `### Removed`, or `### Security` as needed. + - Leave `## [Unreleased]` empty. + - Update the footer compare links: `[Unreleased]` → `vX.Y.Z...HEAD`, add `[X.Y.Z]` → `vPREVIOUS...vX.Y.Z`. +2. On a branch from current `master`, set `app.py` line 3 to the release version without `.dev0` (for example `"0.2.0"`). +3. Update [SECURITY.md](SECURITY.md) line 5 so the version inside its "(currently ...)" parenthetical is the one you are shipping. Keep the surrounding formatting and leave the table at lines 7-10 unchanged. +4. From the repo root, grep for stale version strings (`.dev0` suffixes, the old SECURITY.md parenthetical, or the previous shipped release): + ```sh + PREVIOUS=0.2.0 + PREVIOUS_ESC=$(echo "$PREVIOUS" | sed 's/[.]/\\&/g') + git grep -nE "\.dev0|\(currently |${PREVIOUS_ESC}" + ``` + Point `PREVIOUS` at the release you are replacing (no `v` prefix). Fix any hits that should name the new version (for example `docs/deprecation-policy.md`). +5. Open a PR, get review, merge to `master`. +6. Tag the merge commit (lightweight tag, same as `v0.1.0` and `v0.2.0`): + ```sh + git checkout master + git pull + git tag vX.Y.Z + git push origin vX.Y.Z + ``` + Tag format: `vMAJOR.MINOR.PATCH` (for example `v0.2.0`). +7. Publish the GitHub Release after pushing the tag. From the repo root, extract the body from `CHANGELOG.md`: + ```sh + cd "$(git rev-parse --show-toplevel)" + VERSION=0.2.0 # no leading v; not the literal X.Y.Z placeholder + VERSION="${VERSION#v}" + case "$VERSION" in + *[!0-9.]*|'') echo "error: VERSION must look like 0.2.0" >&2; exit 1 ;; + *..*|.*|*.) echo "error: VERSION must look like 0.2.0" >&2; exit 1 ;; + *.*.*.*) echo "error: VERSION must look like 0.2.0" >&2; exit 1 ;; + *.*.*) ;; + *) echo "error: VERSION must look like 0.2.0" >&2; exit 1 ;; + esac + case "$VERSION" in + 0[0-9]*.*.*|*.[0][0-9]*.*|*.*.[0][0-9]*) + echo "error: VERSION components must not have leading zeros" >&2; exit 1 ;; + esac + NOTES="$(mktemp)" + trap 'rm -f "$NOTES"' EXIT + awk -v ver="$VERSION" ' + BEGIN { heading = "## [" ver "]" } + /^## \[/ { + if (found) exit + if (index($0, heading) == 1) { found=1 } + } + /^\[[^]]+\]:/ { if (found) exit } + found { print } + ' CHANGELOG.md >"$NOTES" + grep -v '^## \[' "$NOTES" | grep -q '[^[:space:]]' || { echo "error: no CHANGELOG.md section for $VERSION" >&2; exit 1; } + printf '\n\n**Full changelog:** https://github.com/cppalliance/claude-code-chat-browser/blob/v%s/CHANGELOG.md\n' "$VERSION" >>"$NOTES" + gh release create "v${VERSION}" --title "v${VERSION}" --verify-tag --notes-file "$NOTES" + ``` + The `printf` adds the same "Full changelog" footer that `v0.1.0` and `v0.2.0` carry. On macOS, Linux, and Git Bash, `mktemp` works. Or paste the `[X.Y.Z]` section in the GitHub UI and add that footer line by hand. + +## After release + +1. On `master`, bump `app.py` `__version__` to the next development suffix when you start the next cycle (for example `0.3.0.dev0` after shipping `0.2.0`). Put that commit in `CHANGELOG.md` under `[Unreleased]` only when there is user-visible work; a bare dev bump can ride with the next feature PR. +2. New work goes under `## [Unreleased]` until the next release. + +## References + +| Topic | Location | +|-------|----------| +| Changelog format | [CHANGELOG.md](CHANGELOG.md) | +| Version bump | `app.py` line 3 | +| Supported versions blurb | `SECURITY.md` line 5 | +| Deprecation / semver | [docs/deprecation-policy.md](docs/deprecation-policy.md) | +| Security reporting | [SECURITY.md](SECURITY.md) | +| CI gates | [`.github/workflows/ci.yml`](.github/workflows/ci.yml), [CONTRIBUTING.md](CONTRIBUTING.md) | diff --git a/SECURITY.md b/SECURITY.md index ec69181..3867d75 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -2,7 +2,7 @@ ## Supported Versions -This project is pre-release. Security fixes are applied to the **latest `master` branch only** (currently `0.1.0.dev0`). +This project is pre-release. Security fixes are applied to the **latest `master` branch only** (currently `0.2.0`). | Version | Supported | | -------------- | --------- | diff --git a/docs/deprecation-policy.md b/docs/deprecation-policy.md index f8a4184..a9a4ae0 100644 --- a/docs/deprecation-policy.md +++ b/docs/deprecation-policy.md @@ -43,7 +43,7 @@ For fields **only read by the bundled SPA** (no external integrators on a tagged ## Versioning -Release versions follow `MAJOR.MINOR.PATCH` in `app.__version__` and [CHANGELOG](../CHANGELOG.md). Shipped tags include [`v0.1.0`](https://github.com/cppalliance/claude-code-chat-browser/releases/tag/v0.1.0) and [`v0.2.0`](https://github.com/cppalliance/claude-code-chat-browser/releases/tag/v0.2.0). Between releases, `main` may carry a `.dev0` suffix in `app.__version__` while developing the next version. The CHANGELOG `[Unreleased]` section is the source of truth for changes not yet tagged. +Release versions follow `MAJOR.MINOR.PATCH` in `app.__version__` and [CHANGELOG](../CHANGELOG.md). Shipped tags include [`v0.1.0`](https://github.com/cppalliance/claude-code-chat-browser/releases/tag/v0.1.0) and [`v0.2.0`](https://github.com/cppalliance/claude-code-chat-browser/releases/tag/v0.2.0). Between releases, `master` may carry a `.dev0` suffix in `app.__version__` while developing the next version. The CHANGELOG `[Unreleased]` section is the source of truth for changes not yet tagged. | Bump | Pre-1.0 meaning | |------|-----------------|