Signed xbps repository release pipeline #14

Closed
opened 2026-11-05 16:14:19 +00:00 by xavierk · 1 comment
Owner

Part of #1

Question

Beyond the tag-driven rule, what are the release pipeline details for the signed personal xbps repository: template location, CI signing flow, repodata publishing, and key handling?

Part of #1 ## Question Beyond the tag-driven rule, what are the release pipeline details for the signed personal xbps repository: template location, CI signing flow, repodata publishing, and key handling?
xavierk added the wayfinder:grilling label 2026-11-05 16:14:19 +00:00
xavierk self-assigned this 2026-11-05 16:23:43 +00:00
Author
Owner

Resolution: signed personal xbps repository release pipeline.

Decision (made by agent under the user's explicit delegation for this wayfinding run, with rationale and evidence below):

  1. Template location: in-repo at packaging/void/srcpkgs/voculinux/template, mirroring the void-packages srcpkgs layout so xbps-src builds it directly. This keeps the template under the same PR review as the code it packages (repo rule: every change via PR, never commit to main).
  2. Tag form: keep the upstream vX.Y.Z[-phase] tags that match src/vocalinux/version.py (the release.yml gate already triggers on v* and warns on tag/version drift). The -vX.Y.Z prefix from the taema runbook is for multi-artifact repos; this single-purpose fork keeps the upstream form so docs/RELEASE_PROCESS.md and just verify-release keep working unchanged.
  3. CI signing flow: a new xbps-release.yml workflow on tag push. It runs inside the pinned void-glibc container, builds with xbps-src, signs with xbps-rindex --sign, and attaches the package plus its .sig2 and the signed x86_64-repodata to the GitHub release. No hand-built or hand-uploaded assets, ever (repo tag-driven rule).
  4. Repodata publishing: every release carries the full signed repodata, and the repository URL is that repo's releases/latest/download, which xbps reads from the newest release. glibc x86_64 only; musl builds are already Out of scope on the map, so no musl repodata is published.
  5. Key handling: one RSA 4096 key generated once on a trusted local machine, stored mode 600 at the operator's release-key path, never committed; exposed to CI only as the XBPS_PRIVKEY Actions secret. Its fingerprint is documented in the README so users pin one fingerprint. Key generation itself is a human act for the implementer; it does not block this decision.
  6. Post-release template bump: the version/checksum bump in the template goes through the normal PR flow, not a direct-to-main bot commit. The taema runbook auto-commits to main, but this repo's no-direct-to-main rule wins.

Rationale: smallest pipeline that reaches the Destination (signed personal repo first, upstream void-packages submission out of scope). Thin-package precedent from packaging/native/nfpm.yaml (distro Python/GTK, vendored pywhispercpp/pynput) carries over to the template's depends; models stay out of the package per the map Notes (first-run download with pinned checksums). Tag push itself remains a human act (pushing tags needs the user's explicit OK each time).

Evidence inspected: map Destination/Notes/Decisions-so-far (Void xbps packaging route decision: signed personal repository first, in-repo templates, tag-driven CI); docs/RELEASE_PROCESS.md (tag-driven, version.py source of truth, never hand-edit published releases); .github/workflows/release.yml (v* trigger, version-drift gate); packaging/native/nfpm.yaml plus tool_checksums.txt (thin packaging, pinned inputs); personal runbook memory release-xbps.md (Bongbetic/taema signed-repo pattern, adapted where repo rules differ as noted).

Domain-modeling note: no new glossary terms (xbps, repodata, srcpkgs, xbps-src/xbps-rindex are standard Void vocabulary) and no docs/adr/ change; GLOSSARY.md and docs/adr/ do not exist in this repo and nothing here meets the ADR bar beyond what this ticket records, so this ticket stays the single home of the decision.

Consequences for later tickets: none; Portal first-run prompt UX under niri (#15) is unaffected.

Resolution: signed personal xbps repository release pipeline. Decision (made by agent under the user's explicit delegation for this wayfinding run, with rationale and evidence below): 1. Template location: in-repo at packaging/void/srcpkgs/voculinux/template, mirroring the void-packages srcpkgs layout so xbps-src builds it directly. This keeps the template under the same PR review as the code it packages (repo rule: every change via PR, never commit to main). 2. Tag form: keep the upstream vX.Y.Z[-phase] tags that match src/vocalinux/version.py (the release.yml gate already triggers on v* and warns on tag/version drift). The <name>-vX.Y.Z prefix from the taema runbook is for multi-artifact repos; this single-purpose fork keeps the upstream form so docs/RELEASE_PROCESS.md and just verify-release keep working unchanged. 3. CI signing flow: a new xbps-release.yml workflow on tag push. It runs inside the pinned void-glibc container, builds with xbps-src, signs with xbps-rindex --sign, and attaches the package plus its .sig2 and the signed x86_64-repodata to the GitHub release. No hand-built or hand-uploaded assets, ever (repo tag-driven rule). 4. Repodata publishing: every release carries the full signed repodata, and the repository URL is that repo's releases/latest/download, which xbps reads from the newest release. glibc x86_64 only; musl builds are already Out of scope on the map, so no musl repodata is published. 5. Key handling: one RSA 4096 key generated once on a trusted local machine, stored mode 600 at the operator's release-key path, never committed; exposed to CI only as the XBPS_PRIVKEY Actions secret. Its fingerprint is documented in the README so users pin one fingerprint. Key generation itself is a human act for the implementer; it does not block this decision. 6. Post-release template bump: the version/checksum bump in the template goes through the normal PR flow, not a direct-to-main bot commit. The taema runbook auto-commits to main, but this repo's no-direct-to-main rule wins. Rationale: smallest pipeline that reaches the Destination (signed personal repo first, upstream void-packages submission out of scope). Thin-package precedent from packaging/native/nfpm.yaml (distro Python/GTK, vendored pywhispercpp/pynput) carries over to the template's depends; models stay out of the package per the map Notes (first-run download with pinned checksums). Tag push itself remains a human act (pushing tags needs the user's explicit OK each time). Evidence inspected: map Destination/Notes/Decisions-so-far (Void xbps packaging route decision: signed personal repository first, in-repo templates, tag-driven CI); docs/RELEASE_PROCESS.md (tag-driven, version.py source of truth, never hand-edit published releases); .github/workflows/release.yml (v* trigger, version-drift gate); packaging/native/nfpm.yaml plus tool_checksums.txt (thin packaging, pinned inputs); personal runbook memory release-xbps.md (Bongbetic/taema signed-repo pattern, adapted where repo rules differ as noted). Domain-modeling note: no new glossary terms (xbps, repodata, srcpkgs, xbps-src/xbps-rindex are standard Void vocabulary) and no docs/adr/ change; GLOSSARY.md and docs/adr/ do not exist in this repo and nothing here meets the ADR bar beyond what this ticket records, so this ticket stays the single home of the decision. Consequences for later tickets: none; Portal first-run prompt UX under niri (#15) is unaffected.
Sign in to join this conversation.