workflows/eval: upload maintainer list of all packages as artifact (#456965)

This commit is contained in:
Wolfgang Walther
2025-10-31 11:28:37 +00:00
committed by GitHub
9 changed files with 99 additions and 19 deletions

View File

@@ -3,6 +3,9 @@ name: Build
on:
workflow_call:
inputs:
artifact-prefix:
required: true
type: string
baseBranch:
required: true
type: string
@@ -100,5 +103,5 @@ jobs:
contains(fromJSON(inputs.baseBranch).type, 'primary')
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: nixos-manual-${{ matrix.name }}
name: ${{ inputs.artifact-prefix }}nixos-manual-${{ matrix.name }}
path: nixos-manual

View File

@@ -3,6 +3,9 @@ name: Eval
on:
workflow_call:
inputs:
artifact-prefix:
required: true
type: string
mergedSha:
required: true
type: string
@@ -110,7 +113,7 @@ jobs:
MATRIX_SYSTEM: ${{ matrix.system }}
MATRIX_VERSION: ${{ matrix.version || 'nixVersions.latest' }}
run: |
nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A eval.singleSystem \
nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A eval.singleSystem \
--argstr evalSystem "$MATRIX_SYSTEM" \
--arg chunkSize 8000 \
--argstr nixPath "$MATRIX_VERSION" \
@@ -119,19 +122,29 @@ jobs:
# Note: Keep the same further down in sync!
- name: Evaluate the ${{ matrix.system }} output paths at the target commit
if: inputs.targetSha
env:
MATRIX_SYSTEM: ${{ matrix.system }}
# This is very quick, because it pulls the eval results from Cachix.
run: |
nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.singleSystem \
TARGET_DRV=$(nix-instantiate nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.singleSystem \
--argstr evalSystem "$MATRIX_SYSTEM" \
--arg chunkSize 8000 \
--argstr nixPath "nixVersions.latest" \
--out-link target
--argstr nixPath "nixVersions.latest")
# Try to fetch this from Cachix a few times, for up to 30 seconds. This avoids running Eval
# twice in the Merge Queue, when a later item finishes Eval at the merge commit earlier.
for _i in {1..6}; do
# Using --max-jobs 0 will cause nix-build to fail if this can't be substituted from cachix.
if nix-build "$TARGET_DRV" --max-jobs 0; then
break
fi
sleep 5
done
# Either fetches from Cachix or runs Eval itself. The fallback is required
# for pull requests into wip-branches without merge queue.
nix-build "$TARGET_DRV" --out-link target
- name: Compare outpaths against the target branch
if: inputs.targetSha
env:
MATRIX_SYSTEM: ${{ matrix.system }}
run: |
@@ -142,16 +155,15 @@ jobs:
--out-link diff
- name: Upload outpaths diff and stats
if: inputs.targetSha
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: ${{ matrix.version && format('{0}-', matrix.version) || '' }}diff-${{ matrix.system }}
name: ${{ inputs.artifact-prefix }}${{ matrix.version && format('{0}-', matrix.version) || '' }}diff-${{ matrix.system }}
path: diff/*
compare:
runs-on: ubuntu-24.04-arm
needs: [eval]
if: inputs.targetSha && !cancelled() && !failure()
if: ${{ !cancelled() && !failure() }}
permissions:
statuses: write
timeout-minutes: 5
@@ -169,7 +181,7 @@ jobs:
- name: Download output paths and eval stats for all systems
uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0
with:
pattern: diff-*
pattern: ${{ inputs.artifact-prefix }}diff-*
path: diff
merge-multiple: true
@@ -182,6 +194,12 @@ jobs:
--arg diffDir ./diff \
--out-link combined
- name: Upload the maintainer list
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: ${{ inputs.artifact-prefix }}maintainers
path: combined/maintainers.json
- name: Compare against the target branch
env:
AUTHOR_ID: ${{ github.event.pull_request.user.id }}
@@ -202,7 +220,7 @@ jobs:
- name: Upload the comparison results
uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0
with:
name: comparison
name: ${{ inputs.artifact-prefix }}comparison
path: comparison/*
- name: Add eval summary to commit statuses
@@ -250,6 +268,7 @@ jobs:
- name: Add version comparison table to job summary
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
ARTIFACT_PREFIX: ${{ inputs.artifact-prefix }}
SYSTEMS: ${{ inputs.systems }}
VERSIONS: ${{ needs.versions.outputs.versions }}
with:
@@ -257,6 +276,7 @@ jobs:
const { readFileSync } = require('node:fs')
const path = require('node:path')
const prefix = process.env.ARTIFACT_PREFIX
const systems = JSON.parse(process.env.SYSTEMS)
const versions = JSON.parse(process.env.VERSIONS)
@@ -272,7 +292,7 @@ jobs:
[{ data: version }].concat(
systems.map((system) => {
try {
const artifact = path.join('versions', `${version}-diff-${system}`)
const artifact = path.join('versions', `${prefix}${version}-diff-${system}`)
const time = Math.round(
parseFloat(
readFileSync(

View File

@@ -4,6 +4,9 @@ on:
merge_group:
workflow_call:
inputs:
artifact-prefix:
required: true
type: string
mergedSha:
required: true
type: string
@@ -54,7 +57,9 @@ jobs:
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
with:
artifact-prefix: ${{ inputs.artifact-prefix }}
mergedSha: ${{ inputs.mergedSha || github.event.merge_group.head_sha }}
targetSha: ${{ inputs.targetSha || github.event.merge_group.base_sha }}
systems: ${{ needs.prepare.outputs.systems }}
# This job's only purpose is to create the target for the "Required Status Checks" branch ruleset.

View File

@@ -3,6 +3,10 @@ name: PR
on:
pull_request_target:
workflow_call:
inputs:
artifact-prefix:
required: true
type: string
secrets:
CACHIX_AUTH_TOKEN:
required: true
@@ -90,6 +94,7 @@ jobs:
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
with:
artifact-prefix: ${{ inputs.artifact-prefix }}
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
targetSha: ${{ needs.prepare.outputs.targetSha }}
systems: ${{ needs.prepare.outputs.systems }}
@@ -116,6 +121,8 @@ jobs:
uses: ./.github/workflows/reviewers.yml
secrets:
OWNER_APP_PRIVATE_KEY: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
with:
artifact-prefix: ${{ inputs.artifact-prefix }}
build:
name: Build
@@ -124,6 +131,7 @@ jobs:
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
with:
artifact-prefix: ${{ inputs.artifact-prefix }}
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
mergedSha: ${{ needs.prepare.outputs.mergedSha }}

View File

@@ -7,6 +7,10 @@ on:
pull_request_target:
types: [ready_for_review]
workflow_call:
inputs:
artifact-prefix:
required: true
type: string
secrets:
OWNER_APP_PRIVATE_KEY:
required: true
@@ -91,6 +95,8 @@ jobs:
- name: Wait for comparison to be done
uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
id: eval
env:
ARTIFACT: ${{ inputs.artifact-prefix }}comparison
with:
script: |
const run_id = (await github.rest.actions.listWorkflowRuns({
@@ -111,7 +117,7 @@ jobs:
owner: context.repo.owner,
repo: context.repo.repo,
run_id,
name: 'comparison'
name: process.env.ARTIFACT,
})
if (result.data.total_count > 0) return
await new Promise(resolve => setTimeout(resolve, 5000))
@@ -128,7 +134,7 @@ jobs:
with:
run-id: ${{ steps.eval.outputs.run-id }}
github-token: ${{ github.token }}
pattern: comparison
pattern: ${{ inputs.artifact-prefix }}comparison
path: comparison
merge-multiple: true

View File

@@ -79,6 +79,7 @@ jobs:
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
with:
artifact-prefix: mg-
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
targetSha: ${{ needs.prepare.outputs.targetSha }}
@@ -95,3 +96,5 @@ jobs:
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
with:
artifact-prefix: pr-

View File

@@ -22,7 +22,7 @@ rec {
splittedPath = lib.splitString "." packagePlatformPath;
# ["python312Packages" "numpy" "aarch64-linux"] -> ["python312Packages" "numpy"]
packagePath = lib.sublist 0 (lib.length splittedPath - 1) splittedPath;
packagePath = lib.init splittedPath;
# "python312Packages.numpy"
name = lib.concatStringsSep "." packagePath;

View File

@@ -111,6 +111,7 @@ let
--option allow-import-from-derivation false \
--query --available \
--out-path --json \
--meta \
--show-trace \
--arg chunkSize "$chunkSize" \
--arg myChunk "$myChunk" \
@@ -204,6 +205,7 @@ let
fi
cat "$chunkOutputDir"/result/* | jq -s 'add | map_values(.outputs)' > $out/${evalSystem}/paths.json
cat "$chunkOutputDir"/result/* | jq -s 'add | map_values(.meta)' > $out/${evalSystem}/meta.json
'';
diff = callPackage ./diff.nix { };
@@ -232,6 +234,14 @@ let
})
' > $out/combined-diff.json
# Combine maintainers from all systems
cat ${diffDir}/*/maintainers.json | jq -s '
add | group_by(.package) | map({
key: .[0].package,
value: map(.maintainers) | flatten | unique
}) | from_entries
' > $out/maintainers.json
mkdir -p $out/before/stats
for d in ${diffDir}/before/*; do
cp -r "$d"/stats-by-chunk $out/before/stats/$(basename "$d")

View File

@@ -76,11 +76,36 @@ let
afterAttrs = getAttrs after;
diffAttrs = diff beforeAttrs afterAttrs;
diffJson = writeText "diff.json" (builtins.toJSON diffAttrs);
# The maintainer list is not diffed, but just taken as is, to provide a map
# of maintainers on the target branch. A list of GitHub IDs is sufficient for
# all our purposes and reduces size massively.
meta = lib.importJSON "${after}/${evalSystem}/meta.json";
maintainers = lib.pipe meta [
(lib.mapAttrsToList (
k: v: {
# splits off the platform suffix
package = lib.pipe k [
(lib.splitString ".")
lib.init
(lib.concatStringsSep ".")
];
maintainers = map (m: m.githubId) v.maintainers or [ ];
}
))
# Some paths don't have a platform suffix, those will appear with an empty package here.
(lib.filter ({ package, maintainers }: package != "" && maintainers != [ ]))
];
maintainersJson = writeText "maintainers.json" (builtins.toJSON maintainers);
in
runCommand "diff" { } ''
mkdir -p $out/${evalSystem}
cp -r ${before} $out/before
cp -r ${after} $out/after
cp -r --no-preserve=mode ${before} $out/before
cp -r --no-preserve=mode ${after} $out/after
# JSON files will be processed above explicitly, so avoid copying over
# the source files to keep the artifacts smaller.
find $out/before $out/after -iname '*.json' -delete
cp ${diffJson} $out/${evalSystem}/diff.json
cp ${maintainersJson} $out/${evalSystem}/maintainers.json
''