This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

11 kB 285 lines
1name: CI 2 3on: 4 push: 5 branches: [master] 6 pull_request: 7 workflow_dispatch: 8 9# A newer run for the same ref replaces a running one. 10concurrency: 11 group: ci-${{ github.ref }} 12 cancel-in-progress: true 13 14# One job per check shows failing checks in the run overview, the same for 15# the NixOS machines, see the eval job. 16jobs: 17 list: 18 runs-on: ubuntu-latest 19 outputs: 20 checks: ${{ steps.list.outputs.checks }} 21 steps: 22 - uses: actions/checkout@v4 23 with: 24 # Fetch all history for git-based operations 25 fetch-depth: 0 26 27 - uses: cachix/install-nix-action@v31 28 29 - id: list 30 run: | 31 checks=$(nix eval --json .#checks.x86_64-linux --apply builtins.attrNames) 32 echo "checks=$checks" >> "$GITHUB_OUTPUT" 33 34 check: 35 needs: list 36 name: ${{ matrix.check }} 37 runs-on: ubuntu-latest 38 strategy: 39 fail-fast: false 40 matrix: 41 check: ${{ fromJSON(needs.list.outputs.checks) }} 42 steps: 43 - uses: actions/checkout@v4 44 with: 45 # Fetch all history for git-based operations 46 fetch-depth: 0 47 48 - uses: cachix/install-nix-action@v31 49 50 - run: nix build -L --no-link '.#checks.x86_64-linux.${{ matrix.check }}' 51 52 outputs: 53 name: packages and devShells 54 runs-on: ubuntu-latest 55 steps: 56 - uses: actions/checkout@v4 57 with: 58 # Fetch all history for git-based operations 59 fetch-depth: 0 60 61 - uses: cachix/install-nix-action@v31 62 63 - run: | 64 for output in packages devShells; do 65 echo "$output:" 66 # shellcheck disable=SC2016 # ${...} is Nix interpolation 67 nix eval --raw ".#$output.x86_64-linux" --apply 'xs: builtins.deepSeq (builtins.mapAttrs (_: x: x.drvPath) xs) "${toString (builtins.length (builtins.attrNames xs))} evaluated\n"' 68 done 69 70 # The NixOS machines, built on plain runners with hestia (the GitHub Actions 71 # cache) as binary cache next to cache.lassul.us: 72 # 73 # - eval: evaluates ciToplevels once (iets), uploads the drv closures to hestia, 74 # lists the machines whose toplevel is in neither cache and the 75 # derivations needed by more than one of them (.github/ci-shared.sh). 76 # - shared: builds those once, so the machine jobs substitute them instead 77 # of each building them; skipped when there are none. 78 # - one job per listed machine, builds its toplevel by drv path on a lazy 79 # /nix/store (.github/lazy-store.sh): the paths it would substitute are 80 # only downloaded once a file in them is opened. 81 # 82 # Every job pushes what it added to the store to cache.lassul.us 83 # (.github/ci-build.sh), for deploys. 84 eval: 85 runs-on: ubuntu-latest 86 permissions: 87 contents: read 88 actions: read # hestia: detect evicted cache entries upfront 89 id-token: write # niks3 push 90 outputs: 91 matrix: ${{ steps.matrix.outputs.matrix }} 92 any-jobs: ${{ steps.matrix.outputs.any-jobs }} 93 manifest-version: ${{ steps.matrix.outputs.manifest-version }} 94 shared: ${{ steps.plan.outputs.shared }} 95 niks3: ${{ steps.tools.outputs.niks3 }} 96 lazy-store: ${{ steps.tools.outputs.lazy-store }} 97 steps: 98 - uses: actions/checkout@v4 99 - uses: cachix/install-nix-action@v31 100 with: 101 extra_nix_config: | 102 trusted-users = root runner 103 extra-substituters = https://cache.lassul.us 104 extra-trusted-public-keys = cache.lassul.us-1:aOMEO5TU6eLvhyPi0jmgjR2sVlGjMq3rK0MeACjTcQ0= 105 - uses: Mic92/hestia@v3 106 with: 107 upstream-cache-filter: true 108 upstream-cache-key-names: cache.nixos.org-1 cache.lassul.us-1 109 filter-drv-closures: true 110 # the niks3 client of all jobs and the lazy store of the machine jobs, 111 # the others substitute them; iets for the evaluation, its eval-jobs 112 # is nix-eval-jobs about 5 times faster (no import from derivation) 113 - id: tools 114 run: | 115 niks3=$(nix build --no-link --print-out-paths .#niks3) 116 lazy=$(nix build --no-link --print-out-paths .#lazy-store) 117 iets=$(nix build --no-link --print-out-paths .#iets) 118 { 119 echo "niks3=$niks3" 120 echo "lazy-store=$lazy" 121 echo "iets=$iets/bin/iets" 122 } >> "$GITHUB_OUTPUT" 123 PATH=$niks3/bin:$PATH .github/niks3-push.sh "$niks3" "$lazy" "$iets" 124 - id: matrix 125 uses: Mic92/hestia/matrix@v3 126 with: 127 flake: ".#ciToplevels" 128 nix-eval-jobs: "${{ steps.tools.outputs.iets }} eval-jobs --workers 4 --max-memory-size 3072" 129 - env: 130 MATRIX: ${{ steps.matrix.outputs.matrix }} 131 run: | 132 echo "not cached: $(jq -r '[.include[].name] | join(" ")' <<<"$MATRIX")" | 133 tee -a "$GITHUB_STEP_SUMMARY" 134 # the derivations the shared job builds and per machine the paths its 135 # lazy store registers 136 - id: plan 137 if: steps.matrix.outputs.any-jobs == 'true' 138 env: 139 MATRIX: ${{ steps.matrix.outputs.matrix }} 140 run: | 141 matrix=$RUNNER_TEMP/matrix.json 142 plans=$RUNNER_TEMP/plans 143 printf '%s' "$MATRIX" > "$matrix" 144 .github/ci-shared.sh "$matrix" "$plans" 145 { 146 for name in $(jq -r '.include[].name' "$matrix"); do 147 echo "- $name: $(wc -l < "$plans/$name.drvs") derivations to build" 148 done 149 echo "- shared (needed by >= 2 machines): $(wc -l < "$plans/shared.drvs")" 150 sed -E 's|^/nix/store/[^-]+-(.*)\.drv$| \1|' "$plans/shared.drvs" 151 } | tee -a "$GITHUB_STEP_SUMMARY" 152 if [ -s "$plans/shared.drvs" ]; then 153 echo "shared=true" >> "$GITHUB_OUTPUT" 154 fi 155 - if: steps.matrix.outputs.any-jobs == 'true' 156 uses: actions/upload-artifact@v4 157 with: 158 name: plans 159 path: | 160 ${{ runner.temp }}/plans/shared.drvs 161 ${{ runner.temp }}/plans/*.fetch 162 163 shared: 164 needs: eval 165 if: needs.eval.outputs.shared == 'true' 166 runs-on: ubuntu-latest 167 permissions: 168 contents: read 169 actions: read # hestia: detect evicted cache entries upfront 170 id-token: write # niks3 push 171 outputs: 172 manifest-version: ${{ steps.build.outputs.manifest-version }} 173 steps: 174 - uses: actions/checkout@v4 175 - uses: cachix/install-nix-action@v31 176 with: 177 extra_nix_config: | 178 trusted-users = root runner 179 extra-substituters = https://cache.lassul.us 180 extra-trusted-public-keys = cache.lassul.us-1:aOMEO5TU6eLvhyPi0jmgjR2sVlGjMq3rK0MeACjTcQ0= 181 - uses: Mic92/hestia@v3 182 with: 183 upstream-cache-filter: true 184 upstream-cache-key-names: cache.nixos.org-1 cache.lassul.us-1 185 wait-manifest-version: ${{ needs.eval.outputs.manifest-version }} 186 - env: 187 NIKS3: ${{ needs.eval.outputs.niks3 }} 188 run: | 189 nix-store --realise "$NIKS3" 190 echo "$NIKS3/bin" >> "$GITHUB_PATH" 191 - uses: actions/download-artifact@v4 192 with: 193 name: plans 194 path: ${{ runner.temp }}/plans 195 - id: build 196 env: 197 EVAL_MANIFEST_VERSION: ${{ needs.eval.outputs.manifest-version }} 198 run: | 199 mapfile -t shared < "$RUNNER_TEMP/plans/shared.drvs" 200 "$HESTIA_BIN" prefetch "${shared[@]/%/^*}" 201 # a failed one fails the jobs of the machines that need it 202 .github/ci-build.sh "${shared[@]/%/^*}" || 203 echo "::warning::some shared derivations failed to build" 204 # upload now instead of in the post step, so the machine jobs can 205 # wait for the manifest version that contains the shared outputs 206 "$HESTIA_BIN" drain --socket "$HESTIA_SOCKET" 2>&1 | tee "$RUNNER_TEMP/drain.txt" 207 drained=$(sed -nE 's/.*; manifest m[0-9]+#([0-9]+)$/\1/p' "$RUNNER_TEMP/drain.txt") 208 echo "manifest-version=${drained:-$EVAL_MANIFEST_VERSION}" >> "$GITHUB_OUTPUT" 209 210 build: 211 needs: [eval, shared] 212 # also when the shared job was skipped: nothing to share 213 if: >- 214 !cancelled() && needs.eval.result == 'success' && needs.eval.outputs.any-jobs == 'true' 215 && (needs.shared.result == 'success' || needs.shared.result == 'skipped') 216 name: ${{ matrix.name }} 217 runs-on: ${{ matrix.os }} 218 permissions: 219 contents: read 220 actions: read # hestia: detect evicted cache entries upfront 221 id-token: write # niks3 push 222 strategy: 223 fail-fast: false 224 matrix: ${{ fromJSON(needs.eval.outputs.matrix) }} 225 steps: 226 - uses: actions/checkout@v4 227 - uses: cachix/install-nix-action@v31 228 with: 229 extra_nix_config: | 230 trusted-users = root runner 231 extra-substituters = https://cache.lassul.us 232 extra-trusted-public-keys = cache.lassul.us-1:aOMEO5TU6eLvhyPi0jmgjR2sVlGjMq3rK0MeACjTcQ0= 233 - uses: Mic92/hestia@v3 234 with: 235 upstream-cache-filter: true 236 upstream-cache-key-names: cache.nixos.org-1 cache.lassul.us-1 237 wait-manifest-version: ${{ needs.shared.outputs.manifest-version || needs.eval.outputs.manifest-version }} 238 - env: 239 NIKS3: ${{ needs.eval.outputs.niks3 }} 240 run: | 241 nix-store --realise "$NIKS3" 242 echo "$NIKS3/bin" >> "$GITHUB_PATH" 243 - uses: actions/download-artifact@v4 244 with: 245 name: plans 246 path: ${{ runner.temp }}/plans 247 - name: build ${{ matrix.name }} 248 env: 249 NAME: ${{ matrix.name }} 250 INSTALLABLES: ${{ matrix.installables }} 251 LAZY_STORE: ${{ needs.eval.outputs.lazy-store }} 252 run: | 253 read -ra installables <<<"$INSTALLABLES" 254 # the closure needs only the caches, so it runs while the drvs are 255 # fetched 256 .github/lazy-store.sh closure "$RUNNER_TEMP/plans/$NAME.fetch" & 257 closure=$! 258 "$HESTIA_BIN" prefetch "${installables[@]}" 259 wait "$closure" 260 .github/lazy-store.sh mount 261 .github/ci-build.sh "${installables[@]}" 262 - name: lazy store log 263 if: always() 264 run: | 265 dir=$RUNNER_TEMP/lazy-store 266 if [ -s "$dir/stats.json" ]; then 267 jq -r '"\(.nar_count // 0) NARs fetched, \((.nar_bytes // 0) / 1048576 | floor) MiB"' "$dir/stats.json" 268 fi 269 cat "$dir/fuse.log" 2>/dev/null || true 270 271 # Fixed-name summary of the jobs above, the required status check for 272 # merging into master (the matrix job names change with the hosts). 273 # Skipped: no machine to build, or a job it needs failed. 274 ci: 275 needs: [list, check, outputs, eval, shared, build] 276 if: always() 277 runs-on: ubuntu-latest 278 steps: 279 - env: 280 RESULTS: ${{ join(needs.*.result, ' ') }} 281 run: | 282 echo "results: $RESULTS" 283 for r in $RESULTS; do 284 [ "$r" = success ] || [ "$r" = skipped ] || exit 1 285 done