Files
punktfunk/.gitea/workflows/deb.yml
T
enricobuehler fe9921cc1c
apple / swift (push) Successful in 53s
android / android (push) Failing after 2m8s
ci / web (push) Successful in 36s
ci / docs-site (push) Successful in 39s
ci / bench (push) Successful in 1m38s
ci / rust (push) Successful in 4m59s
decky / build-publish (push) Successful in 16s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 6s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 5s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 3s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 4s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 4s
flatpak / build-publish (push) Failing after 2s
deb / build-publish (push) Failing after 2m58s
rpm / build-publish (fedora-44, punktfunk-fedora44-rpm) (push) Has been cancelled
rpm / build-publish (bazzite, punktfunk-fedora-rpm) (push) Has been cancelled
docker / deploy-docs (push) Successful in 17s
fix(dist): kill the version-shadow + add build provenance (P0)
The stale code a default install/upgrade got was a TAG LEAK: deb.yml/rpm.yml shared
`tags: ['v*']` with the Apple-client release.yml, so the v0.1.0/v0.1.1 tags cut to ship
the macOS app ALSO published host packages versioned 0.1.1 — which outranks every rolling
0.0.1~ciN / 0.0.1-0.ciN build in both registries (dpkg/rpm version compares confirm), so
`apt install`/`rpm-ostree install` silently fetched ~99-commits-stale code while the READMEs
claimed auto-tracking. Two fixes:

- Decouple host publishing from Apple `v*` tags: deb.yml/rpm.yml now trigger on `host-v*`
  only, so a client tag can never poison the host channel again.
- Bump the rolling base 0.0.1 -> 0.2.0 (deb `0.2.0~ciN`, rpm `0.2.0-0.ciN`): sits ABOVE the
  stray 0.1.1 yet BELOW a future 0.2.0 tag, and still climbs monotonically by run number — so
  `apt upgrade`/`rpm-ostree upgrade` genuinely move forward. Spec default + build scripts +
  PKGBUILD pkgver bumped to match.

Build provenance (so a stale/shadowed host is detectable): build.rs stamps PUNKTFUNK_BUILD_VERSION
(set by CI = the full package version, e.g. 0.2.0~ci120.g802e98d; falls back to the crate version
for a plain `cargo build`) into the binary via rustc-env. Surfaced in `punktfunk-host --version`,
the startup log, and the mgmt /health + /host `version` field (was a hardcoded CARGO_PKG_VERSION).
Deliberately env-driven, not git-derived — the RPM builds from a git-archive tarball with no .git.
Version computed BEFORE the build in deb.yml; the spec %build exports it from %{version}-%{release}
(and gains --locked for reproducibility parity with the .deb path). Validated: plain build reports
0.0.1, env-stamped build reports 0.2.0~ci999.gdeadbee.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-15 10:30:21 +00:00

120 lines
5.2 KiB
YAML

# Build the punktfunk-host and punktfunk-client .debs and publish them to Gitea's Debian
# package registry, so Ubuntu boxes get new builds via `apt update && apt upgrade`. Runs
# inside the same Ubuntu 26.04 rust-ci builder image as ci.yml, so dpkg-shlibdeps pins the
# runtime lib package names (libavcodec62, libpipewire-0.3-0t64, …) to exactly what the
# target boxes run.
#
# Registry (public, unom org): https://git.unom.io/unom/-/packages
# Box setup (once): see packaging/debian/README.md
#
# REGISTRY_TOKEN: repo Actions secret, a PAT with write:package scope (shared with docker.yml).
name: deb
on:
push:
branches: [main]
# HOST-scoped tags only. The Apple client uses `v*` (release.yml); those must NOT trigger a
# host publish — a `v0.1.1` client tag previously shipped a host package versioned 0.1.1 that
# outranked every rolling build (the version-shadow). Host releases use `host-v*`.
tags: ['host-v*']
workflow_dispatch:
env:
REGISTRY: git.unom.io
OWNER: unom
DISTRIBUTION: stable
COMPONENT: main
jobs:
build-publish:
runs-on: ubuntu-24.04
container:
image: git.unom.io/unom/punktfunk-rust-ci:latest
timeout-minutes: 90
steps:
- uses: actions/checkout@v4
- name: Version
# host-vX.Y.Z tag -> X.Y.Z (a real host release). A main push -> 0.2.0~ciN.g<sha>: the '~'
# sorts it BELOW the eventual 0.2.0 tag, it climbs monotonically by run number, AND it sits
# ABOVE the stray 0.1.1, so `apt upgrade` truly moves boxes forward. Computed BEFORE the
# build so it's stamped into the binary (PUNKTFUNK_BUILD_VERSION -> build.rs -> --version).
run: |
SHORT=$(echo "$GITHUB_SHA" | cut -c1-8)
case "$GITHUB_REF" in
refs/tags/host-v*) V="${GITHUB_REF_NAME#host-v}" ;;
*) V="0.2.0~ci${GITHUB_RUN_NUMBER}.g${SHORT}" ;;
esac
echo "VERSION=$V" >> "$GITHUB_ENV"
echo "package version $V"
# dpkg-shlibdeps (Depends resolution) + dpkg-deb live in dpkg-dev. The client's link
# deps are also baked into the rust-ci image, but this job runs against the image
# from the PREVIOUS push (docker.yml bootstrap note) — keep it green across image
# changes; a no-op once the image has them.
- name: dpkg-dev + client link deps
run: |
apt-get update
apt-get install -y --no-install-recommends dpkg-dev \
libgtk-4-dev libadwaita-1-dev libsdl3-dev
# Share ci.yml's cache keys so the release build reuses its registry + target artifacts.
- name: Cache keys
run: echo "rustc=$(rustc --version | cut -d' ' -f2)" >> "$GITHUB_ENV"
- uses: actions/cache@v4
with:
path: |
/usr/local/cargo/registry
/usr/local/cargo/git
key: cargo-home-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-home-
- uses: actions/cache@v4
with:
path: target
# -v2-: bypass a target cache poisoned by a disk-full build (see ci.yml). Shares the
# key with ci.yml so the release build reuses its clean artifacts.
key: cargo-target-v2-${{ env.rustc }}-${{ hashFiles('Cargo.lock') }}
restore-keys: cargo-target-v2-${{ env.rustc }}-
- name: Build release host + client
env:
PUNKTFUNK_BUILD_VERSION: ${{ env.VERSION }} # stamped into the binary (build.rs)
run: |
git config --global --add safe.directory "$PWD"
cargo build --release -p punktfunk-host -p punktfunk-client-linux --locked
- name: Build + smoke-boot web console (node-server preset)
# Gate the .deb on a real node boot: the punktfunk-web .deb runs `node .output/server`,
# so prove the node-server build exists, isn't a bun bundle, and actually serves /login.
run: |
cd web
bun install --frozen-lockfile
bun run build
if grep -q 'Bun\.serve' .output/server/index.mjs; then
echo "ERROR: web build is a bun bundle (Bun.serve) — need the node-server preset"; exit 1
fi
PORT=3009 HOST=127.0.0.1 PUNKTFUNK_UI_PASSWORD=ci node .output/server/index.mjs &
NP=$!; sleep 3
code=$(curl -s -o /dev/null -w '%{http_code}' http://127.0.0.1:3009/login || echo 000)
kill "$NP" 2>/dev/null || true
echo "web console smoke: /login -> $code"
[ "$code" = 200 ] || { echo "ERROR: web console failed to boot under node"; exit 1; }
- name: Build .debs
run: |
VERSION="$VERSION" bash packaging/debian/build-deb.sh
VERSION="$VERSION" bash packaging/debian/build-client-deb.sh
VERSION="$VERSION" bash packaging/debian/build-web-deb.sh
- name: Publish to the Gitea apt registry
env:
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
run: |
for DEB in dist/*.deb; do
echo "uploading $DEB"
# PAT owner (enricobuehler), not the push actor — matches docker.yml's registry login.
curl -fsS --user "enricobuehler:$TOKEN" --upload-file "$DEB" \
"https://$REGISTRY/api/packages/$OWNER/debian/pool/$DISTRIBUTION/$COMPONENT/upload"
done
echo "published to $OWNER/debian $DISTRIBUTION/$COMPONENT"