Skip to content
Back to skills

Usage Monitor Release Beta

ASecurity

Beta channel of usage-monitor — publish a vX.Y.Z-beta.N prerelease for opted-in users, fix it with the next beta, promote the series to stable, or withdraw/restore a beta. Use for any beta release task; plain stable releases use usage-monitor-release.

  • 13 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added September 29, 2026
ai-agentsgorailsgitapi

Works with

  • cli
  • api

Security analysis

A100/100

Scanned September 29, 2026

npx -y skills add edilsonvilarinho/usage-monitor --skill usage-monitor-release-beta --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Usage Monitor Release Beta?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Usage Monitor Release Beta
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/edilsonvilarinho-usage-monitor-release-beta/badge)](https://www.skillsdirectory.com/skills/edilsonvilarinho-usage-monitor-release-beta)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: usage-monitor-release-beta
description: Beta channel of usage-monitor — publish a vX.Y.Z-beta.N prerelease for opted-in users, fix it with the next beta, promote the series to stable, or withdraw/restore a beta. Use for any beta release task; plain stable releases use usage-monitor-release.
---

# Usage Monitor Beta Release

Run the whole life of a beta for the users who opted into the beta channel (issue #355). Publishing
is the stable release flow ([usage-monitor-release](../usage-monitor-release/SKILL.md)) with a
different tag and a different promise: **a beta never becomes `latest`**, so nobody outside the
channel receives it.

## Operations (the argument picks one)

| Argument | What it does | Section |
|---|---|---|
| `patch` / `minor` / `major` | Publish `beta.1` of a new series for the next stable of that type | Workflow |
| `next` | Publish `beta.N+1` of the open series (the way to **fix** a bad beta) | Workflow |
| `promote` | Publish the stable `vX.Y.Z` of the open series — the beta "goes to main/master" | Promote |
| `withdraw [tag]` | Hide a beta: nobody new is offered it (reversible) | Withdraw |
| `restore [tag]` | Undo a `withdraw` | Restore |

There is **no "move the beta to main"**: the tag already points to a commit on `main` —
`verify-version` refuses anything else. The code is merged *before* the beta exists; what "going to
stable" means is publishing a new, stable build of that code (`promote`). There is also **no
rollback** for testers who already installed a beta: the app never downgrades. They leave the beta
when a higher version reaches them — the next beta or the stable.

## How the channel works (read before tagging)

- Tag format: `vX.Y.Z-beta.N`, `N ≥ 1`. Nothing else is accepted — `verify-version` rejects
  `-rc.1`, `-beta` without a number and any other suffix, and the Linux updater refuses them too.
- The workflow sets `prerelease: true` and `make_latest: false` for `-beta.N` tags. Clients outside
  the channel read `/releases/latest`, which the GitHub API never answers with a prerelease — that is
  the whole protection, and it also covers app versions older than the channel.
- Clients inside the channel list `/releases?per_page=20` and take the highest non-draft version by
  SemVer precedence: `42.0.0-beta.1 < 42.0.0-beta.2 < 42.0.0`. The stable `42.0.0` therefore reaches
  every beta tester of the `42.0.0` series. Turning the channel off never downgrades.
- `X.Y.Z` is the **next stable** version the beta previews. Never tag a beta for a number that is
  already released as stable: `41.0.0-beta.1` after `v41.0.0` is lower than the running stable and is
  never offered to anyone.
- Packaging: Exe/Dmg carry only `X.Y.Z` (jpackage rejects the suffix), Deb/Rpm carry `X.Y.Z~beta.N`;
  `CURRENT_APP_VERSION`, the NSIS installer name, the tarball and the release assets keep the full
  `X.Y.Z-beta.N`.

## Workflow

1. Read [AGENTS.md](../../../AGENTS.md), [build.gradle.kts](../../../build.gradle.kts) and
   [.github/workflows/release-linux.yml](../../../.github/workflows/release-linux.yml) first.
2. Invoking this skill already means "cut and publish the beta". Do not ask for confirmation to tag or
   push — go through the whole flow and report the result. The only question allowed is the one in
   step 6 (window hosts).
3. Pick the operation from the request (see the table above). `promote`, `withdraw` and `restore`
   have their own sections below; this workflow is for publishing a beta:
   - `patch` / `minor` / `major` — start a new series for the next stable of that type:
     `N = 1`.
   - `next` (or no type while a series is open) — continue the open series: `N + 1`.
   - If the request is ambiguous and there is no open series, ask which type.
   - An **open series** is `vX.Y.Z-beta.*` with no stable `vX.Y.Z` yet.
4. Verify that `main` is clean and matches `origin/main` — the tag must point to a commit already on
   the remote `main`, or `verify-version` refuses it:
   - `git fetch origin --tags && git status --short --branch`
   - `git log --oneline -5`
5. Compute the version. **There is no version bump commit** — the version comes from the tag.
   - Last stable: `git describe --tags --abbrev=0 --match "v[0-9]*" --exclude "*-beta*"`.
   - Betas of the series: `git tag --list "vX.Y.Z-beta.*"`, highest `N` by numeric sort
     (`git -c versionsort.suffix=- tag --sort=-version:refname --list "vX.Y.Z-beta.*" | head -n 1`).
   - New series: `X.Y.Z` = last stable bumped by the type; refuse if `vX.Y.Z` already exists.
   - Continue: same `X.Y.Z`, `N + 1`; refuse if the stable `vX.Y.Z` already exists (the series is
     closed — start a new one).
6. Run the local verification that must pass before the tag exists:
   - `gradlew.bat allTests` — mandatory. A beta is still a public tag; a broken suite discovered after
     the push is a burned tag.
   - **Window hosts changed? Stop before the tag** (#342), exactly as in the stable skill: run
     `git diff --name-only $(git describe --tags --abbrev=0)..HEAD` and look for `HudWindow.kt`,
     `DesktopWindowFrame.kt`, `Main.kt` or any `*WindowHost*.kt`. If one changed, list the rows of
     [`docs/hud-notch.md` › "Fora do alcance dos testes"](../../../docs/hud-notch.md#fora-do-alcance-dos-testes)
     the change touches and ask the maintainer whether the build was opened on Linux (X11). A beta is
     a good place to *find* such bugs, but the testers still run it as their daily app.
   - Do not package locally as a gate; CI owns packaging for the three OSes.
7. Publish:
   - annotated tag with the temporary agent git identity:
     `git -c user.name=claude -c user.email=claude@anthropic.com tag -a vX.Y.Z-beta.N -m "vX.Y.Z-beta.N"`
   - push **only the tag**: `git push origin vX.Y.Z-beta.N`.
8. Watch `Release Desktop Packages` and report the outcome. Then confirm on the published release:
   - it is marked **Pre-release**:
     `gh release view vX.Y.Z-beta.N --json isPrerelease` → `true` (`gh` has no `isLatest` field);
   - it is **not** Latest — `/releases/latest` still points to the last stable:
     `gh api repos/edilsonvilarinho/usage-monitor/releases/latest --jq .tag_name`;
   - every artifact family is there, each with a `sha256:` digest (auto-update refuses assets without it):
     `UsageMonitor-Setup-X.Y.Z-beta.N.exe`; `.deb`, `.rpm` and `usage-monitor_X.Y.Z-beta.N_linux_x64.tar.gz`;
     `usage-monitor_X.Y.Z-beta.N_macos_arm64.dmg` and `usage-monitor_X.Y.Z-beta.N_macos_x64.dmg`.
     `gh release view vX.Y.Z-beta.N --json assets --jq '.assets[] | [.name, .digest] | @tsv'`
   A beta missing an artifact family, or published as Latest, is a failed release and must be reported
   as such. If it went out as Latest, edit it back with
   `gh release edit vX.Y.Z-beta.N --prerelease --latest=false` and report it — every user outside the
   channel was being offered the beta.
9. The release notes come from the workflow's `Generate release notes` step: a beta diffs against the
   previous tag (beta or stable); the stable release later diffs against the previous **stable**, so it
   lists the whole series. Do not write them by hand.

## Promote — the open series becomes the stable release

The stable is a **new tag and a new build**, never the beta release edited into a stable one. The beta
binaries carry `X.Y.Z-beta.N` in `CURRENT_APP_VERSION`, in the installer name and in the receipt; an
edited release would hand every user a build that calls itself beta. Never run
`gh release edit ... --prerelease=false` or `--latest` on a beta.

1. Find the open series: `git -c versionsort.suffix=- tag --sort=-version:refname --list "v*-beta.*" | head -n 1`
   gives `vX.Y.Z-beta.N`. Refuse if `vX.Y.Z` already exists (nothing to promote) or if there is no
   beta tag.
2. Decide **what** becomes stable:
   - default — the current `origin/main` (the beta code plus whatever was merged after it). Say in
     the report which commits are new since the last beta:
     `git log --oneline vX.Y.Z-beta.N..origin/main`.
   - `promote exact` — the very commit the testers ran: tag `vX.Y.Z` on `vX.Y.Z-beta.N^{commit}`.
     `verify-version` accepts it, because that commit is on `main`.
3. Run the stable flow of [usage-monitor-release](../usage-monitor-release/SKILL.md) from its step 4
   (clean `main` = `origin/main`, `allTests`, the #342 window-host question, annotated tag, push only
   the tag, watch the workflow, check every artifact) with the version fixed to `X.Y.Z` — do **not**
   bump it by type. For `promote exact`, create the tag on the beta commit:
   `git -c user.name=claude -c user.email=claude@anthropic.com tag -a vX.Y.Z vX.Y.Z-beta.N^{commit} -m "vX.Y.Z"`.
4. Confirm: `gh release view vX.Y.Z --json isPrerelease` → `false`, and `/releases/latest` → `vX.Y.Z`.
   The stable notes diff against the previous **stable**, so they list the whole beta series.
5. Result: users outside the channel receive `X.Y.Z` as a normal update; testers on
   `X.Y.Z-beta.N` receive it too (`beta.N < X.Y.Z`) and see its "Novidades". The series is closed —
   the next beta starts a new one.

## Withdraw — a bad beta stops being offered

Withdrawing **hides** the release; it does not delete anything and it is reversible (`restore`).
The client ignores drafts, and anonymous API calls — the ones the app makes — do not see them.

1. Target: the tag in the request, or the highest `v*-beta.*`. Refuse a stable tag: withdrawing a
   stable is not this skill's job.
2. `gh release edit vX.Y.Z-beta.N --repo edilsonvilarinho/usage-monitor --draft=true`
3. Confirm it is hidden from what the app reads:
   `gh api "repos/edilsonvilarinho/usage-monitor/releases?per_page=20" --jq '.[] | select(.draft == false) | .tag_name'`
   must not list it (this call is authenticated and sees drafts only with `draft: true`), and
   `/releases/latest` is unchanged.
4. Report what it does **not** undo, every time:
   - testers who already installed that beta **stay on it** — there is no downgrade. They move when a
     higher version reaches them;
   - an auto-update already downloaded but not yet applied is still applied on the next exit.
5. What to do next — say it in the report:
   - **fix forward** (the normal path): merge the fix and run this skill with `next` —
     `vX.Y.Z-beta.N+1` is offered to everyone in the channel, including those stuck on the bad one;
   - **abandon the series**: `promote` a stable that does not include the bad change, or start a new
     series later. Never reuse a withdrawn tag name — a client may already know it.
6. The tag stays on the remote. Deleting the release or the tag (`gh release delete --cleanup-tag`)
   is permanent and **not** part of this skill: it gains nothing over the draft and loses the record.
   If the maintainer really wants it, tell them the command and let them run it.

## Restore — undo a withdraw

1. `gh release edit vX.Y.Z-beta.N --repo edilsonvilarinho/usage-monitor --draft=false --prerelease --latest=false`
   — the three flags together, so it comes back exactly as a beta and never as Latest.
2. Confirm `isPrerelease: true`, `/releases/latest` unchanged, and that the channel sees it again
   (the non-draft listing above lists it).
3. If a newer beta or the stable of the series already exists, restoring an older beta changes nothing
   for anyone — say so instead of restoring.

## Guardrails

- Never publish a stable version from this skill except through `promote`, which runs the stable
  flow of `usage-monitor-release` with the version fixed to the open series.
- Never turn a beta release into a stable or Latest one by editing it; `restore` always passes
  `--prerelease --latest=false`.
- Never delete a release or a tag; `withdraw` hides it as a draft.
- Never tag a suffix other than `-beta.N`.
- Never tag a beta whose `X.Y.Z` is already released as stable.
- Do not release from a dirty tree unless the user explicitly wants that risk.
- Do not ask the user to confirm the tag or the push; the one exception is step 6 (#342).
- Prefer current code and workflow files over older notes when they disagree.

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.