From 59bcfa1a12066c61f947a87d078bac6b0ae790b4 Mon Sep 17 00:00:00 2001 From: enricobuehler Date: Mon, 15 Jun 2026 13:54:43 +0000 Subject: [PATCH] fix(ci): rpm signing uses rpm's default signer; flatpak installs node before checkout MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two CI fixes: - rpm signing (2nd bug): overriding %__gpg_sign_cmd via --define reached gpg with %{__plaintext_filename}/%{__signature_filename} UNEXPANDED ("No such file or directory"). Stop overriding it — use rpm's default signer (which expands those correctly) and just set _gpg_name; a passphrase-less key + loopback in gpg.conf makes gpg sign headless. (Requires a passphrase-less signing key, as the runbook's %no-protection key is.) - flatpak: the job runs in fedora:43 which has no node, so actions/checkout (a JS action) failed with "node: not found". Install nodejs in a plain `run:` step (shell, no node needed) before checkout. Also scope the heavy flatpak-builder run to client/core/manifest changes (+ tags) so it stops rebuilding on every unrelated docs/host push (tag pushes still build — paths filters only branch pushes). Co-Authored-By: Claude Opus 4.8 (1M context) --- .gitea/workflows/flatpak.yml | 13 +++++++++++++ packaging/rpm/sign-rpms.sh | 28 +++++++++++++--------------- 2 files changed, 26 insertions(+), 15 deletions(-) diff --git a/.gitea/workflows/flatpak.yml b/.gitea/workflows/flatpak.yml index 6163634..d30a644 100644 --- a/.gitea/workflows/flatpak.yml +++ b/.gitea/workflows/flatpak.yml @@ -23,6 +23,14 @@ name: flatpak on: push: branches: [main] + # The flatpak is the CLIENT — only rebuild when the client/core/manifest change, not on every + # docs/host push (this is a heavy flatpak-builder run). Tags (v*, the client release) build too. + paths: + - 'crates/punktfunk-client-linux/**' + - 'crates/punktfunk-core/**' + - 'packaging/flatpak/**' + - 'Cargo.lock' + - '.gitea/workflows/flatpak.yml' tags: ['v*'] workflow_dispatch: @@ -43,6 +51,11 @@ jobs: image: fedora:43 options: --privileged steps: + # fedora:43 has no node, but actions/checkout (a JS action) needs it. A plain `run:` step + # executes via the container shell (no node needed), so install node BEFORE checkout. + - name: node for the JS actions + run: dnf -y install nodejs + - uses: actions/checkout@v4 - name: Tooling diff --git a/packaging/rpm/sign-rpms.sh b/packaging/rpm/sign-rpms.sh index c5de1c4..be9dc3e 100755 --- a/packaging/rpm/sign-rpms.sh +++ b/packaging/rpm/sign-rpms.sh @@ -5,10 +5,11 @@ # exactly today's behaviour — so it is SAFE to ship before a key exists. The signing only activates # once you add the key as a CI secret (see packaging/rpm/README.md "Enabling per-package signing"). # -# Recommended: a DEDICATED, PASSPHRASE-LESS signing key (simplest in CI), distinct from the Gitea -# instance's repo-metadata key. If your key has a passphrase, set RPM_GPG_PASSPHRASE too. +# Requires a DEDICATED, PASSPHRASE-LESS signing key (the one the runbook generates with +# %no-protection), distinct from the Gitea instance's repo-metadata key — rpm's default signer +# can't supply a passphrase non-interactively here. # -# Usage (in rpm.yml, after build-rpm.sh): RPM_GPG_PRIVATE_KEY=... [RPM_GPG_PASSPHRASE=...] bash packaging/rpm/sign-rpms.sh +# Usage (in rpm.yml, after build-rpm.sh): RPM_GPG_PRIVATE_KEY=... bash packaging/rpm/sign-rpms.sh set -euo pipefail if [ -z "${RPM_GPG_PRIVATE_KEY:-}" ]; then @@ -20,24 +21,21 @@ command -v rpmsign >/dev/null 2>&1 || dnf -y install rpm-sign >/dev/null GNUPGHOME="$(mktemp -d)"; export GNUPGHOME; chmod 700 "$GNUPGHOME" trap 'rm -rf "$GNUPGHOME"' EXIT -echo "allow-loopback-pinentry" > "$GNUPGHOME/gpg-agent.conf" +# Non-interactive in CI (no TTY): force loopback pinentry via gpg.conf so even rpm's default +# signing macro's gpg call won't try to prompt. The passphrase-less key needs no prompt anyway. +printf 'pinentry-mode loopback\n' > "$GNUPGHOME/gpg.conf" +printf 'allow-loopback-pinentry\n' > "$GNUPGHOME/gpg-agent.conf" printf '%s' "$RPM_GPG_PRIVATE_KEY" | gpg --batch --import KEYID="$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}')" [ -n "$KEYID" ] || { echo "no secret key imported from RPM_GPG_PRIVATE_KEY" >&2; exit 1; } -# rpm v4 detached-signing macro. NOTE: %{__gpg} already IS the gpg binary path — do NOT add a -# literal `gpg` after it (that becomes a spurious filename arg -> "no command supplied"). Force -# loopback pinentry (no TTY in CI); feed the passphrase, if any, on stdin via --passphrase-fd 0. -SIGN_CMD="%{__gpg} --batch --no-verbose --no-armor --pinentry-mode loopback" -[ -n "${RPM_GPG_PASSPHRASE:-}" ] && SIGN_CMD="$SIGN_CMD --passphrase-fd 0" -SIGN_CMD="$SIGN_CMD -u %{_gpg_name} --digest-algo sha256 -sbo %{__signature_filename} %{__plaintext_filename}" - +# Sign with rpm's DEFAULT __gpg_sign_cmd — it expands %{__signature_filename}/%{__plaintext_filename} +# correctly. (A custom __gpg_sign_cmd passed via --define reached gpg with those filename macros +# UNEXPANDED -> "No such file or directory".) Just point rpm at our key; the GNUPGHOME above +# (passphrase-less key + loopback) lets gpg sign headless. for rpm in dist/*.rpm; do - printf '%s' "${RPM_GPG_PASSPHRASE:-}" | rpmsign \ - --define "_gpg_name $KEYID" \ - --define "__gpg_sign_cmd $SIGN_CMD" \ - --addsign "$rpm" + rpmsign --define "_gpg_name $KEYID" --addsign "$rpm" done # Verify locally so a bad signature fails the build before publishing.