scope: a real beta loop for caldav-mcp, and where the prerelease version comes from #13

Closed
opened 2026-08-26 05:35:32 +00:00 by jlxq0 · 0 comments
Owner

Scope only. No change proposed for merge until the two decisions below are made.

Context is #9: this repo has no beta path in CI, v0.1.1-beta.e1ad86b was cut
by hand, and its sha suffix cannot match the platform's
clusters/fondue/*-beta/** Renovate rule, which requires
-(beta|alpha)\.\d+$. I cut v0.1.2-beta.20260826052605 by hand on 2026-08-26
to unstick it. That is a patch, not the loop.

The house mechanism, read rather than remembered

oddie-apps/lenno_web is the reference. .forgejo/workflows/ci.yml triggers on
push to alpha, beta, main and on v* tags; the image job runs only for
refs/heads/beta, refs/heads/alpha and refs/tags/v*. The version comes from
bin/ci-version, and the part that matters here is that it does not read the
manifest version at all
:

  • BASE_TAG = highest v<major>.<minor>.<patch> git tag.
  • BUMP = conventional-commit analysis of BASE_TAG..HEAD — a !: subject or
    BREAKING CHANGE: body gives major, a feat: subject gives minor, anything
    else gives patch.
  • VERSION = <bumped base>-beta.<UTC YYYYMMDDHHMMSS>.

With this comment against the patch default, verbatim:

Release-please may ignore pure docs/chore commits, but beta/alpha images are
deployable artifacts. Any post-release artifact should sort after the stable
version it is intended to replace.

That is exactly the cost I named when cutting v0.1.2-beta.<ts> by hand: it
sorts below the released 0.1.2. The house scheme bumps first so the beta
sorts above the release it replaces.

Decision 1: does Cargo.toml carry the next version between releases?

No, on the evidence. lenno_web derives the prerelease version from the
latest stable git tag and never from mix.exs. Porting that here keeps this
repo's existing convention — Cargo.toml is bumped at release time by a
chore(release): prepare vX.Y.Z commit — untouched, and removes the reason to
change it.

The consequence is that CI's guard has to move. Today:

if [[ "$VERSION" != "$BASE_VERSION" && "$VERSION" != "$BASE_VERSION"-* ]]; then
  echo "tag version ${VERSION} does not match Cargo version ${BASE_VERSION}" >&2

A derived 0.1.3-beta.<ts> fails that against a Cargo.toml reading 0.1.2,
which is the whole reason the hand-cut tag had to be 0.1.2-beta.<ts>. The
guard is worth keeping for stable v* tags — it is what stops a release tag
naming a version the binary does not report — and worth not applying to a
derived beta version, which by construction has no manifest to agree with.

Decision 2: does this apply to the other four MCP servers?

caldav-mcp-beta is the only *-beta namespace among the five MCP servers in
fondue. Either it is a pilot and the other four follow, or it is a one-off and
the loop should be built no larger than this repo. The work below is written for
one repo; a decision to do all five changes what "port bin/ci-version" should
produce (a copied script per repo, consistent with the no-shared-crate decision
in #3).

The work, if both are settled

  1. Add beta to the workflow's push.branches.
  2. Add bin/ci-version — a port of lenno_web's, minus the release-please
    assumptions. Same three-step derivation, same timestamp suffix.
  3. Split the version guard: keep it for refs/tags/v*, skip it for
    refs/heads/beta.
  4. Give the beta ref PUSH=true, tags v${VERSION} and sha-${short}, and
    no latest — the existing *-* check already covers that.
  5. Buildcache: beta imports and does not export. #8 made main the only
    writer to :buildcache after two concurrent writers failed a run whose image
    had already been pushed. A beta-branch build exporting to the same ref
    reintroduces that race with a branch that will often be pushed alongside
    main. Import-only costs a partial cache hit when beta has diverged, which
    is the cheaper side of that trade.
  6. Nothing changes in oddie-apps/platform. The *-beta rule already matches
    -beta.<digits>, has ignoreUnstable: false, minimumReleaseAge: null and
    automerge: true, so a conforming tag flows without touching that repo.
  7. Retire the hand-cut tag once the loop mints its own.

What this costs

A second long-lived branch to keep in sync with main, and a full cargo job
plus a docker build on every push to it.

Not in scope

The stable release flow, the main build, and anything about the other four
oauth_redirect.rs copies (#3).

Scope only. No change proposed for merge until the two decisions below are made. Context is #9: this repo has no beta path in CI, `v0.1.1-beta.e1ad86b` was cut by hand, and its sha suffix cannot match the platform's `clusters/fondue/*-beta/**` Renovate rule, which requires `-(beta|alpha)\.\d+$`. I cut `v0.1.2-beta.20260826052605` by hand on 2026-08-26 to unstick it. That is a patch, not the loop. ## The house mechanism, read rather than remembered `oddie-apps/lenno_web` is the reference. `.forgejo/workflows/ci.yml` triggers on `push` to `alpha`, `beta`, `main` and on `v*` tags; the image job runs only for `refs/heads/beta`, `refs/heads/alpha` and `refs/tags/v*`. The version comes from `bin/ci-version`, and the part that matters here is that **it does not read the manifest version at all**: - `BASE_TAG` = highest `v<major>.<minor>.<patch>` git tag. - `BUMP` = conventional-commit analysis of `BASE_TAG..HEAD` — a `!:` subject or `BREAKING CHANGE:` body gives major, a `feat:` subject gives minor, anything else gives patch. - `VERSION` = `<bumped base>-beta.<UTC YYYYMMDDHHMMSS>`. With this comment against the patch default, verbatim: > Release-please may ignore pure docs/chore commits, but beta/alpha images are > deployable artifacts. Any post-release artifact should sort after the stable > version it is intended to replace. That is exactly the cost I named when cutting `v0.1.2-beta.<ts>` by hand: it sorts *below* the released `0.1.2`. The house scheme bumps first so the beta sorts above the release it replaces. ## Decision 1: does `Cargo.toml` carry the next version between releases? **No, on the evidence.** `lenno_web` derives the prerelease version from the latest stable *git tag* and never from `mix.exs`. Porting that here keeps this repo's existing convention — `Cargo.toml` is bumped at release time by a `chore(release): prepare vX.Y.Z` commit — untouched, and removes the reason to change it. The consequence is that CI's guard has to move. Today: ```bash if [[ "$VERSION" != "$BASE_VERSION" && "$VERSION" != "$BASE_VERSION"-* ]]; then echo "tag version ${VERSION} does not match Cargo version ${BASE_VERSION}" >&2 ``` A derived `0.1.3-beta.<ts>` fails that against a `Cargo.toml` reading `0.1.2`, which is the whole reason the hand-cut tag had to be `0.1.2-beta.<ts>`. The guard is worth keeping for stable `v*` tags — it is what stops a release tag naming a version the binary does not report — and worth not applying to a derived beta version, which by construction has no manifest to agree with. ## Decision 2: does this apply to the other four MCP servers? `caldav-mcp-beta` is the only `*-beta` namespace among the five MCP servers in `fondue`. Either it is a pilot and the other four follow, or it is a one-off and the loop should be built no larger than this repo. The work below is written for one repo; a decision to do all five changes what "port `bin/ci-version`" should produce (a copied script per repo, consistent with the no-shared-crate decision in #3). ## The work, if both are settled 1. Add `beta` to the workflow's `push.branches`. 2. Add `bin/ci-version` — a port of `lenno_web`'s, minus the release-please assumptions. Same three-step derivation, same timestamp suffix. 3. Split the version guard: keep it for `refs/tags/v*`, skip it for `refs/heads/beta`. 4. Give the beta ref `PUSH=true`, tags `v${VERSION}` and `sha-${short}`, and **no `latest`** — the existing `*-*` check already covers that. 5. **Buildcache: beta imports and does not export.** #8 made `main` the only writer to `:buildcache` after two concurrent writers failed a run whose image had already been pushed. A beta-branch build exporting to the same ref reintroduces that race with a branch that will often be pushed alongside `main`. Import-only costs a partial cache hit when `beta` has diverged, which is the cheaper side of that trade. 6. Nothing changes in `oddie-apps/platform`. The `*-beta` rule already matches `-beta.<digits>`, has `ignoreUnstable: false`, `minimumReleaseAge: null` and `automerge: true`, so a conforming tag flows without touching that repo. 7. Retire the hand-cut tag once the loop mints its own. ## What this costs A second long-lived branch to keep in sync with `main`, and a full `cargo` job plus a docker build on every push to it. ## Not in scope The stable release flow, the `main` build, and anything about the other four `oauth_redirect.rs` copies (#3).
jlxq0 closed this issue 2026-08-26 07:48:22 +00:00
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
jlxq0/caldav-mcp#13
No description provided.