From 21f13c6cd574d9777092c7776373f4ed273e244c Mon Sep 17 00:00:00 2001 From: NeilClack Date: Fri, 11 Sep 2026 19:14:58 -0500 Subject: [PATCH] Consolidate Gitea CI into one event-routed workflow --- .gitea/workflows/{dev.yml => build.yml} | 64 ++++++++++++++---- .gitea/workflows/main.yml | 90 ------------------------- AGENTS.md | 11 +-- 3 files changed, 59 insertions(+), 106 deletions(-) rename .gitea/workflows/{dev.yml => build.yml} (59%) delete mode 100644 .gitea/workflows/main.yml diff --git a/.gitea/workflows/dev.yml b/.gitea/workflows/build.yml similarity index 59% rename from .gitea/workflows/dev.yml rename to .gitea/workflows/build.yml index d03ead2..f42280f 100644 --- a/.gitea/workflows/dev.yml +++ b/.gitea/workflows/build.yml @@ -1,23 +1,36 @@ -name: build-dev +name: build + on: - # Every push to dev: build, run the offline test suite, publish to the - # dev Attic cache. + # Manual dispatch: always builds the `dev` branch (regardless of the ref + # selected when dispatching) and publishes to the dev Attic cache + dev + # live-update manifest. Version fingerprint = short commit hash. + workflow_dispatch: + # Any new tag: builds the tagged revision and publishes a release to the + # release Attic cache + production live-update manifest. Version = the tag. push: - branches: [dev] + tags: ['*'] + jobs: nix-build: runs-on: build-server steps: # actions/checkout@v4 is unreliable on host-mode runners (its files are # copied into the workspace instead of the repo), so clone explicitly. + # A manual dispatch always clones `dev`; a tag push clones the tag. A full + # clone (no --depth) lets `git describe --tags` resolve the real tag. - name: Checkout run: | rm -rf ./* ./.[!.]* 2>/dev/null || true git config --global http.extraheader "Authorization: token ${{ github.token }}" - git clone --branch "${{ gitea.ref_name }}" \ + REF="${{ gitea.ref_name }}" + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + REF=dev + fi + git clone --branch "$REF" \ "${{ gitea.server_url }}/${{ gitea.repository }}.git" . test -f flake.nix git log --oneline -1 + - name: Inspect workspace run: | pwd @@ -26,12 +39,18 @@ jobs: git remote -v 2>&1 || true git describe --tags --always 2>&1 || true test -f flake.nix && echo "flake.nix present" || echo "NO flake.nix" - # Dev builds fingerprint as the short commit hash. - # Persisted via GITHUB_ENV so the impure nix eval below reads it via + + # Dev builds fingerprint as the short commit hash; releases report the + # tag. Persisted via GITHUB_ENV so the impure nix eval below reads it via # builtins.getEnv. - name: Compute version run: | - echo "APP_VERSION=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV" + if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then + echo "APP_VERSION=$(git rev-parse --short HEAD)" >> "$GITHUB_ENV" + else + echo "APP_VERSION=$(git describe --tags --always)" >> "$GITHUB_ENV" + fi + # checks is keyed per-system (checks..default); nix build's # #attr shorthand can't resolve it, so resolve the current system inline. # --impure lets the flake read APP_VERSION via builtins.getEnv @@ -40,12 +59,14 @@ jobs: run: | nix build -L ".#packages.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ --impure --out-link result-pkg + # The offline test suite runs in the check derivation's checkPhase. # This is a separate build/output from the package itself. - name: Build + offline test suite run: | nix build -L ".#checks.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ --impure --out-link result-checks + - name: Live portal tests env: RWT_LIVE_ACCOUNT_EMAIL: ${{ secrets.RWT_LIVE_ACCOUNT_EMAIL }} @@ -58,25 +79,44 @@ jobs: ./build/test_api_client ./build/test_license_service ' - # Dev closure (the actual package, not the check output) lands in the - # dev cache. + + # Manual dispatch -> dev cache; tag push -> release cache. - name: Push to Attic dev cache + if: github.event_name == 'workflow_dispatch' env: ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN_DEV }} run: | attic login radiantwave https://attic.radiantwavetech.com "$ATTIC_TOKEN" attic push radiantwave:radiantwave-dev ./result-pkg + - name: Push to Attic release cache + if: github.event_name != 'workflow_dispatch' + env: + ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN_PROD }} + run: | + attic login radiantwave https://attic.radiantwavetech.com "$ATTIC_TOKEN" + attic push radiantwave:radiantwave ./result-pkg + # Publish the manifest kiosks poll for live app updates. `storePath` - # must match exactly the closure pushed to the dev Attic cache above + # must match exactly the closure pushed to the matching Attic cache above # (readlink resolves the result-pkg out-link symlink to its real # /nix/store path), so a kiosk can `nix copy --from` it without ever # building from source. Upload mirrors the ISO scp pattern to the # fileserver via the build-server's `radiantwave-infra` SSH alias. - - name: Publish manifest + - name: Publish dev manifest + if: github.event_name == 'workflow_dispatch' run: | STOREPATH=$(readlink -f ./result-pkg) printf '{"version":"%s","storePath":"%s"}\n' "${{ env.APP_VERSION }}" "$STOREPATH" > manifest.json cat manifest.json scp manifest.json \ radiantwave-infra:/mnt/infrastructure_data/files/radiantwave-dev/manifest.json + + - name: Publish release manifest + if: github.event_name != 'workflow_dispatch' + run: | + STOREPATH=$(readlink -f ./result-pkg) + printf '{"version":"%s","storePath":"%s"}\n' "${{ env.APP_VERSION }}" "$STOREPATH" > manifest.json + cat manifest.json + scp manifest.json \ + radiantwave-infra:/mnt/infrastructure_data/files/radiantwave/manifest.json diff --git a/.gitea/workflows/main.yml b/.gitea/workflows/main.yml deleted file mode 100644 index 388b3e8..0000000 --- a/.gitea/workflows/main.yml +++ /dev/null @@ -1,90 +0,0 @@ -name: build-main - -on: - # Manual only. Dispatch against main: build, run the offline test suite, - # publish to the release Attic cache and live-update manifest. - workflow_dispatch: - -jobs: - nix-build: - runs-on: build-server - steps: - # actions/checkout@v4 is unreliable on host-mode runners (its files are - # copied into the workspace instead of the repo), so clone explicitly. - # A full clone (no --depth) is required so `git describe --tags` resolves - # the real nearest tag instead of falling back to a hash. - - name: Checkout - run: | - rm -rf ./* ./.[!.]* 2>/dev/null || true - git config --global http.extraheader "Authorization: token ${{ github.token }}" - git clone --branch "${{ gitea.ref_name }}" \ - "${{ gitea.server_url }}/${{ gitea.repository }}.git" . - test -f flake.nix - git log --oneline -1 - - - name: Inspect workspace - run: | - pwd - ls -la - git rev-parse --show-toplevel 2>&1 || true - git remote -v 2>&1 || true - git describe --tags --always 2>&1 || true - test -f flake.nix && echo "flake.nix present" || echo "NO flake.nix" - - # Release builds report the current git tag. - # Persisted via GITHUB_ENV so the impure nix eval below reads it via - # builtins.getEnv. - - name: Compute version - run: | - echo "APP_VERSION=$(git describe --tags --always)" >> "$GITHUB_ENV" - - # checks is keyed per-system (checks..default); nix build's - # #attr shorthand can't resolve it, so resolve the current system inline. - # --impure lets the flake read APP_VERSION via builtins.getEnv - # (pure evals always get the package defaults). - - name: Build package - run: | - nix build -L ".#packages.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ - --impure --out-link result-pkg - # The offline test suite runs in the check derivation's checkPhase. - # This is a separate build/output from the package itself. - - name: Build + offline test suite - run: | - nix build -L ".#checks.$(nix eval --impure --raw --expr 'builtins.currentSystem').default" \ - --impure --out-link result-checks - - - name: Live portal tests - env: - RWT_LIVE_ACCOUNT_EMAIL: ${{ secrets.RWT_LIVE_ACCOUNT_EMAIL }} - RWT_LIVE_LICENSE_EMAIL: ${{ secrets.RWT_LIVE_LICENSE_EMAIL }} - RWT_LIVE_LICENSE_KEY: ${{ secrets.RWT_LIVE_LICENSE_KEY }} - run: | - nix develop --command bash -c ' - cmake -S . -B build -G Ninja -DCMAKE_BUILD_TYPE=Debug - cmake --build build --target test_api_client test_license_service - ./build/test_api_client - ./build/test_license_service - ' - - # Release closure (the actual package, not the check output) lands in the - # release cache. - - name: Push to Attic release cache - env: - ATTIC_TOKEN: ${{ secrets.ATTIC_TOKEN_PROD }} - run: | - attic login radiantwave https://attic.radiantwavetech.com "$ATTIC_TOKEN" - attic push radiantwave:radiantwave ./result-pkg - - # Publish the manifest production kiosks poll for live app updates. - # `storePath` must match exactly the closure pushed to the release Attic - # cache above (readlink resolves the result-pkg out-link symlink to its - # real /nix/store path), so a kiosk can `nix copy --from` it without ever - # building from source. Upload mirrors the ISO scp pattern to the - # fileserver via the build-server's `radiantwave-infra` SSH alias. - - name: Publish manifest - run: | - STOREPATH=$(readlink -f ./result-pkg) - printf '{"version":"%s","storePath":"%s"}\n' "${{ env.APP_VERSION }}" "$STOREPATH" > manifest.json - cat manifest.json - scp manifest.json \ - radiantwave-infra:/mnt/infrastructure_data/files/radiantwave/manifest.json diff --git a/AGENTS.md b/AGENTS.md index 4ce1316..4b25c2a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -225,13 +225,16 @@ cached. - Do not modify files in `archive/` — reference only. - Build needs SDL3 + SDL3_ttf/image/mixer/net + GTest installed; CI uses Gitea Actions on a self-hosted host runner (`build-server`, no docker). - The workflow lives in `.gitea/workflows/build.yml` and is **manual-only** - (`workflow_dispatch`); pick the branch when dispatching. It runs + The single workflow `.gitea/workflows/build.yml` has two triggers: + **`workflow_dispatch`** always builds the `dev` branch and publishes the dev + cache/manifest, and a **tag push** (`tags: ['*']`) builds the tag and + publishes the release cache/manifest. The event name routes the steps + (`github.event_name`). It runs `nix build -L .#checks..default` (build + the offline test suite; `checks` is keyed per-system, so the workflow resolves the current system via `nix eval --impure --expr 'builtins.currentSystem'`). The build bakes - in a per-branch `APP_VERSION` — the current git tag on `main`, the current - commit hash on `dev`. The flake reads `APP_VERSION` from the environment via + in an `APP_VERSION` — the short commit hash on a manual dev run, the current + git tag on a tag push. The flake reads `APP_VERSION` from the environment via `builtins.getEnv`, so the build must pass `--impure` (pure evals get the package defaults). The live portal tests run from `nix develop` when the `RWT_LIVE_*` secrets are set and need `RWT_LIVE_ACCOUNT_EMAIL`,