Clone of https://github.com/NixOS/nixpkgs.git (to stress-test knotserver)
1name: Eval 2 3on: 4 workflow_call: 5 inputs: 6 mergedSha: 7 required: true 8 type: string 9 targetSha: 10 type: string 11 systems: 12 required: true 13 type: string 14 secrets: 15 OWNER_APP_PRIVATE_KEY: 16 required: false 17 18permissions: {} 19 20defaults: 21 run: 22 shell: bash 23 24jobs: 25 eval: 26 runs-on: ubuntu-24.04-arm 27 strategy: 28 fail-fast: false 29 matrix: 30 system: ${{ fromJSON(inputs.systems) }} 31 name: ${{ matrix.system }} 32 outputs: 33 targetRunId: ${{ steps.targetRunId.outputs.targetRunId }} 34 steps: 35 # We'd rather fail than run slow eval on swap. 36 # Failing allows us to adjust the chunkSize to remain fast. 37 - name: Disable swap 38 run: | 39 sudo swapoff -a 40 41 - name: Check out the PR at the test merge commit 42 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 43 with: 44 ref: ${{ inputs.mergedSha }} 45 path: untrusted 46 47 - name: Install Nix 48 uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 49 with: 50 extra_nix_config: sandbox = true 51 52 - name: Evaluate the ${{ matrix.system }} output paths for all derivation attributes 53 env: 54 MATRIX_SYSTEM: ${{ matrix.system }} 55 run: | 56 nix-build untrusted/ci -A eval.singleSystem \ 57 --argstr evalSystem "$MATRIX_SYSTEM" \ 58 --arg chunkSize 8000 \ 59 --out-link merged 60 # If it uses too much memory, slightly decrease chunkSize 61 62 - name: Upload the output paths and eval stats 63 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 64 with: 65 name: merged-${{ matrix.system }} 66 path: merged/* 67 68 - name: Log current API rate limits 69 env: 70 GH_TOKEN: ${{ github.token }} 71 run: gh api /rate_limit | jq 72 73 - name: Get target run id 74 if: inputs.targetSha 75 id: targetRunId 76 uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 77 env: 78 MATRIX_SYSTEM: ${{ matrix.system }} 79 TARGET_SHA: ${{ inputs.targetSha }} 80 with: 81 script: | 82 const system = process.env.MATRIX_SYSTEM 83 const targetSha = process.env.TARGET_SHA 84 85 let run_id 86 try { 87 run_id = (await github.rest.actions.listWorkflowRuns({ 88 ...context.repo, 89 workflow_id: 'push.yml', 90 event: 'push', 91 head_sha: targetSha 92 })).data.workflow_runs[0].id 93 } catch { 94 throw new Error(`Could not find a push.yml workflow run for ${targetSha}.`) 95 } 96 97 // Waiting 120 * 5 sec = 10 min. max. 98 // Eval takes max 5-6 minutes, normally. 99 for (let i = 0; i < 120; i++) { 100 const result = await github.rest.actions.listWorkflowRunArtifacts({ 101 ...context.repo, 102 run_id, 103 name: `merged-${system}` 104 }) 105 if (result.data.total_count > 0) { 106 core.setOutput('targetRunId', run_id) 107 return 108 } 109 await new Promise(resolve => setTimeout(resolve, 5000)) 110 } 111 // No artifact found at this stage. This usually means that Eval failed on the target branch. 112 // This should only happen when Eval is broken on the target branch and this PR fixes it. 113 // Continue without targetRunId to skip the remaining steps, but pass the job. 114 115 - name: Log current API rate limits 116 env: 117 GH_TOKEN: ${{ github.token }} 118 run: gh api /rate_limit | jq 119 120 - uses: actions/download-artifact@v4 121 if: steps.targetRunId.outputs.targetRunId 122 with: 123 run-id: ${{ steps.targetRunId.outputs.targetRunId }} 124 name: merged-${{ matrix.system }} 125 path: target 126 github-token: ${{ github.token }} 127 merge-multiple: true 128 129 - name: Compare outpaths against the target branch 130 if: steps.targetRunId.outputs.targetRunId 131 env: 132 MATRIX_SYSTEM: ${{ matrix.system }} 133 run: | 134 nix-build untrusted/ci -A eval.diff \ 135 --arg beforeDir ./target \ 136 --arg afterDir "$(readlink ./merged)" \ 137 --argstr evalSystem "$MATRIX_SYSTEM" \ 138 --out-link diff 139 140 - name: Upload outpaths diff and stats 141 if: steps.targetRunId.outputs.targetRunId 142 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 143 with: 144 name: diff-${{ matrix.system }} 145 path: diff/* 146 147 compare: 148 runs-on: ubuntu-24.04-arm 149 needs: [eval] 150 if: needs.eval.outputs.targetRunId 151 permissions: 152 statuses: write 153 steps: 154 - name: Download output paths and eval stats for all systems 155 uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8 156 with: 157 pattern: diff-* 158 path: diff 159 merge-multiple: true 160 161 - name: Check out the PR at the target commit 162 uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 163 with: 164 ref: ${{ inputs.targetSha }} 165 path: trusted 166 167 - name: Install Nix 168 uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 169 with: 170 extra_nix_config: sandbox = true 171 172 - name: Combine all output paths and eval stats 173 run: | 174 nix-build trusted/ci -A eval.combine \ 175 --arg diffDir ./diff \ 176 --out-link combined 177 178 - name: Compare against the target branch 179 env: 180 AUTHOR_ID: ${{ github.event.pull_request.user.id }} 181 run: | 182 git -C trusted fetch --depth 1 origin ${{ inputs.mergedSha }} 183 git -C trusted diff --name-only ${{ inputs.mergedSha }} \ 184 | jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json 185 186 # Use the target branch to get accurate maintainer info 187 nix-build trusted/ci -A eval.compare \ 188 --arg combinedDir "$(realpath ./combined)" \ 189 --arg touchedFilesJson ./touched-files.json \ 190 --argstr githubAuthorId "$AUTHOR_ID" \ 191 --out-link comparison 192 193 cat comparison/step-summary.md >> "$GITHUB_STEP_SUMMARY" 194 195 - name: Upload the comparison results 196 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 197 with: 198 name: comparison 199 path: comparison/* 200 201 - name: Add eval summary to commit statuses 202 if: ${{ github.event_name == 'pull_request_target' }} 203 uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 204 with: 205 script: | 206 const { readFile } = require('node:fs/promises') 207 const changed = JSON.parse(await readFile('comparison/changed-paths.json', 'utf-8')) 208 const description = 209 'Package: ' + [ 210 `added ${changed.attrdiff.added.length}`, 211 `removed ${changed.attrdiff.removed.length}`, 212 `changed ${changed.attrdiff.changed.length}` 213 ].join(', ') + 214 ' — Rebuild: ' + [ 215 `linux ${changed.rebuildCountByKernel.linux}`, 216 `darwin ${changed.rebuildCountByKernel.darwin}` 217 ].join(', ') 218 219 const { serverUrl, repo, runId, payload } = context 220 const target_url = 221 `${serverUrl}/${repo.owner}/${repo.repo}/actions/runs/${runId}?pr=${payload.pull_request.number}` 222 223 await github.rest.repos.createCommitStatus({ 224 ...repo, 225 sha: payload.pull_request.head.sha, 226 context: 'Eval Summary', 227 state: 'success', 228 description, 229 target_url 230 }) 231 232 misc: 233 if: ${{ github.event_name != 'push' }} 234 runs-on: ubuntu-24.04-arm 235 steps: 236 - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 237 with: 238 sparse-checkout: .github/actions 239 - name: Check if the PR can be merged and checkout the merge commit 240 uses: ./.github/actions/get-merge-commit 241 with: 242 merged-as-untrusted: true 243 244 - name: Install Nix 245 uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31 246 with: 247 extra_nix_config: sandbox = true 248 249 - name: Ensure flake outputs on all systems still evaluate 250 run: nix flake check --all-systems --no-build ./untrusted 251 252 - name: Query nixpkgs with aliases enabled to check for basic syntax errors 253 run: | 254 time nix-env -I ./untrusted -f ./untrusted -qa '*' --option restrict-eval true --option allow-import-from-derivation false >/dev/null