From f8d1257d358bc5c70a179d6eebe44a88c3b5ce18 Mon Sep 17 00:00:00 2001 From: "Claude (noether)" Date: Wed, 20 May 2026 11:47:24 +0200 Subject: [PATCH 1/2] ci: add check-already-published helper script CI currently rebuilds every recipe on every push. distcc-avahi hasn't changed in weeks but still burns runner-time. Add a small bash helper that takes a recipe dir (arch/ or debian/), resolves the expected pool URL on packages.reauktion.de, and prints `skip=1` or `skip=0`. Live-tested against all 14 recipes. Sources PKGBUILDs in a sandboxed subshell so epoch=, ${_pkgver/-/}, and pkgname=() arrays resolve correctly. For debian/*, extracts top-level PKGVER/PKGREL lines with an awk guard that rejects command-subst and embedded-command assignments (avoids false-positive matches against HEREDOC-quoted dkms.conf content). Wiring into build.yml lands in the next commit. --- .gitea/scripts/check-already-published.sh | 210 ++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100755 .gitea/scripts/check-already-published.sh diff --git a/.gitea/scripts/check-already-published.sh b/.gitea/scripts/check-already-published.sh new file mode 100755 index 000000000..1c19dc853 --- /dev/null +++ b/.gitea/scripts/check-already-published.sh @@ -0,0 +1,210 @@ +#!/bin/bash +# check-already-published.sh +# +# Decide whether a given recipe (arch/ or debian/) is already +# present in https://packages.reauktion.de/. Emits exactly one line to +# stdout: +# +# skip=1 — package with this version-pkgrel-arch tuple already lives in +# the pool; CI should short-circuit. +# skip=0 — file is missing or HEAD failed; CI should build + publish. +# +# Design notes: +# * For Arch recipes we source the PKGBUILD in a clean subshell so +# shell expansions (epoch=, ${_pkgver/-/}, pkgname=() arrays) resolve +# naturally. Only the first element of pkgname[] is checked — split +# packages share one source tarball / one build, so any-one-missing +# forces the full rebuild anyway. +# * For Debian recipes we extract the bare top-level PKGVER= / +# PKGREL= assignments (plus any other top-level VAR=value lines they +# reference) via grep and re-evaluate them in an isolated subshell — +# sourcing the entire build-deb.sh would run curl/tar/dpkg-deb +# against a tempdir we don't want to materialise here. +# * Epoch handling differs by ecosystem: Arch keeps `:` in the +# pool filename, Debian/reprepro strips it. +# * curl --head with -f maps non-2xx to non-zero exit, which is what we +# want — 404 means "build it". -L follows mirrors. --max-time caps +# the worst-case latency per HEAD. +set -euo pipefail + +REPO_BASE="${REPO_BASE:-https://packages.reauktion.de}" +HEAD_TIMEOUT="${HEAD_TIMEOUT:-15}" + +RECIPE_DIR="${1:?usage: $0 (e.g. arch/distcc-avahi or debian/lmcp)}" + +# Resolve relative to repo root if a leading path is passed; allow +# both `arch/foo` and absolute paths. +if [ ! -d "$RECIPE_DIR" ]; then + echo "error: recipe dir not found: $RECIPE_DIR" >&2 + exit 2 +fi + +ecosystem="${RECIPE_DIR%%/*}" + +http_head() { + local url="$1" + curl -sS -L --max-time "$HEAD_TIMEOUT" -o /dev/null \ + -w '%{http_code}' --head "$url" || echo "000" +} + +emit() { + # one-line GITHUB_OUTPUT-compatible kv + echo "skip=$1" + exit 0 +} + +case "$ecosystem" in +arch) + pkgbuild="$RECIPE_DIR/PKGBUILD" + [ -f "$pkgbuild" ] || { echo "error: $pkgbuild missing" >&2; exit 2; } + + # Source in a fresh bash to capture variables. Some PKGBUILDs run + # functions or call commands at top level — keep this fast by + # restricting PATH and trapping side effects. + eval "$( + bash --noprofile --norc -c " + set +e + # Stub out anything that might shell out; we only need variable + # assignments to land. + cd '$RECIPE_DIR' + source ./PKGBUILD >/dev/null 2>&1 || true + # pkgname may be array; print first element. + if declare -p pkgname 2>/dev/null | grep -q 'declare -a'; then + first_name=\"\${pkgname[0]}\" + else + first_name=\"\$pkgname\" + fi + if declare -p arch 2>/dev/null | grep -q 'declare -a'; then + first_arch=\"\${arch[0]}\" + else + first_arch=\"\$arch\" + fi + printf 'PB_NAME=%q\n' \"\$first_name\" + printf 'PB_VER=%q\n' \"\$pkgver\" + printf 'PB_REL=%q\n' \"\$pkgrel\" + printf 'PB_EPOCH=%q\n' \"\${epoch:-}\" + printf 'PB_ARCH=%q\n' \"\$first_arch\" + " + )" + + if [ -z "${PB_NAME:-}" ] || [ -z "${PB_VER:-}" ] || [ -z "${PB_REL:-}" ]; then + echo "error: failed to parse PKGBUILD ($RECIPE_DIR)" >&2 + emit 0 + fi + + # Pool arch: + # arch=('any') → any + # arch=('aarch64' 'x86_64') → aarch64 (we publish for both, but the + # aarch64 artifact is the canonical CI build) + # arch=('aarch64') → aarch64 + case "$PB_ARCH" in + any) pool_arch=any ;; + *) pool_arch=aarch64 ;; + esac + + # Version string with optional epoch (epoch:pkgver-pkgrel). + if [ -n "${PB_EPOCH:-}" ]; then + ver_full="${PB_EPOCH}:${PB_VER}-${PB_REL}" + else + ver_full="${PB_VER}-${PB_REL}" + fi + + # Pool URL path (arch keeps any/aarch64 split; 'any' lands in the + # aarch64 dir per current marfrit layout — both arches share the + # blob via the publish-to-both-arches step in build.yml). + pool_dir="arch/aarch64" + + base_url="${REPO_BASE}/${pool_dir}/${PB_NAME}-${ver_full}-${pool_arch}.pkg.tar" + for ext in zst xz gz; do + code=$(http_head "${base_url}.${ext}") + if [ "$code" = "200" ]; then + emit 1 + fi + done + emit 0 + ;; + +debian) + bd="$RECIPE_DIR/build-deb.sh" + ctrl="$RECIPE_DIR/control" + [ -f "$bd" ] || { echo "error: $bd missing" >&2; exit 2; } + + # Pull top-level `VAR=value` lines until we've passed PKGREL, and + # only those whose RHS is safe to re-evaluate (no command + # substitution `$(...)`, no escaped `\$`, no embedded commands like + # `DESTDIR=... meson ...`). This deliberately undershoots: we just + # need PKGVER/PKGREL plus any version vars they reference. Anything + # else (HERE=$(readlink ...), KERNELVER=\$(uname -r) inside a + # HEREDOC, etc.) gets dropped. + assigns=$(awk ' + /^[A-Z_][A-Z0-9_]*=/ { + # split into LHS and RHS + eq = index($0, "=") + lhs = substr($0, 1, eq - 1) + rhs = substr($0, eq + 1) + # strip inline `# comment` + hash = index(rhs, "#") + if (hash > 1 && substr(rhs, hash-1, 1) == " ") rhs = substr(rhs, 1, hash - 2) + # reject lines with command-subst or escaped-dollar or naked commands + if (rhs ~ /\$\(/) next + if (rhs ~ /\\\$/) next + if (rhs ~ / [a-z]/) next # e.g. `DESTDIR="$ROOT" meson ...` + print lhs "=" rhs + if (lhs == "PKGREL") exit + } + ' "$bd") + + eval "$( + bash --noprofile --norc -c " + set +e + $assigns + printf 'PKGVER=%q\n' \"\${PKGVER:-}\" + printf 'PKGREL=%q\n' \"\${PKGREL:-}\" + " + )" + + if [ -z "${PKGVER:-}" ] || [ -z "${PKGREL:-}" ]; then + echo "error: failed to parse PKGVER/PKGREL from $bd" >&2 + emit 0 + fi + + # Strip epoch (`N:` prefix) — debian pool filenames omit it. + ver_no_epoch="${PKGVER#*:}" + # If PKGVER had no colon, ${PKGVER#*:} returns PKGVER unchanged (bash quirk: + # the pattern must match for the prefix to be stripped). Guard explicitly. + case "$PKGVER" in + *:*) : ;; + *) ver_no_epoch="$PKGVER" ;; + esac + + ver_full="${ver_no_epoch}-${PKGREL}" + + # Architecture: parse control's `Architecture:` field. + if [ ! -f "$ctrl" ]; then + # Some recipes ship debian/control instead of ./control + ctrl="$RECIPE_DIR/debian/control" + fi + ctrl_arch=$(grep -m1 '^Architecture:' "$ctrl" 2>/dev/null | awk '{print $2}') + case "$ctrl_arch" in + all) file_arch=all ;; + arm64|any) file_arch=arm64 ;; + amd64) file_arch=amd64 ;; + *) file_arch=arm64 ;; # conservative default + esac + + pkg_name=$(basename "$RECIPE_DIR") + first_letter="${pkg_name:0:1}" + + url="${REPO_BASE}/debian/pool/main/${first_letter}/${pkg_name}/${pkg_name}_${ver_full}_${file_arch}.deb" + code=$(http_head "$url") + if [ "$code" = "200" ]; then + emit 1 + fi + emit 0 + ;; + +*) + echo "error: unsupported ecosystem '$ecosystem' (recipe-dir=$RECIPE_DIR)" >&2 + emit 0 + ;; +esac -- 2.47.3 From c7bb14f36989d14ce58d2f6a22948bc7f05e9d42 Mon Sep 17 00:00:00 2001 From: "Claude (noether)" Date: Wed, 20 May 2026 11:48:46 +0200 Subject: [PATCH 2/2] ci: skip jobs when package already published MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Wire .gitea/scripts/check-already-published.sh into every job in build.yml. New step `skip if already published` (id: skip-check) lands right after actions/checkout@v4 and runs the helper against the job's recipe-dir. Subsequent steps gain `if: steps.skip-check.outputs.skip != '1'`, except `wipe secrets` which keeps its existing `if: always()`. Recipe-dir per job is taken from each job's existing `cp -r arch/...` or `cd debian/...` line — no guessing. Effect: on push where only e.g. firefox-fourier changed, 13 jobs HEAD the pool, see 200, and short-circuit; only firefox-fourier rebuilds. Verified live against packages.reauktion.de — current branch tip would skip 10/14 jobs. Patch is text-based (no PyYAML round-trip) so comments and blank lines stay where they were. Diff is 190 lines added, 0 removed. --- .gitea/workflows/build.yml | 190 +++++++++++++++++++++++++++++++++++++ 1 file changed, 190 insertions(+) diff --git a/.gitea/workflows/build.yml b/.gitea/workflows/build.yml index 50d853a56..95d473dfd 100644 --- a/.gitea/workflows/build.yml +++ b/.gitea/workflows/build.yml @@ -16,13 +16,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh arch/distcc-avahi) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: bootstrap runner (idempotent) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo avahi popt python python-setuptools - name: import signing key + if: steps.skip-check.outputs.skip != '1' env: PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }} PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }} @@ -37,6 +47,7 @@ jobs: echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust - name: install deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }} run: | @@ -46,6 +57,7 @@ jobs: ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null - name: makepkg distcc-avahi + if: steps.skip-check.outputs.skip != '1' run: | set -e rm -rf /tmp/build-distcc-avahi @@ -56,6 +68,7 @@ jobs: ls -la *.pkg.tar.* | grep -v "\.sig$" - name: sign distcc-avahi + if: steps.skip-check.outputs.skip != '1' run: | set -e cd /tmp/build-distcc-avahi @@ -66,6 +79,7 @@ jobs: done - name: update aarch64 repo db + if: steps.skip-check.outputs.skip != '1' run: | set -e mkdir -p /tmp/arch-stage @@ -105,6 +119,7 @@ jobs: rm -f marfrit.files.sig - name: publish to aarch64 + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -129,13 +144,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh debian/lmcp) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: install dpkg + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed dpkg openssh rsync curl - name: install hertz deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }} run: | @@ -145,6 +170,7 @@ jobs: ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null - name: build lmcp .deb + if: steps.skip-check.outputs.skip != '1' run: | set -e cd debian/lmcp @@ -152,6 +178,7 @@ jobs: ls -la *.deb - name: upload + publish to suites + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -182,13 +209,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh arch/lmcp) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: bootstrap runner (idempotent) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo lua lua-socket - name: import signing key + if: steps.skip-check.outputs.skip != '1' env: PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }} PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }} @@ -203,6 +240,7 @@ jobs: echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust - name: install deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }} run: | @@ -212,6 +250,7 @@ jobs: ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null - name: makepkg lmcp + if: steps.skip-check.outputs.skip != '1' run: | set -e rm -rf /tmp/build-lmcp @@ -222,6 +261,7 @@ jobs: ls -la *.pkg.tar.* | grep -v "\.sig$" - name: sign lmcp + if: steps.skip-check.outputs.skip != '1' run: | set -e cd /tmp/build-lmcp @@ -232,6 +272,7 @@ jobs: done - name: publish lmcp to both arches + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -283,13 +324,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh arch/claude-his-agent) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: bootstrap runner (idempotent) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo - name: import signing key + if: steps.skip-check.outputs.skip != '1' env: PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }} PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }} @@ -304,6 +355,7 @@ jobs: echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust - name: install deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }} run: | @@ -313,6 +365,7 @@ jobs: ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null - name: makepkg claude-his-agent + if: steps.skip-check.outputs.skip != '1' run: | set -e rm -rf /tmp/build-his @@ -323,6 +376,7 @@ jobs: ls -la *.pkg.tar.* | grep -v "\.sig$" - name: sign claude-his-agent + if: steps.skip-check.outputs.skip != '1' run: | set -e cd /tmp/build-his @@ -333,6 +387,7 @@ jobs: done - name: publish claude-his-agent to both arches + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -387,13 +442,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh arch/ffmpeg-v4l2-request-fourier) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: bootstrap runner (idempotent) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo nasm - name: import signing key + if: steps.skip-check.outputs.skip != '1' env: PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }} PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }} @@ -408,6 +473,7 @@ jobs: echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust - name: install deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }} run: | @@ -417,6 +483,7 @@ jobs: ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null - name: makepkg ffmpeg-v4l2-request-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e rm -rf /tmp/build-ffmpeg-v4l2 @@ -430,6 +497,7 @@ jobs: ls -la *.pkg.tar.* | grep -v "\.sig$" - name: sign ffmpeg-v4l2-request-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e cd /tmp/build-ffmpeg-v4l2 @@ -440,6 +508,7 @@ jobs: done - name: update aarch64 repo db + if: steps.skip-check.outputs.skip != '1' run: | set -e mkdir -p /tmp/arch-stage-ffmpeg @@ -475,6 +544,7 @@ jobs: rm -f marfrit.files.sig - name: publish to aarch64 + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -500,13 +570,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh arch/libva-v4l2-request-fourier) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: bootstrap runner (idempotent) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo - name: import signing key + if: steps.skip-check.outputs.skip != '1' env: PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }} PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }} @@ -521,6 +601,7 @@ jobs: echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust - name: install deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }} run: | @@ -530,6 +611,7 @@ jobs: ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null - name: makepkg libva-v4l2-request-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e rm -rf /tmp/build-libva-v4l2 @@ -541,6 +623,7 @@ jobs: ls -la *.pkg.tar.* | grep -v "\.sig$" - name: sign libva-v4l2-request-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e cd /tmp/build-libva-v4l2 @@ -551,6 +634,7 @@ jobs: done - name: update aarch64 repo db + if: steps.skip-check.outputs.skip != '1' run: | set -e mkdir -p /tmp/arch-stage-libva @@ -586,6 +670,7 @@ jobs: rm -f marfrit.files.sig - name: publish to aarch64 + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -611,13 +696,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh arch/mpv-fourier) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: bootstrap runner (idempotent) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo - name: import signing key + if: steps.skip-check.outputs.skip != '1' env: PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }} PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }} @@ -632,6 +727,7 @@ jobs: echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust - name: install deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }} run: | @@ -641,6 +737,7 @@ jobs: ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null - name: configure [marfrit] repo + pre-install ffmpeg-v4l2-request-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e # mpv-fourier links libavcodec at build time. If the build host pulls @@ -668,6 +765,7 @@ jobs: printf 'y\ny\ny\n' | pacman -S marfrit/ffmpeg-v4l2-request-fourier - name: makepkg mpv-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e rm -rf /tmp/build-mpv @@ -679,6 +777,7 @@ jobs: ls -la *.pkg.tar.* | grep -v "\.sig$" - name: sign mpv-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e cd /tmp/build-mpv @@ -689,6 +788,7 @@ jobs: done - name: update aarch64 repo db + if: steps.skip-check.outputs.skip != '1' run: | set -e mkdir -p /tmp/arch-stage-mpv @@ -724,6 +824,7 @@ jobs: rm -f marfrit.files.sig - name: publish to aarch64 + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -746,13 +847,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh debian/claude-his-agent) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: install dpkg + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed dpkg openssh rsync curl - name: install hertz deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }} run: | @@ -762,6 +873,7 @@ jobs: ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null - name: build claude-his-agent .deb + if: steps.skip-check.outputs.skip != '1' run: | set -e cd debian/claude-his-agent @@ -769,6 +881,7 @@ jobs: ls -la *.deb - name: upload + publish to suites + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -798,7 +911,16 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh debian/ffmpeg-v4l2-request-fourier) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: install build-deps (Arch pkg names; build-deb.sh links natively) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -809,6 +931,7 @@ jobs: libvorbis libvpx libwebp x264 x265 libxml2 opus v4l-utils xz zlib - name: install hertz deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }} run: | @@ -818,6 +941,7 @@ jobs: ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null - name: build ffmpeg-v4l2-request-fourier .deb + if: steps.skip-check.outputs.skip != '1' run: | set -e cd debian/ffmpeg-v4l2-request-fourier @@ -825,6 +949,7 @@ jobs: ls -la *.deb - name: upload + publish to suites + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -851,7 +976,16 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh debian/libva-v4l2-request-fourier) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: install build-deps + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -860,6 +994,7 @@ jobs: libva libdrm systemd-libs - name: install hertz deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }} run: | @@ -869,6 +1004,7 @@ jobs: ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null - name: build libva-v4l2-request-fourier .deb + if: steps.skip-check.outputs.skip != '1' run: | set -e cd debian/libva-v4l2-request-fourier @@ -876,6 +1012,7 @@ jobs: ls -la *.deb - name: upload + publish to suites + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -905,7 +1042,16 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh debian/mpv-fourier) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: install build-deps + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -921,6 +1067,7 @@ jobs: vulkan-icd-loader wayland zlib - name: configure [marfrit] repo + pre-install ffmpeg-v4l2-request-fourier + if: steps.skip-check.outputs.skip != '1' run: | set -e curl -sLo /tmp/marfrit.gpg https://packages.reauktion.de/marfrit.gpg @@ -935,6 +1082,7 @@ jobs: printf 'y\ny\ny\n' | pacman -S marfrit/ffmpeg-v4l2-request-fourier - name: install hertz deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }} run: | @@ -944,6 +1092,7 @@ jobs: ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null - name: build mpv-fourier .deb + if: steps.skip-check.outputs.skip != '1' run: | set -e cd debian/mpv-fourier @@ -951,6 +1100,7 @@ jobs: ls -la *.deb - name: upload + publish to suites + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -978,7 +1128,16 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh debian/daedalus-v4l2) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: install build-deps (sans ffmpeg — see [marfrit] step) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -994,6 +1153,7 @@ jobs: libdrm - name: ensure ffmpeg-v4l2-request-fourier installed (link-time ABI source) + if: steps.skip-check.outputs.skip != '1' run: | set -e # Idempotent: pre-install the marfrit fourier ffmpeg so cmake @@ -1011,6 +1171,7 @@ jobs: printf 'y\ny\ny\n' | pacman -S --needed marfrit/ffmpeg-v4l2-request-fourier - name: install hertz deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }} run: | @@ -1020,6 +1181,7 @@ jobs: ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null - name: build daedalus-v4l2 .deb + if: steps.skip-check.outputs.skip != '1' run: | set -e cd debian/daedalus-v4l2 @@ -1027,6 +1189,7 @@ jobs: ls -la *.deb - name: upload + publish to suites + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -1054,13 +1217,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh debian/daedalus-v4l2-dkms) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: install tooling + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed dpkg openssh rsync curl tar gzip - name: install hertz deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_HERTZ_KEY }} run: | @@ -1070,6 +1243,7 @@ jobs: ssh-keyscan -t ed25519 hertz.fritz.box >> /root/.ssh/known_hosts 2>/dev/null - name: build daedalus-v4l2-dkms .deb + if: steps.skip-check.outputs.skip != '1' run: | set -e cd debian/daedalus-v4l2-dkms @@ -1077,6 +1251,7 @@ jobs: ls -la *.deb - name: upload + publish to suites + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } @@ -1110,13 +1285,23 @@ jobs: steps: - uses: actions/checkout@v4 + - name: skip if already published + id: skip-check + run: | + set -e + result=$(./.gitea/scripts/check-already-published.sh arch/mesa-panvk-bifrost) + echo "$result" >> "$GITHUB_OUTPUT" + echo "decision: $result" + - name: bootstrap runner (idempotent) + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } retry pacman -Syu --noconfirm --needed base-devel git rsync gnupg openssh sudo - name: import signing key + if: steps.skip-check.outputs.skip != '1' env: PRIV: ${{ secrets.MARFRIT_REPO_PRIVATE_KEY }} PASS: ${{ secrets.MARFRIT_REPO_PASSPHRASE }} @@ -1131,6 +1316,7 @@ jobs: echo "92D5E96D8F63C75E4116AA1FF5C8C4603D0D250C:6:" | gpg --import-ownertrust - name: install deploy ssh key + if: steps.skip-check.outputs.skip != '1' env: KEY: ${{ secrets.MARFRIT_REPO_DEPLOY_KEY }} run: | @@ -1140,6 +1326,7 @@ jobs: ssh-keyscan -t ed25519 nc.reauktion.de > /root/.ssh/known_hosts 2>/dev/null - name: makepkg mesa-panvk-bifrost + if: steps.skip-check.outputs.skip != '1' run: | set -e rm -rf /tmp/build-mesa-panvk-bifrost @@ -1154,6 +1341,7 @@ jobs: ls -la *.pkg.tar.* | grep -v "\.sig$" - name: sign mesa-panvk-bifrost + if: steps.skip-check.outputs.skip != '1' run: | set -e cd /tmp/build-mesa-panvk-bifrost @@ -1164,6 +1352,7 @@ jobs: done - name: update aarch64 repo db + if: steps.skip-check.outputs.skip != '1' run: | set -e mkdir -p /tmp/arch-stage-mesa-panvk @@ -1199,6 +1388,7 @@ jobs: rm -f marfrit.files.sig - name: publish to aarch64 + if: steps.skip-check.outputs.skip != '1' run: | set -e retry() { for i in 1 2 3; do "$@" && return 0; rc=$?; echo "retry $i (exit=$rc)" >&2; sleep $((i*5)); done; return 1; } -- 2.47.3