Slice 2 of the self-update story. Tagging a release on main now produces a downloadable self-update payload on the Forgejo releases page, and a running box can pull it down, verify it, atomically swap to the new version, and health-check the result. New pieces: - scripts/build-release-tarball.sh <version> — packages the furtka/ package + bundled apps/ + a root-level VERSION file as dist/furtka-<version>.tar.gz, plus a .sha256 sidecar and a release.json metadata blob. - scripts/publish-release.sh <version> — uses the Forgejo v1 API to create a release (body pulled from the CHANGELOG section for this tag, pre-release auto-flagged on -alpha/-beta/-rc) and upload the three assets sequentially. Needs \$FORGEJO_TOKEN. - .forgejo/workflows/release.yml — tag-triggered, runs both scripts with the new \$FORGEJO_RELEASE_TOKEN repo secret. - furtka/updater.py — check_update, prepare_update, apply_update, run_update, rollback. Atomic symlink swap, sha256 verify (TOCTOU- safe: re-hashes on-disk file), health-check post-restart with auto-rollback on failure, stage-by-stage progress persisted to /var/lib/furtka/update-state.json so the UI can poll independent of the (restarting) API process. Path overrides via FURTKA_ROOT / FURTKA_STATE_DIR / FURTKA_LOCK_PATH so tests pin a tmpdir. - furtka/cli.py — \`furtka update [--check] [--json]\` and \`furtka rollback\`. - tests/test_updater.py — 15 tests: version compare, sha256 verify, tarball extract (including traversal refusal), lockfile, apply happy + rollback paths, rollback CLI, check_update with stubbed Forgejo. - iso/build.sh — writes VERSION at the tarball root so the install path matches the self-update path (previously assumed only the release script did this). RELEASING.md now points at the automated flow — no more manually clicking "Create release" on the Forgejo UI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2.8 KiB
Releasing
Furtka uses calendar versioning: YY.N-stage — e.g. 26.0-alpha is 2026, release 0, alpha stage. No v prefix.
YY— last two digits of the current yearN— incrementing release number within the year, starting at 0 (next one in 2026 is26.1-alpha, then26.2-alpha…)-alpha— drop it when the installer boots end-to-end and wipe-and-reinstall is safe
When the year rolls over, the next release becomes 27.0-alpha regardless of how many 26.x releases shipped.
Cadence
Tag per meaningful milestone, not on a calendar. A milestone is: ISO boots, a wizard screen works end-to-end, managed gateway serves its first real domain, etc. If a week goes by with no tag, that's fine — no tag is better than a noisy one.
Release steps
-
Move
[Unreleased]inCHANGELOG.mdto a new version heading.## [Unreleased] ## [26.1-alpha] - 2026-05-20 ### Added - ...Add a
[26.1-alpha]link definition at the bottom:[26.1-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.1-alphaUpdate the
[Unreleased]compare link to point at the new tag. -
Commit the changelog.
git add CHANGELOG.md git commit -m "chore: release 26.1-alpha" -
Tag the commit.
git tag -a 26.1-alpha -m "Release 26.1-alpha" -
Push the tag and main.
git push origin main git push origin 26.1-alpha -
The release workflow does the rest.
.forgejo/workflows/release.ymlfires on the tag push:scripts/build-release-tarball.shbuilds the self-update payload (tarball + sha256 + release.json underdist/),scripts/publish-release.shuploads all three assets to the Forgejo release page. Pre-release is flagged automatically based on the suffix (-alpha/-beta/-rc).The release workflow needs one secret set at repo Settings → Secrets → Actions:
FORGEJO_RELEASE_TOKEN— a PAT withwrite:repositoryscope.
-
Verify CI passed on the tag. The Forgejo Actions run against the tagged commit should be green before you announce the release anywhere — both the CI workflow (lint/test) and the Release workflow (tarball published).
-
(Optional) Dogfood the update path. On a VM running the previous version,
sudo furtka update --checkshould now see the new tag, andsudo furtka updateapplies it without a reinstall.
First-time: find the current version
git describe --tags --abbrev=0
If the project is fresh and git describe fails, the next release is 26.0-alpha.
If the tag is wrong
Don't move published tags. Delete the release + tag, fix the problem, bump to the next number.
git tag -d 26.1-alpha
git push origin :refs/tags/26.1-alpha
# ... fix ...
git tag -a 26.2-alpha ...