Android / Build, or is the channel already serving this? (push) Successful in 3s
CI & Build / Build now, or wait for Android? (push) Successful in 3s
CI & Build / Python lint (push) Successful in 4s
Desktop (Tauri) / Build, or is the channel already serving this? (push) Successful in 4s
CI & Build / TypeScript typecheck (push) Successful in 7s
CI & Build / Python tests (push) Successful in 12s
CI & Build / integration (push) Successful in 18s
CI & Build / Build & push image (push) Skipped
Desktop (Tauri) / Windows installer (cross-compiled) (push) Successful in 3m0s
Desktop (Tauri) / Tauri desktop (Linux) (push) Successful in 5m17s
Desktop (Tauri) / Update manifest (push) Successful in 4s
Android / Kotlin + Rust (APK) (push) Successful in 8m4s
Step 7 of M314, the last one. Rule 22 — the old path comes out completely. ## A release stops building `desktop.yml` no longer triggers on `v*`, and its two `Publish release` steps are gone. `ci.yml` lost its tag trigger in step 6. So a tag now reaches exactly one lane: the new `release.yml`, which builds nothing. That is not a simplification for its own sake. The merge to `main` already published everything a user can receive — `:latest` + `:<sha>`, both channel feeds, the updater manifest. A tag rebuilding that source produces identical artifacts under identical names and re-pushes `:<sha>` with different bytes, which rule 145 forbids even when they match. ## So what a release is FOR The changelog (note 3127 §5). Two halves to "what am I running", and the version answers only the first: which build is this (the footer, /api/config, the APK's versionName) and what is in it that was not in the one I ran last month (nothing, until now). `packaging/release-notes.sh` derives it from git rather than a hand-maintained CHANGELOG, which drifts into recording what someone MEANT to ship. Capped at 60 entries with the omitted count stated — the first dated release spans 181 commits since `v0.1.0`, and a truncated list that does not say it is truncated is a lie. It publishes through `publish-release.sh` rather than making its own API calls, for the create-or-PATCH-on-409 path: a fixed-tag release that only ever POSTs keeps whatever body its first run wrote, which is #2182, and reimplementing that correctly in a second place is how it comes back. ## Retired `MANIFEST_TAG` and the whole branch behind it. It let the manifest live on a `stable` pointer release while the bundles sat on a versioned one — a split step 3 removed when `stable` started holding its own bundles. Nothing had passed it since; a parameter that can only ever receive its own default is a branch nobody exercises and a comment that goes stale, and its stale text was still telling readers the installable builds live on the versioned releases. `desktop/src-tauri/Cargo.toml`'s version and `thoughtsync/__init__.py`'s both now say out loud that they are not shipped values. The Cargo one carries the history worth keeping: the old scheme took its base from that line, so `0.2.<run>` on dev outranked a bare `0.2.0` on main, and the remedy was "remember to bump the minor before tagging" — documented in a comment, enforced nowhere. #2183 is what that looked like in the field. **That ritual is now formally dead**, and this is the deliberate act of killing it rather than a side effect. ## Still there on purpose `install.sh`'s transitional stable fallback. It cannot go until `main` has published to `stable` at least once, and that is gated on an operator request. Removing it now would break the DEFAULT install channel. #3147 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
80 lines
3.3 KiB
Bash
Executable File
80 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env sh
|
|
#
|
|
# The markdown body for a release: what went live since the previous one.
|
|
#
|
|
# release-notes.sh <tag>
|
|
#
|
|
# A release BUILDS NOTHING now (M314 step 7). The merge to `main` already published
|
|
# `:latest`, `:<sha>` and both channel feeds, so a tag rebuilding that same source
|
|
# would produce identical artifacts and re-push `:<sha>` with different bytes —
|
|
# which rule 145 forbids even when the bytes match.
|
|
#
|
|
# So what is a release FOR? Note 3127 §5 answers it: the changelog. There are two
|
|
# halves to "what am I running" and the version answers only the first —
|
|
#
|
|
# which build is this the footer, /api/config, the APK's versionName
|
|
# what is in it that was not ← this
|
|
# in the one I ran last month
|
|
#
|
|
# DERIVED FROM GIT, not hand-maintained. A CHANGELOG.md drifts into being
|
|
# aspirational — it records what someone meant to ship. `git log` records what
|
|
# shipped, and cannot say otherwise.
|
|
set -eu
|
|
|
|
cd "$(git rev-parse --show-toplevel)"
|
|
|
|
tag="${1:?usage: release-notes.sh <tag>}"
|
|
|
|
# The previous release tag, by DATE rather than by name.
|
|
#
|
|
# `v*` only: this repo also carries `dev` and `stable` tags, which are the fixed-tag
|
|
# pointer releases the updater reads. They move constantly and are not releases in
|
|
# this sense; sorting them in would make "the previous release" mean whichever
|
|
# channel published most recently.
|
|
#
|
|
# Excludes the tag being described, so re-running on an existing tag still produces
|
|
# the range that tag covers rather than an empty one.
|
|
prev="$(git tag -l 'v*' --sort=-creatordate | grep -vxF "$tag" | head -1 || true)"
|
|
|
|
if [ -n "$prev" ]; then
|
|
range="$prev..$tag"
|
|
header="Changes since \`$prev\`."
|
|
else
|
|
# The first release. Everything is new, and listing the entire history would be
|
|
# noise — say so instead.
|
|
range="$tag"
|
|
header="First release."
|
|
fi
|
|
|
|
printf 'ThoughtSync %s\n\n%s\n\n' "$tag" "$header"
|
|
|
|
# `--no-merges`: a merge commit's subject is "Merge branch ..." and says nothing
|
|
# about what shipped. The commits it brought in are listed individually, which is
|
|
# what somebody reading this wants.
|
|
#
|
|
# `%s` alone, not `%s (%h)`: the sha is in the forge's own view of the release and
|
|
# a reader chasing a specific change clicks through rather than copying a hash out
|
|
# of prose.
|
|
# CAPPED, because an unbounded list is not a changelog — it is a wall.
|
|
#
|
|
# The first dated release spans everything since `v0.1.0` — 181 commits at the
|
|
# time of writing: nobody reads that, and burying twelve interesting changes in it is worse
|
|
# than not writing one. Later releases will be short and the cap will never bite.
|
|
#
|
|
# The most RECENT are kept, not the oldest, and the count of what was dropped is
|
|
# stated — a truncated list that does not say it is truncated is a lie.
|
|
CAP=60
|
|
total="$(git log --no-merges --format='%s' "$range" | wc -l | tr -d ' ')"
|
|
|
|
git log --no-merges --reverse --format='- %s' "$range" | tail -"$CAP"
|
|
|
|
if [ "$total" -gt "$CAP" ]; then
|
|
printf '\n_...and %s earlier commits in this range, omitted for length._\n' \
|
|
"$((total - CAP))"
|
|
fi
|
|
|
|
printf '\n'
|
|
printf '%s\n' "_No artifacts here. Builds reach users from \`main\`: the desktop and Android"
|
|
printf '%s\n' "channels and the server image all publish on merge, with no tag required. This"
|
|
printf '%s\n' "release is a bookmark — it names a moment and says what was in it._"
|