A second checker that checked nothing anyone was waiting on
Added two commits ago and removed before it ever passed, which is the honest summary. The job re-ran `nix flake check` and the three builds on a second host and then published none of it — deliberately, because GitLab holds the only credential that should be publishing — so what it produced was run artifacts nobody fetches and a nixbuild dispatch per push. The case for it was a push reaching rickub and not GitLab. That is not how anything here is pushed, and if it ever becomes so, the fix is to push both places rather than to build twice. Against it: two failed runs and a cancellation, all of them in the same six lines of SSH plumbing — no systemctl in the image, no daemon to restart, and ssh not reading a root dotfile because $HOME is not /root. None of that was near the thing being built, and none of it taught us anything about libsPortable, which is what actually wanted proving. GitLab's pipeline proves it, on the push that matters, with the tarball at the end of it. The rickub repo stays as a mirror. A mirror that builds nothing is a reasonable thing to be; this was the other kind. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
8288c38 parent: 459c9cd deleted
.rickub/workflows/build.yml +0 -158 | deleted file mode 100644 | ||
| @@ -1,158 +0,0 @@ | ||
| 1 | -# The build, on rickub. The same `nix flake check` and the same three objects | |
| 2 | -# GitLab builds next door, for the case where a push reaches this host and not | |
| 3 | -# that one. | |
| 4 | -# | |
| 5 | -# It does not compile here, and could not: a rickub runner is a Linux x86-64 | |
| 6 | -# container, and this graph is ~800 vendored crates behind libcosmic, iced, | |
| 7 | -# wgpu and aws-lc-sys. What the runner does is evaluate, dispatch and fetch — | |
| 8 | -# eu.nixbuild.net holds every vendor path from previous runs and does the | |
| 9 | -# compiling, exactly as it does for GitLab. So the two hosts share a cache | |
| 10 | -# rather than duplicating an hour of work, and a warm pipeline here is a | |
| 11 | -# pipeline that mostly substitutes. | |
| 12 | -# | |
| 13 | -# What it deliberately does NOT do is publish. The tarballs go to GitLab's | |
| 14 | -# generic package registry, and the token for that is CI_JOB_TOKEN — a GitLab | |
| 15 | -# job's own credential, issued to the job, not something to mint and carry | |
| 16 | -# here as a long-lived secret. One publisher and one place a consumer pins | |
| 17 | -# from is also just simpler to reason about than two. This host builds, checks | |
| 18 | -# and hands the tarballs back as run artifacts; `main` on GitLab is what moves | |
| 19 | -# `latest`. | |
| 20 | -# | |
| 21 | -# Lives in .rickub/workflows/ rather than .github/workflows/ because rickub | |
| 22 | -# reads one or the other and never both — see | |
| 23 | -# https://rickub.com/docs/actions and https://rickub.com/docs/migrating-from-github | |
| 24 | -name: build | |
| 25 | - | |
| 26 | -on: | |
| 27 | - push: | |
| 28 | - pull_request: | |
| 29 | - workflow_dispatch: | |
| 30 | - | |
| 31 | -jobs: | |
| 32 | - check: | |
| 33 | - runs-on: ubuntu-latest | |
| 34 | - # A cold run vendors the world and compiles the workspace. The builder does | |
| 35 | - # the compiling, but this side waits on it, and waits on the fetch of what | |
| 36 | - # comes back. GitLab gives the same job 3h. | |
| 37 | - timeout-minutes: 180 | |
| 38 | - steps: | |
| 39 | - # The flake is fetched from the checkout, and nix wants the git tree | |
| 40 | - # rather than a shallow single commit to resolve `self` from. | |
| 41 | - - uses: actions/checkout@v4 | |
| 42 | - with: | |
| 43 | - fetch-depth: 0 | |
| 44 | - | |
| 45 | - - uses: cachix/install-nix-action@v27 | |
| 46 | - with: | |
| 47 | - extra_nix_config: | | |
| 48 | - experimental-features = nix-command flakes | |
| 49 | - | |
| 50 | - # Everything the GitLab job's before_script sets up, and for the same | |
| 51 | - # reasons — the comments there are the long version. The short one: | |
| 52 | - # | |
| 53 | - # max-jobs must NOT be zero. At zero the runner refuses to build | |
| 54 | - # anything at all, which sends the fixed-output fetches (rust | |
| 55 | - # toolchain tarballs, every crate source) to nixbuild, where the build | |
| 56 | - # sandbox has no network and they can only fail. nproc keeps those and | |
| 57 | - # crane's hundreds of trivial cargo-src derivations local and parallel; | |
| 58 | - # the expensive builds still go remote. | |
| 59 | - # | |
| 60 | - # The explicit priority on nixbuild matters. nix picks a substituter by | |
| 61 | - # priority rather than by the order listed, and an ssh-ng store | |
| 62 | - # defaults to 0 against cache.nixos.org's 40 — so without it nixbuild | |
| 63 | - # wins even for stock nixpkgs paths and they crawl down one SSH | |
| 64 | - # connection instead of coming off the CDN. | |
| 65 | - # | |
| 66 | - # Keep the builder's job count modest: nixbuild's sshd caps concurrent | |
| 67 | - # sessions and refuses the excess, which nix reports as the thoroughly | |
| 68 | - # misleading "Nix daemon disconnected unexpectedly (maybe it crashed?)". | |
| 69 | - - name: Point nix at eu.nixbuild.net | |
| 70 | - env: | |
| 71 | - NIXBUILD_SSH_KEY: ${{ secrets.NIXBUILD_SSH_KEY }} | |
| 72 | - run: | | |
| 73 | - set -eu | |
| 74 | - # ROOT's ~/.ssh. The GitLab job runs as root in a nixos/nix image and | |
| 75 | - # needs no such care; here the step below decides which install this | |
| 76 | - # is, and root is the answer either way — see the note there. | |
| 77 | - sudo mkdir -p /root/.ssh | |
| 78 | - # base64 because a CI variable can only carry a single line. | |
| 79 | - printf '%s' "$NIXBUILD_SSH_KEY" | base64 -d | sudo tee /root/.ssh/nixbuild >/dev/null | |
| 80 | - sudo chmod 600 /root/.ssh/nixbuild | |
| 81 | - 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 | |
| 82 | - printf 'eu.nixbuild.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPIQCZc54poJ8vqawd8TraNryQeJnvH1eLpIDgbiqymM\n' | sudo tee /root/.ssh/known_hosts >/dev/null | |
| 83 | - # nixbuild's paths are signed, but the key is per-account and only | |
| 84 | - # readable from its web UI, so rather than carry a second secret we | |
| 85 | - # lean on the transport — the store is reached over SSH with our own | |
| 86 | - # key. cache.nixos.org is verified by its own key either way; | |
| 87 | - # require-sigs only relaxes nixbuild. | |
| 88 | - sudo tee -a /etc/nix/nix.conf >/dev/null <<EOF | |
| 89 | - builders = ssh-ng://eu.nixbuild.net x86_64-linux - 16 1 big-parallel,benchmark | |
| 90 | - builders-use-substitutes = true | |
| 91 | - substituters = https://cache.nixos.org ssh-ng://eu.nixbuild.net?priority=50 | |
| 92 | - require-sigs = false | |
| 93 | - max-jobs = $(nproc) | |
| 94 | - EOF | |
| 95 | - # Only if there IS a daemon. The runner's installer says | |
| 96 | - # "installing Nix as root is not supported by this script" and falls | |
| 97 | - # back to a SINGLE-USER install, so there is no nix-daemon to | |
| 98 | - # restart and no systemctl in the image to try — an unconditional | |
| 99 | - # restart here exited 127 and took the job with it. | |
| 100 | - # | |
| 101 | - # Which install it is decides two things, and they happen to agree. | |
| 102 | - # A daemon reads nix.conf once at start, so appended settings need | |
| 103 | - # the restart; a single-user client reads it per invocation, so they | |
| 104 | - # are live immediately. And the process opening the SSH connection | |
| 105 | - # is root either way — the daemon in one case, this job in the | |
| 106 | - # other — so the key belongs in /root/.ssh regardless. | |
| 107 | - if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet nix-daemon; then | |
| 108 | - sudo systemctl restart nix-daemon | |
| 109 | - else | |
| 110 | - echo "single-user nix: nix.conf is read per invocation, nothing to restart" | |
| 111 | - fi | |
| 112 | - # Printed rather than assumed. If the builder is not set here, every | |
| 113 | - # derivation below is built on this runner, and the first symptom of | |
| 114 | - # that is not an error — it is three hours of compiling libcosmic. | |
| 115 | - nix config show builders | |
| 116 | - nix config show max-jobs | |
| 117 | - | |
| 118 | - # fmt, clippy and the test suite, plus all four desktop objects — the | |
| 119 | - # checks build them. This is the step that has historically failed, and | |
| 120 | - # it fails fast: fmt costs seconds and runs before anything is compiled. | |
| 121 | - - run: nix flake check -L | |
| 122 | - | |
| 123 | - # Store paths are read-only symlink farms; the runner uploads plain | |
| 124 | - # files, so dereference them into trees it can zip. | |
| 125 | - - name: Stage the objects | |
| 126 | - run: | | |
| 127 | - set -eu | |
| 128 | - nix build -L --no-link --print-out-paths .#libs .#android > /tmp/outs | |
| 129 | - mkdir -p artifacts && xargs -a /tmp/outs -I{} cp -rL {}/. artifacts/ | |
| 130 | - # Staged beside artifacts/ and not into it: libsPortable holds the | |
| 131 | - # same four sonames with a different RUNPATH, so merging the two | |
| 132 | - # trees would leave whichever was copied last under both names. | |
| 133 | - nix build -L --no-link --print-out-paths .#libsPortable > /tmp/portable | |
| 134 | - mkdir -p portable && xargs -a /tmp/portable -I{} cp -rL {}/. portable/ | |
| 135 | - | |
| 136 | - # The same three tarballs GitLab publishes, rooted at lib/ and include/ | |
| 137 | - # so a consumer's `flake = false` input resolves to ${input}/lib/… with | |
| 138 | - # nothing in between. Here they are only artifacts of the run — see the | |
| 139 | - # note at the top about why this host does not upload them anywhere. | |
| 140 | - - name: Tar them the way a consumer takes them | |
| 141 | - run: | | |
| 142 | - set -eu | |
| 143 | - tar czf x86_64-linux.tar.gz -C artifacts include \ | |
| 144 | - lib/libvidya.so lib/libjolttui.so lib/libjoltmoq.so lib/libjoltcosmic.so | |
| 145 | - # `-C portable lib include` and not a file list: the point of this one | |
| 146 | - # is the libraries that came along, and naming the four we know about | |
| 147 | - # would drop them. | |
| 148 | - tar czf x86_64-linux-portable.tar.gz -C portable lib include | |
| 149 | - tar czf android-arm64-v8a.tar.gz -C artifacts include lib/arm64-v8a | |
| 150 | - | |
| 151 | - - uses: actions/upload-artifact@v4 | |
| 152 | - with: | |
| 153 | - name: jolt-native-${{ github.sha }} | |
| 154 | - path: | | |
| 155 | - x86_64-linux.tar.gz | |
| 156 | - x86_64-linux-portable.tar.gz | |
| 157 | - android-arm64-v8a.tar.gz | |
| 158 | - if-no-files-found: error | |
| deleted file mode 100644 | |||
| @@ -1,158 +0,0 @@ | |||
| 1 | -# The build, on rickub. The same `nix flake check` and the same three objects | ||
| 2 | -# GitLab builds next door, for the case where a push reaches this host and not | ||
| 3 | -# that one. | ||
| 4 | -# | ||
| 5 | -# It does not compile here, and could not: a rickub runner is a Linux x86-64 | ||
| 6 | -# container, and this graph is ~800 vendored crates behind libcosmic, iced, | ||
| 7 | -# wgpu and aws-lc-sys. What the runner does is evaluate, dispatch and fetch — | ||
| 8 | -# eu.nixbuild.net holds every vendor path from previous runs and does the | ||
| 9 | -# compiling, exactly as it does for GitLab. So the two hosts share a cache | ||
| 10 | -# rather than duplicating an hour of work, and a warm pipeline here is a | ||
| 11 | -# pipeline that mostly substitutes. | ||
| 12 | -# | ||
| 13 | -# What it deliberately does NOT do is publish. The tarballs go to GitLab's | ||
| 14 | -# generic package registry, and the token for that is CI_JOB_TOKEN — a GitLab | ||
| 15 | -# job's own credential, issued to the job, not something to mint and carry | ||
| 16 | -# here as a long-lived secret. One publisher and one place a consumer pins | ||
| 17 | -# from is also just simpler to reason about than two. This host builds, checks | ||
| 18 | -# and hands the tarballs back as run artifacts; `main` on GitLab is what moves | ||
| 19 | -# `latest`. | ||
| 20 | -# | ||
| 21 | -# Lives in .rickub/workflows/ rather than .github/workflows/ because rickub | ||
| 22 | -# reads one or the other and never both — see | ||
| 23 | -# https://rickub.com/docs/actions and https://rickub.com/docs/migrating-from-github | ||
| 24 | -name: build | ||
| 25 | - | ||
| 26 | -on: | ||
| 27 | - push: | ||
| 28 | - pull_request: | ||
| 29 | - workflow_dispatch: | ||
| 30 | - | ||
| 31 | -jobs: | ||
| 32 | - check: | ||
| 33 | - runs-on: ubuntu-latest | ||
| 34 | - # A cold run vendors the world and compiles the workspace. The builder does | ||
| 35 | - # the compiling, but this side waits on it, and waits on the fetch of what | ||
| 36 | - # comes back. GitLab gives the same job 3h. | ||
| 37 | - timeout-minutes: 180 | ||
| 38 | - steps: | ||
| 39 | - # The flake is fetched from the checkout, and nix wants the git tree | ||
| 40 | - # rather than a shallow single commit to resolve `self` from. | ||
| 41 | - - uses: actions/checkout@v4 | ||
| 42 | - with: | ||
| 43 | - fetch-depth: 0 | ||
| 44 | - | ||
| 45 | - - uses: cachix/install-nix-action@v27 | ||
| 46 | - with: | ||
| 47 | - extra_nix_config: | | ||
| 48 | - experimental-features = nix-command flakes | ||
| 49 | - | ||
| 50 | - # Everything the GitLab job's before_script sets up, and for the same | ||
| 51 | - # reasons — the comments there are the long version. The short one: | ||
| 52 | - # | ||
| 53 | - # max-jobs must NOT be zero. At zero the runner refuses to build | ||
| 54 | - # anything at all, which sends the fixed-output fetches (rust | ||
| 55 | - # toolchain tarballs, every crate source) to nixbuild, where the build | ||
| 56 | - # sandbox has no network and they can only fail. nproc keeps those and | ||
| 57 | - # crane's hundreds of trivial cargo-src derivations local and parallel; | ||
| 58 | - # the expensive builds still go remote. | ||
| 59 | - # | ||
| 60 | - # The explicit priority on nixbuild matters. nix picks a substituter by | ||
| 61 | - # priority rather than by the order listed, and an ssh-ng store | ||
| 62 | - # defaults to 0 against cache.nixos.org's 40 — so without it nixbuild | ||
| 63 | - # wins even for stock nixpkgs paths and they crawl down one SSH | ||
| 64 | - # connection instead of coming off the CDN. | ||
| 65 | - # | ||
| 66 | - # Keep the builder's job count modest: nixbuild's sshd caps concurrent | ||
| 67 | - # sessions and refuses the excess, which nix reports as the thoroughly | ||
| 68 | - # misleading "Nix daemon disconnected unexpectedly (maybe it crashed?)". | ||
| 69 | - - name: Point nix at eu.nixbuild.net | ||
| 70 | - env: | ||
| 71 | - NIXBUILD_SSH_KEY: ${{ secrets.NIXBUILD_SSH_KEY }} | ||
| 72 | - run: | | ||
| 73 | - set -eu | ||
| 74 | - # ROOT's ~/.ssh. The GitLab job runs as root in a nixos/nix image and | ||
| 75 | - # needs no such care; here the step below decides which install this | ||
| 76 | - # is, and root is the answer either way — see the note there. | ||
| 77 | - sudo mkdir -p /root/.ssh | ||
| 78 | - # base64 because a CI variable can only carry a single line. | ||
| 79 | - printf '%s' "$NIXBUILD_SSH_KEY" | base64 -d | sudo tee /root/.ssh/nixbuild >/dev/null | ||
| 80 | - sudo chmod 600 /root/.ssh/nixbuild | ||
| 81 | - 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 | ||
| 82 | - printf 'eu.nixbuild.net ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPIQCZc54poJ8vqawd8TraNryQeJnvH1eLpIDgbiqymM\n' | sudo tee /root/.ssh/known_hosts >/dev/null | ||
| 83 | - # nixbuild's paths are signed, but the key is per-account and only | ||
| 84 | - # readable from its web UI, so rather than carry a second secret we | ||
| 85 | - # lean on the transport — the store is reached over SSH with our own | ||
| 86 | - # key. cache.nixos.org is verified by its own key either way; | ||
| 87 | - # require-sigs only relaxes nixbuild. | ||
| 88 | - sudo tee -a /etc/nix/nix.conf >/dev/null <<EOF | ||
| 89 | - builders = ssh-ng://eu.nixbuild.net x86_64-linux - 16 1 big-parallel,benchmark | ||
| 90 | - builders-use-substitutes = true | ||
| 91 | - substituters = https://cache.nixos.org ssh-ng://eu.nixbuild.net?priority=50 | ||
| 92 | - require-sigs = false | ||
| 93 | - max-jobs = $(nproc) | ||
| 94 | - EOF | ||
| 95 | - # Only if there IS a daemon. The runner's installer says | ||
| 96 | - # "installing Nix as root is not supported by this script" and falls | ||
| 97 | - # back to a SINGLE-USER install, so there is no nix-daemon to | ||
| 98 | - # restart and no systemctl in the image to try — an unconditional | ||
| 99 | - # restart here exited 127 and took the job with it. | ||
| 100 | - # | ||
| 101 | - # Which install it is decides two things, and they happen to agree. | ||
| 102 | - # A daemon reads nix.conf once at start, so appended settings need | ||
| 103 | - # the restart; a single-user client reads it per invocation, so they | ||
| 104 | - # are live immediately. And the process opening the SSH connection | ||
| 105 | - # is root either way — the daemon in one case, this job in the | ||
| 106 | - # other — so the key belongs in /root/.ssh regardless. | ||
| 107 | - if command -v systemctl >/dev/null 2>&1 && systemctl is-active --quiet nix-daemon; then | ||
| 108 | - sudo systemctl restart nix-daemon | ||
| 109 | - else | ||
| 110 | - echo "single-user nix: nix.conf is read per invocation, nothing to restart" | ||
| 111 | - fi | ||
| 112 | - # Printed rather than assumed. If the builder is not set here, every | ||
| 113 | - # derivation below is built on this runner, and the first symptom of | ||
| 114 | - # that is not an error — it is three hours of compiling libcosmic. | ||
| 115 | - nix config show builders | ||
| 116 | - nix config show max-jobs | ||
| 117 | - | ||
| 118 | - # fmt, clippy and the test suite, plus all four desktop objects — the | ||
| 119 | - # checks build them. This is the step that has historically failed, and | ||
| 120 | - # it fails fast: fmt costs seconds and runs before anything is compiled. | ||
| 121 | - - run: nix flake check -L | ||
| 122 | - | ||
| 123 | - # Store paths are read-only symlink farms; the runner uploads plain | ||
| 124 | - # files, so dereference them into trees it can zip. | ||
| 125 | - - name: Stage the objects | ||
| 126 | - run: | | ||
| 127 | - set -eu | ||
| 128 | - nix build -L --no-link --print-out-paths .#libs .#android > /tmp/outs | ||
| 129 | - mkdir -p artifacts && xargs -a /tmp/outs -I{} cp -rL {}/. artifacts/ | ||
| 130 | - # Staged beside artifacts/ and not into it: libsPortable holds the | ||
| 131 | - # same four sonames with a different RUNPATH, so merging the two | ||
| 132 | - # trees would leave whichever was copied last under both names. | ||
| 133 | - nix build -L --no-link --print-out-paths .#libsPortable > /tmp/portable | ||
| 134 | - mkdir -p portable && xargs -a /tmp/portable -I{} cp -rL {}/. portable/ | ||
| 135 | - | ||
| 136 | - # The same three tarballs GitLab publishes, rooted at lib/ and include/ | ||
| 137 | - # so a consumer's `flake = false` input resolves to ${input}/lib/… with | ||
| 138 | - # nothing in between. Here they are only artifacts of the run — see the | ||
| 139 | - # note at the top about why this host does not upload them anywhere. | ||
| 140 | - - name: Tar them the way a consumer takes them | ||
| 141 | - run: | | ||
| 142 | - set -eu | ||
| 143 | - tar czf x86_64-linux.tar.gz -C artifacts include \ | ||
| 144 | - lib/libvidya.so lib/libjolttui.so lib/libjoltmoq.so lib/libjoltcosmic.so | ||
| 145 | - # `-C portable lib include` and not a file list: the point of this one | ||
| 146 | - # is the libraries that came along, and naming the four we know about | ||
| 147 | - # would drop them. | ||
| 148 | - tar czf x86_64-linux-portable.tar.gz -C portable lib include | ||
| 149 | - tar czf android-arm64-v8a.tar.gz -C artifacts include lib/arm64-v8a | ||
| 150 | - | ||
| 151 | - - uses: actions/upload-artifact@v4 | ||
| 152 | - with: | ||
| 153 | - name: jolt-native-${{ github.sha }} | ||
| 154 | - path: | | ||
| 155 | - x86_64-linux.tar.gz | ||
| 156 | - x86_64-linux-portable.tar.gz | ||
| 157 | - android-arm64-v8a.tar.gz | ||
| 158 | - if-no-files-found: error | ||