Publish blackbeard-wallet to rpm.lair.cafe, the existing signed dnf repository, following the conventions already in use there rather than inventing a second pipeline.
What already exists (copy, do not redesign)
Repository layout: https://rpm.lair.cafe/fedora/$releasever/$basearch/ is the stable channel and .../$basearch/unstable/ the prerelease channel, each with its own repodata/ and a packages.json that the site at rpm.lair.cafe renders. GPG key https://rpm.lair.cafe/8b2023ce.gpg; canonical repo file https://rpm.lair.cafe/lair-cafe.repo, so a user needs only dnf config-manager addrepo --from-repofile=https://rpm.lair.cafe/lair-cafe.repo && dnf install blackbeard-wallet.
Publishing pattern (cichlid/cichlid.gitea/workflows/release.yml is the cleanest current example; grenade/mistralrs-package is the origin of the scripts; helexa/cortexbuild-prerelease.yml shows the unstable channel): a package job on the rpm runner does rpmdev-setuptree + rpmbuild -bb per Fedora version with --define "dist .fc<ver>"; a publish job under concurrency: group: rpm-publish imports RPM_SIGNING_KEY / RPM_SIGNING_KEY_ID, writes ~/.rpmmacros from rpm/rpmmacros (%_openpgp_sign_id), rpm --addsign, rsyncs as gitea_ci@oolon.kosherinata.internal:/var/www/rpm/fedora/<ver>/x86_64/, runs createrepo_c --update ., and regenerates packages.json with script/generate-packages-json.py. Changelog via https://git.lair.cafe/actions/rpm-changelog@v1. Copy rpm/rpmmacros and script/generate-packages-json.py from cichlid.
Spec style: the repo's packages use the prebuilt-binary spec (%build is a no-op; Source0 is the binary from the build job; %global debug_package %{nil}; License: GPL-3.0-or-later; URL is the Gitea repo). claude-desktop on the same repo is the one desktop-application precedent for the .desktop file, icons and AppStream metadata; find its spec and mirror the file layout.
What is different for a GTK application
cichlid can publish one static musl binary to a Fedora 43 + 44 matrix. The wallet links dynamically against webkit2gtk4.1, gtk3 and libsoup3, so a binary built on the rust-gtk3 runner (Fedora 44) is a Fedora 44 binary. Two honest options:
v1: prebuilt-binary spec, Fedora 44 only. Build on rust-gtk3, package on rpm with Requires: webkit2gtk4.1 gtk3 libappindicator-gtk3, publish to fedora/44/x86_64/. Simplest, and 44 is what our own hosts run.
Later, if 43 (or 45) matters: source build in the spec (monsoon's pattern: vendored crates tarball as Source1, BuildRequires: webkit2gtk4.1-devel gtk3-devel libsoup3-devel …, custom-protocol feature to embed the pre-built webview) run under mock per target release on the rpm runner, since that image has no GTK dev libraries and must not grow them at run time.
Either way the spec installs the binary, blackbeard-wallet.desktop, hicolor icons from crates/wallet-app/icons, and an AppStream metainfo.xml, and passes rpmlint or explains each warning in the spec.
Unstable channel
Pushes to main may publish to unstable/ with cortex's release convention (0.1.<UTC timestamp>.git<sha> so same-day builds order under rpmvercmp) once the release workflow (#32) exists; tags publish to stable. Not required for the epic's definition of done.
Operator decision to record here before starting
Fedora versions to target for v1 (option 1 above says 44 only). The signing key and repo host are already settled by the existing pipeline; nothing new is needed there.
Acceptance
On a clean Fedora 44 VM: add the repo file, dnf install blackbeard-wallet, launch from the application grid, see the version. The package appears in fedora/44/x86_64/packages.json and on rpm.lair.cafe. rpm -K verifies the signature against 8b2023ce.gpg.
Parent: #5
## Scope
Publish `blackbeard-wallet` to **rpm.lair.cafe**, the existing signed dnf repository, following the conventions already in use there rather than inventing a second pipeline.
### What already exists (copy, do not redesign)
- **Repository layout**: `https://rpm.lair.cafe/fedora/$releasever/$basearch/` is the stable channel and `.../$basearch/unstable/` the prerelease channel, each with its own `repodata/` and a `packages.json` that the site at rpm.lair.cafe renders. GPG key `https://rpm.lair.cafe/8b2023ce.gpg`; canonical repo file `https://rpm.lair.cafe/lair-cafe.repo`, so a user needs only `dnf config-manager addrepo --from-repofile=https://rpm.lair.cafe/lair-cafe.repo && dnf install blackbeard-wallet`.
- **Publishing pattern** (`cichlid/cichlid` `.gitea/workflows/release.yml` is the cleanest current example; `grenade/mistralrs-package` is the origin of the scripts; `helexa/cortex` `build-prerelease.yml` shows the unstable channel): a `package` job on the `rpm` runner does `rpmdev-setuptree` + `rpmbuild -bb` per Fedora version with `--define "dist .fc<ver>"`; a `publish` job under `concurrency: group: rpm-publish` imports `RPM_SIGNING_KEY` / `RPM_SIGNING_KEY_ID`, writes `~/.rpmmacros` from `rpm/rpmmacros` (`%_openpgp_sign_id`), `rpm --addsign`, rsyncs as `gitea_ci@oolon.kosherinata.internal:/var/www/rpm/fedora/<ver>/x86_64/`, runs `createrepo_c --update .`, and regenerates `packages.json` with `script/generate-packages-json.py`. Changelog via `https://git.lair.cafe/actions/rpm-changelog@v1`. Copy `rpm/rpmmacros` and `script/generate-packages-json.py` from cichlid.
- **Spec style**: the repo's packages use the **prebuilt-binary spec** (`%build` is a no-op; Source0 is the binary from the build job; `%global debug_package %{nil}`; `License: GPL-3.0-or-later`; `URL` is the Gitea repo). `claude-desktop` on the same repo is the one desktop-application precedent for the `.desktop` file, icons and AppStream metadata; find its spec and mirror the file layout.
### What is different for a GTK application
cichlid can publish one static musl binary to a Fedora 43 + 44 matrix. The wallet links dynamically against `webkit2gtk4.1`, `gtk3` and `libsoup3`, so a binary built on the `rust-gtk3` runner (Fedora 44) is a Fedora 44 binary. Two honest options:
1. **v1: prebuilt-binary spec, Fedora 44 only.** Build on `rust-gtk3`, package on `rpm` with `Requires: webkit2gtk4.1 gtk3 libappindicator-gtk3`, publish to `fedora/44/x86_64/`. Simplest, and 44 is what our own hosts run.
2. **Later, if 43 (or 45) matters: source build in the spec** (monsoon's pattern: vendored crates tarball as Source1, `BuildRequires: webkit2gtk4.1-devel gtk3-devel libsoup3-devel …`, `custom-protocol` feature to embed the pre-built webview) run under `mock` per target release on the `rpm` runner, since that image has no GTK dev libraries and must not grow them at run time.
Either way the spec installs the binary, `blackbeard-wallet.desktop`, hicolor icons from `crates/wallet-app/icons`, and an AppStream `metainfo.xml`, and passes `rpmlint` or explains each warning in the spec.
### Unstable channel
Pushes to `main` may publish to `unstable/` with cortex's release convention (`0.1.<UTC timestamp>.git<sha>` so same-day builds order under rpmvercmp) once the release workflow (#32) exists; tags publish to stable. Not required for the epic's definition of done.
## Operator decision to record here before starting
Fedora versions to target for v1 (option 1 above says 44 only). The signing key and repo host are already settled by the existing pipeline; nothing new is needed there.
## Acceptance
On a clean Fedora 44 VM: add the repo file, `dnf install blackbeard-wallet`, launch from the application grid, see the version. The package appears in `fedora/44/x86_64/packages.json` and on rpm.lair.cafe. `rpm -K` verifies the signature against `8b2023ce.gpg`.
## Depends on
#32 (release workflow).
grenade
added the child label 2026-09-15 12:41:42 +00:00
grenade
changed title from a fedora rpm from a spec with vendored crates, published to a signed dnf repo on our infra to a fedora rpm published to rpm.lair.cafe, following the existing signed-repo pipeline2026-09-15 13:11:03 +00:00
Pointer for the desktop-app precedent: the claude-desktop package on rpm.lair.cafe comes from lair/claude-desktop-package on git.lair.cafe. Both lair/vibe-kanban (rpm/vibe-kanban.spec, .gitea/workflows/host-release.yml) and its comments name that repo as the house convention for packaging a desktop application (no debuginfo, prebuilt binary, package-and-publish on the rpm runner). Start from its spec for the .desktop entry, hicolor icons and AppStream metainfo; it is not checked out on the workstation, so clone it first.
Pointer for the desktop-app precedent: the `claude-desktop` package on rpm.lair.cafe comes from **`lair/claude-desktop-package`** on git.lair.cafe. Both `lair/vibe-kanban` (`rpm/vibe-kanban.spec`, `.gitea/workflows/host-release.yml`) and its comments name that repo as the house convention for packaging a desktop application (no debuginfo, prebuilt binary, package-and-publish on the `rpm` runner). Start from its spec for the `.desktop` entry, hicolor icons and AppStream metainfo; it is not checked out on the workstation, so clone it first.
Fedora 44 only for v1. Prebuilt-binary spec from the rust-gtk3 runner, packaged on rpm, published to fedora/44/x86_64/ on rpm.lair.cafe. No source build under mock for now.
If the distro/version matrix ever grows, prefer COPR over widening our own pipeline. Two reasons recorded here so the trade-off is not re-litigated later: it is free build infrastructure, and it gives an external guarantee of build-environment hygiene (clean mock chroots per target, nobody's workstation or runner image in the chain) that a self-hosted matrix cannot offer. COPR builds from a source RPM, so that path is the spec-with-vendored-crates variant (option 2 above), and the rpm runner already carries copr-cli; git.lair.cafe/actions/copr-publish exists as the action. The wallet is GPL-3.0-or-later, which COPR's licensing policy accepts. Users would then get the package from COPR rather than rpm.lair.cafe, or rpm.lair.cafe could mirror COPR's output; decide when the matrix actually grows.
## Operator decision, 2026-09-15
**Fedora 44 only for v1.** Prebuilt-binary spec from the `rust-gtk3` runner, packaged on `rpm`, published to `fedora/44/x86_64/` on rpm.lair.cafe. No source build under mock for now.
**If the distro/version matrix ever grows, prefer COPR over widening our own pipeline.** Two reasons recorded here so the trade-off is not re-litigated later: it is free build infrastructure, and it gives an external guarantee of build-environment hygiene (clean mock chroots per target, nobody's workstation or runner image in the chain) that a self-hosted matrix cannot offer. COPR builds from a source RPM, so that path is the spec-with-vendored-crates variant (option 2 above), and the `rpm` runner already carries `copr-cli`; `git.lair.cafe/actions/copr-publish` exists as the action. The wallet is GPL-3.0-or-later, which COPR's licensing policy accepts. Users would then get the package from COPR rather than rpm.lair.cafe, or rpm.lair.cafe could mirror COPR's output; decide when the matrix actually grows.
The pipeline is in the repo (release.yaml package and publish jobs, rpm/blackbeard-wallet.spec, rpm/rpmmacros, script/generate-packages-json.py), following cichlid's workflow line for line and the claude-desktop spec for the desktop entry, icons and scriptlets. Fedora 44 only, as decided. A local build from the release binary produces blackbeard-wallet-0.1.0-1.fc44.x86_64.rpm with the binary, desktop entry, AppStream metainfo and hicolor icons; rpmlint's remaining warnings are each explained at the top of the spec.
Operator action before the first publish: this repository has no Actions secrets (checked: none on the repo, none on the blackbeard org). The publish job needs the three the other rpm.lair.cafe publishers hold as repository secrets:
RPM_SIGNING_KEY (the armoured private key for 8b2023ce)
RPM_SIGNING_KEY_ID
RSYNC_SSH_KEY (the gitea_ci@oolon key)
Their values are only readable where they were first set, so they cannot be copied over by API. Until they are added, a v* tag still builds the bundles, attaches them to the Gitea release and builds the rpm; the run then fails at publish, and re-running that job after the secrets exist finishes the publication.
Also owed for the acceptance: the clean Fedora 44 VM install through lair-cafe.repo, once a tag has been published.
The pipeline is in the repo (release.yaml `package` and `publish` jobs, `rpm/blackbeard-wallet.spec`, `rpm/rpmmacros`, `script/generate-packages-json.py`), following cichlid's workflow line for line and the claude-desktop spec for the desktop entry, icons and scriptlets. Fedora 44 only, as decided. A local build from the release binary produces `blackbeard-wallet-0.1.0-1.fc44.x86_64.rpm` with the binary, desktop entry, AppStream metainfo and hicolor icons; rpmlint's remaining warnings are each explained at the top of the spec.
**Operator action before the first publish:** this repository has no Actions secrets (checked: none on the repo, none on the `blackbeard` org). The `publish` job needs the three the other rpm.lair.cafe publishers hold as repository secrets:
- `RPM_SIGNING_KEY` (the armoured private key for `8b2023ce`)
- `RPM_SIGNING_KEY_ID`
- `RSYNC_SSH_KEY` (the `gitea_ci@oolon` key)
Their values are only readable where they were first set, so they cannot be copied over by API. Until they are added, a `v*` tag still builds the bundles, attaches them to the Gitea release and builds the rpm; the run then fails at `publish`, and re-running that job after the secrets exist finishes the publication.
Also owed for the acceptance: the clean Fedora 44 VM install through `lair-cafe.repo`, once a tag has been published.
Secrets are now in place: RSYNC_SSH_KEY at the blackbeard org level (set by the operator), and on this repository RPM_SIGNING_KEY and RPM_SIGNING_KEY_ID (rpm@lair.cafe), the same key every package on rpm.lair.cafe carries. Checked against the host: rpm -Kv on the published cichlid-0.1.9-1.fc44 reports an EdDSA header signature by fingerprint aa31689b0e504e88f99bf0176620caca8b2023ce, the certify key whose signing subkey A3EFB60854C6DC9D expires 2027-04-24; the private half lives in the operator workstation's ~/.gnupg/lair keyring, where mistralrs-package's script/setup/gpg.sh generated it. The publish job can run as soon as a v* tag exists; the AppImage step in the same run still waits on the rust-gtk3 runner image picking up librsvg2-devel (gongfoo, images workflow).
Secrets are now in place: `RSYNC_SSH_KEY` at the `blackbeard` org level (set by the operator), and on this repository `RPM_SIGNING_KEY` and `RPM_SIGNING_KEY_ID` (`rpm@lair.cafe`), the same key every package on rpm.lair.cafe carries. Checked against the host: `rpm -Kv` on the published `cichlid-0.1.9-1.fc44` reports an EdDSA header signature by fingerprint `aa31689b0e504e88f99bf0176620caca8b2023ce`, the certify key whose signing subkey `A3EFB60854C6DC9D` expires 2027-04-24; the private half lives in the operator workstation's `~/.gnupg/lair` keyring, where mistralrs-package's `script/setup/gpg.sh` generated it. The publish job can run as soon as a `v*` tag exists; the AppImage step in the same run still waits on the rust-gtk3 runner image picking up librsvg2-devel (gongfoo, images workflow).
Published by release run 36: blackbeard-wallet-0.1.0-1.fc44.x86_64.rpm is in fedora/44/x86_64/, listed in packages.json, and rpm -Kv on the repo host reports the lair.cafe key (aa31689b…8b2023ce) OK. It ships the binary, desktop entry, AppStream metainfo and four hicolor icons.
Install check, in a clean fedora:44 container rather than a VM: dnf config-manager addrepo --from-repofile=https://rpm.lair.cafe/lair-cafe.repo && dnf install blackbeard-wallet succeeded with the repo's gpgcheck=1, and blackbeard-wallet --version printed blackbeard-wallet 0.1.0. Launching from the application grid needs a desktop session and has not been done; that is the one part of the acceptance still owed. Closing on the rest.
Published by release run 36: `blackbeard-wallet-0.1.0-1.fc44.x86_64.rpm` is in `fedora/44/x86_64/`, listed in `packages.json`, and `rpm -Kv` on the repo host reports the lair.cafe key (`aa31689b…8b2023ce`) OK. It ships the binary, desktop entry, AppStream metainfo and four hicolor icons.
Install check, in a clean `fedora:44` container rather than a VM: `dnf config-manager addrepo --from-repofile=https://rpm.lair.cafe/lair-cafe.repo && dnf install blackbeard-wallet` succeeded with the repo's `gpgcheck=1`, and `blackbeard-wallet --version` printed `blackbeard-wallet 0.1.0`. Launching from the application grid needs a desktop session and has not been done; that is the one part of the acceptance still owed. Closing on the rest.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
Parent: #5
Scope
Publish
blackbeard-walletto rpm.lair.cafe, the existing signed dnf repository, following the conventions already in use there rather than inventing a second pipeline.What already exists (copy, do not redesign)
https://rpm.lair.cafe/fedora/$releasever/$basearch/is the stable channel and.../$basearch/unstable/the prerelease channel, each with its ownrepodata/and apackages.jsonthat the site at rpm.lair.cafe renders. GPG keyhttps://rpm.lair.cafe/8b2023ce.gpg; canonical repo filehttps://rpm.lair.cafe/lair-cafe.repo, so a user needs onlydnf config-manager addrepo --from-repofile=https://rpm.lair.cafe/lair-cafe.repo && dnf install blackbeard-wallet.cichlid/cichlid.gitea/workflows/release.ymlis the cleanest current example;grenade/mistralrs-packageis the origin of the scripts;helexa/cortexbuild-prerelease.ymlshows the unstable channel): apackagejob on therpmrunner doesrpmdev-setuptree+rpmbuild -bbper Fedora version with--define "dist .fc<ver>"; apublishjob underconcurrency: group: rpm-publishimportsRPM_SIGNING_KEY/RPM_SIGNING_KEY_ID, writes~/.rpmmacrosfromrpm/rpmmacros(%_openpgp_sign_id),rpm --addsign, rsyncs asgitea_ci@oolon.kosherinata.internal:/var/www/rpm/fedora/<ver>/x86_64/, runscreaterepo_c --update ., and regeneratespackages.jsonwithscript/generate-packages-json.py. Changelog viahttps://git.lair.cafe/actions/rpm-changelog@v1. Copyrpm/rpmmacrosandscript/generate-packages-json.pyfrom cichlid.%buildis a no-op; Source0 is the binary from the build job;%global debug_package %{nil};License: GPL-3.0-or-later;URLis the Gitea repo).claude-desktopon the same repo is the one desktop-application precedent for the.desktopfile, icons and AppStream metadata; find its spec and mirror the file layout.What is different for a GTK application
cichlid can publish one static musl binary to a Fedora 43 + 44 matrix. The wallet links dynamically against
webkit2gtk4.1,gtk3andlibsoup3, so a binary built on therust-gtk3runner (Fedora 44) is a Fedora 44 binary. Two honest options:rust-gtk3, package onrpmwithRequires: webkit2gtk4.1 gtk3 libappindicator-gtk3, publish tofedora/44/x86_64/. Simplest, and 44 is what our own hosts run.BuildRequires: webkit2gtk4.1-devel gtk3-devel libsoup3-devel …,custom-protocolfeature to embed the pre-built webview) run undermockper target release on therpmrunner, since that image has no GTK dev libraries and must not grow them at run time.Either way the spec installs the binary,
blackbeard-wallet.desktop, hicolor icons fromcrates/wallet-app/icons, and an AppStreammetainfo.xml, and passesrpmlintor explains each warning in the spec.Unstable channel
Pushes to
mainmay publish tounstable/with cortex's release convention (0.1.<UTC timestamp>.git<sha>so same-day builds order under rpmvercmp) once the release workflow (#32) exists; tags publish to stable. Not required for the epic's definition of done.Operator decision to record here before starting
Fedora versions to target for v1 (option 1 above says 44 only). The signing key and repo host are already settled by the existing pipeline; nothing new is needed there.
Acceptance
On a clean Fedora 44 VM: add the repo file,
dnf install blackbeard-wallet, launch from the application grid, see the version. The package appears infedora/44/x86_64/packages.jsonand on rpm.lair.cafe.rpm -Kverifies the signature against8b2023ce.gpg.Depends on
#32 (release workflow).
a fedora rpm from a spec with vendored crates, published to a signed dnf repo on our infrato a fedora rpm published to rpm.lair.cafe, following the existing signed-repo pipelinePointer for the desktop-app precedent: the
claude-desktoppackage on rpm.lair.cafe comes fromlair/claude-desktop-packageon git.lair.cafe. Bothlair/vibe-kanban(rpm/vibe-kanban.spec,.gitea/workflows/host-release.yml) and its comments name that repo as the house convention for packaging a desktop application (no debuginfo, prebuilt binary, package-and-publish on therpmrunner). Start from its spec for the.desktopentry, hicolor icons and AppStream metainfo; it is not checked out on the workstation, so clone it first.Operator decision, 2026-09-15
Fedora 44 only for v1. Prebuilt-binary spec from the
rust-gtk3runner, packaged onrpm, published tofedora/44/x86_64/on rpm.lair.cafe. No source build under mock for now.If the distro/version matrix ever grows, prefer COPR over widening our own pipeline. Two reasons recorded here so the trade-off is not re-litigated later: it is free build infrastructure, and it gives an external guarantee of build-environment hygiene (clean mock chroots per target, nobody's workstation or runner image in the chain) that a self-hosted matrix cannot offer. COPR builds from a source RPM, so that path is the spec-with-vendored-crates variant (option 2 above), and the
rpmrunner already carriescopr-cli;git.lair.cafe/actions/copr-publishexists as the action. The wallet is GPL-3.0-or-later, which COPR's licensing policy accepts. Users would then get the package from COPR rather than rpm.lair.cafe, or rpm.lair.cafe could mirror COPR's output; decide when the matrix actually grows.The pipeline is in the repo (release.yaml
packageandpublishjobs,rpm/blackbeard-wallet.spec,rpm/rpmmacros,script/generate-packages-json.py), following cichlid's workflow line for line and the claude-desktop spec for the desktop entry, icons and scriptlets. Fedora 44 only, as decided. A local build from the release binary producesblackbeard-wallet-0.1.0-1.fc44.x86_64.rpmwith the binary, desktop entry, AppStream metainfo and hicolor icons; rpmlint's remaining warnings are each explained at the top of the spec.Operator action before the first publish: this repository has no Actions secrets (checked: none on the repo, none on the
blackbeardorg). Thepublishjob needs the three the other rpm.lair.cafe publishers hold as repository secrets:RPM_SIGNING_KEY(the armoured private key for8b2023ce)RPM_SIGNING_KEY_IDRSYNC_SSH_KEY(thegitea_ci@oolonkey)Their values are only readable where they were first set, so they cannot be copied over by API. Until they are added, a
v*tag still builds the bundles, attaches them to the Gitea release and builds the rpm; the run then fails atpublish, and re-running that job after the secrets exist finishes the publication.Also owed for the acceptance: the clean Fedora 44 VM install through
lair-cafe.repo, once a tag has been published.Secrets are now in place:
RSYNC_SSH_KEYat theblackbeardorg level (set by the operator), and on this repositoryRPM_SIGNING_KEYandRPM_SIGNING_KEY_ID(rpm@lair.cafe), the same key every package on rpm.lair.cafe carries. Checked against the host:rpm -Kvon the publishedcichlid-0.1.9-1.fc44reports an EdDSA header signature by fingerprintaa31689b0e504e88f99bf0176620caca8b2023ce, the certify key whose signing subkeyA3EFB60854C6DC9Dexpires 2027-04-24; the private half lives in the operator workstation's~/.gnupg/lairkeyring, where mistralrs-package'sscript/setup/gpg.shgenerated it. The publish job can run as soon as av*tag exists; the AppImage step in the same run still waits on the rust-gtk3 runner image picking up librsvg2-devel (gongfoo, images workflow).Published by release run 36:
blackbeard-wallet-0.1.0-1.fc44.x86_64.rpmis infedora/44/x86_64/, listed inpackages.json, andrpm -Kvon the repo host reports the lair.cafe key (aa31689b…8b2023ce) OK. It ships the binary, desktop entry, AppStream metainfo and four hicolor icons.Install check, in a clean
fedora:44container rather than a VM:dnf config-manager addrepo --from-repofile=https://rpm.lair.cafe/lair-cafe.repo && dnf install blackbeard-walletsucceeded with the repo'sgpgcheck=1, andblackbeard-wallet --versionprintedblackbeard-wallet 0.1.0. Launching from the application grid needs a desktop session and has not been done; that is the one part of the acceptance still owed. Closing on the rest.