From fde2de3d294024990e76c9e4daab3f0fa06affad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Djalma=20Ara=C3=BAjo?= Date: Tue, 23 Jun 2026 13:57:07 -0300 Subject: [PATCH 1/4] [Documentation] Add release process checklist to CLAUDE.md --- CLAUDE.md | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 82841d8a..8f4f3070 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -48,6 +48,23 @@ bundle exec standardrb - Stimulus controllers colocated with components: `_controller.js`. JS deps declared in `gem/package.json` and per-component in `dependencies.yml`. - Tests extend `ComponentTest`; render via `phlex { ... }` helper. +## Releasing + +A release is **not done** until all four steps below are complete. Skipping the publish, the docs/website reflection, or the git tag leaves the release half-finished. + +Decide the bump with SemVer against commits since the last `vX.Y.Z` tag: new backward-compatible features → **minor**; bug fixes / docs only → **patch**. List the range with `git log --oneline vX.Y.Z..HEAD`. + +1. **Bump the version (gem).** Edit `RubyUI::VERSION` in `gem/lib/ruby_ui.rb`. Then from each app dir regenerate lockfiles so the path dependency tracks the new version: `gem/Gemfile.lock` and `docs/Gemfile.lock` should both read `ruby_ui (X.Y.Z)`. + +2. **Publish the gem to RubyGems.** From `gem/`: `gem build ruby_ui.gemspec` then `gem push ruby_ui-X.Y.Z.gem`. The account has **MFA**, so `gem push` prompts for a one-time password — have the OTP ready (or pass `--otp `). Confirm `djalmaaraujo` is in `gem owner ruby_ui` first. Do not commit the built `.gem` artifact. + +3. **Reflect the version on the docs website (PR against `main`).** Releases go through a `[Release] vX.Y.Z` PR (main is protected — no direct pushes). The PR bundles, on a `release/vX.Y.Z` branch: + - the `gem/lib/ruby_ui.rb` bump + both regenerated `Gemfile.lock`s; + - `docs/app/views/pages/home.rb` — update the home hero badge copy to the headline features (the header version badge reads `RubyUI::VERSION` and updates automatically; do not hardcode it); + - `mcp/data/registry.json` — rebuild with `cd mcp && bundle exec rake mcp:build` (reads `../gem`, so it picks up the new version). + +4. **Tag + GitHub release.** After the release PR merges, tag `vX.Y.Z` on the merge commit, push the tag, and cut the GitHub release. The git tag and the published gem must both exist — publishing the gem without tagging (or vice versa) is an incomplete release. + ## Commits & PRs - Bracketed prefixes (`[Feature]`, `[Bug Fix]`, `[Documentation]`) or scoped conventional (`feat(scope): ...`). @@ -58,5 +75,6 @@ bundle exec standardrb - Don't run commands from repo root expecting them to work — `cd gem` or `cd docs` first. - Don't edit a component without updating its `docs/app/views/docs/.rb` counterpart. -- Don't bump the gem version or release from `docs/`; releases happen in `gem/`. +- Don't bump the gem version from `docs/`; `RubyUI::VERSION` lives in `gem/lib/ruby_ui.rb` and the gem is published from `gem/`. (The release PR also reflects the version into `docs/` and `mcp/` — see [Releasing](#releasing).) +- Don't call a release done after only publishing the gem — tag `vX.Y.Z` and reflect the version on the website too. - Don't commit secrets; each app uses local env config. From d5d90d4046a81ed6f2d18922e7e7e09f95dea809 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Djalma=20Ara=C3=BAjo?= Date: Tue, 23 Jun 2026 13:59:45 -0300 Subject: [PATCH 2/4] [Documentation] Generalize gem owner check, drop hardcoded username --- CLAUDE.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CLAUDE.md b/CLAUDE.md index 8f4f3070..238e3a46 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -56,7 +56,7 @@ Decide the bump with SemVer against commits since the last `vX.Y.Z` tag: new bac 1. **Bump the version (gem).** Edit `RubyUI::VERSION` in `gem/lib/ruby_ui.rb`. Then from each app dir regenerate lockfiles so the path dependency tracks the new version: `gem/Gemfile.lock` and `docs/Gemfile.lock` should both read `ruby_ui (X.Y.Z)`. -2. **Publish the gem to RubyGems.** From `gem/`: `gem build ruby_ui.gemspec` then `gem push ruby_ui-X.Y.Z.gem`. The account has **MFA**, so `gem push` prompts for a one-time password — have the OTP ready (or pass `--otp `). Confirm `djalmaaraujo` is in `gem owner ruby_ui` first. Do not commit the built `.gem` artifact. +2. **Publish the gem to RubyGems.** From `gem/`: `gem build ruby_ui.gemspec` then `gem push ruby_ui-X.Y.Z.gem`. The account has **MFA**, so `gem push` prompts for a one-time password — have the OTP ready (or pass `--otp `). Confirm the publishing account is listed in `gem owner ruby_ui` first. Do not commit the built `.gem` artifact. 3. **Reflect the version on the docs website (PR against `main`).** Releases go through a `[Release] vX.Y.Z` PR (main is protected — no direct pushes). The PR bundles, on a `release/vX.Y.Z` branch: - the `gem/lib/ruby_ui.rb` bump + both regenerated `Gemfile.lock`s; From 79c8daba5760ec9c01949c3931d5fafbe91707e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Djalma=20Ara=C3=BAjo?= Date: Tue, 23 Jun 2026 14:07:38 -0300 Subject: [PATCH 3/4] [Documentation] Add X.com announcement share link as final release step --- CLAUDE.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/CLAUDE.md b/CLAUDE.md index 238e3a46..d0e26063 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -65,6 +65,22 @@ Decide the bump with SemVer against commits since the last `vX.Y.Z` tag: new bac 4. **Tag + GitHub release.** After the release PR merges, tag `vX.Y.Z` on the merge commit, push the tag, and cut the GitHub release. The git tag and the published gem must both exist — publishing the gem without tagging (or vice versa) is an incomplete release. +5. **Hand over the announcement URL (final step).** As the last step, give the user a ready-to-post X.com (Twitter) share link for the RubyUI account — the user posts it manually. Use the prefilled-tweet intent URL with the body URL-encoded: + + ``` + https://x.com/intent/post?text=RubyUI%20X.Y%20released%21%20%F0%9F%9A%80%0A%0Ahttps%3A%2F%2Fwww.rubyui.com%2Fdocs%2Fchangelog + ``` + + which decodes to: + + ``` + RubyUI X.Y released! 🚀 + + https://www.rubyui.com/docs/changelog + ``` + + Substitute the real `X.Y` (e.g. `1.4`) in the encoded `text`. Output the link so the user can open and post it. + ## Commits & PRs - Bracketed prefixes (`[Feature]`, `[Bug Fix]`, `[Documentation]`) or scoped conventional (`feat(scope): ...`). From eef3e8fe7c9faba5f2c6e0c95ce1b236f7ff2a99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Djalma=20Ara=C3=BAjo?= Date: Tue, 23 Jun 2026 14:19:03 -0300 Subject: [PATCH 4/4] [Documentation] Use full X.Y.Z in release announcement so patches get posted --- CLAUDE.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/CLAUDE.md b/CLAUDE.md index d0e26063..e6a36262 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -68,18 +68,18 @@ Decide the bump with SemVer against commits since the last `vX.Y.Z` tag: new bac 5. **Hand over the announcement URL (final step).** As the last step, give the user a ready-to-post X.com (Twitter) share link for the RubyUI account — the user posts it manually. Use the prefilled-tweet intent URL with the body URL-encoded: ``` - https://x.com/intent/post?text=RubyUI%20X.Y%20released%21%20%F0%9F%9A%80%0A%0Ahttps%3A%2F%2Fwww.rubyui.com%2Fdocs%2Fchangelog + https://x.com/intent/post?text=RubyUI%20X.Y.Z%20released%21%20%F0%9F%9A%80%0A%0Ahttps%3A%2F%2Fwww.rubyui.com%2Fdocs%2Fchangelog ``` which decodes to: ``` - RubyUI X.Y released! 🚀 + RubyUI X.Y.Z released! 🚀 https://www.rubyui.com/docs/changelog ``` - Substitute the real `X.Y` (e.g. `1.4`) in the encoded `text`. Output the link so the user can open and post it. + Substitute the real full `X.Y.Z` (e.g. `1.4.0`) in the encoded `text` — always include all three numbers so patch releases get announced too. Output the link so the user can open and post it. ## Commits & PRs