This repository has no description
4.5 kB
118 lines
1name: farm
2
3# On-demand nix-grpc-store farm (tools/ci-farm) that builds NixOS machines,
4# each derivation once. Outputs land in cache.lassul.us via niks3.
5#
6# - coordinator: scheduler and balancer, no builder; runs until all machine
7# jobs have finished.
8# - one job per machine: joins the farm as a builder, evaluates its machine
9# and builds the toplevel through the farm, then leaves (its outputs are in
10# niks3 by then). Red when its machine fails to evaluate or build.
11#
12# Called by ci.yml for pushes to master and PRs (its `ci` check requires this
13# workflow), or dispatched by hand for some machines.
14#
15# Needs the FARM_KEY secret: the farm's TLS private key, matching
16# tools/ci-farm/farm.crt (`pass show ci-farm/key`).
17
18on:
19 workflow_call:
20 inputs:
21 machines:
22 description: NixOS machines to build, space separated (empty for all)
23 type: string
24 default: ""
25 workflow_dispatch:
26 inputs:
27 machines:
28 description: NixOS machines to build, space separated (empty for all)
29 default: ""
30
31permissions:
32 contents: read
33 id-token: write # niks3 push
34 actions: read # the jobs watch each other
35
36# The farm's iroh endpoints are fixed, so only one farm at a time, queued
37# FIFO. Called from ci.yml the calling job holds the `farm` group, and the
38# github context (github.workflow) is ci.yml's: a group of its own then, so
39# the two don't wait for each other.
40concurrency:
41 group: ${{ github.workflow == 'farm' && 'farm' || format('farm-call-{0}', github.run_id) }}
42 queue: max
43
44jobs:
45 list:
46 runs-on: ubuntu-latest
47 outputs:
48 machines: ${{ steps.list.outputs.machines }}
49 steps:
50 - uses: actions/checkout@v4
51 - uses: cachix/install-nix-action@v31
52 - id: list
53 env:
54 MACHINES: ${{ inputs.machines }}
55 run: |
56 if [ -z "$MACHINES" ]; then
57 MACHINES=$(nix eval --raw .#nixosConfigurations --apply "c: builtins.concatStringsSep \" \" (builtins.attrNames c)")
58 fi
59 # index: the machine job's builder slot on the farm, the
60 # position in the coordinator's arguments
61 machines=$(jq -cn --arg m "$MACHINES" '$m | split(" ") | map(select(. != ""))
62 | to_entries | map({ index: (.key + 1), machine: .value })')
63 echo "machines=$machines" >> "$GITHUB_OUTPUT"
64 echo "$machines" | jq .
65
66 coordinator:
67 needs: list
68 runs-on: ubuntu-latest
69 steps:
70 - uses: actions/checkout@v4
71 - uses: cachix/install-nix-action@v31
72 with:
73 extra_nix_config: |
74 trusted-users = root runner
75 extra-substituters = https://cache.lassul.us
76 extra-trusted-public-keys = cache.lassul.us-1:aOMEO5TU6eLvhyPi0jmgjR2sVlGjMq3rK0MeACjTcQ0=
77 - run: nix build -L .#ci-farm -o ci-farm
78 # so the next run substitutes it instead of compiling it on every runner
79 - env:
80 FARM_KEY: ${{ secrets.FARM_KEY }}
81 run: ./ci-farm/bin/ci-farm push ./ci-farm
82 - env:
83 FARM_KEY: ${{ secrets.FARM_KEY }}
84 GH_TOKEN: ${{ github.token }}
85 MACHINES: ${{ needs.list.outputs.machines }}
86 run: |
87 mapfile -t machines < <(jq -r '.[].machine' <<<"$MACHINES")
88 ./ci-farm/bin/ci-farm farm "${machines[@]}"
89
90 machine:
91 needs: list
92 name: ${{ matrix.machine }}
93 runs-on: ubuntu-latest
94 strategy:
95 fail-fast: false
96 # GitHub's free plan runs 20 jobs at once. The machine jobs wait for the
97 # coordinator; leave it and other workflows room, so they can't take
98 # every slot while it is still queued.
99 max-parallel: 15
100 matrix:
101 include: ${{ fromJSON(needs.list.outputs.machines) }}
102 steps:
103 - uses: actions/checkout@v4
104 - uses: cachix/install-nix-action@v31
105 with:
106 extra_nix_config: |
107 trusted-users = root runner
108 extra-substituters = https://cache.lassul.us
109 extra-trusted-public-keys = cache.lassul.us-1:aOMEO5TU6eLvhyPi0jmgjR2sVlGjMq3rK0MeACjTcQ0=
110 # Builders need each other's outputs as soon as they are pushed;
111 # a remembered miss (default: 1 h) fails the build instead.
112 narinfo-cache-negative-ttl = 0
113 - run: nix build -L .#ci-farm -o ci-farm
114 - name: build ${{ matrix.machine }}
115 env:
116 FARM_KEY: ${{ secrets.FARM_KEY }}
117 GH_TOKEN: ${{ github.token }}
118 run: ./ci-farm/bin/ci-farm machine ${{ matrix.index }} ${{ matrix.machine }}