···8787 - name: Get target run id
8888 if: needs.prepare.outputs.targetSha
8989 id: targetRunId
9090+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
9091 env:
9191- GH_TOKEN: ${{ github.token }}
9292 MATRIX_SYSTEM: ${{ matrix.system }}
9393- REPOSITORY: ${{ github.repository }}
9493 TARGET_SHA: ${{ needs.prepare.outputs.targetSha }}
9595- run: |
9696- # Get the latest eval.yml workflow run for the PR's target commit
9797- if ! run=$(gh api --method GET /repos/"$REPOSITORY"/actions/workflows/eval.yml/runs \
9898- -f head_sha="$TARGET_SHA" -f event=push \
9999- --jq '.workflow_runs | sort_by(.run_started_at) | .[-1]') \
100100- || [[ -z "$run" ]]; then
101101- echo "Could not find an eval.yml workflow run for $TARGET_SHA, cannot make comparison"
102102- exit 1
103103- fi
104104- echo "Comparing against $(jq .html_url <<< "$run")"
105105- runId=$(jq .id <<< "$run")
9494+ with:
9595+ script: |
9696+ const system = process.env.MATRIX_SYSTEM
9797+ const targetSha = process.env.TARGET_SHA
10698107107- if ! job=$(gh api --method GET /repos/"$REPOSITORY"/actions/runs/"$runId"/jobs \
108108- --jq ".jobs[] | select (.name == \"Outpaths ($MATRIX_SYSTEM)\")") \
109109- || [[ -z "$job" ]]; then
110110- echo "Could not find the Outpaths ($MATRIX_SYSTEM) job for workflow run $runId, cannot make comparison"
111111- exit 1
112112- fi
113113- jobId=$(jq .id <<< "$job")
114114- conclusion=$(jq -r .conclusion <<< "$job")
9999+ let run_id
100100+ try {
101101+ run_id = (await github.rest.actions.listWorkflowRuns({
102102+ owner: context.repo.owner,
103103+ repo: context.repo.repo,
104104+ workflow_id: 'eval.yml',
105105+ event: 'push',
106106+ head_sha: targetSha
107107+ })).data.workflow_runs[0].id
108108+ } catch {
109109+ throw new Error(`Could not find an eval.yml workflow run for ${targetSha}.`)
110110+ }
115111116116- while [[ "$conclusion" == null || "$conclusion" == "" ]]; do
117117- echo "Job not done, waiting 10 seconds before checking again"
118118- sleep 10
119119- conclusion=$(gh api /repos/"$REPOSITORY"/actions/jobs/"$jobId" --jq '.conclusion')
120120- done
112112+ core.setOutput('targetRunId', run_id)
121113122122- if [[ "$conclusion" != "success" ]]; then
123123- echo "Job was not successful (conclusion: $conclusion), cannot make comparison"
124124- exit 1
125125- fi
126126-127127- echo "targetRunId=$runId" >> "$GITHUB_OUTPUT"
114114+ // Waiting 120 * 5 sec = 10 min. max.
115115+ // Eval takes max 5-6 minutes, normally.
116116+ for (let i = 0; i < 120; i++) {
117117+ const result = await github.rest.actions.listWorkflowRunArtifacts({
118118+ owner: context.repo.owner,
119119+ repo: context.repo.repo,
120120+ run_id,
121121+ name: `merged-${system}`
122122+ })
123123+ if (result.data.total_count > 0) return
124124+ await new Promise(resolve => setTimeout(resolve, 5000))
125125+ }
126126+ throw new Error(`No merged-${system} artifact found.`)
128127129128 - uses: actions/download-artifact@v4
130129 if: steps.targetRunId.outputs.targetRunId
···212211213212 - name: Labelling pull request
214213 if: ${{ github.event_name == 'pull_request_target' }}
215215- env:
216216- GH_TOKEN: ${{ github.token }}
217217- REPOSITORY: ${{ github.repository }}
218218- NUMBER: ${{ github.event.number }}
219219- run: |
220220- # Get all currently set labels that we manage
221221- gh api \
222222- /repos/"$REPOSITORY"/issues/"$NUMBER"/labels \
223223- --jq '.[].name | select(startswith("10.rebuild") or . == "11.by: package-maintainer")' \
224224- | sort > before
214214+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
215215+ with:
216216+ script: |
217217+ const { readFile } = require('node:fs/promises')
218218+219219+ const pr = {
220220+ owner: context.repo.owner,
221221+ repo: context.repo.repo,
222222+ issue_number: context.payload.pull_request.number
223223+ }
224224+225225+ // Get all currently set labels that we manage
226226+ const before =
227227+ (await github.paginate(github.rest.issues.listLabelsOnIssue, pr))
228228+ .map(({ name }) => name)
229229+ .filter(name => name.startsWith('10.rebuild') || name == '11.by: package-maintainer')
225230226226- # And the labels that should be there
227227- jq -r '.labels[]' comparison/changed-paths.json \
228228- | sort > after
231231+ // And the labels that should be there
232232+ const after = JSON.parse(await readFile('comparison/changed-paths.json', 'utf-8')).labels
229233230230- # Remove the ones not needed anymore
231231- while read -r toRemove; do
232232- echo "Removing label $toRemove"
233233- gh api \
234234- --method DELETE \
235235- /repos/"$REPOSITORY"/issues/"$NUMBER"/labels/"$toRemove"
236236- done < <(comm -23 before after)
234234+ // Remove the ones not needed anymore
235235+ await Promise.all(
236236+ before.filter(name => !after.includes(name))
237237+ .map(name => github.rest.issues.removeLabel({
238238+ ...pr,
239239+ name
240240+ }))
241241+ )
237242238238- # And add the ones that aren't set already
239239- while read -r toAdd; do
240240- echo "Adding label $toAdd"
241241- gh api \
242242- --method POST \
243243- /repos/"$REPOSITORY"/issues/"$NUMBER"/labels \
244244- -f "labels[]=$toAdd"
245245- done < <(comm -13 before after)
243243+ // And add the ones that aren't set already
244244+ const added = after.filter(name => !before.includes(name))
245245+ if (added.length > 0) {
246246+ await github.rest.issues.addLabels({
247247+ ...pr,
248248+ labels: added
249249+ })
250250+ }
246251247252 - name: Add eval summary to commit statuses
248253 if: ${{ github.event_name == 'pull_request_target' }}
249249- env:
250250- GH_TOKEN: ${{ github.token }}
251251- PR_HEAD_SHA: ${{ github.event.pull_request.head.sha }}
252252- NUMBER: ${{ github.event.number }}
253253- run: |
254254- description=$(jq -r '
255255- "Package: added " + (.attrdiff.added | length | tostring) +
256256- ", removed " + (.attrdiff.removed | length | tostring) +
257257- ", changed " + (.attrdiff.changed | length | tostring) +
258258- ", Rebuild: linux " + (.rebuildCountByKernel.linux | tostring) +
259259- ", darwin " + (.rebuildCountByKernel.darwin | tostring)
260260- ' <comparison/changed-paths.json)
261261- target_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID?pr=$NUMBER"
262262- gh api --method POST \
263263- -H "Accept: application/vnd.github+json" -H "X-GitHub-Api-Version: 2022-11-28" \
264264- "/repos/$GITHUB_REPOSITORY/statuses/$PR_HEAD_SHA" \
265265- -f "context=Eval / Summary" -f "state=success" -f "description=$description" -f "target_url=$target_url"
254254+ uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
255255+ with:
256256+ script: |
257257+ const { readFile } = require('node:fs/promises')
258258+ const changed = JSON.parse(await readFile('comparison/changed-paths.json', 'utf-8'))
259259+ const description =
260260+ 'Package: ' + [
261261+ `added ${changed.attrdiff.added.length}`,
262262+ `removed ${changed.attrdiff.removed.length}`,
263263+ `changed ${changed.attrdiff.changed.length}`
264264+ ].join(', ') +
265265+ ' — Rebuild: ' + [
266266+ `linux ${changed.rebuildCountByKernel.linux}`,
267267+ `darwin ${changed.rebuildCountByKernel.darwin}`
268268+ ].join(', ')
269269+270270+ const { serverUrl, repo, runId, payload } = context
271271+ const target_url =
272272+ `${serverUrl}/${repo.owner}/${repo.repo}/actions/runs/${runId}?pr=${payload.pull_request.number}`
273273+274274+ await github.rest.repos.createCommitStatus({
275275+ owner: repo.owner,
276276+ repo: repo.repo,
277277+ sha: payload.pull_request.head.sha,
278278+ context: 'Eval / Summary',
279279+ state: 'success',
280280+ description,
281281+ target_url
282282+ })
266283267284 reviewers:
268285 name: Reviewers
+2-1
.github/workflows/manual-nixos-v2.yml
···77 pull_request_target:
88 branches:
99 - master
1010+ - release-*
1011 paths:
1112 - "nixos/**"
1213 # Also build when the nixpkgs doc changed, since we take things like
···52535354 - name: Build NixOS manual
5455 id: build-manual
5555- run: NIX_PATH=nixpkgs=$(pwd)/untrusted nix-build --option restrict-eval true untrusted/ci -A manual-nixos --argstr system ${{ matrix.system }}
5656+ run: nix-build untrusted/ci -A manual-nixos --argstr system ${{ matrix.system }}
56575758 - name: Upload NixOS manual
5859 uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
+7
ci/check-cherry-picks.md
···11+This report is automatically generated by the `check-cherry-picks` CI workflow.
22+33+Some of the commits in this PR have not been cherry-picked exactly and require the author's and reviewer's attention.
44+55+Please make sure to follow the [backporting guidelines](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#how-to-backport-pull-requests) and cherry-pick with the `-x` flag. This requires changes to go to the unstable branches (`master` / `staging`) first, before backporting them.
66+77+Occasionally, it is not possible to cherry-pick exactly the same patch. This most frequently happens when resolving merge conflicts while cherry-picking or when updating minor versions of packages which have already advanced to the next major on unstable. If you need to merge this PR despite the warnings, please [dismiss](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/dismissing-a-pull-request-review) this review.
+73-37
ci/check-cherry-picks.sh
···11#!/usr/bin/env bash
22# Find alleged cherry-picks
3344-set -eo pipefail
44+set -euo pipefail
5566-if [ $# != "2" ] ; then
77- echo "usage: check-cherry-picks.sh base_rev head_rev"
66+if [[ $# != "2" && $# != "3" ]] ; then
77+ echo "usage: check-cherry-picks.sh base_rev head_rev [markdown_file]"
88 exit 2
99fi
10101111+markdown_file="$(realpath ${3:-/dev/null})"
1212+[ -v 3 ] && rm -f "$markdown_file"
1313+1114# Make sure we are inside the nixpkgs repo, even when called from outside
1215cd "$(dirname "${BASH_SOURCE[0]}")"
1316···19222023commits="$(git rev-list --reverse "$1..$2")"
21242525+log() {
2626+ type="$1"
2727+ shift 1
2828+2929+ local -A prefix
3030+ prefix[success]=" ✔ "
3131+ if [ -v GITHUB_ACTIONS ]; then
3232+ prefix[warning]="::warning::"
3333+ prefix[error]="::error::"
3434+ else
3535+ prefix[warning]=" ⚠ "
3636+ prefix[error]=" ✘ "
3737+ fi
3838+3939+ echo "${prefix[$type]}$@"
4040+4141+ # Only logging errors and warnings, which allows comparing the markdown file
4242+ # between pushes to the PR. Even if a new, proper cherry-pick, commit is added
4343+ # it won't change the markdown file's content and thus not trigger another comment.
4444+ if [ "$type" != "success" ]; then
4545+ local -A alert
4646+ alert[warning]="WARNING"
4747+ alert[error]="CAUTION"
4848+ echo >> $markdown_file
4949+ echo "> [!${alert[$type]}]" >> $markdown_file
5050+ echo "> $@" >> $markdown_file
5151+ fi
5252+}
5353+5454+endgroup() {
5555+ if [ -v GITHUB_ACTIONS ] ; then
5656+ echo ::endgroup::
5757+ fi
5858+}
5959+2260while read -r new_commit_sha ; do
2323- if [ -z "$new_commit_sha" ] ; then
2424- continue # skip empty lines
2525- fi
2626- if [ "$GITHUB_ACTIONS" = 'true' ] ; then
6161+ if [ -v GITHUB_ACTIONS ] ; then
2762 echo "::group::Commit $new_commit_sha"
2863 else
2964 echo "================================================="
···3772 | grep -Eoi -m1 '[0-9a-f]{40}' || true
3873 )
3974 if [ -z "$original_commit_sha" ] ; then
4040- if [ "$GITHUB_ACTIONS" = 'true' ] ; then
4141- echo ::endgroup::
4242- echo -n "::error ::"
4343- else
4444- echo -n " ✘ "
4545- fi
4646- echo "Couldn't locate original commit hash in message"
4747- echo "Note this should not necessarily be treated as a hard fail, but a reviewer's attention should" \
4848- "be drawn to it and github actions have no way of doing that but to raise a 'failure'"
7575+ endgroup
7676+ log warning "Couldn't locate original commit hash in message of $new_commit_sha."
4977 problem=1
5078 continue
5179 fi
···65936694 while read -r picked_branch ; do
6795 if git merge-base --is-ancestor "$original_commit_sha" "$picked_branch" ; then
6868- echo " ✔ $original_commit_sha present in branch $picked_branch"
6969-7096 range_diff_common='git --no-pager range-diff
7197 --no-notes
7298 --creation-factor=100
···75101 '
7610277103 if $range_diff_common --no-color 2> /dev/null | grep -E '^ {4}[+-]{2}' > /dev/null ; then
7878- if [ "$GITHUB_ACTIONS" = 'true' ] ; then
7979- echo ::endgroup::
8080- echo -n "::warning ::"
8181- else
8282- echo -n " ⚠ "
104104+ log success "$original_commit_sha present in branch $picked_branch"
105105+ endgroup
106106+ log warning "Difference between $new_commit_sha and original $original_commit_sha may warrant inspection."
107107+108108+ # First line contains commit SHAs, which we already printed.
109109+ $range_diff_common --color | tail -n +2
110110+111111+ echo -e "> <details><summary>Show diff</summary>\n>" >> $markdown_file
112112+ echo '> ```diff' >> $markdown_file
113113+ # The output of `git range-diff` is indented with 4 spaces, which we need to match with the
114114+ # code blocks indent to get proper syntax highlighting on GitHub.
115115+ diff="$($range_diff_common | tail -n +2 | sed -Ee 's/^ {4}/> /g')"
116116+ # Also limit the output to 10k bytes (and remove the last, potentially incomplete line), because
117117+ # GitHub comments are limited in length. The value of 10k is arbitrary with the assumption, that
118118+ # after the range-diff becomes a certain size, a reviewer is better off reviewing the regular diff
119119+ # in GitHub's UI anyway, thus treating the commit as "new" and not cherry-picked.
120120+ # Note: This could still lead to a too lengthy comment with multiple commits touching the limit. We
121121+ # consider this too unlikely to happen, to deal with explicitly.
122122+ max_length=10000
123123+ if [ "${#diff}" -gt $max_length ]; then
124124+ printf -v diff "%s\n\n[...truncated...]" "$(echo "$diff" | head -c $max_length | head -n-1)"
83125 fi
8484- echo "Difference between $new_commit_sha and original $original_commit_sha may warrant inspection:"
8585-8686- $range_diff_common --color
126126+ echo "$diff" >> $markdown_file
127127+ echo '> ```' >> $markdown_file
128128+ echo "> </details>" >> $markdown_file
871298888- echo "Note this should not necessarily be treated as a hard fail, but a reviewer's attention should" \
8989- "be drawn to it and github actions have no way of doing that but to raise a 'failure'"
90130 problem=1
91131 else
9292- echo " ✔ $original_commit_sha highly similar to $new_commit_sha"
132132+ log success "$original_commit_sha present in branch $picked_branch"
133133+ log success "$original_commit_sha highly similar to $new_commit_sha"
93134 $range_diff_common --color
9494- [ "$GITHUB_ACTIONS" = 'true' ] && echo ::endgroup::
135135+ endgroup
95136 fi
9613797138 # move on to next commit
···100141 done <<< "$branches"
101142 done
102143103103- if [ "$GITHUB_ACTIONS" = 'true' ] ; then
104104- echo ::endgroup::
105105- echo -n "::error ::"
106106- else
107107- echo -n " ✘ "
108108- fi
109109- echo "$original_commit_sha not found in any pickable branch"
144144+ endgroup
145145+ log error "$original_commit_sha given in $new_commit_sha not found in any pickable branch."
110146111147 problem=1
112148done <<< "$commits"
···11+# udevCheckHook {#udevcheckhook}
22+33+The `udevCheckHook` derivation adds `udevCheckPhase` to the [`preInstallCheckHooks`](#ssec-installCheck-phase),
44+which finds all udev rules in all outputs and verifies them using `udevadm verify --resolve-names=never --no-style`.
55+It should be used in any package that has udev rules outputs to ensure the rules are and stay valid.
66+77+The hook runs in `installCheckPhase`, requiring `doInstallCheck` is enabled for the hook to take effect:
88+```nix
99+{
1010+ lib,
1111+ stdenv,
1212+ udevCheckHook,
1313+# ...
1414+}:
1515+1616+stdenv.mkDerivation (finalAttrs: {
1717+ # ...
1818+1919+ nativeInstallCheckInputs = [
2020+ udevCheckHook
2121+ ];
2222+ doInstallCheck = true;
2323+2424+ # ...
2525+})
2626+```
2727+Note that for [`buildPythonPackage`](#buildpythonpackage-function) and [`buildPythonApplication`](#buildpythonapplication-function), `doInstallCheck` is enabled by default.
2828+2929+All outputs are scanned for their `/{etc,lib}/udev/rules.d` paths.
3030+If no rule output is found, the hook is basically a no-op.
3131+3232+The `udevCheckHook` adds a dependency on `systemdMinimal`.
3333+It is internally guarded behind `hostPlatform` supporting udev and `buildPlatform` being able to execute `udevadm`.
3434+The hook does not need explicit platform checks in the places where it is used.
3535+3636+The hook can be disabled using `dontUdevCheck`, which is necessary if you want to run some different task in `installCheckPhase` on a package with broken udev rule outputs.
···18181919stdenv.mkDerivation rec {
2020 pname = "exult";
2121- version = "1.10.1";
2121+ version = "1.12.0";
22222323 src = fetchFromGitHub {
2424 owner = "exult";
2525 repo = "exult";
2626 rev = "v${version}";
2727- hash = "sha256-NlvtYtmJNYhOC1BtIxIij3NEQHWAGOeD4XgRq7evjzE=";
2727+ hash = "sha256-SZwYaqTTWESNRphXefa3JyH988y3WiaIr12yORhiFow=";
2828 };
29293030- # We can't use just DESTDIR because with it we'll have /nix/store/...-exult-1.10.1/nix/store/...-exult-1.10.1/bin
3030+ # We can't use just DESTDIR because with it we'll have /nix/store/...-exult-1.12.0/nix/store/...-exult-1.12.0/bin
3131 postPatch = ''
3232 substituteInPlace macosx/macosx.am \
3333 --replace-fail DESTDIR NIX_DESTDIR
···278278 homepage = "https://github.com/HarbourMasters/Shipwright";
279279 description = "A PC port of Ocarina of Time with modern controls, widescreen, high-resolution, and more";
280280 mainProgram = "soh";
281281- platforms = [ "x86_64-linux" ] ++ lib.platforms.darwin;
281281+ platforms = lib.platforms.linux ++ lib.platforms.darwin;
282282 maintainers = with lib.maintainers; [
283283 j0lol
284284 matteopacini
···448448 CoinMP = coinmp; # Added 2024-06-12
449449 collada-dom = opencollada; # added 2024-02-21
450450 colorpicker = throw "'colorpicker' has been removed due to lack of maintenance upstream. Consider using 'xcolor', 'gcolor3', 'eyedropper' or 'gpick' instead"; # Added 2024-10-19
451451+ connman-ncurses = throw "'connman-ncurses' has been removed due to lack of maintenance upstream."; # Added 2025-05-27
451452 coriander = throw "'coriander' has been removed because it depends on GNOME 2 libraries"; # Added 2024-06-27
452453 corretto19 = throw "Corretto 19 was removed as it has reached its end of life"; # Added 2024-08-01
453454 cosmic-tasks = tasks; # Added 2024-07-04