diff --git a/.gitea/workflows/deb.yml b/.gitea/workflows/deb.yml index 65402a2..1047367 100644 --- a/.gitea/workflows/deb.yml +++ b/.gitea/workflows/deb.yml @@ -13,7 +13,10 @@ name: deb on: push: branches: [main] - tags: ['v*'] + # 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: @@ -31,6 +34,20 @@ jobs: 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: 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 @@ -60,6 +77,8 @@ jobs: 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 @@ -81,19 +100,6 @@ jobs: echo "web console smoke: /login -> $code" [ "$code" = 200 ] || { echo "ERROR: web console failed to boot under node"; exit 1; } - - name: Version - # Tag v1.2.3 -> 1.2.3 (a real release); a main push -> 0.0.1~ciN.g, which sorts - # BEFORE 0.0.1 (the '~') yet monotonically increases by run number, so `apt upgrade` - # always moves the boxes to the newest main build. - run: | - SHORT=$(echo "$GITHUB_SHA" | cut -c1-8) - case "$GITHUB_REF" in - refs/tags/v*) V="${GITHUB_REF_NAME#v}" ;; - *) V="0.0.1~ci${GITHUB_RUN_NUMBER}.g${SHORT}" ;; - esac - echo "VERSION=$V" >> "$GITHUB_ENV" - echo "package version $V" - - name: Build .debs run: | VERSION="$VERSION" bash packaging/debian/build-deb.sh diff --git a/.gitea/workflows/rpm.yml b/.gitea/workflows/rpm.yml index 5481372..f1773a8 100644 --- a/.gitea/workflows/rpm.yml +++ b/.gitea/workflows/rpm.yml @@ -13,7 +13,9 @@ name: rpm on: push: branches: [main] - tags: ['v*'] + # HOST-scoped tags only — the Apple client's `v*` tags (release.yml) must NOT publish a host + # RPM (a `v0.1.1` client tag previously shipped a host 0.1.1 that shadowed every rolling build). + tags: ['host-v*'] workflow_dispatch: env: @@ -65,14 +67,15 @@ jobs: restore-keys: cargo-home- - name: Version - # Tag v1.2.3 -> 1.2.3-1 (release); main push -> 0.0.1-0.ciN.g, whose release "0." - # sorts BEFORE the eventual "1" yet increases by run number, so `rpm-ostree upgrade` - # always moves to the newest main build. + # host-vX.Y.Z tag -> X.Y.Z-1 (a real host release); main push -> 0.2.0-0.ciN.g, whose + # "0." release sorts BELOW the eventual 0.2.0-1 yet climbs by run number AND outranks the + # stray 0.1.1, so `rpm-ostree upgrade` truly moves to the newest build. The spec %build + # stamps PUNKTFUNK_BUILD_VERSION from these macros into the binary (--version provenance). run: | SHORT=$(echo "$GITHUB_SHA" | cut -c1-8) case "$GITHUB_REF" in - refs/tags/v*) V="${GITHUB_REF_NAME#v}"; R="1" ;; - *) V="0.0.1"; R="0.ci${GITHUB_RUN_NUMBER}.g${SHORT}" ;; + refs/tags/host-v*) V="${GITHUB_REF_NAME#host-v}"; R="1" ;; + *) V="0.2.0"; R="0.ci${GITHUB_RUN_NUMBER}.g${SHORT}" ;; esac echo "PF_VERSION=$V" >> "$GITHUB_ENV" echo "PF_RELEASE=$R" >> "$GITHUB_ENV" diff --git a/crates/punktfunk-host/build.rs b/crates/punktfunk-host/build.rs index 4c312d1..33d1d90 100644 --- a/crates/punktfunk-host/build.rs +++ b/crates/punktfunk-host/build.rs @@ -6,6 +6,19 @@ //! Codec SDK, or an import lib generated from the driver's `nvEncodeAPI64.dll` //! (`lib /def:nvenc.def /machine:x64 /out:nvencodeapi.lib` with the two exports above). fn main() { + // Build provenance: stamp the exact package/build version into the binary so a running host + // can report what it is (mgmt /health, the startup log, `--version`) and a stale/shadowed + // install is detectable. CI (deb.yml / rpm.yml / the RPM spec / the PKGBUILD) sets + // PUNKTFUNK_BUILD_VERSION to the full package version (e.g. `0.2.0~ci120.g802e98d`); a plain + // `cargo build` falls back to the crate version. Deliberately NOT git-derived — the RPM builds + // from a `git archive` tarball with no .git, and a hard git dependency would break it. + let version = std::env::var("PUNKTFUNK_BUILD_VERSION") + .ok() + .filter(|v| !v.trim().is_empty()) + .unwrap_or_else(|| std::env::var("CARGO_PKG_VERSION").unwrap_or_else(|_| "unknown".into())); + println!("cargo:rustc-env=PUNKTFUNK_VERSION={version}"); + println!("cargo:rerun-if-env-changed=PUNKTFUNK_BUILD_VERSION"); + if std::env::var_os("CARGO_FEATURE_NVENC").is_some() { if let Some(dir) = std::env::var_os("PUNKTFUNK_NVENC_LIB_DIR") { println!("cargo:rustc-link-search=native={}", dir.to_string_lossy()); diff --git a/crates/punktfunk-host/src/main.rs b/crates/punktfunk-host/src/main.rs index 19ec8ec..d0849e4 100644 --- a/crates/punktfunk-host/src/main.rs +++ b/crates/punktfunk-host/src/main.rs @@ -56,12 +56,23 @@ fn main() { } fn real_main() -> Result<()> { + let args: Vec = std::env::args().skip(1).collect(); + + // `--version` prints the build-stamped version (build.rs) to stdout and exits — no logging. + if matches!( + args.first().map(String::as_str), + Some("--version") | Some("-V") | Some("version") + ) { + println!("punktfunk-host {}", env!("PUNKTFUNK_VERSION")); + return Ok(()); + } + tracing::info!( - "punktfunk-host (punktfunk_core ABI v{})", + "punktfunk-host {} (punktfunk_core ABI v{})", + env!("PUNKTFUNK_VERSION"), punktfunk_core::ABI_VERSION ); - let args: Vec = std::env::args().skip(1).collect(); match args.first().map(String::as_str) { // GameStream host control plane (P1.1: mDNS + serverinfo) + management API, and (with // --native) the native punktfunk/1 host in the same process — the unified host. diff --git a/crates/punktfunk-host/src/mgmt.rs b/crates/punktfunk-host/src/mgmt.rs index 0d2210d..85b7b00 100644 --- a/crates/punktfunk-host/src/mgmt.rs +++ b/crates/punktfunk-host/src/mgmt.rs @@ -571,7 +571,7 @@ fn token_eq(presented: &str, expected: &str) -> bool { async fn get_health() -> Json { Json(Health { status: "ok".into(), - version: env!("CARGO_PKG_VERSION").into(), + version: env!("PUNKTFUNK_VERSION").into(), abi_version: punktfunk_core::ABI_VERSION, }) } @@ -593,7 +593,7 @@ async fn get_host_info(State(st): State>) -> Json { hostname: h.hostname.clone(), uniqueid: h.uniqueid.clone(), local_ip: h.local_ip.to_string(), - version: env!("CARGO_PKG_VERSION").into(), + version: env!("PUNKTFUNK_VERSION").into(), abi_version: punktfunk_core::ABI_VERSION, app_version: APP_VERSION.into(), gfe_version: GFE_VERSION.into(), diff --git a/packaging/arch/PKGBUILD b/packaging/arch/PKGBUILD index c110031..655d2d8 100644 --- a/packaging/arch/PKGBUILD +++ b/packaging/arch/PKGBUILD @@ -19,7 +19,7 @@ pkgbase=punktfunk # the RPM spec's `%bcond_with web` (off by default). Set PF_WITH_WEB=1 to also build punktfunk-web # (appended to pkgname + bun to makedepends below). pkgname=('punktfunk-host' 'punktfunk-client') -pkgver=0.0.1 +pkgver=0.2.0 pkgrel=1 arch=('x86_64') url="https://git.unom.io/unom/punktfunk" @@ -46,6 +46,7 @@ _repo() { printf '%s' "${PF_SRCDIR:-$srcdir/punktfunk}"; } build() { cd "$(_repo)" export RUSTUP_TOOLCHAIN=stable CARGO_TARGET_DIR="$srcdir/target" + export PUNKTFUNK_BUILD_VERSION="${pkgver}-${pkgrel}" # stamp --version / mgmt /health (build.rs) # The host's zero-copy FFI link-needs libcuda at build time; nvidia-utils provides it on an # NVIDIA builder. On a GPU-less builder symlink the CUDA stub into the link path first (same # caveat the RPM documents): ln -s "$(find / -name libcuda.so -path '*stubs*'|head -1)" /usr/lib/ diff --git a/packaging/debian/build-deb.sh b/packaging/debian/build-deb.sh index 0bd0184..f0cec39 100755 --- a/packaging/debian/build-deb.sh +++ b/packaging/debian/build-deb.sh @@ -26,7 +26,7 @@ cd "$ROOTDIR" BIN="target/release/$PKG" if [ ! -x "$BIN" ]; then echo "==> building $PKG (release)" - cargo build --release -p "$PKG" --locked + PUNKTFUNK_BUILD_VERSION="$VERSION" cargo build --release -p "$PKG" --locked # stamp --version (build.rs) fi STAGE="$(mktemp -d)" diff --git a/packaging/rpm/build-rpm.sh b/packaging/rpm/build-rpm.sh index 78ae0b4..58060bf 100755 --- a/packaging/rpm/build-rpm.sh +++ b/packaging/rpm/build-rpm.sh @@ -9,7 +9,7 @@ # Output: dist/punktfunk--..rpm (+ the -debuginfo/-debugsource subpkgs) set -euo pipefail -PF_VERSION="${PF_VERSION:-0.0.1}" +PF_VERSION="${PF_VERSION:-0.2.0}" PF_RELEASE="${PF_RELEASE:-1}" # PF_WITH_WEB=1 builds the punktfunk-web subpackage too (needs `bun` on PATH — present in the CI # builder image, not in a plain mock chroot). Default off so a bare `rpmbuild`/COPR still works. diff --git a/packaging/rpm/punktfunk.spec b/packaging/rpm/punktfunk.spec index 6139701..fa2b9a7 100644 --- a/packaging/rpm/punktfunk.spec +++ b/packaging/rpm/punktfunk.spec @@ -18,10 +18,11 @@ Name: punktfunk # Version/Release are overridable so CI can stamp a rolling snapshot: a main build passes -# --define "pf_version 0.0.1" --define "pf_release 0.ci42.gdeadbee" -# (Release starting "0." sorts BEFORE the eventual "1" release), a v* tag passes the clean -# version with "pf_release 1". A plain `rpmbuild` (or COPR) with no defines builds 0.0.1-1. -Version: %{?pf_version}%{!?pf_version:0.0.1} +# --define "pf_version 0.2.0" --define "pf_release 0.ci42.gdeadbee" +# (Release starting "0." sorts BEFORE the eventual "1" release; base 0.2.0 sits ABOVE the stray +# 0.1.1), a host-v* tag passes the clean version with "pf_release 1". A plain `rpmbuild` (or COPR) +# with no defines builds 0.2.0-1. +Version: %{?pf_version}%{!?pf_version:0.2.0} Release: %{?pf_release}%{!?pf_release:1}%{?dist} Summary: Low-latency desktop/game streaming host (Moonlight-compatible + punktfunk/1) @@ -149,7 +150,10 @@ editing. Enable with `systemctl --user enable --now punktfunk-web`. # Release build of the host + client binaries (the workspace also has the core lib). # cargo fetches crates over the network; COPR build hosts allow this. export RUSTFLAGS="%{?build_rustflags}" -cargo build --release -p punktfunk-host -p punktfunk-client-linux +# Stamp the exact NVR into the binary for --version / mgmt /health provenance (build.rs reads it). +export PUNKTFUNK_BUILD_VERSION="%{version}-%{release}" +# --locked: reproducible from (commit + Cargo.lock), matching the .deb build path. +cargo build --release --locked -p punktfunk-host -p punktfunk-client-linux %if %{with web} # Management web console: build the Nitro/Node SSR bundle (node-server preset) with bun. The