From d3a3f542044084d1a807368d2923a2e0e4ebf46a Mon Sep 17 00:00:00 2001 From: Xavier Karma Date: Fri, 6 Nov 2026 18:28:11 +0530 Subject: [PATCH] docs(release): describe the Gitea xbps release and the template bump pull request Cover the one-time setup (the XBPS_SIGNING_KEY secret, the committed public key and its fingerprint, the runner and token needs), the tag-push gates and what the workflow publishes to the tag release and to latest, and the checklist items for verifying the run. The template version and checksum bump stays a normal pull request, never a bot commit to main, and now says the checksum is the sha256 of the fork's own release asset. The cherry-pick policy from ticket #30 was already in this file and is enforced by tests/test_upstream_intake_policy.py. Correct what it names as the retained internal module: it is vocalinux (src/vocalinux/), not voculinux. --- docs/RELEASE_PROCESS.md | 89 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 78 insertions(+), 11 deletions(-) diff --git a/docs/RELEASE_PROCESS.md b/docs/RELEASE_PROCESS.md index e098450..246e3d1 100644 --- a/docs/RELEASE_PROCESS.md +++ b/docs/RELEASE_PROCESS.md @@ -37,6 +37,24 @@ publish succeeds. `publish-aur` skips itself when `AUR_SSH_PRIVATE_KEY` is unset. See docs/AUR.md. +### Void xbps repository (required for a Void release) + +The signed Void repository is released by `.gitea/workflows/xbps-release.yml` +on the fork's Gitea host, not by `release.yml`. Set it up once: + +| what | value | +|---|---| +| Secret | `XBPS_SIGNING_KEY`: the PEM-encoded RSA 4096 repository private key (Gitea repository settings, Actions, Secrets) | +| Public key | `packaging/void/repository-key.plist`, committed, fingerprint `fa:d1:00:32:ce:b1:b9:fd:73:05:05:76:75:54:37:25` | +| Runner | `bongbetic-ci` with podman (the workflow installs it with apt when absent). Never Docker | +| Token | the job token must be allowed to create releases and upload release assets | + +Without the secret the workflow fails and publishes nothing; it never signs +with a different key either, because the fingerprint of the key that signed +must equal the one above. The private key is never committed; only the public +`.plist` is. Key generation and the check that a private key matches the +committed public key are in `packaging/void/README.md`. + ## Quick Release Checklist Use this checklist for every release: @@ -81,7 +99,7 @@ Install `just` from https://just.systems or the distro package `just`. - [ ] Commit all version changes - [ ] Push branch and create PR - [ ] After PR merge, create tag: `git tag -a vX.Y.Z-PHASE -m "Release X.Y.Z-PHASE"` -- [ ] Push tag: `git push origin vX.Y.Z-PHASE` +- [ ] Push tag: `git push origin vX.Y.Z-PHASE` (this also starts the Gitea xbps workflow, see Step 8) ### After the release run finishes - [ ] Run `just verify-release` - the published release verifies as published @@ -316,13 +334,21 @@ Update the supported versions table: After the tag is cut, the Void templates in `packaging/void/srcpkgs/` must point at the new release: bump `version` in the `voculinux` template (and any template whose upstream moved) and refresh every pinned `checksum` -(`sha256` sums of the release sdist and distfiles). Land the bump as a -**pull request** through the normal test, lint, and type gates — never as -a direct or bot commit to `main`, and never hand-edited onto the release -itself (see `just verify-release`). `tests/test_void_app_template.py` -fails if the template version or checksum drifts from -`src/vocalinux/version.py` and the published sdist, and the signed xbps -repository for the *next* release builds from these templates. +(`sha256` sums of the release sdist and distfiles). The `voculinux` template +builds the fork's release asset `voculinux-X.Y.Z.tar.gz`; its `checksum` is +the sha256 of that exact downloaded asset, never a value copied from +upstream, and stays `PENDING_FORK_RELEASE_SHA256` (which fails closed in +`xbps-src`) until the asset exists. Land the bump as a **pull request** +through the normal test, lint, and type gates, never as a direct or bot +commit to `main`, and never hand-edited onto the release itself (see +`just verify-release`). `tests/test_void_app_template.py` fails if the +template version or checksum drifts from `src/vocalinux/version.py` and the +published sdist. + +Nothing automates this: the xbps workflow never commits or pushes. The +signed repository a tag publishes is built from the templates as committed +at that tag, so a bump merged after tag `vX.Y.Z` first ships with the next +tag push. ### Step 4: Update Website @@ -383,7 +409,7 @@ bash -n install.sh ### Upstream Fix Intake (Cherry-Pick Policy) -Upstream Voculinux fixes enter this fork only as hand cherry-picks: taken at +Upstream Vocalinux fixes enter this fork only as hand cherry-picks: taken at defined sync points, never as continuous tracking and never as wholesale merges. Like every other change, each port goes through the pull request flow with the standard test, lint, and type gates. Never land one as a direct or @@ -404,8 +430,10 @@ worktree per branch, every change via a pull request, never commit on `main` renames on top. Conflicts concentrate at the renamed user-visible surfaces (application name, entry points, desktop and D-Bus identity, configuration and data directories, package, website) precisely because the internal - Python module name stays `voculinux` as a retained internal name — that - split is what keeps hand cherry-picks nearly conflict-free everywhere else. + Python module name stays `vocalinux` (`src/vocalinux/`) as a retained + internal name, so only the user-visible surfaces diverge from upstream, and + that split is what keeps hand cherry-picks nearly conflict-free everywhere + else. Upstream URLs and changelog history stay untouched for provenance. - **What qualifies.** Fixes and documentation that changes user instructions port. Features are re-decided per release, not ported automatically. @@ -507,6 +535,39 @@ After pushing the tag, the GitHub Actions workflow will automatically: Monitor at: https://github.com/VocaHQ/vocalinux/actions +#### Void xbps repository (Gitea tag workflow) + +Pushing the tag to `origin` (the fork's Gitea repository) also starts +`.gitea/workflows/xbps-release.yml`. Pushing a tag is a human act and is +approved each time: the workflow has no schedule and no manual trigger. + +1. **Tag equals version.** The tag must be exactly `v` plus `__version__` in + `src/vocalinux/version.py`. Any other tag, including one that merely + contains the version, exits 1 and publishes nothing. +2. **Signing key required.** An empty `XBPS_SIGNING_KEY` exits 1 before any + container runs. The key is written to a 0600 temp file, passed to + `packaging/void/repo.sh`, and removed by a step that always runs. +3. **Build and sign.** `repo.sh` is the only path that builds or signs: the + pinned Void glibc container under podman, every template in smoke-gate + order, the full `x86_64` index, every package and the metadata signed. +4. **Verify.** Packages, signatures, repodata, `FINGERPRINT` and the client + key must all be present, nothing but glibc `x86_64` data may be present, + every package must be signed, and the signing fingerprint must be the + pinned one. A partial or unsigned repository never attaches. +5. **Publish.** The complete signed set attaches to the tag's release on + Gitea and replaces the assets of the rolling `latest` release, which the + client registration URL + (`https://git.bongbetic.com/xavierk/voculinux/releases/download/latest`) + serves. Push tags in version order: pushing an older tag refreshes + `latest` with the older repository. + +The workflow never commits or pushes to any branch and never bumps a +template; that is the pull request in section 3.5. The `voculinux` template +fetches the fork's `vX.Y.Z` release asset, so that asset must exist and its +checksum must be in the template before the build can pass. A tag whose +templates still carry the pending checksum fails at the build step, by +design. + ### Step 9: Post-Release Tasks - [ ] Verify GitHub Release was created correctly @@ -526,6 +587,12 @@ Monitor at: https://github.com/VocaHQ/vocalinux/actions - [ ] Verify PyPI package was published (if applicable), and that its wheel sha256 matches the line for that wheel in `SHA256SUMS` - [ ] Verify website was deployed (check voculinux.com) +- [ ] Verify the Gitea xbps run succeeded, and that both the tag release and + `latest` carry the full signed set (`*.x86_64.xbps`, `*.sig2`, + `x86_64-repodata`, `FINGERPRINT`, the `.plist`) and that the fingerprint + matches the one in `README.md` +- [ ] Open the Void template bump pull request (section 3.5); never commit + it directly to `main` - [ ] If the Flatpak remote is configured, verify it picked up the tag: `flatpak remote-info vocahq com.voculinux.Voculinux` (docs/FLATPAK_REMOTE.md) - [ ] Announce on social media/communities