fix(packaging/gamescope): bump the pin past upstream's capture-format probe, and sign the RPM
Three things, one delivery path — a Fedora/Nobara box getting the patched gamescope. **The pin moves 8c676c39 -> 5fb8dce4** (3.16.25-1 -> 3.16.25-11). The commit that matters is ff6b924, `rendervulkan: fall back to XBGR2101010 when XRGB2101010 is unsupported`: it probes `linearTilingFeatures` for STORAGE+SAMPLED and captures as XBGR2101010 where A2R10G10B10 linear storage is unavailable — which is every NVIDIA. That covers the paths that are upstream's rather than ours: the RGB intermediate `paint_pipewire()` acquires when the stream is YCbCr, and AVIF screenshots. #143 fixed our own node host-side; this is the other half, and its commit message asked for exactly this bump. All six patches rebased. Only 0006 conflicted: upstream's f8be7ee added `vulkan_has_drm_modifiers_for_features()` immediately above the `g_device` declaration our patch turns into a reference — both kept. 0003 and 0005 come out byte-identical; 0006 also picks up the `--zero-commit --no-signature` form 0001-0005 already used. **Patch 0001 now offers `xBGR_210LE` BEFORE `xRGB_210LE`**, mirroring the host-side `HDR_FORMAT_ORDER` rationale on the producer end. A consumer takes the first pod it can use, and we were handing third-party consumers (OBS and friends) the one format NVIDIA fills byte-reversed under a correct-looking label. Deliberately NOT done by calling upstream's `vulkan_get_rgb10_capture_format()`, which is what pw_pods.rs proposes: that symbol landed after 3.16.25, so it would break `packaging/nix/gamescope.nix` — which applies these patches to whatever gamescope nixpkgs pins — with an opaque C++ error instead of a patch conflict. The reorder gets the same outcome on any base. Note added there so the next reader does not "fix" it. **And the RPM was never signed.** `Sign RPMs` runs right after `Build RPM`; the gamescope RPM is built ~90 steps later, behind its own ~10-minute cache, so it missed the signing pass entirely — every punktfunk-gamescope RPM ever published went out unsigned. The repo file we tell users to install carries `gpgcheck=1`, so `dnf install punktfunk-gamescope` failed with "The package is not signed" on every Fedora and Nobara box. The package was in the channel the whole time and could not be installed from it, which is worse than absent: the notes and the docs-site both say it is there. `sign-rpms.sh` now takes explicit paths (defaulting to `dist/*.rpm` as before) and a second pass signs this one before publish, fail-closed on a tag like the first. Verified on Nobara 44 (VM 123, RTX 5070 Ti passthrough), canary 0.27.0-0.ci12611.g516a2954: * Builds clean in the fc44 CI image; banner `3.16.25-17-ga87390d+pfhdr4` (11 upstream + our 6), so the marker the host probes still reads 4 — no capability moved, hence pkgrel 3 and `.pfhdrN` staying put. * `pw-cli enum-params` on the live node: BGRx, NV12, **xBGR_210LE (81), xRGB_210LE (80)** — 8-bit consumers still negotiate bit-for-bit, 10-bit now leads with the safe one. * All four patched flags present, `--pipewire-composite-external-overlay` included. * Patch 0006 confirmed working by comparison, which is the only way to see it: the new build exits 0 where both the pre-0006 `+pfhdr2` build and the stock 3.16.23.2 abort with 134. * Signing fix proven with a throwaway key: `Signature: (none)` -> `digests signatures OK`. * Host health on the canary: synthetic spike 300/300 encoded, loopback 300 recovered, 0 mismatches. One unexplained one-off: the very first headless run after install segfaulted at exit (SIGSEGV, after "Primary child shut down!"). Not reproduced in 11 subsequent runs across every flag combination, so it is recorded rather than diagnosed — the binary is stripped and there is no symbolised core.
This commit is contained in:
@@ -247,6 +247,31 @@ jobs:
|
||||
echo "::warning::no usable punktfunk-gamescope for f${{ matrix.fedver }} — skipping its RPM"
|
||||
fi
|
||||
|
||||
# A SECOND signing pass, for this package only. The main "Sign RPMs" step ran back at build
|
||||
# time, long before this RPM existed — the gamescope build sits behind its own ~10-minute
|
||||
# cache and deliberately runs after the host RPMs are already published. So every
|
||||
# punktfunk-gamescope RPM went to the registry UNSIGNED, and the repo file we tell users to
|
||||
# install carries gpgcheck=1: `dnf install punktfunk-gamescope` failed with "The package is
|
||||
# not signed" on every Fedora and Nobara box. The package was in the channel the whole time
|
||||
# and could not be installed from it — which is worse than absent, because the release notes
|
||||
# and the docs-site both say it is there.
|
||||
#
|
||||
# Same fail-closed rule as the first pass: sign-rpms.sh hard-fails on refs/tags/v* if the org
|
||||
# secret is missing, rather than republishing something a user's dnf will reject.
|
||||
- name: Sign punktfunk-gamescope
|
||||
env:
|
||||
RPM_GPG_PRIVATE_KEY: ${{ secrets.RPM_GPG_PRIVATE_KEY }}
|
||||
RPM_GPG_PASSPHRASE: ${{ secrets.RPM_GPG_PASSPHRASE }}
|
||||
run: |
|
||||
shopt -s nullglob
|
||||
rpms=(dist/punktfunk-gamescope-*.rpm)
|
||||
# No RPM here is the best-effort skip above, already warned about — not a signing failure.
|
||||
if [ "${#rpms[@]}" -eq 0 ]; then
|
||||
echo "no punktfunk-gamescope RPM to sign (see the packaging step above)"
|
||||
exit 0
|
||||
fi
|
||||
bash packaging/rpm/sign-rpms.sh "${rpms[@]}"
|
||||
|
||||
- name: Publish punktfunk-gamescope to the Gitea RPM registry
|
||||
env:
|
||||
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
||||
|
||||
@@ -272,7 +272,7 @@ modules:
|
||||
- type: git
|
||||
url: https://github.com/ValveSoftware/gamescope.git
|
||||
# KEEP IN SYNC with `_gsrev` in packaging/gamescope/PKGBUILD.
|
||||
commit: 8c676c399c761e4540587f61004c957993d12fea
|
||||
commit: 5fb8dce4a09d0a68d097b9faf9513782106bc843
|
||||
# Wrap pins as of that rev (`subprojects/*.wrap`). These are meson WRAPS, not gamescope
|
||||
# submodules, so nothing else populates them and they need explicit sources.
|
||||
#
|
||||
|
||||
@@ -18,11 +18,17 @@ pkgname=punktfunk-gamescope
|
||||
# The `.pfhdrN` suffix is the patch-set revision the binary stamps into its banner (see README.md);
|
||||
# bump it with the marker so pacman sees a new version when only our patches moved.
|
||||
_gsver=3.16.25
|
||||
_gsrev=8c676c399c761e4540587f61004c957993d12fea
|
||||
_gsrev=5fb8dce4a09d0a68d097b9faf9513782106bc843
|
||||
pkgver="${_gsver}.pfhdr4"
|
||||
# 2: patch 0006 (never destroy the Vulkan device/output at exit). No capability moved, so the
|
||||
# `.pfhdrN` level deliberately stays put — see README.md.
|
||||
pkgrel=2
|
||||
# 3: pin moved 8c676c39 -> 5fb8dce4 (3.16.25-1 -> 3.16.25-11), which brings upstream's own
|
||||
# `vulkan_get_rgb10_capture_format()` — the XBGR2101010 fallback for devices with no linear-tiled
|
||||
# A2R10G10B10 storage (every NVIDIA). That fixes the NV12/P010 capture intermediate and AVIF
|
||||
# screenshots, which are upstream's paths, not ours. Patch 0001 additionally now offers
|
||||
# `xBGR_210LE` BEFORE `xRGB_210LE` so a third-party consumer cannot pick the one NVIDIA fills
|
||||
# byte-reversed. Still no capability the host probes for, so `.pfhdrN` stays at 4.
|
||||
pkgrel=3
|
||||
pkgdesc="gamescope with 10-bit BT.2020/PQ PipeWire capture, for punktfunk HDR streaming"
|
||||
arch=('x86_64' 'aarch64')
|
||||
url="https://git.unom.io/unom/punktfunk"
|
||||
|
||||
@@ -97,14 +97,21 @@ distro's `gamescope`.
|
||||
|
||||
## Building
|
||||
|
||||
Pinned upstream: `8c676c39` (master, 2026-07-27 — tags through 3.16.25). The patches apply
|
||||
cleanly to that commit; they touch `src/pipewire.cpp`, `src/steamcompmgr.cpp` and
|
||||
`src/meson.build` only.
|
||||
Pinned upstream: `5fb8dce4` (master, 2026-08-03 — `3.16.25-11-g5fb8dce`). The patches apply
|
||||
cleanly to that commit; they touch `src/pipewire.cpp`, `src/steamcompmgr.cpp`,
|
||||
`src/rendervulkan.cpp`, `src/rendervulkan.hpp` and `src/meson.build` only.
|
||||
|
||||
The bump from `8c676c39` is deliberate: it brings upstream's `vulkan_get_rgb10_capture_format()`
|
||||
(`ff6b924`), which probes `linearTilingFeatures` for STORAGE+SAMPLED and falls back to
|
||||
`DRM_FORMAT_XBGR2101010` on devices that cannot do linear-tiled `A2R10G10B10` — i.e. every
|
||||
NVIDIA. That covers the paths that are upstream's rather than ours: the RGB intermediate
|
||||
`paint_pipewire()` acquires when the stream is YCbCr, and AVIF screenshots. Our own 10-bit RGB
|
||||
node is covered by patch `0001`, which offers `xBGR_210LE` first for the same reason.
|
||||
|
||||
```sh
|
||||
git clone https://github.com/ValveSoftware/gamescope.git
|
||||
cd gamescope
|
||||
git checkout 8c676c39
|
||||
git checkout 5fb8dce4
|
||||
git submodule update --init --recursive # or let meson fetch the subprojects
|
||||
git am /path/to/punktfunk/packaging/gamescope/patches/*.patch
|
||||
|
||||
|
||||
@@ -25,7 +25,7 @@ set -euo pipefail
|
||||
|
||||
# The pinned upstream. Bump together with the patches (they are `git am`-able and rebase cheaply —
|
||||
# two files, mirroring code that already exists in-tree; see README.md).
|
||||
GAMESCOPE_REV="8c676c399c761e4540587f61004c957993d12fea"
|
||||
GAMESCOPE_REV="5fb8dce4a09d0a68d097b9faf9513782106bc843"
|
||||
GAMESCOPE_REPO="https://github.com/ValveSoftware/gamescope.git"
|
||||
|
||||
REV="$GAMESCOPE_REV" PREFIX=/usr DESTDIR="" SRCDIR="" JOBS="" SETCAP=1
|
||||
|
||||
+19
-10
@@ -32,12 +32,12 @@ follow what the app happens to render.
|
||||
Works on the headless backend as well as a real connector: no HDR display is
|
||||
involved anywhere in the LUT set.
|
||||
---
|
||||
src/pipewire.cpp | 114 +++++++++++++++++++++++++++++++++----------
|
||||
src/pipewire.cpp | 123 ++++++++++++++++++++++++++++++++++---------
|
||||
src/steamcompmgr.cpp | 21 ++++++--
|
||||
2 files changed, 106 insertions(+), 29 deletions(-)
|
||||
2 files changed, 115 insertions(+), 29 deletions(-)
|
||||
|
||||
diff --git a/src/pipewire.cpp b/src/pipewire.cpp
|
||||
index 76b3ea8..6b56b01 100644
|
||||
index 76b3ea8..c84b19c 100644
|
||||
--- a/src/pipewire.cpp
|
||||
+++ b/src/pipewire.cpp
|
||||
@@ -18,6 +18,40 @@
|
||||
@@ -159,7 +159,7 @@ index 76b3ea8..6b56b01 100644
|
||||
params.push_back((const struct spa_pod *) spa_pod_builder_pop(builder, &obj_frame));
|
||||
|
||||
// for (auto& param : params)
|
||||
@@ -166,6 +209,14 @@ static std::vector<const struct spa_pod *> build_format_params(struct spa_pod_bu
|
||||
@@ -166,6 +209,23 @@ static std::vector<const struct spa_pod *> build_format_params(struct spa_pod_bu
|
||||
|
||||
build_format_params(builder, SPA_VIDEO_FORMAT_BGRx, params);
|
||||
build_format_params(builder, SPA_VIDEO_FORMAT_NV12, params);
|
||||
@@ -168,13 +168,22 @@ index 76b3ea8..6b56b01 100644
|
||||
+ // negotiates today's 8-bit stream keeps negotiating it bit-for-bit. Only a consumer that
|
||||
+ // asks for a 10-bit format by name — and accepts the MANDATORY BT.2020 + PQ colorimetry
|
||||
+ // above — ever reaches these.
|
||||
+ build_format_params(builder, SPA_VIDEO_FORMAT_xRGB_210LE, params);
|
||||
+ //
|
||||
+ // xBGR_210LE FIRST, and that order is correctness, not style. A consumer takes the first pod
|
||||
+ // it can use, and xBGR is the only one every vendor fills correctly: capture textures are
|
||||
+ // mappable, hence linear-tiled, and linear STORAGE for A2R10G10B10 is an optional Vulkan
|
||||
+ // feature NVIDIA does not implement — there the composite's `imageStore` lands in XBGR order,
|
||||
+ // so a consumer that took xRGB_210LE gets a buffer LABELLED XRGB2101010 and FILLED as XBGR,
|
||||
+ // i.e. red and blue swapped, with every format mapping on both ends individually correct.
|
||||
+ // A2B10G10R10 is the universally supported packed-10 format, so leading with it costs nothing
|
||||
+ // on AMD or Intel. xRGB_210LE stays as the second pod for a consumer that only speaks it.
|
||||
+ build_format_params(builder, SPA_VIDEO_FORMAT_xBGR_210LE, params);
|
||||
+ build_format_params(builder, SPA_VIDEO_FORMAT_xRGB_210LE, params);
|
||||
+#endif
|
||||
|
||||
return params;
|
||||
}
|
||||
@@ -288,7 +339,7 @@ static void dispatch_nudge(struct pipewire_state *state, int fd)
|
||||
@@ -288,7 +348,7 @@ static void dispatch_nudge(struct pipewire_state *state, int fd)
|
||||
if (s_nCaptureWidth != state->video_info.size.width || s_nCaptureHeight != state->video_info.size.height) {
|
||||
pwr_log.debugf("renegotiating stream params (size: %dx%d)", s_nCaptureWidth, s_nCaptureHeight);
|
||||
|
||||
@@ -183,7 +192,7 @@ index 76b3ea8..6b56b01 100644
|
||||
struct spa_pod_builder builder = SPA_POD_BUILDER_INIT(buf, sizeof(buf));
|
||||
std::vector<const struct spa_pod *> format_params = build_format_params(&builder);
|
||||
int ret = pw_stream_update_params(state->stream, format_params.data(), format_params.size());
|
||||
@@ -412,6 +463,12 @@ static void stream_handle_param_changed(void *data, uint32_t id, const struct sp
|
||||
@@ -412,6 +472,12 @@ static void stream_handle_param_changed(void *data, uint32_t id, const struct sp
|
||||
state->video_info.size.width, state->video_info.size.height,
|
||||
s_nRequestedWidth, s_nRequestedHeight,
|
||||
state->video_info.format, state->shm_stride, shm_size, state->dmabuf);
|
||||
@@ -196,7 +205,7 @@ index 76b3ea8..6b56b01 100644
|
||||
}
|
||||
|
||||
static void randname(char *buf)
|
||||
@@ -450,6 +507,11 @@ uint32_t spa_format_to_drm(uint32_t spa_format)
|
||||
@@ -450,6 +516,11 @@ uint32_t spa_format_to_drm(uint32_t spa_format)
|
||||
switch (spa_format)
|
||||
{
|
||||
case SPA_VIDEO_FORMAT_NV12: return DRM_FORMAT_NV12;
|
||||
@@ -208,7 +217,7 @@ index 76b3ea8..6b56b01 100644
|
||||
default:
|
||||
case SPA_VIDEO_FORMAT_BGR: return DRM_FORMAT_XRGB8888;
|
||||
}
|
||||
@@ -715,7 +777,7 @@ bool init_pipewire(void)
|
||||
@@ -715,7 +786,7 @@ bool init_pipewire(void)
|
||||
s_nOutputHeight = g_nOutputHeight;
|
||||
calculate_capture_size();
|
||||
|
||||
@@ -218,7 +227,7 @@ index 76b3ea8..6b56b01 100644
|
||||
std::vector<const struct spa_pod *> format_params = build_format_params(&builder);
|
||||
|
||||
diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
|
||||
index ff9ae1f..01b2abf 100644
|
||||
index ecb3808..83c751b 100644
|
||||
--- a/src/steamcompmgr.cpp
|
||||
+++ b/src/steamcompmgr.cpp
|
||||
@@ -2335,17 +2335,32 @@ static void paint_pipewire()
|
||||
|
||||
+3
-3
@@ -58,7 +58,7 @@ index 9fc54f0..1eb35b3 100644
|
||||
" If this is not set, and there is a HDR client, it will be tonemapped SDR.\n"
|
||||
" --sdr-gamut-wideness Set the 'wideness' of the gamut for SDR comment. 0 - 1.\n"
|
||||
diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
|
||||
index 01b2abf..5c65420 100644
|
||||
index 83c751b..a8a816f 100644
|
||||
--- a/src/steamcompmgr.cpp
|
||||
+++ b/src/steamcompmgr.cpp
|
||||
@@ -2316,6 +2316,13 @@ static void update_touch_scaling( const struct FrameInfo_t *frameInfo )
|
||||
@@ -146,9 +146,9 @@ index 01b2abf..5c65420 100644
|
||||
+ }
|
||||
+
|
||||
gamescope::Rc<CVulkanTexture> pRGBTexture = s_pPipewireBuffer->texture->isYcbcr()
|
||||
? vulkan_acquire_capture_texture( uWidth, uHeight, false, DRM_FORMAT_XRGB2101010 )
|
||||
? vulkan_acquire_capture_texture( uWidth, uHeight, false, vulkan_get_rgb10_capture_format() )
|
||||
: gamescope::Rc<CVulkanTexture>{ s_pPipewireBuffer->texture };
|
||||
@@ -8397,6 +8452,12 @@ steamcompmgr_main(int argc, char **argv)
|
||||
@@ -8404,6 +8459,12 @@ steamcompmgr_main(int argc, char **argv)
|
||||
g_FadeOutDuration = atoi(optarg);
|
||||
} else if (strcmp(opt_name, "force-windows-fullscreen") == 0) {
|
||||
bForceWindowsFullscreen = true;
|
||||
|
||||
+2
-2
@@ -62,7 +62,7 @@ index 2c4fb50..b406caf 100644
|
||||
" If this is not set, and there is a HDR client, it will be tonemapped SDR.\n"
|
||||
" --sdr-gamut-wideness Set the 'wideness' of the gamut for SDR comment. 0 - 1.\n"
|
||||
diff --git a/src/steamcompmgr.cpp b/src/steamcompmgr.cpp
|
||||
index 5c65420..0d293c6 100644
|
||||
index a8a816f..64e1a8c 100644
|
||||
--- a/src/steamcompmgr.cpp
|
||||
+++ b/src/steamcompmgr.cpp
|
||||
@@ -2323,6 +2323,12 @@ gamescope::ConVar<bool> cv_pipewire_composite_cursor{ "pipewire_composite_cursor
|
||||
@@ -127,7 +127,7 @@ index 5c65420..0d293c6 100644
|
||||
// The cursor, when this stream was asked for it. gamescope keeps the pointer OUT of the
|
||||
// PipeWire node by default — it lives on a hardware plane for scanout, and a remote-play
|
||||
// consumer that draws its own would end up with two — so a consumer that has no cursor of
|
||||
@@ -8457,6 +8490,12 @@ steamcompmgr_main(int argc, char **argv)
|
||||
@@ -8464,6 +8497,12 @@ steamcompmgr_main(int argc, char **argv)
|
||||
cv_pipewire_composite_cursor = true;
|
||||
#else
|
||||
fprintf( stderr, "gamescope: --pipewire-composite-cursor ignored (built without PipeWire)\n" );
|
||||
|
||||
+7
-10
@@ -1,4 +1,4 @@
|
||||
From 509fb928c7dc3307372629ca692f4c895c4fe984 Mon Sep 17 00:00:00 2001
|
||||
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
||||
From: =?UTF-8?q?Enrico=20B=C3=BChler?= <enrico.buehler@unom.io>
|
||||
Date: Sat, 8 Aug 2026 19:17:25 +0200
|
||||
Subject: [PATCH] punktfunk: never destroy the Vulkan device or output at exit
|
||||
@@ -49,7 +49,7 @@ Both are needed: pinning only the device relocated the fault into
|
||||
2 files changed, 35 insertions(+), 4 deletions(-)
|
||||
|
||||
diff --git a/src/rendervulkan.cpp b/src/rendervulkan.cpp
|
||||
index 5c2dd11..8cd5ca2 100644
|
||||
index 3f7ea90..0382a4b 100644
|
||||
--- a/src/rendervulkan.cpp
|
||||
+++ b/src/rendervulkan.cpp
|
||||
@@ -118,7 +118,37 @@ static VkResult vulkan_load_module()
|
||||
@@ -102,10 +102,10 @@ index 5c2dd11..8cd5ca2 100644
|
||||
static bool allDMABUFsEqual( wlr_dmabuf_attributes *pDMA )
|
||||
{
|
||||
diff --git a/src/rendervulkan.hpp b/src/rendervulkan.hpp
|
||||
index b6749d4..a9335c4 100644
|
||||
index c49b95f..ee98b38 100644
|
||||
--- a/src/rendervulkan.hpp
|
||||
+++ b/src/rendervulkan.hpp
|
||||
@@ -564,7 +564,7 @@ enum ShaderType {
|
||||
@@ -565,7 +565,7 @@ enum ShaderType {
|
||||
SHADER_TYPE_COUNT
|
||||
};
|
||||
|
||||
@@ -114,12 +114,9 @@ index b6749d4..a9335c4 100644
|
||||
|
||||
struct SamplerState
|
||||
{
|
||||
@@ -1007,4 +1007,4 @@ void vulkan_wait_idle();
|
||||
// Whether the driver implements VK_EXT_physical_device_drm
|
||||
bool vulkan_has_drm_props();
|
||||
@@ -1010,4 +1010,4 @@ bool vulkan_has_drm_props();
|
||||
|
||||
bool vulkan_has_drm_modifiers_for_features(VkFormat format, VkFormatFeatureFlags features);
|
||||
|
||||
-extern CVulkanDevice g_device;
|
||||
+extern CVulkanDevice &g_device;
|
||||
--
|
||||
2.55.0
|
||||
|
||||
|
||||
@@ -20,6 +20,14 @@
|
||||
# been stable across the 3.16 series (`src/pipewire.cpp`'s format builders, `paint_pipewire()` in
|
||||
# `src/steamcompmgr.cpp`), so this normally just works — and when it does not, the build fails
|
||||
# loudly at `patchPhase` rather than producing a gamescope that quietly cannot do HDR.
|
||||
#
|
||||
# ⚠️ Kept deliberately free of any dependency on the pinned rev. The pin moved past upstream's
|
||||
# `vulkan_get_rgb10_capture_format()` (`ff6b924`, after 3.16.25) to fix red/blue on NVIDIA, and it
|
||||
# would have been natural to have patch `0001` call it — that is what the host-side note in
|
||||
# `crates/pf-capture/src/linux/pw_pods.rs` proposes. It does NOT, precisely so this derivation
|
||||
# keeps building against a nixpkgs that still pins 3.16.25, where that symbol does not exist and
|
||||
# the failure would be an opaque C++ error rather than a patch conflict. Patch `0001` gets the
|
||||
# same outcome version-independently by offering `xBGR_210LE` ahead of `xRGB_210LE`.
|
||||
{
|
||||
lib,
|
||||
gamescope,
|
||||
|
||||
@@ -17,8 +17,24 @@
|
||||
# can't supply a passphrase non-interactively here.
|
||||
#
|
||||
# Usage (in rpm.yml, after build-rpm.sh): RPM_GPG_PRIVATE_KEY=... bash packaging/rpm/sign-rpms.sh
|
||||
#
|
||||
# Takes the RPMs to sign as arguments, defaulting to `dist/*.rpm`. The argument form exists because
|
||||
# punktfunk-gamescope is built LATER in the job than the host RPMs — it is a ~10-minute C++ build
|
||||
# behind its own cache — so it misses the main signing pass entirely and needs a second one just
|
||||
# for itself. It shipped unsigned into a `gpgcheck=1` repo that way, which made
|
||||
# `dnf install punktfunk-gamescope` fail with "The package is not signed" for every Fedora/Nobara
|
||||
# user: the package was in the channel and still uninstallable.
|
||||
set -euo pipefail
|
||||
|
||||
# Default target, and a real glob rather than a literal when nothing matched.
|
||||
if [ "$#" -gt 0 ]; then
|
||||
RPMS=("$@")
|
||||
else
|
||||
shopt -s nullglob
|
||||
RPMS=(dist/*.rpm)
|
||||
fi
|
||||
[ "${#RPMS[@]}" -gt 0 ] || { echo "no RPMs to sign" >&2; exit 1; }
|
||||
|
||||
if [ -z "${RPM_GPG_PRIVATE_KEY:-}" ]; then
|
||||
case "${GITHUB_REF:-}" in
|
||||
refs/tags/v*)
|
||||
@@ -47,11 +63,11 @@ KEYID="$(gpg --list-secret-keys --with-colons | awk -F: '/^sec:/{print $5; exit}
|
||||
# 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
|
||||
for rpm in "${RPMS[@]}"; do
|
||||
rpmsign --define "_gpg_name $KEYID" --addsign "$rpm"
|
||||
done
|
||||
|
||||
# Verify locally so a bad signature fails the build before publishing.
|
||||
rpm --import <(gpg --export --armor "$KEYID")
|
||||
rpmkeys --checksig dist/*.rpm
|
||||
echo "signed + verified $(find dist -name '*.rpm' | wc -l) RPM(s) with key $KEYID"
|
||||
rpmkeys --checksig "${RPMS[@]}"
|
||||
echo "signed + verified ${#RPMS[@]} RPM(s) with key $KEYID"
|
||||
|
||||
Reference in New Issue
Block a user