# The build, on rickub. The same `nix flake check` and the same three objects # GitLab builds next door, for the case where a push reaches this host and not # that one. # # It does not compile here, and could not: a rickub runner is a Linux x86-64 # container, and this graph is ~800 vendored crates behind libcosmic, iced, # wgpu and aws-lc-sys. What the runner does is evaluate, dispatch and fetch — # eu.nixbuild.net holds every vendor path from previous runs and does the # compiling, exactly as it does for GitLab. So the two hosts share a cache # rather than duplicating an hour of work, and a warm pipeline here is a # pipeline that mostly substitutes. # # What it deliberately does NOT do is publish. The tarballs go to GitLab's # generic package registry, and the token for that is CI_JOB_TOKEN — a GitLab # job's own credential, issued to the job, not something to mint and carry # here as a long-lived secret. One publisher and one place a consumer pins # from is also just simpler to reason about than two. This host builds, checks # and hands the tarballs back as run artifacts; `main` on GitLab is what moves # `latest`. # # Lives in .rickub/workflows/ rather than .github/workflows/ because rickub # reads one or the other and never both — see # https://rickub.com/docs/actions and https://rickub.com/docs/migrating-from-github name: build on: push: pull_request: workflow_dispatch: jobs: check: runs-on: ubuntu-latest # A cold run vendors the world and compiles the workspace. The builder does # the compiling, but this side waits on it, and waits on the fetch of what # comes back. GitLab gives the same job 3h. timeout-minutes: 180 steps: # The flake is fetched from the checkout, and nix wants the git tree # rather than a shallow single commit to resolve `self` from. - uses: actions/checkout@v4 with: fetch-depth: 0 - uses: cachix/install-nix-action@v27 with: extra_nix_config: | experimental-features = nix-command flakes # Everything the GitLab job's before_script sets up, and for the same # reasons — the comments there are the long version. The short one: # # max-jobs must NOT be zero. At zero the runner refuses to build # anything at all, which sends the fixed-output fetches (rust # toolchain tarballs, every crate source) to nixbuild, where the build # sandbox has no network and they can only fail. nproc keeps those and # crane's hundreds of trivial cargo-src derivations local and parallel; # the expensive builds still go remote. # # The explicit priority on nixbuild matters. nix picks a substituter by # priority rather than by the order listed, and an ssh-ng store # defaults to 0 against cache.nixos.org's 40 — so without it nixbuild # wins even for stock nixpkgs paths and they crawl down one SSH # connection instead of coming off the CDN. # # Keep the builder's job count modest: nixbuild's sshd caps concurrent # sessions and refuses the excess, which nix reports as the thoroughly # misleading "Nix daemon disconnected unexpectedly (maybe it crashed?)". - name: Point nix at eu.nixbuild.net env: NIXBUILD_SSH_KEY: ${{ secrets.NIXBUILD_SSH_KEY }} run: | set -eu # ROOT's ~/.ssh. The GitLab job runs as root in a nixos/nix image and # needs no such care; here the step below decides which install this # is, and root is the answer either way — see the note there. sudo mkdir -p /root/.ssh # base64 because a CI variable can only carry a single line. printf '%s' "$NIXBUILD_SSH_KEY" | base64 -d | sudo tee /root/.ssh/nixbuild >/dev/null sudo chmod 600 /root/.ssh/nixbuild printf 'Host eu.nixbuild.net\n PubkeyAcceptedKeyTypes ssh-ed25519\n IdentityFile /root/.ssh/nixbuild\n IdentitiesOnly yes\n' | sudo tee /root/.ssh/config >/dev/null printf 'eu.nixbuild.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPIQCZc54poJ8vqawd8TraNryQeJnvH1eLpIDgbiqymM\n' | sudo tee /root/.ssh/known_hosts >/dev/null # nixbuild's paths are signed, but the key is per-account and only # readable from its web UI, so rather than carry a second secret we # lean on the transport — the store is reached over SSH with our own # key. cache.nixos.org is verified by its own key either way; # require-sigs only relaxes nixbuild. sudo tee -a /etc/nix/nix.conf >/dev/null </dev/null 2>&1 && systemctl is-active --quiet nix-daemon; then sudo systemctl restart nix-daemon else echo "single-user nix: nix.conf is read per invocation, nothing to restart" fi # Printed rather than assumed. If the builder is not set here, every # derivation below is built on this runner, and the first symptom of # that is not an error — it is three hours of compiling libcosmic. nix config show builders nix config show max-jobs # fmt, clippy and the test suite, plus all four desktop objects — the # checks build them. This is the step that has historically failed, and # it fails fast: fmt costs seconds and runs before anything is compiled. - run: nix flake check -L # Store paths are read-only symlink farms; the runner uploads plain # files, so dereference them into trees it can zip. - name: Stage the objects run: | set -eu nix build -L --no-link --print-out-paths .#libs .#android > /tmp/outs mkdir -p artifacts && xargs -a /tmp/outs -I{} cp -rL {}/. artifacts/ # Staged beside artifacts/ and not into it: libsPortable holds the # same four sonames with a different RUNPATH, so merging the two # trees would leave whichever was copied last under both names. nix build -L --no-link --print-out-paths .#libsPortable > /tmp/portable mkdir -p portable && xargs -a /tmp/portable -I{} cp -rL {}/. portable/ # The same three tarballs GitLab publishes, rooted at lib/ and include/ # so a consumer's `flake = false` input resolves to ${input}/lib/… with # nothing in between. Here they are only artifacts of the run — see the # note at the top about why this host does not upload them anywhere. - name: Tar them the way a consumer takes them run: | set -eu tar czf x86_64-linux.tar.gz -C artifacts include \ lib/libvidya.so lib/libjolttui.so lib/libjoltmoq.so lib/libjoltcosmic.so # `-C portable lib include` and not a file list: the point of this one # is the libraries that came along, and naming the four we know about # would drop them. tar czf x86_64-linux-portable.tar.gz -C portable lib include tar czf android-arm64-v8a.tar.gz -C artifacts include lib/arm64-v8a - uses: actions/upload-artifact@v4 with: name: jolt-native-${{ github.sha }} path: | x86_64-linux.tar.gz x86_64-linux-portable.tar.gz android-arm64-v8a.tar.gz if-no-files-found: error