f6490f4c28
The file moves (docs/ → design/, docs/api/openapi.json → api/openapi.json) landed
in d01a8fd, but the matching reference updates did not — so mgmt.rs's drift-test
`include_str!("../../../docs/api/openapi.json")` pointed at a path that no longer
exists and the host failed to build. This restores it and updates every reference:
- mgmt.rs include_str! → ../../../api/openapi.json (fixes the build)
- web/orval.config.ts codegen target, web/Dockerfile, .dockerignore
- deb/rpm/Arch packaging install paths
- CLAUDE.md, the .gitea CI workflows, code doc-comments, design-doc cross-links
docs-site route URLs (/docs/...) untouched.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
238 lines
13 KiB
YAML
238 lines
13 KiB
YAML
# Build the native punktfunk Linux CLIENT as a single-file Flatpak bundle and publish it to
|
|
# Gitea's GENERIC package registry, so the Steam Deck (and any flatpak distro) installs it
|
|
# the SteamOS-native, update-survivable way: `flatpak install --user <downloaded>.flatpak`.
|
|
# (The HOST stays an RPM/deb — it needs unsandboxed /dev/uinput + zero-copy NVENC; only the
|
|
# CLIENT is sandbox-friendly. See packaging/README.md and packaging/flatpak/README.md.)
|
|
#
|
|
# Gitea has NO flatpak/ostree registry, so the bundle lives in the generic registry:
|
|
# PUT https://git.unom.io/api/packages/unom/generic/punktfunk-client-flatpak/<version>/<file>
|
|
# GET https://git.unom.io/api/packages/unom/generic/punktfunk-client-flatpak/<version>/<file>
|
|
# On tags the bundle is ALSO attached to the Gitea release (mirrors release.yml's DMG).
|
|
#
|
|
# PRIVILEGED-BUILD CONSTRAINT: flatpak-builder runs bubblewrap, which needs user namespaces.
|
|
# In a Gitea/act_runner Docker executor that means the job container must be --privileged
|
|
# (the same runner already runs `docker build` in docker.yml, so its Docker daemon allows it).
|
|
# If your runner CANNOT grant --privileged, this job will fail at `flatpak-builder` with
|
|
# "Creating new namespace failed: Operation not permitted" — see the fallback in
|
|
# packaging/flatpak/README.md (build on the Deck via org.flatpak.Builder, or on a Linux box,
|
|
# then upload with the curl line below).
|
|
#
|
|
# REGISTRY_TOKEN: repo Actions secret, a PAT with write:package scope (shared with deb/rpm/docker).
|
|
name: flatpak
|
|
|
|
on:
|
|
push:
|
|
branches: [main]
|
|
# The flatpak is the CLIENT — only rebuild when the client/core/manifest change, not on every
|
|
# design/host push (this is a heavy flatpak-builder run). Tags (v*, the client release) build too.
|
|
paths:
|
|
- 'clients/linux/**'
|
|
- 'crates/punktfunk-core/**'
|
|
- 'packaging/flatpak/**'
|
|
- 'Cargo.lock'
|
|
- '.gitea/workflows/flatpak.yml'
|
|
tags: ['v*']
|
|
workflow_dispatch:
|
|
|
|
env:
|
|
REGISTRY: git.unom.io
|
|
OWNER: unom
|
|
APP_ID: io.unom.Punktfunk
|
|
MANIFEST: packaging/flatpak/io.unom.Punktfunk.yml
|
|
PACKAGE: punktfunk-client-flatpak # generic-registry package name
|
|
REPO_URL: https://flatpak.unom.io # shared unom OSTree repo (reusable across unom apps)
|
|
DEPLOY_DIR: unom-flatpak # ~/<dir> on unom-1 (compose + ./site tree)
|
|
|
|
jobs:
|
|
build-publish:
|
|
runs-on: ubuntu-24.04
|
|
timeout-minutes: 120
|
|
container:
|
|
# Fedora ships a recent flatpak + flatpak-builder + the kernel userns support.
|
|
# --privileged is required for bubblewrap inside the Docker executor (see header).
|
|
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
|
|
run: |
|
|
# flatpak-cargo-generator.py (master) needs aiohttp + tomlkit (NOT the old `toml`).
|
|
# gnupg2/rsync/openssh-clients: sign the OSTree repo + rsync it to unom-1 (see the deploy step).
|
|
dnf -y install flatpak flatpak-builder git python3 python3-aiohttp python3-tomlkit curl jq \
|
|
gnupg2 rsync openssh-clients
|
|
# Flathub provides the GNOME runtime/SDK + the rust-stable + ffmpeg-full extensions.
|
|
flatpak remote-add --user --if-not-exists flathub \
|
|
https://dl.flathub.org/repo/flathub.flatpakrepo
|
|
git config --global --add safe.directory "$PWD"
|
|
|
|
- name: Version + channel
|
|
# Tag vX.Y.Z -> X.Y.Z on the OSTree `stable` branch (a real release); a main push ->
|
|
# 0.3.0-ciN.g<sha> on the `canary` branch. The two branches live side-by-side in one repo
|
|
# (rsync runs without --delete), each tracked by its own .flatpakref, so `flatpak update`
|
|
# on a stable box never jumps to a canary build. The generic-registry version string allows
|
|
# letters/dots/hyphens.
|
|
run: |
|
|
SHORT=$(echo "$GITHUB_SHA" | cut -c1-8)
|
|
case "$GITHUB_REF" in
|
|
refs/tags/v*) V="${GITHUB_REF_NAME#v}"; BRANCH=stable; ALIAS=latest ;;
|
|
*) V="0.3.0-ci${GITHUB_RUN_NUMBER}.g${SHORT}"; BRANCH=canary; ALIAS=canary ;;
|
|
esac
|
|
echo "VERSION=$V" >> "$GITHUB_ENV"
|
|
echo "BUNDLE=punktfunk-client-${V}.flatpak" >> "$GITHUB_ENV"
|
|
echo "FLATPAK_BRANCH=$BRANCH" >> "$GITHUB_ENV"
|
|
echo "ALIAS=$ALIAS" >> "$GITHUB_ENV"
|
|
echo "flatpak version $V -> branch '$BRANCH' alias '$ALIAS'"
|
|
|
|
- name: Generate offline cargo sources
|
|
# flatpak builds with no network; vendor every crate from Cargo.lock into
|
|
# cargo-sources.json next to the manifest (referenced by the manifest's
|
|
# punktfunk-client module).
|
|
#
|
|
# Prune the microsoft/windows-rs git crates first: they belong to
|
|
# punktfunk-client-windows, which the flatpak never builds, and leaving them in makes
|
|
# flatpak-builder full-clone that multi-GB repo at build time → "No space left on
|
|
# device" (see packaging/flatpak/prune-windows-lock.py). The committed Cargo.lock is
|
|
# untouched; cargo --offline only needs sources for the crates it compiles.
|
|
run: |
|
|
curl -fsSL -o /tmp/flatpak-cargo-generator.py \
|
|
https://raw.githubusercontent.com/flatpak/flatpak-builder-tools/master/cargo/flatpak-cargo-generator.py
|
|
python3 packaging/flatpak/prune-windows-lock.py Cargo.lock /tmp/Cargo.flatpak.lock
|
|
python3 /tmp/flatpak-cargo-generator.py /tmp/Cargo.flatpak.lock \
|
|
-o packaging/flatpak/cargo-sources.json
|
|
|
|
- name: Build the flatpak (install deps from Flathub, offline build)
|
|
run: |
|
|
# --install-deps-from=flathub pulls everything the manifest declares: the GNOME 50
|
|
# runtime/SDK + the rust-stable (//25.08, rustc 1.96) and llvm20 SDK extensions, plus
|
|
# the runtime's auto codecs-extra (HEVC libavcodec). --disable-rofiles-fuse is the
|
|
# container-safe path (no FUSE).
|
|
# --default-branch=$FLATPAK_BRANCH pins the ref to app/io.unom.Punktfunk/x86_64/<branch>
|
|
# (canary or stable) so the matching hosted .flatpakref resolves deterministically
|
|
# (manifest sets no branch).
|
|
flatpak-builder --user --force-clean --disable-rofiles-fuse \
|
|
--default-branch="$FLATPAK_BRANCH" \
|
|
--install-deps-from=flathub \
|
|
--repo="$PWD/repo" \
|
|
"$PWD/build-dir" "$MANIFEST"
|
|
|
|
- name: Export single-file bundle
|
|
run: |
|
|
# Branch must be passed explicitly (matches --default-branch above); build-bundle
|
|
# otherwise defaults to `master` and errors "Refspec … not found".
|
|
flatpak build-bundle "$PWD/repo" "$BUNDLE" "$APP_ID" "$FLATPAK_BRANCH"
|
|
ls -lh "$BUNDLE"
|
|
|
|
- name: Publish to the Gitea generic registry
|
|
env:
|
|
TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
|
run: |
|
|
BASE="https://$REGISTRY/api/packages/$OWNER/generic/$PACKAGE"
|
|
# 1) Immutable, versioned URL.
|
|
curl -fsS --user "enricobuehler:$TOKEN" --upload-file "$BUNDLE" \
|
|
"$BASE/$VERSION/$BUNDLE"
|
|
echo "published $BASE/$VERSION/$BUNDLE"
|
|
# 2) Channel alias (stable release -> latest/, canary main build -> canary/) for the
|
|
# Decky fallback + scripts. The generic registry rejects re-uploading an existing
|
|
# version/file (409), so delete the prior alias file first (ignore 404 on run #1).
|
|
curl -fsS -o /dev/null --user "enricobuehler:$TOKEN" -X DELETE \
|
|
"$BASE/$ALIAS/punktfunk-client.flatpak" || true
|
|
curl -fsS --user "enricobuehler:$TOKEN" --upload-file "$BUNDLE" \
|
|
"$BASE/$ALIAS/punktfunk-client.flatpak"
|
|
echo "published $BASE/$ALIAS/punktfunk-client.flatpak"
|
|
|
|
# Sign the OSTree repo flatpak-builder already produced and publish it to flatpak.unom.io on
|
|
# unom-1, so users get `flatpak update` (the single-file bundle above has no remote). Mirrors
|
|
# docker.yml's deploy-docs (DEPLOY_* = the unom-ci-deploy key). No-ops cleanly until the GPG
|
|
# secret + DEPLOY_* exist, so the bundle build stays green during setup.
|
|
- name: Sign + deploy the OSTree repo to unom-1 (flatpak.unom.io)
|
|
env:
|
|
FLATPAK_GPG_PRIVATE_KEY: ${{ secrets.FLATPAK_GPG_PRIVATE_KEY }}
|
|
DEPLOY_HOST: ${{ secrets.DEPLOY_HOST }}
|
|
DEPLOY_USER: ${{ secrets.DEPLOY_USER }}
|
|
DEPLOY_PORT: ${{ secrets.DEPLOY_PORT }}
|
|
DEPLOY_SSH_KEY: ${{ secrets.DEPLOY_SSH_KEY }}
|
|
run: |
|
|
set -euo pipefail
|
|
if [ -z "${FLATPAK_GPG_PRIVATE_KEY:-}" ] || [ -z "${DEPLOY_HOST:-}" ]; then
|
|
echo "::warning::FLATPAK_GPG_PRIVATE_KEY/DEPLOY_* not set — skipping repo deploy (bundle still published)."
|
|
exit 0
|
|
fi
|
|
# 1) Import the signing key into a throwaway keyring; sign the repo.
|
|
export GNUPGHOME="$(mktemp -d)"; chmod 700 "$GNUPGHOME"
|
|
echo "$FLATPAK_GPG_PRIVATE_KEY" | base64 -d | gpg --batch --import
|
|
KEYID="$(gpg --list-keys --with-colons | awk -F: '/^fpr:/{print $10; exit}')"
|
|
# build-sign signs the COMMIT objects; build-update-repo signs the SUMMARY. Both are
|
|
# required — clients with gpg-verify=true verify the commit, so summary-only signing
|
|
# fails the pull with "GPG verification enabled, but no signatures found".
|
|
flatpak build-sign "$PWD/repo" "$APP_ID" "$FLATPAK_BRANCH" \
|
|
--gpg-sign="$KEYID" --gpg-homedir="$GNUPGHOME"
|
|
flatpak build-update-repo --generate-static-deltas \
|
|
--gpg-sign="$KEYID" --gpg-homedir="$GNUPGHOME" "$PWD/repo"
|
|
# 2) Build the install descriptors (GPGKey = the committed public key, base64).
|
|
GPGKEY="$(base64 -w0 packaging/flatpak/unom-flatpak.gpg)"
|
|
rm -rf site && mkdir -p site
|
|
cat > site/unom.flatpakrepo <<EOF
|
|
[Flatpak Repo]
|
|
Title=unom
|
|
Url=$REPO_URL/repo/
|
|
Homepage=https://punktfunk.unom.io
|
|
Comment=unom Flatpak applications
|
|
GPGKey=$GPGKEY
|
|
EOF
|
|
# Two refs, one per channel — both regenerated every run and rsync'd without --delete, so
|
|
# the server always offers both (the stable ref only resolves once a release has built the
|
|
# `stable` branch). A box installs ONE; `flatpak update` then tracks that channel's branch.
|
|
write_ref() { # <filename> <branch> <title>
|
|
cat > "site/$1" <<EOF
|
|
[Flatpak Ref]
|
|
Name=$APP_ID
|
|
Branch=$2
|
|
Url=$REPO_URL/repo/
|
|
Title=$3
|
|
Homepage=https://punktfunk.unom.io
|
|
IsRuntime=false
|
|
GPGKey=$GPGKEY
|
|
RuntimeRepo=https://dl.flathub.org/repo/flathub.flatpakrepo
|
|
EOF
|
|
}
|
|
write_ref "${APP_ID}.flatpakref" stable "Punktfunk"
|
|
write_ref "${APP_ID}.Canary.flatpakref" canary "Punktfunk (Canary)"
|
|
cat > site/index.html <<EOF
|
|
<!doctype html><meta charset=utf-8><title>unom flatpak repo</title>
|
|
<h1>unom Flatpak repository</h1>
|
|
<p>Install the Punktfunk Linux client (auto-adds Flathub for the GNOME runtime, then tracks updates).</p>
|
|
<p><b>Stable</b> (recommended — only moves on releases):</p>
|
|
<pre>flatpak install --user $REPO_URL/${APP_ID}.flatpakref
|
|
flatpak run $APP_ID</pre>
|
|
<p><b>Canary</b> (latest main build, unstable):</p>
|
|
<pre>flatpak install --user $REPO_URL/${APP_ID}.Canary.flatpakref</pre>
|
|
<p>Or add the whole remote: <code>flatpak remote-add --user --if-not-exists unom $REPO_URL/unom.flatpakrepo</code></p>
|
|
EOF
|
|
# 3) Ship to unom-1 and (re)start the static server. rsync WITHOUT --delete keeps old
|
|
# objects so clients mid-update aren't broken; the fresh signed summary advertises latest.
|
|
install -d -m700 ~/.ssh
|
|
printf '%s\n' "$DEPLOY_SSH_KEY" > ~/.ssh/deploy; chmod 600 ~/.ssh/deploy
|
|
SSH="ssh -i $HOME/.ssh/deploy -p ${DEPLOY_PORT:-22} -o StrictHostKeyChecking=accept-new"
|
|
DEST="${DEPLOY_USER}@${DEPLOY_HOST}"
|
|
$SSH "$DEST" "mkdir -p ~/$DEPLOY_DIR/site/repo"
|
|
rsync -az --info=stats1 -e "$SSH" repo/ "$DEST:$DEPLOY_DIR/site/repo/"
|
|
rsync -az -e "$SSH" site/unom.flatpakrepo "site/${APP_ID}.flatpakref" "site/${APP_ID}.Canary.flatpakref" site/index.html "$DEST:$DEPLOY_DIR/site/"
|
|
rsync -az -e "$SSH" packaging/flatpak/server/compose.production.yml packaging/flatpak/server/Caddyfile "$DEST:$DEPLOY_DIR/"
|
|
$SSH "$DEST" "cd ~/$DEPLOY_DIR && docker compose -f compose.production.yml up -d"
|
|
echo "deployed → $REPO_URL/${APP_ID}.flatpakref"
|
|
|
|
- name: Attach bundle to the Gitea release (stable tags only)
|
|
if: startsWith(gitea.ref, 'refs/tags/v')
|
|
env:
|
|
GITEA_TOKEN: ${{ secrets.REGISTRY_TOKEN }}
|
|
run: |
|
|
. scripts/ci/gitea-release.sh
|
|
RID=$(ensure_release "$GITHUB_REF_NAME" "$GITHUB_REF_NAME" auto)
|
|
upsert_asset "$RID" "$BUNDLE"
|