Build #8
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: Build | |
| # Produces the actual downloadable HDM release: the `hdm` (daemon) and | |
| # `hdm-greeter` (greeter, Tauri v2 — the Solid.js UI is bundled into it via | |
| # Tauri's asset embedding, so ui/dist is not shipped separately) release | |
| # binaries, plus the packaging files needed to actually install them | |
| # (systemd unit, PAM service stub, default config), tarballed up. | |
| # | |
| # This is deliberately a SEPARATE workflow from test.yml (fmt/clippy/lint/ | |
| # unit tests): test.yml is a fast correctness gate that runs on every push | |
| # and PR; this one does a full `--release` build plus a Tauri build with | |
| # all the GTK/WebKitGTK system dependencies, which takes meaningfully | |
| # longer and isn't something every PR needs to pay for. It runs: | |
| # - on every push to main (so main always has a fresh downloadable build) | |
| # - on version tags (v*.*.*), where it also attaches the tarball to a | |
| # GitHub Release | |
| # - on manual dispatch, for building a one-off from any branch/commit | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ['v*.*.*'] | |
| workflow_dispatch: | |
| env: | |
| CARGO_TERM_COLOR: always | |
| jobs: | |
| build: | |
| name: Build release binaries | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v4 | |
| - name: Install Rust | |
| uses: dtolnay/rust-toolchain@stable | |
| - name: Install Tauri Linux build dependencies | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install -y \ | |
| libwebkit2gtk-4.1-dev \ | |
| libgtk-3-dev \ | |
| librsvg2-dev \ | |
| libsoup-3.0-dev \ | |
| libjavascriptcoregtk-4.1-dev \ | |
| libayatana-appindicator3-dev \ | |
| patchelf \ | |
| build-essential | |
| - name: Install Node.js | |
| uses: actions/setup-node@v4 | |
| with: | |
| node-version: '20' | |
| # See test.yml for why this deliberately does NOT use | |
| # `cache: npm` / `cache-dependency-path`: that combination | |
| # hard-fails the whole step if the lockfile path can't be | |
| # resolved, instead of just skipping the cache. Caching is done | |
| # manually below for the same reason. | |
| - name: Cache npm dependencies (ui) | |
| uses: actions/cache@v4 | |
| with: | |
| path: ui/node_modules | |
| key: ${{ runner.os }}-npm-ui-${{ hashFiles('ui/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-npm-ui- | |
| - name: Cache npm dependencies (greeter) | |
| uses: actions/cache@v4 | |
| with: | |
| path: greeter/node_modules | |
| key: ${{ runner.os }}-npm-greeter-${{ hashFiles('greeter/package-lock.json') }} | |
| restore-keys: | | |
| ${{ runner.os }}-npm-greeter- | |
| - name: Cache cargo registry & build artifacts (release profile) | |
| uses: Swatinem/rust-cache@v2 | |
| with: | |
| workspaces: | | |
| daemon | |
| greeter | |
| key: release | |
| # ── daemon ────────────────────────────────────────────────────────── | |
| - name: cargo build --release (daemon) | |
| working-directory: daemon | |
| run: cargo build --release | |
| # ── ui + greeter ──────────────────────────────────────────────────── | |
| # `tauri build`'s beforeBuildCommand (see greeter/tauri.conf.json) | |
| # does `cd ../ui && npm run build` itself, but it does NOT run | |
| # `npm install` first — the ui/node_modules tree has to already be | |
| # there, or that step fails on the first missing package. Same | |
| # graceful `npm ci` → `npm install` fallback as test.yml (see the | |
| # comment there for why). | |
| - name: Install dependencies (ui) | |
| working-directory: ui | |
| run: | | |
| if [ -f package-lock.json ]; then | |
| npm ci | |
| else | |
| echo "::warning::ui/package-lock.json is missing — falling back to 'npm install'." | |
| npm install | |
| fi | |
| - name: Install dependencies (greeter — installs @tauri-apps/cli) | |
| working-directory: greeter | |
| run: | | |
| if [ -f package-lock.json ]; then | |
| npm ci | |
| else | |
| echo "::warning::greeter/package-lock.json is missing — falling back to 'npm install'." | |
| npm install | |
| fi | |
| # bundle.active is false in tauri.conf.json (see greeter/tauri.conf.json) | |
| # — deliberately: HDM ships as raw binaries + a systemd unit + config, | |
| # installed by build.hl / a .deb / an .rpm, not as a self-contained | |
| # Tauri .AppImage/.deb bundle. `tauri build` with active:false just | |
| # compiles the release binary and skips bundling. | |
| - name: tauri build (greeter — also builds the UI via beforeBuildCommand) | |
| working-directory: greeter | |
| run: npx tauri build | |
| - name: Verify both binaries exist and report their sizes | |
| run: | | |
| test -x daemon/target/release/hdm || { echo "::error::daemon binary missing"; exit 1; } | |
| test -x greeter/target/release/hdm-greeter || { echo "::error::greeter binary missing"; exit 1; } | |
| ls -lh daemon/target/release/hdm greeter/target/release/hdm-greeter | |
| # ── package everything needed for a real install ─────────────────── | |
| - name: Assemble release directory | |
| run: | | |
| set -euo pipefail | |
| VERSION="$(grep -m1 '^version' daemon/Cargo.toml | sed -E 's/version *= *"(.*)"/\1/')" | |
| echo "VERSION=$VERSION" >> "$GITHUB_ENV" | |
| OUT="hdm-${VERSION}-linux-x86_64" | |
| mkdir -p "$OUT" | |
| cp daemon/target/release/hdm "$OUT/hdm" | |
| cp greeter/target/release/hdm-greeter "$OUT/hdm-greeter" | |
| # config/ already contains config/systemd/hdm.service, the | |
| # default config/hdm.hk, and config/pam-hdm — there is no | |
| # separate top-level systemd/ directory in this repo. | |
| cp -r config "$OUT/" | |
| cp README.md LICENSE "$OUT/" | |
| tar -czf "${OUT}.tar.gz" "$OUT" | |
| echo "ARCHIVE=${OUT}.tar.gz" >> "$GITHUB_ENV" | |
| - name: Upload binaries artifact | |
| uses: actions/upload-artifact@v4 | |
| with: | |
| name: hdm-linux-x86_64 | |
| path: ${{ env.ARCHIVE }} | |
| retention-days: 30 | |
| # Only on a version tag (e.g. v1.0.0): also attach the tarball to a | |
| # GitHub Release so it's downloadable without digging through Actions | |
| # run history. Plain pushes to main only get the Actions artifact | |
| # above (a "latest main build", not a public release). | |
| - name: Create GitHub Release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: softprops/action-gh-release@v2 | |
| with: | |
| files: ${{ env.ARCHIVE }} | |
| generate_release_notes: true |