forked from
lass.pds.lassul.us/superconfig
This repository has no description
7.6 kB
199 lines
1name: update-pkgs
2
3# Daily package and flake.lock updates, one PR per package:
4#
5# - update (one job per package): run its passthru.updateScript through
6# tools/update-pkgs, build the package on its platform (darwin-only
7# packages on macOS), push update/<pkg> on top of the current master and
8# open its PR.
9# - lock: `nix flake update`, pushed as update/flake-lock with its own PR.
10#
11# A branch whose tree already equals the new commit is left alone, so a
12# failing PR isn't built again until upstream or master changes. Otherwise
13# it is replaced by the new commit, which keeps open PRs rebased onto master.
14#
15# Pushes, PRs and auto-merge use the UPDATE_PKGS_TOKEN secret (fine-grained
16# PAT or GitHub App token with contents, pull requests and workflows
17# read/write). Unlike GITHUB_TOKEN, its pushes run ci.yml on the PR, and
18# GitHub merges the PR with a merge commit once master's ruleset (the ci
19# check) is met. That merge counts as the token's, so ci.yml runs on master
20# as well. Needs "Allow auto-merge" in the repo settings.
21
22on:
23 schedule:
24 - cron: "0 3 * * *" # daily 03:00 UTC
25 workflow_dispatch:
26 inputs:
27 packages:
28 description: Packages to update, space separated (empty for all)
29 default: ""
30 automerge:
31 description: Enable auto-merge on the PRs
32 type: boolean
33 default: true
34
35permissions:
36 contents: read
37
38concurrency:
39 group: update-pkgs
40 cancel-in-progress: false
41
42env:
43 NIX_CONFIG: |
44 extra-substituters = https://cache.lassul.us
45 extra-trusted-public-keys = cache.lassul.us-1:aOMEO5TU6eLvhyPi0jmgjR2sVlGjMq3rK0MeACjTcQ0=
46
47jobs:
48 list:
49 runs-on: ubuntu-latest
50 outputs:
51 matrix: ${{ steps.list.outputs.matrix }}
52 steps:
53 - env:
54 TOKEN: ${{ secrets.UPDATE_PKGS_TOKEN }}
55 run: |
56 if [ -z "$TOKEN" ]; then
57 echo "::error::secret UPDATE_PKGS_TOKEN is not set (fine-grained PAT or GitHub App token with contents, pull requests and workflows read/write)"
58 exit 1
59 fi
60 - uses: actions/checkout@v4
61 - uses: cachix/install-nix-action@v31
62 - id: list
63 env:
64 PACKAGES: ${{ inputs.packages }}
65 run: |
66 names() {
67 nix eval --json --impure --apply builtins.attrNames --expr \
68 "import ./tools/update-pkgs/scripts.nix { flake = toString ./.; host = \"$1\"; }"
69 }
70 # Linux packages update and build on ubuntu; the ones that only
71 # exist for darwin on macOS.
72 matrix=$(jq -cn --argjson linux "$(names x86_64-linux)" \
73 --argjson all "$(names aarch64-darwin)" --arg only "$PACKAGES" '
74 ($only | split(" ") | map(select(. != ""))) as $want
75 | [ $all[]
76 | select(($want | length) == 0 or (. as $p | $want | index($p)))
77 | if (. as $p | $linux | index($p))
78 then { pkg: ., os: "ubuntu-latest", system: "x86_64-linux" }
79 else { pkg: ., os: "macos-latest", system: "aarch64-darwin" }
80 end ]')
81 echo "matrix=$matrix" >> "$GITHUB_OUTPUT"
82 echo "$matrix" | jq .
83
84 update:
85 needs: list
86 if: needs.list.outputs.matrix != '[]'
87 name: ${{ matrix.pkg }}
88 runs-on: ${{ matrix.os }}
89 strategy:
90 fail-fast: false
91 matrix:
92 include: ${{ fromJSON(needs.list.outputs.matrix) }}
93 steps:
94 - uses: actions/checkout@v4
95 with:
96 fetch-depth: 0
97 token: ${{ secrets.UPDATE_PKGS_TOKEN }}
98 - uses: cachix/install-nix-action@v31
99 - env:
100 PKG: ${{ matrix.pkg }}
101 SYSTEM: ${{ matrix.system }}
102 GH_TOKEN: ${{ secrets.UPDATE_PKGS_TOKEN }}
103 # nix-update and the update scripts query the GitHub API
104 GITHUB_TOKEN: ${{ github.token }}
105 AUTOMERGE: ${{ github.event_name == 'schedule' || inputs.automerge }}
106 run: |
107 version() { nix eval --raw ".#packages.$SYSTEM.$PKG.version" 2>/dev/null || echo unknown; }
108 old=$(version)
109
110 nix run .#update-pkgs -- "$PKG"
111 if [ -z "$(git status --porcelain)" ]; then
112 echo "$PKG: no update"
113 exit 0
114 fi
115
116 nix build -L --no-link ".#packages.$SYSTEM.$PKG"
117
118 new=$(version)
119 prefix=pkgs
120 [ -d "pkgs/$PKG" ] || prefix=tools
121 if [ "$old" != "$new" ]; then
122 msg="$prefix.$PKG: $old -> $new"
123 else
124 msg="$prefix.$PKG: update"
125 fi
126
127 branch="update/$PKG"
128 git config user.name "github-actions[bot]"
129 git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
130 git switch -c "$branch"
131 git add -A
132 git commit -m "$msg"
133
134 if git fetch -q origin "$branch" 2>/dev/null && git diff --quiet FETCH_HEAD HEAD; then
135 echo "$PKG: $branch already has this update on this master"
136 else
137 git push --force origin "$branch"
138 fi
139
140 if [ -z "$(gh pr list --head "$branch" --state open --json number --jq '.[].number')" ]; then
141 gh pr create --base master --head "$branch" --title "$msg" \
142 --body "Automated update by the update-pkgs workflow (\`nix run .#update-pkgs -- $PKG\`), package built on $SYSTEM. Merged automatically once ci (including the build of all machines) passed."
143 fi
144 if [ "$AUTOMERGE" = true ]; then
145 gh pr merge "$branch" --auto --merge --delete-branch
146 fi
147
148 lock:
149 needs: list
150 # whole runs only, not manual runs for selected packages
151 if: inputs.packages == ''
152 runs-on: ubuntu-latest
153 steps:
154 - uses: actions/checkout@v4
155 with:
156 fetch-depth: 0
157 token: ${{ secrets.UPDATE_PKGS_TOKEN }}
158 - uses: cachix/install-nix-action@v31
159 - env:
160 GH_TOKEN: ${{ secrets.UPDATE_PKGS_TOKEN }}
161 GITHUB_TOKEN: ${{ github.token }}
162 AUTOMERGE: ${{ github.event_name == 'schedule' || inputs.automerge }}
163 run: |
164 export NIX_CONFIG="$NIX_CONFIG"$'\n'"access-tokens = github.com=$GITHUB_TOKEN"
165 nix flake update 2>&1 | tee "$RUNNER_TEMP/update.log"
166 if git diff --quiet -- flake.lock; then
167 echo "flake.lock: no update"
168 exit 0
169 fi
170
171 msg="flake.lock: update"
172 branch="update/flake-lock"
173 git config user.name "github-actions[bot]"
174 git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
175 git switch -c "$branch"
176 git commit -m "$msg" -- flake.lock
177
178 if git fetch -q origin "$branch" 2>/dev/null && git diff --quiet FETCH_HEAD HEAD; then
179 echo "flake.lock: $branch already has this update on this master"
180 else
181 git push --force origin "$branch"
182 fi
183
184 {
185 echo "Automated \`nix flake update\` by the update-pkgs workflow. Merged automatically once ci (including the build of all machines) passed."
186 echo
187 echo '```'
188 sed -n '/^• /,$p' "$RUNNER_TEMP/update.log"
189 echo '```'
190 } >"$RUNNER_TEMP/body.md"
191 pr=$(gh pr list --head "$branch" --state open --json number --jq '.[].number')
192 if [ -z "$pr" ]; then
193 gh pr create --base master --head "$branch" --title "$msg" --body-file "$RUNNER_TEMP/body.md"
194 else
195 gh pr edit "$pr" --body-file "$RUNNER_TEMP/body.md"
196 fi
197 if [ "$AUTOMERGE" = true ]; then
198 gh pr merge "$branch" --auto --merge --delete-branch
199 fi