docs: add changelog, contributor guide, release process, and runner setup
- CHANGELOG.md: Keep-a-Changelog format, [26.0-alpha] entry covering
everything shipped so far (installer webapp, drive scoring, base
archinstall config, wireframes, competitor analysis, wizard flow spec)
- CONTRIBUTING.md: dev setup, conventional commit format, code style
- RELEASING.md: calendar versioning rules (YY.N-stage, no "v" prefix)
and the release workflow (bump changelog, commit, tag, push, create
Forgejo Release)
- docs/runner-setup.md: install + register a forgejo-runner so the
upcoming CI workflow actually executes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:23:48 +02:00
# Releasing
2026-04-13 21:43:34 +02:00
Furtka uses calendar versioning: ** `YY.N-stage` ** — e.g. `26.0-alpha` is 2026, release 0, alpha stage. No `v` prefix.
docs: add changelog, contributor guide, release process, and runner setup
- CHANGELOG.md: Keep-a-Changelog format, [26.0-alpha] entry covering
everything shipped so far (installer webapp, drive scoring, base
archinstall config, wireframes, competitor analysis, wizard flow spec)
- CONTRIBUTING.md: dev setup, conventional commit format, code style
- RELEASING.md: calendar versioning rules (YY.N-stage, no "v" prefix)
and the release workflow (bump changelog, commit, tag, push, create
Forgejo Release)
- docs/runner-setup.md: install + register a forgejo-runner so the
upcoming CI workflow actually executes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:23:48 +02:00
- `YY` — last two digits of the current year
- `N` — incrementing release number within the year, starting at 0 (next one in 2026 is `26.1-alpha` , then `26.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
1. **Move `[Unreleased]` in `CHANGELOG.md` to a new version heading.**
```markdown
## [Unreleased]
## [26.1-alpha] - 2026-05-20
### Added
- ...
```
Add a `[26.1-alpha]` link definition at the bottom:
```markdown
2026-04-13 21:43:34 +02:00
[26.1-alpha]: https://forgejo.sourcegate.online/daniel/furtka/releases/tag/26.1-alpha
docs: add changelog, contributor guide, release process, and runner setup
- CHANGELOG.md: Keep-a-Changelog format, [26.0-alpha] entry covering
everything shipped so far (installer webapp, drive scoring, base
archinstall config, wireframes, competitor analysis, wizard flow spec)
- CONTRIBUTING.md: dev setup, conventional commit format, code style
- RELEASING.md: calendar versioning rules (YY.N-stage, no "v" prefix)
and the release workflow (bump changelog, commit, tag, push, create
Forgejo Release)
- docs/runner-setup.md: install + register a forgejo-runner so the
upcoming CI workflow actually executes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:23:48 +02:00
```
Update the `[Unreleased]` compare link to point at the new tag.
2. **Commit the changelog.**
```bash
git add CHANGELOG.md
git commit -m "chore: release 26.1-alpha"
```
3. **Tag the commit.**
```bash
git tag -a 26.1-alpha -m "Release 26.1-alpha"
```
4. **Push the tag and main.**
```bash
git push origin main
git push origin 26.1-alpha
```
feat(website): download page for the ISO, homepage with download CTA and 3-step how-it-works
- /download/ and /de/download/: big download button, file name, size and
release date, requirements (64-bit PC, UEFI or BIOS, >=16 GB disk that
gets erased, USB stick, network cable with internet, second device),
five install steps (Etcher / Rufus DD mode / dd, boot menu, Secure Boot
off, proksi.local:5000, wizard, pull stick), checksum + verify commands
when the release has one, alpha notice, link to all releases
- the release data comes from the Forgejo API at build time
(partials/release.html): newest release with an .iso asset, falling back
to params.version if the lookup fails; getresource cache disabled so a
build never pins an old release
- homepage: status chip follows the latest release, 'Download ISO' primary
CTA + 'Source code' ghost CTA, numbered how-it-works cards, download band
before the closer
- releases now upload furtka-<ver>.iso.sha256, and release.yml rebuilds the
site after publishing so the download page follows each release
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Wq1hzUp4ZmCKHDuLKCnu73
2026-09-28 14:52:59 +02:00
5. **The release workflow does the rest.** `.forgejo/workflows/release.yml` fires on the tag push and runs on the self-hosted runner: `scripts/build-release-tarball.sh` builds the self-update payload (tarball + sha256 + release.json under `dist/` ), `iso/build.sh` builds the live-installer ISO, `scripts/publish-release.sh` uploads tarball + sha256 + release.json + ISO to the Forgejo release page. Pre-release is flagged automatically based on the suffix (`-alpha` /`-beta` /`-rc` ). The ISO gets a `furtka-<ver>.iso.sha256` sidecar, and a last step rebuilds furtka.org so the download page (`/download/` ) picks up the new ISO, size, date and checksum from the Forgejo API. ISO build is `continue-on-error` : a flaky ISO step doesn't block the core tarball (the thing boxes need for self-update).
docs: add changelog, contributor guide, release process, and runner setup
- CHANGELOG.md: Keep-a-Changelog format, [26.0-alpha] entry covering
everything shipped so far (installer webapp, drive scoring, base
archinstall config, wireframes, competitor analysis, wizard flow spec)
- CONTRIBUTING.md: dev setup, conventional commit format, code style
- RELEASING.md: calendar versioning rules (YY.N-stage, no "v" prefix)
and the release workflow (bump changelog, commit, tag, push, create
Forgejo Release)
- docs/runner-setup.md: install + register a forgejo-runner so the
upcoming CI workflow actually executes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:23:48 +02:00
feat(furtka): release CI + \`furtka update\` / \`furtka rollback\` CLI
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>
2026-04-16 13:30:45 +02:00
The release workflow needs one secret set at repo **Settings → Secrets → Actions** :
- `FORGEJO_RELEASE_TOKEN` — a PAT with `write:repository` scope.
6. **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).
7. ** (Optional) Dogfood the update path.** On a VM running the previous version, `sudo furtka update --check` should now see the new tag, and `sudo furtka update` applies it without a reinstall.
docs: add changelog, contributor guide, release process, and runner setup
- CHANGELOG.md: Keep-a-Changelog format, [26.0-alpha] entry covering
everything shipped so far (installer webapp, drive scoring, base
archinstall config, wireframes, competitor analysis, wizard flow spec)
- CONTRIBUTING.md: dev setup, conventional commit format, code style
- RELEASING.md: calendar versioning rules (YY.N-stage, no "v" prefix)
and the release workflow (bump changelog, commit, tag, push, create
Forgejo Release)
- docs/runner-setup.md: install + register a forgejo-runner so the
upcoming CI workflow actually executes
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-13 20:23:48 +02:00
## First-time: find the current version
```bash
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.
```bash
git tag -d 26.1-alpha
git push origin :refs/tags/26.1-alpha
# ... fix ...
git tag -a 26.2-alpha ...
```