Compare commits

..

1 Commits

Author SHA1 Message Date
Marcin Serwin
09f6b8288f Revert "zlib: 1.3.1 -> 1.3.1.2" 2026-02-16 16:08:15 +01:00
24924 changed files with 512338 additions and 882377 deletions

View File

@@ -1,6 +1,6 @@
{ {
"name": "nixpkgs", "name": "nixpkgs",
"image": "mcr.microsoft.com/devcontainers/universal:5-linux", "image": "mcr.microsoft.com/devcontainers/universal:2-linux",
"features": { "features": {
"ghcr.io/devcontainers/features/nix:1": { "ghcr.io/devcontainers/features/nix:1": {
// fails in the devcontainer sandbox, enable sandbox via config instead // fails in the devcontainer sandbox, enable sandbox via config instead

23
.gitattributes vendored
View File

@@ -1,26 +1,7 @@
# node/js lock files
**/package-lock.json linguist-generated
**/yarn.nix linguist-generated
**/yarn.lock linguist-generated
# Rust lock files
**/Cargo.lock linguist-generated
pkgs/build-support/rust/**/Cargo.lock -linguist-generated
# NuGet, Gradle and others
**/deps.json linguist-generated
# Ruby lock files
**/gemset.nix linguist-generated
**/Gemfile.lock linguist-generated
# PHP lock files
**/composer.lock linguist-generated
# various package managers and tools
**/deps.nix linguist-generated **/deps.nix linguist-generated
**/deps.json linguist-generated
**/deps.toml linguist-generated **/deps.toml linguist-generated
**/node-packages.nix linguist-generated
pkgs/applications/editors/emacs-modes/*-generated.nix linguist-generated pkgs/applications/editors/emacs-modes/*-generated.nix linguist-generated
pkgs/development/r-modules/*-packages.nix linguist-generated pkgs/development/r-modules/*-packages.nix linguist-generated

6
.github/ISSUE_TEMPLATE.md vendored Normal file
View File

@@ -0,0 +1,6 @@
<!--
Please note: This blank issue template is meant for extraordinary issues
that do not fit the templates. Unless you know your issue is relevant to
Nixpkgs and requires the free-form blank issue, please use the issue
templates instead.
-->

View File

@@ -35,8 +35,8 @@ body:
If you are using an older version, please update to the latest stable version and check if the issue persists before continuing this bug report. If you are using an older version, please update to the latest stable version and check if the issue persists before continuing this bug report.
options: options:
- "Please select a version." - "Please select a version."
- "- Unstable (26.11)" - "- Unstable (26.05)"
- "- Stable (26.05)" - "- Stable (25.11)"
default: 0 default: 0
validations: validations:
required: true required: true
@@ -54,7 +54,7 @@ body:
description: "Please include a step-by-step guide for reproducing this issue. Consider writing in concise, numbered bullet points to ensure that Nixpkgs developers can retrace your steps." description: "Please include a step-by-step guide for reproducing this issue. Consider writing in concise, numbered bullet points to ensure that Nixpkgs developers can retrace your steps."
validations: validations:
required: true required: true
- type: "textarea" - type: "input"
id: "expected-behaviour" id: "expected-behaviour"
attributes: attributes:
label: "Expected behaviour" label: "Expected behaviour"
@@ -121,8 +121,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -35,8 +35,8 @@ body:
If you are using an older version, please update to the latest stable version and check if the issue persists before continuing this bug report. If you are using an older version, please update to the latest stable version and check if the issue persists before continuing this bug report.
options: options:
- "Please select a version." - "Please select a version."
- "- Unstable (26.11)" - "- Unstable (26.05)"
- "- Stable (26.05)" - "- Stable (25.11)"
default: 0 default: 0
validations: validations:
required: true required: true
@@ -54,7 +54,7 @@ body:
description: "Please include a step-by-step guide for reproducing this issue. Consider writing in concise, numbered bullet points to ensure that Nixpkgs developers can retrace your steps." description: "Please include a step-by-step guide for reproducing this issue. Consider writing in concise, numbered bullet points to ensure that Nixpkgs developers can retrace your steps."
validations: validations:
required: true required: true
- type: "textarea" - type: "input"
id: "expected-behaviour" id: "expected-behaviour"
attributes: attributes:
label: "Expected behaviour" label: "Expected behaviour"
@@ -99,7 +99,7 @@ body:
attributes: attributes:
label: "Are you using nix-darwin?" label: "Are you using nix-darwin?"
description: | description: |
[`nix-darwin`](https://github.com/nix-darwin/nix-darwin) is a set of NixOS-like modules for macOS systems. Depending on your issue, this information may be relevant. [`nix-darwin`](https://github.com/LnL7/nix-darwin) is a set of NixOS-like modules for macOS systems. Depending on your issue, this information may be relevant.
options: options:
- "Yes, I am using nix-darwin." - "Yes, I am using nix-darwin."
- "No, I am not using nix-darwin." - "No, I am not using nix-darwin."
@@ -135,8 +135,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -35,8 +35,8 @@ body:
If you are using an older version, please update to the latest stable version and check if the issue persists before continuing this bug report. If you are using an older version, please update to the latest stable version and check if the issue persists before continuing this bug report.
options: options:
- "Please select a version." - "Please select a version."
- "- Unstable (26.11)" - "- Unstable (26.05)"
- "- Stable (26.05)" - "- Stable (25.11)"
default: 0 default: 0
validations: validations:
required: true required: true
@@ -54,7 +54,7 @@ body:
description: "Please include a step-by-step guide for reproducing this issue. Consider writing in concise, numbered bullet points to ensure that Nixpkgs developers can retrace your steps." description: "Please include a step-by-step guide for reproducing this issue. Consider writing in concise, numbered bullet points to ensure that Nixpkgs developers can retrace your steps."
validations: validations:
required: true required: true
- type: "textarea" - type: "input"
id: "expected-behaviour" id: "expected-behaviour"
attributes: attributes:
label: "Expected behaviour" label: "Expected behaviour"
@@ -125,8 +125,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -37,8 +37,8 @@ body:
If you are purposefully trying to build an ancient version of a package in an older Nixpkgs, please coordinate with the [NixOS Archivists](https://matrix.to/#/#archivists:nixos.org). If you are purposefully trying to build an ancient version of a package in an older Nixpkgs, please coordinate with the [NixOS Archivists](https://matrix.to/#/#archivists:nixos.org).
options: options:
- "Please select a version." - "Please select a version."
- "- Unstable (26.11)" - "- Unstable (26.05)"
- "- Stable (26.05)" - "- Stable (25.11)"
default: 0 default: 0
validations: validations:
required: true required: true
@@ -56,12 +56,12 @@ body:
description: | description: |
Can [Hydra](https://hydra.nixos.org), Nixpkgs' Continuous Integration system, reproduce this build failure? Can [Hydra](https://hydra.nixos.org), Nixpkgs' Continuous Integration system, reproduce this build failure?
Please use the search function in the header bar to locate the last build job for the package in question. Please use the search function in the header bar to locate the last build job for the package in question.
- If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/subprojects/hydra/root/static/images/emojione-red-x-274c.svg" width="20px" align="top" alt="Red X"> icon near the package entry, say '**Yes, Hydra can reproduce this build failure.**' - If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/src/root/static/images/emojione-red-x-274c.svg" width="20px" align="top" alt="Red X"> icon near the package entry, say '**Yes, Hydra can reproduce this build failure.**'
- If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/subprojects/hydra/root/static/images/emojione-gray-x-2716.svg" width="20px" align="top" alt="Dark Gray X"> icon near the package entry, then the build failure occurs with another package, and you need to track the original failing package by going down the chain of 'Cached failures' until you reach the final package in the failing dependency chain. Once you locate the failing package, re-write this report against that package and say '**Yes, Hydra can reproduce this build failure.**' - If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/src/root/static/images/emojione-gray-x-2716.svg" width="20px" align="top" alt="Dark Gray X"> icon near the package entry, then the build failure occurs with another package, and you need to track the original failing package by going down the chain of 'Cached failures' until you reach the final package in the failing dependency chain. Once you locate the failing package, re-write this report against that package and say '**Yes, Hydra can reproduce this build failure.**'
- If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/subprojects/hydra/root/static/images/emojione-check-2714.svg" width="20px" align="top" alt="Green Check Mark"> icon near the package entry, then it most likely means it's a local issue with your system. (Maybe you ran out of space?) - If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/src/root/static/images/emojione-check-2714.svg" width="20px" align="top" alt="Green Check Mark"> icon near the package entry, then it most likely means it's a local issue with your system. (Maybe you ran out of space?)
You can still open a build failure report, but please say '**No, Hydra cannot reproduce this build failure.**' below. You can still open a build failure report, but please say '**No, Hydra cannot reproduce this build failure.**' below.
- If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/subprojects/hydra/root/static/images/emojione-question-2754.svg" width="20px" align="top" alt="Gray Question Mark"> icon near the package entry, say '**Hydra is currently rebuilding this package.**' - If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/src/root/static/images/emojione-question-2754.svg" width="20px" align="top" alt="Gray Question Mark"> icon near the package entry, say '**Hydra is currently rebuilding this package.**'
- If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/subprojects/hydra/root/static/images/emojione-stopsign-1f6d1.svg" width="20px" align="top" alt="Red Stop Sign"> icon near the package entry, then the build job was stopped manually. If this occurs, please coordinate with the [Infrastructure Team](https://matrix.to/#/#infra:nixos.org), and say '**The last build job was manually cancelled.**' - If there's a <img src="https://raw.githubusercontent.com/NixOS/hydra/refs/heads/master/src/root/static/images/emojione-stopsign-1f6d1.svg" width="20px" align="top" alt="Red Stop Sign"> icon near the package entry, then the build job was stopped manually. If this occurs, please coordinate with the [Infrastructure Team](https://matrix.to/#/#infra:nixos.org), and say '**The last build job was manually cancelled.**'
- If Hydra isn't supposed to build the package at all, say '**Hydra doesnt try to build the package.**' - If Hydra isn't supposed to build the package at all, say '**Hydra doesnt try to build the package.**'
options: options:
- "Please select the Hydra Status." - "Please select the Hydra Status."
@@ -131,8 +131,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -37,8 +37,8 @@ body:
If the package has been updated in unstable, but you believe the update should be backported to the stable release of Nixpkgs, please file the '**Request: backport to stable**' form instead. If the package has been updated in unstable, but you believe the update should be backported to the stable release of Nixpkgs, please file the '**Request: backport to stable**' form instead.
options: options:
- "Please select a version." - "Please select a version."
- "- Unstable (26.11)" - "- Unstable (26.05)"
- "- Stable (26.05)" - "- Stable (25.11)"
default: 0 default: 0
validations: validations:
required: true required: true
@@ -104,8 +104,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -35,8 +35,8 @@ body:
If you are using an older or stable version, please update to the latest **unstable** version and check if the module still does not exist before continuing this request. If you are using an older or stable version, please update to the latest **unstable** version and check if the module still does not exist before continuing this request.
options: options:
- "Please select a version." - "Please select a version."
- "- Unstable (26.11)" - "- Unstable (26.05)"
- "- Stable (26.05)" - "- Stable (25.11)"
default: 0 default: 0
validations: validations:
required: true required: true
@@ -79,8 +79,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -85,8 +85,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -67,8 +67,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -137,8 +137,6 @@ body:
required: true required: true
- label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it." - label: "I assert that I have read the [NixOS Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) and agree to abide by it."
required: true required: true
- label: "I assert that I have read the [automation/AI policy](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy) and that this issue report complies with it."
required: true
- type: "markdown" - type: "markdown"
attributes: attributes:
value: | value: |

View File

@@ -13,6 +13,7 @@ For new packages please briefly describe the package or provide a link to its ho
- Built on platform: - Built on platform:
- [ ] x86_64-linux - [ ] x86_64-linux
- [ ] aarch64-linux - [ ] aarch64-linux
- [ ] x86_64-darwin
- [ ] aarch64-darwin - [ ] aarch64-darwin
- Tested, as applicable: - Tested, as applicable:
- [ ] [NixOS tests] in [nixos/tests]. - [ ] [NixOS tests] in [nixos/tests].
@@ -26,14 +27,12 @@ For new packages please briefly describe the package or provide a link to its ho
- [ ] Module addition: when adding a new NixOS module. - [ ] Module addition: when adding a new NixOS module.
- [ ] Module update: when the change is significant. - [ ] Module update: when the change is significant.
- [ ] Fits [CONTRIBUTING.md], [pkgs/README.md], [maintainers/README.md] and other READMEs. - [ ] Fits [CONTRIBUTING.md], [pkgs/README.md], [maintainers/README.md] and other READMEs.
- [ ] Follows the [automation/AI policy].
[NixOS tests]: https://nixos.org/manual/nixos/unstable/index.html#sec-nixos-tests [NixOS tests]: https://nixos.org/manual/nixos/unstable/index.html#sec-nixos-tests
[Package tests]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#package-tests [Package tests]: https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#package-tests
[nixpkgs-review usage]: https://github.com/Mic92/nixpkgs-review#usage [nixpkgs-review usage]: https://github.com/Mic92/nixpkgs-review#usage
[CONTRIBUTING.md]: https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md [CONTRIBUTING.md]: https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md
[automation/AI policy]: https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#automationai-policy
[lib/tests]: https://github.com/NixOS/nixpkgs/blob/master/lib/tests [lib/tests]: https://github.com/NixOS/nixpkgs/blob/master/lib/tests
[maintainers/README.md]: https://github.com/NixOS/nixpkgs/blob/master/maintainers/README.md [maintainers/README.md]: https://github.com/NixOS/nixpkgs/blob/master/maintainers/README.md
[nixos/tests]: https://github.com/NixOS/nixpkgs/blob/master/nixos/tests [nixos/tests]: https://github.com/NixOS/nixpkgs/blob/master/nixos/tests

View File

@@ -13,13 +13,12 @@ inputs:
runs: runs:
using: composite using: composite
steps: steps:
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env: env:
MERGED_SHA: ${{ inputs.merged-as-untrusted-at }} MERGED_SHA: ${{ inputs.merged-as-untrusted-at }}
TARGET_SHA: ${{ inputs.target-as-trusted-at }} TARGET_SHA: ${{ inputs.target-as-trusted-at }}
PIN_BUMP_SHA: ${{ inputs.untrusted-pin-bump }} PIN_BUMP_SHA: ${{ inputs.untrusted-pin-bump }}
with: with:
retries: 3
script: | script: |
const { rm, writeFile } = require('node:fs/promises') const { rm, writeFile } = require('node:fs/promises')
const { spawn } = require('node:child_process') const { spawn } = require('node:child_process')
@@ -96,22 +95,25 @@ runs:
// This would fail without --refetch, because the we had a partial clone before, but changed it above. // This would fail without --refetch, because the we had a partial clone before, but changed it above.
await run('git', 'fetch', '--depth=1', '--refetch', 'origin', ...(commits.map(({ sha }) => sha))) await run('git', 'fetch', '--depth=1', '--refetch', 'origin', ...(commits.map(({ sha }) => sha)))
// On Linux, checking out onto tmpfs takes 1s and is faster by at least 10x. // Checking out onto tmpfs takes 1s and is faster by at least factor 10x.
// Currently, on Darwin we can only allocate 3.5GB, which isn't enough.
// See https://github.com/NixOS/nixpkgs/pull/506437
await run('mkdir', 'nixpkgs') await run('mkdir', 'nixpkgs')
if (process.env.RUNNER_OS === 'Linux') { switch (process.env.RUNNER_OS) {
await run('sudo', 'mount', '-t', 'tmpfs', 'tmpfs', 'nixpkgs') case 'macOS':
await run('sudo', 'mount_tmpfs', 'nixpkgs')
break
case 'Linux':
await run('sudo', 'mount', '-t', 'tmpfs', 'tmpfs', 'nixpkgs')
break
} }
// Git worktree setup can race when multiple worktrees are created and // Create all worktrees in parallel.
// initialized at the same time against one repository. See #511286. await Promise.all(
// Keep the setup sequential so shared repo config updates cannot contend. commits.map(async ({ sha, path }) => {
for (const { sha, path } of commits) { await run('git', 'worktree', 'add', join('nixpkgs', path), sha, '--no-checkout')
await run('git', 'worktree', 'add', join('nixpkgs', path), sha, '--no-checkout') await run('git', '-C', join('nixpkgs', path), 'sparse-checkout', 'disable')
await run('git', '-C', join('nixpkgs', path), 'sparse-checkout', 'disable') await run('git', '-C', join('nixpkgs', path), 'checkout', '--progress')
await run('git', '-C', join('nixpkgs', path), 'checkout', '--progress') })
} )
// Apply pin bump to untrusted worktree // Apply pin bump to untrusted worktree
if (pin_bump_sha) { if (pin_bump_sha) {
@@ -132,6 +134,3 @@ runs:
await rm('pin-bump.patch') await rm('pin-bump.patch')
} }
} }
console.log('final disk usage:')
await run('df', '-h')

View File

@@ -5,5 +5,3 @@ updates:
schedule: schedule:
interval: "weekly" interval: "weekly"
labels: [] labels: []
commit-message:
prefix: ".github"

View File

@@ -22,7 +22,7 @@
- doc/**/* - doc/**/*
- nixos/doc/**/* - nixos/doc/**/*
"backport release-26.05": "backport release-25.11":
- all: - all:
- changed-files: - changed-files:
- any-glob-to-any-file: - any-glob-to-any-file:

8
.github/labeler.yml vendored
View File

@@ -9,7 +9,6 @@
- '^release-' - '^release-'
- '^staging-\d' - '^staging-\d'
- '^staging-next-\d' - '^staging-next-\d'
- '^staging-nixos-\d'
# NOTE: bsd, darwin and cross-compilation labels are handled by ofborg # NOTE: bsd, darwin and cross-compilation labels are handled by ofborg
"6.topic: agda": "6.topic: agda":
@@ -271,14 +270,8 @@
- any: - any:
- changed-files: - changed-files:
- any-glob-to-any-file: - any-glob-to-any-file:
- doc/packages/linux.section.md
- lib/kernel.nix
- nixos/doc/manual/configuration/linux-kernel.chapter.md
- nixos/modules/system/boot/kernel.nix
- nixos/tests/kernel-generic/**/*
- pkgs/build-support/kernel/**/* - pkgs/build-support/kernel/**/*
- pkgs/os-specific/linux/kernel/**/* - pkgs/os-specific/linux/kernel/**/*
- pkgs/top-level/linux-kernels.nix
"6.topic: lib": "6.topic: lib":
- any: - any:
@@ -552,6 +545,7 @@
- pkgs/by-name/*/*tree-sitter*/**/* - pkgs/by-name/*/*tree-sitter*/**/*
- pkgs/by-name/ne/neovim-unwrapped/treesitter-parsers.nix - pkgs/by-name/ne/neovim-unwrapped/treesitter-parsers.nix
- pkgs/development/python-modules/*tree-sitter*/**/* - pkgs/development/python-modules/*tree-sitter*/**/*
- pkgs/development/tools/parsing/tree-sitter/**/*
"6.topic: updaters": "6.topic: updaters":
- any: - any:

View File

@@ -11,8 +11,8 @@ on:
permissions: permissions:
contents: read contents: read
issues: write # adding the 'has: port to stable' and 'has: backport failed' label issues: write
pull-requests: write # creating backport pull requests pull-requests: write
defaults: defaults:
run: run:
@@ -21,22 +21,22 @@ defaults:
jobs: jobs:
backport: backport:
name: Backport Pull Request name: Backport Pull Request
if: vars.NIXPKGS_CI_CLIENT_ID && github.event.pull_request.merged == true && (github.event.action != 'labeled' || startsWith(github.event.label.name, 'backport')) if: vars.NIXPKGS_CI_APP_ID && github.event.pull_request.merged == true && (github.event.action != 'labeled' || startsWith(github.event.label.name, 'backport'))
runs-on: ubuntu-slim runs-on: ubuntu-slim
timeout-minutes: 3 timeout-minutes: 3
steps: steps:
# Use a GitHub App to create the PR so that CI gets triggered # Use a GitHub App to create the PR so that CI gets triggered
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs # The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
id: app-token id: app-token
with: with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }} app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-contents: write permission-contents: write
permission-pull-requests: write permission-pull-requests: write
permission-workflows: write permission-workflows: write
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
ref: ${{ github.event.pull_request.head.sha }} ref: ${{ github.event.pull_request.head.sha }}
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
@@ -49,10 +49,9 @@ jobs:
- name: Create backport PRs - name: Create backport PRs
id: backport id: backport
uses: korthout/backport-action@2e830a1d0b8269505846ddd407a70876913ad1f8 # v4.6.0 uses: korthout/backport-action@c656f5d5851037b2b38fb5db2691a03fa229e3b2 # v4.0.1
with: with:
# Config README: https://github.com/korthout/backport-action#backport-action # Config README: https://github.com/korthout/backport-action#backport-action
add_author_as_reviewer: true
copy_labels_pattern: 'severity:\ssecurity' copy_labels_pattern: 'severity:\ssecurity'
github_token: ${{ steps.app-token.outputs.token }} github_token: ${{ steps.app-token.outputs.token }}
pull_description: |- pull_description: |-
@@ -72,7 +71,7 @@ jobs:
- name: "Add 'has: port to stable' label" - name: "Add 'has: port to stable' label"
if: steps.backport.outputs.created_pull_numbers != '' if: steps.backport.outputs.created_pull_numbers != ''
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
# Not using the app on purpose to avoid triggering another workflow run after adding this label. # Not using the app on purpose to avoid triggering another workflow run after adding this label.
script: | script: |
@@ -82,16 +81,3 @@ jobs:
issue_number: context.payload.pull_request.number, issue_number: context.payload.pull_request.number,
labels: [ '8.has: port to stable' ] labels: [ '8.has: port to stable' ]
}) })
- name: "Add 'has: failed backport' label"
if: steps.backport.outputs.was_successful == 'false'
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
# Not using the app on purpose to avoid triggering another workflow run after adding this label.
script: |
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: [ '8.has: failed backport' ]
})

View File

@@ -30,8 +30,8 @@ concurrency:
# This is used as fallback without app only. # This is used as fallback without app only.
# This happens when testing in forks without setting up that app. # This happens when testing in forks without setting up that app.
permissions: permissions:
issues: write # managing issue labels and comments issues: write
pull-requests: write # managing pull request labels and comments pull-requests: write
defaults: defaults:
run: run:
@@ -46,21 +46,21 @@ jobs:
# https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/ # https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true" FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: | sparse-checkout: |
ci/github-script ci/github-script
- name: Install dependencies - name: Install dependencies
run: npm install @actions/artifact@6.2.1 bottleneck@2.19.5 run: npm install @actions/artifact@5.0.3 bottleneck@2.19.5
# Use a GitHub App, because it has much higher rate limits: 12,500 instead of 5,000 req / hour. # Use a GitHub App, because it has much higher rate limits: 12,500 instead of 5,000 req / hour.
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_CLIENT_ID if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_APP_ID
id: app-token id: app-token
with: with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }} app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-administration: read permission-administration: read
permission-contents: write permission-contents: write
@@ -74,7 +74,7 @@ jobs:
run: gh api /rate_limit | jq run: gh api /rate_limit | jq
- name: Run bot - name: Run bot
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
github-token: ${{ steps.app-token.outputs.token || github.token }} github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 3 retries: 3
@@ -91,7 +91,7 @@ jobs:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }} GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq run: gh api /rate_limit | jq
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0 - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
name: Labels from touched files name: Labels from touched files
if: | if: |
github.event_name == 'pull_request_target' && github.event_name == 'pull_request_target' &&
@@ -101,7 +101,7 @@ jobs:
configuration-path: .github/labeler.yml # default configuration-path: .github/labeler.yml # default
sync-labels: true sync-labels: true
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0 - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
name: Labels from touched files (no sync) name: Labels from touched files (no sync)
if: | if: |
github.event_name == 'pull_request_target' && github.event_name == 'pull_request_target' &&
@@ -111,7 +111,7 @@ jobs:
configuration-path: .github/labeler-no-sync.yml configuration-path: .github/labeler-no-sync.yml
sync-labels: false sync-labels: false
- uses: actions/labeler@b8dd2d9be0f68b860e7dae5dae7d772984eacd6d # v6.2.0 - uses: actions/labeler@634933edcd8ababfe52f92936142cc22ac488b1b # v6.0.1
name: Labels from touched files (development branches) name: Labels from touched files (development branches)
# Development branches like staging-next, haskell-updates and python-updates get special labels. # Development branches like staging-next, haskell-updates and python-updates get special labels.
# This is to avoid the mass of labels there, which is mostly useless - and really annoying for # This is to avoid the mass of labels there, which is mostly useless - and really annoying for

View File

@@ -34,22 +34,25 @@ jobs:
matrix: matrix:
include: include:
- runner: ubuntu-24.04 - runner: ubuntu-24.04
system: x86_64-linux name: x86_64-linux
systems: x86_64-linux
builds: [shell, manual-nixos, lib-tests, tarball] builds: [shell, manual-nixos, lib-tests, tarball]
desc: shell, docs, lib, tarball desc: shell, docs, lib, tarball
- runner: ubuntu-24.04-arm - runner: ubuntu-24.04-arm
system: aarch64-linux name: aarch64-linux
systems: aarch64-linux
builds: [shell, manual-nixos, manual-nixpkgs] builds: [shell, manual-nixos, manual-nixpkgs]
desc: shell, docs desc: shell, docs
- runner: macos-14 - runner: macos-14
system: aarch64-darwin name: darwin
systems: aarch64-darwin x86_64-darwin
builds: [shell] builds: [shell]
desc: shell desc: shell
name: '${{ matrix.system }}: ${{ matrix.desc }}' name: '${{ matrix.name }}: ${{ matrix.desc }}'
runs-on: ${{ matrix.runner }} runs-on: ${{ matrix.runner }}
timeout-minutes: 60 timeout-minutes: 60
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -59,12 +62,12 @@ jobs:
merged-as-untrusted-at: ${{ inputs.mergedSha }} merged-as-untrusted-at: ${{ inputs.mergedSha }}
target-as-trusted-at: ${{ inputs.targetSha }} target-as-trusted-at: ${{ inputs.targetSha }}
- uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
with: with:
# Sandbox is disabled on MacOS by default. # Sandbox is disabled on MacOS by default.
extra_nix_config: sandbox = true extra_nix_config: sandbox = true
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17 - uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
continue-on-error: true continue-on-error: true
with: with:
# The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI. # The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI.
@@ -77,16 +80,12 @@ jobs:
- name: Build shell - name: Build shell
if: contains(matrix.builds, 'shell') if: contains(matrix.builds, 'shell')
env: run: echo "${{ matrix.systems }}" | xargs -n1 nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A shell --argstr system
system: ${{ matrix.system }}
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A shell --argstr system "$system"
- name: Build NixOS manual - name: Build NixOS manual
if: | if: |
contains(matrix.builds, 'manual-nixos') && !cancelled() && contains(matrix.builds, 'manual-nixos') && !cancelled() &&
(contains(fromJSON(inputs.baseBranch).type, 'primary') contains(fromJSON(inputs.baseBranch).type, 'primary')
|| startsWith(fromJSON(inputs.baseBranch).branch, 'staging-nixos')
)
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixos --out-link nixos-manual run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixos --out-link nixos-manual
- name: Build Nixpkgs manual - name: Build Nixpkgs manual
@@ -105,7 +104,7 @@ jobs:
if: | if: |
contains(matrix.builds, 'manual-nixos') && !cancelled() && contains(matrix.builds, 'manual-nixos') && !cancelled() &&
contains(fromJSON(inputs.baseBranch).type, 'primary') contains(fromJSON(inputs.baseBranch).type, 'primary')
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: ${{ inputs.artifact-prefix }}nixos-manual-${{ matrix.system }} name: ${{ inputs.artifact-prefix }}nixos-manual-${{ matrix.name }}
path: nixos-manual path: nixos-manual

View File

@@ -16,14 +16,6 @@ on:
required: true required: true
type: string type: string
secrets: secrets:
# Can be provided in pull requests because the job it is used in does
# not evaluate untrusted code.
NIXPKGS_COMMIT_CHECK_APP_PRIVATE_KEY:
required: false
# Can be provided in pull requests because the job it is used in does
# not evaluate untrusted code.
NIXPKGS_MANUAL_EDIT_CHECK_APP_PRIVATE_KEY:
required: false
# Should only be provided in the merge queue, not in pull requests, # Should only be provided in the merge queue, not in pull requests,
# where we're evaluating untrusted code. # where we're evaluating untrusted code.
CACHIX_AUTH_TOKEN_GHA: CACHIX_AUTH_TOKEN_GHA:
@@ -39,11 +31,11 @@ jobs:
commits: commits:
if: inputs.baseBranch && inputs.headBranch if: inputs.baseBranch && inputs.headBranch
permissions: permissions:
pull-requests: write # submitting PR reviews pull-requests: write
runs-on: ubuntu-slim runs-on: ubuntu-slim
timeout-minutes: 3 timeout-minutes: 3
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
path: trusted path: trusted
@@ -53,26 +45,17 @@ jobs:
- name: Install dependencies - name: Install dependencies
run: npm install bottleneck@2.19.5 run: npm install bottleneck@2.19.5
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
if: github.event_name != 'pull_request' && vars.NIXPKGS_COMMIT_CHECK_CLIENT_ID
id: app-token
with:
client-id: ${{ vars.NIXPKGS_COMMIT_CHECK_CLIENT_ID }}
private-key: ${{ secrets.NIXPKGS_COMMIT_CHECK_APP_PRIVATE_KEY }}
permission-pull-requests: write
- name: Log current API rate limits - name: Log current API rate limits
env: env:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }} GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq run: gh api /rate_limit | jq
- name: Check commits - name: Check commits
id: check id: check
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env: env:
TARGETS_STABLE: ${{ fromJSON(inputs.baseBranch).stable && !contains(fromJSON(inputs.headBranch).type, 'development') }} TARGETS_STABLE: ${{ fromJSON(inputs.baseBranch).stable && !contains(fromJSON(inputs.headBranch).type, 'development') }}
with: with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: | script: |
const targetsStable = JSON.parse(process.env.TARGETS_STABLE) const targetsStable = JSON.parse(process.env.TARGETS_STABLE)
require('./trusted/ci/github-script/commits.js')({ require('./trusted/ci/github-script/commits.js')({
@@ -85,59 +68,14 @@ jobs:
- name: Log current API rate limits - name: Log current API rate limits
env: env:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }} GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq
manual-file-edits:
if: inputs.baseBranch && inputs.headBranch
permissions:
pull-requests: write
runs-on: ubuntu-24.04-arm
timeout-minutes: 8
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
path: trusted
sparse-checkout: |
ci/github-script
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
if: github.event_name != 'pull_request' && vars.NIXPKGS_MANUAL_EDIT_CHECK_CLIENT_ID
id: app-token
with:
client-id: ${{ vars.NIXPKGS_MANUAL_EDIT_CHECK_CLIENT_ID }}
private-key: ${{ secrets.NIXPKGS_MANUAL_EDIT_CHECK_APP_PRIVATE_KEY }}
permission-pull-requests: write
- name: Log current API rate limits
env:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq
- name: Discourage manual edits to certain files
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: |
require('./trusted/ci/github-script/manual-file-edits.js')({
github,
context,
core,
dry: context.eventName == 'pull_request',
repoPath: 'trusted',
})
- name: Log current API rate limits
env:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq run: gh api /rate_limit | jq
owners: owners:
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
timeout-minutes: 5 timeout-minutes: 5
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -147,9 +85,9 @@ jobs:
merged-as-untrusted-at: ${{ inputs.mergedSha }} merged-as-untrusted-at: ${{ inputs.mergedSha }}
target-as-trusted-at: ${{ inputs.targetSha }} target-as-trusted-at: ${{ inputs.targetSha }}
- uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17 - uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
continue-on-error: true continue-on-error: true
with: with:
# The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI. # The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI.

View File

@@ -7,7 +7,7 @@ on:
# This is used as fallback without app only. # This is used as fallback without app only.
# This happens when testing in forks without setting up that app. # This happens when testing in forks without setting up that app.
permissions: permissions:
pull-requests: write # adding reactions to comments pull-requests: write
defaults: defaults:
run: run:
@@ -23,22 +23,22 @@ jobs:
timeout-minutes: 2 timeout-minutes: 2
if: contains(github.event.comment.body, '@NixOS/nixpkgs-merge-bot merge') if: contains(github.event.comment.body, '@NixOS/nixpkgs-merge-bot merge')
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: | sparse-checkout: |
ci/github-script ci/github-script
# Use the GitHub App to make sure the reaction happens with the same user who will later merge. # Use the GitHub App to make sure the reaction happens with the same user who will later merge.
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_CLIENT_ID if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_APP_ID
id: app-token id: app-token
with: with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }} app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-pull-requests: write permission-pull-requests: write
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
github-token: ${{ steps.app-token.outputs.token || github.token }} github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 3 retries: 3

View File

@@ -36,14 +36,14 @@ jobs:
# Use a GitHub App to create the PR so that CI gets triggered # Use a GitHub App to create the PR so that CI gets triggered
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs # The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
# We only need Pull Requests: write here, but the app is also used for backports. # We only need Pull Requests: write here, but the app is also used for backports.
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
id: app-token id: app-token
with: with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }} app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-pull-requests: write permission-pull-requests: write
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
github-token: ${{ steps.app-token.outputs.token }} github-token: ${{ steps.app-token.outputs.token }}
script: | script: |

View File

@@ -15,9 +15,6 @@ on:
targetSha: targetSha:
required: true required: true
type: string type: string
baseBranch:
required: true
type: string
systems: systems:
required: true required: true
type: string type: string
@@ -26,10 +23,6 @@ on:
default: false default: false
type: boolean type: boolean
secrets: secrets:
# Can be provided in pull requests because the job it is used in does
# not evaluate untrusted code.
NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY:
required: false
# Should only be provided in the merge queue, not in pull requests, # Should only be provided in the merge queue, not in pull requests,
# where we're evaluating untrusted code. # where we're evaluating untrusted code.
CACHIX_AUTH_TOKEN_GHA: CACHIX_AUTH_TOKEN_GHA:
@@ -50,7 +43,7 @@ jobs:
ciPinBumpCommit: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommit }} ciPinBumpCommit: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommit }}
ciPinBumpCommitShort: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommitShort }} ciPinBumpCommitShort: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommitShort }}
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
path: trusted path: trusted
@@ -58,7 +51,7 @@ jobs:
ci/supportedVersions.nix ci/supportedVersions.nix
- name: Check out the PR at the test merge commit - name: Check out the PR at the test merge commit
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
ref: ${{ inputs.mergedSha }} ref: ${{ inputs.mergedSha }}
@@ -68,7 +61,7 @@ jobs:
- name: Find commit that touched ci/pinned.json - name: Find commit that touched ci/pinned.json
id: find-pinned-commit id: find-pinned-commit
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env: env:
TARGET_SHA: ${{ inputs.targetSha }} TARGET_SHA: ${{ inputs.targetSha }}
HEAD_SHA: ${{ inputs.headSha }} HEAD_SHA: ${{ inputs.headSha }}
@@ -139,7 +132,7 @@ jobs:
core.info(`Found pinned.json commit: ${ciPinBumpCommit}`) core.info(`Found pinned.json commit: ${ciPinBumpCommit}`)
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- name: Load supported versions - name: Load supported versions
id: versions id: versions
@@ -161,7 +154,7 @@ jobs:
# to not interrupt main Eval's compare step. # to not interrupt main Eval's compare step.
continue-on-error: ${{ matrix.version != '' }} continue-on-error: ${{ matrix.version != '' }}
name: ${{ matrix.system }}${{ matrix.version && format(' @ {0} ({1})', matrix.version, needs.versions.outputs.ciPinBumpCommitShort) || '' }} name: ${{ matrix.system }}${{ matrix.version && format(' @ {0} ({1})', matrix.version, needs.versions.outputs.ciPinBumpCommitShort) || '' }}
timeout-minutes: 20 timeout-minutes: 15
steps: steps:
# This is not supposed to be used and just acts as a fallback. # This is not supposed to be used and just acts as a fallback.
# Without swap, when Eval runs OOM, it will fail badly with a # Without swap, when Eval runs OOM, it will fail badly with a
@@ -174,7 +167,7 @@ jobs:
sudo mkswap /swap sudo mkswap /swap
sudo swapon /swap sudo swapon /swap
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -187,9 +180,9 @@ jobs:
target-as-trusted-at: ${{ inputs.targetSha }} target-as-trusted-at: ${{ inputs.targetSha }}
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17 - uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
continue-on-error: true continue-on-error: true
with: with:
# The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI. # The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI.
@@ -245,7 +238,7 @@ jobs:
--out-link diff --out-link diff
- name: Upload outpaths diff and stats - name: Upload outpaths diff and stats
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: ${{ inputs.artifact-prefix }}${{ matrix.version && format('{0}-', matrix.version) || '' }}diff-${{ matrix.system }} name: ${{ inputs.artifact-prefix }}${{ matrix.version && format('{0}-', matrix.version) || '' }}diff-${{ matrix.system }}
path: diff/* path: diff/*
@@ -255,11 +248,11 @@ jobs:
needs: [eval] needs: [eval]
if: ${{ !cancelled() && !failure() }} if: ${{ !cancelled() && !failure() }}
permissions: permissions:
pull-requests: write # submitting 'wrong branch' reviews pull-requests: write
statuses: write # creating 'Eval Summary' commit statuses statuses: write
timeout-minutes: 5 timeout-minutes: 5
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -270,14 +263,14 @@ jobs:
target-as-trusted-at: ${{ inputs.targetSha }} target-as-trusted-at: ${{ inputs.targetSha }}
- name: Download output paths and eval stats for all systems - name: Download output paths and eval stats for all systems
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
pattern: ${{ inputs.artifact-prefix }}diff-* pattern: ${{ inputs.artifact-prefix }}diff-*
path: diff path: diff
merge-multiple: true merge-multiple: true
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- name: Combine all output paths and eval stats - name: Combine all output paths and eval stats
run: | run: |
@@ -286,7 +279,7 @@ jobs:
--out-link combined --out-link combined
- name: Upload the maintainer list - name: Upload the maintainer list
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: ${{ inputs.artifact-prefix }}maintainers name: ${{ inputs.artifact-prefix }}maintainers
path: combined/maintainers.json path: combined/maintainers.json
@@ -294,7 +287,6 @@ jobs:
- name: Compare against the target branch - name: Compare against the target branch
env: env:
TARGET_SHA: ${{ inputs.mergedSha }} TARGET_SHA: ${{ inputs.mergedSha }}
BASE_BRANCH: ${{ fromJSON(inputs.baseBranch).branch }}
run: | run: |
git -C nixpkgs/trusted diff --name-only "$TARGET_SHA" \ git -C nixpkgs/trusted diff --name-only "$TARGET_SHA" \
| jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json | jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json
@@ -303,30 +295,23 @@ jobs:
nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.compare \ nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.compare \
--arg combinedDir ./combined \ --arg combinedDir ./combined \
--arg touchedFilesJson ./touched-files.json \ --arg touchedFilesJson ./touched-files.json \
--argstr baseBranch "$BASE_BRANCH" \
--out-link comparison --out-link comparison
cat comparison/step-summary.md >> "$GITHUB_STEP_SUMMARY" cat comparison/step-summary.md >> "$GITHUB_STEP_SUMMARY"
- name: Upload the comparison results - name: Upload the comparison results
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1 uses: actions/upload-artifact@b7c566a772e6b6bfb58ed0dc250532a479d7789f # v6.0.0
with: with:
name: ${{ inputs.artifact-prefix }}comparison name: ${{ inputs.artifact-prefix }}comparison
path: comparison/* path: comparison/*
- name: Add eval summary to commit statuses - name: Add eval summary to commit statuses
if: ${{ github.event_name == 'pull_request_target' }} if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
script: | script: |
const { readFile } = require('node:fs/promises') const { readFile } = require('node:fs/promises')
const changed = JSON.parse(await readFile('comparison/changed-paths.json', 'utf-8')) const changed = JSON.parse(await readFile('comparison/changed-paths.json', 'utf-8'))
const removedByKernel = Object.fromEntries(
Object.entries(changed.attrdiffByKernel ?? {}).map(([kernel, diff]) => [
kernel,
diff.removed.length,
]),
)
const description = const description =
'Package: ' + [ 'Package: ' + [
`added ${changed.attrdiff.added.length}`, `added ${changed.attrdiff.added.length}`,
@@ -336,15 +321,7 @@ jobs:
' — Rebuild: ' + [ ' — Rebuild: ' + [
`linux ${changed.rebuildCountByKernel.linux}`, `linux ${changed.rebuildCountByKernel.linux}`,
`darwin ${changed.rebuildCountByKernel.darwin}` `darwin ${changed.rebuildCountByKernel.darwin}`
].join(', ') + ].join(', ')
(
Object.values(removedByKernel).some((count) => count > 0)
? ' — Removed: ' + [
`linux ${removedByKernel.linux ?? 0}`,
`darwin ${removedByKernel.darwin ?? 0}`
].join(', ')
: ''
)
const { serverUrl, repo, runId, payload } = context const { serverUrl, repo, runId, payload } = context
const target_url = const target_url =
@@ -358,22 +335,10 @@ jobs:
description, description,
target_url target_url
}) })
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
if: github.event_name == 'pull_request_target' && vars.NIXPKGS_BRANCH_CHECK_CLIENT_ID
id: app-token
with:
client-id: ${{ vars.NIXPKGS_BRANCH_CHECK_CLIENT_ID }}
private-key: ${{ secrets.NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY }}
permission-pull-requests: write
# It's fine to reuse this app in the 'pull-request-target / prepare' job,
# because that job has to run before this one.
- name: Request changes if PR is against an inappropriate branch - name: Request changes if PR is against an inappropriate branch
if: ${{ github.event_name == 'pull_request_target' }} if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: | script: |
require('./nixpkgs/trusted/ci/github-script/check-target-branch.js')({ require('./nixpkgs/trusted/ci/github-script/check-target-branch.js')({
github, github,
@@ -388,13 +353,13 @@ jobs:
needs: [versions, eval] needs: [versions, eval]
steps: steps:
- name: Download output paths and eval stats for all versions - name: Download output paths and eval stats for all versions
uses: actions/download-artifact@3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8.0.1 uses: actions/download-artifact@37930b1c2abaa49bbe596cd826c3c89aef350131 # v7.0.0
with: with:
pattern: "*-diff-*" pattern: "*-diff-*"
path: versions path: versions
- name: Add version comparison table to job summary - name: Add version comparison table to job summary
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env: env:
ARTIFACT_PREFIX: ${{ inputs.artifact-prefix }} ARTIFACT_PREFIX: ${{ inputs.artifact-prefix }}
SYSTEMS: ${{ inputs.systems }} SYSTEMS: ${{ inputs.systems }}
@@ -476,7 +441,7 @@ jobs:
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -486,7 +451,7 @@ jobs:
merged-as-untrusted-at: ${{ inputs.mergedSha }} merged-as-untrusted-at: ${{ inputs.mergedSha }}
- name: Install Nix - name: Install Nix
uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- name: Ensure flake outputs on all systems still evaluate - name: Ensure flake outputs on all systems still evaluate
run: nix flake check --all-systems --no-build './nixpkgs/untrusted?shallow=1' run: nix flake check --all-systems --no-build './nixpkgs/untrusted?shallow=1'

View File

@@ -26,7 +26,7 @@ jobs:
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -35,7 +35,7 @@ jobs:
with: with:
merged-as-untrusted-at: ${{ inputs.mergedSha }} merged-as-untrusted-at: ${{ inputs.mergedSha }}
- uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
# TODO: Figure out how to best enable caching for the treefmt job. Cachix won't work well, # TODO: Figure out how to best enable caching for the treefmt job. Cachix won't work well,
# because the cache would be invalidated on every commit - treefmt checks every file. # because the cache would be invalidated on every commit - treefmt checks every file.
@@ -61,7 +61,7 @@ jobs:
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -70,9 +70,9 @@ jobs:
with: with:
merged-as-untrusted-at: ${{ inputs.mergedSha }} merged-as-untrusted-at: ${{ inputs.mergedSha }}
- uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17 - uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
continue-on-error: true continue-on-error: true
with: with:
# The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI. # The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI.
@@ -90,7 +90,7 @@ jobs:
runs-on: ubuntu-24.04-arm runs-on: ubuntu-24.04-arm
timeout-minutes: 10 timeout-minutes: 10
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: .github/actions sparse-checkout: .github/actions
@@ -100,9 +100,9 @@ jobs:
merged-as-untrusted-at: ${{ inputs.mergedSha }} merged-as-untrusted-at: ${{ inputs.mergedSha }}
target-as-trusted-at: ${{ inputs.targetSha }} target-as-trusted-at: ${{ inputs.targetSha }}
- uses: cachix/install-nix-action@a49548c11d9846ad46ecc0115273879b045f001c # v31.10.7 - uses: cachix/install-nix-action@4e002c8ec80594ecd40e759629461e26c8abed15 # v31
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17 - uses: cachix/cachix-action@3ba601ff5bbb07c7220846facfa2cd81eeee15a1 # v16
continue-on-error: true continue-on-error: true
with: with:
# The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI. # The nixpkgs-gha cache should not be trusted or used outside of Nixpkgs and its forks' CI.
@@ -131,15 +131,15 @@ jobs:
# Luckily there's no need to lint commit messages in the Merge Queue, because # Luckily there's no need to lint commit messages in the Merge Queue, because
# changes to the target branch can't change commit messages on the base branch. # changes to the target branch can't change commit messages on the base branch.
if: ${{ github.event.pull_request.number }} if: ${{ github.event.pull_request.number }}
runs-on: ubuntu-24.04-arm runs-on: ubuntu-slim
timeout-minutes: 8 timeout-minutes: 5
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: true # Needed to run git fetch for large PRs. persist-credentials: true # Needed to run git fetch for large PRs.
path: trusted path: trusted
- name: Check commit messages - name: Check commit messages
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
script: | script: |
const checkCommitMessages = require('./trusted/ci/github-script/lint-commits.js') const checkCommitMessages = require('./trusted/ci/github-script/lint-commits.js')

View File

@@ -25,22 +25,20 @@ jobs:
targetSha: ${{ steps.prepare.outputs.targetSha }} targetSha: ${{ steps.prepare.outputs.targetSha }}
systems: ${{ steps.prepare.outputs.systems }} systems: ${{ steps.prepare.outputs.systems }}
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: | sparse-checkout: |
ci/github-script/supportedSystems.js ci/supportedSystems.json
- id: prepare - id: prepare
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env: env:
MERGED_SHA: ${{ inputs.mergedSha }} MERGED_SHA: ${{ inputs.mergedSha }}
TARGET_SHA: ${{ inputs.targetSha }} TARGET_SHA: ${{ inputs.targetSha }}
with: with:
script: | script: |
const { classify } = require('./ci/supportedBranches.js') const { classify } = require('./ci/supportedBranches.js')
const supportedSystems = require('./ci/github-script/supportedSystems.js')
const baseBranch = ( const baseBranch = (
context.payload.merge_group?.base_ref ?? context.payload.merge_group?.base_ref ??
context.payload.pull_request.base.ref context.payload.pull_request.base.ref
@@ -49,23 +47,19 @@ jobs:
core.setOutput('base', baseClassification) core.setOutput('base', baseClassification)
core.info('base classification:', baseClassification) core.info('base classification:', baseClassification)
const mergedSha = context.payload.merge_group?.head_sha ?? process.env.MERGED_SHA core.setOutput('mergedSha', context.payload.merge_group?.head_sha ?? process.env.MERGED_SHA)
core.setOutput('mergedSha', mergedSha) core.info(`mergedSha: ${context.payload.merge_group?.head_sha ?? process.env.MERGED_SHA}`)
core.info(`mergedSha: ${mergedSha}`) core.setOutput('targetSha', context.payload.merge_group?.base_sha ?? process.env.TARGET_SHA)
core.info(`targetSha: ${context.payload.merge_group?.base_sha ?? process.env.TARGET_SHA}`)
const targetSha = context.payload.merge_group?.base_sha ?? process.env.TARGET_SHA core.setOutput('systems', require('./ci/supportedSystems.json'))
core.setOutput('targetSha', targetSha)
core.info(`targetSha: ${targetSha}`)
const systems = await supportedSystems({ github, context, targetSha })
core.setOutput('systems', systems)
check: check:
name: Check name: Check
needs: [prepare] needs: [prepare]
uses: ./.github/workflows/check.yml uses: ./.github/workflows/check.yml
permissions: permissions:
pull-requests: write # cherry-picks: unused in merge queue but required for check workflow # cherry-picks; formality right now, but unused
pull-requests: write
secrets: secrets:
CACHIX_AUTH_TOKEN_GHA: ${{ secrets.CACHIX_AUTH_TOKEN_GHA }} CACHIX_AUTH_TOKEN_GHA: ${{ secrets.CACHIX_AUTH_TOKEN_GHA }}
with: with:
@@ -89,15 +83,15 @@ jobs:
# The eval workflow requests these permissions so we must explicitly allow them, # The eval workflow requests these permissions so we must explicitly allow them,
# even though they are unused when working with the merge queue. # even though they are unused when working with the merge queue.
permissions: permissions:
pull-requests: write # compare: unused in merge queue but required by eval workflow # compare
statuses: write # compare: unused in merge queue but required by eval workflow pull-requests: write
statuses: write
secrets: secrets:
CACHIX_AUTH_TOKEN_GHA: ${{ secrets.CACHIX_AUTH_TOKEN_GHA }} CACHIX_AUTH_TOKEN_GHA: ${{ secrets.CACHIX_AUTH_TOKEN_GHA }}
with: with:
artifact-prefix: ${{ inputs.artifact-prefix }} artifact-prefix: ${{ inputs.artifact-prefix }}
mergedSha: ${{ needs.prepare.outputs.mergedSha }} mergedSha: ${{ needs.prepare.outputs.mergedSha }}
targetSha: ${{ needs.prepare.outputs.targetSha }} targetSha: ${{ needs.prepare.outputs.targetSha }}
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
systems: ${{ needs.prepare.outputs.systems }} systems: ${{ needs.prepare.outputs.systems }}
build: build:
@@ -124,9 +118,9 @@ jobs:
- build - build
runs-on: ubuntu-slim runs-on: ubuntu-slim
permissions: permissions:
statuses: write # creating 'no PR failures' commit status statuses: write
steps: steps:
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env: env:
RESULTS: ${{ toJSON(needs.*.result) }} RESULTS: ${{ toJSON(needs.*.result) }}
with: with:

View File

@@ -22,7 +22,7 @@ defaults:
jobs: jobs:
periodic-merge: periodic-merge:
if: github.repository_owner == 'NixOS' || github.event_name == 'workflow_dispatch' if: github.repository_owner == 'NixOS'
strategy: strategy:
# don't fail fast, so that all pairs are tried # don't fail fast, so that all pairs are tried
fail-fast: false fail-fast: false
@@ -31,12 +31,10 @@ jobs:
max-parallel: 1 max-parallel: 1
matrix: matrix:
pairs: pairs:
- from: release-26.05 - from: release-25.11
into: staging-next-26.05 into: staging-next-25.11
- from: staging-next-26.05 - from: staging-next-25.11
into: staging-26.05 into: staging-25.11
- from: release-26.05
into: staging-nixos-26.05
- name: merge-base(master,staging) → haskell-updates - name: merge-base(master,staging) → haskell-updates
from: master staging from: master staging
into: haskell-updates into: haskell-updates
@@ -47,34 +45,3 @@ jobs:
name: ${{ matrix.pairs.name || format('{0} → {1}', matrix.pairs.from, matrix.pairs.into) }} name: ${{ matrix.pairs.name || format('{0} → {1}', matrix.pairs.from, matrix.pairs.into) }}
secrets: secrets:
NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
# Resets the target branch of the current haskell-updates PR.
# This makes GitHub hide all the commits that are already part of staging and gives us a much clearer PR view.
haskell-updates:
needs: periodic-merge
runs-on: ubuntu-slim
permissions:
pull-requests: write
steps:
- name: Find PR and update target branch
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
// There will at most be a single haskell-updates PR anyway, so no need to paginate.
await Promise.all(
(
await github.rest.pulls.list({
...context.repo,
state: 'open',
head: `${context.repo.owner}:haskell-updates`,
})
).data.map((pr) =>
github.rest.pulls.update({
...context.repo,
pull_number: pr.number,
// Just updating to the same branch to trigger a UI update.
// This is staging most of the time, but could be staging-next in rare cases.
base: pr.base.ref,
}),
),
)

View File

@@ -22,7 +22,7 @@ defaults:
jobs: jobs:
periodic-merge: periodic-merge:
if: github.repository_owner == 'NixOS' || github.event_name == 'workflow_dispatch' if: github.repository_owner == 'NixOS'
strategy: strategy:
# don't fail fast, so that all pairs are tried # don't fail fast, so that all pairs are tried
fail-fast: false fail-fast: false

View File

@@ -26,15 +26,15 @@ jobs:
steps: steps:
# Use a GitHub App to create the PR so that CI gets triggered # Use a GitHub App to create the PR so that CI gets triggered
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs # The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
id: app-token id: app-token
with: with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }} app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-contents: write permission-contents: write
permission-pull-requests: write permission-pull-requests: write
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
@@ -60,10 +60,10 @@ jobs:
github_token: ${{ steps.app-token.outputs.token }} github_token: ${{ steps.app-token.outputs.token }}
- name: Comment on failure - name: Comment on failure
uses: peter-evans/create-or-update-comment@e8674b075228eee787fea43ef493e45ece1004c9 # v5.0.0
if: ${{ failure() }} if: ${{ failure() }}
env: with:
BODY_TEXT: | issue-number: 105153
body: |
Periodic merge from `${{ inputs.from }}` into [`${{ inputs.into }}`](https://github.com/NixOS/nixpkgs/tree/${{ inputs.into }}) has [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}). Periodic merge from `${{ inputs.from }}` into [`${{ inputs.into }}`](https://github.com/NixOS/nixpkgs/tree/${{ inputs.into }}) has [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}).
GH_TOKEN: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
run: |
gh pr comment 105153 --body "$BODY_TEXT"

View File

@@ -10,12 +10,6 @@ on:
secrets: secrets:
NIXPKGS_CI_APP_PRIVATE_KEY: NIXPKGS_CI_APP_PRIVATE_KEY:
required: true required: true
NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY:
required: true
NIXPKGS_COMMIT_CHECK_APP_PRIVATE_KEY:
required: true
NIXPKGS_MANUAL_EDIT_CHECK_APP_PRIVATE_KEY:
required: true
concurrency: concurrency:
group: pr-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }} group: pr-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
@@ -27,7 +21,8 @@ jobs:
prepare: prepare:
runs-on: ubuntu-slim runs-on: ubuntu-slim
permissions: permissions:
pull-requests: write # submitting 'wrong branch' reviews # wrong branch review comment
pull-requests: write
outputs: outputs:
baseBranch: ${{ steps.prepare.outputs.base }} baseBranch: ${{ steps.prepare.outputs.base }}
headBranch: ${{ steps.prepare.outputs.head }} headBranch: ${{ steps.prepare.outputs.head }}
@@ -36,27 +31,15 @@ jobs:
systems: ${{ steps.prepare.outputs.systems }} systems: ${{ steps.prepare.outputs.systems }}
touched: ${{ steps.prepare.outputs.touched }} touched: ${{ steps.prepare.outputs.touched }}
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout-cone-mode: true # default, for clarity sparse-checkout-cone-mode: true # default, for clarity
sparse-checkout: | sparse-checkout: |
ci/github-script ci/github-script
# It's fine to reuse this app in the 'eval / compare' job,
# because this job has to run before that one.
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
if: vars.NIXPKGS_BRANCH_CHECK_CLIENT_ID && github.actor != 'dependabot[bot]'
id: app-token
with:
client-id: ${{ vars.NIXPKGS_BRANCH_CHECK_CLIENT_ID }}
private-key: ${{ secrets.NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY }}
permission-pull-requests: write
- id: prepare - id: prepare
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 10 retries: 10
# The default for this includes code 422, which happens regularly for us when comparing commits: # The default for this includes code 422, which happens regularly for us when comparing commits:
# 422 - Server Error: Sorry, this diff is taking too long to generate. # 422 - Server Error: Sorry, this diff is taking too long to generate.
@@ -78,9 +61,6 @@ jobs:
permissions: permissions:
# cherry-picks # cherry-picks
pull-requests: write pull-requests: write
secrets:
NIXPKGS_COMMIT_CHECK_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_COMMIT_CHECK_APP_PRIVATE_KEY }}
NIXPKGS_MANUAL_EDIT_CHECK_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_MANUAL_EDIT_CHECK_APP_PRIVATE_KEY }}
with: with:
baseBranch: ${{ needs.prepare.outputs.baseBranch }} baseBranch: ${{ needs.prepare.outputs.baseBranch }}
headBranch: ${{ needs.prepare.outputs.headBranch }} headBranch: ${{ needs.prepare.outputs.headBranch }}
@@ -103,14 +83,11 @@ jobs:
# compare # compare
pull-requests: write pull-requests: write
statuses: write statuses: write
secrets:
NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY }}
with: with:
artifact-prefix: ${{ inputs.artifact-prefix }} artifact-prefix: ${{ inputs.artifact-prefix }}
mergedSha: ${{ needs.prepare.outputs.mergedSha }} mergedSha: ${{ needs.prepare.outputs.mergedSha }}
headSha: ${{ github.event.pull_request.head.sha }} headSha: ${{ github.event.pull_request.head.sha }}
targetSha: ${{ needs.prepare.outputs.targetSha }} targetSha: ${{ needs.prepare.outputs.targetSha }}
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
systems: ${{ needs.prepare.outputs.systems }} systems: ${{ needs.prepare.outputs.systems }}
testVersions: ${{ contains(fromJSON(needs.prepare.outputs.touched), 'pinned') && !contains(fromJSON(needs.prepare.outputs.headBranch).type, 'development') }} testVersions: ${{ contains(fromJSON(needs.prepare.outputs.touched), 'pinned') && !contains(fromJSON(needs.prepare.outputs.headBranch).type, 'development') }}
@@ -150,7 +127,7 @@ jobs:
permissions: permissions:
statuses: write statuses: write
steps: steps:
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env: env:
RESULTS: ${{ toJSON(needs.*.result) }} RESULTS: ${{ toJSON(needs.*.result) }}
with: with:

View File

@@ -9,7 +9,7 @@ on:
# This is used as fallback without app only. # This is used as fallback without app only.
# This happens when testing in forks without setting up that app. # This happens when testing in forks without setting up that app.
permissions: permissions:
pull-requests: write # minimizing dismissed reviews and adding reactions pull-requests: write
defaults: defaults:
run: run:
@@ -20,22 +20,22 @@ jobs:
runs-on: ubuntu-slim runs-on: ubuntu-slim
timeout-minutes: 2 timeout-minutes: 2
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: | sparse-checkout: |
ci/github-script ci/github-script
# Use the GitHub App to make sure the reaction happens with the same user who will later merge. # Use the GitHub App to make sure the reaction happens with the same user who will later merge.
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_CLIENT_ID if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_APP_ID
id: app-token id: app-token
with: with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }} app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-pull-requests: write permission-pull-requests: write
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
github-token: ${{ steps.app-token.outputs.token || github.token }} github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 3 retries: 3

View File

@@ -2,7 +2,7 @@ name: Teams
on: on:
schedule: schedule:
# Every Monday at 19:42 (randomly chosen) # Every Tuesday at 19:42 (randomly chosen)
- cron: '42 19 * * 1' - cron: '42 19 * * 1'
workflow_dispatch: workflow_dispatch:
@@ -19,10 +19,10 @@ jobs:
steps: steps:
# Use a GitHub App to create the PR so that CI gets triggered and to # Use a GitHub App to create the PR so that CI gets triggered and to
# request team member lists. # request team member lists.
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0 - uses: actions/create-github-app-token@29824e69f54612133e76f7eaac726eef6c875baf # v2.2.1
id: app-token id: app-token
with: with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }} app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-administration: read permission-administration: read
permission-contents: write permission-contents: write
@@ -30,7 +30,7 @@ jobs:
permission-pull-requests: write permission-pull-requests: write
- name: Fetch source - name: Fetch source
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout: | sparse-checkout: |
@@ -41,7 +41,7 @@ jobs:
run: npm install bottleneck@2.19.5 run: npm install bottleneck@2.19.5
- name: Synchronise teams - name: Synchronise teams
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
github-token: ${{ steps.app-token.outputs.token }} github-token: ${{ steps.app-token.outputs.token }}
script: | script: |
@@ -64,7 +64,7 @@ jobs:
echo "git-string=$name <$email>" >> "$GITHUB_OUTPUT" echo "git-string=$name <$email>" >> "$GITHUB_OUTPUT"
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@5f6978faf089d4d20b00c7766989d076bb2fc7f1 # v8.1.1 uses: peter-evans/create-pull-request@c0f553fe549906ede9cf27b5156039d195d2ece0 # v8.1.0
with: with:
token: ${{ steps.app-token.outputs.token }} token: ${{ steps.app-token.outputs.token }}
add-paths: maintainers/github-teams.json add-paths: maintainers/github-teams.json

View File

@@ -19,14 +19,14 @@ jobs:
push: ${{ steps.files.outputs.push }} push: ${{ steps.files.outputs.push }}
targetSha: ${{ steps.prepare.outputs.targetSha }} targetSha: ${{ steps.prepare.outputs.targetSha }}
steps: steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3 - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with: with:
persist-credentials: false persist-credentials: false
sparse-checkout-cone-mode: true # default, for clarity sparse-checkout-cone-mode: true # default, for clarity
sparse-checkout: | sparse-checkout: |
ci/github-script ci/github-script
- id: prepare - id: prepare
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
retries: 10 retries: 10
# The default for this includes code 422, which happens regularly for us when comparing commits: # The default for this includes code 422, which happens regularly for us when comparing commits:
@@ -45,7 +45,7 @@ jobs:
- name: Determine changed files - name: Determine changed files
id: files id: files
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0 uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
with: with:
script: | script: |
const files = (await github.paginate(github.rest.pulls.listFiles, { const files = (await github.paginate(github.rest.pulls.listFiles, {
@@ -55,16 +55,10 @@ jobs:
})).map(file => file.filename) })).map(file => file.filename)
if (files.some(file => [ if (files.some(file => [
'.github/workflows/build.yml',
'.github/workflows/check.yml',
'.github/workflows/eval.yml', '.github/workflows/eval.yml',
'.github/workflows/lint.yml', '.github/workflows/lint.yml',
'.github/workflows/merge-group.yml', '.github/workflows/merge-group.yml',
'.github/workflows/test.yml', '.github/workflows/test.yml',
'ci/github-script/supportedSystems.js',
'ci/pinned.json',
'ci/supportedBranches.js',
'pkgs/top-level/release-supported-systems.json',
].includes(file))) core.setOutput('merge-group', true) ].includes(file))) core.setOutput('merge-group', true)
if (files.some(file => [ if (files.some(file => [
@@ -77,19 +71,8 @@ jobs:
'.github/workflows/pull-request-target.yml', '.github/workflows/pull-request-target.yml',
'.github/workflows/test.yml', '.github/workflows/test.yml',
'ci/github-script/bot.js', 'ci/github-script/bot.js',
'ci/github-script/check-target-branch.js',
'ci/github-script/commits.js',
'ci/github-script/get-pr-commit-details.js',
'ci/github-script/lint-commits.js',
'ci/github-script/merge.js', 'ci/github-script/merge.js',
'ci/github-script/prepare.js',
'ci/github-script/reviewers.js',
'ci/github-script/reviews.js',
'ci/github-script/supportedSystems.js',
'ci/github-script/withRateLimit.js', 'ci/github-script/withRateLimit.js',
'ci/pinned.json',
'ci/supportedBranches.js',
'pkgs/top-level/release-supported-systems.json',
].includes(file))) core.setOutput('pr', true) ].includes(file))) core.setOutput('pr', true)
merge-group: merge-group:
@@ -99,8 +82,8 @@ jobs:
uses: ./.github/workflows/merge-group.yml uses: ./.github/workflows/merge-group.yml
# Those are actually only used on the merge_group event, but will throw an error if not set. # Those are actually only used on the merge_group event, but will throw an error if not set.
permissions: permissions:
pull-requests: write # unused on pull_request, required by merge-group workflow pull-requests: write
statuses: write # unused on pull_request, required by merge-group workflow statuses: write
with: with:
artifact-prefix: mg- artifact-prefix: mg-
mergedSha: ${{ needs.prepare.outputs.mergedSha }} mergedSha: ${{ needs.prepare.outputs.mergedSha }}
@@ -113,13 +96,10 @@ jobs:
uses: ./.github/workflows/pull-request-target.yml uses: ./.github/workflows/pull-request-target.yml
# Those are actually only used on the pull_request_target event, but will throw an error if not set. # Those are actually only used on the pull_request_target event, but will throw an error if not set.
permissions: permissions:
issues: write # unused on pull_request, required by bot workflow issues: write
pull-requests: write # unused on pull_request, required by PR workflow pull-requests: write
statuses: write # unused on pull_request, required by PR workflow statuses: write
secrets: secrets:
NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_BRANCH_CHECK_APP_PRIVATE_KEY }}
NIXPKGS_COMMIT_CHECK_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_COMMIT_CHECK_APP_PRIVATE_KEY }}
NIXPKGS_MANUAL_EDIT_CHECK_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_MANUAL_EDIT_CHECK_APP_PRIVATE_KEY }}
with: with:
artifact-prefix: pr- artifact-prefix: pr-

2
.github/zizmor.yml vendored
View File

@@ -10,5 +10,3 @@
rules: rules:
dangerous-triggers: dangerous-triggers:
disable: true disable: true
secrets-outside-env:
disable: true

View File

@@ -17,13 +17,11 @@ jopejoe1 <nixpkgs@missing.ninja> <34899572+jopejoe1@users.noreply.github.com>
jopejoe1 <nixpkgs@missing.ninja> <jopejoe1@missing.ninja> jopejoe1 <nixpkgs@missing.ninja> <jopejoe1@missing.ninja>
jopejoe1 <nixpkgs@missing.ninja> <jopejoe1> jopejoe1 <nixpkgs@missing.ninja> <jopejoe1>
Jörg Thalheim <joerg@thalheim.io> <Mic92@users.noreply.github.com> Jörg Thalheim <joerg@thalheim.io> <Mic92@users.noreply.github.com>
Katalin Rebhan <me@dblsaiko.net>
Lin Jian <me@linj.tech> <linj.dev@outlook.com> Lin Jian <me@linj.tech> <linj.dev@outlook.com>
Lin Jian <me@linj.tech> <75130626+jian-lin@users.noreply.github.com> Lin Jian <me@linj.tech> <75130626+jian-lin@users.noreply.github.com>
Martin Weinelt <hexa@darmstadt.ccc.de> <mweinelt@users.noreply.github.com> Martin Weinelt <hexa@darmstadt.ccc.de> <mweinelt@users.noreply.github.com>
Martin Häcker <spamfaenger@gmx.de> <spamfaenger@gmx.de> Martin Häcker <spamfaenger@gmx.de> <spamfaenger@gmx.de>
moni <lythe1107@gmail.com> <lythe1107@icloud.com> moni <lythe1107@gmail.com> <lythe1107@icloud.com>
Noah Biewesch <dev@noahbiewesch.com> <90870942+trueNAHO@users.noreply.github.com>
quantenzitrone <nix@dev.quantenzitrone.eu> quantenzitrone <nix@dev.quantenzitrone.eu>
quantenzitrone <nix@dev.quantenzitrone.eu> <74491719+Quantenzitrone@users.noreply.github.com> quantenzitrone <nix@dev.quantenzitrone.eu> <74491719+Quantenzitrone@users.noreply.github.com>
quantenzitrone <nix@dev.quantenzitrone.eu> <74491719+quantenzitrone@users.noreply.github.com> quantenzitrone <nix@dev.quantenzitrone.eu> <74491719+quantenzitrone@users.noreply.github.com>

View File

@@ -206,7 +206,7 @@ For example, if you make a change to `texlive`, you probably would only check th
#### Meets Nixpkgs contribution standards #### Meets Nixpkgs contribution standards
The last two checkboxes are about whether it fits the guidelines in this `CONTRIBUTING.md` file. The last checkbox is about whether it fits the guidelines in this `CONTRIBUTING.md` file.
This document details our standards for commit messages, reviews, licensing of contributions, etc... This document details our standards for commit messages, reviews, licensing of contributions, etc...
Everyone should read and understand these standards before submitting a pull request. Everyone should read and understand these standards before submitting a pull request.
@@ -442,7 +442,6 @@ The staging workflow is used for all stable branches with corresponding names:
- `master`/`release-YY.MM` - `master`/`release-YY.MM`
- `staging`/`staging-YY.MM` - `staging`/`staging-YY.MM`
- `staging-next`/`staging-next-YY.MM` - `staging-next`/`staging-next-YY.MM`
- `staging-nixos`/`staging-nixos-YY.MM`
[^1]: Except changes that cause no more rebuilds than kernel updates [^1]: Except changes that cause no more rebuilds than kernel updates
@@ -506,7 +505,7 @@ These PRs go to `staging-nixos`, see [the next section for more context](#change
Changes causing a rebuild of all NixOS tests get a special [`10.rebuild-nixos-tests`](https://github.com/NixOS/nixpkgs/issues?q=state%3Aopen%20label%3A10.rebuild-nixos-tests) label. Changes causing a rebuild of all NixOS tests get a special [`10.rebuild-nixos-tests`](https://github.com/NixOS/nixpkgs/issues?q=state%3Aopen%20label%3A10.rebuild-nixos-tests) label.
These changes pose a significant impact on the build infrastructure. These changes pose a significant impact on the build infrastructure.
Hence, these PRs should either target a `staging`-branch or `staging-nixos`-branch, provided one of following conditions applies: Hence, these PRs should either target a `staging`-branch or `staging-nixos`, provided one of following conditions applies:
* The label `10.rebuild-nixos-tests` is set, or * The label `10.rebuild-nixos-tests` is set, or
* The PR is a change affecting the Linux kernel. * The PR is a change affecting the Linux kernel.
@@ -889,77 +888,3 @@ As mentioned previously, it is unfortunately perfectly normal for a PR to sit ar
Please don't blow up situations where progress is happening but is merely not going fast enough for your tastes. Please don't blow up situations where progress is happening but is merely not going fast enough for your tastes.
Honking in a traffic jam will not make you go any faster. Honking in a traffic jam will not make you go any faster.
# Automation/AI policy
Every contribution to Nixpkgs and related development venues, including code, documentation, and communication on GitHub and Matrix, must have a **responsible person in the loop** who is accountable for that contribution and reviews it before submission, and must **transparently disclose** any nontrivial use of automation to produce it, including but not limited to LLMbased AI tools.
The following sections give more detail.
## Scope
Any use of automated tools to generate nontrivial amounts of output as part of a contribution, in whole or in part, verbatim or edited, is covered by this policy, except as listed in the Exemptions section.
Both LLMbased AI tools and handwritten automation are covered.
Contributions include code and documentation in commits, commit messages, pull request summaries and reviews, issue and vulnerability reports, GitHub comments, Matrix messages, and Discourse posts.
The covered venues are the GitHub repositories for Nixpkgs and [related projects](https://github.com/orgs/NixOS/teams/nixpkgs-core/repositories) under the jurisdiction of the Nixpkgs core team, Matrix rooms that are focused on development of those projects, and Discourse topics about Nixpkgs development.
## Accountability
Everyone who submits a contribution to Nixpkgs is responsible for it, regardless of the use of automated tooling.
Before submission, they must establish a reasonable level of understanding of the contribution and expectation of its correctness.
A contributor submitting a contribution intended for inclusion in Nixpkgs is also responsible for ensuring that it is [appropriately licensed](https://github.com/NixOS/nixpkgs/blob/master/COPYING) and credited, and not encumbered by any incompatible copyright.
When output from automated tooling is used in contributions, a contributor must establish confidence in that output.
This can be achieved by establishing confidence in the correctness of the toolings logic, manual review of the included output, or using further automation to verify the output (e.g. programmatically checking whether a refactor avoids causing rebuilds).
As the inner workings of LLMbased AI tools cannot be sufficiently understood at present, only the latter two options are available when those are used; vibe coding without review is not permitted.
When automation is used to verify output, the verification tooling itself must be disclosed and reviewed in line with this policy.
This policy applies equally to any further discussion of a contribution.
Comments and reviews must separately satisfy the same requirements of understanding, review, and disclosure.
Contributors are expected to be able to answer questions about their contribution and respond to feedback appropriately, without simply forwarding messages back and forth to automated tools.
It is not permitted to submit automated contributions without any manual review or intervention, outside of standard community automation.
Automation without any manual review must not be used as the sole arbiter of whether to merge a change.
## Transparency
All covered use of automated tooling for a contribution must be disclosed as part of that contribution.
In the case of LLMbased AI tooling used for commits, this **must** be in the form of an `Assisted-by:` Git commit trailer, including at least the tool name and the primary model name and version used for the contribution.
A `Co-authored-by:` trailer does not satisfy this policy.
Any adequate form of disclosure is permitted for other kinds of tooling and contribution.
Pull request summaries and review comments must be disclosed separately to commits.
## Exemptions
The following situations are fully or partially exempt:
* Use of standard deterministic editor/IDE/formatter/text transformation tooling to produce changes that the author manually reviews and understands is exempt, including inline “autocompletion” (even if LLMbased) of short, rote snippets of text that do not contribute anything beyond boilerplate the author would have written anyway.
* Use of standard community automation is exempt, such as `nix-update`, the official Nixpkgs CI bots, the @r-ryantm update bot, other maintainerapproved bots that run update scripts, and the Nixpkgs security tracker bot.
* Use of AI tools for research, testing, debugging, or private review is out of scope, if no substantial amount of their output is included in the resulting contribution.
However, if these tools had a significant technical influence on your contribution, you are still responsible for it per the Accountability section, and are expected to disclose this where relevant.
* Use of machine translation is exempt from the requirement to understand the translated output.
However, the requirements of appropriate confidence in the original text, responsibility, and disclosure still apply, and you are encouraged to additionally include the original untranslated contribution.
* Use of automation in a contribution clearly marked as not being ready for merge (e.g. a draft pull request) is exempt from the requirement for full selfreview, as long as some amount of review has been done and it is expected that the requirements will be met by the time it is marked as ready.
This does not waive any other requirement.
* Use of automated tools to develop upstream software packaged inside Nixpkgs is not in scope.
## Enforcement
If you believe that someone is using automation without appropriate disclosure and review, you can politely ask them if thats the case and point them to this policy as appropriate.
Please assume good faith and remain civil; its not always possible to determine, and it is more likely that someone overlooked this policy than deliberately violated it.
If you think someone is continuing to break the policy after this, please escalate to the [Nixpkgs core team](https://nixos.org/community/teams/nixpkgs-core/) rather than fighting over it.
If a contribution is clearly in violation of the policy (e.g. the contributor admits it was not followed, or there are AI tool attributions that do not meet our required format), it can be closed or hidden, preferably after informing the contributor of the policy and giving them a chance to address the violations.
Deliberate violations of this policy are considered to break the [Code of Conduct](https://github.com/NixOS/.github/blob/master/CODE_OF_CONDUCT.md) clause against “Wasting other peoples time with low quality contributions, including but not limited to LLM and bot spam”.
Repeated violations are grounds for further moderation action.
## Credits
This policy takes inspiration from similar policies in [LLVM](https://llvm.org/docs/AIToolPolicy.html), [Mesa](https://gitlab.freedesktop.org/mesa/mesa/-/blob/mesa-26.1.0-rc1/docs/submittingpatches.rst?ref_type=tags), [Fedora](https://docs.fedoraproject.org/en-US/council/policy/ai-contribution-policy/), and the [Linux kernel](https://docs.kernel.org/7.0/process/coding-assistants.html), along with [a proposal by the author of Anubis](https://xeiaso.net/notes/2025/assisted-by-footer/).

View File

@@ -1,9 +1,9 @@
<p align="center"> <p align="center">
<a href="https://nixos.org"> <a href="https://nixos.org">
<picture> <picture>
<source media="(prefers-color-scheme: light)" srcset="https://brand.nixos.org/logos/nixos-logo-rainbow-gradient-black-regular-horizontal-minimal.svg"> <source media="(prefers-color-scheme: light)" srcset="https://brand.nixos.org/logos/nixos-logo-default-gradient-black-regular-horizontal-minimal.svg">
<source media="(prefers-color-scheme: dark)" srcset="https://brand.nixos.org/logos/nixos-logo-rainbow-gradient-white-regular-horizontal-minimal.svg"> <source media="(prefers-color-scheme: dark)" srcset="https://brand.nixos.org/logos/nixos-logo-default-gradient-white-regular-horizontal-minimal.svg">
<img src="https://brand.nixos.org/logos/nixos-logo-rainbow-gradient-black-regular-horizontal-minimal.svg" width="500px" alt="NixOS logo"> <img src="https://brand.nixos.org/logos/nixos-logo-default-gradient-black-regular-horizontal-minimal.svg" width="500px" alt="NixOS logo">
</picture> </picture>
</a> </a>
</p> </p>
@@ -13,7 +13,7 @@
<a href="https://opencollective.com/nixos"><img src="https://opencollective.com/nixos/tiers/supporter/badge.svg?label=supporters&color=brightgreen" alt="Open Collective supporters" /></a> <a href="https://opencollective.com/nixos"><img src="https://opencollective.com/nixos/tiers/supporter/badge.svg?label=supporters&color=brightgreen" alt="Open Collective supporters" /></a>
</p> </p>
[Nixpkgs](https://github.com/nixos/nixpkgs) is a collection of over 140,000 software packages that can be installed with the [Nix](https://nixos.org/nix/) package manager. [Nixpkgs](https://github.com/nixos/nixpkgs) is a collection of over 120,000 software packages that can be installed with the [Nix](https://nixos.org/nix/) package manager.
It also implements [NixOS](https://nixos.org/nixos/), a purely-functional Linux distribution. It also implements [NixOS](https://nixos.org/nixos/), a purely-functional Linux distribution.
# Manuals # Manuals
@@ -47,9 +47,9 @@ Here are some of the main ones:
Nixpkgs and NixOS are built and tested by our continuous integration system, [Hydra](https://hydra.nixos.org/). Nixpkgs and NixOS are built and tested by our continuous integration system, [Hydra](https://hydra.nixos.org/).
* [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined) * [Continuous package builds for unstable/master](https://hydra.nixos.org/jobset/nixos/trunk-combined)
* [Continuous package builds for the NixOS 26.05 release](https://hydra.nixos.org/jobset/nixos/release-26.05) * [Continuous package builds for the NixOS 25.11 release](https://hydra.nixos.org/jobset/nixos/release-25.11)
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents) * [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Tests for the NixOS 26.05 release](https://hydra.nixos.org/job/nixos/release-26.05/tested#tabs-constituents) * [Tests for the NixOS 25.11 release](https://hydra.nixos.org/job/nixos/release-25.11/tested#tabs-constituents)
Artifacts successfully built with Hydra are published to cache at https://cache.nixos.org/. Artifacts successfully built with Hydra are published to cache at https://cache.nixos.org/.
When successful build and test criteria are met, the Nixpkgs expressions are distributed via [Nix channels](https://nix.dev/manual/nix/stable/command-ref/nix-channel.html). When successful build and test criteria are met, the Nixpkgs expressions are distributed via [Nix channels](https://nix.dev/manual/nix/stable/command-ref/nix-channel.html).

183
ci/OWNERS
View File

@@ -21,31 +21,30 @@
/ci/OWNERS @infinisil @philiptaron /ci/OWNERS @infinisil @philiptaron
# Development support # Development support
/.editorconfig @Mic92 /.editorconfig @Mic92 @zowoq
/shell.nix @infinisil @NixOS/Security /shell.nix @infinisil @NixOS/Security
# Libraries # Libraries
/lib @infinisil @hsjobeki @llakala /lib @infinisil @hsjobeki
/lib/generators.nix @infinisil @hsjobeki @llakala /lib/generators.nix @infinisil @hsjobeki @Profpatsch
/lib/cli.nix @infinisil @hsjobeki @llakala /lib/cli.nix @infinisil @hsjobeki @Profpatsch
/lib/debug.nix @infinisil @hsjobeki @llakala /lib/debug.nix @infinisil @hsjobeki @Profpatsch
/lib/asserts.nix @infinisil @hsjobeki @llakala /lib/asserts.nix @infinisil @hsjobeki @Profpatsch
/lib/path/* @infinisil @hsjobeki @llakala /lib/path/* @infinisil @hsjobeki
/lib/fileset @infinisil @hsjobeki @llakala /lib/fileset @infinisil @hsjobeki
/maintainers/github-teams.json @infinisil @llakala /maintainers/github-teams.json @infinisil
/maintainers/computed-team-list.nix @infinisil @llakala /maintainers/computed-team-list.nix @infinisil
## Standard environmentrelated libraries ## Standard environmentrelated libraries
/lib/customisation.nix @alyssais @NixOS/stdenv @llakala /lib/customisation.nix @alyssais @NixOS/stdenv
/lib/derivations.nix @NixOS/stdenv @llakala /lib/derivations.nix @NixOS/stdenv
/lib/fetchers.nix @alyssais @NixOS/stdenv @llakala /lib/fetchers.nix @alyssais @NixOS/stdenv
/lib/meta.nix @alyssais @NixOS/stdenv @llakala /lib/meta.nix @alyssais @NixOS/stdenv
/lib/meta-types.nix @infinisil @adisbladis @NixOS/stdenv @llakala /lib/source-types.nix @alyssais @NixOS/stdenv
/lib/source-types.nix @alyssais @NixOS/stdenv @llakala /lib/systems @alyssais @NixOS/stdenv
/lib/systems @alyssais @NixOS/stdenv @llakala
## Libraries / Module system ## Libraries / Module system
/lib/modules.nix @infinisil @roberth @hsjobeki @llakala /lib/modules.nix @infinisil @roberth @hsjobeki
/lib/types.nix @infinisil @roberth @hsjobeki @llakala /lib/types.nix @infinisil @roberth @hsjobeki
/lib/options.nix @infinisil @roberth @hsjobeki @llakala /lib/options.nix @infinisil @roberth @hsjobeki
/lib/tests/modules.sh @infinisil @roberth @hsjobeki /lib/tests/modules.sh @infinisil @roberth @hsjobeki
/lib/tests/modules @infinisil @roberth @hsjobeki /lib/tests/modules @infinisil @roberth @hsjobeki
@@ -57,30 +56,28 @@
/pkgs/top-level/splice.nix @Ericson2314 /pkgs/top-level/splice.nix @Ericson2314
/pkgs/top-level/release-cross.nix @Ericson2314 /pkgs/top-level/release-cross.nix @Ericson2314
/pkgs/top-level/by-name-overlay.nix @infinisil @philiptaron /pkgs/top-level/by-name-overlay.nix @infinisil @philiptaron
/pkgs/top-level/config.nix @jopejoe1 /pkgs/stdenv @philiptaron @NixOS/stdenv
/pkgs/top-level/make-tarball.nix @jopejoe1 /pkgs/stdenv/generic @Ericson2314 @NixOS/stdenv
/pkgs/top-level/packages-config.nix @jopejoe1 /pkgs/stdenv/generic/check-meta.nix @Ericson2314 @adisbladis @NixOS/stdenv
/pkgs/top-level/packages-info.nix @jopejoe1 /pkgs/stdenv/generic/meta-types.nix @adisbladis @NixOS/stdenv
/pkgs/top-level/release-lib.nix @jopejoe1
/pkgs/top-level/release.nix @jopejoe1
/pkgs/stdenv @philiptaron @NixOS/stdenv @llakala
/pkgs/stdenv/generic @Ericson2314 @NixOS/stdenv @llakala
/pkgs/stdenv/generic/problems.nix @infinisil @llakala
/pkgs/test/problems @infinisil
/pkgs/stdenv/generic/check-meta.nix @infinisil @Ericson2314 @adisbladis @NixOS/stdenv @llakala
/pkgs/stdenv/cross @Ericson2314 @NixOS/stdenv /pkgs/stdenv/cross @Ericson2314 @NixOS/stdenv
/pkgs/build-support @philiptaron /pkgs/build-support @philiptaron
/pkgs/build-support/cc-wrapper @Ericson2314 /pkgs/build-support/cc-wrapper @Ericson2314
/pkgs/build-support/bintools-wrapper @Ericson2314 /pkgs/build-support/bintools-wrapper @Ericson2314
/pkgs/build-support/setup-hooks @Ericson2314 /pkgs/build-support/setup-hooks @Ericson2314
/pkgs/build-support/setup-hooks/arrayUtilities @ConnorBaker /pkgs/build-support/setup-hooks/arrayUtilities @ConnorBaker
/pkgs/build-support/setup-hooks/auto-patchelf.sh @layus
/pkgs/by-name/au/auto-patchelf @layus
## Format generators/serializers ## Format generators/serializers
/pkgs/pkgs-lib @Stunkymonkey @h7x4 /pkgs/pkgs-lib @Stunkymonkey @h7x4
/pkgs/pkgs-lib/formats/json2x @Stunkymonkey @h7x4 @figsoda
# Nixpkgs build-support # Nixpkgs build-support
/pkgs/build-support/writers @lassulus /pkgs/build-support/writers @lassulus @Profpatsch
# Nixpkgs make-disk-image
/doc/build-helpers/images/makediskimage.section.md @raitobezarius
/nixos/lib/make-disk-image.nix @raitobezarius
# Nix, the package manager # Nix, the package manager
# @raitobezarius is not "code owner", but is listed here to be notified of changes # @raitobezarius is not "code owner", but is listed here to be notified of changes
@@ -95,16 +92,16 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/maintainers/scripts/doc @jtojnar @ryantm /maintainers/scripts/doc @jtojnar @ryantm
# Contributor documentation # Contributor documentation
/CONTRIBUTING.md /CONTRIBUTING.md @infinisil
/.github/PULL_REQUEST_TEMPLATE.md /.github/PULL_REQUEST_TEMPLATE.md @infinisil
/doc/contributing/ /doc/contributing/ @infinisil
/doc/contributing/contributing-to-documentation.chapter.md @jtojnar /doc/contributing/contributing-to-documentation.chapter.md @jtojnar @infinisil
/lib/README.md /lib/README.md @infinisil
/doc/README.md /doc/README.md @infinisil
/nixos/README.md /nixos/README.md @infinisil
/pkgs/README.md /pkgs/README.md @infinisil
/pkgs/by-name/README.md /pkgs/by-name/README.md @infinisil
/maintainers/README.md /maintainers/README.md @infinisil
# User-facing development documentation # User-facing development documentation
/doc/development.md @infinisil /doc/development.md @infinisil
@@ -123,6 +120,9 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/doc/redirects.json @GetPsyched /doc/redirects.json @GetPsyched
/nixos/doc/manual/redirects.json @GetPsyched /nixos/doc/manual/redirects.json @GetPsyched
# NixOS integration test driver
/nixos/lib/test-driver @tfc
# NixOS QEMU virtualisation # NixOS QEMU virtualisation
/nixos/modules/virtualisation/qemu-vm.nix @raitobezarius /nixos/modules/virtualisation/qemu-vm.nix @raitobezarius
/nixos/modules/services/backup/libvirtd-autosnapshot.nix @6543 /nixos/modules/services/backup/libvirtd-autosnapshot.nix @6543
@@ -182,10 +182,12 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/pkgs/by-name/an/android* @NixOS/android /pkgs/by-name/an/android* @NixOS/android
# Python-related code and docs # Python-related code and docs
/doc/languages-frameworks/python.section.md @mweinelt /doc/languages-frameworks/python.section.md @mweinelt @natsukium
/maintainers/scripts/update-python-libraries @mweinelt /maintainers/scripts/update-python-libraries @mweinelt @natsukium
/pkgs/by-name/up/update-python-libraries @mweinelt /pkgs/by-name/up/update-python-libraries @mweinelt @natsukium
/pkgs/development/interpreters/python @mweinelt /pkgs/development/interpreters/python @mweinelt @natsukium
/pkgs/top-level/python-packages.nix @natsukium
/pkgs/top-level/release-python.nix @natsukium
# CUDA # CUDA
/pkgs/top-level/cuda-packages.nix @NixOS/cuda-maintainers /pkgs/top-level/cuda-packages.nix @NixOS/cuda-maintainers
@@ -215,10 +217,10 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/pkgs/development/r-modules @jbedo /pkgs/development/r-modules @jbedo
# Rust # Rust
/pkgs/development/compilers/rust @NixOS/rust @alyssais /pkgs/development/compilers/rust @alyssais @Mic92 @zowoq @winterqt
/pkgs/build-support/rust @NixOS/rust /pkgs/build-support/rust @zowoq @winterqt
/pkgs/build-support/rust/fetch-cargo-vendor* @TomaSajt /pkgs/build-support/rust/fetch-cargo-vendor* @TomaSajt
/doc/languages-frameworks/rust.section.md @NixOS/rust /doc/languages-frameworks/rust.section.md @zowoq @winterqt
# Tcl # Tcl
/pkgs/development/interpreters/tcl @fgaz /pkgs/development/interpreters/tcl @fgaz
@@ -230,10 +232,14 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
# C compilers # C compilers
/pkgs/development/compilers/gcc /pkgs/development/compilers/gcc
/pkgs/development/compilers/llvm @NixOS/llvm /pkgs/development/compilers/llvm @NixOS/llvm
/pkgs/development/compilers/emscripten @raitobezarius
/doc/toolchains/llvm.chapter.md @NixOS/llvm /doc/toolchains/llvm.chapter.md @NixOS/llvm
/doc/languages-frameworks/emscripten.section.md @raitobezarius
# Audio # Audio
/nixos/modules/services/audio/botamusique.nix @mweinelt
/nixos/modules/services/audio/snapserver.nix @mweinelt /nixos/modules/services/audio/snapserver.nix @mweinelt
/nixos/tests/botamusique.nix @mweinelt
/nixos/tests/snapcast.nix @mweinelt /nixos/tests/snapcast.nix @mweinelt
# Browsers # Browsers
@@ -260,18 +266,18 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/applications/editors/jetbrains @leona-ya @theCapypara /pkgs/applications/editors/jetbrains @leona-ya @theCapypara
# Licenses # Licenses
/lib/licenses @alyssais @emilazy @jopejoe1 @llakala /lib/licenses.nix @alyssais @emilazy @jopejoe1
# Qt # Qt
/pkgs/development/libraries/qt-5 @K900 @NickCao @SuperSandro2000 /pkgs/development/libraries/qt-5 @K900 @NickCao @SuperSandro2000 @ttuegel
/pkgs/development/libraries/qt-6 @K900 @NickCao @SuperSandro2000 /pkgs/development/libraries/qt-6 @K900 @NickCao @SuperSandro2000 @ttuegel
# KDE Frameworks 5 # KDE Frameworks 5
/pkgs/development/libraries/kde-frameworks @K900 @NickCao @SuperSandro2000 /pkgs/development/libraries/kde-frameworks @K900 @NickCao @SuperSandro2000 @ttuegel
# KDE / Plasma 6 # KDE / Plasma 6
/pkgs/kde @K900 @NickCao @SuperSandro2000 /pkgs/kde @K900 @NickCao @SuperSandro2000 @ttuegel
/maintainers/scripts/kde @K900 @NickCao @SuperSandro2000 /maintainers/scripts/kde @K900 @NickCao @SuperSandro2000 @ttuegel
# PostgreSQL and related stuff # PostgreSQL and related stuff
/pkgs/by-name/po/postgresqlTestHook @NixOS/postgres /pkgs/by-name/po/postgresqlTestHook @NixOS/postgres
@@ -286,6 +292,13 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/nixos/modules/services/databases/mysql.nix @6543 /nixos/modules/services/databases/mysql.nix @6543
/nixos/modules/services/backup/mysql-backup.nix @6543 /nixos/modules/services/backup/mysql-backup.nix @6543
# Hardened profile & related modules
/nixos/modules/profiles/hardened.nix @joachifm
/nixos/modules/security/lock-kernel-modules.nix @joachifm
/nixos/modules/security/misc.nix @joachifm
/nixos/tests/hardened.nix @joachifm
/pkgs/os-specific/linux/kernel/hardened/ @fabianhjr @joachifm
# Home Automation # Home Automation
/nixos/modules/services/home-automation/home-assistant.nix @mweinelt /nixos/modules/services/home-automation/home-assistant.nix @mweinelt
/nixos/modules/services/home-automation/zigbee2mqtt.nix @mweinelt /nixos/modules/services/home-automation/zigbee2mqtt.nix @mweinelt
@@ -295,14 +308,8 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/by-name/es/esphome @mweinelt /pkgs/by-name/es/esphome @mweinelt
# Linux kernel # Linux kernel
/doc/packages/linux.section.md @NixOS/linux-kernel
/lib/kernel.nix @NixOS/linux-kernel
/nixos/doc/manual/configuration/linux-kernel.chapter.md @NixOS/linux-kernel
/nixos/modules/system/boot/kernel.nix @NixOS/linux-kernel
/nixos/tests/kernel-generic/ @NixOS/linux-kernel
/pkgs/build-support/kernel/ @NixOS/linux-kernel
/pkgs/os-specific/linux/kernel/ @NixOS/linux-kernel
/pkgs/top-level/linux-kernels.nix @NixOS/linux-kernel /pkgs/top-level/linux-kernels.nix @NixOS/linux-kernel
/pkgs/os-specific/linux/kernel/ @NixOS/linux-kernel
# Network Time Daemons # Network Time Daemons
/pkgs/by-name/ch/chrony @thoughtpolice /pkgs/by-name/ch/chrony @thoughtpolice
@@ -322,16 +329,16 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/nixos/tests/knot.nix @mweinelt /nixos/tests/knot.nix @mweinelt
# Web servers # Web servers
/doc/packages/nginx.section.md @leona-ya @Ma27 /doc/packages/nginx.section.md @raitobezarius
/pkgs/servers/http/nginx/ @helsinki-Jo @leona-ya @Ma27 /pkgs/servers/http/nginx/ @raitobezarius
/nixos/modules/services/web-servers/nginx/ @leona-ya @Ma27 /nixos/modules/services/web-servers/nginx/ @raitobezarius
# D # D
/pkgs/build-support/dlang @jtbx @TomaSajt /pkgs/build-support/dlang @jtbx @TomaSajt
# Dhall # Dhall
/pkgs/development/dhall-modules @Gabriella439 /pkgs/development/dhall-modules @Gabriella439 @Profpatsch
/pkgs/development/interpreters/dhall @Gabriella439 /pkgs/development/interpreters/dhall @Gabriella439 @Profpatsch
# Agda # Agda
/pkgs/build-support/agda @NixOS/agda /pkgs/build-support/agda @NixOS/agda
@@ -344,6 +351,9 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/development/idris-modules @Infinisil /pkgs/development/idris-modules @Infinisil
/pkgs/development/compilers/idris2 @mattpolzin /pkgs/development/compilers/idris2 @mattpolzin
# Bazel
/pkgs/by-name/ba/bazel_7 @Profpatsch
# NixOS modules for e-mail and dns services # NixOS modules for e-mail and dns services
/nixos/modules/services/mail/mailman.nix @peti /nixos/modules/services/mail/mailman.nix @peti
/nixos/modules/services/mail/postfix.nix @peti /nixos/modules/services/mail/postfix.nix @peti
@@ -364,14 +374,10 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/development/lua-modules @NixOS/lua /pkgs/development/lua-modules @NixOS/lua
# Neovim # Neovim
/pkgs/applications/editors/neovim @NixOS/neovim /pkgs/applications/editors/neovim @NixOS/neovim
/doc/languages-frameworks/neovim.section.md @NixOS/neovim
# VimPlugins # VimPlugins
/pkgs/applications/editors/vim/plugins @NixOS/neovim /pkgs/applications/editors/vim/plugins @NixOS/neovim
## nvim-treesitter
/pkgs/applications/editors/vim/plugins/nvim-treesitter/overrides.nix @NixOS/neovim @figsoda
/pkgs/applications/editors/vim/plugins/utils/nvim-treesitter @NixOS/neovim @figsoda
# VsCode Extensions # VsCode Extensions
/pkgs/applications/editors/vscode/extensions /pkgs/applications/editors/vscode/extensions
@@ -389,15 +395,18 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/nixos/tests/docker-tools* @roberth @jhol /nixos/tests/docker-tools* @roberth @jhol
/doc/build-helpers/images/dockertools.section.md @roberth @jhol /doc/build-helpers/images/dockertools.section.md @roberth @jhol
# Blockchains
/pkgs/applications/blockchains @mmahut @RaghavSood
# Go # Go
/doc/languages-frameworks/go.section.md @kalbasit @katexochen @Mic92 /doc/languages-frameworks/go.section.md @kalbasit @katexochen @Mic92
/pkgs/build-support/go @kalbasit @katexochen @Mic92 /pkgs/build-support/go @kalbasit @katexochen @Mic92
/pkgs/development/compilers/go @kalbasit @katexochen @Mic92 /pkgs/development/compilers/go @kalbasit @katexochen @Mic92
# GNOME # GNOME
/pkgs/desktops/gnome @NixOS/gnome /pkgs/desktops/gnome @jtojnar
/pkgs/desktops/gnome/extensions @NixOS/gnome /pkgs/desktops/gnome/extensions @jtojnar
/pkgs/build-support/make-hardcode-gsettings-patch @NixOS/gnome /pkgs/build-support/make-hardcode-gsettings-patch @jtojnar
# Cinnamon # Cinnamon
/pkgs/by-name/ci/cinnamon-* @mkg20001 /pkgs/by-name/ci/cinnamon-* @mkg20001
@@ -429,7 +438,6 @@ nixos/tests/forgejo.nix @adamcstephens @bendlas @christoph-heiss @
/doc/languages-frameworks/javascript.section.md @winterqt /doc/languages-frameworks/javascript.section.md @winterqt
/pkgs/development/tools/pnpm @Scrumplex @gepbird /pkgs/development/tools/pnpm @Scrumplex @gepbird
/pkgs/build-support/node/fetch-pnpm-deps @Scrumplex @gepbird /pkgs/build-support/node/fetch-pnpm-deps @Scrumplex @gepbird
/pkgs/test/pnpm @Scrumplex @gepbird
# OCaml # OCaml
/pkgs/build-support/ocaml @ulrikstrid /pkgs/build-support/ocaml @ulrikstrid
@@ -471,7 +479,7 @@ pkgs/by-name/lx/lxc* @adamcstephens
/pkgs/desktops/expidus @RossComputerGuy /pkgs/desktops/expidus @RossComputerGuy
# GNU Tar & Zip # GNU Tar & Zip
/pkgs/by-name/gn/gnutar @RossComputerGuy /pkgs/tools/archivers/gnutar @RossComputerGuy
/pkgs/by-name/zi/zip @RossComputerGuy /pkgs/by-name/zi/zip @RossComputerGuy
# SELinux # SELinux
@@ -486,7 +494,7 @@ pkgs/by-name/lx/lxc* @adamcstephens
# Darwin # Darwin
/pkgs/by-name/ap/apple-sdk @NixOS/darwin-core /pkgs/by-name/ap/apple-sdk @NixOS/darwin-core
/pkgs/os-specific/darwin @NixOS/darwin-core /pkgs/os-specific/darwin/apple-source-releases @NixOS/darwin-core
/pkgs/stdenv/darwin @NixOS/darwin-core /pkgs/stdenv/darwin @NixOS/darwin-core
# BEAM # BEAM
@@ -496,7 +504,7 @@ pkgs/development/interpreters/elixir/ @NixOS/beam
pkgs/development/interpreters/lfe/ @NixOS/beam pkgs/development/interpreters/lfe/ @NixOS/beam
# Authelia # Authelia
pkgs/by-name/au/authelia/ @06kellyjac @nicomem pkgs/by-name/au/authelia/ @06kellyjac @dit7ya @nicomem
# OctoDNS # OctoDNS
pkgs/by-name/oc/octodns/ @anthonyroussel pkgs/by-name/oc/octodns/ @anthonyroussel
@@ -506,23 +514,10 @@ pkgs/by-name/oc/octodns/ @anthonyroussel
pkgs/by-name/te/teleport* @arianvp @justinas @sigma @tomberek @techknowlogick @JuliusFreudenberger pkgs/by-name/te/teleport* @arianvp @justinas @sigma @tomberek @techknowlogick @JuliusFreudenberger
# Warp-terminal # Warp-terminal
pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @4evy @johnrtitor pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @FlameFlag @johnrtitor
# Nim # Nim
/doc/languages-frameworks/nim.section.md @NixOS/nim /doc/languages-frameworks/nim.section.md @NixOS/nim
/pkgs/build-support/build-nim-package.nix @NixOS/nim /pkgs/build-support/build-nim-package.nix @NixOS/nim
/pkgs/build-support/build-nim-sbom.nix @NixOS/nim /pkgs/build-support/build-nim-sbom.nix @NixOS/nim
/pkgs/top-level/nim-overrides.nix @NixOS/nim /pkgs/top-level/nim-overrides.nix @NixOS/nim
# Radicle
/pkgs/build-support/fetchradicle/ @NixOS/radicle
/pkgs/build-support/fetchradiclepatch/ @NixOS/radicle
# Zellij plugins
/pkgs/by-name/ze/zellij/plugins/ @PerchunPak
# Test-driver
/nixos/lib/test-driver @NixOS/test-driver
/nixos/lib/testing @NixOS/test-driver
/nixos/tests/nixos-test-driver @NixOS/test-driver
/nixos/modules/virtualisation/nspawn-container/run-nspawn @NixOS/test-driver

View File

@@ -51,16 +51,6 @@ To ensure security and a focused utility, the bot adheres to specific limitation
- opened by [@r-ryantm](https://nix-community.github.io/nixpkgs-update/r-ryantm/). - opened by [@r-ryantm](https://nix-community.github.io/nixpkgs-update/r-ryantm/).
- The user attempting to merge is a member of [@NixOS/nixpkgs-maintainers]. - The user attempting to merge is a member of [@NixOS/nixpkgs-maintainers].
- The user attempting to merge is a maintainer of all packages touched by the PR. - The user attempting to merge is a maintainer of all packages touched by the PR.
- No [committer][@NixOS/nixpkgs-committers] has an outstanding "changes requested" review.
These block both the merge queue and auto-merge, so the bot refuses to merge until the review is addressed or dismissed.
Once these constraints are met, the bot picks a merge strategy based on the `no PR failures` commit status:
- CI passing: the PR is added to the merge queue.
- CI unfinished (pending or missing status): the bot enables [Auto Merge], which queues the PR once required checks succeed.
Note that if CI later fails, nothing happens until it is fixed and passes.
- CI already failing (`error`/`failure` status): the bot does not enable Auto Merge, because it would never trigger, and fixing CI requires a new push that invalidates the merge command.
A fresh `@NixOS/nixpkgs-merge-bot merge` comment is needed once CI is green again.
### Approving merge bot changes ### Approving merge bot changes
@@ -114,4 +104,3 @@ This script can also be run locally to print basic test cases.
[@NixOS/nixpkgs-ci]: https://github.com/orgs/NixOS/teams/nixpkgs-ci [@NixOS/nixpkgs-ci]: https://github.com/orgs/NixOS/teams/nixpkgs-ci
[@NixOS/nixpkgs-core]: https://github.com/orgs/NixOS/teams/nixpkgs-core [@NixOS/nixpkgs-core]: https://github.com/orgs/NixOS/teams/nixpkgs-core
[RFC 172]: https://github.com/NixOS/rfcs/pull/172 [RFC 172]: https://github.com/NixOS/rfcs/pull/172
[Auto Merge]: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request

View File

@@ -26,7 +26,132 @@ let
fmt = fmt =
let let
treefmt = pkgs.treefmt.withConfig ./treefmt.nix; treefmtNixSrc = fetchTarball {
inherit (pinned.treefmt-nix) url;
sha256 = pinned.treefmt-nix.hash;
};
treefmtEval = (import treefmtNixSrc).evalModule pkgs {
# Important: The auto-rebase script uses `git filter-branch --tree-filter`,
# which creates trees within the Git repository under `.git-rewrite/t`,
# notably without having a `.git` themselves.
# So if this projectRootFile were the default `.git/config`,
# having the auto-rebase script use treefmt on such a tree would make it
# format all files in the _parent_ Git tree as well.
projectRootFile = ".git-blame-ignore-revs";
# Be a bit more verbose by default, so we can see progress happening
settings.verbose = 1;
# By default it's info, which is too noisy since we have many unmatched files
settings.on-unmatched = "debug";
programs.actionlint.enable = true;
programs.biome = {
enable = true;
# Disable settings validation because its inputs are liable to hash mismatch
validate.enable = false;
settings.formatter = {
useEditorconfig = true;
};
settings.javascript.formatter = {
quoteStyle = "single";
semicolons = "asNeeded";
};
settings.json.formatter.enabled = false;
};
settings.formatter.biome.excludes = [
"*.min.js"
"pkgs/*"
];
programs.keep-sorted.enable = true;
# This uses nixfmt underneath, the default formatter for Nix code.
# See https://github.com/NixOS/nixfmt
programs.nixfmt = {
enable = true;
package = pkgs.nixfmt;
};
programs.yamlfmt = {
enable = true;
settings.formatter = {
retain_line_breaks = true;
};
};
settings.formatter.yamlfmt.excludes = [
# Aligns comments with whitespace
"pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml"
# TODO: Fix formatting for auto-generated file
"pkgs/development/haskell-modules/configuration-hackage2nix/transitive-broken.yaml"
];
programs.nixf-diagnose = {
enable = true;
ignore = [
# Rule names can currently be looked up here:
# https://github.com/nix-community/nixd/blob/main/libnixf/src/Basic/diagnostic.py
# TODO: Remove the following and fix things.
"sema-unused-def-lambda-noarg-formal"
"sema-unused-def-lambda-witharg-arg"
"sema-unused-def-lambda-witharg-formal"
"sema-unused-def-let"
# Keep this rule, because we have `lib.or`.
"or-identifier"
# TODO: remove after outstanding prelude diagnostics issues are fixed:
# https://github.com/nix-community/nixd/issues/761
# https://github.com/nix-community/nixd/issues/762
"sema-primop-removed-prefix"
"sema-primop-overridden"
"sema-constant-overridden"
"sema-primop-unknown"
];
};
settings.formatter.nixf-diagnose = {
# Ensure nixfmt cleans up after nixf-diagnose.
priority = -1;
excludes = [
# Auto-generated; violates sema-extra-with
# Can only sensibly be removed when --auto-fix supports multiple fixes at once:
# https://github.com/inclyc/nixf-diagnose/issues/13
"pkgs/servers/home-assistant/component-packages.nix"
# https://github.com/nix-community/nixd/issues/708
"nixos/maintainers/scripts/azure-new/examples/basic/system.nix"
];
};
settings.formatter.editorconfig-checker = {
command = "${pkgs.lib.getExe pkgs.editorconfig-checker}";
options = [
"-disable-indent-size"
# TODO: Remove this once this upstream issue is fixed:
# https://github.com/editorconfig-checker/editorconfig-checker/issues/505
"-disable-charset"
];
includes = [ "*" ];
priority = 1;
};
# TODO: Upstream this into treefmt-nix eventually:
# https://github.com/numtide/treefmt-nix/issues/387
settings.formatter.markdown-code-runner = {
command = pkgs.lib.getExe pkgs.markdown-code-runner;
options =
let
config = pkgs.writers.writeTOML "markdown-code-runner-config" {
presets.nixfmt = {
language = "nix";
command = [ (pkgs.lib.getExe pkgs.nixfmt) ];
};
};
in
[ "--config=${config}" ];
includes = [ "*.md" ];
};
programs.zizmor.enable = true;
};
fs = pkgs.lib.fileset; fs = pkgs.lib.fileset;
nixFilesSrc = fs.toSource { nixFilesSrc = fs.toSource {
root = ../.; root = ../.;
@@ -34,24 +159,14 @@ let
}; };
in in
{ {
pkg = treefmt; shell = treefmtEval.config.build.devShell;
check = treefmt.check nixFilesSrc; pkg = treefmtEval.config.build.wrapper;
check = treefmtEval.config.build.check nixFilesSrc;
}; };
# nixos-render-docs and nixos-render-docs-redirects
# Should be used from tree to build the matching in-tree documentation
docPkgs = pkgs.extend (
final: prev: {
nixos-render-docs = final.callPackage ../pkgs/by-name/ni/nixos-render-docs/package.nix { };
nixos-render-docs-redirects =
final.callPackage ../pkgs/by-name/ni/nixos-render-docs-redirects/package.nix
{ };
}
);
in in
rec { rec {
inherit pkgs docPkgs fmt; inherit pkgs fmt;
codeownersValidator = pkgs.callPackage ./codeowners-validator { }; codeownersValidator = pkgs.callPackage ./codeowners-validator { };
# FIXME(lf-): it might be useful to test other Nix implementations # FIXME(lf-): it might be useful to test other Nix implementations
@@ -64,15 +179,14 @@ rec {
# CI jobs # CI jobs
lib-tests = import ../lib/tests/release.nix { inherit pkgs; }; lib-tests = import ../lib/tests/release.nix { inherit pkgs; };
manual-nixos = (import ../nixos/release.nix { }).manual.${system} or null; manual-nixos = (import ../nixos/release.nix { }).manual.${system} or null;
manual-nixpkgs = (import ../doc { pkgs = docPkgs; }); manual-nixpkgs = (import ../doc { inherit pkgs; });
nixpkgs-vet = pkgs.callPackage ./nixpkgs-vet.nix { nixpkgs-vet = pkgs.callPackage ./nixpkgs-vet.nix {
nix = pkgs.nixVersions.latest; nix = pkgs.nixVersions.latest;
}; };
parse = pkgs.lib.recurseIntoAttrs { parse = pkgs.lib.recurseIntoAttrs {
nix_latest = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.latest; }; latest = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.latest; };
stable = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.stable; };
lix = pkgs.callPackage ./parse.nix { nix = pkgs.lix; }; lix = pkgs.callPackage ./parse.nix { nix = pkgs.lix; };
lix_latest = pkgs.callPackage ./parse.nix { nix = pkgs.lixPackageSets.latest.lix; }; nix_2_28 = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.nix_2_28; };
}; };
shell = import ../shell.nix { inherit nixpkgs system; }; shell = import ../shell.nix { inherit nixpkgs system; };
tarball = import ../pkgs/top-level/make-tarball.nix { tarball = import ../pkgs/top-level/make-tarball.nix {

View File

@@ -10,14 +10,14 @@ nix-build ci -A eval.baseline
The two most important arguments are: The two most important arguments are:
- `--arg evalSystems`: The set of systems for which `nixpkgs` should be evaluated. - `--arg evalSystems`: The set of systems for which `nixpkgs` should be evaluated.
Defaults to the [supported systems](../../pkgs/top-level/release-supported-systems.json) for the branch. Defaults to the four official platforms (`x86_64-linux`, `aarch64-linux`, `x86_64-darwin` and `aarch64-darwin`).
Example: `--arg evalSystems '["x86_64-linux" "aarch64-darwin"]'` Example: `--arg evalSystems '["x86_64-linux" "aarch64-darwin"]'`
- `--arg quickTest`: Enables testing a single chunk of the current system only for quick iteration. - `--arg quickTest`: Enables testing a single chunk of the current system only for quick iteration.
Example: `--arg quickTest true` Example: `--arg quickTest true`
The following arguments can be used to fine-tune performance: The following arguments can be used to fine-tune performance:
- `--max-jobs`: The maximum number of derivations to run at the same time. - `--max-jobs`: The maximum number of derivations to run at the same time.
Only each supported system gets a separate derivation, so it doesn't make sense to set this higher than that number. Only each [supported system](../supportedSystems.json) gets a separate derivation, so it doesn't make sense to set this higher than that number.
- `--cores`: The number of cores to use for each job. - `--cores`: The number of cores to use for each job.
Recommended to set this to the number of cores on your system divided by `--max-jobs`. Recommended to set this to the number of cores on your system divided by `--max-jobs`.
- `--arg chunkSize`: The number of attributes that are evaluated simultaneously on a single core. - `--arg chunkSize`: The number of attributes that are evaluated simultaneously on a single core.

85
ci/eval/attrpaths.nix Normal file
View File

@@ -0,0 +1,85 @@
# This expression will, as efficiently as possible, dump a
# *superset* of all attrpaths of derivations which might be
# part of a release on *any* platform.
#
# This expression runs single-threaded under all current Nix
# implementations, but much faster and with much less memory
# used than ./outpaths.nix itself.
#
# Once you have the list of attrnames you can split it up into
# $NUM_CORES batches and evaluate the outpaths separately for each
# batch, in parallel.
#
# To dump the attrnames:
#
# nix-instantiate --eval --strict --json ci/eval/attrpaths.nix -A names
#
{
lib ? import (path + "/lib"),
trace ? false,
path ? ./../..,
extraNixpkgsConfigJson ? "{}",
}:
let
# TODO: Use mapAttrsToListRecursiveCond when this PR lands:
# https://github.com/NixOS/nixpkgs/pull/395160
justAttrNames =
path: value:
let
result =
if path == [ "AAAAAASomeThingsFailToEvaluate" ] || !(lib.isAttrs value) then
[ ]
else if lib.isDerivation value then
[ path ]
else
lib.pipe value [
(lib.mapAttrsToList (
name: value:
lib.addErrorContext "while evaluating package set attribute path '${
lib.showAttrPath (path ++ [ name ])
}'" (justAttrNames (path ++ [ name ]) value)
))
lib.concatLists
];
in
lib.traceIf trace "** ${lib.showAttrPath path}" result;
outpaths = import ./outpaths.nix {
inherit path;
extraNixpkgsConfig = builtins.fromJSON extraNixpkgsConfigJson;
attrNamesOnly = true;
};
paths = [
# Some of the following are based on variants, which are disabled with `attrNamesOnly = true`.
# Until these have been removed from release.nix / hydra, we manually add them to the list.
[
"pkgsLLVM"
"stdenv"
]
[
"pkgsArocc"
"stdenv"
]
[
"pkgsZig"
"stdenv"
]
[
"pkgsStatic"
"stdenv"
]
[
"pkgsMusl"
"stdenv"
]
]
++ justAttrNames [ ] outpaths;
names = map lib.showAttrPath paths;
in
{
inherit paths names;
}

View File

@@ -2,8 +2,8 @@
{ {
lib ? import ../../lib, lib ? import ../../lib,
path ? ../.., path ? ../..,
# The file containing the preEval result # The file containing all available attribute paths, which are split into chunks here
preEvalFile, attrpathFile,
chunkSize, chunkSize,
myChunk, myChunk,
includeBroken, includeBroken,
@@ -12,13 +12,12 @@
}: }:
let let
preEvalResult = lib.importJSON preEvalFile; attrpaths = lib.importJSON attrpathFile;
myAttrpaths = lib.sublist (chunkSize * myChunk) chunkSize preEvalResult.paths; myAttrpaths = lib.sublist (chunkSize * myChunk) chunkSize attrpaths;
unfiltered = import ./outpaths.nix { unfiltered = import ./outpaths.nix {
inherit path; inherit path;
inherit includeBroken systems; inherit includeBroken systems;
inherit (preEvalResult) attrPathsDisallowedForInternalUse;
extraNixpkgsConfig = builtins.fromJSON extraNixpkgsConfigJson; extraNixpkgsConfig = builtins.fromJSON extraNixpkgsConfigJson;
}; };

View File

@@ -49,7 +49,6 @@ in
{ {
combinedDir, combinedDir,
touchedFilesJson, touchedFilesJson,
baseBranch,
ownersFile ? ../../OWNERS, ownersFile ? ../../OWNERS,
}: }:
let let
@@ -75,38 +74,9 @@ let
{ {
attrdiff: { attrdiff: {
added: ["package1"], added: ["package1"],
changed: ["package2", "package3", "package4"], changed: ["package2", "package3"],
removed: ["package4"], removed: ["package4"],
}, },
attrdiffByKernel: {
darwin: {
added: [],
changed: ["package2", "package4"],
removed: ["package4"],
},
linux: {
added: ["package1"],
changed: ["package3", "package4"],
removed: [],
},
},
attrdiffByPlatform: {
aarch64-darwin: {
added: [],
changed: ["package2"],
removed: ["package4"],
},
aarch64-linux: {
added: ["package1"],
changed: ["package3"],
removed: [],
},
x86_64-linux: {
added: [],
changed: ["package4"],
removed: [],
},
},
labels: { labels: {
"10.rebuild-darwin: 1-10": true, "10.rebuild-darwin: 1-10": true,
"10.rebuild-linux: 1-10": true "10.rebuild-linux: 1-10": true
@@ -143,8 +113,6 @@ let
inherit (import ./utils.nix { inherit lib; }) inherit (import ./utils.nix { inherit lib; })
groupByKernel groupByKernel
convertToPackagePlatformAttrs convertToPackagePlatformAttrs
groupAttrdiffByKernel
groupAttrdiffByPlatform
groupByPlatform groupByPlatform
extractPackageNames extractPackageNames
getLabels getLabels
@@ -155,29 +123,21 @@ let
# - values: lists of `packagePlatformPath`s # - values: lists of `packagePlatformPath`s
diffAttrs = builtins.fromJSON (builtins.readFile "${combined}/combined-diff.json"); diffAttrs = builtins.fromJSON (builtins.readFile "${combined}/combined-diff.json");
changedPackagePlatformAttrs = convertToPackagePlatformAttrs diffAttrs.changed;
rebuildsPackagePlatformAttrs = convertToPackagePlatformAttrs diffAttrs.rebuilds; rebuildsPackagePlatformAttrs = convertToPackagePlatformAttrs diffAttrs.rebuilds;
removedPackagePlatformAttrs = convertToPackagePlatformAttrs diffAttrs.removed;
changed-paths = changed-paths =
let let
attrdiff = lib.mapAttrs (_: extractPackageNames) {
inherit (diffAttrs) added changed removed;
};
attrdiffByPlatform = groupAttrdiffByPlatform {
inherit (diffAttrs) added changed removed;
};
attrdiffByKernel = groupAttrdiffByKernel {
inherit (diffAttrs) added changed removed;
};
rebuildsByPlatform = groupByPlatform rebuildsPackagePlatformAttrs; rebuildsByPlatform = groupByPlatform rebuildsPackagePlatformAttrs;
rebuildsByKernel = groupByKernel rebuildsPackagePlatformAttrs; rebuildsByKernel = groupByKernel rebuildsPackagePlatformAttrs;
rebuildCountByKernel = lib.mapAttrs ( rebuildCountByKernel = lib.mapAttrs (
kernel: kernelRebuilds: lib.length kernelRebuilds kernel: kernelRebuilds: lib.length kernelRebuilds
) rebuildsByKernel; ) rebuildsByKernel;
rebuildNames = extractPackageNames diffAttrs.rebuilds;
in in
writeText "changed-paths.json" ( writeText "changed-paths.json" (
builtins.toJSON { builtins.toJSON {
inherit attrdiff attrdiffByKernel attrdiffByPlatform; attrdiff = lib.mapAttrs (_: extractPackageNames) { inherit (diffAttrs) added changed removed; };
inherit inherit
rebuildsByPlatform rebuildsByPlatform
rebuildsByKernel rebuildsByKernel
@@ -191,19 +151,20 @@ let
) rebuildsByKernel ) rebuildsByKernel
// { // {
"10.rebuild-nixos-tests" = "10.rebuild-nixos-tests" =
lib.elem "nixosTests.simple-container" rebuildNames || lib.elem "nixosTests.simple-vm" rebuildNames; lib.elem "nixosTests.simple" (extractPackageNames diffAttrs.rebuilds)
&&
# Only set this label when no other label with indication for staging has been set.
# This avoids confusion whether to target staging or batch this with kernel updates.
lib.last (lib.sort lib.lessThan (lib.attrValues rebuildCountByKernel)) <= 500;
}; };
} }
); );
getMaintainers = callPackage ./maintainers.nix { };
inherit inherit
(getMaintainers { (callPackage ./maintainers.nix {
affectedAttrPaths = map (a: a.packagePath) ( changedattrs = lib.attrNames (lib.groupBy (a: a.name) changedPackagePlatformAttrs);
convertToPackagePlatformAttrs (diffAttrs.changed ++ diffAttrs.removed) changedpathsjson = touchedFilesJson;
); removedattrs = lib.attrNames (lib.groupBy (a: a.name) removedPackagePlatformAttrs);
changedFiles = lib.importJSON touchedFilesJson;
}) })
users users
teams teams
@@ -220,7 +181,7 @@ runCommand "compare"
]; ];
users = builtins.toJSON users; users = builtins.toJSON users;
teams = builtins.toJSON teams; teams = builtins.toJSON teams;
packages = builtins.toJSON (lib.map (lib.concatStringsSep ".") packages); packages = builtins.toJSON packages;
passAsFile = [ passAsFile = [
"users" "users"
"teams" "teams"
@@ -239,33 +200,34 @@ runCommand "compare"
jq -r -f ${./generate-step-summary.jq} < ${changed-paths} jq -r -f ${./generate-step-summary.jq} < ${changed-paths}
} >> $out/step-summary.md } >> $out/step-summary.md
{ if jq -e '(.attrdiff.added | length == 0) and (.attrdiff.removed | length == 0)' "${changed-paths}" > /dev/null; then
echo # Chunks have changed between revisions
echo "# Performance comparison" # We cannot generate a performance comparison
echo
echo "This compares the performance of this branch against the \`${baseBranch}\` branch."
echo
} >> $out/step-summary.md
# cmp-stats only compares the stats chunks present in both revisions, so the
# comparison is still produced when packages were added/removed. The paired
# chunks may cover different attrs in that case, so caveat the figures.
if ! jq -e '(.attrdiff.added | length == 0) and (.attrdiff.removed | length == 0)' "${changed-paths}" > /dev/null; then
{ {
echo "> [!NOTE]" echo
echo "> The package sets differ between the two revisions. This comparison only" echo "# Performance comparison"
echo "> covers packages evaluated in both, so treat the figures as approximate." echo
echo "This compares the performance of this branch against its pull request base branch (e.g., 'master')"
echo
echo "For further help please refer to: [ci/README.md](https://github.com/NixOS/nixpkgs/blob/master/ci/README.md)"
echo echo
} >> $out/step-summary.md } >> $out/step-summary.md
cmp-stats --explain ${combined}/before/stats ${combined}/after/stats >> $out/step-summary.md
else
# Package chunks are the same in both revisions
# We can use the to generate a performance comparison
{
echo
echo "# Performance Comparison"
echo
echo "Performance stats were skipped because the package sets differ between the two revisions."
echo
echo "For further help please refer to: [ci/README.md](https://github.com/NixOS/nixpkgs/blob/master/ci/README.md)"
} >> $out/step-summary.md
fi fi
{
echo "For further help please refer to: [ci/README.md](https://github.com/NixOS/nixpkgs/blob/master/ci/README.md)"
echo
} >> $out/step-summary.md
cmp-stats --explain ${combined}/before/stats ${combined}/after/stats >> $out/step-summary.md
jq -r '.[]' "${touchedFilesJson}" > ./touched-files jq -r '.[]' "${touchedFilesJson}" > ./touched-files
readarray -t touchedFiles < ./touched-files readarray -t touchedFiles < ./touched-files
echo "This PR touches ''${#touchedFiles[@]} files" echo "This PR touches ''${#touchedFiles[@]} files"

View File

@@ -1,59 +1,70 @@
# Figure out which maintainers (users/teams) are relevant for a PR:
# - All maintainers that can be linked directly to changedFiles
# - Maintainers of affectedAttrPaths if a file directly related to the attribute is in changedFiles
#
# Files and attributes are linked in various ways:
# - pkgs/by-name/<attr>/* is linked to pkgs.<attr>
# - The file position of various attributes of pkgs.<attr>
# - Explicitly specified file positions in derivations
#
# Test with
# nix-instantiate --eval --strict --json test.nix -A result | jq
#
# Empty list as an output means success
# Dependencies coming from the CI-pinned Nixpkgs
{ {
lib, lib,
changedattrs,
changedpathsjson,
removedattrs,
}: }:
# Function arguments let
{ pkgs = import ../../.. {
# Files that were changed
# Type: ListOf (Nixpkgs-root-relative path)
changedFiles,
# Attributes whose value was affected by the change
# Type: ListOf (ListOf String)
affectedAttrPaths,
# Nixpkgs used to check maintainers. Customisable for testing
pkgs ? import ../../.. {
system = "x86_64-linux"; system = "x86_64-linux";
# We should never try to ping maintainers through package aliases, this can only lead to errors. # We should never try to ping maintainers through package aliases, this can only lead to errors.
# One example case is, where an attribute is a throw alias, but then re-introduced in a PR. # One example case is, where an attribute is a throw alias, but then re-introduced in a PR.
# This would trigger the throw. By disabling aliases, we can fallback gracefully below. # This would trigger the throw. By disabling aliases, we can fallback gracefully below.
config.allowAliases = false; config.allowAliases = false;
overlays = [ ]; };
},
}:
let
nixpkgsRoot = toString ../../.. + "/";
stripNixpkgsRootFromKeys = lib.mapAttrs' (
file: value: lib.nameValuePair (lib.removePrefix nixpkgsRoot file) value
);
moduleMeta = (pkgs.nixos { }).config.meta; changedpaths = lib.importJSON changedpathsjson;
# Currently just nixos module maintainers, but in the future we can use this for code owners too # Extract attributes that changed from by-name paths.
fileUsers = stripNixpkgsRootFromKeys moduleMeta.maintainers; # This allows pinging reviewers for pure refactors.
fileTeams = stripNixpkgsRootFromKeys moduleMeta.teams; touchedattrs = lib.pipe changedpaths [
(lib.filter (changed: lib.hasPrefix "pkgs/by-name/" changed && changed != "pkgs/by-name/README.md"))
(map (lib.splitString "/"))
(map (path: lib.elemAt path 3))
lib.unique
];
anyMatchingFile = filename: lib.any (lib.hasPrefix filename) changedFiles; anyMatchingFile = filename: lib.any (lib.hasPrefix filename) changedpaths;
anyMatchingFiles = files: lib.any anyMatchingFile files; anyMatchingFiles = files: lib.any anyMatchingFile files;
sharded = name: "${lib.substring 0 2 name}/${name}";
attrsWithMaintainers = lib.pipe (changedattrs ++ removedattrs ++ touchedattrs) [
# An attribute can appear in changed/removed *and* touched
lib.unique
(map (
name:
let
path = lib.splitString "." name;
# Some packages might be reported as changed on a different platform, but
# not even have an attribute on the platform the maintainers are requested on.
# Fallback to `null` for these to filter them out below.
package = lib.attrByPath path null pkgs;
in
{
inherit name package;
# Adds all files in by-name to each package, no matter whether they are discoverable
# via meta attributes below. For example, this allows pinging maintainers for
# updates to .json files.
# TODO: Support by-name package sets.
filenames = lib.optional (lib.length path == 1) "pkgs/by-name/${sharded (lib.head path)}/";
# meta.maintainers also contains all individual team members.
# We only want to ping individuals if they're added individually as maintainers, not via teams.
users = package.meta.nonTeamMaintainers or [ ];
teams = package.meta.teams or [ ];
}
))
# No need to match up packages without maintainers with their files.
# This also filters out attributes where `packge = null`, which is the
# case for libintl, for example.
(lib.filter (pkg: pkg.users != [ ] || pkg.teams != [ ]))
];
relevantFilenames = relevantFilenames =
drv: drv:
(lib.unique ( (lib.unique (
map (pos: lib.removePrefix nixpkgsRoot pos.file) ( map (pos: lib.removePrefix "${toString ../../..}/" pos.file) (
lib.filter (x: x != null) [ lib.filter (x: x != null) [
(drv.meta.maintainersPosition or null) (drv.meta.maintainersPosition or null)
(drv.meta.teamsPosition or null) (drv.meta.teamsPosition or null)
@@ -76,84 +87,50 @@ let
) )
)); ));
relevantAffectedAttrPaths = lib.filter ( attrsWithFilenames = map (
attrPath: pkg: pkg // { filenames = pkg.filenames ++ relevantFilenames pkg.package; }
# Some packages might be reported as changed on a different platform, but ) attrsWithMaintainers;
# not even have an attribute on the platform the maintainers are requested on.
# Fallback to `null` for these to filter them out
let
package = lib.attrByPath attrPath null pkgs;
in
package != null && anyMatchingFiles (relevantFilenames package)
) affectedAttrPaths;
# Extract attributes that changed from by-name paths. attrsWithModifiedFiles = lib.filter (pkg: anyMatchingFiles pkg.filenames) attrsWithFilenames;
# This allows pinging reviewers for pure refactors.
changedByNameAttrPaths = lib.pipe changedFiles [
(lib.filter (changed: lib.hasPrefix "pkgs/by-name/" changed))
(map (lib.splitString "/"))
# Filters out e.g. pkgs/by-name/README.md
(lib.filter (path: lib.length path > 3))
(map (path: lib.elemAt path 3))
(map lib.singleton)
# Filter out new packages
(lib.filter (attrPath: lib.hasAttrByPath attrPath pkgs))
];
# An attribute can appear in affected *and* touched
attrPathsToGetMaintainersFor = lib.unique (relevantAffectedAttrPaths ++ changedByNameAttrPaths);
attrPathEntities = lib.concatMap (
attrPath:
let
package = lib.getAttrFromPath attrPath pkgs;
in
# meta.maintainers also contains all individual team members.
# We only want to ping individuals if they're added individually as maintainers, not via teams.
userPings { inherit attrPath; } (package.meta.nonTeamMaintainers or [ ])
++ lib.concatMap (teamPings { inherit attrPath; }) (package.meta.teams or [ ])
) attrPathsToGetMaintainersFor;
changedFileEntities = lib.concatMap (
file:
userPings { inherit file; } (fileUsers.${file} or [ ])
++ lib.concatMap (teamPings { inherit file; }) (fileTeams.${file} or [ ])
) changedFiles;
userPings = userPings =
context: pkg:
map (maintainer: { map (maintainer: {
type = "user"; type = "user";
userId = maintainer.githubId; userId = maintainer.githubId;
inherit context; packageName = pkg.name;
}); });
teamPings = teamPings =
context: team: pkg: team:
if team ? githubId then if team ? github then
[ [
{ {
type = "team"; type = "team";
teamId = team.githubId; teamId = team.githubId;
inherit context; packageName = pkg.name;
} }
] ]
else else
userPings context team.members; userPings pkg team.members;
byType = lib.groupBy (ping: ping.type) (attrPathEntities ++ changedFileEntities); maintainersToPing = lib.concatMap (
pkg: userPings pkg pkg.users ++ lib.concatMap (teamPings pkg) pkg.teams
) attrsWithModifiedFiles;
byType = lib.groupBy (ping: ping.type) maintainersToPing;
byUser = lib.pipe (byType.user or [ ]) [ byUser = lib.pipe (byType.user or [ ]) [
(lib.groupBy (ping: toString ping.userId)) (lib.groupBy (ping: toString ping.userId))
(lib.mapAttrs (_user: lib.map (pkg: pkg.context))) (lib.mapAttrs (_user: lib.map (pkg: pkg.packageName)))
]; ];
byTeam = lib.pipe (byType.team or [ ]) [ byTeam = lib.pipe (byType.team or [ ]) [
(lib.groupBy (ping: toString ping.teamId)) (lib.groupBy (ping: toString ping.teamId))
(lib.mapAttrs (_team: lib.map (pkg: pkg.context))) (lib.mapAttrs (_team: lib.map (pkg: pkg.packageName)))
]; ];
in in
{ {
users = byUser; users = byUser;
teams = byTeam; teams = byTeam;
packages = attrPathsToGetMaintainersFor; packages = lib.catAttrs "name" attrsWithModifiedFiles;
} }

View File

@@ -1,311 +0,0 @@
{
pkgs ? import ../../.. {
config = { };
overlays = [ ];
},
lib ? pkgs.lib,
}:
let
fun = import ./maintainers.nix { inherit lib; };
utils = import ./utils.nix { inherit lib; };
mockPkgs =
{
packages ? [ ],
modules ? [ ],
githubTeams ? true,
}:
lib.updateManyAttrsByPath
(lib.imap0 (i: p: {
path = p;
update = _: {
meta.maintainersPosition.file = lib.concatStringsSep "/" p;
meta.nonTeamMaintainers = [ { githubId = i; } ];
meta.teams =
if githubTeams then [ { githubId = i + 100; } ] else [ { members = [ { githubId = i + 100; } ]; } ];
};
}) packages)
{
nixos =
{ }:
{
config.meta.maintainers = lib.listToAttrs (
lib.imap0 (i: m: lib.nameValuePair m [ { githubId = i; } ]) modules
);
config.meta.teams = lib.listToAttrs (
lib.imap0 (
i: m:
lib.nameValuePair m (
if githubTeams then [ { githubId = i + 100; } ] else [ { members = [ { githubId = i + 100; } ]; } ]
)
) modules
);
};
};
tests = {
testEmpty = {
expr = fun {
pkgs = mockPkgs { };
changedFiles = [ ];
affectedAttrPaths = [ ];
};
expected = {
packages = [ ];
teams = { };
users = { };
};
};
testNonExistentAffected = {
expr = fun {
pkgs = mockPkgs { };
changedFiles = [ "a" ];
affectedAttrPaths = [ [ "b" ] ];
};
expected = {
packages = [ ];
teams = { };
users = { };
};
};
testIrrelevantAffected = {
expr = fun {
pkgs = mockPkgs {
packages = [ [ "b" ] ];
};
changedFiles = [ "a" ];
affectedAttrPaths = [ [ "b" ] ];
};
expected = {
packages = [ ];
teams = { };
users = { };
};
};
testRelevantAffected = {
expr = fun {
pkgs = mockPkgs {
packages = [ [ "b" ] ];
};
# Also tests that subpaths work
changedFiles = [ "b/c" ];
affectedAttrPaths = [ [ "b" ] ];
};
expected = {
packages = [ [ "b" ] ];
teams."100" = [
{ attrPath = [ "b" ]; }
];
users."0" = [
{ attrPath = [ "b" ]; }
];
};
};
testRelevantAffectedNonGitHub = {
expr = fun {
pkgs = mockPkgs {
packages = [ [ "b" ] ];
githubTeams = false;
};
changedFiles = [ "b/c" ];
affectedAttrPaths = [ [ "b" ] ];
};
expected = {
packages = [ [ "b" ] ];
teams = { };
users."0" = [
{ attrPath = [ "b" ]; }
];
users."100" = [
{ attrPath = [ "b" ]; }
];
};
};
testByNameChanged = {
expr = fun {
pkgs = mockPkgs {
packages = [ [ "hello" ] ];
};
changedFiles = [ "pkgs/by-name/he/hello/sources.json" ];
affectedAttrPaths = [ ];
};
expected = {
packages = [ [ "hello" ] ];
teams."100" = [
{ attrPath = [ "hello" ]; }
];
users."0" = [
{ attrPath = [ "hello" ]; }
];
};
};
testByNameNonExistentChanged = {
expr = fun {
pkgs = mockPkgs {
packages = [ ];
};
# Happens when a new package was added to pkgs/by-name
changedFiles = [ "pkgs/by-name/he/hello/sources.json" ];
affectedAttrPaths = [ ];
};
expected = {
packages = [ ];
teams = { };
users = { };
};
};
testByNameReadmeChanged = {
expr = fun {
pkgs = mockPkgs {
packages = [ [ "hello" ] ];
};
changedFiles = [ "pkgs/by-name/README.md" ];
affectedAttrPaths = [ ];
};
expected = {
packages = [ ];
teams = { };
users = { };
};
};
testNoDuplicates = {
expr = fun {
pkgs = mockPkgs {
packages = [ [ "hello" ] ];
};
changedFiles = [
"hello"
"pkgs/by-name/he/hello/sources.json"
];
affectedAttrPaths = [ [ "hello" ] ];
};
expected = {
packages = [ [ "hello" ] ];
teams."100" = [
{ attrPath = [ "hello" ]; }
];
users."0" = [
{ attrPath = [ "hello" ]; }
];
};
};
testModuleMaintainers = {
expr = fun {
pkgs = mockPkgs {
modules = [ "a" ];
};
changedFiles = [ "a" ];
affectedAttrPaths = [ ];
};
expected = {
packages = [ ];
teams."100" = [
{ file = "a"; }
];
users."0" = [
{ file = "a"; }
];
};
};
testModuleMaintainersNonGithub = {
expr = fun {
pkgs = mockPkgs {
modules = [ "a" ];
githubTeams = false;
};
changedFiles = [ "a" ];
affectedAttrPaths = [ ];
};
expected = {
packages = [ ];
teams = { };
users."100" = [
{ file = "a"; }
];
users."0" = [
{ file = "a"; }
];
};
};
testGroupAttrdiffByPlatform = {
expr = utils.groupAttrdiffByPlatform {
added = [
"new-tool.aarch64-linux"
"new-tool.x86_64-darwin"
];
changed = [
"updated-tool.x86_64-darwin"
"shared-tool.x86_64-darwin"
];
removed = [
"removed-tool.aarch64-darwin"
"shared-tool.aarch64-darwin"
];
};
expected = {
aarch64-darwin = {
added = [ ];
changed = [ ];
removed = [
"removed-tool"
"shared-tool"
];
};
aarch64-linux = {
added = [ "new-tool" ];
changed = [ ];
removed = [ ];
};
x86_64-darwin = {
added = [ "new-tool" ];
changed = [
"shared-tool"
"updated-tool"
];
removed = [ ];
};
};
};
testGroupAttrdiffByKernel = {
expr =
let
grouped = utils.groupAttrdiffByKernel {
added = [
"new-tool.aarch64-linux"
"new-tool.x86_64-darwin"
];
changed = [
"updated-tool.x86_64-darwin"
"shared-tool.x86_64-darwin"
];
removed = [
"removed-tool.aarch64-darwin"
"shared-tool.aarch64-darwin"
];
};
in
lib.mapAttrs (_: diff: lib.mapAttrs (_: lib.sort lib.lessThan) diff) grouped;
expected = {
darwin = {
added = [ "new-tool" ];
changed = [
"shared-tool"
"updated-tool"
];
removed = [
"removed-tool"
"shared-tool"
];
};
linux = {
added = [ "new-tool" ];
changed = [ ];
removed = [ ];
};
};
};
};
in
{
result = lib.runTests tests;
}

View File

@@ -150,50 +150,6 @@ rec {
in in
lib.genAttrs [ "linux" "darwin" ] filterKernel; lib.genAttrs [ "linux" "darwin" ] filterKernel;
/*
Group an attrdiff-style mapping by a derived key such as platform or kernel.
Turns
{
added = [ "new-tool.aarch64-linux" "new-tool.x86_64-darwin" ];
changed = [ "updated-tool.x86_64-darwin" "shared-tool.x86_64-darwin" ];
removed = [ "removed-tool.aarch64-darwin" "shared-tool.aarch64-darwin" ];
}
into
{
aarch64-darwin = {
added = [ ];
changed = [ ];
removed = [ "removed-tool" "shared-tool" ];
};
aarch64-linux = {
added = [ "new-tool" ];
changed = [ ];
removed = [ ];
};
x86_64-darwin = {
added = [ "new-tool" ];
changed = [ "shared-tool" "updated-tool" ];
removed = [ ];
};
}
when used with `groupByPlatform`.
*/
groupAttrdiffBy =
grouper: attrdiff:
let
groupedByKind = lib.mapAttrs (
_: packagePlatformPaths:
grouper (convertToPackagePlatformAttrs (uniqueStrings packagePlatformPaths))
) attrdiff;
groups = uniqueStrings (lib.flatten (map builtins.attrNames (lib.attrValues groupedByKind)));
in
lib.genAttrs groups (group: lib.mapAttrs (_: byGroup: byGroup.${group} or [ ]) groupedByKind);
groupAttrdiffByPlatform = groupAttrdiffBy groupByPlatform;
groupAttrdiffByKernel = groupAttrdiffBy groupByKernel;
/* /*
Maps an attrs of `kernel - rebuild counts` mappings to an attrs of labels Maps an attrs of `kernel - rebuild counts` mappings to an attrs of labels

View File

@@ -17,7 +17,6 @@
busybox, busybox,
jq, jq,
nix, nix,
perf,
}: }:
{ {
@@ -39,7 +38,8 @@ let
fileset = unions ( fileset = unions (
map (lib.path.append ../..) [ map (lib.path.append ../..) [
".version" ".version"
"ci/eval/pre-eval.nix" "ci/supportedSystems.json"
"ci/eval/attrpaths.nix"
"ci/eval/chunk.nix" "ci/eval/chunk.nix"
"ci/eval/outpaths.nix" "ci/eval/outpaths.nix"
"default.nix" "default.nix"
@@ -53,15 +53,13 @@ let
); );
}; };
supportedSystems = builtins.fromJSON ( supportedSystems = builtins.fromJSON (builtins.readFile ../supportedSystems.json);
builtins.readFile ../../pkgs/top-level/release-supported-systems.json
);
preEval = attrpathsSuperset =
{ {
evalSystem, evalSystem,
}: }:
runCommand "pre-eval" runCommand "attrpaths-superset.json"
{ {
src = nixpkgs; src = nixpkgs;
# Don't depend on -dev outputs to reduce closure size for CI. # Don't depend on -dev outputs to reduce closure size for CI.
@@ -74,15 +72,15 @@ let
export NIX_STATE_DIR=$(mktemp -d) export NIX_STATE_DIR=$(mktemp -d)
mkdir $out mkdir $out
export GC_INITIAL_HEAP_SIZE=4g export GC_INITIAL_HEAP_SIZE=4g
command time -f "Pre-eval done [%MKB max resident, %Es elapsed] %C" \ command time -f "Attribute eval done [%MKB max resident, %Es elapsed] %C" \
nix-instantiate --eval --strict --json --show-trace \ nix-instantiate --eval --strict --json --show-trace \
"$src/ci/eval/pre-eval.nix" \ "$src/ci/eval/attrpaths.nix" \
-A result \ -A paths \
-I "$src" \ -I "$src" \
--argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \ --argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \
--option restrict-eval true \ --option restrict-eval true \
--option allow-import-from-derivation false \ --option allow-import-from-derivation false \
--option eval-system "${evalSystem}" > $out/result.json --option eval-system "${evalSystem}" > $out/paths.json
''; '';
singleSystem = singleSystem =
@@ -91,10 +89,8 @@ let
# Note that this is intentionally not called `system`, # Note that this is intentionally not called `system`,
# because `--argstr system` would only be passed to the ci/default.nix file! # because `--argstr system` would only be passed to the ci/default.nix file!
evalSystem ? builtins.currentSystem, evalSystem ? builtins.currentSystem,
# The path to the `result.json` file from `preEval` # The path to the `paths.json` file from `attrpathsSuperset`
preEvalFile ? "${preEval { inherit evalSystem; }}/result.json", attrpathFile ? "${attrpathsSuperset { inherit evalSystem; }}/paths.json",
# Output the number of assembly instructions executed during evaluation
countInstructions ? false,
}: }:
let let
singleChunk = writeShellScript "single-chunk" '' singleChunk = writeShellScript "single-chunk" ''
@@ -103,7 +99,6 @@ let
myChunk=$2 myChunk=$2
system=$3 system=$3
outputDir=$4 outputDir=$4
preEvalFile=$5
# Default is 5, higher values effectively disable the warning. # Default is 5, higher values effectively disable the warning.
# This randomly breaks Eval. # This randomly breaks Eval.
@@ -125,12 +120,12 @@ let
--show-trace \ --show-trace \
--arg chunkSize "$chunkSize" \ --arg chunkSize "$chunkSize" \
--arg myChunk "$myChunk" \ --arg myChunk "$myChunk" \
--arg preEvalFile "$preEvalFile" \ --arg attrpathFile "${attrpathFile}" \
--arg systems "[ \"$system\" ]" \ --arg systems "[ \"$system\" ]" \
--arg includeBroken ${lib.boolToString includeBroken} \ --arg includeBroken ${lib.boolToString includeBroken} \
--argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \ --argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \
-I ${nixpkgs} \ -I ${nixpkgs} \
-I "$preEvalFile" \ -I ${attrpathFile} \
> "$outputDir/result/$myChunk" \ > "$outputDir/result/$myChunk" \
2> "$outputDir/stderr/$myChunk" 2> "$outputDir/stderr/$myChunk"
exitCode=$? exitCode=$?
@@ -150,16 +145,13 @@ let
runCommand "nixpkgs-eval-${evalSystem}" runCommand "nixpkgs-eval-${evalSystem}"
{ {
# Don't depend on -dev outputs to reduce closure size for CI. # Don't depend on -dev outputs to reduce closure size for CI.
nativeBuildInputs = map lib.getBin ( nativeBuildInputs = map lib.getBin [
[ busybox
busybox jq
jq nix
nix ];
]
++ lib.optionals countInstructions [ perf ]
);
env = { env = {
inherit evalSystem chunkSize countInstructions; inherit evalSystem chunkSize;
}; };
__structuredAttrs = true; __structuredAttrs = true;
unsafeDiscardReferences.out = true; unsafeDiscardReferences.out = true;
@@ -171,6 +163,12 @@ let
echo "System: $evalSystem" echo "System: $evalSystem"
cores=$NIX_BUILD_CORES cores=$NIX_BUILD_CORES
echo "Cores: $cores" echo "Cores: $cores"
attrCount=$(jq length "${attrpathFile}")
echo "Attribute count: $attrCount"
echo "Chunk size: $chunkSize"
# Same as `attrCount / chunkSize` but rounded up
chunkCount=$(( (attrCount - 1) / chunkSize + 1 ))
echo "Chunk count: $chunkCount"
mkdir -p $out/${evalSystem} mkdir -p $out/${evalSystem}
@@ -191,78 +189,29 @@ let
done done
) & ) &
chunkedEval() { seq_end=$(( chunkCount - 1 ))
local chunkOutputDir=$1
local preEvalFile=$2
local attrCount=$(jq '.paths | length' "$preEvalFile") ${lib.optionalString quickTest ''
echo "Attribute count: $attrCount" seq_end=0
echo "Chunk size: $chunkSize" ''}
# Same as `attrCount / chunkSize` but rounded up
local chunkCount=$(( (attrCount - 1) / chunkSize + 1 ))
echo "Chunk count: $chunkCount"
local seq_end=$(( chunkCount - 1 )) chunkOutputDir=$(mktemp -d)
${lib.optionalString quickTest '' mkdir "$chunkOutputDir"/{result,stats,timestats,stderr}
seq_end=0
''}
mkdir -p "$chunkOutputDir"/{result,stats,timestats,stderr} seq -w 0 "$seq_end" |
command time -f "%e" -o "$out/${evalSystem}/total-time" \
xargs -I{} -P"$cores" \
${singleChunk} "$chunkSize" {} "$evalSystem" "$chunkOutputDir"
runAllChunks() { cp -r "$chunkOutputDir"/stats $out/${evalSystem}/stats-by-chunk
seq -w 0 "$seq_end" |
xargs -I{} -P"$cores" \
${singleChunk} "$chunkSize" {} "$evalSystem" "$chunkOutputDir" "$preEvalFile"
}
if [[ -n "$countInstructions" ]]; then if (( chunkSize * chunkCount != attrCount )); then
export seq_end cores chunkSize evalSystem chunkOutputDir preEvalFile # A final incomplete chunk would mess up the stats, don't include it
export -f runAllChunks rm "$chunkOutputDir"/stats/"$seq_end"
perf stat \
--event instructions:u --field-separator , --output "$chunkOutputDir"/perf-output-file \
bash -c runAllChunks
cat "$chunkOutputDir"/perf-output-file | tail -n 1 | cut -d, -f1 > "$chunkOutputDir"/instructions
rm "$chunkOutputDir"/perf-output-file
else
runAllChunks
fi
if (( chunkSize * chunkCount != attrCount )); then
# A final incomplete chunk would mess up the stats, don't include it
rm "$chunkOutputDir"/stats/"$seq_end"
fi
}
chunkOutputDirs=$(mktemp -d)
# Preparation for the second eval
disallowedAttributesPreEvalFile=$(mktemp)
jq '{
paths: (.attrPathsDisallowedForInternalUse | map(.attrPath)),
attrPathsDisallowedForInternalUse: []
}' ${preEvalFile} > "$disallowedAttributesPreEvalFile"
startEpoch=$(date +%s)
# The first eval evaluates only attributes that are not disallowed for internal Nixpkgs use, ensuring that they don't depend on disallowed attributes
# Because the first eval doesn't evaluate the disallowed attributes themselves, but we still want to check that they don't fail evaluation, we evaluate them separately in a second eval
# The reason we need two evals is because we want disallowed attributes to be able to depend on other disallowed attributes, which inherently needs a separate Nixpkgs instantiation
# And while we could interleave that instantiation into a single eval, that would ~double memory usage for all chunks, while doing it separately doesn't
echo "Evaluating the internally allowed attributes"
chunkedEval "$chunkOutputDirs"/allowed ${preEvalFile}
echo "Evaluating the internally disallowed attributes"
chunkedEval "$chunkOutputDirs"/disallowed "$disallowedAttributesPreEvalFile"
echo $(( $(date +%s) - startEpoch )) > "$out/${evalSystem}/total-time"
# We only use the stats from the allowed attrs eval, because the disallowed attrs are generally not even a full chunk
cp -r "$chunkOutputDirs"/allowed/stats $out/${evalSystem}/stats-by-chunk
if [[ -f "$chunkOutputDirs"/allowed/instructions ]]; then
cp "$chunkOutputDirs"/allowed/instructions $out/${evalSystem}/instructions
fi fi
cat "$chunkOutputDirs"/*/result/* | jq -s 'add | map_values(.outputs)' > $out/${evalSystem}/paths.json cat "$chunkOutputDir"/result/* | jq -s 'add | map_values(.outputs)' > $out/${evalSystem}/paths.json
cat "$chunkOutputDirs"/*/result/* | jq -s 'add | map_values(.meta)' > $out/${evalSystem}/meta.json cat "$chunkOutputDir"/result/* | jq -s 'add | map_values(.meta)' > $out/${evalSystem}/meta.json
''; '';
diff = callPackage ./diff.nix { }; diff = callPackage ./diff.nix { };
@@ -299,20 +248,14 @@ let
}) | from_entries }) | from_entries
' > $out/maintainers.json ' > $out/maintainers.json
mkdir -p $out/before/stats $out/before/instructions mkdir -p $out/before/stats
for d in ${diffDir}/before/*; do for d in ${diffDir}/before/*; do
cp -r "$d"/stats-by-chunk $out/before/stats/$(basename "$d") cp -r "$d"/stats-by-chunk $out/before/stats/$(basename "$d")
if [[ -f "$d"/instructions ]]; then
cp "$d"/instructions $out/before/instructions/$(basename "$d")
fi
done done
mkdir -p $out/after/stats $out/after/instructions mkdir -p $out/after/stats
for d in ${diffDir}/after/*; do for d in ${diffDir}/after/*; do
cp -r "$d"/stats-by-chunk $out/after/stats/$(basename "$d") cp -r "$d"/stats-by-chunk $out/after/stats/$(basename "$d")
if [[ -f "$d"/instructions ]]; then
cp "$d"/instructions $out/after/instructions/$(basename "$d")
fi
done done
''; '';
@@ -322,16 +265,13 @@ let
{ {
# Whether to evaluate on a specific set of systems, by default all are evaluated # Whether to evaluate on a specific set of systems, by default all are evaluated
evalSystems ? if quickTest then [ "x86_64-linux" ] else supportedSystems, evalSystems ? if quickTest then [ "x86_64-linux" ] else supportedSystems,
# Output the number of assembly instructions executed during evaluation on
# each system
countInstructions ? false,
}: }:
symlinkJoin { symlinkJoin {
name = "nixpkgs-eval-baseline"; name = "nixpkgs-eval-baseline";
paths = map ( paths = map (
evalSystem: evalSystem:
singleSystem { singleSystem {
inherit evalSystem countInstructions; inherit evalSystem;
} }
) evalSystems; ) evalSystems;
}; };
@@ -347,12 +287,6 @@ let
# | jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json # | jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json
# ``` # ```
touchedFilesJson ? builtins.toFile "touched-files.json" "[ ]", touchedFilesJson ? builtins.toFile "touched-files.json" "[ ]",
# The branch the local comparison is made against; matches the `master`
# used in the touched-files expression above.
baseBranch ? "master",
# Output the number of assembly instructions executed during evaluation on
# each system
countInstructions ? false,
}: }:
let let
diffs = symlinkJoin { diffs = symlinkJoin {
@@ -363,14 +297,14 @@ let
inherit evalSystem; inherit evalSystem;
beforeDir = baseline; beforeDir = baseline;
afterDir = singleSystem { afterDir = singleSystem {
inherit evalSystem countInstructions; inherit evalSystem;
}; };
} }
) evalSystems; ) evalSystems;
}; };
comparisonReport = compare { comparisonReport = compare {
combinedDir = combine { diffDir = diffs; }; combinedDir = combine { diffDir = diffs; };
inherit touchedFilesJson baseBranch; inherit touchedFilesJson;
}; };
in in
comparisonReport; comparisonReport;
@@ -378,7 +312,7 @@ let
in in
{ {
inherit inherit
preEval attrpathsSuperset
singleSystem singleSystem
diff diff
combine combine

35
ci/eval/outpaths.nix Executable file → Normal file
View File

@@ -6,15 +6,11 @@
includeBroken ? true, # set this to false to exclude meta.broken packages from the output includeBroken ? true, # set this to false to exclude meta.broken packages from the output
path ? ./../.., path ? ./../..,
# used by ./pre-eval.nix # used by ./attrpaths.nix
attrNamesOnly ? false, attrNamesOnly ? false,
# Set this to `null` to build for builtins.currentSystem only # Set this to `null` to build for builtins.currentSystem only
systems ? builtins.fromJSON ( systems ? builtins.fromJSON (builtins.readFile ../supportedSystems.json),
builtins.readFile (path + "/pkgs/top-level/release-supported-systems.json")
),
attrPathsDisallowedForInternalUse ? [ ],
# Customize the config used to evaluate nixpkgs # Customize the config used to evaluate nixpkgs
extraNixpkgsConfig ? { }, extraNixpkgsConfig ? { },
@@ -37,25 +33,6 @@ let
allowVariants = !attrNamesOnly; allowVariants = !attrNamesOnly;
checkMeta = true; checkMeta = true;
# We don't need to care about problems being caught using the
# standard mechanism, because any problems whose kind is not
# nixpkgsInternalUseAllowed cause the corresponding attributes to
# be disallowed entirely for internal use with
# attrPathsDisallowedForInternalUse, see also ./pre-eval.nix
problems.matchers = lib.mkForce [
# We only need to set the broken handler to error, so that CI
# doesn't evaluate those. No reason it couldn't evaluate them
# afaik, but this is how it's been before.
{
kind = "broken";
handler = "error";
}
];
inherit attrPathsDisallowedForInternalUse;
# Silence the `x86_64-darwin` deprecation warning.
allowDeprecatedx86_64Darwin = true;
handleEvalIssue = handleEvalIssue =
reason: errormsg: reason: errormsg:
let let
@@ -90,9 +67,7 @@ let
nixosJobs = import (path + "/nixos/release.nix") { nixosJobs = import (path + "/nixos/release.nix") {
inherit attrNamesOnly; inherit attrNamesOnly;
supportedSystems = lib.filter (lib.hasSuffix "-linux") ( supportedSystems = if systems == null then [ builtins.currentSystem ] else systems;
if systems == null then [ builtins.currentSystem ] else systems
);
}; };
recurseIntoAttrs = attrs: attrs // { recurseForDerivations = true; }; recurseIntoAttrs = attrs: attrs // { recurseForDerivations = true; };
@@ -126,8 +101,6 @@ in
tweak ( tweak (
(removeAttrs nixpkgsJobs blacklist) (removeAttrs nixpkgsJobs blacklist)
// { // {
nixosTests = lib.filterAttrs ( nixosTests.simple = nixosJobs.tests.simple;
name: _: name == "simple-container" || name == "simple-vm"
) nixosJobs.tests;
} }
) )

View File

@@ -1,128 +0,0 @@
# This file does a fast pre-evaluation of Nixpkgs to determine:
# - paths: A *superset* of all attrpaths of derivations which might be part of a release on *any* platform.
# - attrPathsDisallowedForInternalUse: Attribute paths whose meta.problems has problems whose kinds should not be used internally in Nixpkgs
#
# This expression runs single-threaded under all current Nix
# implementations, but much faster and with much less memory
# used than ./outpaths.nix itself.
#
# Once you have the list of attrnames you can split it up into
# $NUM_CORES batches and evaluate the outpaths separately for each
# batch, in parallel.
#
# To dump the result:
#
# nix-instantiate --eval --strict --json ci/eval/pre-eval.nix -A result
#
{
lib ? import (path + "/lib"),
trace ? false,
path ? ./../..,
extraNixpkgsConfigJson ? "{}",
}:
let
# TODO: Use mapAttrsToListRecursiveCond when this PR lands:
# https://github.com/NixOS/nixpkgs/pull/395160
listAttrs =
path: value:
let
result =
if path == [ "AAAAAASomeThingsFailToEvaluate" ] || !(lib.isAttrs value) then
[ ]
else if lib.isDerivation value then
[
{
inherit path value;
}
]
else
lib.pipe value [
(lib.mapAttrsToList (
name: value:
lib.addErrorContext "while evaluating package set attribute path '${
lib.showAttrPath (path ++ [ name ])
}'" (listAttrs (path ++ [ name ]) value)
))
lib.concatLists
];
in
lib.traceIf trace "** ${lib.showAttrPath path}" result;
outpaths = import ./outpaths.nix {
inherit path;
extraNixpkgsConfig = builtins.fromJSON extraNixpkgsConfigJson;
attrNamesOnly = true;
};
list =
map
(path: {
inherit path;
# This looks a bit weird, but the only reason we care about this value
# is for the meta.problems check below, and stdenv's certainly don't
# have any problems, so this is fine :)
value = { };
})
[
# Some of the following are based on variants, which are disabled with `attrNamesOnly = true`.
# Until these have been removed from release.nix / hydra, we manually add them to the list.
[
"pkgsLLVM"
"stdenv"
]
[
"pkgsArocc"
"stdenv"
]
[
"pkgsZig"
"stdenv"
]
[
"pkgsStatic"
"stdenv"
]
[
"pkgsMusl"
"stdenv"
]
]
++ listAttrs [ ] outpaths;
paths = map (attrs: attrs.path) list;
names = map lib.showAttrPath paths;
inherit (import ../../pkgs/stdenv/generic/problems.nix { inherit lib; })
disallowNixpkgsInternalUseKinds
;
# Determine the list of attributes whose packages have any meta.problems
# with a kind that's disallowed from internal Nixpkgs use
attrPathsDisallowedForInternalUse = lib.pipe list [
(lib.map (
attrs:
attrs
// {
problematicProblems = builtins.tryEval (
lib.filterAttrs (name: problem: disallowNixpkgsInternalUseKinds ? ${problem.kind}) (
attrs.value.meta.problems or { }
)
);
}
))
(lib.filter (attrs: attrs.problematicProblems.success && attrs.problematicProblems.value != { }))
(lib.map (attrs: {
attrPath = attrs.path;
reason = "it has certain meta.problems whose kinds are disallowed: ${
lib.generators.toPretty { } attrs.problematicProblems.value
}";
}))
];
in
{
# TODO: Do we still need these? Probably not
inherit paths names;
result = {
inherit paths attrPathsDisallowedForInternalUse;
};
}

View File

@@ -1,6 +1,6 @@
module.exports = async ({ github, context, core, dry }) => { module.exports = async ({ github, context, core, dry }) => {
const path = require('node:path') const path = require('node:path')
const { DefaultArtifactClient } = await import('@actions/artifact') const { DefaultArtifactClient } = require('@actions/artifact')
const { readFile, writeFile } = require('node:fs/promises') const { readFile, writeFile } = require('node:fs/promises')
const withRateLimit = require('./withRateLimit.js') const withRateLimit = require('./withRateLimit.js')
const { classify } = require('../supportedBranches.js') const { classify } = require('../supportedBranches.js')
@@ -206,8 +206,20 @@ module.exports = async ({ github, context, core, dry }) => {
const maintainers = await getMaintainerMap(pull_request.base.ref) const maintainers = await getMaintainerMap(pull_request.base.ref)
const merge_bot_eligible = await handleMerge({
github,
context,
core,
log,
dry,
pull_request,
events,
maintainers,
getTeamMembers,
getUser,
})
// Check for any human reviews other than the PR author, GitHub actions and other GitHub apps. // Check for any human reviews other than the PR author, GitHub actions and other GitHub apps.
// `commit { oid }` is needed by handleMerge to verify approvals are against the current head.
const reviews = ( const reviews = (
await github.graphql( await github.graphql(
`query($owner: String!, $repo: String!, $pr: Int!) { `query($owner: String!, $repo: String!, $pr: Int!) {
@@ -219,7 +231,6 @@ module.exports = async ({ github, context, core, dry }) => {
reviews(first: 100) { reviews(first: 100) {
nodes { nodes {
state state
commit { oid }
user: author { user: author {
# Only get users, no bots # Only get users, no bots
... on User { ... on User {
@@ -255,20 +266,6 @@ module.exports = async ({ github, context, core, dry }) => {
r.user.id !== pull_request.user?.id, r.user.id !== pull_request.user?.id,
) )
const merge_bot_eligible = await handleMerge({
github,
context,
core,
log,
dry,
pull_request,
events,
reviews,
maintainers,
getTeamMembers,
getUser,
})
const approvals = new Set( const approvals = new Set(
reviews reviews
.filter((review) => review.state === 'APPROVED') .filter((review) => review.state === 'APPROVED')

View File

@@ -25,16 +25,6 @@ async function checkTargetBranch({ github, context, core, dry }) {
* changed: string[], * changed: string[],
* removed: string[], * removed: string[],
* }, * },
* attrdiffByKernel: Record<string, {
* added: string[],
* changed: string[],
* removed: string[],
* }>,
* attrdiffByPlatform: Record<string, {
* added: string[],
* changed: string[],
* removed: string[],
* }>,
* labels: Record<string, boolean>, * labels: Record<string, boolean>,
* rebuildCountByKernel: Record<string, number>, * rebuildCountByKernel: Record<string, number>,
* rebuildsByKernel: Record<string, string[]>, * rebuildsByKernel: Record<string, string[]>,
@@ -99,13 +89,13 @@ async function checkTargetBranch({ github, context, core, dry }) {
...Object.values(changed.rebuildCountByKernel), ...Object.values(changed.rebuildCountByKernel),
) )
const rebuildsAllTests = const rebuildsAllTests =
changed.attrdiff.changed.includes('nixosTests.simple-container') || changed.attrdiff.changed.includes('nixosTests.simple')
changed.attrdiff.changed.includes('nixosTests.simple-vm')
// https://github.com/NixOS/nixpkgs/pull/521157 // https://github.com/NixOS/nixpkgs/pull/481205#issuecomment-3790123921
// These should go to master and release-xx.xx when backported // These should go to staging-nixos instead of master,
// but release-xx.xx (not staging-xx.xx) when backported
let isExemptKernelUpdate = false let isExemptKernelUpdate = false
if (prInfo.changed_files === 1) { if (prInfo.changed_files === 1 && base.startsWith('release-')) {
const changedFiles = ( const changedFiles = (
await github.rest.pulls.listFiles({ await github.rest.pulls.listFiles({
...context.repo, ...context.repo,
@@ -115,7 +105,7 @@ async function checkTargetBranch({ github, context, core, dry }) {
isExemptKernelUpdate = isExemptKernelUpdate =
changedFiles.length === 1 && changedFiles.length === 1 &&
changedFiles[0].filename === changedFiles[0].filename ===
'pkgs/os-specific/linux/kernel/xanmod-kernels.nix' 'pkgs/os-specific/linux/kernel/kernels-org.json'
} }
// https://github.com/NixOS/nixpkgs/pull/483194#issuecomment-3793393218 // https://github.com/NixOS/nixpkgs/pull/483194#issuecomment-3793393218
@@ -151,19 +141,19 @@ async function checkTargetBranch({ github, context, core, dry }) {
core, core,
dry, dry,
body, body,
event: 'REQUEST_CHANGES', event: 'COMMENT',
reviewKey, reviewKey,
}) })
throw new Error('This PR is against the wrong branch.')
} else if (rebuildsAllTests && !isExemptKernelUpdate) { } else if (rebuildsAllTests && !isExemptKernelUpdate) {
let branchText let branchText
if (base === 'master' && maxRebuildCount >= 500) { if (base === 'master' && maxRebuildCount >= 500) {
branchText = '(probably either `staging-nixos` or `staging`)' branchText = '(probably either `staging-nixos` or `staging`)'
} else if (base === 'master') { } else if (base === 'master') {
branchText = '(probably `staging-nixos`)' branchText = '(probably `staging-nixos`)'
} else if (maxRebuildCount >= 500) {
branchText = `(probably either \`staging-nixos-${split(base).version}\` or \`staging-${split(base).version}\`)`
} else { } else {
branchText = `(probably \`staging-nixos-${split(base).version}\`)` branchText = `(probably \`staging-${split(base).version}\`)`
} }
const body = [ const body = [
`The PR's base branch is set to \`${base}\`, but this PR rebuilds all NixOS tests.`, `The PR's base branch is set to \`${base}\`, but this PR rebuilds all NixOS tests.`,
@@ -179,9 +169,11 @@ async function checkTargetBranch({ github, context, core, dry }) {
core, core,
dry, dry,
body, body,
event: 'REQUEST_CHANGES', event: 'COMMENT',
reviewKey, reviewKey,
}) })
throw new Error('This PR is against the wrong branch.')
} else if ( } else if (
maxRebuildCount >= 500 && maxRebuildCount >= 500 &&
!isExemptKernelUpdate && !isExemptKernelUpdate &&
@@ -202,7 +194,7 @@ async function checkTargetBranch({ github, context, core, dry }) {
core, core,
dry, dry,
body, body,
event: 'REQUEST_CHANGES', event: 'COMMENT',
reviewKey, reviewKey,
}) })
} else { } else {

View File

@@ -1,117 +0,0 @@
// @ts-check
const { promisify } = require('node:util')
const execFile = promisify(require('node:child_process').execFile)
/**
* @typedef {{
* subject: string,
* sha: string,
* author: { name: string, email: string },
* committer: { name: string, email: string}
* changedPaths: string[],
* changedPathSegments: Set<string>,
* }} Commit
*/
/**
* @param {{
* args: string[]
* core: import('@actions/core'),
* quiet?: boolean,
* repoPath?: string,
* }} RunGitProps
*/
async function runGit({ args, repoPath, core, quiet }) {
if (repoPath) {
args = ['-C', repoPath, ...args]
}
if (!quiet) {
core.info(`About to run \`git ${args.map((s) => `'${s}'`).join(' ')}\``)
}
return await execFile('git', args)
}
/**
* Gets the SHA, subject and changed files for each commit in the given PR.
*
* Don't use GitHub API at all: the "list commits on PR" endpoint has a limit
* of 250 commits and doesn't return the changed files.
*
* @param {{
* core: import('@actions/core'),
* pr: Awaited<ReturnType<InstanceType<import('@actions/github/lib/utils').GitHub>["rest"]["pulls"]["get"]>>["data"]
* repoPath?: string,
* }} GetCommitMessagesForPRProps
*
* @returns {Promise<Commit[]>}
*/
async function getCommitDetailsForPR({ core, pr, repoPath }) {
await runGit({
args: ['fetch', `--depth=1`, 'origin', pr.base.sha],
repoPath,
core,
})
await runGit({
args: ['fetch', `--depth=${pr.commits + 1}`, 'origin', pr.head.sha],
repoPath,
core,
})
const shas = (
await runGit({
args: [
'rev-list',
`--max-count=${pr.commits}`,
`${pr.base.sha}..${pr.head.sha}`,
],
repoPath,
core,
})
).stdout
.split('\n')
.map((s) => s.trim())
.filter(Boolean)
return Promise.all(
shas.map(async (sha) => {
// Subject, author name, author email, committer name, committer email (all tab-seperated)
// then a blank line, then filenames.
const result = (
await runGit({
args: [
'log',
'--format=%s\t%aN\t%aE\t%cN\t%cE',
'--name-only',
'-1',
sha,
],
repoPath,
core,
quiet: true,
})
).stdout.split('\n')
const [subject, authorName, authorEmail, committerName, committerEmail] =
result[0].split('\t')
const changedPaths = result.slice(2, -1)
const changedPathSegments = new Set(
changedPaths.flatMap((path) => path.split('/')),
)
return {
sha,
subject,
author: { name: authorName, email: authorEmail },
committer: { name: committerName, email: committerEmail },
changedPaths,
changedPathSegments,
}
}),
)
}
module.exports = { getCommitDetailsForPR }

View File

@@ -1,18 +1,37 @@
// @ts-check // @ts-check
const { classify } = require('../supportedBranches.js') const { classify } = require('../supportedBranches.js')
const { getCommitDetailsForPR } = require('./get-pr-commit-details.js') const { promisify } = require('node:util')
const execFile = promisify(require('node:child_process').execFile)
/** @typedef {import('./get-pr-commit-details.js').Commit} Commit */ /**
* @param {{
* args: string[]
* core: import('@actions/core'),
* quiet?: boolean,
* repoPath?: string,
* }} RunGitProps
*/
async function runGit({ args, repoPath, core, quiet }) {
if (repoPath) {
args = ['-C', repoPath, ...args]
}
if (!quiet) {
core.info(`About to run \`git ${args.map((s) => `'${s}'`).join(' ')}\``)
}
return await execFile('git', args)
}
/** /**
* @param {{ * @param {{
* github: InstanceType<import('@actions/github/lib/utils').GitHub>, * github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: typeof import('@actions/github').context, * context: import('@actions/github/lib/context').Context,
* core: import('@actions/core'), * core: import('@actions/core'),
* repoPath?: string, * repoPath?: string,
* }} LintCommitsProps * }} CheckCommitMessagesProps
*/ */
async function lintCommits({ github, context, core, repoPath }) { async function checkCommitMessages({ github, context, core, repoPath }) {
// This check should only be run when we have the pull_request context. // This check should only be run when we have the pull_request context.
const pull_number = context.payload.pull_request?.number const pull_number = context.payload.pull_request?.number
if (!pull_number) { if (!pull_number) {
@@ -48,81 +67,84 @@ async function lintCommits({ github, context, core, repoPath }) {
return return
} }
const commits = await getCommitDetailsForPR({ core, pr, repoPath })
await checkCommitMessages({ commits, core })
await checkCommitMetadata({ commits, core })
}
/**
* @param {{
* commits: Commit[],
* core: import('@actions/core'),
* }} CheckCommitMessagesProps
*/
async function checkCommitMessages({ commits, core }) {
const failures = new Set()
const conventionalCommitTypes = [
'build',
'chore',
'ci',
'doc',
'docs',
'feat',
'feature',
'fix',
'perf',
'refactor',
'style',
'test',
]
/** /**
* @param {string[]} types e.g. ["fix", "feat"] * GitHub's API will return a maximum of 250 commits.
* @param {string?} sha commit hash * We will use it if we can, but fall back to using git locally.
* This type is used to abstract over the differences between the two.
* @type {{
* message: string,
* sha: string,
* }[]}
*/ */
function makeConventionalCommitRegex(types, sha = null) { let commits
core.info(
`${
sha
? `Conventional commit types for ${sha?.slice(0, 16)}`
: 'Default conventional commit types'
}: ${JSON.stringify(types)}`,
)
return new RegExp(`^(${types.join('|')})!?(\\(.*\\))?!?:`) if (pr.commits < 250) {
commits = (
await github.paginate(github.rest.pulls.listCommits, {
...context.repo,
pull_number,
})
).map((commit) => ({ message: commit.commit.message, sha: commit.sha }))
} else {
await runGit({
args: ['fetch', `--depth=1`, 'origin', pr.base.sha],
repoPath,
core,
})
await runGit({
args: ['fetch', `--depth=${pr.commits + 1}`, 'origin', pr.head.sha],
repoPath,
core,
})
const shas = (
await runGit({
args: [
'rev-list',
`--max-count=${pr.commits}`,
`${pr.base.sha}..${pr.head.sha}`,
],
repoPath,
core,
})
).stdout
.split('\n')
.map((s) => s.trim())
.filter(Boolean)
commits = await Promise.all(
shas.map(async (sha) => ({
sha,
message: (
await runGit({
args: ['log', '--format=%s', '-1', sha],
repoPath,
core,
quiet: true,
})
).stdout,
})),
)
} }
// Optimize for the common case that we don't have path segments with the const failures = new Set()
// same name as a conventional commit type.
const fullConventionalCommitRegex = makeConventionalCommitRegex(
conventionalCommitTypes,
)
for (const commit of commits) { for (const commit of commits) {
const logMsgStart = `Commit ${commit.sha}'s message's subject ("${commit.subject}")` const message = commit.message
const firstLine = message.split('\n')[0]
// If we have a commit `perf: ...`, and we touch a file containing the path const logMsgStart = `Commit ${commit.sha}'s message's subject ("${firstLine}")`
// segment "perf", we don't want to flag this.
const filteredTypes = conventionalCommitTypes.filter(
(type) => !commit.changedPathSegments.has(type),
)
const conventionalCommitRegex =
filteredTypes.length === conventionalCommitTypes.length
? fullConventionalCommitRegex
: makeConventionalCommitRegex(filteredTypes, commit.sha)
if (!commit.subject.includes(': ')) { if (!firstLine.includes(': ')) {
core.error( core.error(
`${logMsgStart} was detected as not meeting our guidelines because ` + `${logMsgStart} was detected as not meeting our guidelines because ` +
'it does not contain a colon followed by a whitespace. ' + 'it does not contain a colon followed by a whitespace.' +
'There are likely other issues as well.', 'There are likely other issues as well.',
) )
failures.add(commit.sha) failures.add(commit.sha)
} }
if (commit.subject.endsWith('.')) { if (firstLine.endsWith('.')) {
core.error( core.error(
`${logMsgStart} was detected as not meeting our guidelines because ` + `${logMsgStart} was detected as not meeting our guidelines because ` +
'it ends in a period. There may be other issues as well.', 'it ends in a period. There may be other issues as well.',
@@ -131,25 +153,15 @@ async function checkCommitMessages({ commits, core }) {
} }
const fixups = ['amend!', 'fixup!', 'squash!'] const fixups = ['amend!', 'fixup!', 'squash!']
if (fixups.some((s) => commit.subject.startsWith(s))) { if (fixups.some((s) => firstLine.startsWith(s))) {
core.error( core.error(
`${logMsgStart} was detected as not meeting our guidelines because ` + `${logMsgStart} was detected as not meeting our guidelines because ` +
`it begins with "${fixups.find((s) => commit.subject.startsWith(s))}". ` + `it begins with "${fixups.find((s) => firstLine.startsWith(s))}". ` +
'Did you forget to run `git rebase -i --autosquash`?', 'Did you forget to run `git rebase -i --autosquash`?',
) )
failures.add(commit.sha) failures.add(commit.sha)
} }
if (conventionalCommitRegex.test(commit.subject)) {
core.error(
`${logMsgStart} was detected as not meeting our guidelines because ` +
'it seems to use conventional commit (conventionalcommits.org) ' +
'formatting. Nixpkgs has its own, different, commit message ' +
'formatting standards.',
)
failures.add(commit.sha)
}
if (!failures.has(commit.sha)) { if (!failures.has(commit.sha)) {
core.info(`${logMsgStart} passed our automated checks!`) core.info(`${logMsgStart} passed our automated checks!`)
} }
@@ -158,66 +170,11 @@ async function checkCommitMessages({ commits, core }) {
if (failures.size !== 0) { if (failures.size !== 0) {
core.error( core.error(
'Please review the guidelines at ' + 'Please review the guidelines at ' +
'<https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#commit-conventions>, ' + 'https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#commit-conventions, ' +
'as well as the applicable area-specific guidelines linked there.', 'as well as the applicable area-specific guidelines linked there.',
) )
core.setFailed('Committers: merging is discouraged.') core.setFailed('Committers: merging is discouraged.')
} }
} }
/** module.exports = checkCommitMessages
* @param {{
* commits: Commit[],
* core: import('@actions/core'),
* }} CheckGitFieldsProps
*/
async function checkCommitMetadata({ commits, core }) {
const failures = new Set()
/** @type {(s: string) => boolean} */
const isEmail = (s) => /^.+@.*$/.test(s)
for (const commit of commits) {
if (!commit.author.name) {
core.error(`Commit ${commit.sha} author's name field is missing`)
failures.add(commit.sha)
}
if (!commit.author.email || !isEmail(commit.author.email)) {
core.error(
`Commit ${commit.sha} author's email field is missing or invalid`,
)
failures.add(commit.sha)
}
if (!commit.committer.name) {
core.error(`Commit ${commit.sha} committer's name field is missing`)
failures.add(commit.sha)
}
if (!commit.committer.email || !isEmail(commit.committer.email)) {
core.error(
`Commit ${commit.sha} committer's email field is missing or invalid`,
)
failures.add(commit.sha)
}
if (!failures.has(commit.sha)) {
core.info(
`Commit ${commit.sha}'s git fields passed our automated checks!`,
)
}
}
if (failures.size !== 0) {
core.error(
'Please add the missing commit fields. ' +
'You can use the noreply email address generated for you by GitHub ' +
'(https://docs.github.com/en/account-and-profile/reference/email-addresses-reference#your-noreply-email-address) ' +
"if you'd like.",
)
core.setFailed('Committers: merging is discouraged.')
}
}
module.exports = lintCommits

View File

@@ -1,95 +0,0 @@
// @ts-check
const { classify } = require('../supportedBranches.js')
const { getCommitDetailsForPR } = require('./get-pr-commit-details')
/**
* @param {{
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: import('@actions/github/lib/context').Context,
* core: import('@actions/core'),
* repoPath?: string,
* dry: boolean,
* }} CheckManualFileEditsProps
*/
async function checkManualFileEdits({ github, context, core, repoPath, dry }) {
const { dismissReviews, postReview } = require('./reviews.js')
const reviewKey = 'manual-file-edits'
const pull_number = context.payload.pull_request?.number
if (!pull_number) {
core.info('This is not a pull request. Skipping checks.')
return
}
const pr = (
await github.rest.pulls.get({
...context.repo,
pull_number,
})
).data
if (pr.user.login.endsWith('[bot]')) {
core.info('This is a bot, so these checks do not apply.')
return
}
const baseBranchType = classify(
pr.base.ref.replace(/^refs\/heads\//, ''),
).type
const headBranchType = classify(
pr.head.ref.replace(/^refs\/heads\//, ''),
).type
if (
baseBranchType.includes('development') &&
headBranchType.includes('development') &&
pr.base.repo.id === pr.head.repo?.id
) {
// This matches, for example, PRs from NixOS:staging-next to NixOS:master, or vice versa.
// Ignore them: we should only care about PRs introducing *new* commits.
// We still want to run on PRs from, e.g., Someone:master to NixOS:master, though.
core.info(
'This PR is from one development branch to another. Skipping checks.',
)
return
}
const details = await getCommitDetailsForPR({ core, pr, repoPath })
if (
details.some(({ changedPaths }) =>
changedPaths.includes('maintainers/github-teams.json'),
)
) {
postReview({
github,
context,
core,
dry,
event: 'REQUEST_CHANGES',
body: [
'maintainers/github-teams.json is supposed to accurately reflect the state of the teams in GitHub.\n',
'Therefore, it should not be edited manually.\n',
'All changes to teams listed in maintainers/github-teams.json should be performed in GitHub by a team maintainer.\n',
"Team maintainers are listed in the github-teams.json file and in GitHub's UI.\n",
'If there is no team maintainer available, an org owner can make the needed change, please contact one by',
'following the instructions at https://github.com/NixOS/org/blob/main/doc/github-org-owners.md#how-to-contact-the-team.\n',
'Thank you!',
].reduce(
(prev, curr) => prev + (!prev || prev.endsWith('\n') ? '' : ' ') + curr,
'',
),
reviewKey,
})
} else {
dismissReviews({
github,
context,
core,
dry,
reviewKey,
})
}
}
module.exports = checkManualFileEdits

View File

@@ -2,11 +2,11 @@ const { classify } = require('../supportedBranches.js')
function runChecklist({ function runChecklist({
committers, committers,
events,
files, files,
pull_request, pull_request,
log, log,
maintainers, maintainers,
reviews,
user, user,
userIsMaintainer, userIsMaintainer,
}) { }) {
@@ -27,35 +27,18 @@ function runChecklist({
.reduce((acc, cur) => acc?.intersection(cur) ?? cur) .reduce((acc, cur) => acc?.intersection(cur) ?? cur)
const approvals = new Set( const approvals = new Set(
reviews events
.filter( .filter(
({ state, commit }) => ({ event, state, commit_id }) =>
state === 'APPROVED' && event === 'reviewed' &&
state === 'approved' &&
// Only approvals for the current head SHA count, otherwise authors could push // Only approvals for the current head SHA count, otherwise authors could push
// bad code between the approval and the merge. // bad code between the approval and the merge.
commit?.oid === pull_request.head.sha, commit_id === pull_request.head.sha,
) )
.map(({ user }) => user.id), .map(({ user }) => user?.id)
) // Some users have been deleted, so filter these out.
.filter(Boolean),
// A "changes requested" review from a committer blocks both the merge queue and
// auto-merge, even if it was made on an older commit (unlike approvals, GitHub does
// not auto-dismiss changes-requested reviews on push). For each committer, take their
// latest actionable review; if it's CHANGES_REQUESTED, they're blocking the PR.
// Dismissed reviews surface as DISMISSED and comment-only follow-ups as COMMENTED, so
// both are skipped naturally — the prior actionable review still stands until the
// committer explicitly approves or requests changes again.
const committerReviewState = new Map()
for (const { user, state } of reviews) {
if (
committers.has(user.id) &&
['APPROVED', 'CHANGES_REQUESTED'].includes(state)
) {
committerReviewState.set(user.id, state)
}
}
const noBlockingReviews = !Array.from(committerReviewState.values()).includes(
'CHANGES_REQUESTED',
) )
const checklist = { const checklist = {
@@ -63,22 +46,13 @@ function runChecklist({
classify(pull_request.base.ref).type.includes('development'), classify(pull_request.base.ref).type.includes('development'),
'PR touches only files of packages in `pkgs/by-name/`.': allByName, 'PR touches only files of packages in `pkgs/by-name/`.': allByName,
'PR is at least one of:': { 'PR is at least one of:': {
'Approved by a [committer](https://github.com/orgs/NixOS/teams/nixpkgs-committers).': 'Approved by a committer.': committers.intersection(approvals).size > 0,
committers.intersection(approvals).size > 0,
'Backported via label.': 'Backported via label.':
pull_request.user.login === 'nixpkgs-ci[bot]' && pull_request.user.login === 'nixpkgs-ci[bot]' &&
pull_request.head.ref.startsWith('backport-'), pull_request.head.ref.startsWith('backport-'),
'Opened by a [committer](https://github.com/orgs/NixOS/teams/nixpkgs-committers).': 'Opened by a committer.': committers.has(pull_request.user.id),
committers.has(pull_request.user.id), 'Opened by r-ryantm.': pull_request.user.login === 'r-ryantm',
'Opened by [@r-ryantm](https://nix-community.github.io/nixpkgs-update/r-ryantm/).':
pull_request.user.login === 'r-ryantm',
}, },
'PR is not a draft': !pull_request.draft,
// CI state is intentionally *not* a checklist item: auto-merge exists precisely to
// cover unfinished CI, and an already-failed CI is reported via the merge message
// (see merge() below) rather than a blanket refusal.
'PR is not blocked by a "changes requested" review from a [committer](https://github.com/orgs/NixOS/teams/nixpkgs-committers).':
noBlockingReviews,
} }
if (user) { if (user) {
@@ -88,9 +62,8 @@ function runChecklist({
if (allByName) { if (allByName) {
// We can only determine the below, if all packages are in by-name, since // We can only determine the below, if all packages are in by-name, since
// we can't reliably relate changed files to packages outside by-name. // we can't reliably relate changed files to packages outside by-name.
checklist[ checklist[`${user.login} is a maintainer of all touched packages.`] =
`${user.login} is a maintainer of all touched packages on the ${pull_request.base.ref} branch.` eligible.has(user.id)
] = eligible.has(user.id)
} }
} else { } else {
// This is only used when no user is passed, i.e. for labeling. // This is only used when no user is passed, i.e. for labeling.
@@ -119,7 +92,7 @@ function hasMergeCommand(body) {
return (body ?? '') return (body ?? '')
.replace(/<!--.*?-->/gms, '') .replace(/<!--.*?-->/gms, '')
.replace(/(^`{3,})[^`].*?\1/gms, '') .replace(/(^`{3,})[^`].*?\1/gms, '')
.match(/^@NixOS\/nixpkgs-merge-bot merge\s*$/im) .match(/^@NixOS\/nixpkgs-merge-bot merge\s*$/m)
} }
async function handleMergeComment({ github, body, node_id, reaction }) { async function handleMergeComment({ github, body, node_id, reaction }) {
@@ -145,7 +118,6 @@ async function handleMerge({
dry, dry,
pull_request, pull_request,
events, events,
reviews,
maintainers, maintainers,
getTeamMembers, getTeamMembers,
getUser, getUser,
@@ -171,14 +143,6 @@ async function handleMerge({
// including an early exit when the first non-by-name file is found. // including an early exit when the first non-by-name file is found.
if (files.length >= 100) return false if (files.length >= 100) return false
const noPrFailuresState = (
await github.rest.repos.listCommitStatusesForRef({
...context.repo,
ref: pull_request.head.sha,
per_page: 100,
})
).data.find(({ context }) => context === 'no PR failures')?.state
// Only look through comments *after* the latest (force) push. // Only look through comments *after* the latest (force) push.
const lastPush = events.findLastIndex( const lastPush = events.findLastIndex(
({ event, sha, commit_id }) => ({ event, sha, commit_id }) =>
@@ -204,12 +168,10 @@ async function handleMerge({
)), )),
) )
// Returns `{ reaction, messages }`: the reaction to leave on the merge comment and the
// lines to append to the bot's reply. Throws only on an unexpected API error.
async function merge() { async function merge() {
if (dry) { if (dry) {
core.info(`Merging #${pull_number}... (dry)`) core.info(`Merging #${pull_number}... (dry)`)
return { reaction: 'ROCKET', messages: ['Merge completed (dry)'] } return ['Merge completed (dry)']
} }
// Using GraphQL mutations instead of the REST /merge endpoint, because the latter // Using GraphQL mutations instead of the REST /merge endpoint, because the latter
@@ -229,38 +191,16 @@ async function handleMerge({
}`, }`,
{ node_id: pull_request.node_id, sha: pull_request.head.sha }, { node_id: pull_request.node_id, sha: pull_request.head.sha },
) )
log('merge', 'Queued for merge') return [
return { `:heavy_check_mark: [Queued](${resp.enqueuePullRequest.mergeQueueEntry.mergeQueue.url}) for merge (#306934)`,
reaction: 'ROCKET', ]
messages: [
`:heavy_check_mark: [Queued](${resp.enqueuePullRequest.mergeQueueEntry.mergeQueue.url}) for merge (#306934)`,
],
}
} catch (e) { } catch (e) {
log('Enqueuing failed', e.response.errors[0].message) log('Enqueing failed', e.response.errors[0].message)
} }
// Enqueuing fails when the required status checks are not satisfied, yet. If CI has // If required status checks are not satisfied, yet, the above will fail. In this case
// already failed, enabling auto-merge would be pointless: it would never fire, and // we can enable auto-merge. We could also only use auto-merge, but this often gets
// fixing CI requires a new push, which invalidates this merge command anyway (we only // stuck for no apparent reason.
// act on comments after the latest push). So we don't enable auto-merge and instead
// ask for a fresh command once CI is green again.
if (['error', 'failure'].includes(noPrFailuresState)) {
log('merge', 'CI has failed, not enabling auto-merge')
return {
reaction: 'THUMBS_DOWN',
messages: [
':x: Pull Request could not be merged: CI has failed (#305350).',
'',
'> [!TIP]',
'> PRs cannot be merged while CI is failing.',
'> Once CI is passing, comment `@NixOS/nixpkgs-merge-bot merge` again.',
],
}
}
// CI has not finished yet, so we enable auto-merge. We could also only use auto-merge,
// but this often gets stuck for no apparent reason.
try { try {
await github.graphql( await github.graphql(
`mutation($node_id: ID!, $sha: GitObjectID) { `mutation($node_id: ID!, $sha: GitObjectID) {
@@ -272,18 +212,12 @@ async function handleMerge({
}`, }`,
{ node_id: pull_request.node_id, sha: pull_request.head.sha }, { node_id: pull_request.node_id, sha: pull_request.head.sha },
) )
log('merge', 'Auto-merge enabled') return [
return { `:heavy_check_mark: Enabled Auto Merge (#306934)`,
reaction: 'ROCKET', '',
messages: [ '> [!TIP]',
`:heavy_check_mark: Enabled Auto Merge (#306934)`, '> Sometimes GitHub gets stuck after enabling Auto Merge. In this case, leaving another approval should trigger the merge.',
'', ]
'> [!TIP]',
'> [Auto Merge](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/automatically-merging-a-pull-request) will queue this PR once required CI checks succeed.',
'> If CI fails instead, fixing it needs a new push, which disables Auto Merge and invalidates this command — comment `@NixOS/nixpkgs-merge-bot merge` again once CI is green.',
'> If GitHub gets stuck even though CI passed (it sometimes does), leaving another approval should kick off the merge.',
],
}
} catch (e) { } catch (e) {
log('Auto Merge failed', e.response.errors[0].message) log('Auto Merge failed', e.response.errors[0].message)
throw new Error(e.response.errors[0].message) throw new Error(e.response.errors[0].message)
@@ -326,11 +260,11 @@ async function handleMerge({
const { result, eligible, checklist } = runChecklist({ const { result, eligible, checklist } = runChecklist({
committers, committers,
events,
files, files,
pull_request, pull_request,
log, log,
maintainers, maintainers,
reviews,
user: comment.user, user: comment.user,
userIsMaintainer: await isMaintainer(comment.user.login), userIsMaintainer: await isMaintainer(comment.user.login),
}) })
@@ -367,12 +301,10 @@ async function handleMerge({
} }
if (result) { if (result) {
await react('ROCKET')
try { try {
const { reaction, messages } = await merge() body.push(...(await merge()))
await react(reaction)
body.push(...messages)
} catch (e) { } catch (e) {
await react('THUMBS_DOWN')
// Remove the HTML comment with node_id reference to allow retrying this merge on the next run. // Remove the HTML comment with node_id reference to allow retrying this merge on the next run.
body.shift() body.shift()
body.push(`:x: Merge failed with: ${e} (#371492)`) body.push(`:x: Merge failed with: ${e} (#371492)`)
@@ -397,11 +329,11 @@ async function handleMerge({
const { result } = runChecklist({ const { result } = runChecklist({
committers, committers,
events,
files, files,
pull_request, pull_request,
log, log,
maintainers, maintainers,
reviews,
}) })
// Returns a boolean, which indicates whether the PR is merge-bot eligible in principle. // Returns a boolean, which indicates whether the PR is merge-bot eligible in principle.

View File

@@ -4,107 +4,55 @@
"requires": true, "requires": true,
"packages": { "packages": {
"": { "": {
"name": "github-script",
"dependencies": { "dependencies": {
"@actions/artifact": "6.2.1", "@actions/artifact": "5.0.3",
"@actions/core": "1.10.1", "@actions/core": "1.11.1",
"@actions/github": "9.1.0", "@actions/github": "6.0.1",
"bottleneck": "2.19.5", "bottleneck": "2.19.5",
"commander": "14.0.3" "commander": "14.0.3"
} }
}, },
"node_modules/@actions/artifact": { "node_modules/@actions/artifact": {
"version": "6.2.1", "version": "5.0.3",
"resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-6.2.1.tgz", "resolved": "https://registry.npmjs.org/@actions/artifact/-/artifact-5.0.3.tgz",
"integrity": "sha512-sJGH0mhEbEjBCw7o6SaLhUU66u27aFW8HTfkIb5Tk2/Wy0caUDc+oYQEgnuFN7a0HCpAbQyK0U6U7XUJDgDWrw==", "integrity": "sha512-FIEG8Kum0wABZnktJvFi1xuVPc31xrunhZwLCvjrCGISQOm0ifyo7cjqf6PHiEeqoWMa5HIGOsB+lGM4aKCseA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/core": "^3.0.0", "@actions/core": "^2.0.0",
"@actions/github": "^9.0.0", "@actions/github": "^6.0.1",
"@actions/http-client": "^4.0.0", "@actions/http-client": "^3.0.2",
"@azure/storage-blob": "^12.30.0", "@azure/storage-blob": "^12.29.1",
"@octokit/core": "^7.0.6", "@octokit/core": "^5.2.1",
"@octokit/plugin-request-log": "^6.0.0", "@octokit/plugin-request-log": "^1.0.4",
"@octokit/plugin-retry": "^8.0.0", "@octokit/plugin-retry": "^3.0.9",
"@octokit/request": "^10.0.7", "@octokit/request": "^8.4.1",
"@octokit/request-error": "^7.1.0", "@octokit/request-error": "^5.1.1",
"@protobuf-ts/plugin": "^2.2.3-alpha.1", "@protobuf-ts/plugin": "^2.2.3-alpha.1",
"@protobuf-ts/runtime": "^2.9.4",
"archiver": "^7.0.1", "archiver": "^7.0.1",
"jwt-decode": "^4.0.0", "jwt-decode": "^3.1.2",
"unzip-stream": "^0.3.1" "unzip-stream": "^0.3.1"
} }
}, },
"node_modules/@actions/artifact/node_modules/@actions/core": { "node_modules/@actions/artifact/node_modules/@actions/core": {
"version": "3.0.1", "version": "2.0.3",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@actions/core/-/core-2.0.3.tgz",
"integrity": "sha512-a6d/Nwahm9fliVGRhdhofo40HjHQasUPusmc7vBfyky+7Z+P2A1J68zyFVaNcEclc/Se+eO595oAr5nwEIoIUA==", "integrity": "sha512-Od9Thc3T1mQJYddvVPM4QGiLUewdh+3txmDYHHxoNdkqysR1MbCT+rFOtNUxYAz+7+6RIsqipVahY2GJqGPyxA==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/exec": "^3.0.0", "@actions/exec": "^2.0.0",
"@actions/http-client": "^4.0.0" "@actions/http-client": "^3.0.2"
} }
}, },
"node_modules/@actions/artifact/node_modules/@actions/exec": { "node_modules/@actions/artifact/node_modules/@actions/exec": {
"version": "3.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-3.0.0.tgz", "resolved": "https://registry.npmjs.org/@actions/exec/-/exec-2.0.0.tgz",
"integrity": "sha512-6xH/puSoNBXb72VPlZVm7vQ+svQpFyA96qdDBvhB8eNZOE8LtPf9L4oAsfzK/crCL8YZ+19fKYVnM63Sl+Xzlw==", "integrity": "sha512-k8ngrX2voJ/RIN6r9xB82NVqKpnMRtxDoiO+g3olkIUpQNqjArXrCQceduQZCQj3P3xm32pChRLqRrtXTlqhIw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@actions/io": "^3.0.2" "@actions/io": "^2.0.0"
} }
}, },
"node_modules/@actions/artifact/node_modules/@actions/http-client": { "node_modules/@actions/artifact/node_modules/@actions/http-client": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-4.0.1.tgz",
"integrity": "sha512-+Nvd1ImaOZBSoPbsUtEhv+1z99H12xzncCkz0a3RuehINE81FZSe2QTj3uvAPTcJX/SCzUQHQ0D1GrPMbrPitg==",
"license": "MIT",
"dependencies": {
"tunnel": "^0.0.6",
"undici": "^6.23.0"
}
},
"node_modules/@actions/artifact/node_modules/@actions/io": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-3.0.2.tgz",
"integrity": "sha512-nRBchcMM+QK1pdjO7/idu86rbJI5YHUKCvKs0KxnSYbVe3F51UfGxuZX4Qy/fWlp6l7gWFwIkrOzN+oUK03kfw==",
"license": "MIT"
},
"node_modules/@actions/artifact/node_modules/undici": {
"version": "6.25.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz",
"integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==",
"license": "MIT",
"engines": {
"node": ">=18.17"
}
},
"node_modules/@actions/core": {
"version": "1.10.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.10.1.tgz",
"integrity": "sha512-3lBR9EDAY+iYIpTnTIXmWcNbX3T2kCkAEQGIQx4NVQ0575nk2k3GRZDTPQG+vVtS2izSLmINlxXf0uLtnrTP+g==",
"license": "MIT",
"dependencies": {
"@actions/http-client": "^2.0.1",
"uuid": "^8.3.2"
}
},
"node_modules/@actions/github": {
"version": "9.1.0",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-9.1.0.tgz",
"integrity": "sha512-u0hDGQeCS+7VNoLA8hYG65RLdPLMaPGfka0sZ0up7P0AiShqfX6xcuXNteGkQ7X7Tod7AMNwHd4p7DS63i8zzA==",
"license": "MIT",
"dependencies": {
"@actions/http-client": "^3.0.2",
"@octokit/core": "^7.0.6",
"@octokit/plugin-paginate-rest": "^14.0.0",
"@octokit/plugin-rest-endpoint-methods": "^17.0.0",
"@octokit/request": "^10.0.7",
"@octokit/request-error": "^7.1.0",
"undici": "^6.23.0"
}
},
"node_modules/@actions/github/node_modules/@actions/http-client": {
"version": "3.0.2", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-3.0.2.tgz",
"integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==", "integrity": "sha512-JP38FYYpyqvUsz+Igqlc/JG6YO9PaKuvqjM3iGvaLqFnJ7TFmcLyy2IDrY0bI0qCQug8E9K+elv5ZNfw62ZJzA==",
@@ -114,15 +62,115 @@
"undici": "^6.23.0" "undici": "^6.23.0"
} }
}, },
"node_modules/@actions/github/node_modules/undici": { "node_modules/@actions/artifact/node_modules/@actions/io": {
"version": "6.25.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.25.0.tgz", "resolved": "https://registry.npmjs.org/@actions/io/-/io-2.0.0.tgz",
"integrity": "sha512-ZgpWDC5gmNiuY9CnLVXEH8rl50xhRCuLNA97fAUnKi8RRuV4E6KG31pDTsLVUKnohJE0I3XDrTeEydAXRw47xg==", "integrity": "sha512-Jv33IN09XLO+0HS79aaODsvIRyduiF7NY/F6LYeK5oeUmrsz7aFdRphQjFoESF4jS7lMauDOttKALcpapVDIAg==",
"license": "MIT"
},
"node_modules/@actions/artifact/node_modules/undici": {
"version": "6.23.0",
"resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
"integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=18.17" "node": ">=18.17"
} }
}, },
"node_modules/@actions/core": {
"version": "1.11.1",
"resolved": "https://registry.npmjs.org/@actions/core/-/core-1.11.1.tgz",
"integrity": "sha512-hXJCSrkwfA46Vd9Z3q4cpEpHB1rL5NG04+/rbqW9d3+CSvtB1tYe8UTpAlixa1vj0m/ULglfEK2UKxMGxCxv5A==",
"license": "MIT",
"dependencies": {
"@actions/exec": "^1.1.1",
"@actions/http-client": "^2.0.1"
}
},
"node_modules/@actions/exec": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/@actions/exec/-/exec-1.1.1.tgz",
"integrity": "sha512-+sCcHHbVdk93a0XT19ECtO/gIXoxvdsgQLzb2fE2/5sIZmWQuluYyjPQtrtTHdU1YzTZ7bAPN4sITq2xi1679w==",
"license": "MIT",
"dependencies": {
"@actions/io": "^1.0.1"
}
},
"node_modules/@actions/github": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/@actions/github/-/github-6.0.1.tgz",
"integrity": "sha512-xbZVcaqD4XnQAe35qSQqskb3SqIAfRyLBrHMd/8TuL7hJSz2QtbDwnNM8zWx4zO5l2fnGtseNE3MbEvD7BxVMw==",
"license": "MIT",
"dependencies": {
"@actions/http-client": "^2.2.0",
"@octokit/core": "^5.0.1",
"@octokit/plugin-paginate-rest": "^9.2.2",
"@octokit/plugin-rest-endpoint-methods": "^10.4.0",
"@octokit/request": "^8.4.1",
"@octokit/request-error": "^5.1.1",
"undici": "^5.28.5"
}
},
"node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest": {
"version": "9.2.2",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-9.2.2.tgz",
"integrity": "sha512-u3KYkGF7GcZnSD/3UP0S7K5XUFT2FkOQdcfXZGZQPGv3lm4F2Xbf71lvjldr8c1H3nNbF+33cLEkWYbokGWqiQ==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^12.6.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": "5"
}
},
"node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/openapi-types": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
"license": "MIT"
},
"node_modules/@actions/github/node_modules/@octokit/plugin-paginate-rest/node_modules/@octokit/types": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^20.0.0"
}
},
"node_modules/@actions/github/node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "10.4.1",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-10.4.1.tgz",
"integrity": "sha512-xV1b+ceKV9KytQe3zCVqjg+8GTGfDYwaT1ATU5isiUyVtlVAO3HNdzpS4sr4GBx4hxQ46s7ITtZrAsxG22+rVg==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^12.6.0"
},
"engines": {
"node": ">= 18"
},
"peerDependencies": {
"@octokit/core": "5"
}
},
"node_modules/@actions/github/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/openapi-types": {
"version": "20.0.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-20.0.0.tgz",
"integrity": "sha512-EtqRBEjp1dL/15V7WiX5LJMIxxkdiGJnabzYx5Apx4FkQIFgAfKumXeYAqqJCj1s+BMX4cPFIFC4OLCR6stlnA==",
"license": "MIT"
},
"node_modules/@actions/github/node_modules/@octokit/plugin-rest-endpoint-methods/node_modules/@octokit/types": {
"version": "12.6.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-12.6.0.tgz",
"integrity": "sha512-1rhSOfRa6H9w4YwK0yrf5faDaDTb+yLyBUKOCV4xtCDB5VmIPqd/v9yr9o6SAzOAlRxMiRiCic6JVM1/kunVkw==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^20.0.0"
}
},
"node_modules/@actions/http-client": { "node_modules/@actions/http-client": {
"version": "2.2.3", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz", "resolved": "https://registry.npmjs.org/@actions/http-client/-/http-client-2.2.3.tgz",
@@ -133,6 +181,12 @@
"undici": "^5.25.4" "undici": "^5.25.4"
} }
}, },
"node_modules/@actions/io": {
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/@actions/io/-/io-1.1.3.tgz",
"integrity": "sha512-wi9JjgKLYS7U/z8PPbco+PvTb/nRWjeoFlJ1Qer83k/3C5PHQi28hiVdeE2kHXmIL99mQFawx8qt/JPjZilJ8Q==",
"license": "MIT"
},
"node_modules/@azure/abort-controller": { "node_modules/@azure/abort-controller": {
"version": "2.1.2", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz",
@@ -164,6 +218,7 @@
"resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz", "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.10.1.tgz",
"integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==", "integrity": "sha512-Nh5PhEOeY6PrnxNPsEHRr9eimxLwgLlpmguQaHKBinFYA/RU9+kOYVOQqOrTsCL+KSxrLLl1gD8Dk5BFW/7l/w==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@azure/abort-controller": "^2.1.2", "@azure/abort-controller": "^2.1.2",
"@azure/core-auth": "^1.10.0", "@azure/core-auth": "^1.10.0",
@@ -225,6 +280,7 @@
"resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.2.tgz", "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.22.2.tgz",
"integrity": "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==", "integrity": "sha512-MzHym+wOi8CLUlKCQu12de0nwcq9k9Kuv43j4Wa++CsCpJwps2eeBQwD2Bu8snkxTtDKDx4GwjuR9E8yC8LNrg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@azure/abort-controller": "^2.1.2", "@azure/abort-controller": "^2.1.2",
"@azure/core-auth": "^1.10.0", "@azure/core-auth": "^1.10.0",
@@ -391,174 +447,197 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/@nodable/entities": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/@nodable/entities/-/entities-2.1.0.tgz",
"integrity": "sha512-nyT7T3nbMyBI/lvr6L5TyWbFJAI9FTgVRakNoBqCD+PmID8DzFrrNdLLtHMwMszOtqZa8PAOV24ZqDnQrhQINA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/nodable"
}
],
"license": "MIT"
},
"node_modules/@octokit/auth-token": { "node_modules/@octokit/auth-token": {
"version": "6.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-6.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-4.0.0.tgz",
"integrity": "sha512-P4YJBPdPSpWTQ1NU4XYdvHvXJJDxM6YwpS0FZHRgP7YFkdVxsWcpWGy/NVqlAA7PcPCnMacXlRm1y2PFZRWL/w==", "integrity": "sha512-tY/msAuJo6ARbK6SPIxZrPBms3xPbfwBrulZe0Wtr/DIY9lje2HeV1uoebShn6mx7SjCHif6EjMvoREj+gZ+SA==",
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">= 20" "node": ">= 18"
} }
}, },
"node_modules/@octokit/core": { "node_modules/@octokit/core": {
"version": "7.0.6", "version": "5.2.2",
"resolved": "https://registry.npmjs.org/@octokit/core/-/core-7.0.6.tgz", "resolved": "https://registry.npmjs.org/@octokit/core/-/core-5.2.2.tgz",
"integrity": "sha512-DhGl4xMVFGVIyMwswXeyzdL4uXD5OGILGX5N8Y+f6W7LhC1Ze2poSNrkF/fedpVDHEEZ+PHFW0vL14I+mm8K3Q==", "integrity": "sha512-/g2d4sW9nUDJOMz3mabVQvOGhVa4e/BN/Um7yca9Bb2XTzPPnfTWHWQg+IsEYO7M3Vx+EXvaM/I2pJWIMun1bg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"@octokit/auth-token": "^6.0.0", "@octokit/auth-token": "^4.0.0",
"@octokit/graphql": "^9.0.3", "@octokit/graphql": "^7.1.0",
"@octokit/request": "^10.0.6", "@octokit/request": "^8.4.1",
"@octokit/request-error": "^7.0.2", "@octokit/request-error": "^5.1.1",
"@octokit/types": "^16.0.0", "@octokit/types": "^13.0.0",
"before-after-hook": "^4.0.0", "before-after-hook": "^2.2.0",
"universal-user-agent": "^7.0.0" "universal-user-agent": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">= 20" "node": ">= 18"
}
},
"node_modules/@octokit/core/node_modules/@octokit/openapi-types": {
"version": "24.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
"license": "MIT"
},
"node_modules/@octokit/core/node_modules/@octokit/types": {
"version": "13.10.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^24.2.0"
} }
}, },
"node_modules/@octokit/endpoint": { "node_modules/@octokit/endpoint": {
"version": "11.0.3", "version": "9.0.6",
"resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-11.0.3.tgz", "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-9.0.6.tgz",
"integrity": "sha512-FWFlNxghg4HrXkD3ifYbS/IdL/mDHjh9QcsNyhQjN8dplUoZbejsdpmuqdA76nxj2xoWPs7p8uX2SNr9rYu0Ag==", "integrity": "sha512-H1fNTMA57HbkFESSt3Y9+FBICv+0jFceJFPWDePYlR/iMGrwM5ph+Dd4XRQs+8X+PUFURLQgX9ChPfhJ/1uNQw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/types": "^16.0.0", "@octokit/types": "^13.1.0",
"universal-user-agent": "^7.0.2" "universal-user-agent": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">= 20" "node": ">= 18"
}
},
"node_modules/@octokit/endpoint/node_modules/@octokit/openapi-types": {
"version": "24.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
"license": "MIT"
},
"node_modules/@octokit/endpoint/node_modules/@octokit/types": {
"version": "13.10.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^24.2.0"
} }
}, },
"node_modules/@octokit/graphql": { "node_modules/@octokit/graphql": {
"version": "9.0.3", "version": "7.1.1",
"resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-9.0.3.tgz", "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-7.1.1.tgz",
"integrity": "sha512-grAEuupr/C1rALFnXTv6ZQhFuL1D8G5y8CN04RgrO4FIPMrtm+mcZzFG7dcBm+nq+1ppNixu+Jd78aeJOYxlGA==", "integrity": "sha512-3mkDltSfcDUoa176nlGoA32RGjeWjl3K7F/BwHwRMJUW/IteSa4bnSV8p2ThNkcIcZU2umkZWxwETSSCJf2Q7g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/request": "^10.0.6", "@octokit/request": "^8.4.1",
"@octokit/types": "^16.0.0", "@octokit/types": "^13.0.0",
"universal-user-agent": "^7.0.0" "universal-user-agent": "^6.0.0"
}, },
"engines": { "engines": {
"node": ">= 20" "node": ">= 18"
}
},
"node_modules/@octokit/graphql/node_modules/@octokit/openapi-types": {
"version": "24.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
"license": "MIT"
},
"node_modules/@octokit/graphql/node_modules/@octokit/types": {
"version": "13.10.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^24.2.0"
} }
}, },
"node_modules/@octokit/openapi-types": { "node_modules/@octokit/openapi-types": {
"version": "27.0.0", "version": "12.11.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-27.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz",
"integrity": "sha512-whrdktVs1h6gtR+09+QsNk2+FO+49j6ga1c55YZudfEG+oKJVvJLQi3zkOm5JjiUXAagWK2tI2kTGKJ2Ys7MGA==", "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/@octokit/plugin-paginate-rest": {
"version": "14.0.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-14.0.0.tgz",
"integrity": "sha512-fNVRE7ufJiAA3XUrha2omTA39M6IXIc6GIZLvlbsm8QOQCYvpq/LkMNGyFlB1d8hTDzsAXa3OKtybdMAYsV/fw==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^16.0.0"
},
"engines": {
"node": ">= 20"
},
"peerDependencies": {
"@octokit/core": ">=6"
}
},
"node_modules/@octokit/plugin-request-log": { "node_modules/@octokit/plugin-request-log": {
"version": "6.0.0", "version": "1.0.4",
"resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-6.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/plugin-request-log/-/plugin-request-log-1.0.4.tgz",
"integrity": "sha512-UkOzeEN3W91/eBq9sPZNQ7sUBvYCqYbrrD8gTbBuGtHEuycE4/awMXcYvx6sVYo7LypPhmQwwpUe4Yyu4QZN5Q==", "integrity": "sha512-mLUsMkgP7K/cnFEw07kWqXGF5LKrOkD+lhCrKvPHXWDywAwuDUeDwWBpc69XK3pNX0uKiVt8g5z96PJ6z9xCFA==",
"license": "MIT", "license": "MIT",
"engines": {
"node": ">= 20"
},
"peerDependencies": { "peerDependencies": {
"@octokit/core": ">=6" "@octokit/core": ">=3"
}
},
"node_modules/@octokit/plugin-rest-endpoint-methods": {
"version": "17.0.0",
"resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-17.0.0.tgz",
"integrity": "sha512-B5yCyIlOJFPqUUeiD0cnBJwWJO8lkJs5d8+ze9QDP6SvfiXSz1BF+91+0MeI1d2yxgOhU/O+CvtiZ9jSkHhFAw==",
"license": "MIT",
"dependencies": {
"@octokit/types": "^16.0.0"
},
"engines": {
"node": ">= 20"
},
"peerDependencies": {
"@octokit/core": ">=6"
} }
}, },
"node_modules/@octokit/plugin-retry": { "node_modules/@octokit/plugin-retry": {
"version": "8.1.0", "version": "3.0.9",
"resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-8.1.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/plugin-retry/-/plugin-retry-3.0.9.tgz",
"integrity": "sha512-O1FZgXeiGb2sowEr/hYTr6YunGdSAFWnr2fyW39Ah85H8O33ELASQxcvOFF5LE6Tjekcyu2ms4qAzJVhSaJxTw==", "integrity": "sha512-r+fArdP5+TG6l1Rv/C9hVoty6tldw6cE2pRHNGmFPdyfrc696R6JjrQ3d7HdVqGwuzfyrcaLAKD7K8TX8aehUQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/request-error": "^7.0.2", "@octokit/types": "^6.0.3",
"@octokit/types": "^16.0.0",
"bottleneck": "^2.15.3" "bottleneck": "^2.15.3"
},
"engines": {
"node": ">= 20"
},
"peerDependencies": {
"@octokit/core": ">=7"
} }
}, },
"node_modules/@octokit/request": { "node_modules/@octokit/request": {
"version": "10.0.9", "version": "8.4.1",
"resolved": "https://registry.npmjs.org/@octokit/request/-/request-10.0.9.tgz", "resolved": "https://registry.npmjs.org/@octokit/request/-/request-8.4.1.tgz",
"integrity": "sha512-o8Bi3f608eyM+7BmBiUWxFsdjLb3/ym1cQek5LZOv9KkZcxRrHCPhhRzm6xjO6HVZ85ItD6+sTsjxo821SVa/A==", "integrity": "sha512-qnB2+SY3hkCmBxZsR/MPCybNmbJe4KAlfWErXq+rBKkQJlbjdJeS85VI9r8UqeLYLvnAenU8Q1okM/0MBsAGXw==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/endpoint": "^11.0.3", "@octokit/endpoint": "^9.0.6",
"@octokit/request-error": "^7.0.2", "@octokit/request-error": "^5.1.1",
"@octokit/types": "^16.0.0", "@octokit/types": "^13.1.0",
"content-type": "^2.0.0", "universal-user-agent": "^6.0.0"
"fast-content-type-parse": "^3.0.0",
"json-with-bigint": "^3.5.3",
"universal-user-agent": "^7.0.2"
}, },
"engines": { "engines": {
"node": ">= 20" "node": ">= 18"
} }
}, },
"node_modules/@octokit/request-error": { "node_modules/@octokit/request-error": {
"version": "7.1.0", "version": "5.1.1",
"resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-7.1.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-5.1.1.tgz",
"integrity": "sha512-KMQIfq5sOPpkQYajXHwnhjCC0slzCNScLHs9JafXc4RAJI+9f+jNDlBNaIMTvazOPLgb4BnlhGJOTbnN0wIjPw==", "integrity": "sha512-v9iyEQJH6ZntoENr9/yXxjuezh4My67CBSu9r6Ve/05Iu5gNgnisNWOsoJHTP6k0Rr0+HQIpnH+kyammu90q/g==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/types": "^16.0.0" "@octokit/types": "^13.1.0",
"deprecation": "^2.0.0",
"once": "^1.4.0"
}, },
"engines": { "engines": {
"node": ">= 20" "node": ">= 18"
}
},
"node_modules/@octokit/request-error/node_modules/@octokit/openapi-types": {
"version": "24.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
"license": "MIT"
},
"node_modules/@octokit/request-error/node_modules/@octokit/types": {
"version": "13.10.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^24.2.0"
}
},
"node_modules/@octokit/request/node_modules/@octokit/openapi-types": {
"version": "24.2.0",
"resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-24.2.0.tgz",
"integrity": "sha512-9sIH3nSUttelJSXUrmGzl7QUBFul0/mB8HRYl3fOlgHbIWG+WnYDXU3v/2zMtAvuzZ/ed00Ei6on975FhBfzrg==",
"license": "MIT"
},
"node_modules/@octokit/request/node_modules/@octokit/types": {
"version": "13.10.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-13.10.0.tgz",
"integrity": "sha512-ifLaO34EbbPj0Xgro4G5lP5asESjwHracYJvVaPIyXMuiuXLlhic3S47cBdTb+jfODkTE5YtGCLt3Ay3+J97sA==",
"license": "MIT",
"dependencies": {
"@octokit/openapi-types": "^24.2.0"
} }
}, },
"node_modules/@octokit/types": { "node_modules/@octokit/types": {
"version": "16.0.0", "version": "6.41.0",
"resolved": "https://registry.npmjs.org/@octokit/types/-/types-16.0.0.tgz", "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz",
"integrity": "sha512-sKq+9r1Mm4efXW1FCk7hFSeJo4QKreL/tTbR0rz/qx/r1Oa2VV83LTA/H/MuCOX7uCIJmQVRKBcbmWoySjAnSg==", "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@octokit/openapi-types": "^27.0.0" "@octokit/openapi-types": "^12.11.0"
} }
}, },
"node_modules/@pkgjs/parseargs": { "node_modules/@pkgjs/parseargs": {
@@ -766,9 +845,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/before-after-hook": { "node_modules/before-after-hook": {
"version": "4.0.0", "version": "2.2.3",
"resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-4.0.0.tgz", "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz",
"integrity": "sha512-q6tR3RPqIB1pMiTRMFcZwuG5T8vwp+vUvEG0vuI6B+Rikh5BfPp2fQ82c925FOs+b0lcFQ8CFrL+KbilfZFhOQ==", "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==",
"license": "Apache-2.0" "license": "Apache-2.0"
}, },
"node_modules/binary": { "node_modules/binary": {
@@ -791,9 +870,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/brace-expansion": { "node_modules/brace-expansion": {
"version": "2.1.0", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
"integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==", "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"balanced-match": "^1.0.0" "balanced-match": "^1.0.0"
@@ -895,19 +974,6 @@
"node": ">= 14" "node": ">= 14"
} }
}, },
"node_modules/content-type": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/content-type/-/content-type-2.0.0.tgz",
"integrity": "sha512-j/O/d7GcZCyNl7/hwZAb606rzqkyvaDctLmckbxLzHvFBzTJHuGEdodATcP3yIRoDrLHkIATJuvzbFlp/ki2cQ==",
"license": "MIT",
"engines": {
"node": ">=18"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/express"
}
},
"node_modules/core-util-is": { "node_modules/core-util-is": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
@@ -970,6 +1036,12 @@
} }
} }
}, },
"node_modules/deprecation": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz",
"integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==",
"license": "ISC"
},
"node_modules/eastasianwidth": { "node_modules/eastasianwidth": {
"version": "0.2.0", "version": "0.2.0",
"resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
@@ -1000,48 +1072,16 @@
"node": ">=0.8.x" "node": ">=0.8.x"
} }
}, },
"node_modules/fast-content-type-parse": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/fast-content-type-parse/-/fast-content-type-parse-3.0.0.tgz",
"integrity": "sha512-ZvLdcY8P+N8mGQJahJV5G4U88CSvT1rP8ApL6uETe88MBXrBHAkZlSEySdUlyztF7ccb+Znos3TFqaepHxdhBg==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fastify"
},
{
"type": "opencollective",
"url": "https://opencollective.com/fastify"
}
],
"license": "MIT"
},
"node_modules/fast-fifo": { "node_modules/fast-fifo": {
"version": "1.3.2", "version": "1.3.2",
"resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz",
"integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==", "integrity": "sha512-/d9sfos4yxzpwkDkuN7k2SqFKtYNmCTzgfEpz82x34IM9/zc8KGxQoXg1liNC/izpRM/MBdt44Nmx41ZWqk+FQ==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/fast-xml-builder": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/fast-xml-builder/-/fast-xml-builder-1.2.0.tgz",
"integrity": "sha512-00aAWieqff+ZJhsXA4g1g7M8k+7AYoMUUHF+/zFb5U6Uv/P0Vl4QZo84/IcufzYalLuEj9928bXN9PbbFzMF0Q==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"license": "MIT",
"dependencies": {
"path-expression-matcher": "^1.5.0",
"xml-naming": "^0.1.0"
}
},
"node_modules/fast-xml-parser": { "node_modules/fast-xml-parser": {
"version": "5.8.0", "version": "5.3.6",
"resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.8.0.tgz", "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.3.6.tgz",
"integrity": "sha512-6bIM7fsJxeo3uXv7OncQYsBAMPJ7V16Slahl/6M98C/i2q+vB1+4a0MtrvYwDFEUrwDSbAmeLDRXsOBwrL7yAg==", "integrity": "sha512-QNI3sAvSvaOiaMl8FYU4trnEzCwiRr8XMWgAHzlrWpTSj+QaCSvOf1h82OEP1s4hiAXhnbXSyFWCf4ldZzZRVA==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -1050,11 +1090,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@nodable/entities": "^2.1.0", "strnum": "^2.1.2"
"fast-xml-builder": "^1.2.0",
"path-expression-matcher": "^1.5.0",
"strnum": "^2.3.0",
"xml-naming": "^0.1.0"
}, },
"bin": { "bin": {
"fxparser": "src/cli/cli.js" "fxparser": "src/cli/cli.js"
@@ -1203,20 +1239,11 @@
"@pkgjs/parseargs": "^0.11.0" "@pkgjs/parseargs": "^0.11.0"
} }
}, },
"node_modules/json-with-bigint": {
"version": "3.5.8",
"resolved": "https://registry.npmjs.org/json-with-bigint/-/json-with-bigint-3.5.8.tgz",
"integrity": "sha512-eq/4KP6K34kwa7TcFdtvnftvHCD9KvHOGGICWwMFc4dOOKF5t4iYqnfLK8otCRCRv06FXOzGGyqE8h8ElMvvdw==",
"license": "MIT"
},
"node_modules/jwt-decode": { "node_modules/jwt-decode": {
"version": "4.0.0", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-4.0.0.tgz", "resolved": "https://registry.npmjs.org/jwt-decode/-/jwt-decode-3.1.2.tgz",
"integrity": "sha512-+KJGIyHgkGuIq3IEBNftfhW/LfWhXUIY6OmyVWjliu5KH1y0fw7VQ8YndE2O4qZdMSd9SqbnC8GOcZEy0Om7sA==", "integrity": "sha512-UfpWE/VZn0iP50d8cz9NrZLM9lSWhcJ+0Gt/nm4by88UL+J1SiKN8/5dkjMmbEzwL2CAe+67GsegCbIKtbp75A==",
"license": "MIT", "license": "MIT"
"engines": {
"node": ">=18"
}
}, },
"node_modules/lazystream": { "node_modules/lazystream": {
"version": "1.0.1", "version": "1.0.1",
@@ -1261,9 +1288,9 @@
} }
}, },
"node_modules/lodash": { "node_modules/lodash": {
"version": "4.18.1", "version": "4.17.23",
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
"integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==", "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/lru-cache": { "node_modules/lru-cache": {
@@ -1273,12 +1300,12 @@
"license": "ISC" "license": "ISC"
}, },
"node_modules/minimatch": { "node_modules/minimatch": {
"version": "9.0.9", "version": "9.0.5",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.9.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
"integrity": "sha512-OBwBN9AL4dqmETlpS2zasx+vTeWclWzkblfZk7KTA5j3jeOONz/tRCnZomUyvNg83wL5Zv9Ss6HMJXAgL8R2Yg==", "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.2" "brace-expansion": "^2.0.1"
}, },
"engines": { "engines": {
"node": ">=16 || 14 >=14.17" "node": ">=16 || 14 >=14.17"
@@ -1332,27 +1359,21 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
"integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
"license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
"node_modules/package-json-from-dist": { "node_modules/package-json-from-dist": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
"integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
"license": "BlueOak-1.0.0" "license": "BlueOak-1.0.0"
}, },
"node_modules/path-expression-matcher": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/path-expression-matcher/-/path-expression-matcher-1.5.0.tgz",
"integrity": "sha512-cbrerZV+6rvdQrrD+iGMcZFEiiSrbv9Tfdkvnusy6y0x0GKBXREFg/Y65GhIfm0tnLntThhzCnfKwp1WRjeCyQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"license": "MIT",
"engines": {
"node": ">=14.0.0"
}
},
"node_modules/path-key": { "node_modules/path-key": {
"version": "3.1.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
@@ -1419,9 +1440,9 @@
} }
}, },
"node_modules/readdir-glob/node_modules/minimatch": { "node_modules/readdir-glob/node_modules/minimatch": {
"version": "5.1.9", "version": "5.1.6",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.9.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
"integrity": "sha512-7o1wEA2RyMP7Iu7GNba9vc0RWWGACJOCZBJX2GJWip0ikV+wcOsgVuY9uE8CPiyQhkGFSlhuSkZPavN7u1c2Fw==", "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
"license": "ISC", "license": "ISC",
"dependencies": { "dependencies": {
"brace-expansion": "^2.0.1" "brace-expansion": "^2.0.1"
@@ -1602,9 +1623,9 @@
} }
}, },
"node_modules/strnum": { "node_modules/strnum": {
"version": "2.3.0", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/strnum/-/strnum-2.3.0.tgz", "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz",
"integrity": "sha512-ums3KNd42PGyx5xaoVTO1mjU1bH3NpY4vsrVlnv9PNGqQj8wd7rJ6nEypLrJ7z5vxK5RP0yMLo6J/Gsm62DI5Q==", "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==",
"funding": [ "funding": [
{ {
"type": "github", "type": "github",
@@ -1662,6 +1683,7 @@
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
"license": "Apache-2.0", "license": "Apache-2.0",
"peer": true,
"bin": { "bin": {
"tsc": "bin/tsc", "tsc": "bin/tsc",
"tsserver": "bin/tsserver" "tsserver": "bin/tsserver"
@@ -1683,9 +1705,9 @@
} }
}, },
"node_modules/universal-user-agent": { "node_modules/universal-user-agent": {
"version": "7.0.3", "version": "6.0.1",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz", "resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-6.0.1.tgz",
"integrity": "sha512-TmnEAEAsBJVZM/AADELsK76llnwcf9vMKuPz8JflO1frO8Lchitr0fNaN9d+Ap0BjKtqWqd/J17qeDnXh8CL2A==", "integrity": "sha512-yCzhz6FN2wU1NiiQRogkTQszlQSlpWaw8SvVegAc+bDxbzHgh1vX8uIe8OYyMH6DwH+sdTJsgMl36+mSMdRJIQ==",
"license": "ISC" "license": "ISC"
}, },
"node_modules/unzip-stream": { "node_modules/unzip-stream": {
@@ -1704,16 +1726,6 @@
"integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
"license": "MIT" "license": "MIT"
}, },
"node_modules/uuid": {
"version": "8.3.2",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
"integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
"deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
"license": "MIT",
"bin": {
"uuid": "dist/bin/uuid"
}
},
"node_modules/which": { "node_modules/which": {
"version": "2.0.2", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
@@ -1820,20 +1832,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/xml-naming": { "node_modules/wrappy": {
"version": "0.1.0", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/xml-naming/-/xml-naming-0.1.0.tgz", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-k8KO9hrMyNk6tUWqUfkTEZbezRRpONVOzUTnc97VnCvyj6Tf9lyUR9EDAIeiVLv56jsMcoXEwjW8Kv5yPY52lw==", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
"funding": [ "license": "ISC"
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
}
],
"license": "MIT",
"engines": {
"node": ">=16.0.0"
}
}, },
"node_modules/zip-stream": { "node_modules/zip-stream": {
"version": "6.0.1", "version": "6.0.1",

View File

@@ -7,9 +7,9 @@
"`.github/workflows/bot.yml`." "`.github/workflows/bot.yml`."
], ],
"dependencies": { "dependencies": {
"@actions/artifact": "6.2.1", "@actions/artifact": "5.0.3",
"@actions/core": "1.10.1", "@actions/core": "1.11.1",
"@actions/github": "9.1.0", "@actions/github": "6.0.1",
"bottleneck": "2.19.5", "bottleneck": "2.19.5",
"commander": "14.0.3" "commander": "14.0.3"
} }

View File

@@ -1,7 +1,6 @@
const { classify } = require('../supportedBranches.js') const { classify } = require('../supportedBranches.js')
const { postReview, dismissReviews } = require('./reviews.js') const { postReview, dismissReviews } = require('./reviews.js')
const reviewKey = 'prepare' const reviewKey = 'prepare'
const supportedSystems = require('./supportedSystems.js')
module.exports = async ({ github, context, core, dry }) => { module.exports = async ({ github, context, core, dry }) => {
const pull_number = context.payload.pull_request.number const pull_number = context.payload.pull_request.number
@@ -172,20 +171,14 @@ module.exports = async ({ github, context, core, dry }) => {
' ```', ' ```',
].join('\n') ].join('\n')
await postReview({ await postReview({ github, context, core, dry, body, reviewKey })
github,
context, throw new Error(`The PR contains commits from a different base.`)
core,
dry,
body,
event: 'REQUEST_CHANGES',
reviewKey,
})
} else {
await dismissReviews({ github, context, core, dry, reviewKey })
} }
} }
await dismissReviews({ github, context, core, dry, reviewKey })
let mergedSha, targetSha let mergedSha, targetSha
if (prInfo.mergeable) { if (prInfo.mergeable) {
@@ -216,8 +209,7 @@ module.exports = async ({ github, context, core, dry }) => {
core.setOutput('mergedSha', mergedSha) core.setOutput('mergedSha', mergedSha)
core.setOutput('targetSha', targetSha) core.setOutput('targetSha', targetSha)
const systems = await supportedSystems({ github, context, targetSha }) core.setOutput('systems', require('../supportedSystems.json'))
core.setOutput('systems', systems)
const files = ( const files = (
await github.paginate(github.rest.pulls.listFiles, { await github.paginate(github.rest.pulls.listFiles, {

View File

@@ -5,28 +5,10 @@ const eventToState = {
REQUEST_CHANGES: 'CHANGES_REQUESTED', REQUEST_CHANGES: 'CHANGES_REQUESTED',
} }
// Use substring checks in order to allow testing in forks
// Usernames must also end in "[bot]"
const reviewUsers = [
'github-actions',
'nixpkgs-ci',
'branch-check',
'commit-check',
'manual-edit',
]
/**
* @typedef {InstanceType<import('@actions/github/lib/utils').GitHub>} GitHub
* @typedef {typeof import('@actions/github').context} Context
*
* @typedef {Awaited<ReturnType<GitHub['rest']['pulls']['listReviews']>>['data'][number]} Review
* @typedef {Review & { user: NonNullable<Review['user']> }} ReviewWithNonNullUser
*/
/** /**
* @param {{ * @param {{
* github: GitHub, * github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: Context, * context: import('@actions/github/lib/context').Context,
* core: import('@actions/core'), * core: import('@actions/core'),
* dry: boolean, * dry: boolean,
* reviewKey?: string, * reviewKey?: string,
@@ -43,32 +25,18 @@ async function dismissReviews({ github, context, core, dry, reviewKey }) {
return return
} }
const allReviews = await github.paginate(github.rest.pulls.listReviews, { const reviews = (
...context.repo, await github.paginate(github.rest.pulls.listReviews, {
pull_number, ...context.repo,
}) pull_number,
})
const reviews = /** @type {ReviewWithNonNullUser[]} */ ( ).filter(
allReviews.filter( (review) =>
(review) => review.user?.login === 'github-actions[bot]' &&
review.user && review.state !== 'DISMISSED',
review.state !== 'DISMISSED' &&
review.user.login.endsWith('[bot]') &&
reviewUsers.some((substr) => review.user?.login.includes(substr)),
)
) )
const changesRequestedReviews = reviews.filter(
const reviewsByUser = reviews.reduce( (review) => review.state === 'CHANGES_REQUESTED',
(prev, curr) => {
if (!(curr.user.login in prev)) {
prev[curr.user.login] = []
}
prev[curr.user.login].push(curr)
return prev
},
/** @type {Record<string, ReviewWithNonNullUser[]> } */ ({}),
) )
const commentRegex = new RegExp( const commentRegex = new RegExp(
@@ -82,8 +50,8 @@ async function dismissReviews({ github, context, core, dry, reviewKey }) {
) )
let reviewsToMinimize = reviews let reviewsToMinimize = reviews
const /** @type {ReviewWithNonNullUser[]} */ reviewsToDismiss = [] let /** @type {typeof reviews} */ reviewsToDismiss = []
const /** @type {ReviewWithNonNullUser[]} */ reviewsToResolve = [] let /** @type {typeof reviews} */ reviewsToResolve = []
if (reviewKey && reviews.every((review) => commentRegex.test(review.body))) { if (reviewKey && reviews.every((review) => commentRegex.test(review.body))) {
reviewsToMinimize = reviews.filter((review) => reviewsToMinimize = reviews.filter((review) =>
@@ -91,39 +59,29 @@ async function dismissReviews({ github, context, core, dry, reviewKey }) {
) )
} }
for (const reviewsForUser of Object.values(reviewsByUser)) { // If we want to dismiss all reviews with the key reviewKey,
// Make sure that we don't dismiss all reviews by a user if they // but there are other requested changes from CI, we can't dismiss,
// have any reviews we don't want to dismiss. // because then the other requested changes will be dismissed too.
if ( if (
reviewsForUser.every( changesRequestedReviews.every(
(review) => (review) =>
commentResolvedRegex.test(review.body) || commentResolvedRegex.test(review.body) ||
(reviewKey && reviewKeyRegex.test(review.body)) || (reviewKey && reviewKeyRegex.test(review.body)) ||
// If we are called by check-commits and the review body is clearly // If we are called by check-commits and the review body is clearly
// from `commits.js`, then we can safely dismiss the review. // from `commits.js`, then we can safely dismiss the review.
// This helps with pre-existing reviews (before the comments were added). // This helps with pre-existing reviews (before the comments were added).
(reviewKey && (reviewKey &&
reviewKey === 'check-commits' && reviewKey === 'check-commits' &&
review.body.includes('PR / Check / cherry-pick')), review.body.includes('PR / Check / cherry-pick')),
) )
) { ) {
reviewsToDismiss.push( reviewsToDismiss = changesRequestedReviews
...reviewsForUser.filter( } else if (reviewsToMinimize.length) {
(review) => review.state === 'CHANGES_REQUESTED', reviewsToResolve = reviewsToMinimize.filter(
), (review) =>
) review.state === 'CHANGES_REQUESTED' &&
} else { !commentResolvedRegex.test(review.body),
reviewsToResolve.push( )
...reviewsForUser.filter(
(review) =>
review.state === 'CHANGES_REQUESTED' &&
!commentResolvedRegex.test(review.body) &&
reviewsToMinimize.some(
(toMinimize) => toMinimize.node_id === review.node_id,
),
),
)
}
} }
await Promise.all([ await Promise.all([
@@ -163,8 +121,8 @@ async function dismissReviews({ github, context, core, dry, reviewKey }) {
/** /**
* @param {{ * @param {{
* github: GitHub, * github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: Context, * context: import('@actions/github/lib/context').Context
* core: import('@actions/core'), * core: import('@actions/core'),
* dry: boolean, * dry: boolean,
* body: string, * body: string,
@@ -200,13 +158,11 @@ async function postReview({
}) })
).filter( ).filter(
(review) => (review) =>
review.user && review.user?.login === 'github-actions[bot]' &&
review.state !== 'DISMISSED' && review.state !== 'DISMISSED',
review.user.login.endsWith('[bot]') &&
reviewUsers.some((substr) => review.user?.login.includes(substr)),
) )
/** @type {null | Review} */ /** @type {null | typeof reviews[number]} */
let pendingReview let pendingReview
const matchingReviews = reviews.filter((review) => const matchingReviews = reviews.filter((review) =>
reviewKeyRegex.test(review.body), reviewKeyRegex.test(review.body),

View File

@@ -116,15 +116,4 @@ program
await run(checkCommitMessages, owner, repo, pr, options) await run(checkCommitMessages, owner, repo, pr, options)
}) })
program
.command('manual-file-edits')
.description("Error when files that shouldn't be edited manually are")
.argument('<owner>', 'Owner of the GitHub repository to run on (Example: NixOS)')
.argument('<repo>', 'Name of the GitHub repository to run on (Example: nixpkgs)')
.argument('<pr>', 'Number of the Pull Request to run on')
.action(async (owner, repo, pr, options) => {
const checkManualFileEdits = (await import('./manual-file-edits.js')).default
await run(checkManualFileEdits, owner, repo, pr, options)
})
await program.parse() await program.parse()

View File

@@ -1,10 +0,0 @@
module.exports = async ({ github, context, targetSha }) => {
const { content, encoding } = (
await github.rest.repos.getContent({
...context.repo,
path: 'pkgs/top-level/release-supported-systems.json',
ref: targetSha,
})
).data
return JSON.parse(Buffer.from(content, encoding).toString())
}

View File

@@ -28,14 +28,7 @@ runCommand "nix-parse-${nix.name}"
# the other CI jobs will report in more detail. This job is about checking parsing # the other CI jobs will report in more detail. This job is about checking parsing
# across different implementations / versions, not about providing the best DX. # across different implementations / versions, not about providing the best DX.
# Returning all parse errors requires significantly more resources. # Returning all parse errors requires significantly more resources.
find . -type f -iname '*.nix' | xargs -P $(nproc) nix-instantiate --parse >/dev/null
find . -type f -iname '*.nix' | xargs -P $(nproc) nix-instantiate --parse 2>&1 >/dev/null | {
# Also fail on (deprecation) warnings printed to stderr.
if grep "warning"; then
echo "Failing due to warnings in stderr" >&2
exit 1
fi
}
touch $out touch $out
'' ''

View File

@@ -9,10 +9,23 @@
}, },
"branch": "nixpkgs-unstable", "branch": "nixpkgs-unstable",
"submodules": false, "submodules": false,
"revision": "6edbf1a6a03e75886a6609c088801a0856449e88", "revision": "bde09022887110deb780067364a0818e89258968",
"url": "https://github.com/NixOS/nixpkgs/archive/6edbf1a6a03e75886a6609c088801a0856449e88.tar.gz", "url": "https://github.com/NixOS/nixpkgs/archive/bde09022887110deb780067364a0818e89258968.tar.gz",
"hash": "sha256-0lkauQbtrljJqwtzTCILPAiHAJyMvn6XDo264moDv30=" "hash": "13mi187zpa4rw680qbwp7pmykjia8cra3nwvjqmsjba3qhlzif5l"
},
"treefmt-nix": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "numtide",
"repo": "treefmt-nix"
},
"branch": "main",
"submodules": false,
"revision": "e96d59dff5c0d7fddb9d113ba108f03c3ef99eca",
"url": "https://github.com/numtide/treefmt-nix/archive/e96d59dff5c0d7fddb9d113ba108f03c3ef99eca.tar.gz",
"hash": "02gqyxila3ghw8gifq3mns639x86jcq079kvfvjm42mibx7z5fzb"
} }
}, },
"version": 8 "version": 5
} }

6
ci/supportedSystems.json Normal file
View File

@@ -0,0 +1,6 @@
[
"aarch64-linux",
"aarch64-darwin",
"x86_64-linux",
"x86_64-darwin"
]

View File

@@ -1,175 +0,0 @@
{
lib,
pkgs,
...
}:
{
runtimeInputs = [
# tree-root uses `git rev-parse --show-toplevel`
pkgs.gitMinimal
];
settings = {
# numtide/treefmt-nix defaults
excludes = [
"*.lock"
"*.patch"
"*.diff"
"package-lock.json"
"go.mod"
"go.sum"
".gitattributes"
".gitignore"
".gitmodules"
"COPYING"
"LICENSE"
];
# Be a bit more verbose by default, so we can see progress happening
verbose = 1;
# By default it's info, which is too noisy since we have many unmatched files
on-unmatched = "debug";
formatter = {
# keep-sorted start block=yes newline_separated=yes
actionlint = {
command = lib.getExe pkgs.actionlint;
includes = [
".github/workflows/*.yml"
".github/workflows/*.yaml"
];
};
biome = {
command = lib.getExe pkgs.biome;
excludes = [
"*.min.js"
"pkgs/*"
];
includes = [
"*.js"
"*.ts"
"*.mjs"
"*.mts"
"*.cjs"
"*.cts"
"*.jsx"
"*.tsx"
"*.d.ts"
"*.d.cts"
"*.d.mts"
"*.css"
];
options = [
"check"
"--write"
"--no-errors-on-unmatched"
"--use-editorconfig=true"
"--javascript-formatter-quote-style=single"
"--semicolons=as-needed"
];
};
editorconfig-checker = {
command = lib.getExe pkgs.editorconfig-checker;
options = [
"-disable-indent-size"
# TODO: Remove this once this upstream issue is fixed:
# https://github.com/editorconfig-checker/editorconfig-checker/issues/505
"-disable-charset"
];
includes = [ "*" ];
priority = 1;
};
keep-sorted = {
command = lib.getExe pkgs.keep-sorted;
includes = [ "*" ];
};
markdown-code-runner = {
command = lib.getExe pkgs.markdown-code-runner;
options =
let
config = pkgs.writers.writeTOML "markdown-code-runner-config" {
presets.nixfmt = {
language = "nix";
command = [ (lib.getExe pkgs.nixfmt) ];
};
};
in
[ "--config=${config}" ];
includes = [ "*.md" ];
};
nixf-diagnose = {
command = lib.getExe pkgs.nixf-diagnose;
excludes = [
# Auto-generated; violates sema-extra-with
# Can only sensibly be removed when --auto-fix supports multiple fixes at once:
# https://github.com/inclyc/nixf-diagnose/issues/13
"pkgs/servers/home-assistant/component-packages.nix"
# https://github.com/nix-community/nixd/issues/708
"nixos/maintainers/scripts/azure-new/examples/basic/system.nix"
];
includes = [ "*.nix" ];
options = [
"--auto-fix"
# Rule names can currently be looked up here:
# https://github.com/nix-community/nixd/blob/main/libnixf/src/Basic/diagnostic.py
# TODO: Remove the following and fix things.
"--ignore=sema-unused-def-lambda-noarg-formal"
"--ignore=sema-unused-def-lambda-witharg-arg"
"--ignore=sema-unused-def-lambda-witharg-formal"
"--ignore=sema-unused-def-let"
# TODO: remove after outstanding prelude diagnostics issues are fixed:
# https://github.com/nix-community/nixd/issues/761
# https://github.com/nix-community/nixd/issues/762
"--ignore=sema-primop-removed-prefix"
"--ignore=sema-primop-overridden"
"--ignore=sema-constant-overridden"
"--ignore=sema-primop-unknown"
];
# Ensure nixfmt cleans up after nixf-diagnose.
priority = -1;
};
# This uses nixfmt underneath, the default formatter for Nix code.
# See https://github.com/NixOS/nixfmt
nixfmt = {
command = lib.getExe pkgs.nixfmt;
includes = [ "*.nix" ];
};
yamlfmt = {
command = lib.getExe pkgs.yamlfmt;
excludes = [
# Aligns comments with whitespace
"pkgs/development/haskell-modules/configuration-hackage2nix/main.yaml"
# TODO: Fix formatting for auto-generated file
"pkgs/development/haskell-modules/configuration-hackage2nix/transitive-broken.yaml"
];
includes = [
"*.yaml"
"*.yml"
];
options = [
"-formatter"
"retain_line_breaks=true"
];
};
zizmor = {
command = lib.getExe pkgs.zizmor;
includes = [
".github/workflows/*.yml"
".github/workflows/*.yaml"
".github/actions/**/*.yml"
".github/actions/**/*.yaml"
];
};
# keep-sorted end
};
};
}

View File

@@ -1,9 +1,8 @@
#!/usr/bin/env nix-shell #!/usr/bin/env nix-shell
#!nix-shell -i bash -E 'with import ../. {}; mkShell { packages = [ npins ]; }' #!nix-shell -i bash -p npins
set -euo pipefail set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")" cd "$(dirname "${BASH_SOURCE[0]}")"
npins --lock-file pinned.json upgrade
npins --lock-file pinned.json update npins --lock-file pinned.json update

View File

@@ -1,32 +1,21 @@
# Contributing to the Nixpkgs manual # Contributing to the Nixpkgs reference manual
This directory houses the source files for the Nixpkgs manual. This directory houses the source files for the Nixpkgs reference manual.
> [!NOTE] > [!IMPORTANT]
> We are actively restructuring our documentation to follow the [Diátaxis framework](https://diataxis.fr/)
> >
> We are actively restructuring our documentation to be more beginner friendly. > Going forward, this directory should **only** contain [reference documentation](https://nix.dev/contributing/documentation/diataxis#reference).
> For tutorials, guides and explanations, contribute to <https://nix.dev/> instead.
> >
> We are actively working to generate **all** reference documentation from the [doc-comments](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) present in code.
> This also provides the benefit of using `:doc` in the `nix repl` to view reference documentation locally on the fly.
When writing new docs use **Progressive Disclosure** For documentation only relevant for contributors, use Markdown files next to the source and regular code comments.
Start simple, pick up beginners. > [!TIP]
Use **examples** first to show how to get something done. Keep **Explanation** lean. > Feedback for improving support for parsing and rendering doc-comments is highly appreciated.
> [Open an issue](https://github.com/NixOS/nixpkgs/issues/new?labels=6.topic%3A+documentation&title=Doc%3A+) to request bugfixes or new features.
Use our [styleguide](./styleguide.md) for more in depth guidance on writing good documentation.
This directory contains **guides** and **reference** documentation for Nixpkgs.
Borrowing from [Diátaxis framework](https://diataxis.fr/) what suits our needs:
**Guides** are task-oriented. They can be tutorial-style walkthroughs or how-to sections.
Explanations appear as prose after examples.
**Reference** documentation is the specification of functions and attributes.
We are actively working to generate **all** reference documentation from the [doc-comments](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) present in code.
This also provides the benefit of using `:doc` in the `nix repl` to view reference documentation locally on the fly.
See [Document structure](#document-structure) for a structural template.
Rendered documentation: Rendered documentation:
- [Unstable (from master)](https://nixos.org/manual/nixpkgs/unstable/) - [Unstable (from master)](https://nixos.org/manual/nixpkgs/unstable/)
@@ -47,7 +36,7 @@ If the build succeeds, the manual will be in `./result/share/doc/nixpkgs/manual.
### Development environment ### Development environment
To reduce repetition, consider using tools from the provided development environment: In order to reduce repetition, consider using tools from the provided development environment:
Load it from the Nixpkgs documentation directory with Load it from the Nixpkgs documentation directory with
@@ -65,11 +54,9 @@ Make sure that your local files aren't added to Git history by adding the follow
/**/.direnv /**/.direnv
``` ```
#### Live preview #### `devmode`
Run [`devmode`](../pkgs/by-name/de/devmode/README.md) for a live preview while editing the manual: it rebuilds on every change and reloads the page in your browser automatically. Use [`devmode`](../pkgs/by-name/de/devmode/README.md) for a live preview when editing the manual.
Changes to the renderer 'pkgs/by-name/ni/nixos-render-docs' need a manual restart. Run: `devmode` again.
### Testing redirects ### Testing redirects
@@ -220,64 +207,6 @@ When needed, each convention explains why it exists, so you can make a decision
Note that these conventions are about the **structure** of the manual (and its source files), not about the content that goes in it. Note that these conventions are about the **structure** of the manual (and its source files), not about the content that goes in it.
You, as the writer of documentation, are still in charge of its content. You, as the writer of documentation, are still in charge of its content.
**For prose style, see the [documentation styleguide](./styleguide.md).**
### Document structure
Organize each chapter as guide sections first, then a single `## Reference` section.
A well-structured chapter looks like this:
````markdown
# Foo {#foo}
`foo` builds Foo projects from a `foo.toml`.
## Package a Foo application {#foo-packaging}
:::{.example #ex-foo-packaging}
# Package the hello app
```nix
{ foo }:
buildFooPackage {
pname = "hello";
version = "1.0";
}
```
:::
`buildFooPackage` needs `pname` and `version`.
Keep explanation short, and place it after the example.
## Reference {#foo-reference}
### `buildFooPackage` {#foo-buildFooPackage}
Builds a Foo application from source.
#### Inputs {#foo-buildFooPackage-inputs}
`pname` (String)
: The program name.
#### Examples {#foo-buildFooPackage-examples}
See [](#ex-foo-packaging).
````
Examples live in one place: the guide owns them and the reference links to them.
Guides introduce minimal working examples that are goal-oriented (typical usage).
Reference may introduce additional examples that are unit-oriented. (minimal usage, edge-cases).
If the guide example is already sufficient, just link to it from the reference.
Follow this structure strictly; to deviate, ping @NixOS/documentation-team.
### One sentence per line ### One sentence per line
Put each sentence in its own line. Put each sentence in its own line.
@@ -288,37 +217,6 @@ Not everything has been migrated to this format yet.
Please always use it for new content. Please always use it for new content.
When changing existing content, update formatting if possible, but avoid excessive diffs. When changing existing content, update formatting if possible, but avoid excessive diffs.
### Examples first
Put examples before detailed explanations (see the [styleguide](./styleguide.md) for the rationale).
Use this structure for each documented item:
1. Title
2. Abstract (optional, one sentence max)
3. Example
4. Explanation (details, edge cases, types, defaults)
Rendered example:
````markdown
## `lib.toUpper`
Converts all characters in a string to uppercase.
:::{.example #ex-lib-toUpper}
# Converting a string to uppercase
```nix
lib.toUpper "hello"
=> "HELLO"
```
:::
Only acts on ASCII characters.
Unicode characters are passed through unchanged.
````
### Writing Function Documentation ### Writing Function Documentation
Function documentation is *reference documentation*, for which Function documentation is *reference documentation*, for which
@@ -351,17 +249,11 @@ Returns the difference as a number.
Use the [admonition syntax](#admonitions) for callouts and examples. Use the [admonition syntax](#admonitions) for callouts and examples.
### `callPackage`-compatible examples ### Provide self-contained examples
Provide at least one example per function, in its doc-comment. Provide at least one example per function, and make examples self-contained.
This is easier to understand for beginners.
Keep each example at the level it documents: It also helps with testing that it actually works especially once we introduce automation.
- A **reference example** might sometimes live in a doc-comment and show function call shape.
- A **guide example** lives in a guide section and shows a complete task that may compose several functions.
When the task is nothing more than the call itself, the guide example is enough.
The reference example links to the guide example.
Example code should be such that it can be passed to `pkgs.callPackage`. Example code should be such that it can be passed to `pkgs.callPackage`.
Instead of something like: Instead of something like:

View File

@@ -25,5 +25,6 @@ build-helpers/dev-shell-tools.chapter.md
build-helpers/special.md build-helpers/special.md
build-helpers/images.md build-helpers/images.md
hooks/index.md hooks/index.md
languages-frameworks/index.md
packages/index.md packages/index.md
``` ```

View File

@@ -2,7 +2,7 @@
The `nix-shell` command has popularized the concept of transient shell environments for development or testing purposes. The `nix-shell` command has popularized the concept of transient shell environments for development or testing purposes.
<!-- <!--
We should try to document the product, not its development process in the Nixpkgs manual, We should try to document the product, not its development process in the Nixpkgs reference manual,
but *something* needs to be said to provide context for this library. but *something* needs to be said to provide context for this library.
This is the most future proof sentence I could come up with while Nix itself does not yet make use of this. This is the most future proof sentence I could come up with while Nix itself does not yet make use of this.
Relevant is the current status of the devShell attribute "project": https://github.com/NixOS/nix/issues/7501 Relevant is the current status of the devShell attribute "project": https://github.com/NixOS/nix/issues/7501

View File

@@ -920,14 +920,14 @@ respectively. Otherwise, the fetcher uses `fetchzip`.
This is used with Radicle repositories. The arguments expected are similar to `fetchgit`. This is used with Radicle repositories. The arguments expected are similar to `fetchgit`.
Requires a `seed` argument (e.g. `seed.radicle.dev` or `rosa.radicle.network`) and a `repo` argument Requires a `seed` argument (e.g. `seed.radicle.xyz` or `rosa.radicle.xyz`) and a `repo` argument
(the repository id *without* the `rad:` prefix). Also accepts an optional `node` argument which (the repository id *without* the `rad:` prefix). Also accepts an optional `node` argument which
contains the id of the node from which to fetch the specified ref. If `node` is `null` (the contains the id of the node from which to fetch the specified ref. If `node` is `null` (the
default), a canonical ref is fetched instead. default), a canonical ref is fetched instead.
```nix ```nix
fetchFromRadicle { fetchFromRadicle {
seed = "seed.radicle.dev"; seed = "seed.radicle.xyz";
repo = "z3gqcJUoA1n9HaHKufZs5FCSGazv5"; # heartwood repo = "z3gqcJUoA1n9HaHKufZs5FCSGazv5"; # heartwood
tag = "releases/1.3.0"; tag = "releases/1.3.0";
hash = "sha256-4o88BWKGGOjCIQy7anvzbA/kPOO+ZsLMzXJhE61odjw="; hash = "sha256-4o88BWKGGOjCIQy7anvzbA/kPOO+ZsLMzXJhE61odjw=";
@@ -942,7 +942,7 @@ contains the full revision id of the Radicle patch to fetch.
```nix ```nix
fetchRadiclePatch { fetchRadiclePatch {
seed = "rosa.radicle.network"; seed = "rosa.radicle.xyz";
repo = "z4V1sjrXqjvFdnCUbxPFqd5p4DtH5"; # radicle-explorer repo = "z4V1sjrXqjvFdnCUbxPFqd5p4DtH5"; # radicle-explorer
revision = "d97d872386c70607beda2fb3fc2e60449e0f4ce4"; # patch: d77e064 revision = "d97d872386c70607beda2fb3fc2e60449e0f4ce4"; # patch: d77e064
hash = "sha256-ttnNqj0lhlSP6BGzEhhUOejKkkPruM9yMwA5p9Di4bk="; hash = "sha256-ttnNqj0lhlSP6BGzEhhUOejKkkPruM9yMwA5p9Di4bk=";
@@ -1003,27 +1003,3 @@ fetchtorrent {
- `config`: When using `transmission` as the `backend`, a json configuration can - `config`: When using `transmission` as the `backend`, a json configuration can
be supplied to transmission. Refer to the [upstream documentation](https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md) for information on how to configure. be supplied to transmission. Refer to the [upstream documentation](https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md) for information on how to configure.
## `fetchItchIo` {#fetchitchio}
`fetchItchIo` is a fetcher for downloading game assets from [itch.io](https://itch.io/). It accepts these arguments:
- `gameUrl`: The store page URL of the game.
- `upload`: The numerical ID of the asset to download. To find the upload ID of an asset, check the basename of the request URL when you download the asset using a browser.
- `hash`.
- `name` (optional): The derivation name, often the filename of the asset.
- `extraMessage` (optional): Extra message printed if the API key is not provided or if the account did not purchase the game.
For this fetcher to work, the environment variable `NIX_ITCHIO_API_KEY` must be set for the nix building process (which is nix-daemon in multi-user mode), and it must belong to an account that has bought the game if it is behind a paywall.
To get your API key, go to the ["API key" section](https://itch.io/user/settings/api-keys) of your account settings on itch.io.
```nix
{ fetchItchIo }:
fetchItchIo {
name = "DungeonDuelMonsters-linux-x64.zip";
hash = "sha256-gq2nGwpaStqaVI1pL63xygxOI/z53o+zLwiKizG98Ks=";
gameUrl = "https://mikaygo.itch.io/ddm";
upload = "13371354";
}
```

View File

@@ -1,50 +1,48 @@
# Fixed-point arguments of build helpers {#chap-build-helpers-finalAttrs} # Fixed-point arguments of build helpers {#chap-build-helpers-finalAttrs}
`stdenv.mkDerivation` also accepts a [fixed-point function](#function-library-lib.fixedPoints.fix) instead of a plain attribute set: As mentioned in the beginning of this part, `stdenv.mkDerivation` could alternatively accept a fixed-point function. The input of this function, typically named `finalAttrs`, is expected to be the final state of the attribute set. A build helper like this is said to accept **fixed-point arguments**.
```nix Build helpers don't always support fixed-point arguments yet, as support in [`stdenv.mkDerivation`](#mkderivation-recursive-attributes) was first included in Nixpkgs 22.05.
{
stdenv,
fetchurl,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "hello";
version = "2.12";
src = fetchurl { ## Defining a build helper with `lib.extendMkDerivation` {#sec-build-helper-extendMkDerivation}
url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz";
hash = "sha256-...";
};
})
```
The function's input, conventionally named `finalAttrs`, is the final state of the attribute set. Here `src` reads `finalAttrs.version` instead of repeating the version string. A build helper like this is said to accept **fixed-point arguments**. Developers can use the Nixpkgs library function [`lib.customisation.extendMkDerivation`](#function-library-lib.customisation.extendMkDerivation) to define a build helper supporting fixed-point arguments from an existing one with such support, with an attribute overlay similar to the one taken by [`<pkg>.overrideAttrs`](#sec-pkg-overrideAttrs).
Attributes that reference each other through `finalAttrs` stay correct when changing any of them with [`overrideAttrs`](#sec-pkg-overrideAttrs), because they all access the final values of the fixed-point computation.
`rec` cannot do this: its self-references are fixed when the set is defined and ignore later overrides.
See [recursive-sets](https://nix.dev/manual/nix/stable/language/syntax#recursive-sets) for the underlying mechanism.
## Define a build helper with `lib.extendMkDerivation` {#sec-build-helper-extendMkDerivation}
Use [`lib.customisation.extendMkDerivation`](#function-library-lib.customisation.extendMkDerivation) to define a build helper with fixed-point support from an existing one.
Its argument `extendDrvArgs` takes an attribute overlay similar to [`<pkg>.overrideAttrs`](#sec-pkg-overrideAttrs).
Besides overriding, `lib.extendMkDerivation` also supports `excludeDrvArgNames` to optionally exclude some arguments in the input fixed-point arguments from passing down to the base build helper (specified as `constructDrv`). Besides overriding, `lib.extendMkDerivation` also supports `excludeDrvArgNames` to optionally exclude some arguments in the input fixed-point arguments from passing down to the base build helper (specified as `constructDrv`).
:::{.example #ex-build-helpers-extendMkDerivation} :::{.example #ex-build-helpers-extendMkDerivation}
# Example `mkLocalDerivation` - a build helper over `mkDerivation` # Example definition of `mkLocalDerivation` extended from `stdenv.mkDerivation` with `lib.extendMkDerivation`
Define a build helper named `mkLocalDerivation` that builds locally without using substitutes by default. We want to define a build helper named `mkLocalDerivation` that builds locally without using substitutes by default.
Use `lib.extendMkDerivation`: Instead of taking a plain attribute set,
```nix ```nix
{ {
lib, preferLocalBuild ? true,
stdenv, allowSubstitute ? false,
}: specialArg ? (_: false),
...
}@args:
stdenv.mkDerivation (
removeAttrs [
# Don't pass specialArg into mkDerivation.
"specialArg"
] args
// {
# Arguments to pass
inherit preferLocalBuild allowSubstitute;
# Some expressions involving specialArg
greeting = if specialArg "hi" then "hi" else "hello";
}
)
```
we could define with `lib.extendMkDerivation` an attribute overlay to make the result build helper also accept the attribute set's fixed point passing to the underlying `stdenv.mkDerivation`, named `finalAttrs` here:
```nix
lib.extendMkDerivation { lib.extendMkDerivation {
constructDrv = stdenv.mkDerivation; constructDrv = stdenv.mkDerivation;
excludeDrvArgNames = [ excludeDrvArgNames = [
@@ -69,77 +67,4 @@ lib.extendMkDerivation {
``` ```
::: :::
To apply extra changes to the result derivation, pass `transformDrv` to `lib.extendMkDerivation`: If one needs to apply extra changes to the result derivation, pass the derivation transformation function to `lib.extendMkDerivation` as `lib.customisation.extendMkDerivation { transformDrv = drv: ...; }`.
```nix
lib.customisation.extendMkDerivation { transformDrv = drv: /...; }
```
Construct a wrapper derivation around another derivation using `transformDrv`
The wrapper has access to the original arguments
:::{.example #ex-build-helpers-extendMkDerivation-transformDrv-wrapper}
# Define a custom build helper that downloads and builds
```nix
{
lib,
stdenvNoCC,
cacert,
configure-example,
download-example,
}:
lib.extendMkDerivation {
constructDrv = stdenvNoCC.mkDerivation;
excludeDrvArgNames = [
"bar"
];
extendDrvArgs =
finalAttrs:
{
bar,
foo,
hash ? "",
...
}@args:
{
inherit hash;
nativeBuildInputs = args.nativeBuildInputs or [ ] ++ [
cacert
download-example
];
buildPhase = ''
runHook preBuild
download-example --foo="$foo" --out="$out"
runHook postBuild
'';
impureEnvVars = lib.fetchers.proxyImpureEnvVars;
outputHash = if finalAttrs.hash != "" then finalAttrs.hash else lib.fakeHash;
outputHashFormat = "recursive";
passthru = args.passthru or { } // {
inherit bar;
};
};
transformDrv =
unwrapped:
stdenvNoCC.mkDerivation (finalAttrs: {
name = finalAttrs.src.name + "-wrapped";
src = unwrapped;
nativeBuildInputs = [
configure-example
];
inherit (unwrapped) bar;
buildPhase = ''
runHook preBuild
configure-example --bar="$bar"
runHook postBuild
'';
});
}
```

View File

@@ -3,7 +3,6 @@
This chapter describes several special build helpers. This chapter describes several special build helpers.
```{=include=} sections ```{=include=} sections
special/buildenv.section.md
special/fakenss.section.md special/fakenss.section.md
special/fhs-environments.section.md special/fhs-environments.section.md
special/makesetuphook.section.md special/makesetuphook.section.md

View File

@@ -1,101 +0,0 @@
# buildEnv {#sec-buildEnv}
`buildEnv` constructs a derivation containing directories and symbolic links, which resembles the profile layout where a list of derivations or store paths are installed.
Unlike [`symlinkJoin`](#trivial-builder-symlinkJoin), `buildEnv` takes special care of the outputs to link and checks for content collisions across the paths by default.
A common use case for `buildEnv` is constructing environment wrappers, such as an interpreter with modules or a program with extensions.
For example, [`python.withPackage`](#attributes-on-interpreters-packages) is based on `buildEnv`.
## Arguments {#sec-buildEnv-arguments}
`buildEnv` takes [fixed-point arguments (`buildEnv (finalAttrs: { })`)](#chap-build-helpers-finalAttrs) as well as a plain attribute set.
Unless otherwise noted, arguments can be overridden directly using [`<pkg>.overrideAttrs`](#sec-pkg-overrideAttrs).
`buildEnv` enforces [structured attributes (`{ __structuredAttrs = true; }`)](https://nix.dev/manual/nix/2.18/language/advanced-attributes.html#adv-attr-structuredAttrs).
- `name` or `pname` and `version` (required):
The name of the environment.
- `paths` (required):
The derivations or store paths to symlink ("install").
The elements can be any path-like object that string-interpolates to a store path.
The priority of each path is taken from `<path>.meta.priority` and falls back to `lib.meta.defaultPriority` if not set.
The argument `paths` is passed as attribute `passthru.paths` to prevent unexpected context pollution.
`passthru.paths` can be overridden with `<pkg>.overrideAttrs`.
- `extraOutputsToInstall` (default to `[ ]`):
Package outputs to include in addition to what `meta.outputsToInstall` specifies.
- `includeClosures` (default to `false`):
Whether to include closures of all input paths.
The list of the closure paths are constructed with `writeClosure`.
They are installed with lower priority and with build-time exceptions silenced.
- `extraPrefix` (default to `""`):
Root the result in directory `"$out${extraPrefix}"`, e.g. `"/share"`.
- `ignoreCollisions` (default: `false`):
Don't fail the build upon content collisions.
- `checkCollisionContents` (default: `true`):
If there is a collision, check whether the contents and permissions match; and only if not, throw a collision error.
- `ignoreSingleFileOutputs` (default: `false`):
Don't fail the build upon single-file outputs.
- `manifest` (default: `""`):
The manifest file (if any). A symlink `$out/manifest` will be created to it.
- `pathsToLink` (default: `[ "/" ]`):
The paths (relative to each element of `paths`) that we want to symlink (e.g., `["/bin"]`).
Any file outside the directories in this list won't be symlinked into the produced environment.
- `postBuild` (default: `""`):
Shell commands to run after building the symlink tree.
- `passthru` and `meta` (default: `{ }`):
`stdenv.mkDerivation`-supported attributes not passing down to `builtins.derivation`.
- `derivationArgs` (default: `{ }`):
Additional `stdenv.mkDerivation` arguments, such as `nativeBuildInputs`/`buildInputs` for `postBuild` dependencies and setup hooks.
`derivationArgs` is not passed down to `stdenv.mkDerivation`.
Override its attributes directly via `<pkg>.overrideAttrs` and reference directly via `finalAttrs`.
## Build-time exceptions {#sec-buildEnv-exceptions}
There are situations where the specified `paths` might not produce sensible profile layout.
By default, the builder fails early upon detecting these exceptions.
`buildEnv` provides arguments to fine-tune or ignore certain exceptions.
### Path collisions {#ssec-buildEnv-collisions}
Path collisions occur when files provided by two more output paths with the same priority overlap with each other, making the result profile layout potentially affected by the order of elements of `paths`.
This is undesirable in several use cases, such as when `paths` are determined by merging Nix modules.
If the argument `checkCollisionContents` is `true`, the builder checks whether the overlapping paths share the same content and mode, and fails only if not.
The argument `ignoreCollisions` silence the collision checks and allow the files to be overwritten based on the order of chosen output paths.
In addition to silencing this exception with `ignoreCollisions`, one can also adjust the priority of colliding packages and store paths.
Store paths can specify priority in the form
```nix
{
outPath = <path>;
meta.priority = <priority>;
}
```
And [`lib.meta.setPrio`](#function-library-lib.meta.setPrio)-related Nixpkgs Library functions also apply to a string-like attribute set (`{ outPath = <path>; }`).
### Single-file outputs {#ssec-buildEnv-singleFileOutputs}
When an output path provides a single file instead of a directory, it inherently cannot merge into the result layout.
All discoverable packages should configure their `meta.outputsToInstall` correctly, so that single-file outputs won't be installed into a profile.
Set `ignoreSingleFileOutputs` to `true` to drop all single-file output paths silently.
This option is useful when the specified paths contain the output paths of package tests.

View File

@@ -98,14 +98,6 @@ It has two modes:
: The path to the files to check. : The path to the files to check.
`relocatable` (boolean, optional) {#tester-lycheeLinkCheck-param-relocatable}
: Whether the site is expected to be relocatable, i.e. servable from any URL path prefix.
When `true` (the default), root-relative links (starting with `/`) are treated as errors, because they break when the site is served from a subpath or opened via `file://` URLs.
When `false`, root-relative links are resolved against the `site` directory.
`remap` (attribute set, optional) {#tester-lycheeLinkCheck-param-remap} `remap` (attribute set, optional) {#tester-lycheeLinkCheck-param-remap}
: An attribute set where the attribute names are regular expressions. : An attribute set where the attribute names are regular expressions.
@@ -137,13 +129,6 @@ It has two modes:
Example: `{ "include_verbatim" = true; }` Example: `{ "include_verbatim" = true; }`
`extraArgs` (list of strings, optional) {#tester-lycheeLinkCheck-param-extraArgs}
: Extra command line arguments to pass to the `lychee` invocation.
These are passed in both the offline (build) and [`online`](#tester-lycheeLinkCheck-return) modes.
Example: `[ "--format" "json" ]`
`lychee` (derivation, optional) {#tester-lycheeLinkCheck-param-lychee} `lychee` (derivation, optional) {#tester-lycheeLinkCheck-param-lychee}
: The `lychee` package to use. : The `lychee` package to use.
@@ -737,102 +722,4 @@ Notable attributes:
* `driverInteractive`: a script that launches an interactive Python session in the context of the `testScript`. * `driverInteractive`: a script that launches an interactive Python session in the context of the `testScript`.
## `modularServiceCompliance` {#tester-modularServiceCompliance}
Compliance suite for [modular service](https://nixos.org/manual/nixos/unstable/#modular-services) integrations.
Tests that a service manager integration correctly handles the portable modular services contract: `process.argv`, sub-services, assertions, and warnings.
### Return value {#tester-modularServiceCompliance-return}
An attribute set of derivations which perform the tests during their build.
### Inputs {#tester-modularServiceCompliance-inputs}
`evalConfig` (function)
: `{ services } -> { config; checkDrv; }`.
Function to evaluate the given services in the integration's full context.
This function is called for evaluation checks on configurations that will not be run.
- Input `services` is an attrset of modular service configurations. These should be used verbatim.
- Output attribute `config` is the resulting evaluated services attrset (e.g., the value of the `system.services` option in NixOS).
This attribute must be available even if `checkDrv` would fail.
- Output attribute `checkDrv` is a representative derivation whose existence and buildability prove the eval is sound (e.g., `system.build.toplevel` in NixOS, but could perhaps be more specific in the case of another process manager integration).
`mkTest` (function)
: `{ name, services, testExe } -> derivation`.
- Input `name` is a test name, suitable for use as a derivation name.
- Input `services` is an attrset of modular service configurations, matching the structure of the integration's services option.
- Input `testExe` is a store path to an executable that verifies the services.
- Output: a derivation that runs the service manager with the provided configuration inputs and then calls `testExe` after starting the services. That executable must have access to `sharedDir`.
`sharedDir` (string)
: Path to a directory writable by service processes and readable by `testExe`.
The integration must ensure this directory is available when the services and `testExe` run.
:::{.example #ex-modularServiceCompliance-nixos}
# NixOS invocation of the compliance suite
```nix
# In nixos/tests/all-tests.nix:
# modularServiceCompliance =
recurseIntoAttrs (
pkgs.testers.modularServiceCompliance {
sharedDir = "/tmp/modular-service-compliance";
evalConfig =
{ services }:
let
machine = evalSystem (
{ ... }:
{
system.services = services;
system.stateVersion = "25.05";
fileSystems."/" = {
device = "/test/dummy";
fsType = "auto";
};
boot.loader.grub.enable = false;
}
);
in
{
config = machine.config.system.services;
checkDrv = machine.config.system.build.toplevel;
};
mkTest =
{
name,
services,
testExe,
}:
runTest {
_class = "nixosTest";
inherit name;
nodes.machine.system.services = services;
testScript = ''
machine.wait_for_unit("multi-user.target")
machine.succeed("${testExe}")
'';
};
}
)
```
:::
### Manual compliance items {#tester-modularServiceCompliance-manual}
The following compliance items are not yet automated and must be verified manually when implementing a new modular service integration.
- **Failing assertions prevent deployment.**
A service with `assertions = [{ assertion = false; message = "..."; }]` must cause the deployment to fail.
The mechanism is integration-specific (e.g., NixOS checks assertions during `system.build.toplevel` evaluation).
- **Warnings are visible to the user.**
A service with `warnings = [ "..." ]` must surface the warning to the user.
On NixOS these are `builtins.warn` messages emitted during evaluation.
[file system object]: https://nix.dev/manual/nix/latest/store/file-system-object [file system object]: https://nix.dev/manual/nix/latest/store/file-system-object

View File

@@ -734,80 +734,7 @@ Some basic Bash options are set by default (`errexit`, `nounset`, and `pipefail`
Extra arguments may be passed to `stdenv.mkDerivation` by setting `derivationArgs`; note that variables set in this manner will be set when the shell script is _built,_ not when it's run. Extra arguments may be passed to `stdenv.mkDerivation` by setting `derivationArgs`; note that variables set in this manner will be set when the shell script is _built,_ not when it's run.
Runtime environment variables can be set with the `runtimeEnv` argument. Runtime environment variables can be set with the `runtimeEnv` argument.
`writeShellApplication` has the following arguments: For example, the following shell application can refer to `curl` directly, rather than needing to write `${curl}/bin/curl`:
`name` (String)
: The name of the script to write.
`text` (String)
: The shell script's text, not including a shebang.
`runtimeInputs` (List of derivations or strings, _optional_)
: Inputs to add to the shell script's `$PATH` at runtime.
Each elements can either be a normal derivation, or a string containing a path, in which case it will be suffixed with `/bin` to create a `PATH` expression (see [`lib.strings.makeBinPath`](#function-library-lib.strings.makeBinPath) for more information).
`runtimeEnv` (Attribute set, _optional_)
: Extra environment variables to set at runtime.
`checkPhase` (String, _optional_)
: The `checkPhase` to run.
The script path will be given as `$target` in the `checkPhase`
_Default behavior:_ run [`shellcheck`](https://github.com/koalaman/shellcheck) (on supported platforms) and `bash -n` (check syntax but don't execute commands).
`excludeShellChecks` (List of strings, _optional_)
: Checks to exclude when running `shellcheck`.
For example, `excludeShellChecks = [ "SC2016" ]` would prevent `shellcheck` from reporting `SC2016`, but would still detect any other problems.
See [the `shellcheck` wiki](https://www.shellcheck.net/wiki/) for a list of checks.
`extraShellCheckFlags` (List of strings, _optional_)
: Extra command-line flags to pass to `shellcheck`.
`bashOptions` (List of strings, _optional_)
: Bash options to activate with `set -o` at the start of the script
_Default:_ `[ "errexit" "nounset" "pipefail" ]`, which means:
1. A failing command inside of a command list or pipeline will make the script exit, except if used as a conditional (inside a `while`, `if`, `&&`, `||`, etc.);
2. Any attempt to expand an undefined variable will make the script exit.
`inheritPath` (Bool, _optional_)
: Whether the script will inherit the PATH from its parent environment.
_Default:_ `true`
`meta` (Attribute set, _optional_)
: `stdenv.mkDerivation`'s [`meta`](#chap-meta) argument
`passthru` (Attribute set, _optional_)
: `stdenv.mkDerivation`'s [`passthru`](#chap-passthru) argument
`derivationArgs` (Attribute set, _optional_)
: Extra arguments to pass to [`stdenv.mkDerivation`](#chap-stdenv)
::: {.caution}
Certain derivation attributes are also set internally, so overriding those could cause problems.
:::
::: {.example #ex-writeShellApplication}
# Usage of `writeShellApplication`
The following shell application can refer to `curl` directly, rather than needing to write `${curl}/bin/curl`
```nix ```nix
writeShellApplication { writeShellApplication {
@@ -823,7 +750,6 @@ writeShellApplication {
''; '';
} }
``` ```
:::
## `symlinkJoin` {#trivial-builder-symlinkJoin} ## `symlinkJoin` {#trivial-builder-symlinkJoin}

View File

@@ -1,5 +1,5 @@
{ {
pkgs ? (import ../ci { }).docPkgs, pkgs ? (import ../ci { }).pkgs,
nixpkgs ? { }, nixpkgs ? { },
}: }:

View File

@@ -37,16 +37,16 @@ runCommand "manual.epub"
</book> </book>
''; '';
__structuredAttrs = true; passAsFile = [ "epub" ];
} }
'' ''
mkdir scratch mkdir scratch
printf "%s" "$epub" | xsltproc \ xsltproc \
--param chapter.autolabel 0 \ --param chapter.autolabel 0 \
--nonet \ --nonet \
--output scratch/ \ --output scratch/ \
${docbook_xsl_ns}/xml/xsl/docbook/epub/docbook.xsl \ ${docbook_xsl_ns}/xml/xsl/docbook/epub/docbook.xsl \
- $epubPath
echo "application/epub+zip" > mimetype echo "application/epub+zip" > mimetype
zip -0Xq -b "$TMPDIR" "$out" mimetype zip -0Xq -b "$TMPDIR" "$out" mimetype

View File

@@ -1,7 +0,0 @@
<div class="manual-header">
<nav class="manual-header--tabs">
<a class="manual-header--tab manual-header--tab-active" href="#">Nixpkgs</a>
<a class="manual-header--tab" href="https://nixos.org/manual/nixos/stable/">NixOS</a>
</nav>
<span class="manual-header--title">Nixpkgs Manual</span>
</div>

View File

@@ -54,7 +54,7 @@ stdenvNoCC.mkDerivation (
}; };
in in
{ {
version = lib.trivial.release; inherit (lib.trivial) version;
pname = "nixpkgs-manual"; pname = "nixpkgs-manual";
nativeBuildInputs = [ nixos-render-docs ]; nativeBuildInputs = [ nixos-render-docs ];
@@ -73,7 +73,6 @@ stdenvNoCC.mkDerivation (
../anchor.min.js ../anchor.min.js
../manpage-urls.json ../manpage-urls.json
../redirects.json ../redirects.json
../nav.json
] ]
); );
}; };
@@ -117,10 +116,8 @@ stdenvNoCC.mkDerivation (
--script ./highlightjs/loader.js \ --script ./highlightjs/loader.js \
--script ./anchor.min.js \ --script ./anchor.min.js \
--script ./anchor-use.js \ --script ./anchor-use.js \
--sidebar-depth 3 \ --toc-depth 1 \
--nav ./nav.json \ --section-toc-depth 1 \
--header ${./header.html}\
--no-navheader \
manual.md \ manual.md \
out/index.html out/index.html

View File

@@ -1,84 +0,0 @@
# Package your first application {#chap-first-package}
Package an application with Nixpkgs by picking the build helper for its language and setting a few attributes.
Each language ecosystem has its own build helper.
See [](#chap-language-support) for the full set.
## Package a Go application {#first-package-go}
`buildGoModule` builds Go programs that use Go modules.
Write the package to `package.nix`:
:::{.example #ex-first-package-go}
# Package `pet` with `buildGoModule`
```nix
# package.nix
{
buildGoModule,
fetchFromGitHub,
lib,
}:
buildGoModule (finalAttrs: {
pname = "pet";
version = "0.3.4";
src = fetchFromGitHub {
owner = "knqyf263";
repo = "pet";
tag = "v${finalAttrs.version}";
hash = "sha256-Gjw1dRrgM8D3G7v6WIM2+50r4HmTXvx0Xxme2fH9TlQ=";
};
vendorHash = "sha256-6hCgv2/8UIRHw1kCe3nLkxF23zE/7t5RDwEjSzX3pBQ=";
meta = {
description = "Simple command-line snippet manager, written in Go";
homepage = "https://github.com/knqyf263/pet";
license = lib.licenses.mit;
maintainers = with lib.maintainers; [ kalbasit ];
};
})
```
:::
`buildGoModule` needs `pname`, `version`, `src`, and `vendorHash`.
Pin Nixpkgs and call the package from `default.nix`:
```nix
# default.nix
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz";
pkgs = import nixpkgs { };
in
pkgs.callPackage ./package.nix { }
```
Build it:
```shell
$ nix-build ./default.nix
# or equivalent
$ nix-build
```
Run it:
```shell
$ ./result/bin/pet --help
pet - Simple command-line snippet manager.
```
`vendorHash` pins the fetched dependencies.
To find its value:
1. Set `vendorHash` to an empty string `""`.
2. Run `nix-build`.
3. Copy the correct value from the error into `vendorHash`.
See the [Go reference](#sec-language-go) for every attribute and advanced usage.

View File

@@ -1,24 +0,0 @@
# checkPhaseThreadLimitHook {#setup-hook-check-phase-thread-limit}
This hook defaults a variety of environment variables known
to control thread counts to 1. Many of these otherwise default
to `$(nproc)`, which causes massive overloads on build machines
if nix build jobs and build cores are already tuned to fully utilize
compute capacity of a builder without additional parallelism.
Currently sets the following environment variables:
- [`OMP_NUM_THREADS`](https://www.openmp.org/spec-html/5.0/openmpse50.html)
- [`OPENBLAS_NUM_THREADS`](https://github.com/OpenMathLib/OpenBLAS/blob/e7b45174355edec1f04de1cabcf5ca6a98ea7fbc/USAGE.md#how-can-i-use-openblas-in-multi-threaded-applications)
- [`MKL_NUM_THREADS`](https://www.intel.com/content/www/us/en/docs/onemkl/developer-guide-linux/2023-0/mkl-domain-num-threads.html)
- [`BLIS_NUM_THREADS`](https://github.com/flame/blis/blob/b8b75b4e19459f5d618b57aa814ca38b1d82eb82/docs/Multithreading.md#specifying-multithreading)
- `VECLIB_MAXIMUM_THREADS`: Only affects darwin, see [`man 7 Accelerate`](https://manp.gs/mac/7/Accelerate)
- [`NUMBA_NUM_THREADS`](https://numba.readthedocs.io/en/stable/reference/envvars.html#threading-control)
- [`NUMEXPR_NUM_THREADS`](https://numexpr.readthedocs.io/en/latest/user_guide.html#threadpool-configuration)
The `NIX_CHECK_PHASE_DEFAULT_NUM_THREADS` environment variable
can be used to override the default thread count limit.
`dontLimitCheckPhaseThreads = true;` can be used to disable
thread limiting on an individual package.
This hook will not attempt to override already existing
definitions for thread count environment variables.

View File

@@ -13,7 +13,6 @@ aws-c-common.section.md
bmake.section.md bmake.section.md
breakpoint.section.md breakpoint.section.md
cernlib.section.md cernlib.section.md
check-phase-thread-limit-hook.section.md
cmake.section.md cmake.section.md
desktop-file-utils.section.md desktop-file-utils.section.md
gdk-pixbuf.section.md gdk-pixbuf.section.md
@@ -21,7 +20,6 @@ ghc.section.md
gnome.section.md gnome.section.md
haredo.section.md haredo.section.md
installShellFiles.section.md installShellFiles.section.md
installFonts.section.md
julec.section.md julec.section.md
just.section.md just.section.md
libglycin.section.md libglycin.section.md
@@ -30,15 +28,9 @@ libxml2.section.md
meson.section.md meson.section.md
mpi-check-hook.section.md mpi-check-hook.section.md
ninja.section.md ninja.section.md
nodejs-install-executables.section.md
nodejs-install-manuals.section.md
npm-build-hook.section.md
npm-config-hook.section.md
npm-install-hook.section.md
patch-rc-path-hooks.section.md patch-rc-path-hooks.section.md
perl.section.md perl.section.md
pkg-config.section.md pkg-config.section.md
pnpm.section.md
postgresql-test-hook.section.md postgresql-test-hook.section.md
premake.section.md premake.section.md
python.section.md python.section.md
@@ -50,7 +42,6 @@ unzip.section.md
validatePkgConfig.section.md validatePkgConfig.section.md
versionCheckHook.section.md versionCheckHook.section.md
waf.section.md waf.section.md
writable-tmpdir-as-home-hook.section.md
zig.section.md zig.section.md
xcbuild.section.md xcbuild.section.md
xfce4-dev-tools.section.md xfce4-dev-tools.section.md

View File

@@ -1,24 +0,0 @@
# `installFonts` {#installfonts}
This hook installs common font formats to the proper location. In its default state, the hook automatically handles ttf, ttc, otf, bdf, and psf. Given a `webfont` output, woff and woff2 formats will be installed under this output.
The automatic behavior of the hook can be disabled by setting the `dontInstallFonts` variable to true.
Additionally, it exposes the `installFont` function that can be used from your `postInstall`
hook, to install additional formats:
## `installFont` {#installfonts-installfont}
The `installFont` function takes two arguments, a file extension to move (*without* a preceding dot), and the install location.
### Example Usage {#installfonts-installfont-exampleusage}
```nix
{
nativeBuildInputs = [ installFonts ];
postInstall = ''
installFont svg $out/share/fonts/svg
'';
}
```

View File

@@ -1,33 +0,0 @@
# `juce.projucerHook` {#juce-projucer-hook}
[Projucer](https://juce.com/tutorials/tutorial_new_projucer_project/) is a graphical project management utility and build system for the [JUCE](https://juce.com/) audio programming framework. It is available in nixpkgs under the `juce` package.
The `juce.projucerHook` setup hook overrides the configure and install phases. It is only supported on Linux and requires your project's `.jucer` file to contain a `LinuxMakefile` exporter.
## Example {#juce-projucer-hook-example}
```nix
{
juce,
stdenv,
}:
stdenv.mkDerivation {
# ...
nativeBuildInputs = [ juce.projucerHook ];
jucerFile = "Microbiome.jucer";
dontUseProjucerInstall = true;
# ...
}
```
## Variables controlling `juce.projucerHook` {#juce-projucer-hook-variables}
### `dontUseProjucerConfigure`
Disables `projucerConfigurePhase`
### `dontUseProjucerInstall`
Disables `projucerInstallPhase`

View File

@@ -1,29 +0,0 @@
# nodejsInstallExecutables {#nodejs-install-executables}
Hook for wrapping Node.js executables.
Primarily created for a multi-language environment.
## Examples {#nodejs-install-executables-example}
[](#npm-build-hook-example-snippet)
## Variables controlling `nodejsInstallExecutables` {#nodejs-install-executables-variables}
### `nodejsInstallExecutables` Exclusive Variables {#nodejs-install-executables-exclusive-variables}
#### `makeWrapperArgs` {#nodejs-install-executables-wrapper-args}
Flags to pass to the call to [`makeWrapper`](#fun-makeWrapper).
To avoid double-wrapping, this flag can also be accessed in Bash.
```nix
stdenv.mkDerivation (finalAttrs: {
#...
dontWrapGApps = true;
postInstall = ''
makeWrapperArgs+=("''${gappsWrapperArgs[@]}")
'';
#...
})
```

View File

@@ -1,12 +0,0 @@
# nodejsInstallManuals {#nodejs-install-manuals}
Detects manuals in Node.js packages, and attempts to install them in standard locations.
This detection is done by inspecting the package.json of the project and finding any entries
with type `man`.
There are no ways currently to configure this hook.
## Examples {#nodejs-install-manuals-example}
[](#npm-build-hook-example-snippet)

View File

@@ -1,93 +0,0 @@
# npmHooks.npmBuildHook {#npm-build-hook}
Hook for building packages that use npm. Can be used in multi-language environments.
## Examples {#npm-build-hook-snippet}
:::{.example #npm-build-hook-example-snippet}
# Using `npmHooks`
```nix
{
stdenv,
fetchFromGitHub,
fetchNpmDeps,
npmHooks,
nodejsInstallExecutables,
nodejsInstallManuals,
nodejs,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "some-npm-project";
version = "1.0";
src = fetchFromGitHub {
owner = "JohnNpm";
repo = "SomeProject";
tag = finalAttrs.version;
hash = "...";
};
strictDeps = true;
nativeBuildInputs = [
nodejs
nodejsInstallExecutables
nodejsInstallManuals
npmHooks.npmConfigHook
npmHooks.npmBuildHook
npmHooks.npmInstallHook
];
npmBuildScript = "build";
npmBuildFlags = [
"--prod"
];
npmFlags = [
"--ignore-scripts"
];
npmDeps = fetchNpmDeps {
inherit (finalAttrs) src;
hash = "...";
};
makeWrapperArgs = [
"--set"
"NODE_ENV"
"production"
];
meta = {
description = "npm project";
};
})
```
:::
## Variables controlling `npmBuildHook` {#npm-build-hook-variables}
### `npmBuildHook` Exclusive Variables {#npm-build-hook-exclusive-variables}
#### `npmBuildScript` {#npm-build-hook-script}
Controls the script ran to build the npm package within the `package.json` file.
Required to be set, usually to `build`, but can vary between packages.
#### `npmBuildFlags` {#npm-build-hook-flags}
Controls the arguments to the {command}`npm run $npmBuildScript` command.
#### `dontNpmBuild` {#npm-build-hook-dont}
Disables `npmBuildHook` when enabled
### Honored Variables {#npm-build-hook-honored-variables}
The following variables are honored by the `npmBuildHook`.
- [`npmWorkspace`](#javascript-buildNpmPackage-npmWorkspace)
- [`npmFlags`](#javascript-buildNpmPackage-npmFlags)

View File

@@ -1,41 +0,0 @@
# npmHooks.npmConfigHook {#npm-config-hook}
Hook for configuring packages that use npm.
Primarily made for a multi-language environment.
## Examples {#npm-config-hook-snippet}
[](#npm-build-hook-example-snippet)
## Variables controlling `npmConfigHook` {#npm-config-hook-variables}
### `npmConfigHook` Exclusive Variables {#npm-config-hook-exclusive-variables}
#### `npmDeps` {#npm-config-hook-deps}
Derivation that contains the npm package dependencies.
Usually built with `fetchNpmDeps`.
This attribute is required or the hook will abort the build.
#### `makeCacheWritable` {#npm-config-hook-writable-cache}
Whether to make the dependency cache writable prior to installing the dependencies.
Don't set this unless npm tries to write to the cache directory.
#### `npmInstallFlags` {#npm-config-hook-install-flags}
Flags to pass to the {command}`npm ci` call for installing the dependencies to the build environment.
Defaults to `--ignore-scripts`, which cannot be removed.
This does not control anything with the `npmInstallHook`.
#### `npmRebuildFlags` {#npm-config-hook-rebuild-flags}
Flags to pass to the {command}`npm rebuild` command after the dependencies are installed to the environment.
### Honored Variables {#npm-config-hook-honored-variables}
The following variables are honored by the `npmConfigHook`.
- [`npmWorkspace`](#javascript-buildNpmPackage-npmWorkspace)
- [`npmFlags`](#javascript-buildNpmPackage-npmFlags)
- `npmRoot`

View File

@@ -1,35 +0,0 @@
# npmHooks.npmInstallHook {#npm-install-hook}
Hook to install node_modules for npm packages.
Does not create wrappers for executable npm projects
Primarily made for a multi-language environment.
## Examples {#npm-install-hook-snippet}
[](#npm-build-hook-example-snippet)
## Variables controlling `npmInstallHook` {#npm-install-hook-variables}
### `npmInstallHook` Exclusive Variables {#npm-install-hook-exclusive-variables}
#### `dontNpmPrune` {#npm-install-hook-dont-prune}
Whether to run {command}`npm prune` on the `node_modules` or not.
Defaults to `true`.
#### `npmInstallFlags` {#npm-install-hook-prune-flags}
Flags to pass to the {command}`npm prune` call for the `node_modules` of the package.
Defaults to `--omit=dev --no-save` which cannot be modified.
#### `dontNpmInstall` {#npm-install-hook-dont}
Controls whether `npmInstallHook` is enabled or not.
Defaults to `true`, so the hook will run.
### Honored Variables {#npm-install-hook-honored-variables}
The following variables are honored by the `npmInstallHook`.
- [`npmWorkspace`](#javascript-buildNpmPackage-npmWorkspace)
- [`npmFlags`](#javascript-buildNpmPackage-npmFlags)

View File

@@ -1,142 +0,0 @@
# pnpmBuildHook {#pnpm-build-hook}
[pnpm](https://pnpm.io/) is a an NPM-compatible package manager focused on increasing managment speeds, and reducing disk space.
The `pnpmBuildHook` in Nixpkgs overrides the default build phase for building packages that use pnpm.
:::{.example #ex-pnpm-build-hook}
## pnpmBuildHook example code snippet {#pnpm-build-hook-code-snippet}
```nix
{
lib,
stdenv,
fetchFromGitHub,
fetchPnpmDeps,
pnpmConfigHook,
pnpmBuildHook,
makeBinaryWrapper,
pnpm_10,
}:
let
pnpm = pnpm_10;
in
stdenv.mkDerivation (finalAttrs: {
pname = "coolPackages";
version = "1.0";
src = fetchFromGitHub {
owner = "JaneCool";
repo = "coolpackage";
tag = finalAttrs.version;
hash = lib.fakeHash;
};
__structuredAttrs = true;
strictDeps = true;
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs) pname version src;
inherit pnpm;
fetcherversion = 4;
hash = lib.fakeHash;
};
nativeBuildInputs = [
pnpmConfigHook
pnpmBuildHook
makeBinaryWrapper
];
pnpmBuildScript = "build";
pnpmBuildFlags = [
"--mode"
"production"
];
pnpmWorkspaces = [
"test"
];
installPhase = ''
runHook preInstall
mkdir "$out"
cp -r dist/. "$out"
runHook postInstall
'';
meta = {
description = "very cool package that does cool things";
mainProgram = "cool";
};
})
```
:::
## Variables controlling pnpmBuildHook {#pnpm-build-hook-variables}
### pnpm Exclusive Variables {#pnpm-build-hook-exclusive-variables}
#### `pnpmBuildScript` {#pnpm-build-hook-script}
Controls the script ran to build the package, by default the script is `build`.
#### `pnpmFlags` {#pnpm-build-hook-flags}
Controls flags used for all invocations of pnpm across all hooks local to this derivation.
#### `pnpmBuildFlags` {#pnpm-build-hook-build-flags}
Controls the flags pass only to the pnpm build script invocation.
#### `dontPnpmBuild` {#pnpm-build-hook-dont}
Disables automatically running `pnpmBuildHook`. The build can still be run manually if needed, for example:
```nix
{
lib,
rustPlatform,
pnpmBuildHook,
pnpmConfigHook,
fetchPnpmDeps,
emptyDirectory,
pnpm_10,
}:
let
pnpm = pnpm_10;
in
rustPlatform.buildRustPackage (finalAttrs: {
pname = "super-fast-application";
version = "1.0";
src = emptyDirectory;
cargoHash = lib.fakeHash;
nativeBuildInputs = [
pnpmBuildHook
pnpmConfigHook
];
pnpmDeps = fetchPnpmDeps {
inherit (finalAttrs) pname version src;
inherit pnpm;
fetcherversion = 4;
hash = lib.fakeHash;
};
dontPnpmBuild = true;
postBuild = ''
pnpmBuildHook
'';
})
```
### Honored Variables {#pnpm-build-hook-honored-variables}
The following variables are honored by `pnpmBuildHook`.
* [`pnpmRoot`](#javascript-pnpm-sourceRoot)
* [`pnpmWorkspaces`](#javascript-pnpm-workspaces)

View File

@@ -1,5 +0,0 @@
# writableTmpDirAsHomeHook {#writableTmpDirAsHomeHook}
This setup hook provides a writable home directory for packages that require it.
To use, just add the hook to the `nativeBuildInputs` of the package.

View File

@@ -27,7 +27,7 @@ Alternatively, you can pass composeAndroidPackages to the `withSdk` passthrough:
} }
``` ```
These will export `ANDROID_HOME` and `ANDROID_NDK_ROOT` to the SDK and NDK directories These will export `ANDROID_SDK_ROOT` and `ANDROID_NDK_ROOT` to the SDK and NDK directories
in the specified Android build environment. in the specified Android build environment.
## Deploying an Android SDK installation with plugins {#deploying-an-android-sdk-installation-with-plugins} ## Deploying an Android SDK installation with plugins {#deploying-an-android-sdk-installation-with-plugins}
@@ -308,7 +308,7 @@ Ensure that your buildToolsVersion and ndkVersion match what is declared in andr
If you are using cmake, make sure its declared version is correct too. If you are using cmake, make sure its declared version is correct too.
Otherwise, you may get cryptic errors from aapt2 and the Android Gradle plugin warning Otherwise, you may get cryptic errors from aapt2 and the Android Gradle plugin warning
that it cannot install the build tools because the SDK directory is not writable. that it cannot install the build tools because the SDK directory is not writeable.
```gradle ```gradle
android { android {

View File

@@ -6,68 +6,46 @@ In this document and related Nix expressions, we use the term, _BEAM_, to descri
## Available versions and deprecations schedule {#available-versions-and-deprecations-schedule} ## Available versions and deprecations schedule {#available-versions-and-deprecations-schedule}
### Erlang OTP {#erlang}
Nixpkgs follows upstream Erlang in their [support lifecycle](https://erlang.org/download/otp_versions_tree.html) and keeps up to the last 3 released versions of Erlang available. Due to upstream and NixOS release timings, this may mean removal of the oldest release prior to upstream fully dropping support.
### Elixir {#elixir} ### Elixir {#elixir}
Nixpkgs follows the [official elixir deprecation schedule](https://hexdocs.pm/elixir/compatibility-and-deprecations.html) and keeps up to the last 5 released versions of Elixir available. Nixpkgs follows the [official elixir deprecation schedule](https://hexdocs.pm/elixir/compatibility-and-deprecations.html) and keeps the last 5 released versions of Elixir available.
## Structure {#beam-structure} ## Structure {#beam-structure}
All BEAM-related expressions are available via top-level package sets. It is recommended to work with a single package set to ensure consistent versions. All BEAM-related expressions are available via the top-level `beam` attribute, which includes:
- `beamPackages` - default OTP version - `interpreters`: a set of compilers running on the BEAM, including multiple Erlang/OTP versions (`beam.interpreters.erlang_22`, etc), Elixir (`beam.interpreters.elixir`) and LFE (Lisp Flavoured Erlang) (`beam.interpreters.lfe`).
- `beamMinimalPackages` - default OTP version, without wxwidgets, which saves ~1GB in closure size
There are also OTP version specific package sets, e.g. for OTP 28: - `packages`: a set of package builders (Mix and rebar3), each compiled with a specific Erlang/OTP version, e.g. `beam.packages.erlang22`.
- `beam28Packages` The default Erlang compiler, defined by `beam.interpreters.erlang`, is aliased as `erlang`. The default BEAM package set is defined by `beam.packages.erlang` and aliased at the top level as `beamPackages`.
- `beamMinimal28Packages`
Inside each package set are: To create a package builder built with a custom Erlang version, use the lambda, `beam.packagesWith`, which accepts an Erlang/OTP derivation and produces a package builder similar to `beam.packages.erlang`.
- erlang itself (version comes from package set) Many Erlang/OTP distributions available in `beam.interpreters` have versions with ODBC and/or Java enabled or without wx (no observer support). For example, there's `beam.interpreters.erlang_22_odbc_javac`, which corresponds to `beam.interpreters.erlang_22` and `beam.interpreters.erlang_22_nox`, which corresponds to `beam.interpreters.erlang_22`.
- interpreters: elixir (multiple versions, e.g. elixir_1_18) and lfe
- packages: rebar3, hex, etc
- builders: mixRelease, buildRebar3, etc
- hooks: for composing builders and packages
To use a non-default Elixir it's important to keep the rest of the package set consistent, so it's recommended to use `.extend`. This ensures that builders like `mixRelease`, `fetchMixDeps`, and `buildMix` all pick up the overridden Elixir: ## Build Tools {#build-tools}
```nix ### Rebar3 {#build-tools-rebar3}
let
beamPackages = beam27Packages.extend (self: super: { elixir = self.elixir_1_18; });
in
beamPackages.mixRelease {
# ...
}
```
## Build Tools {#beam-build-tools} We provide a version of Rebar3, under `rebar3`. We also provide a helper to fetch Rebar3 dependencies from a lockfile under `fetchRebar3Deps`.
### Rebar3 {#beam-build-tools-rebar3} We also provide a version on Rebar3 with plugins included, under `rebar3WithPlugins`. This package is a function which takes two arguments: `plugins`, a list of nix derivations to include as plugins (loaded only when specified in `rebar.config`), and `globalPlugins`, which should always be loaded by rebar3. Example: `rebar3WithPlugins { globalPlugins = [beamPackages.pc]; }`.
We provide a version of Rebar3, under `beamPackages.rebar3`. We also provide a helper to fetch Rebar3 dependencies from a lockfile under `beamPackages.fetchRebar3Deps`. When adding a new plugin it is important that the `packageName` attribute is the same as the atom used by rebar3 to refer to the plugin.
We also provide a version on Rebar3 with plugins included, under `beamPackages.rebar3WithPlugins`. This package is a function which takes two arguments: `plugins`, a list of nix derivations to include as plugins (loaded only when specified in `rebar.config`), and `globalPlugins`, which should always be loaded by rebar3. Example: `beamPackages.rebar3WithPlugins { globalPlugins = [beamPackages.pc]; }`. ### Mix & Erlang.mk {#build-tools-other}
When adding a new plugin it is important that the `name` attribute is the same as the atom used by rebar3 to refer to the plugin.
### Erlang.mk {#beam-build-tools-erlangmk}
Erlang.mk works exactly as expected. There is a bootstrap process that needs to be run, which is supported by the `buildErlangMk` derivation. Erlang.mk works exactly as expected. There is a bootstrap process that needs to be run, which is supported by the `buildErlangMk` derivation.
### Mix {#beam-build-tools-mix} For Elixir applications use `mixRelease` to make a release. See examples for more details.
For Elixir applications that use [mix release](https://hexdocs.pm/mix/Mix.Release.html), use the `mixRelease` builder to make a release. See examples for more details. There is also a `buildMix` helper, whose behavior is closer to that of `buildErlangMk` and `buildRebar3`. The primary difference is that mixRelease makes a release, while buildMix only builds the package, making it useful for libraries and other dependencies.
There is also a `buildMix` helper, whose behavior is closer to that of `buildErlangMk` and `buildRebar3`. The primary difference is that `mixRelease` makes a release, while `buildMix` only builds the package, which is more useful for libraries and other dependencies.
## How to Install BEAM Packages {#how-to-install-beam-packages} ## How to Install BEAM Packages {#how-to-install-beam-packages}
To use any of these builders in your environment, refer to them by their attribute path under `beamPackages` (or another BEAM package set), e.g. `beamPackages.rebar3`: BEAM builders are not registered at the top level, because they are not relevant to the vast majority of Nix users.
To use any of those builders into your environment, refer to them by their attribute path under `beamPackages`, e.g. `beamPackages.rebar3`:
::: {.example #ex-beam-ephemeral-shell} ::: {.example #ex-beam-ephemeral-shell}
# Ephemeral shell # Ephemeral shell
@@ -97,39 +75,35 @@ pkgs.mkShell { packages = [ pkgs.beamPackages.rebar3 ]; }
#### Rebar3 Packages {#rebar3-packages} #### Rebar3 Packages {#rebar3-packages}
The builder `beamPackages.buildRebar3` can be used to build a derivation that understands how to build a Rebar3 project. The Nix function, `buildRebar3`, defined in `beam.packages.erlang.buildRebar3` and aliased at the top level, can be used to build a derivation that understands how to build a Rebar3 project.
If a package needs to compile native code via Rebar3's port compilation mechanism, add `compilePort = true;` to the derivation.
#### Erlang.mk Packages {#erlang-mk-packages} #### Erlang.mk Packages {#erlang-mk-packages}
Erlang.mk functions similarly to Rebar3, except we use `beamPackages.buildErlangMk` instead of `beamPackages.buildRebar3`. Erlang.mk functions similarly to Rebar3, except we use `buildErlangMk` instead of `buildRebar3`.
If a package needs to compile native code via Erlang.mk's port compilation mechanism, add `compilePorts = true;` to the derivation.
### Elixir Applications {#packaging-elixir-applications}
#### Mix Packages {#mix-packages} #### Mix Packages {#mix-packages}
`beamPackages.mixRelease` is used to make a release in the mix sense. Dependencies will need to be fetched with `beamPackages.fetchMixDeps` and passed to it. `mixRelease` is used to make a release in the mix sense. Dependencies will need to be fetched with `fetchMixDeps` and passed to it.
#### mixRelease - Elixir Phoenix example {#mix-release-elixir-phoenix-example} #### mixRelease - Elixir Phoenix example {#mix-release-elixir-phoenix-example}
There are 3 steps: frontend dependencies (javascript), backend dependencies (elixir), and the final derivation that puts both of those together. there are 3 steps: frontend dependencies (javascript), backend dependencies (elixir), and the final derivation that puts both of those together
##### mixRelease - Frontend dependencies (javascript) {#mix-release-javascript-deps} ##### mixRelease - Frontend dependencies (javascript) {#mix-release-javascript-deps}
For phoenix projects, inside of Nixpkgs you can either use `fetchYarnDeps` or `buildNpmPackage`. An example with `buildNpmPackage` can be found [here](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/pl/plausible/package.nix), and an example with `fetchYarnDeps` can be found [here](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/pi/pinchflat/package.nix). For phoenix projects, inside of Nixpkgs you can either use yarn2nix (mkYarnModule) or node2nix. An example with yarn2nix can be found [here](https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/web-apps/plausible/default.nix#L39). An example with node2nix will follow. To package something outside of nixpkgs, you have alternatives like [npmlock2nix](https://github.com/nix-community/npmlock2nix) or [nix-npm-buildpackage](https://github.com/serokell/nix-npm-buildpackage)
##### mixRelease - backend dependencies (mix) {#mix-release-mix-deps} ##### mixRelease - backend dependencies (mix) {#mix-release-mix-deps}
There are 2 ways to package backend dependencies: either per-dependency mix2nix or with a fixed-output-derivation (FOD). There are 2 ways to package backend dependencies. With mix2nix and with a fixed-output-derivation (FOD).
When writing an elixir project targeting `mixRelease`, you can also consider using [deps_nix](https://github.com/code-supply/deps_nix) with `mixNixDeps`. `deps_nix` supports git dependencies, but is intended to be added to the project's `mix.exs` directly. ###### mix2nix {#mix2nix}
##### mix2nix {#mix2nix}
`mix2nix` is a cli tool available in Nixpkgs. It will generate a Nix expression from a `mix.lock` file. It is quite standard in the 2nix tool series. `mix2nix` is a cli tool available in Nixpkgs. It will generate a Nix expression from a `mix.lock` file. It is quite standard in the 2nix tool series.
Note that currently mix2nix can't handle git dependencies inside the mix.lock file. If you have git dependencies, you can either add them manually (see [example](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/pl/pleroma/package.nix)) or use the FOD method. Note that currently mix2nix can't handle git dependencies inside the mix.lock file. If you have git dependencies, you can either add them manually (see [example](https://github.com/NixOS/nixpkgs/blob/master/pkgs/servers/pleroma/default.nix#L20)) or use the FOD method.
The advantage of using mix2nix is that nix will know your whole dependency graph. On a dependency update, this won't trigger a full rebuild and download of all the dependencies, where FOD will do so. The advantage of using mix2nix is that nix will know your whole dependency graph. On a dependency update, this won't trigger a full rebuild and download of all the dependencies, where FOD will do so.
@@ -175,9 +149,9 @@ If there are git dependencies.
You will need to run the build process once to fix the hash to correspond to your new git src. You will need to run the build process once to fix the hash to correspond to your new git src.
##### FOD {#fixed-output-derivation} ###### FOD {#fixed-output-derivation}
A fixed output derivation will download mix dependencies from the internet. To ensure reproducibility, a hash will be supplied. Note that mix is relatively reproducible. An FOD generating a different hash on each run hasn't been observed (as opposed to npm where the chances are relatively high). See [akkoma](https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-name/ak/akkoma/package.nix) for a usage example of FOD. A fixed output derivation will download mix dependencies from the internet. To ensure reproducibility, a hash will be supplied. Note that mix is relatively reproducible. An FOD generating a different hash on each run hasn't been observed (as opposed to npm where the chances are relatively high). See [elixir-ls](https://github.com/NixOS/nixpkgs/blob/master/pkgs/development/beam-modules/elixir-ls/default.nix) for a usage example of FOD.
Practical steps Practical steps
@@ -202,11 +176,12 @@ Note that if after you've replaced the value, nix suggests another hash, then mi
Here is how your `default.nix` file would look for a Phoenix project. Here is how your `default.nix` file would look for a Phoenix project.
```nix ```nix
{ with import <nixpkgs> { };
# beam27Packages or beam29Packages is available if you need a particular version
beamPackages,
}:
let let
# beam.interpreters.erlang_26 is available if you need a particular version
packages = beam.packagesWith beam.interpreters.erlang;
pname = "your_project"; pname = "your_project";
version = "0.0.1"; version = "0.0.1";
@@ -216,7 +191,7 @@ let
}; };
# if using mix2nix you can use the mixNixDeps attribute # if using mix2nix you can use the mixNixDeps attribute
mixFodDeps = beamPackages.fetchMixDeps { mixFodDeps = packages.fetchMixDeps {
pname = "mix-deps-${pname}"; pname = "mix-deps-${pname}";
inherit src version; inherit src version;
# nix will complain and tell you the right value to replace this with # nix will complain and tell you the right value to replace this with
@@ -225,8 +200,11 @@ let
# if you have build time environment variables add them here # if you have build time environment variables add them here
MY_ENV_VAR = "my_value"; MY_ENV_VAR = "my_value";
}; };
nodeDependencies = (pkgs.callPackage ./assets/default.nix { }).shell.nodeDependencies;
in in
beamPackages.mixRelease { packages.mixRelease {
inherit inherit
src src
pname pname
@@ -237,6 +215,9 @@ beamPackages.mixRelease {
MY_ENV_VAR = "my_value"; MY_ENV_VAR = "my_value";
postBuild = '' postBuild = ''
ln -sf ${nodeDependencies}/lib/node_modules assets/node_modules
npm run deploy --prefix ./assets
# for external task you need a workaround for the no deps check flag # for external task you need a workaround for the no deps check flag
# https://github.com/phoenixframework/phoenix/issues/2690 # https://github.com/phoenixframework/phoenix/issues/2690
mix do deps.loadpaths --no-deps-check, phx.digest mix do deps.loadpaths --no-deps-check, phx.digest
@@ -248,14 +229,14 @@ beamPackages.mixRelease {
Setup will require the following steps: Setup will require the following steps:
- Move your secrets to runtime environment variables. For more information refer to the [runtime.exs docs](https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-runtime-configuration). On a fresh Phoenix build that would mean that both `DATABASE_URL` and `SECRET_KEY` need to be moved to `runtime.exs`. - Move your secrets to runtime environment variables. For more information refer to the [runtime.exs docs](https://hexdocs.pm/mix/Mix.Tasks.Release.html#module-runtime-configuration). On a fresh Phoenix build that would mean that both `DATABASE_URL` and `SECRET_KEY` need to be moved to `runtime.exs`.
- Generate a Nix expression for your frontend dependencies using `fetchNpmDeps`/`buildNpmPackage` or `fetchYarnDeps`, depending on whether the project uses npm or yarn - `cd assets` and `nix-shell -p node2nix --run "node2nix --development"` will generate a Nix expression containing your frontend dependencies
- commit and push those changes - commit and push those changes
- you can now `nix-build .` - you can now `nix-build .`
- To run the release, set the `RELEASE_TMP` environment variable to a directory that your program has write access to. It will be used to store the BEAM settings. - To run the release, set the `RELEASE_TMP` environment variable to a directory that your program has write access to. It will be used to store the BEAM settings.
#### Example of creating a service for an Elixir - Phoenix project {#example-of-creating-a-service-for-an-elixir---phoenix-project} #### Example of creating a service for an Elixir - Phoenix project {#example-of-creating-a-service-for-an-elixir---phoenix-project}
To create a service with your release, you could add a `service.nix` In order to create a service with your release, you could add a `service.nix`
in your project with the following in your project with the following
```nix ```nix
@@ -267,7 +248,7 @@ in your project with the following
}: }:
let let
release = pkgs.callPackage ./default.nix { }; release = pkgs.callPackage ./default.nix;
release_name = "app"; release_name = "app";
working_directory = "/home/app"; working_directory = "/home/app";
in in
@@ -339,10 +320,9 @@ Usually, we need to create a `shell.nix` file and do our development inside the
with pkgs; with pkgs;
let let
# pin OTP via beam27Packages/beam28Packages/... and Elixir via .extend elixir = beam.packages.erlang_27.elixir_1_18;
beamPackages = beam27Packages.extend (self: super: { elixir = self.elixir_1_18; });
in in
mkShell { buildInputs = [ beamPackages.elixir ]; } mkShell { buildInputs = [ elixir ]; }
``` ```
### Using an overlay {#beam-using-overlays} ### Using an overlay {#beam-using-overlays}
@@ -357,7 +337,7 @@ let
self: super: { self: super: {
elixir_1_18 = super.elixir_1_18.override { elixir_1_18 = super.elixir_1_18.override {
version = "1.18.1"; version = "1.18.1";
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA="; sha256 = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
}; };
} }
); );
@@ -375,17 +355,18 @@ Here is an example `shell.nix`.
with import <nixpkgs> { }; with import <nixpkgs> { };
let let
# pin OTP via beam27Packages/beam28Packages/... and Elixir via .extend
beamPackages = beam27Packages.extend (self: super: { elixir = self.elixir_1_18; });
# define packages to install # define packages to install
basePackages = [ basePackages = [
git git
beamPackages.elixir # replace with beam.packages.erlang.elixir_1_18 if you need
beam.packages.erlang.elixir
nodejs nodejs
postgresql_14 postgresql_14
# only used for frontend dependencies
# you are free to use yarn2nix as well
nodePackages.node2nix
# formatting js file # formatting js file
prettier nodePackages.prettier
]; ];
inputs = basePackages ++ lib.optionals stdenv.hostPlatform.isLinux [ inotify-tools ]; inputs = basePackages ++ lib.optionals stdenv.hostPlatform.isLinux [ inotify-tools ];
@@ -398,13 +379,13 @@ let
export HEX_HOME=$PWD/.nix-mix export HEX_HOME=$PWD/.nix-mix
# make hex from Nixpkgs available # make hex from Nixpkgs available
# `mix local.hex` will install hex into MIX_HOME and should take precedence # `mix local.hex` will install hex into MIX_HOME and should take precedence
export MIX_PATH="${beamPackages.hex}/lib/erlang/lib/hex/ebin" export MIX_PATH="${beam.packages.erlang.hex}/lib/erlang/lib/hex/ebin"
export PATH=$MIX_HOME/bin:$HEX_HOME/bin:$PATH export PATH=$MIX_HOME/bin:$HEX_HOME/bin:$PATH
export LANG=C.UTF-8 export LANG=C.UTF-8
# keep your shell history in iex # keep your shell history in iex
export ERL_AFLAGS="-kernel shell_history enabled" export ERL_AFLAGS="-kernel shell_history enabled"
# postgres related # postges related
# keep all your db data in a folder inside the project # keep all your db data in a folder inside the project
export PGDATA="$PWD/db" export PGDATA="$PWD/db"

View File

@@ -36,19 +36,19 @@ Dart supports multiple [outputs types](https://dart.dev/tools/dart-compile#types
fetchFromGitHub, fetchFromGitHub,
}: }:
buildDartApplication (finalAttrs: { buildDartApplication rec {
pname = "dart-sass"; pname = "dart-sass";
version = "1.62.1"; version = "1.62.1";
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "sass"; owner = "sass";
repo = "dart-sass"; repo = "dart-sass";
tag = finalAttrs.version; tag = version;
hash = "sha256-U6enz8yJcc4Wf8m54eYIAnVg/jsGi247Wy8lp1r1wg4="; hash = "sha256-U6enz8yJcc4Wf8m54eYIAnVg/jsGi247Wy8lp1r1wg4=";
}; };
pubspecLock = lib.importJSON ./pubspec.lock.json; pubspecLock = lib.importJSON ./pubspec.lock.json;
}) }
``` ```
### Patching dependencies {#ssec-dart-applications-patching-dependencies} ### Patching dependencies {#ssec-dart-applications-patching-dependencies}
@@ -102,14 +102,14 @@ The function `buildFlutterApplication` builds Flutter applications.
See the [Dart documentation](#ssec-dart-applications) for more details on required files and arguments. See the [Dart documentation](#ssec-dart-applications) for more details on required files and arguments.
`flutter` in Nixpkgs always points to `flutterPackages.stable`, which is the latest packaged version. To avoid unforeseen breakage during upgrade, packages in Nixpkgs should use a specific flutter version, such as `flutter335` and `flutter338`, instead of using `flutter` directly. `flutter` in Nixpkgs always points to `flutterPackages.stable`, which is the latest packaged version. To avoid unforeseen breakage during upgrade, packages in Nixpkgs should use a specific flutter version, such as `flutter319` and `flutter322`, instead of using `flutter` directly.
```nix ```nix
{ flutter335, fetchFromGitHub }: { flutter322, fetchFromGitHub }:
flutter335.buildFlutterApplication (finalAttrs: { flutter322.buildFlutterApplication {
pname = "firmware-updater"; pname = "firmware-updater";
version = "0-unstable-2025-09-09"; version = "0-unstable-2023-04-30";
# To build for the Web, use the targetFlutterPlatform argument. # To build for the Web, use the targetFlutterPlatform argument.
# targetFlutterPlatform = "web"; # targetFlutterPlatform = "web";
@@ -117,17 +117,13 @@ flutter335.buildFlutterApplication (finalAttrs: {
src = fetchFromGitHub { src = fetchFromGitHub {
owner = "canonical"; owner = "canonical";
repo = "firmware-updater"; repo = "firmware-updater";
rev = "402e97254b9d63c8d962c46724995e377ff922c8"; rev = "6e7dbdb64e344633ea62874b54ff3990bd3b8440";
hash = "sha256-nQn5mlgNj157h++67+mhez/F1ALz4yY+bxiGsi0/xX8="; hash = "sha256-s5mwtr5MSPqLMN+k851+pFIFFPa0N1hqz97ys050tFA=";
fetchSubmodules = true; fetchSubmodules = true;
}; };
pubspecLock = lib.importJSON ./pubspec.lock.json; pubspecLock = lib.importJSON ./pubspec.lock.json;
}
sourceRoot = "${finalAttrs.src.name}/apps/firmware_updater";
gitHashes.fwupd = "sha256-l/+HrrJk1mE2Mrau+NmoQ7bu9qhHU6wX68+m++9Hjd4=";
})
``` ```
### Usage with nix-shell {#ssec-dart-flutter-nix-shell} ### Usage with nix-shell {#ssec-dart-flutter-nix-shell}

View File

@@ -205,7 +205,7 @@ pkgs.buildEmscriptenPackage {
## Debugging {#declarative-debugging} ## Debugging {#declarative-debugging}
Use `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz` and from there you can go through the individual steps. This makes it easy to build a good `unit test` or list the files of the project. Use `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz` and from there you can go trough the individual steps. This makes it easy to build a good `unit test` or list the files of the project.
1. `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz` 1. `nix-shell -I nixpkgs=/some/dir/nixpkgs -A emscriptenPackages.libz`
2. `cd /tmp/` 2. `cd /tmp/`

View File

@@ -105,7 +105,7 @@ Given the requirements above, the package expression would become messy quickly:
} }
``` ```
Fortunately, we have a [family of hooks]{#ssec-gnome-hooks-wrapgappshook} that automate this. They work in conjunction with other setup hooks that populate environment variables, and will then wrap all executables in `bin` and `libexec` directories using said variables. If a package has multiple outputs, these hooks will work on `outputBin` by default, or on the outputs listed in `wrapGAppsInOutputs` if set. Fortunately, we have a [family of hooks]{#ssec-gnome-hooks-wrapgappshook} that automate this. They work in conjunction with other setup hooks that populate environment variables, and will then wrap all executables in `bin` and `libexec` directories using said variables.
- [`wrapGAppsHook3`]{#ssec-gnome-hooks-wrapgappshook3} for GTK 3 apps. For convenience, it also adds `dconf.lib` for a GIO module implementing a GSettings backend using `dconf`, `gtk3` for GSettings schemas, and `librsvg` for GdkPixbuf loader to the closure. - [`wrapGAppsHook3`]{#ssec-gnome-hooks-wrapgappshook3} for GTK 3 apps. For convenience, it also adds `dconf.lib` for a GIO module implementing a GSettings backend using `dconf`, `gtk3` for GSettings schemas, and `librsvg` for GdkPixbuf loader to the closure.
- [`wrapGAppsHook4`]{#ssec-gnome-hooks-wrapgappshook4} for GTK 4 apps. Same as `wrapGAppsHook3` but replaces `gtk3` with `gtk4`. - [`wrapGAppsHook4`]{#ssec-gnome-hooks-wrapgappshook4} for GTK 4 apps. Same as `wrapGAppsHook3` but replaces `gtk3` with `gtk4`.

View File

@@ -101,7 +101,6 @@ If `true`, the intermediate fetcher downloads dependencies from the
This is useful if your code depends on C code and `go mod tidy` does not include the needed sources to build or This is useful if your code depends on C code and `go mod tidy` does not include the needed sources to build or
if any dependency has case-insensitive conflicts which will produce platform-dependent `vendorHash` checksums. if any dependency has case-insensitive conflicts which will produce platform-dependent `vendorHash` checksums.
It may also be needed if the module targets language version 1.16 or earlier, since vendoring compiles all dependencies against language version 1.16 in this case.
Defaults to `false`. Defaults to `false`.

View File

@@ -679,7 +679,7 @@ Defaults to `false`.
`genericBuilderArgsModifier` `genericBuilderArgsModifier`
: This argument accepts a function allowing you to modify the arguments passed : This argument accepts a function allowing you to modify the arguments passed
to `mkDerivation` to create the development environment. For example, to `mkDerivation` in order to create the development environment. For example,
`args: { doCheck = false; }` would cause the environment to not include any test `args: { doCheck = false; }` would cause the environment to not include any test
dependencies. Defaults to `lib.id`. dependencies. Defaults to `lib.id`.

View File

@@ -2,10 +2,6 @@
The [standard build environment](#chap-stdenv) makes it easy to build typical Autotools-based packages with very little code. Any other kind of package can be accommodated by overriding the appropriate phases of `stdenv`. However, there are specialised functions in Nixpkgs to easily build packages for other programming languages, such as Perl or Haskell. These are described in this chapter. The [standard build environment](#chap-stdenv) makes it easy to build typical Autotools-based packages with very little code. Any other kind of package can be accommodated by overriding the appropriate phases of `stdenv`. However, there are specialised functions in Nixpkgs to easily build packages for other programming languages, such as Perl or Haskell. These are described in this chapter.
::: {.tip}
New to packaging? Start with [](#chap-first-package), then return here for the ecosystem you need.
:::
Each supported language or software ecosystem has its own package set named `<language or ecosystem>Packages`, which can be explored in various ways: Each supported language or software ecosystem has its own package set named `<language or ecosystem>Packages`, which can be explored in various ways:
- Search on [search.nixos.org](https://search.nixos.org/packages) - Search on [search.nixos.org](https://search.nixos.org/packages)
@@ -21,7 +17,7 @@ Each supported language or software ecosystem has its own package set named `<la
# Navigate Java compiler variants in `javaPackages` with `nix repl` # Navigate Java compiler variants in `javaPackages` with `nix repl`
```shell-session ```shell-session
$ nix repl -f '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable $ nix repl '<nixpkgs>' -I nixpkgs=channel:nixpkgs-unstable
nix-repl> javaPackages.<tab> nix-repl> javaPackages.<tab>
javaPackages.compiler javaPackages.openjfx15 javaPackages.openjfx21 javaPackages.recurseForDerivations javaPackages.compiler javaPackages.openjfx15 javaPackages.openjfx21 javaPackages.recurseForDerivations
javaPackages.jogl_2_4_0 javaPackages.openjfx17 javaPackages.openjfx25 javaPackages.jogl_2_4_0 javaPackages.openjfx17 javaPackages.openjfx25
@@ -60,6 +56,7 @@ android.section.md
astal.section.md astal.section.md
beam.section.md beam.section.md
chicken.section.md chicken.section.md
rocq.section.md
cosmic.section.md cosmic.section.md
crystal.section.md crystal.section.md
cuda.section.md cuda.section.md
@@ -82,7 +79,6 @@ ios.section.md
java.section.md java.section.md
javascript.section.md javascript.section.md
julia.section.md julia.section.md
lean4.section.md
lisp.section.md lisp.section.md
lua.section.md lua.section.md
maven.section.md maven.section.md
@@ -95,7 +91,6 @@ pkg-config.section.md
python.section.md python.section.md
qt.section.md qt.section.md
r.section.md r.section.md
rocq.section.md
ruby.section.md ruby.section.md
rust.section.md rust.section.md
scheme.section.md scheme.section.md

Some files were not shown because too many files have changed in this diff Show More