Skip to content

Commit 9efc78a

Browse files
committed
tools: add workflow to compare Nix changes
If a change breaks e.g. the benchmark workflow, it might be not obvious to detect as we typically do not run any benchmark when bumping the nixpkgs pin. The added workflows will verify that all derivations can be built on all platforms, and report the list of changes. Signed-off-by: Antoine du Hamel <duhamelantoine1995@gmail.com>
1 parent 8fec65d commit 9efc78a

3 files changed

Lines changed: 234 additions & 20 deletions

File tree

.github/workflows/linters.yml

Lines changed: 0 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -132,26 +132,6 @@ jobs:
132132
NODE=$(command -v node) make lint-md
133133
env:
134134
NODE_RELEASED_VERSIONS: ${{ steps.get-released-versions.outputs.NODE_RELEASED_VERSIONS }}
135-
lint-nix:
136-
if: github.event.pull_request.draft == false
137-
runs-on: ubuntu-slim
138-
steps:
139-
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
140-
with:
141-
persist-credentials: false
142-
sparse-checkout: '*.nix'
143-
sparse-checkout-cone-mode: false
144-
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
145-
- name: Lint Nix files
146-
run: |
147-
nix-shell -I nixpkgs=./tools/nix/pkgs.nix -p 'nixfmt-tree' --run '
148-
treefmt --quiet --ci
149-
' && EXIT_CODE="$?" || EXIT_CODE="$?"
150-
if [ "$EXIT_CODE" != "0" ]
151-
then
152-
git --no-pager diff || true
153-
exit "$EXIT_CODE"
154-
fi
155135

156136
lint-py:
157137
if: github.event.pull_request.draft == false
Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
# This action requires the following secrets to be set on the repository:
2+
# GH_USER_TOKEN: GitHub user token, to be used by ncu and to push changes
3+
name: Comment on PR on Nix changes
4+
5+
on:
6+
workflow_run:
7+
workflows: [Nix files edited]
8+
types: [completed]
9+
10+
permissions: {}
11+
12+
jobs:
13+
aggregate-results:
14+
if: ${{ github.event.workflow_run.conclusion == 'success' }}
15+
name: Aggregate results
16+
runs-on: ubuntu-slim
17+
permissions:
18+
pull-requests: write
19+
steps:
20+
- name: Download artefacts
21+
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1
22+
with:
23+
run-id: ${{ github.event.workflow_run.id }}
24+
# Using privileged token to be able to download file from a different workflow
25+
github-token: ${{ secrets.GH_USER_TOKEN }}
26+
27+
- name: Fetch PR data
28+
id: pr-data
29+
run: |
30+
mv requisites-*/* .
31+
ls
32+
echo "NUMBER=$(grep -E '^[0-9]+$' pr_number.txt || true)" >> "$GITHUB_OUTPUT"
33+
34+
- name: Aggregate results
35+
if: ${{ steps.pr-data.outputs.NUMBER }}
36+
run: |
37+
set -x
38+
> requisites-before.list
39+
> requisites-after.list
40+
TABLE=$(
41+
echo '| Platform | Number of requisites | Proportion of new derivations |'
42+
echo '| :-: | -: | -: |'
43+
TOTAL_BEFORE=0
44+
TOTAL_AFTER=0
45+
TOTAL_CHANGED=0
46+
QUOTE='`'
47+
for PLATFORM in x86_64-linux aarch64-linux x86_64-darwin aarch64-darwin; do
48+
BEFORE=$(wc -l < "requisites-${PLATFORM}-before.list")
49+
TOTAL_BEFORE=$(($TOTAL_BEFORE + $BEFORE))
50+
AFTER=$(wc -l < "requisites-${PLATFORM}-after.list")
51+
TOTAL_AFTER=$(($TOTAL_AFTER + $AFTER))
52+
DIFF="_no changes_"
53+
[ "$BEFORE" = "$AFTER" ] || DIFF="**$([ "$AFTER" < "$BEFORE" ] || echo '+')$(($AFTER - $BEFORE))**"
54+
CHANGED=$(git diff --no-index "requisites-${PLATFORM}-before.list" "requisites-${PLATFORM}-after.list" | grep -c '^+[^+]')
55+
TOTAL_CHANGED=$(($TOTAL_CHANGED + $CHANGED))
56+
PERCENT=100
57+
[ "$CHANGED" = "$AFTER" ] || {
58+
PERMILLE=$((1000 * $CHANGED / $AFTER))
59+
PERCENT="$((PERMILLE / 10)).$((PERMILLE % 10))"
60+
}
61+
echo "| ${QUOTE}${PLATFORM}${QUOTE} | $BEFORE -> $AFTER => $DIFF | $CHANGED / $AFTER = $PERCENT% |"
62+
awk '{ print $0 " ('"$PLATFORM"')" }' "requisites-${PLATFORM}-before.list" >> requisites-before.list
63+
awk '{ print $0 " ('"$PLATFORM"')" }' "requisites-${PLATFORM}-after.list" >> requisites-after.list
64+
done
65+
66+
DIFF="_no changes_"
67+
[ "$TOTAL_BEFORE" = "$TOTAL_AFTER" ] || DIFF="**$([ "$TOTAL_AFTER" < "$TOTAL_BEFORE" ] || echo '+')$(($TOTAL_AFTER - $TOTAL_BEFORE))**"
68+
PERCENT=100
69+
[ "$TOTAL_CHANGED" = "$TOTAL_AFTER" ] || {
70+
PERMILLE=$((1000 * $TOTAL_CHANGED / $TOTAL_AFTER))
71+
PERCENT="$((PERMILLE / 10)).$((PERMILLE % 10))"
72+
}
73+
echo "| **Total** | $TOTAL_BEFORE -> $TOTAL_AFTER => $DIFF | $TOTAL_CHANGED / $TOTAL_AFTER = $PERCENT% |"
74+
)
75+
sort -k1.45 requisites-before.list > requisites-before.sort
76+
sort -k1.45 requisites-after.list > requisites-after.sort
77+
if git diff -U0 --no-color --no-index requisites-before.sort requisites-after.sort > requisites.diff; then
78+
echo 'No changes detected.'
79+
else
80+
{
81+
echo "$TABLE"
82+
echo
83+
echo '<details><summary>Changelog</summary>'
84+
echo
85+
echo '```diff'
86+
tail -n +5 requisites.diff
87+
echo '```'
88+
echo
89+
echo '</details>'
90+
} | gh pr comment -R "$GITHUB_REPOSITORY" "$PR_NUMBER" -F -
91+
fi
92+
env:
93+
GH_TOKEN: ${{ github.token }}
94+
PR_NUMBER: ${{ steps.pr-data.outputs.NUMBER }}

.github/workflows/nix-changes.yml

Lines changed: 140 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,140 @@
1+
# This action uses the following secrets:
2+
# CACHIX_AUTH_TOKEN: Write access to nodejs.cachix.org – without it, the cache is read-only.
3+
name: Nix files edited
4+
5+
on:
6+
push:
7+
branches:
8+
- main
9+
- canary
10+
- v[0-9]+.x-staging
11+
- v[0-9]+.x
12+
paths:
13+
- '**.nix'
14+
- .github/workflows/nix-changes.yml
15+
pull_request:
16+
paths:
17+
- '**.nix'
18+
- .github/workflows/nix-changes.yml
19+
types: [opened, synchronize, reopened, ready_for_review]
20+
21+
concurrency:
22+
group: ${{ github.workflow }}-${{ github.head_ref || github.run_id }}
23+
cancel-in-progress: true
24+
25+
permissions:
26+
contents: read
27+
28+
jobs:
29+
diff:
30+
if: github.event.pull_request.draft == false
31+
strategy:
32+
fail-fast: false
33+
matrix:
34+
include:
35+
- runner: ubuntu-24.04
36+
system: x86_64-linux
37+
- runner: ubuntu-24.04-arm
38+
system: aarch64-linux
39+
- runner: macos-15-intel
40+
system: x86_64-darwin
41+
- runner: macos-latest
42+
system: aarch64-darwin
43+
name: '${{ matrix.system }}: dependencies diff'
44+
runs-on: ${{ matrix.runner }}
45+
steps:
46+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
47+
with:
48+
fetch-depth: 2
49+
persist-credentials: false
50+
sparse-checkout: '*.nix'
51+
sparse-checkout-cone-mode: false
52+
53+
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
54+
with:
55+
extra_nix_config: sandbox = true
56+
57+
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17
58+
with:
59+
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
60+
name: nodejs
61+
62+
- name: Compute requisites after change
63+
shell: bash # See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference, we want the pipefail option.
64+
run: |
65+
nix-store --query --references "$(
66+
nix-instantiate -I "nixpkgs=./tools/nix/pkgs.nix" shell.nix \
67+
--arg devTools "
68+
(import ./tools/nix/devTools.nix {})
69+
++ builtins.attrValues (
70+
{ inherit (import <nixpkgs> {}) nixfmt-tree sccache; }
71+
// import ./tools/nix/openssl-matrix.nix {}
72+
)")" \
73+
| xargs nix-store --realise \
74+
| xargs nix-store --query --requisites \
75+
| sort -k1.45 \
76+
> requisites-${{ matrix.system }}-after.list
77+
78+
- name: Compute requisites before change
79+
shell: bash # See https://docs.github.com/en/actions/writing-workflows/workflow-syntax-for-github-actions#exit-codes-and-error-action-preference, we want the pipefail option.
80+
run: |
81+
git reset HEAD^ --hard
82+
nix-store --query --references "$(
83+
nix-instantiate -I "nixpkgs=./tools/nix/pkgs.nix" shell.nix \
84+
--arg devTools "
85+
(import ./tools/nix/devTools.nix {})
86+
++ builtins.attrValues (
87+
{ inherit (import <nixpkgs> {}) nixfmt-tree sccache; }
88+
// import ./tools/nix/openssl-matrix.nix {}
89+
)")" \
90+
| xargs nix-store --realise \
91+
| xargs nix-store --query --requisites \
92+
| sort -k1.45 \
93+
> requisites-${{ matrix.system }}-before.list
94+
95+
- name: Output diff
96+
run: |
97+
{
98+
if diff_output="$(git diff -U0 --no-color --no-index requisites-${{ matrix.system }}-before.list requisites-${{ matrix.system }}-after.list)"; then
99+
echo 'No changes detected.'
100+
else
101+
echo '```diff'
102+
echo "$diff_output" | tail -n +5
103+
echo '```'
104+
fi
105+
} >> "$GITHUB_STEP_SUMMARY"
106+
107+
- name: Store PR number
108+
if: ${{ github.event.pull_request && matrix.system == 'x86_64-linux' }}
109+
run: echo "${{ github.event.pull_request.number }}" > pr_number.txt
110+
111+
- name: Upload requisites lists
112+
if: ${{ github.event.pull_request }}
113+
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
114+
with:
115+
name: requisites-${{ matrix.system }}
116+
path: |
117+
pr_number.*
118+
requisites-${{ matrix.system }}-before.list
119+
requisites-${{ matrix.system }}-after.list
120+
121+
lint-nix:
122+
if: github.event.pull_request.draft == false
123+
runs-on: ubuntu-slim
124+
steps:
125+
- uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0
126+
with:
127+
persist-credentials: false
128+
sparse-checkout: '*.nix'
129+
sparse-checkout-cone-mode: false
130+
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
131+
- name: Lint Nix files
132+
run: |
133+
nix-shell -I nixpkgs=./tools/nix/pkgs.nix -p 'nixfmt-tree' --run '
134+
treefmt --quiet --ci
135+
' && EXIT_CODE="$?" || EXIT_CODE="$?"
136+
if [ "$EXIT_CODE" != "0" ]
137+
then
138+
git --no-pager diff || true
139+
exit "$EXIT_CODE"
140+
fi

0 commit comments

Comments
 (0)