Compare commits

..

1 Commits

Author SHA1 Message Date
yaya
705e992991 26.05 beta release 2026-05-24 13:32:15 +02:00
22121 changed files with 374016 additions and 617342 deletions

View File

@@ -23,15 +23,15 @@ insert_final_newline = false
# see https://nixos.org/nixpkgs/manual/#chap-conventions
[*.{bash,css,js,json,lock,md,nix,pl,pm,py,rb,sh,ts,xml}]
[*.{bash,css,js,json,lock,md,nix,pl,pm,py,rb,sh,xml}]
indent_style = space
# Match docbook files, set indent width of one
[*.xml]
indent_size = 1
# Match js/json/lockfiles/markdown/nix/ruby/ts files, set indent width of two
[*.{js,json,lock,md,nix,rb,ts}]
# Match json/lockfiles/markdown/nix/ruby files, set indent width of two
[*.{js,json,lock,md,nix,rb}]
indent_size = 2
# Match all the Bash code in Nix files, set indent width of two
@@ -79,7 +79,7 @@ indent_size = unset
trim_trailing_whitespace = true
# binaries
[*.{nib,torrent}]
[*.nib]
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset

3
.gitattributes vendored
View File

@@ -62,6 +62,3 @@ ci/OWNERS linguist-language=CODEOWNERS
# patching CRLF line endings from an upstream source package.
*.diff !text !eol
*.patch !text !eol
# Torrent files are binary files and should not be re-encoded.
*.torrent !text !eol

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.
options:
- "Please select a version."
- "- Unstable (26.11)"
- "- Stable (26.05)"
- "- Unstable (26.05)"
- "- Stable (25.11)"
default: 0
validations:
required: true

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.
options:
- "Please select a version."
- "- Unstable (26.11)"
- "- Stable (26.05)"
- "- Unstable (26.05)"
- "- Stable (25.11)"
default: 0
validations:
required: true
@@ -99,7 +99,7 @@ body:
attributes:
label: "Are you using nix-darwin?"
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:
- "Yes, I am using nix-darwin."
- "No, I am not using nix-darwin."

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.
options:
- "Please select a version."
- "- Unstable (26.11)"
- "- Stable (26.05)"
- "- Unstable (26.05)"
- "- Stable (25.11)"
default: 0
validations:
required: true

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).
options:
- "Please select a version."
- "- Unstable (26.11)"
- "- Stable (26.05)"
- "- Unstable (26.05)"
- "- Stable (25.11)"
default: 0
validations:
required: true
@@ -56,12 +56,12 @@ body:
description: |
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.
- 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/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/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-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-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-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.
- 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/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-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-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.**'
options:
- "Please select the Hydra Status."

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.
options:
- "Please select a version."
- "- Unstable (26.11)"
- "- Stable (26.05)"
- "- Unstable (26.05)"
- "- Stable (25.11)"
default: 0
validations:
required: true

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.
options:
- "Please select a version."
- "- Unstable (26.11)"
- "- Stable (26.05)"
- "- Unstable (26.05)"
- "- Stable (25.11)"
default: 0
validations:
required: true

View File

@@ -13,6 +13,7 @@ For new packages please briefly describe the package or provide a link to its ho
- Built on platform:
- [ ] x86_64-linux
- [ ] aarch64-linux
- [ ] x86_64-darwin
- [ ] aarch64-darwin
- Tested, as applicable:
- [ ] [NixOS tests] in [nixos/tests].

View File

@@ -13,13 +13,12 @@ inputs:
runs:
using: composite
steps:
- uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
- uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0
env:
MERGED_SHA: ${{ inputs.merged-as-untrusted-at }}
TARGET_SHA: ${{ inputs.target-as-trusted-at }}
PIN_BUMP_SHA: ${{ inputs.untrusted-pin-bump }}
with:
retries: 3
script: |
const { rm, writeFile } = require('node:fs/promises')
const { spawn } = require('node:child_process')

View File

@@ -1,9 +1,7 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directories:
- "/"
- ".github/actions/*/*"
directory: "/"
schedule:
interval: "weekly"
labels: []

View File

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

21
.github/labeler.yml vendored
View File

@@ -9,7 +9,6 @@
- '^release-'
- '^staging-\d'
- '^staging-next-\d'
- '^staging-nixos-\d'
# NOTE: bsd, darwin and cross-compilation labels are handled by ofborg
"6.topic: agda":
@@ -43,6 +42,14 @@
- .github/**/*
- ci/**/*.*
"6.topic: coq":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/applications/science/logic/coq/**/*
- pkgs/development/coq-modules/**/*
- pkgs/top-level/coq-packages.nix
"6.topic: COSMIC":
- any:
- changed-files:
@@ -458,18 +465,6 @@
- any-glob-to-any-file:
- pkgs/development/rocm-modules/**/*
"6.topic: rocq":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/applications/science/logic/coq/**/*
- pkgs/applications/science/logic/rocq-core/**/*
- pkgs/build-support/coq/**/*
- pkgs/build-support/rocq/**/*
- pkgs/development/rocq-modules/**/*
- pkgs/top-level/coq-packages.nix
- pkgs/top-level/rocq-packages.nix
"6.topic: ruby":
- any:
- changed-files:

View File

@@ -21,7 +21,7 @@ defaults:
jobs:
backport:
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
timeout-minutes: 3
steps:
@@ -30,17 +30,15 @@ jobs:
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
id: app-token
with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write
permission-workflows: write
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
ref: ${{ github.event.pull_request.head.sha }}
# Avoid materializing full nixpkgs tree
sparse-checkout: .
token: ${{ steps.app-token.outputs.token }}
persist-credentials: true
@@ -51,7 +49,7 @@ jobs:
- name: Create backport PRs
id: backport
uses: korthout/backport-action@2e830a1d0b8269505846ddd407a70876913ad1f8 # v4.6.0
uses: korthout/backport-action@66065406958f46e82238fd59546f5a99e69e22aa # v4.5.2
with:
# Config README: https://github.com/korthout/backport-action#backport-action
add_author_as_reviewer: true

View File

@@ -41,23 +41,26 @@ jobs:
run:
runs-on: ubuntu-slim
if: github.event_name != 'schedule' || github.repository_owner == 'NixOS'
env:
# TODO: Remove after 2026-03-04, when Node 24 becomes the default.
# https://github.blog/changelog/2025-09-19-deprecation-of-node-20-on-github-actions-runners/
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24: "true"
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: |
ci/github-script
- name: Install dependencies
run: npm ci --package-lock-only=false --no-audit @actions/artifact bottleneck
working-directory: ci/github-script
run: npm install @actions/artifact@6.2.1 bottleneck@2.19.5
# 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
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
with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-administration: read
permission-contents: write
@@ -76,8 +79,7 @@ jobs:
github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 3
script: |
const { default: bot } = await import('${{ github.workspace }}/ci/github-script/bot.js')
await bot({
require('./ci/github-script/bot.js')({
github,
context,
core,
@@ -89,7 +91,7 @@ jobs:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
name: Labels from touched files
if: |
github.event_name == 'pull_request_target' &&
@@ -99,7 +101,7 @@ jobs:
configuration-path: .github/labeler.yml # default
sync-labels: true
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
name: Labels from touched files (no sync)
if: |
github.event_name == 'pull_request_target' &&
@@ -109,7 +111,7 @@ jobs:
configuration-path: .github/labeler-no-sync.yml
sync-labels: false
- uses: actions/labeler@bf12e9b00b37c5c0ca2b87b79b2daf7891dbda13 # v7.0.0
- uses: actions/labeler@f27b608878404679385c85cfa523b85ccb86e213 # v6.1.0
name: Labels from touched files (development branches)
# 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

View File

@@ -34,22 +34,25 @@ jobs:
matrix:
include:
- runner: ubuntu-24.04
system: x86_64-linux
name: x86_64-linux
systems: x86_64-linux
builds: [shell, manual-nixos, lib-tests, tarball]
desc: shell, docs, lib, tarball
- runner: ubuntu-24.04-arm
system: aarch64-linux
name: aarch64-linux
systems: aarch64-linux
builds: [shell, manual-nixos, manual-nixpkgs]
desc: shell, docs
- runner: macos-14
system: aarch64-darwin
name: darwin
systems: aarch64-darwin x86_64-darwin
builds: [shell]
desc: shell
name: '${{ matrix.system }}: ${{ matrix.desc }}'
name: '${{ matrix.name }}: ${{ matrix.desc }}'
runs-on: ${{ matrix.runner }}
timeout-minutes: 60
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
@@ -59,7 +62,7 @@ jobs:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
target-as-trusted-at: ${{ inputs.targetSha }}
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
with:
# Sandbox is disabled on MacOS by default.
extra_nix_config: sandbox = true
@@ -77,9 +80,7 @@ jobs:
- name: Build shell
if: contains(matrix.builds, 'shell')
env:
system: ${{ matrix.system }}
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A shell --argstr system "$system"
run: echo "${{ matrix.systems }}" | xargs -n1 nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A shell --argstr system
- name: Build NixOS manual
if: |
@@ -107,5 +108,5 @@ jobs:
contains(fromJSON(inputs.baseBranch).type, 'primary')
uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
with:
name: ${{ inputs.artifact-prefix }}nixos-manual-${{ matrix.system }}
name: ${{ inputs.artifact-prefix }}nixos-manual-${{ matrix.name }}
path: nixos-manual

View File

@@ -43,7 +43,7 @@ jobs:
runs-on: ubuntu-slim
timeout-minutes: 3
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
path: trusted
@@ -51,8 +51,7 @@ jobs:
ci/github-script
- name: Install dependencies
run: npm ci --package-lock-only=false --no-audit bottleneck
working-directory: trusted/ci/github-script
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
@@ -76,8 +75,7 @@ jobs:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: |
const targetsStable = JSON.parse(process.env.TARGETS_STABLE)
const { default: commits } = await import('${{ github.workspace }}/trusted/ci/github-script/commits.js')
await commits({
require('./trusted/ci/github-script/commits.js')({
github,
context,
core,
@@ -94,10 +92,10 @@ jobs:
if: inputs.baseBranch && inputs.headBranch
permissions:
pull-requests: write
runs-on: ubuntu-24.04-arm
timeout-minutes: 8
runs-on: ubuntu-slim
timeout-minutes: 3
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
path: trusted
@@ -122,8 +120,7 @@ jobs:
with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: |
const { default: checkManualFileEdits } = await import('${{ github.workspace }}/trusted/ci/github-script/manual-file-edits.js')
await checkManualFileEdits({
require('./trusted/ci/github-script/manual-file-edits.js')({
github,
context,
core,
@@ -136,51 +133,21 @@ jobs:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq
github-script:
runs-on: ubuntu-24.04-arm
timeout-minutes: 5
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
with:
persist-credentials: false
sparse-checkout: .github/actions
- name: Checkout merge and target commits
uses: ./.github/actions/checkout
with:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
target-as-trusted-at: ${{ inputs.targetSha }}
- name: Install dependencies to trusted/
run: |
npm ci --package-lock-only=false --no-audit
echo "$PWD/node_modules/.bin" >> "$GITHUB_PATH"
working-directory: nixpkgs/trusted/ci/github-script
- name: Link trusted/ dependencies to untrusted/
run: ln -s "$PWD/trusted/ci/github-script/node_modules" untrusted/ci/github-script/node_modules
working-directory: nixpkgs
- name: Check ci/github-script
run: npm test
working-directory: nixpkgs/untrusted/ci/github-script
owners:
runs-on: ubuntu-24.04-arm
timeout-minutes: 5
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
- name: Checkout merge and target commits
uses: ./.github/actions/checkout
with:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
target-as-trusted-at: ${{ inputs.targetSha }}
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17
continue-on-error: true

View File

@@ -23,7 +23,7 @@ jobs:
timeout-minutes: 2
if: contains(github.event.comment.body, '@NixOS/nixpkgs-merge-bot merge')
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: |
@@ -31,10 +31,10 @@ jobs:
# 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
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
with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-pull-requests: write
@@ -43,7 +43,7 @@ jobs:
github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 3
script: |
const { handleMergeComment } = await import('${{ github.workspace }}/ci/github-script/merge.js')
const { handleMergeComment } = require('./ci/github-script/merge.js')
const { body, node_id } = context.payload.comment
await handleMergeComment({

View File

@@ -39,7 +39,7 @@ jobs:
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
id: app-token
with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-pull-requests: write

View File

@@ -15,9 +15,6 @@ on:
targetSha:
required: true
type: string
baseBranch:
required: true
type: string
systems:
required: true
type: string
@@ -50,7 +47,7 @@ jobs:
ciPinBumpCommit: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommit }}
ciPinBumpCommitShort: ${{ steps.find-pinned-commit.outputs.ciPinBumpCommitShort }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
path: trusted
@@ -58,7 +55,7 @@ jobs:
ci/supportedVersions.nix
- 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:
persist-credentials: false
ref: ${{ inputs.mergedSha }}
@@ -139,7 +136,7 @@ jobs:
core.info(`Found pinned.json commit: ${ciPinBumpCommit}`)
- name: Install Nix
uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Load supported versions
id: versions
@@ -174,7 +171,7 @@ jobs:
sudo mkswap /swap
sudo swapon /swap
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
@@ -187,7 +184,7 @@ jobs:
target-as-trusted-at: ${{ inputs.targetSha }}
- name: Install Nix
uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17
continue-on-error: true
@@ -259,7 +256,7 @@ jobs:
statuses: write # creating 'Eval Summary' commit statuses
timeout-minutes: 5
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
@@ -277,7 +274,7 @@ jobs:
merge-multiple: true
- name: Install Nix
uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Combine all output paths and eval stats
run: |
@@ -294,7 +291,6 @@ jobs:
- name: Compare against the target branch
env:
TARGET_SHA: ${{ inputs.mergedSha }}
BASE_BRANCH: ${{ fromJSON(inputs.baseBranch).branch }}
run: |
git -C nixpkgs/trusted diff --name-only "$TARGET_SHA" \
| jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json
@@ -303,7 +299,6 @@ jobs:
nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.compare \
--arg combinedDir ./combined \
--arg touchedFilesJson ./touched-files.json \
--argstr baseBranch "$BASE_BRANCH" \
--out-link comparison
cat comparison/step-summary.md >> "$GITHUB_STEP_SUMMARY"
@@ -375,8 +370,7 @@ jobs:
with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
script: |
const { checkTargetBranch } = await import('${{ github.workspace }}/nixpkgs/trusted/ci/github-script/check-target-branch.ts')
await checkTargetBranch({
require('./nixpkgs/trusted/ci/github-script/check-target-branch.js')({
github,
context,
core,
@@ -477,7 +471,7 @@ jobs:
runs-on: ubuntu-24.04-arm
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
@@ -487,7 +481,7 @@ jobs:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
- name: Install Nix
uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- name: Ensure flake outputs on all systems still evaluate
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
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
@@ -35,7 +35,7 @@ jobs:
with:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
# 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.
@@ -61,7 +61,7 @@ jobs:
runs-on: ubuntu-24.04-arm
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
@@ -70,7 +70,7 @@ jobs:
with:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17
continue-on-error: true
@@ -90,7 +90,7 @@ jobs:
runs-on: ubuntu-24.04-arm
timeout-minutes: 10
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: .github/actions
@@ -100,7 +100,7 @@ jobs:
merged-as-untrusted-at: ${{ inputs.mergedSha }}
target-as-trusted-at: ${{ inputs.targetSha }}
- uses: cachix/install-nix-action@13d8dd58da0234aa297dedd986986ccb8e7f3e24 # v31.11.1
- uses: cachix/install-nix-action@8aa03977d8d733052d78f4e008a241fd1dbf36b3 # v31.10.6
- uses: cachix/cachix-action@5f2d7c5294214f71b873db4b969586b980625e71 # v17
continue-on-error: true
@@ -131,10 +131,10 @@ jobs:
# 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.
if: ${{ github.event.pull_request.number }}
runs-on: ubuntu-24.04-arm
timeout-minutes: 8
runs-on: ubuntu-slim
timeout-minutes: 5
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: true # Needed to run git fetch for large PRs.
path: trusted
@@ -142,9 +142,9 @@ jobs:
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
script: |
const { default: checkCommitMessages } = await import('${{ github.workspace }}/trusted/ci/github-script/lint-commits.js')
const checkCommitMessages = require('./trusted/ci/github-script/lint-commits.js')
await checkCommitMessages({
checkCommitMessages({
github,
context,
core,

View File

@@ -25,11 +25,11 @@ jobs:
targetSha: ${{ steps.prepare.outputs.targetSha }}
systems: ${{ steps.prepare.outputs.systems }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: |
ci/github-script
ci/github-script/supportedSystems.js
- id: prepare
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
@@ -38,8 +38,8 @@ jobs:
TARGET_SHA: ${{ inputs.targetSha }}
with:
script: |
const { classify } = await import('${{ github.workspace }}/ci/github-script/supportedBranches.js')
const { default: supportedSystems } = await import('${{ github.workspace }}/ci/github-script/supportedSystems.js')
const { classify } = require('./ci/supportedBranches.js')
const supportedSystems = require('./ci/github-script/supportedSystems.js')
const baseBranch = (
context.payload.merge_group?.base_ref ??
@@ -97,7 +97,6 @@ jobs:
artifact-prefix: ${{ inputs.artifact-prefix }}
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
targetSha: ${{ needs.prepare.outputs.targetSha }}
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
systems: ${{ needs.prepare.outputs.systems }}
build:

View File

@@ -22,7 +22,7 @@ defaults:
jobs:
periodic-merge:
if: github.repository_owner == 'NixOS' || github.event_name == 'workflow_dispatch'
if: github.repository_owner == 'NixOS'
strategy:
# don't fail fast, so that all pairs are tried
fail-fast: false
@@ -31,12 +31,14 @@ jobs:
max-parallel: 1
matrix:
pairs:
- from: release-26.05
- from: release-25.11
into: staging-next-25.11
- from: staging-next-25.11
into: staging-25.11
- from: master
into: staging-next-26.05
- from: staging-next-26.05
into: staging-26.05
- from: release-26.05
into: staging-nixos-26.05
- name: merge-base(master,staging) → haskell-updates
from: master staging
into: haskell-updates
@@ -47,34 +49,3 @@ jobs:
name: ${{ matrix.pairs.name || format('{0} → {1}', matrix.pairs.from, matrix.pairs.into) }}
secrets:
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:
periodic-merge:
if: github.repository_owner == 'NixOS' || github.event_name == 'workflow_dispatch'
if: github.repository_owner == 'NixOS'
strategy:
# don't fail fast, so that all pairs are tried
fail-fast: false

View File

@@ -29,12 +29,12 @@ jobs:
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
id: app-token
with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-contents: write
permission-pull-requests: write
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false

View File

@@ -36,7 +36,7 @@ jobs:
systems: ${{ steps.prepare.outputs.systems }}
touched: ${{ steps.prepare.outputs.touched }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout-cone-mode: true # default, for clarity
@@ -64,8 +64,7 @@ jobs:
# https://github.com/octokit/plugin-retry.js/blob/9a2443746c350b3beedec35cf26e197ea318a261/src/index.ts#L14
retry-exempt-status-codes: 400,401,403,404
script: |
const { default: prepare } = await import('${{ github.workspace }}/ci/github-script/prepare.js')
await prepare({
require('./ci/github-script/prepare.js')({
github,
context,
core,
@@ -111,7 +110,6 @@ jobs:
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
headSha: ${{ github.event.pull_request.head.sha }}
targetSha: ${{ needs.prepare.outputs.targetSha }}
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
systems: ${{ needs.prepare.outputs.systems }}
testVersions: ${{ contains(fromJSON(needs.prepare.outputs.touched), 'pinned') && !contains(fromJSON(needs.prepare.outputs.headBranch).type, 'development') }}

View File

@@ -20,7 +20,7 @@ jobs:
runs-on: ubuntu-slim
timeout-minutes: 2
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: |
@@ -28,10 +28,10 @@ jobs:
# 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
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
with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-pull-requests: write
@@ -40,7 +40,7 @@ jobs:
github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 3
script: |
const { handleMergeComment } = await import('${{ github.workspace }}/ci/github-script/merge.js')
const { handleMergeComment } = require('./ci/github-script/merge.js')
// PRs from forks don't have any PRs associated by default.
// Thus, we request the PR number with an API call *to* the fork's repo.

View File

@@ -2,7 +2,7 @@ name: Teams
on:
schedule:
# Every Monday at 19:42 (randomly chosen)
# Every Tuesday at 19:42 (randomly chosen)
- cron: '42 19 * * 1'
workflow_dispatch:
@@ -22,7 +22,7 @@ jobs:
- uses: actions/create-github-app-token@bcd2ba49218906704ab6c1aa796996da409d3eb1 # v3.2.0
id: app-token
with:
client-id: ${{ vars.NIXPKGS_CI_CLIENT_ID }}
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-administration: read
permission-contents: write
@@ -30,7 +30,7 @@ jobs:
permission-pull-requests: write
- name: Fetch source
uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout: |
@@ -38,16 +38,14 @@ jobs:
maintainers/github-teams.json
- name: Install dependencies
run: npm ci --package-lock-only=false --no-audit bottleneck
working-directory: ci/github-script
run: npm install bottleneck@2.19.5
- name: Synchronise teams
uses: actions/github-script@3a2844b7e9c422d3c10d287c895573f7108da1b3 # v9.0.0
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
const { default: getTeams } = await import('${{ github.workspace }}/ci/github-script/get-teams.js')
await getTeams({
require('./ci/github-script/get-teams.js')({
github,
context,
core,
@@ -79,3 +77,4 @@ jobs:
This is an automated PR to sync the GitHub teams with access to this repository to the `lib.teams` list.
This PR can be merged without taking any further action.

View File

@@ -19,7 +19,7 @@ jobs:
push: ${{ steps.files.outputs.push }}
targetSha: ${{ steps.prepare.outputs.targetSha }}
steps:
- uses: actions/checkout@df4cb1c069e1874edd31b4311f1884172cec0e10 # v6.0.3
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
with:
persist-credentials: false
sparse-checkout-cone-mode: true # default, for clarity
@@ -35,8 +35,7 @@ jobs:
# https://github.com/octokit/plugin-retry.js/blob/9a2443746c350b3beedec35cf26e197ea318a261/src/index.ts#L14
retry-exempt-status-codes: 400,401,403,404
script: |
const { default: prepare } = await import('${{ github.workspace }}/ci/github-script/prepare.js')
await prepare({
require('./ci/github-script/prepare.js')({
github,
context,
core,
@@ -62,12 +61,9 @@ jobs:
'.github/workflows/lint.yml',
'.github/workflows/merge-group.yml',
'.github/workflows/test.yml',
'ci/github-script/package.json',
'ci/github-script/package-lock.json',
'ci/github-script/supportedBranches.js',
'ci/github-script/supportedSystems.js',
'ci/pinned.json',
'pkgs/top-level/release-supported-systems.json',
'ci/supportedBranches.js',
].includes(file))) core.setOutput('merge-group', true)
if (files.some(file => [
@@ -80,21 +76,18 @@ jobs:
'.github/workflows/pull-request-target.yml',
'.github/workflows/test.yml',
'ci/github-script/bot.js',
'ci/github-script/check-target-branch.ts',
'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/package.json',
'ci/github-script/package-lock.json',
'ci/github-script/prepare.js',
'ci/github-script/reviewers.js',
'ci/github-script/reviews.js',
'ci/github-script/supportedBranches.js',
'ci/github-script/supportedSystems.js',
'ci/github-script/withRateLimit.js',
'ci/pinned.json',
'pkgs/top-level/release-supported-systems.json',
'ci/supportedBranches.js',
].includes(file))) core.setOutput('pr', true)
merge-group:

3
.gitignore vendored
View File

@@ -27,9 +27,6 @@ tags
.mypy_cache
__pycache__
/AGENTS.md
/CLAUDE.md
/pkgs/development/libraries/qt-5/*/tmp/
/pkgs/desktops/kde-5/*/tmp/
/pkgs/development/mobile/androidenv/xml/*

View File

@@ -6,7 +6,6 @@ Christina Sørensen <christina@cafkafk.com> <christinaafk@gmail.com>
Christina Sørensen <christina@cafkafk.com> <89321978+cafkafk@users.noreply.github.com>
Daniel Løvbrøtte Olsen <me@dandellion.xyz> <daniel.olsen99@gmail.com>
Ethan Carter Edwards <ethan@ethancedwards.com> Ethan Edwards <ethancarteredwards@gmail.com>
Ethan Carter Edwards <ethan@ethancedwards.com> <ethancedwards8@users.noreply.github.com>
Fabian Affolter <mail@fabian-affolter.ch> <fabian@affolter-engineering.ch>
Fiona Behrens <me@kloenk.dev>
Fiona Behrens <me@kloenk.dev> <me@kloenk.de>
@@ -18,7 +17,6 @@ jopejoe1 <nixpkgs@missing.ninja> <34899572+jopejoe1@users.noreply.github.com>
jopejoe1 <nixpkgs@missing.ninja> <jopejoe1@missing.ninja>
jopejoe1 <nixpkgs@missing.ninja> <jopejoe1>
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> <75130626+jian-lin@users.noreply.github.com>
Martin Weinelt <hexa@darmstadt.ccc.de> <mweinelt@users.noreply.github.com>

View File

@@ -442,7 +442,6 @@ The staging workflow is used for all stable branches with corresponding names:
- `master`/`release-YY.MM`
- `staging`/`staging-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
@@ -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.
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 PR is a change affecting the Linux kernel.
@@ -571,10 +570,7 @@ If a contributor does not want committers to push to their branch, they must unc
### Release notes
If you add or remove a NixOS module, or make other breaking or significant NixOS changes, write about it in the next NixOS release notes in [`nixos/doc/manual/release-notes`](./nixos/doc/manual/release-notes).
If you make major or breaking changes to a package (other than removal), write about it in the next Nixpkgs release notes in [`doc/release-notes`](./doc/release-notes).
Package removals should not get a Nixpkgs release note, [a throwing alias should be added instead](./pkgs/README.md#steps-to-remove-a-package-from-nixpkgs).
If you removed packages or made some major NixOS changes, write about it in the next release notes in [`nixos/doc/manual/release-notes`](./nixos/doc/manual/release-notes).
### File naming and organisation
@@ -587,9 +583,9 @@ CI [enforces](./.github/workflows/lint.yml) all Nix files to be formatted using
You can ensure this locally using either of these commands:
```
nix fmt
nix develop --command treefmt
nix-shell --run treefmt
nix develop --command treefmt
nix fmt
```
If you're starting your editor in `nix-shell` or `nix develop`, you can also set it up to automatically run `treefmt` on save.
@@ -957,6 +953,7 @@ The following situations are fully or partially exempt:
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”.

View File

@@ -1,9 +1,9 @@
<p align="center">
<a href="https://nixos.org">
<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: dark)" srcset="https://brand.nixos.org/logos/nixos-logo-rainbow-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">
<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-default-gradient-white-regular-horizontal-minimal.svg">
<img src="https://brand.nixos.org/logos/nixos-logo-default-gradient-black-regular-horizontal-minimal.svg" width="500px" alt="NixOS logo">
</picture>
</a>
</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>
</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.
# 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/).
* [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 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/.
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).

160
ci/OWNERS
View File

@@ -25,27 +25,26 @@
/shell.nix @infinisil @NixOS/Security
# Libraries
/lib @infinisil @hsjobeki @llakala
/lib/generators.nix @infinisil @hsjobeki @llakala
/lib/cli.nix @infinisil @hsjobeki @llakala
/lib/debug.nix @infinisil @hsjobeki @llakala
/lib/asserts.nix @infinisil @hsjobeki @llakala
/lib/path/* @infinisil @hsjobeki @llakala
/lib/fileset @infinisil @hsjobeki @llakala
/maintainers/github-teams.json @infinisil @llakala
/maintainers/computed-team-list.nix @infinisil @llakala
/lib @infinisil @hsjobeki
/lib/generators.nix @infinisil @hsjobeki
/lib/cli.nix @infinisil @hsjobeki
/lib/debug.nix @infinisil @hsjobeki
/lib/asserts.nix @infinisil @hsjobeki
/lib/path/* @infinisil @hsjobeki
/lib/fileset @infinisil @hsjobeki
/maintainers/github-teams.json @infinisil
/maintainers/computed-team-list.nix @infinisil
## Standard environmentrelated libraries
/lib/customisation.nix @alyssais @NixOS/stdenv @llakala
/lib/derivations.nix @NixOS/stdenv @llakala
/lib/fetchers.nix @alyssais @NixOS/stdenv @llakala
/lib/meta.nix @alyssais @NixOS/stdenv @llakala
/lib/meta-types.nix @infinisil @adisbladis @NixOS/stdenv @llakala
/lib/source-types.nix @alyssais @NixOS/stdenv @llakala
/lib/customisation.nix @alyssais @NixOS/stdenv
/lib/derivations.nix @NixOS/stdenv
/lib/fetchers.nix @alyssais @NixOS/stdenv
/lib/meta.nix @alyssais @NixOS/stdenv
/lib/source-types.nix @alyssais @NixOS/stdenv
/lib/systems @alyssais @NixOS/stdenv
## Libraries / Module system
/lib/modules.nix @infinisil @roberth @hsjobeki @llakala
/lib/types.nix @infinisil @roberth @hsjobeki @llakala
/lib/options.nix @infinisil @roberth @hsjobeki @llakala
/lib/modules.nix @infinisil @roberth @hsjobeki
/lib/types.nix @infinisil @roberth @hsjobeki
/lib/options.nix @infinisil @roberth @hsjobeki
/lib/tests/modules.sh @infinisil @roberth @hsjobeki
/lib/tests/modules @infinisil @roberth @hsjobeki
@@ -57,31 +56,31 @@
/pkgs/top-level/splice.nix @Ericson2314
/pkgs/top-level/release-cross.nix @Ericson2314
/pkgs/top-level/by-name-overlay.nix @infinisil @philiptaron
/pkgs/top-level/config.nix @jopejoe1
/pkgs/top-level/make-tarball.nix @jopejoe1
/pkgs/top-level/packages-config.nix @jopejoe1
/pkgs/top-level/packages-info.nix @jopejoe1
/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/stdenv @philiptaron @NixOS/stdenv
/pkgs/stdenv/generic @Ericson2314 @NixOS/stdenv
/pkgs/stdenv/generic/problems.nix @infinisil
/pkgs/test/problems @infinisil
/pkgs/stdenv/generic/check-meta.nix @infinisil @Ericson2314 @adisbladis @NixOS/stdenv @llakala
/pkgs/stdenv/generic/check-meta.nix @infinisil @Ericson2314 @adisbladis @NixOS/stdenv
/pkgs/stdenv/generic/meta-types.nix @infinisil @adisbladis @NixOS/stdenv
/pkgs/stdenv/cross @Ericson2314 @NixOS/stdenv
/pkgs/build-support @philiptaron
/pkgs/build-support/cc-wrapper @Ericson2314
/pkgs/build-support/bintools-wrapper @Ericson2314
/pkgs/build-support/setup-hooks @Ericson2314
/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
/pkgs/pkgs-lib @Stunkymonkey @h7x4
/pkgs/pkgs-lib/formats/json2x @Stunkymonkey @h7x4 @figsoda
# Nixpkgs build-support
/pkgs/build-support/writers @lassulus
# Nixpkgs make-disk-image
/doc/build-helpers/images/makediskimage.section.md @raitobezarius
/nixos/lib/make-disk-image.nix @raitobezarius
# Nix, the package manager
# @raitobezarius is not "code owner", but is listed here to be notified of changes
# pertaining to the Nix package manager.
@@ -95,16 +94,16 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/maintainers/scripts/doc @jtojnar @ryantm
# Contributor documentation
/CONTRIBUTING.md
/.github/PULL_REQUEST_TEMPLATE.md
/doc/contributing/
/doc/contributing/contributing-to-documentation.chapter.md @jtojnar
/lib/README.md
/doc/README.md
/nixos/README.md
/pkgs/README.md
/pkgs/by-name/README.md
/maintainers/README.md
/CONTRIBUTING.md @infinisil
/.github/PULL_REQUEST_TEMPLATE.md @infinisil
/doc/contributing/ @infinisil
/doc/contributing/contributing-to-documentation.chapter.md @jtojnar @infinisil
/lib/README.md @infinisil
/doc/README.md @infinisil
/nixos/README.md @infinisil
/pkgs/README.md @infinisil
/pkgs/by-name/README.md @infinisil
/maintainers/README.md @infinisil
# User-facing development documentation
/doc/development.md @infinisil
@@ -123,6 +122,9 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/doc/redirects.json @GetPsyched
/nixos/doc/manual/redirects.json @GetPsyched
# NixOS integration test driver
/nixos/lib/test-driver @tfc
# NixOS QEMU virtualisation
/nixos/modules/virtualisation/qemu-vm.nix @raitobezarius
/nixos/modules/services/backup/libvirtd-autosnapshot.nix @6543
@@ -182,10 +184,12 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/pkgs/by-name/an/android* @NixOS/android
# Python-related code and docs
/doc/languages-frameworks/python.section.md @mweinelt
/maintainers/scripts/update-python-libraries @mweinelt
/pkgs/by-name/up/update-python-libraries @mweinelt
/pkgs/development/interpreters/python @mweinelt
/doc/languages-frameworks/python.section.md @mweinelt @natsukium
/maintainers/scripts/update-python-libraries @mweinelt @natsukium
/pkgs/by-name/up/update-python-libraries @mweinelt @natsukium
/pkgs/development/interpreters/python @mweinelt @natsukium
/pkgs/top-level/python-packages.nix @natsukium
/pkgs/top-level/release-python.nix @natsukium
# CUDA
/pkgs/top-level/cuda-packages.nix @NixOS/cuda-maintainers
@@ -199,7 +203,7 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/doc/languages-frameworks/haskell.section.md @sternenseemann @maralorn @wolfgangwalther
/maintainers/scripts/haskell @sternenseemann @maralorn @wolfgangwalther
/pkgs/development/compilers/ghc @sternenseemann @maralorn @wolfgangwalther
/pkgs/development/compilers/ghc/9.6.6-debian-binary.nix @sternenseemann @maralorn @wolfgangwalther @OPNA2608 @liberodark @NixOS/loongarch64
/pkgs/development/compilers/ghc/9.6.6-debian-binary.nix @sternenseemann @maralorn @wolfgangwalther @OPNA2608
/pkgs/development/haskell-modules @sternenseemann @maralorn @wolfgangwalther
/pkgs/test/haskell @sternenseemann @maralorn @wolfgangwalther
/pkgs/top-level/release-haskell.nix @sternenseemann @maralorn @wolfgangwalther
@@ -211,14 +215,14 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
/pkgs/development/perl-modules @stigtsp @marcusramberg
# R
/pkgs/by-name/r/R @jbedo
/pkgs/applications/science/math/R @jbedo
/pkgs/development/r-modules @jbedo
# Rust
/pkgs/development/compilers/rust @NixOS/rust @alyssais
/pkgs/build-support/rust @NixOS/rust
/pkgs/development/compilers/rust @alyssais @Mic92 @winterqt
/pkgs/build-support/rust @winterqt
/pkgs/build-support/rust/fetch-cargo-vendor* @TomaSajt
/doc/languages-frameworks/rust.section.md @NixOS/rust
/doc/languages-frameworks/rust.section.md @winterqt
# Tcl
/pkgs/development/interpreters/tcl @fgaz
@@ -230,10 +234,14 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @Artturin @Ericson2314 @lo
# C compilers
/pkgs/development/compilers/gcc
/pkgs/development/compilers/llvm @NixOS/llvm
/pkgs/development/compilers/emscripten @raitobezarius
/doc/toolchains/llvm.chapter.md @NixOS/llvm
/doc/languages-frameworks/emscripten.section.md @raitobezarius
# Audio
/nixos/modules/services/audio/botamusique.nix @mweinelt
/nixos/modules/services/audio/snapserver.nix @mweinelt
/nixos/tests/botamusique.nix @mweinelt
/nixos/tests/snapcast.nix @mweinelt
# Browsers
@@ -263,15 +271,15 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/lib/licenses @alyssais @emilazy @jopejoe1
# Qt
/pkgs/development/libraries/qt-5 @NixOS/qt-kde
/pkgs/development/libraries/qt-6 @NixOS/qt-kde
/pkgs/development/libraries/qt-5 @K900 @NickCao @SuperSandro2000 @ttuegel
/pkgs/development/libraries/qt-6 @K900 @NickCao @SuperSandro2000 @ttuegel
# KDE Frameworks 5
/pkgs/development/libraries/kde-frameworks @NixOS/qt-kde
/pkgs/development/libraries/kde-frameworks @K900 @NickCao @SuperSandro2000 @ttuegel
# KDE / Plasma 6
/pkgs/kde @NixOS/qt-kde
/maintainers/scripts/kde @NixOS/qt-kde
/pkgs/kde @K900 @NickCao @SuperSandro2000 @ttuegel
/maintainers/scripts/kde @K900 @NickCao @SuperSandro2000 @ttuegel
# PostgreSQL and related stuff
/pkgs/by-name/po/postgresqlTestHook @NixOS/postgres
@@ -322,9 +330,9 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/nixos/tests/knot.nix @mweinelt
# Web servers
/doc/packages/nginx.section.md @leona-ya @Ma27
/pkgs/servers/http/nginx/ @helsinki-Jo @leona-ya @Ma27
/nixos/modules/services/web-servers/nginx/ @leona-ya @Ma27
/doc/packages/nginx.section.md @raitobezarius
/pkgs/servers/http/nginx/ @raitobezarius
/nixos/modules/services/web-servers/nginx/ @raitobezarius
# D
/pkgs/build-support/dlang @jtbx @TomaSajt
@@ -361,14 +369,10 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/pkgs/applications/editors/kakoune @philiptaron
# LuaPackages
/pkgs/development/interpreters/lua-5 @NixOS/lua
/pkgs/development/interpreters/luajit @NixOS/lua
/pkgs/development/lua-modules @NixOS/lua
/pkgs/top-level/lua-packages.nix @NixOS/lua
# Neovim
/pkgs/applications/editors/neovim @NixOS/neovim
/doc/languages-frameworks/neovim.section.md @NixOS/neovim
/pkgs/applications/editors/neovim @NixOS/neovim
# VimPlugins
/pkgs/applications/editors/vim/plugins @NixOS/neovim
@@ -392,15 +396,18 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
/nixos/tests/docker-tools* @roberth @jhol
/doc/build-helpers/images/dockertools.section.md @roberth @jhol
# Blockchains
/pkgs/applications/blockchains @mmahut @RaghavSood
# Go
/doc/languages-frameworks/go.section.md @kalbasit @Mic92
/pkgs/build-support/go @kalbasit @Mic92
/pkgs/development/compilers/go @kalbasit @Mic92
/doc/languages-frameworks/go.section.md @kalbasit @katexochen @Mic92
/pkgs/build-support/go @kalbasit @katexochen @Mic92
/pkgs/development/compilers/go @kalbasit @katexochen @Mic92
# GNOME
/pkgs/desktops/gnome @NixOS/gnome
/pkgs/desktops/gnome/extensions @NixOS/gnome
/pkgs/build-support/make-hardcode-gsettings-patch @NixOS/gnome
/pkgs/desktops/gnome @jtojnar
/pkgs/desktops/gnome/extensions @jtojnar
/pkgs/build-support/make-hardcode-gsettings-patch @jtojnar
# Cinnamon
/pkgs/by-name/ci/cinnamon-* @mkg20001
@@ -432,7 +439,6 @@ nixos/tests/forgejo.nix @adamcstephens @bendlas @christoph-heiss @
/doc/languages-frameworks/javascript.section.md @winterqt
/pkgs/development/tools/pnpm @Scrumplex @gepbird
/pkgs/build-support/node/fetch-pnpm-deps @Scrumplex @gepbird
/pkgs/test/pnpm @Scrumplex @gepbird
# OCaml
/pkgs/build-support/ocaml @ulrikstrid
@@ -469,8 +475,9 @@ nixos/tests/incus/ @adamcstephens
pkgs/by-name/in/incus/ @adamcstephens
pkgs/by-name/lx/lxc* @adamcstephens
# Flutter
# ExpidusOS, Flutter
/pkgs/development/compilers/flutter @RossComputerGuy
/pkgs/desktops/expidus @RossComputerGuy
# GNU Tar & Zip
/pkgs/by-name/gn/gnutar @RossComputerGuy
@@ -508,7 +515,7 @@ pkgs/by-name/oc/octodns/ @anthonyroussel
pkgs/by-name/te/teleport* @arianvp @justinas @sigma @tomberek @techknowlogick @JuliusFreudenberger
# Warp-terminal
pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @4evy @johnrtitor
pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @FlameFlag @johnrtitor
# Nim
/doc/languages-frameworks/nim.section.md @NixOS/nim
@@ -519,16 +526,3 @@ pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @4evy @johnrtitor
# 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
# Boot security
/pkgs/by-name/au/autopen @NixOS/boot-security
/pkgs/misc/signed-packages @NixOS/boot-security

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/).
- 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.
- 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
@@ -104,7 +94,7 @@ For the purposes of CI, branches in the NixOS/nixpkgs repository are classified
Some branches also have a version component, which is either `unstable` or `YY.MM`.
`ci/github-script/supportedBranches.js` is a script imported by CI to classify the base and head branches of a Pull Request.
`ci/supportedBranches.js` is a script imported by CI to classify the base and head branches of a Pull Request.
This classification will then be used to skip certain jobs.
This script can also be run locally to print basic test cases.
@@ -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-core]: https://github.com/orgs/NixOS/teams/nixpkgs-core
[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 =
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;
nixFilesSrc = fs.toSource {
root = ../.;
@@ -34,24 +159,14 @@ let
};
in
{
pkg = treefmt;
check = treefmt.check nixFilesSrc;
shell = treefmtEval.config.build.devShell;
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
rec {
inherit pkgs docPkgs fmt;
inherit pkgs fmt;
codeownersValidator = pkgs.callPackage ./codeowners-validator { };
# FIXME(lf-): it might be useful to test other Nix implementations
@@ -64,13 +179,13 @@ rec {
# CI jobs
lib-tests = import ../lib/tests/release.nix { inherit pkgs; };
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 {
nix = pkgs.nixVersions.latest;
};
parse = pkgs.lib.recurseIntoAttrs {
nix_latest = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.latest; };
stable = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.stable; };
nix_2_28 = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.nix_2_28; };
lix = pkgs.callPackage ./parse.nix { nix = pkgs.lix; };
lix_latest = pkgs.callPackage ./parse.nix { nix = pkgs.lixPackageSets.latest.lix; };
};

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

View File

@@ -49,7 +49,6 @@ in
{
combinedDir,
touchedFilesJson,
baseBranch,
ownersFile ? ../../OWNERS,
}:
let
@@ -239,33 +238,34 @@ runCommand "compare"
jq -r -f ${./generate-step-summary.jq} < ${changed-paths}
} >> $out/step-summary.md
{
echo
echo "# 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
if jq -e '(.attrdiff.added | length == 0) and (.attrdiff.removed | length == 0)' "${changed-paths}" > /dev/null; then
# Chunks have changed between revisions
# We cannot generate a performance comparison
{
echo "> [!NOTE]"
echo "> The package sets differ between the two revisions. This comparison only"
echo "> covers packages evaluated in both, so treat the figures as approximate."
echo
echo "# Performance comparison"
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
} >> $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
{
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
readarray -t touchedFiles < ./touched-files
echo "This PR touches ''${#touchedFiles[@]} files"

View File

@@ -17,7 +17,6 @@
busybox,
jq,
nix,
perf,
}:
{
@@ -39,7 +38,7 @@ let
fileset = unions (
map (lib.path.append ../..) [
".version"
"ci/eval/pre-eval.nix"
"ci/eval/attrpaths.nix"
"ci/eval/chunk.nix"
"ci/eval/outpaths.nix"
"default.nix"
@@ -57,11 +56,11 @@ let
builtins.readFile ../../pkgs/top-level/release-supported-systems.json
);
preEval =
attrpathsSuperset =
{
evalSystem,
}:
runCommand "pre-eval"
runCommand "attrpaths-superset.json"
{
src = nixpkgs;
# Don't depend on -dev outputs to reduce closure size for CI.
@@ -74,15 +73,15 @@ let
export NIX_STATE_DIR=$(mktemp -d)
mkdir $out
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 \
"$src/ci/eval/pre-eval.nix" \
-A result \
"$src/ci/eval/attrpaths.nix" \
-A paths \
-I "$src" \
--argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \
--option restrict-eval true \
--option allow-import-from-derivation false \
--option eval-system "${evalSystem}" > $out/result.json
--option eval-system "${evalSystem}" > $out/paths.json
'';
singleSystem =
@@ -91,10 +90,8 @@ let
# Note that this is intentionally not called `system`,
# because `--argstr system` would only be passed to the ci/default.nix file!
evalSystem ? builtins.currentSystem,
# The path to the `result.json` file from `preEval`
preEvalFile ? "${preEval { inherit evalSystem; }}/result.json",
# Output the number of assembly instructions executed during evaluation
countInstructions ? false,
# The path to the `paths.json` file from `attrpathsSuperset`
attrpathFile ? "${attrpathsSuperset { inherit evalSystem; }}/paths.json",
}:
let
singleChunk = writeShellScript "single-chunk" ''
@@ -103,7 +100,6 @@ let
myChunk=$2
system=$3
outputDir=$4
preEvalFile=$5
# Default is 5, higher values effectively disable the warning.
# This randomly breaks Eval.
@@ -125,12 +121,12 @@ let
--show-trace \
--arg chunkSize "$chunkSize" \
--arg myChunk "$myChunk" \
--arg preEvalFile "$preEvalFile" \
--arg attrpathFile "${attrpathFile}" \
--arg systems "[ \"$system\" ]" \
--arg includeBroken ${lib.boolToString includeBroken} \
--argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \
-I ${nixpkgs} \
-I "$preEvalFile" \
-I ${attrpathFile} \
> "$outputDir/result/$myChunk" \
2> "$outputDir/stderr/$myChunk"
exitCode=$?
@@ -150,16 +146,13 @@ let
runCommand "nixpkgs-eval-${evalSystem}"
{
# Don't depend on -dev outputs to reduce closure size for CI.
nativeBuildInputs = map lib.getBin (
[
busybox
jq
nix
]
++ lib.optionals countInstructions [ perf ]
);
nativeBuildInputs = map lib.getBin [
busybox
jq
nix
];
env = {
inherit evalSystem chunkSize countInstructions;
inherit evalSystem chunkSize;
};
__structuredAttrs = true;
unsafeDiscardReferences.out = true;
@@ -171,6 +164,12 @@ let
echo "System: $evalSystem"
cores=$NIX_BUILD_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}
@@ -191,78 +190,29 @@ let
done
) &
chunkedEval() {
local chunkOutputDir=$1
local preEvalFile=$2
seq_end=$(( chunkCount - 1 ))
local attrCount=$(jq '.paths | length' "$preEvalFile")
echo "Attribute count: $attrCount"
echo "Chunk size: $chunkSize"
# Same as `attrCount / chunkSize` but rounded up
local chunkCount=$(( (attrCount - 1) / chunkSize + 1 ))
echo "Chunk count: $chunkCount"
${lib.optionalString quickTest ''
seq_end=0
''}
local seq_end=$(( chunkCount - 1 ))
${lib.optionalString quickTest ''
seq_end=0
''}
chunkOutputDir=$(mktemp -d)
mkdir "$chunkOutputDir"/{result,stats,timestats,stderr}
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() {
seq -w 0 "$seq_end" |
xargs -I{} -P"$cores" \
${singleChunk} "$chunkSize" {} "$evalSystem" "$chunkOutputDir" "$preEvalFile"
}
cp -r "$chunkOutputDir"/stats $out/${evalSystem}/stats-by-chunk
if [[ -n "$countInstructions" ]]; then
export seq_end cores chunkSize evalSystem chunkOutputDir preEvalFile
export -f runAllChunks
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
if (( chunkSize * chunkCount != attrCount )); then
# A final incomplete chunk would mess up the stats, don't include it
rm "$chunkOutputDir"/stats/"$seq_end"
fi
cat "$chunkOutputDirs"/*/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(.outputs)' > $out/${evalSystem}/paths.json
cat "$chunkOutputDir"/result/* | jq -s 'add | map_values(.meta)' > $out/${evalSystem}/meta.json
'';
diff = callPackage ./diff.nix { };
@@ -299,20 +249,14 @@ let
}) | from_entries
' > $out/maintainers.json
mkdir -p $out/before/stats $out/before/instructions
mkdir -p $out/before/stats
for d in ${diffDir}/before/*; do
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
mkdir -p $out/after/stats $out/after/instructions
mkdir -p $out/after/stats
for d in ${diffDir}/after/*; do
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
'';
@@ -322,16 +266,13 @@ let
{
# Whether to evaluate on a specific set of systems, by default all are evaluated
evalSystems ? if quickTest then [ "x86_64-linux" ] else supportedSystems,
# Output the number of assembly instructions executed during evaluation on
# each system
countInstructions ? false,
}:
symlinkJoin {
name = "nixpkgs-eval-baseline";
paths = map (
evalSystem:
singleSystem {
inherit evalSystem countInstructions;
inherit evalSystem;
}
) evalSystems;
};
@@ -347,12 +288,6 @@ let
# | jq --raw-input --slurp 'split("\n")[:-1]' > 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
diffs = symlinkJoin {
@@ -363,14 +298,14 @@ let
inherit evalSystem;
beforeDir = baseline;
afterDir = singleSystem {
inherit evalSystem countInstructions;
inherit evalSystem;
};
}
) evalSystems;
};
comparisonReport = compare {
combinedDir = combine { diffDir = diffs; };
inherit touchedFilesJson baseBranch;
inherit touchedFilesJson;
};
in
comparisonReport;
@@ -378,7 +313,7 @@ let
in
{
inherit
preEval
attrpathsSuperset
singleSystem
diff
combine

View File

@@ -6,7 +6,7 @@
includeBroken ? true, # set this to false to exclude meta.broken packages from the output
path ? ./../..,
# used by ./pre-eval.nix
# used by ./attrpaths.nix
attrNamesOnly ? false,
# Set this to `null` to build for builtins.currentSystem only
@@ -14,8 +14,6 @@
builtins.readFile (path + "/pkgs/top-level/release-supported-systems.json")
),
attrPathsDisallowedForInternalUse ? [ ],
# Customize the config used to evaluate nixpkgs
extraNixpkgsConfig ? { },
}:
@@ -37,22 +35,6 @@ let
allowVariants = !attrNamesOnly;
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;

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,5 +1,2 @@
comparison
comparison.zip
node_modules
step-summary.md
*.tsbuildinfo

View File

@@ -1,13 +1,12 @@
// @ts-nocheck
import { readFile, writeFile } from 'node:fs/promises'
import path from 'node:path'
import { DefaultArtifactClient } from '@actions/artifact'
import { handleMerge } from './merge.js'
import { handleReviewers } from './reviewers.js'
import { classify } from './supportedBranches.js'
import withRateLimit from './withRateLimit.js'
module.exports = async ({ github, context, core, dry }) => {
const path = require('node:path')
const { DefaultArtifactClient } = await import('@actions/artifact')
const { readFile, writeFile } = require('node:fs/promises')
const withRateLimit = require('./withRateLimit.js')
const { classify } = require('../supportedBranches.js')
const { handleMerge } = require('./merge.js')
const { handleReviewers } = require('./reviewers.js')
export default async ({ github, context, core, dry }) => {
const artifactClient = new DefaultArtifactClient()
// Detect if running in a fork (not NixOS/nixpkgs)
@@ -207,8 +206,20 @@ export default async ({ github, context, core, dry }) => {
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.
// `commit { oid }` is needed by handleMerge to verify approvals are against the current head.
const reviews = (
await github.graphql(
`query($owner: String!, $repo: String!, $pr: Int!) {
@@ -220,7 +231,6 @@ export default async ({ github, context, core, dry }) => {
reviews(first: 100) {
nodes {
state
commit { oid }
user: author {
# Only get users, no bots
... on User {
@@ -256,20 +266,6 @@ export default async ({ github, context, core, dry }) => {
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(
reviews
.filter((review) => review.state === 'APPROVED')
@@ -396,13 +392,6 @@ export default async ({ github, context, core, dry }) => {
pull_number,
per_page: 100,
})
// label llm-assisted PRs accordingly, retaining it if manually set
const assistedByPattern = /Assisted-by: (?!nix-init)/i
if (prCommits.some((c) => assistedByPattern.test(c.commit.message))) {
evalLabels['llm-assisted'] = true
}
const commitSubjects = prCommits.map(
(c) => c.commit.message.split('\n')[0],
)
@@ -689,21 +678,16 @@ export default async ({ github, context, core, dry }) => {
if (context.payload.pull_request) {
await handle({ item: context.payload.pull_request, stats })
} else {
// We don't use filters here because that causes GitHub to use an often-outdated index,
// resulting in the cursor not being updated, and therefore causing the same PRs
// to use up our rate limit over and over again.
const lastRun = (
await github.rest.actions.listWorkflowRuns({
...context.repo,
workflow_id: 'bot.yml',
event: 'schedule',
status: 'success',
exclude_pull_requests: true,
per_page: 1,
})
).data.workflow_runs.find(
(run) => run.event === 'schedule' && run.conclusion === 'success',
)
core.info(
`Last successful run created at: ${lastRun?.created_at ?? '<n/a>'}`,
)
).data.workflow_runs[0]
const cutoff = new Date(
Math.max(
@@ -799,7 +783,6 @@ export default async ({ github, context, core, dry }) => {
} else {
// No stats.artifacts++, because this does not allow passing a custom token.
// Thus, the upload will not happen with the app token, but the default github.token.
core.info(`pagination-cursor: ${cursor}`)
await artifactClient.uploadArtifact(
'pagination-cursor',
[uploadPath],
@@ -809,8 +792,6 @@ export default async ({ github, context, core, dry }) => {
},
)
}
} else {
core.info('pagination-cursor: <n/a>')
}
// Some items might be in both search results, so filtering out duplicates as well.

View File

@@ -1,242 +0,0 @@
import assert from 'node:assert/strict'
import test from 'node:test'
import { evaluateTargetBranchPolicy } from './check-target-branch-policy.ts'
type DecisionFacts = {
base: string
head: string
maxRebuildCount: number
rebuildsAllTests: boolean
onlyChangedFile: string | null
}
type Decision =
| 'mass-rebuild'
| 'nixos-rebuild'
| 'possible-mass-rebuild'
| 'skip-development-merge'
| 'dismiss'
const defaults: DecisionFacts = {
base: 'master',
head: 'topic-branch',
maxRebuildCount: 0,
rebuildsAllTests: false,
onlyChangedFile: null,
}
const cases: Array<{
name: string
facts: Partial<DecisionFacts>
expected: Decision
}> = [
{
name: 'allows fewer than 500 rebuilds on master',
facts: { maxRebuildCount: 499 },
expected: 'dismiss',
},
{
name: 'flags 500 rebuilds on master as a possible mass rebuild',
facts: { maxRebuildCount: 500 },
expected: 'possible-mass-rebuild',
},
{
name: 'flags 999 rebuilds on master as a possible mass rebuild',
facts: { maxRebuildCount: 999 },
expected: 'possible-mass-rebuild',
},
{
name: 'flags 1000 rebuilds on master as a mass rebuild',
facts: { maxRebuildCount: 1000 },
expected: 'mass-rebuild',
},
{
name: 'flags a mass rebuild on staging-nixos',
facts: { base: 'staging-nixos', maxRebuildCount: 24_000 },
expected: 'mass-rebuild',
},
{
name: 'flags a mass rebuild on a release staging-nixos branch',
facts: { base: 'staging-nixos-26.05', maxRebuildCount: 1000 },
expected: 'mass-rebuild',
},
{
name: 'allows mass rebuilds on staging',
facts: { base: 'staging', maxRebuildCount: 1000 },
expected: 'dismiss',
},
{
name: 'flags a mass rebuild on a release branch',
facts: { base: 'release-26.05', maxRebuildCount: 1000 },
expected: 'mass-rebuild',
},
{
name: 'flags NixOS test rebuilds on master',
facts: { rebuildsAllTests: true },
expected: 'nixos-rebuild',
},
{
name: 'flags NixOS test rebuilds on a release branch',
facts: { base: 'release-26.05', rebuildsAllTests: true },
expected: 'nixos-rebuild',
},
{
name: 'allows NixOS test rebuilds on staging-nixos',
facts: { base: 'staging-nixos', rebuildsAllTests: true },
expected: 'dismiss',
},
{
name: 'does not flag a possible mass rebuild when staging-nixos rebuilds all NixOS tests',
facts: {
base: 'staging-nixos',
maxRebuildCount: 500,
rebuildsAllTests: true,
},
expected: 'dismiss',
},
{
name: 'flags other possible mass rebuilds on staging-nixos',
facts: { base: 'staging-nixos', maxRebuildCount: 500 },
expected: 'possible-mass-rebuild',
},
{
name: 'skips staging into master',
facts: {
head: 'staging',
maxRebuildCount: 24_000,
},
expected: 'skip-development-merge',
},
{
name: 'skips staging-nixos into master',
facts: {
head: 'staging-nixos',
maxRebuildCount: 24_000,
},
expected: 'skip-development-merge',
},
{
name: 'skips master into staging-nixos',
facts: {
base: 'staging-nixos',
head: 'master',
maxRebuildCount: 24_000,
},
expected: 'skip-development-merge',
},
{
name: 'checks staging into staging-nixos',
facts: {
base: 'staging-nixos',
head: 'staging',
maxRebuildCount: 24_000,
},
expected: 'mass-rebuild',
},
{
name: 'skips release staging-nixos into its release branch',
facts: {
base: 'release-26.05',
head: 'staging-nixos-26.05',
maxRebuildCount: 24_000,
},
expected: 'skip-development-merge',
},
{
name: 'skips a release branch into its staging-nixos branch',
facts: {
base: 'staging-nixos-26.05',
head: 'release-26.05',
maxRebuildCount: 24_000,
},
expected: 'skip-development-merge',
},
{
name: 'checks release staging into its staging-nixos branch',
facts: {
base: 'staging-nixos-26.05',
head: 'staging-26.05',
maxRebuildCount: 24_000,
},
expected: 'mass-rebuild',
},
{
name: 'kernels-org exemption suppresses a possible mass rebuild',
facts: {
maxRebuildCount: 999,
onlyChangedFile: 'pkgs/os-specific/linux/kernel/kernels-org.json',
},
expected: 'dismiss',
},
{
name: 'kernels-org exemption suppresses a definite mass rebuild',
facts: {
maxRebuildCount: 1000,
onlyChangedFile: 'pkgs/os-specific/linux/kernel/kernels-org.json',
},
expected: 'dismiss',
},
{
name: 'kernels-org exemption suppresses a NixOS test rebuild',
facts: {
rebuildsAllTests: true,
onlyChangedFile: 'pkgs/os-specific/linux/kernel/kernels-org.json',
},
expected: 'dismiss',
},
{
name: 'xanmod kernel exemption suppresses a possible mass rebuild',
facts: {
maxRebuildCount: 999,
onlyChangedFile: 'pkgs/os-specific/linux/kernel/xanmod-kernels.nix',
},
expected: 'dismiss',
},
{
name: 'xanmod kernel exemption suppresses a definite mass rebuild',
facts: {
maxRebuildCount: 1000,
onlyChangedFile: 'pkgs/os-specific/linux/kernel/xanmod-kernels.nix',
},
expected: 'dismiss',
},
{
name: 'xanmod kernel exemption suppresses a NixOS test rebuild',
facts: {
rebuildsAllTests: true,
onlyChangedFile: 'pkgs/os-specific/linux/kernel/xanmod-kernels.nix',
},
expected: 'dismiss',
},
{
name: 'Home Assistant exemption suppresses a mass rebuild',
facts: {
head: 'wip-home-assistant',
maxRebuildCount: 1500,
},
expected: 'dismiss',
},
{
name: 'does not exempt a Home Assistant update above 1500 rebuilds',
facts: { head: 'wip-home-assistant', maxRebuildCount: 1501 },
expected: 'mass-rebuild',
},
{
name: 'Home Assistant exemption does not suppress a NixOS test rebuild',
facts: {
head: 'wip-home-assistant',
maxRebuildCount: 1500,
rebuildsAllTests: true,
},
expected: 'nixos-rebuild',
},
]
for (const { name, facts, expected } of cases) {
test(name, () => {
assert.equal(
evaluateTargetBranchPolicy({ ...defaults, ...facts }).decision,
expected,
)
})
}

View File

@@ -1,116 +0,0 @@
import { classify, split } from './supportedBranches.js'
type TargetBranchPolicyFacts = {
base: string
head: string
maxRebuildCount: number
rebuildsAllTests: boolean
onlyChangedFile: string | null
}
type TargetBranchReviewDecision =
| 'mass-rebuild'
| 'nixos-rebuild'
| 'possible-mass-rebuild'
| 'skip-development-merge'
| 'dismiss'
type TargetBranchPolicyResult = {
decision: TargetBranchReviewDecision
details: {
isExemptKernelUpdate: boolean
isExemptHomeAssistantUpdate: boolean
}
}
export function getTargetBranchPolicy({
base,
head,
}: {
base: string
head: string
}) {
const baseClassification = classify(base)
const headClassification = classify(head)
const isPrimaryBase = baseClassification.type.includes('primary')
const isPrimaryHead = headClassification.type.includes('primary')
const isStagingNixosBase = split(base).prefix === 'staging-nixos'
const isDevelopmentHead = headClassification.type.includes('development')
const shouldSkipDevelopmentMerge =
isDevelopmentHead && (!isStagingNixosBase || isPrimaryHead)
return {
isStagingNixosBase,
shouldSkipDevelopmentMerge,
shouldCheckMassRebuild:
!shouldSkipDevelopmentMerge && (isPrimaryBase || isStagingNixosBase),
shouldCheckNixosRebuild: !shouldSkipDevelopmentMerge && isPrimaryBase,
}
}
export function evaluateTargetBranchPolicy({
base,
head,
maxRebuildCount,
rebuildsAllTests,
onlyChangedFile,
}: TargetBranchPolicyFacts): TargetBranchPolicyResult {
const {
isStagingNixosBase,
shouldSkipDevelopmentMerge,
shouldCheckMassRebuild,
shouldCheckNixosRebuild,
} = getTargetBranchPolicy({ base, head })
// https://github.com/NixOS/nixpkgs/pull/553786#issuecomment-5510286851
// kernels-org should go to staging-nixos (or master) and staging-nixos-xx.xx (or release-xx.xx) when backported
// https://github.com/NixOS/nixpkgs/pull/521157
// xanmod should go to master and release-xx.xx when backported
const isExemptKernelUpdate =
onlyChangedFile === 'pkgs/os-specific/linux/kernel/kernels-org.json' ||
onlyChangedFile === 'pkgs/os-specific/linux/kernel/xanmod-kernels.nix'
// https://github.com/NixOS/nixpkgs/pull/483194#issuecomment-3793393218
const isExemptHomeAssistantUpdate =
maxRebuildCount <= 1500 && head === 'wip-home-assistant'
const details = {
isExemptKernelUpdate,
isExemptHomeAssistantUpdate,
}
const result = (decision: TargetBranchReviewDecision) => ({
decision,
details,
})
const isMassRebuild =
maxRebuildCount >= 1000 &&
!isExemptKernelUpdate &&
!isExemptHomeAssistantUpdate
if (shouldCheckMassRebuild && isMassRebuild) {
return result('mass-rebuild')
}
if (shouldCheckNixosRebuild && rebuildsAllTests && !isExemptKernelUpdate) {
return result('nixos-rebuild')
}
const isPossibleMassRebuild =
maxRebuildCount >= 500 &&
!isMassRebuild &&
!isExemptKernelUpdate &&
!isExemptHomeAssistantUpdate
if (
shouldCheckMassRebuild &&
isPossibleMassRebuild &&
!(rebuildsAllTests && isStagingNixosBase)
) {
return result('possible-mass-rebuild')
}
return result(
shouldSkipDevelopmentMerge ? 'skip-development-merge' : 'dismiss',
)
}

View File

@@ -0,0 +1,223 @@
/// @ts-check
// TODO: should this be combined with the branch checks in prepare.js?
// They do seem quite similar, but this needs to run after eval,
// and prepare.js obviously doesn't.
const { classify, split } = require('../supportedBranches.js')
const { readFile } = require('node:fs/promises')
const { postReview, dismissReviews } = require('./reviews.js')
const reviewKey = 'check-target-branch'
/**
* @param {{
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: import('@actions/github/lib/context').Context
* core: import('@actions/core')
* dry: boolean
* }} CheckTargetBranchProps
*/
async function checkTargetBranch({ github, context, core, dry }) {
/**
* @type {{
* attrdiff: {
* added: string[],
* changed: 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>,
* rebuildCountByKernel: Record<string, number>,
* rebuildsByKernel: Record<string, string[]>,
* rebuildsByPlatform: Record<string, string[]>,
* }}
*/
const changed = JSON.parse(
await readFile('comparison/changed-paths.json', 'utf-8'),
)
const pull_number = context.payload.pull_request?.number
if (!pull_number) {
core.warning(
'Skipping checkTargetBranch: no pull_request number (is this being run as part of a merge group?)',
)
return
}
const prInfo = (
await github.rest.pulls.get({
...context.repo,
pull_number,
})
).data
const base = prInfo.base.ref
const head = prInfo.head.ref
const baseClassification = classify(base)
const headClassification = classify(head)
// Don't run on, e.g., staging-nixos to master merges.
if (headClassification.type.includes('development')) {
core.info(
`Skipping checkTargetBranch: PR is from a development branch (${head})`,
)
await dismissReviews({
github,
context,
core,
dry,
reviewKey,
})
return
}
// Don't run on PRs against staging branches, wip branches, haskell-updates, etc.
if (!baseClassification.type.includes('primary')) {
core.info(
`Skipping checkTargetBranch: PR is against a non-primary base branch (${base})`,
)
await dismissReviews({
github,
context,
core,
dry,
reviewKey,
})
return
}
const maxRebuildCount = Math.max(
...Object.values(changed.rebuildCountByKernel),
)
const rebuildsAllTests =
changed.attrdiff.changed.includes('nixosTests.simple-container') ||
changed.attrdiff.changed.includes('nixosTests.simple-vm')
// https://github.com/NixOS/nixpkgs/pull/481205#issuecomment-3790123921
// These should go to staging-nixos instead of master,
// but release-xx.xx (not staging-xx.xx) when backported
let isExemptKernelUpdate = false
if (prInfo.changed_files === 1) {
const changedFiles = (
await github.rest.pulls.listFiles({
...context.repo,
pull_number,
})
).data
isExemptKernelUpdate =
changedFiles.length === 1 &&
(changedFiles[0].filename ===
'pkgs/os-specific/linux/kernel/xanmod-kernels.nix' ||
(base.startsWith('release-') &&
changedFiles[0].filename ===
'pkgs/os-specific/linux/kernel/kernels-org.json'))
}
// https://github.com/NixOS/nixpkgs/pull/483194#issuecomment-3793393218
const isExemptHomeAssistantUpdate =
maxRebuildCount <= 1500 && head === 'wip-home-assistant'
core.info(
[
`checkTargetBranch: this PR:`,
` * causes ${maxRebuildCount} rebuilds`,
` * ${rebuildsAllTests ? 'rebuilds' : 'does not rebuild'} all NixOS tests`,
` * ${isExemptKernelUpdate ? 'is' : 'is not'} an exempt kernel update`,
` * ${isExemptHomeAssistantUpdate ? 'is' : 'is not'} an exempt home-assistant update`,
].join('\n'),
)
if (
maxRebuildCount >= 1000 &&
!isExemptHomeAssistantUpdate &&
!isExemptKernelUpdate
) {
const desiredBranch =
base === 'master' ? 'staging' : `staging-${split(base).version}`
const body = [
`The PR's base branch is set to \`${base}\`, but this PR causes ${maxRebuildCount} rebuilds.`,
'It is therefore considered a mass rebuild.',
`Please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) (probably \`${desiredBranch}\`).`,
].join('\n')
await postReview({
github,
context,
core,
dry,
body,
event: 'REQUEST_CHANGES',
reviewKey,
})
} else if (rebuildsAllTests && !isExemptKernelUpdate) {
let branchText
if (base === 'master' && maxRebuildCount >= 500) {
branchText = '(probably either `staging-nixos` or `staging`)'
} else if (base === 'master') {
branchText = '(probably `staging-nixos`)'
} else {
branchText = `(probably \`staging-${split(base).version}\`)`
}
const body = [
`The PR's base branch is set to \`${base}\`, but this PR rebuilds all NixOS tests.`,
base === 'master' && maxRebuildCount >= 500
? `Since this PR also causes ${maxRebuildCount} rebuilds, it may also be considered a mass rebuild.`
: '',
`Please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) ${branchText}.`,
].join('\n')
await postReview({
github,
context,
core,
dry,
body,
event: 'REQUEST_CHANGES',
reviewKey,
})
} else if (
maxRebuildCount >= 500 &&
!isExemptKernelUpdate &&
!isExemptHomeAssistantUpdate
) {
const stagingBranch =
base === 'master' ? 'staging' : `staging-${split(base).version}`
const body = [
`The PR's base branch is set to \`${base}\`, and this PR causes ${maxRebuildCount} rebuilds.`,
`Please consider whether this PR causes a mass rebuild according to [our conventions](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions).`,
`If it does cause a mass rebuild, please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) (probably \`${stagingBranch}\`).`,
`If it does not cause a mass rebuild, this message can be ignored.`,
].join('\n')
await postReview({
github,
context,
core,
dry,
body,
event: 'REQUEST_CHANGES',
reviewKey,
})
} else {
core.info('checkTargetBranch: this PR is against an appropriate branch.')
await dismissReviews({
github,
context,
core,
dry,
reviewKey,
})
}
}
module.exports = checkTargetBranch

View File

@@ -1,242 +0,0 @@
import { readFile } from 'node:fs/promises'
import type * as actionsCore from '@actions/core'
import type { context as actionsContext } from '@actions/github'
import type { GitHub } from '@actions/github/lib/utils'
import {
evaluateTargetBranchPolicy,
getTargetBranchPolicy,
} from './check-target-branch-policy.ts'
import { dismissReviews, postReview } from './reviews.js'
import { split } from './supportedBranches.js'
// TODO: should this be combined with the branch checks in prepare.js?
// They do seem quite similar, but this needs to run after eval,
// and prepare.js obviously doesn't.
const reviewKey = 'check-target-branch'
type ChangedPaths = {
attrdiff: {
added: string[]
changed: 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>
rebuildCountByKernel: Record<string, number>
rebuildsByKernel: Record<string, string[]>
rebuildsByPlatform: Record<string, string[]>
}
type TargetBranchReviewFacts = {
github: InstanceType<typeof GitHub>
context: typeof actionsContext
core: typeof actionsCore
dry: boolean
base: string
maxRebuildCount: number
}
function getStagingBranch(base: string) {
const version = split(base).version
return version ? `staging-${version}` : 'staging'
}
async function postMassRebuildReview(facts: TargetBranchReviewFacts) {
const { github, context, core, dry, base, maxRebuildCount } = facts
const desiredBranch = getStagingBranch(base)
const body = [
`The PR's base branch is set to \`${base}\`, but this PR causes ${maxRebuildCount} rebuilds.`,
'It is therefore considered a mass rebuild.',
`Please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) (probably \`${desiredBranch}\`).`,
].join('\n')
await postReview({
github,
context,
core,
dry,
body,
event: 'REQUEST_CHANGES',
reviewKey,
})
}
async function postNixosRebuildReview(facts: TargetBranchReviewFacts) {
const { github, context, core, dry, base, maxRebuildCount } = facts
let branchText: string
if (base === 'master' && maxRebuildCount >= 500) {
branchText = '(probably either `staging-nixos` or `staging`)'
} else if (base === 'master') {
branchText = '(probably `staging-nixos`)'
} else if (maxRebuildCount >= 500) {
branchText = `(probably either \`staging-nixos-${split(base).version}\` or \`staging-${split(base).version}\`)`
} else {
branchText = `(probably \`staging-nixos-${split(base).version}\`)`
}
const body = [
`The PR's base branch is set to \`${base}\`, but this PR rebuilds all NixOS tests.`,
base === 'master' && maxRebuildCount >= 500
? `Since this PR also causes ${maxRebuildCount} rebuilds, it may also be considered a mass rebuild.`
: '',
`Please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) ${branchText}.`,
].join('\n')
await postReview({
github,
context,
core,
dry,
body,
event: 'REQUEST_CHANGES',
reviewKey,
})
}
async function postPossibleMassRebuildReview(facts: TargetBranchReviewFacts) {
const { github, context, core, dry, base, maxRebuildCount } = facts
const stagingBranch = getStagingBranch(base)
const body = [
`The PR's base branch is set to \`${base}\`, and this PR causes ${maxRebuildCount} rebuilds.`,
`Please consider whether this PR causes a mass rebuild according to [our conventions](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions).`,
`If it does cause a mass rebuild, please [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to [the right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions) (probably \`${stagingBranch}\`).`,
`If it does not cause a mass rebuild, this message can be ignored.`,
].join('\n')
await postReview({
github,
context,
core,
dry,
body,
event: 'REQUEST_CHANGES',
reviewKey,
})
}
export async function checkTargetBranch({
github,
context,
core,
dry,
}: {
github: InstanceType<typeof GitHub>
context: typeof actionsContext
core: typeof actionsCore
dry: boolean
}) {
const changed: ChangedPaths = JSON.parse(
await readFile('comparison/changed-paths.json', 'utf-8'),
)
const pull_number = context.payload.pull_request?.number
if (!pull_number) {
core.warning(
'Skipping checkTargetBranch: no pull_request number (is this being run as part of a merge group?)',
)
return
}
const prInfo = (
await github.rest.pulls.get({
...context.repo,
pull_number,
})
).data
const base = prInfo.base.ref
const head = prInfo.head.ref
const { shouldCheckMassRebuild } = getTargetBranchPolicy({ base, head })
const maxRebuildCount = Math.max(
...Object.values(changed.rebuildCountByKernel),
)
const rebuildsAllTests =
changed.attrdiff.changed.includes('nixosTests.simple-container') ||
changed.attrdiff.changed.includes('nixosTests.simple-vm')
let onlyChangedFile: string | null = null
if (shouldCheckMassRebuild && prInfo.changed_files === 1) {
const changedFiles = (
await github.rest.pulls.listFiles({
...context.repo,
pull_number,
})
).data
onlyChangedFile =
changedFiles.length === 1 ? changedFiles[0].filename : null
}
const {
decision,
details: { isExemptKernelUpdate, isExemptHomeAssistantUpdate },
} = evaluateTargetBranchPolicy({
base,
head,
maxRebuildCount,
rebuildsAllTests,
onlyChangedFile,
})
core.info(
[
`checkTargetBranch: this PR:`,
` * causes ${maxRebuildCount} rebuilds`,
` * ${rebuildsAllTests ? 'rebuilds' : 'does not rebuild'} all NixOS tests`,
` * ${isExemptKernelUpdate ? 'is' : 'is not'} an exempt kernel update`,
` * ${isExemptHomeAssistantUpdate ? 'is' : 'is not'} an exempt home-assistant update`,
].join('\n'),
)
const reviewFacts: TargetBranchReviewFacts = {
github,
context,
core,
dry,
base,
maxRebuildCount,
}
if (decision === 'mass-rebuild') {
await postMassRebuildReview(reviewFacts)
return
}
if (decision === 'nixos-rebuild') {
await postNixosRebuildReview(reviewFacts)
return
}
if (decision === 'possible-mass-rebuild') {
await postPossibleMassRebuildReview(reviewFacts)
return
}
if (decision === 'skip-development-merge') {
core.info(
`Skipping checkTargetBranch: PR merges the development branch ${head} into ${base}`,
)
} else {
core.info('checkTargetBranch: this PR is against an appropriate branch.')
}
await dismissReviews({
github,
context,
core,
dry,
reviewKey,
})
}

View File

@@ -1,12 +1,8 @@
// @ts-nocheck
import { execFileSync } from 'node:child_process'
import { dismissReviews, postReview } from './reviews.js'
import { classify } from './supportedBranches.js'
import withRateLimit from './withRateLimit.js'
const dirname = import.meta.dirname
export default async ({ github, context, core, dry, cherryPicks }) => {
module.exports = async ({ github, context, core, dry, cherryPicks }) => {
const { execFileSync } = require('node:child_process')
const { classify } = require('../supportedBranches.js')
const withRateLimit = require('./withRateLimit.js')
const { dismissReviews, postReview } = require('./reviews.js')
const reviewKey = 'check-commits'
await withRateLimit({ github, core }, async (stats) => {
@@ -96,7 +92,7 @@ export default async ({ github, context, core, dry, cherryPicks }) => {
function diff({ sha, commit, original_sha }) {
const diff = execFileSync('git', [
'-C',
dirname,
__dirname,
'range-diff',
'--no-color',
'--ignore-all-space',
@@ -123,7 +119,7 @@ export default async ({ github, context, core, dry, cherryPicks }) => {
const colored_diff = execFileSync('git', [
'-C',
dirname,
__dirname,
'range-diff',
'--color',
'--no-notes',
@@ -162,7 +158,7 @@ export default async ({ github, context, core, dry, cherryPicks }) => {
// Fetching all commits we need for diff at once is much faster than any other method.
execFileSync('git', [
'-C',
dirname,
__dirname,
'fetch',
'--depth=2',
'origin',
@@ -290,7 +286,7 @@ export default async ({ github, context, core, dry, cherryPicks }) => {
// that's too long. We think this is unlikely to happen, and so don't deal with it explicitly.
const truncated = []
let total_length = 0
for (const line of diff) {
for (line of diff) {
total_length += line.length
if (total_length > 10000) {
truncated.push('', '[...truncated...]')

View File

@@ -1,7 +1,6 @@
import { execFile as nodeExecFile } from 'node:child_process'
import { promisify } from 'node:util'
const execFile = promisify(nodeExecFile)
// @ts-check
const { promisify } = require('node:util')
const execFile = promisify(require('node:child_process').execFile)
/**
* @typedef {{
@@ -17,7 +16,7 @@ const execFile = promisify(nodeExecFile)
/**
* @param {{
* args: string[]
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* quiet?: boolean,
* repoPath?: string,
* }} RunGitProps
@@ -41,14 +40,14 @@ async function runGit({ args, repoPath, core, quiet }) {
* of 250 commits and doesn't return the changed files.
*
* @param {{
* core: typeof import('@actions/core'),
* pr: Awaited<ReturnType<InstanceType<typeof import('@actions/github/lib/utils').GitHub>["rest"]["pulls"]["get"]>>["data"]
* core: import('@actions/core'),
* pr: Awaited<ReturnType<InstanceType<import('@actions/github/lib/utils').GitHub>["rest"]["pulls"]["get"]>>["data"]
* repoPath?: string,
* }} GetCommitMessagesForPRProps
*
* @returns {Promise<Commit[]>}
*/
export async function getCommitDetailsForPR({ core, pr, repoPath }) {
async function getCommitDetailsForPR({ core, pr, repoPath }) {
await runGit({
args: ['fetch', `--depth=1`, 'origin', pr.base.sha],
repoPath,
@@ -77,7 +76,7 @@ export async function getCommitDetailsForPR({ core, pr, repoPath }) {
return Promise.all(
shas.map(async (sha) => {
// Subject, author name, author email, committer name, committer email (all tab-separated)
// Subject, author name, author email, committer name, committer email (all tab-seperated)
// then a blank line, then filenames.
const result = (
await runGit({
@@ -114,3 +113,5 @@ export async function getCommitDetailsForPR({ core, pr, repoPath }) {
}),
)
}
module.exports = { getCommitDetailsForPR }

View File

@@ -1,14 +1,13 @@
// @ts-nocheck
import { writeFileSync } from 'node:fs'
import withRateLimit from './withRateLimit.js'
const excludeTeams = [
/^voters.*$/,
/^nixpkgs-maintainers$/,
/^nixpkgs-committers$/,
]
export default async ({ github, context, core, outFile }) => {
module.exports = async ({ github, context, core, outFile }) => {
const withRateLimit = require('./withRateLimit.js')
const { writeFileSync } = require('node:fs')
const org = context.repo.owner
const result = {}

View File

@@ -1,17 +1,18 @@
import { getCommitDetailsForPR } from './get-pr-commit-details.js'
import { classify } from './supportedBranches.js'
// @ts-check
const { classify } = require('../supportedBranches.js')
const { getCommitDetailsForPR } = require('./get-pr-commit-details.js')
/** @typedef {import('./get-pr-commit-details.js').Commit} Commit */
/**
* @param {{
* github: InstanceType<typeof import('@actions/github/lib/utils').GitHub>,
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: typeof import('@actions/github').context,
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* repoPath?: string,
* }} LintCommitsProps
*/
export default async function lintCommits({ github, context, core, repoPath }) {
async function lintCommits({ github, context, core, repoPath }) {
// This check should only be run when we have the pull_request context.
const pull_number = context.payload.pull_request?.number
if (!pull_number) {
@@ -56,7 +57,7 @@ export default async function lintCommits({ github, context, core, repoPath }) {
/**
* @param {{
* commits: Commit[],
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* }} CheckCommitMessagesProps
*/
async function checkCommitMessages({ commits, core }) {
@@ -73,10 +74,8 @@ async function checkCommitMessages({ commits, core }) {
'fix',
'perf',
'refactor',
'services',
'style',
'test',
'update',
]
/**
@@ -169,7 +168,7 @@ async function checkCommitMessages({ commits, core }) {
/**
* @param {{
* commits: Commit[],
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* }} CheckGitFieldsProps
*/
async function checkCommitMetadata({ commits, core }) {
@@ -220,3 +219,5 @@ async function checkCommitMetadata({ commits, core }) {
core.setFailed('Committers: merging is discouraged.')
}
}
module.exports = lintCommits

View File

@@ -1,23 +1,18 @@
import { getCommitDetailsForPR } from './get-pr-commit-details.js'
import { dismissReviews, postReview } from './reviews.js'
import { classify } from './supportedBranches.js'
// @ts-check
const { classify } = require('../supportedBranches.js')
const { getCommitDetailsForPR } = require('./get-pr-commit-details')
/**
* @param {{
* github: InstanceType<typeof import('@actions/github/lib/utils').GitHub>,
* context: typeof import('@actions/github').context,
* core: typeof import('@actions/core'),
* github: InstanceType<import('@actions/github/lib/utils').GitHub>,
* context: import('@actions/github/lib/context').Context,
* core: import('@actions/core'),
* repoPath?: string,
* dry: boolean,
* }} CheckManualFileEditsProps
*/
export default async function checkManualFileEdits({
github,
context,
core,
repoPath,
dry,
}) {
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
@@ -96,3 +91,5 @@ export default async function checkManualFileEdits({
})
}
}
module.exports = checkManualFileEdits

View File

@@ -1,13 +1,12 @@
// @ts-nocheck
import { classify } from './supportedBranches.js'
const { classify } = require('../supportedBranches.js')
function runChecklist({
committers,
events,
files,
pull_request,
log,
maintainers,
reviews,
user,
userIsMaintainer,
}) {
@@ -28,35 +27,18 @@ function runChecklist({
.reduce((acc, cur) => acc?.intersection(cur) ?? cur)
const approvals = new Set(
reviews
events
.filter(
({ state, commit }) =>
state === 'APPROVED' &&
({ event, state, commit_id }) =>
event === 'reviewed' &&
state === 'approved' &&
// Only approvals for the current head SHA count, otherwise authors could push
// bad code between the approval and the merge.
commit?.oid === pull_request.head.sha,
commit_id === pull_request.head.sha,
)
.map(({ user }) => user.id),
)
// 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',
.map(({ user }) => user?.id)
// Some users have been deleted, so filter these out.
.filter(Boolean),
)
const checklist = {
@@ -75,11 +57,6 @@ function runChecklist({
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) {
@@ -120,10 +97,10 @@ function hasMergeCommand(body) {
return (body ?? '')
.replace(/<!--.*?-->/gms, '')
.replace(/(^`{3,})[^`].*?\1/gms, '')
.match(/^@NixOS\/nixpkgs-merge-bot merge\s*$/im)
.match(/^@NixOS\/nixpkgs-merge-bot merge\s*$/m)
}
export async function handleMergeComment({ github, body, node_id, reaction }) {
async function handleMergeComment({ github, body, node_id, reaction }) {
if (!hasMergeCommand(body)) return
await github.graphql(
@@ -138,7 +115,7 @@ export async function handleMergeComment({ github, body, node_id, reaction }) {
)
}
export async function handleMerge({
async function handleMerge({
github,
context,
core,
@@ -146,7 +123,6 @@ export async function handleMerge({
dry,
pull_request,
events,
reviews,
maintainers,
getTeamMembers,
getUser,
@@ -172,14 +148,6 @@ export async function handleMerge({
// including an early exit when the first non-by-name file is found.
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.
const lastPush = events.findLastIndex(
({ event, sha, commit_id }) =>
@@ -205,12 +173,10 @@ export 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() {
if (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
@@ -231,37 +197,16 @@ export async function handleMerge({
{ node_id: pull_request.node_id, sha: pull_request.head.sha },
)
log('merge', 'Queued for merge')
return {
reaction: 'ROCKET',
messages: [
`:heavy_check_mark: [Queued](${resp.enqueuePullRequest.mergeQueueEntry.mergeQueue.url}) for merge (#306934)`,
],
}
return [
`:heavy_check_mark: [Queued](${resp.enqueuePullRequest.mergeQueueEntry.mergeQueue.url}) for merge (#306934)`,
]
} catch (e) {
log('Enqueuing failed', e.response.errors[0].message)
}
// Enqueuing fails when the required status checks are not satisfied, yet. If CI has
// already failed, enabling auto-merge would be pointless: it would never fire, and
// fixing CI requires a new push, which invalidates this merge command anyway (we only
// 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.
// If required status checks are not satisfied, yet, the above will fail. In this case
// we can enable auto-merge. We could also only use auto-merge, but this often gets
// stuck for no apparent reason.
try {
await github.graphql(
`mutation($node_id: ID!, $sha: GitObjectID) {
@@ -274,17 +219,12 @@ export async function handleMerge({
{ node_id: pull_request.node_id, sha: pull_request.head.sha },
)
log('merge', 'Auto-merge enabled')
return {
reaction: 'ROCKET',
messages: [
`:heavy_check_mark: Enabled Auto Merge (#306934)`,
'',
'> [!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.',
],
}
return [
`:heavy_check_mark: Enabled Auto Merge (#306934)`,
'',
'> [!TIP]',
'> Sometimes GitHub gets stuck after enabling Auto Merge. In this case, leaving another approval should trigger the merge.',
]
} catch (e) {
log('Auto Merge failed', e.response.errors[0].message)
throw new Error(e.response.errors[0].message)
@@ -327,11 +267,11 @@ export async function handleMerge({
const { result, eligible, checklist } = runChecklist({
committers,
events,
files,
pull_request,
log,
maintainers,
reviews,
user: comment.user,
userIsMaintainer: await isMaintainer(comment.user.login),
})
@@ -368,12 +308,10 @@ export async function handleMerge({
}
if (result) {
await react('ROCKET')
try {
const { reaction, messages } = await merge()
await react(reaction)
body.push(...messages)
body.push(...(await merge()))
} catch (e) {
await react('THUMBS_DOWN')
// Remove the HTML comment with node_id reference to allow retrying this merge on the next run.
body.shift()
body.push(`:x: Merge failed with: ${e} (#371492)`)
@@ -398,14 +336,19 @@ export async function handleMerge({
const { result } = runChecklist({
committers,
events,
files,
pull_request,
log,
maintainers,
reviews,
})
// Returns a boolean, which indicates whether the PR is merge-bot eligible in principle.
// This is used to set the respective label in bot.js.
return result
}
module.exports = {
handleMerge,
handleMergeComment,
}

View File

@@ -4,16 +4,13 @@
"requires": true,
"packages": {
"": {
"name": "github-script",
"dependencies": {
"@actions/artifact": "6.2.1",
"@actions/core": "1.10.1",
"@actions/github": "9.1.0",
"bottleneck": "2.19.5",
"commander": "14.0.3"
},
"devDependencies": {
"@types/node": "24.13.3",
"typescript": "7.0.2"
}
},
"node_modules/@actions/artifact": {
@@ -592,19 +589,6 @@
"protoc-gen-ts": "bin/protoc-gen-ts"
}
},
"node_modules/@protobuf-ts/plugin/node_modules/typescript": {
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=4.2.0"
}
},
"node_modules/@protobuf-ts/protoc": {
"version": "2.11.1",
"resolved": "https://registry.npmjs.org/@protobuf-ts/protoc/-/protoc-2.11.1.tgz",
@@ -629,336 +613,6 @@
"@protobuf-ts/runtime": "^2.11.1"
}
},
"node_modules/@types/node": {
"version": "24.13.3",
"resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.3.tgz",
"integrity": "sha512-Dh8vAsV36ig5wa9OX4pXvMc9D3Veibfw2wix0CUwYODLD8nkj9UsLjASr49nPg+2eKzxhBV+v7L8pXvT4e639Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"undici-types": "~7.18.0"
}
},
"node_modules/@typescript/typescript-aix-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-aix-ppc64/-/typescript-aix-ppc64-7.0.2.tgz",
"integrity": "sha512-MTKKkWB7p/0E9xi1d1tHtZ5PiLkGEMIq88pK2CubZjOsLtYTLqhgIgi6zepFa+9GHZ6h05NMCkQxGKiPXMxXtQ==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"aix"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-arm64/-/typescript-darwin-arm64-7.0.2.tgz",
"integrity": "sha512-gowzar9MwS/aRWp6f3a4KUqzRjAZjOsmGNCM6LcTgXum+dBfgsBVMN+AgvOCCbguXyick6LJhpBszxMebJ8syA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-darwin-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-darwin-x64/-/typescript-darwin-x64-7.0.2.tgz",
"integrity": "sha512-SZ9xZInqApNlNGc9s0W1VSsktYSOe9cFqNOIqmN1Gs8SmkjKZYFt017G4VwPxASInODuAdbTW7sXiFUf893RgA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"darwin"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-arm64/-/typescript-freebsd-arm64-7.0.2.tgz",
"integrity": "sha512-W5NH4y/J0plIIS5b2xvTEkU7JFxyqdMAOgf+Ilhl0vHQXKO5dZoxd+C/jEtq56c4F3wk71RB4BMRQ2XdI+bwYQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-freebsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-freebsd-x64/-/typescript-freebsd-x64-7.0.2.tgz",
"integrity": "sha512-UMGDx5sTpzNw3WiPebH7l90IWfJggEd+egHt/q6p7/Cm3zqoV7VxkGXt+3DxPIw8CcmvAB0j3sVVfbhX+M4Tpw==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"freebsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm/-/typescript-linux-arm-7.0.2.tgz",
"integrity": "sha512-gffT3xPz9sR7j/YJExkyPntrI0P2EP9XbOyWzth2/Gs0RstK+90RBcO0ncXoXy/beYll1SXw846Nf2zdnEz0QQ==",
"cpu": [
"arm"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-arm64/-/typescript-linux-arm64-7.0.2.tgz",
"integrity": "sha512-Qh4eU4/y3yDjnfjjyPYihMj5/ODIlmt+Bzu17OI+fiSRDW57QmU5SiN63exPRNJPKUzcc1INa1NXdrJ+MqHjUQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-loong64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-loong64/-/typescript-linux-loong64-7.0.2.tgz",
"integrity": "sha512-uEHck9i8hoAzXPiYRib1O7miOnz23SxIeVl6F4LXox+qov1K35jHcEW6VHKvZI+pyvl7fZEP4MCU5LYvIq1GuQ==",
"cpu": [
"loong64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-mips64el": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-mips64el/-/typescript-linux-mips64el-7.0.2.tgz",
"integrity": "sha512-R4KvAMnE43W5Qeqb0Ly56O3mWMWIAgsMyz36DCaycd5nbg/9kzm0liw3JocfRqyJY0KPmzFjbswozXyW0DnIYA==",
"cpu": [
"mips64el"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-ppc64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-ppc64/-/typescript-linux-ppc64-7.0.2.tgz",
"integrity": "sha512-DORx5b3sd/4S7eayxm4FQv+A7CrkUIGRaHiwI8oiHTAI1fAPWhF4J0vAlkC8biAlHSVVwxMQ3tjZ2/DVbnQiiA==",
"cpu": [
"ppc64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-riscv64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-riscv64/-/typescript-linux-riscv64-7.0.2.tgz",
"integrity": "sha512-wf0jqEDOjrPRnKwYRyyJDRo11KMbvMFrU+q4zqKyChODBzvlkbhNQfKvLxQCcwTpdDaXSHZTVuh0JoCrKCUMHQ==",
"cpu": [
"riscv64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-s390x": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-s390x/-/typescript-linux-s390x-7.0.2.tgz",
"integrity": "sha512-IkwJc3L7yhytWd/ewjyxNDfOmswCm9GWMJT/ue/dU4aZNbwZeYAetq42VyLmsmSjvoX7z74X6ZaYCtzAr0EuGw==",
"cpu": [
"s390x"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-linux-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-linux-x64/-/typescript-linux-x64-7.0.2.tgz",
"integrity": "sha512-EYdf2cNg7rgCWJnxCdJ+F3V39O8ihb37eHAu1LK8oAFizgTQbPOK7zHHXbPt8rX24COqODXeI3sIf0fCXG7H/A==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"linux"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-arm64/-/typescript-netbsd-arm64-7.0.2.tgz",
"integrity": "sha512-+polYF4MF04aPpO5FTkHran9yUQDSXqy5GiSDKpsll5jy3l3+g9QLhpf39T+ePtefhXLOGrLl0QIjkQP6VnelA==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-netbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-netbsd-x64/-/typescript-netbsd-x64-7.0.2.tgz",
"integrity": "sha512-8YIT0EHM/3dq10ZOVF/A7pc/YSMtbcecct4rWtexrnSCHOPcpC2KTLXfTCR6vDpnSiY12heNb1GiN/wu+T/FyA==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"netbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-arm64/-/typescript-openbsd-arm64-7.0.2.tgz",
"integrity": "sha512-APT8+ClYnuYm1u9+kgGXoMj2VzWzcymwh2gNSQVySHfkRDGOTVkoWLjCmOQSaO+PoqQ57B0flRp9SA+7GnnkzQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-openbsd-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-openbsd-x64/-/typescript-openbsd-x64-7.0.2.tgz",
"integrity": "sha512-yX7s+Q0Dln0Dt9tEzZsAjXXR/+ytBM7AlglaqyeMPxQszJ1JhlJdZ6jLA+IzldHtflX81em7lDao1xXu+aRRkg==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"openbsd"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-sunos-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-sunos-x64/-/typescript-sunos-x64-7.0.2.tgz",
"integrity": "sha512-dLJDGaLZ1D4HPQn62u1n8mBDkJREwMsAkCdkwd4Ieqw+x3TUyTsqY0YiBCtE6H6OzzgGk3iuZ3vFWRS+E8/d1g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"sunos"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-arm64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-arm64/-/typescript-win32-arm64-7.0.2.tgz",
"integrity": "sha512-Gyl1Vy6OsWesLzmq+EP0Fb7b4Nid5232AvcA2SFcdYreldpNtYFFofPjnt62y9hQy7VTaZp65ICJjuAQRaVcIQ==",
"cpu": [
"arm64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/typescript-win32-x64": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/@typescript/typescript-win32-x64/-/typescript-win32-x64-7.0.2.tgz",
"integrity": "sha512-0BQ3HkAHHlKLSp1qRvf3SUhGpGsDuhB/jgFw75guyqbxJqEaS0Cw/VFO8i2nHglJUzQCRtMMR/IBAKE3ETMC4g==",
"cpu": [
"x64"
],
"license": "Apache-2.0",
"optional": true,
"os": [
"win32"
],
"engines": {
"node": ">=16.20.0"
}
},
"node_modules/@typescript/vfs": {
"version": "1.6.1",
"resolved": "https://registry.npmjs.org/@typescript/vfs/-/vfs-1.6.1.tgz",
@@ -2004,37 +1658,16 @@
}
},
"node_modules/typescript": {
"version": "7.0.2",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-7.0.2.tgz",
"integrity": "sha512-8FYau96o3NKOhbjKi/qNvG/W5jhzxkbdm5sj9AbZ/5T5sWqn3hJgLfGx27sRKZWTvyzCP8dLRBTf5tBTSRVUNA==",
"version": "3.9.10",
"resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz",
"integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==",
"license": "Apache-2.0",
"bin": {
"tsc": "bin/tsc"
"tsc": "bin/tsc",
"tsserver": "bin/tsserver"
},
"engines": {
"node": ">=16.20.0"
},
"optionalDependencies": {
"@typescript/typescript-aix-ppc64": "7.0.2",
"@typescript/typescript-darwin-arm64": "7.0.2",
"@typescript/typescript-darwin-x64": "7.0.2",
"@typescript/typescript-freebsd-arm64": "7.0.2",
"@typescript/typescript-freebsd-x64": "7.0.2",
"@typescript/typescript-linux-arm": "7.0.2",
"@typescript/typescript-linux-arm64": "7.0.2",
"@typescript/typescript-linux-loong64": "7.0.2",
"@typescript/typescript-linux-mips64el": "7.0.2",
"@typescript/typescript-linux-ppc64": "7.0.2",
"@typescript/typescript-linux-riscv64": "7.0.2",
"@typescript/typescript-linux-s390x": "7.0.2",
"@typescript/typescript-linux-x64": "7.0.2",
"@typescript/typescript-netbsd-arm64": "7.0.2",
"@typescript/typescript-netbsd-x64": "7.0.2",
"@typescript/typescript-openbsd-arm64": "7.0.2",
"@typescript/typescript-openbsd-x64": "7.0.2",
"@typescript/typescript-sunos-x64": "7.0.2",
"@typescript/typescript-win32-arm64": "7.0.2",
"@typescript/typescript-win32-x64": "7.0.2"
"node": ">=4.2.0"
}
},
"node_modules/undici": {
@@ -2049,13 +1682,6 @@
"node": ">=14.0"
}
},
"node_modules/undici-types": {
"version": "7.18.2",
"resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.18.2.tgz",
"integrity": "sha512-AsuCzffGHJybSaRrmr5eHr81mwJU3kjw6M+uprWvCXiNeN9SOGwQ3Jn8jb8m3Z6izVgknn1R0FTCEAP2QrLY/w==",
"dev": true,
"license": "MIT"
},
"node_modules/universal-user-agent": {
"version": "7.0.3",
"resolved": "https://registry.npmjs.org/universal-user-agent/-/universal-user-agent-7.0.3.tgz",

View File

@@ -1,14 +1,10 @@
{
"private": true,
"scripts": {
"typecheck": "tsc --build",
"testsuite": "node --test",
"test": "npm run typecheck && npm run testsuite"
},
"type": "module",
"//": [
"Keep `@actions/core` and `@actions/github` in sync with",
"https://github.com/actions/github-script/blob/main/package.json."
"https://github.com/actions/github-script/blob/main/package.json.",
"Keep `@actions/artifact` and `bottleneck` in sync with",
"`.github/workflows/bot.yml`."
],
"dependencies": {
"@actions/artifact": "6.2.1",
@@ -16,9 +12,5 @@
"@actions/github": "9.1.0",
"bottleneck": "2.19.5",
"commander": "14.0.3"
},
"devDependencies": {
"@types/node": "24.13.3",
"typescript": "7.0.2"
}
}

View File

@@ -1,11 +1,9 @@
// @ts-nocheck
import { dismissReviews, postReview } from './reviews.js'
import { classify } from './supportedBranches.js'
import supportedSystems from './supportedSystems.js'
const { classify } = require('../supportedBranches.js')
const { postReview, dismissReviews } = require('./reviews.js')
const reviewKey = 'prepare'
const supportedSystems = require('./supportedSystems.js')
export default async ({ github, context, core, dry }) => {
module.exports = async ({ github, context, core, dry }) => {
const pull_number = context.payload.pull_request.number
for (const retryInterval of [5, 10, 20, 40, 80]) {
@@ -66,7 +64,7 @@ export default async ({ github, context, core, dry }) => {
// commits between that base and head is the real base. We can query for this via GitHub's
// REST API. There can be multiple candidates for the real base with the same number of
// commits. In this case we pick the "best" candidate by a fixed ordering of branches,
// as defined in ci/github-script/supportedBranches.js.
// as defined in ci/supportedBranches.js.
//
// These requests take a while, when comparing against the wrong release - they need
// to look at way more than 10k commits in that case. Thus, we try to minimize the

View File

@@ -1,5 +1,4 @@
// @ts-nocheck
export async function handleReviewers({
async function handleReviewers({
github,
context,
core,
@@ -183,3 +182,7 @@ export async function handleReviewers({
teams_reached.size === 0
)
}
module.exports = {
handleReviewers,
}

View File

@@ -1,3 +1,5 @@
// @ts-check
const eventToState = {
COMMENT: 'COMMENTED',
REQUEST_CHANGES: 'CHANGES_REQUESTED',
@@ -14,7 +16,7 @@ const reviewUsers = [
]
/**
* @typedef {InstanceType<typeof import('@actions/github/lib/utils').GitHub>} GitHub
* @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
@@ -25,18 +27,12 @@ const reviewUsers = [
* @param {{
* github: GitHub,
* context: Context,
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* dry: boolean,
* reviewKey?: string,
* }} DismissReviewsProps
*/
export async function dismissReviews({
github,
context,
core,
dry,
reviewKey,
}) {
async function dismissReviews({ github, context, core, dry, reviewKey }) {
const pull_number = context.payload.pull_request?.number
if (!pull_number) {
core.warning('dismissReviews called outside of pull_request context')
@@ -169,14 +165,14 @@ export async function dismissReviews({
* @param {{
* github: GitHub,
* context: Context,
* core: typeof import('@actions/core'),
* core: import('@actions/core'),
* dry: boolean,
* body: string,
* event: keyof typeof eventToState,
* event: keyof eventToState,
* reviewKey: string,
* }} PostReviewProps
*/
export async function postReview({
async function postReview({
github,
context,
core,
@@ -268,3 +264,8 @@ export async function postReview({
}
}
}
module.exports = {
dismissReviews,
postReview,
}

View File

@@ -1,4 +1,4 @@
#!/usr/bin/env node
#!/usr/bin/env -S node --import ./run
import { execSync } from 'node:child_process'
import { closeSync, mkdtempSync, openSync, rmSync } from 'node:fs'
import { tmpdir } from 'node:os'
@@ -112,8 +112,8 @@ program
.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 checkTargetBranch = (await import('./check-target-branch.ts')).checkTargetBranch
await run(checkTargetBranch, owner, repo, pr, options)
const checkCommitMessages = (await import('./check-target-branch.js')).default
await run(checkCommitMessages, owner, repo, pr, options)
})
program

View File

@@ -1,5 +1,4 @@
// @ts-nocheck
export default async ({ github, context, targetSha }) => {
module.exports = async ({ github, context, targetSha }) => {
const { content, encoding } = (
await github.rest.repos.getContent({
...context.repo,

View File

@@ -1,26 +0,0 @@
{
"compilerOptions": {
"lib": [
"es2024",
"ESNext.Array",
"ESNext.Collection",
"ESNext.Error",
"ESNext.Iterator",
"ESNext.Promise"
],
"module": "nodenext",
"target": "es2024",
"strict": true,
"esModuleInterop": true,
"skipLibCheck": true,
"moduleResolution": "nodenext",
"allowImportingTsExtensions": true,
"allowJs": true,
"checkJs": true,
"erasableSyntaxOnly": true,
"verbatimModuleSyntax": true,
"noEmit": true,
}
}

View File

@@ -1,7 +1,6 @@
// @ts-nocheck
import Bottleneck from 'bottleneck'
module.exports = async ({ github, core, maxConcurrent = 1 }, callback) => {
const Bottleneck = require('bottleneck')
export default async ({ github, core, maxConcurrent = 1 }, callback) => {
const stats = {
issues: 0,
prs: 0,

View File

@@ -31,7 +31,6 @@ runCommand "nixpkgs-vet"
env.NIXPKGS_VET_NIX_PACKAGE = nix;
}
''
export NIX_STORE_DIR=$(mktemp -d)
export NIX_STATE_DIR=$(mktemp -d)
$NIXPKGS_VET_NIX_PACKAGE/bin/nix-store --init

View File

@@ -9,23 +9,23 @@
},
"branch": "nixpkgs-unstable",
"submodules": false,
"revision": "7525d999cd850b9a488817abc89c75dc733acf17",
"url": "https://github.com/NixOS/nixpkgs/archive/7525d999cd850b9a488817abc89c75dc733acf17.tar.gz",
"hash": "sha256-4IHyyLgLBdKefkljdKod4IMn023pQiDXAWJA187cmdY="
"revision": "02f3fa0374fa13707d42d55d58ecc76b091f223c",
"url": "https://github.com/NixOS/nixpkgs/archive/02f3fa0374fa13707d42d55d58ecc76b091f223c.tar.gz",
"hash": "0z8d33c5g0gk9a74ppqq77npisf9xx9c8ai9isxa2hyjx4lv1pki"
},
"nixpkgs-26.05-darwin": {
"treefmt-nix": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "NixOS",
"repo": "nixpkgs"
"owner": "numtide",
"repo": "treefmt-nix"
},
"branch": "nixpkgs-26.05-darwin",
"branch": "main",
"submodules": false,
"revision": "51fe96f9107566e6b8eeb7fc4ba696c01e548b04",
"url": "https://github.com/NixOS/nixpkgs/archive/51fe96f9107566e6b8eeb7fc4ba696c01e548b04.tar.gz",
"hash": "sha256-yj0LPLnsmYoLmA3FGANjeTEwej0/DHjZBXWnDQDUuIs="
"revision": "790751ff7fd3801feeaf96d7dc416a8d581265ba",
"url": "https://github.com/numtide/treefmt-nix/archive/790751ff7fd3801feeaf96d7dc416a8d581265ba.tar.gz",
"hash": "1zah3dmbpn3ap5acg22kq1j19dg32gj73l43yamjcxhc38sv9kd5"
}
},
"version": 8
"version": 5
}

View File

@@ -2,9 +2,6 @@
/*
#!nix-shell -i node -p nodejs
*/
// @ts-nocheck
import { resolve } from 'node:path'
import { fileURLToPath } from 'node:url'
const typeConfig = {
master: ['development', 'primary'],
@@ -47,13 +44,10 @@ function classify(branch) {
}
}
export { classify, split }
module.exports = { classify, split }
// If called directly via CLI, runs the following tests:
if (
process.argv[1] &&
fileURLToPath(import.meta.url) === resolve(process.argv[1])
) {
if (!module.parent) {
console.log('split(branch)')
function testSplit(branch) {
console.log(branch, split(branch))

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
#!nix-shell -i bash -E 'with import ../. {}; mkShell { packages = [ npins ]; }'
#!nix-shell -i bash -p npins
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
npins --lock-file pinned.json upgrade
npins --lock-file pinned.json update

View File

@@ -1,27 +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.
Use **examples** first to show how to get something done. Keep **Explanation** lean.
Use our [styleguide](./styleguide.md) for more in depth guidance on writing good documentation.
Documentation about Nixpkgs belongs here, this includes 'getting-started'-guides and 'onboarding-guides' for *using* Nixpkgs and the language frameworks it ships.
Write **guides** task-first: lead with a working example, then explain in prose.
Write **reference** as the specification of functions and attributes.
We are actively working to generate reference documentation from the [doc-comments](https://github.com/NixOS/rfcs/blob/master/rfcs/0145-doc-strings.md) present in code, which also lets you view it locally with `:doc` in `nix repl`.
See [Document structure](#document-structure) for a structural template.
> [!TIP]
> 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.
Rendered documentation:
- [Unstable (from master)](https://nixos.org/manual/nixpkgs/unstable/)
@@ -42,7 +36,7 @@ If the build succeeds, the manual will be in `./result/share/doc/nixpkgs/manual.
### 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
@@ -60,11 +54,9 @@ Make sure that your local files aren't added to Git history by adding the follow
/**/.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.
Changes to the renderer 'pkgs/by-name/ni/nixos-render-docs' need a manual restart. Run: `devmode` again.
Use [`devmode`](../pkgs/by-name/de/devmode/README.md) for a live preview when editing the manual.
### Testing redirects
@@ -193,15 +185,15 @@ watermelon
- If creating a commit purely for documentation changes, format the commit message in the following way:
```
doc/component: (documentation summary)
doc: (documentation summary)
(Motivation for change, relevant links, additional information.)
```
Examples:
* doc/stdenv: update the kernel config documentation to use `nix-shell`
* doc/getting-started: add information about `nix-update-script`
* doc: update the kernel config documentation to use `nix-shell`
* doc: add information about `nix-update-script`
Closes #216321.
@@ -215,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.
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
Put each sentence in its own line.
@@ -285,16 +219,17 @@ When changing existing content, update formatting if possible, but avoid excessi
### Examples first
Put examples before detailed explanations (see the [styleguide](./styleguide.md) for the rationale).
Readers look at examples first: an example communicates what something does faster than a description.
Put examples before detailed explanations.
Use this structure for each documented item:
Prefer this structure for each documented item:
1. Title
2. Abstract (optional, one sentence max)
2. Abstract (optional, one sentence max, the example often speaks for itself)
3. Example
4. Explanation (details, edge cases, types, defaults)
Rendered example:
For instance:
````markdown
## `lib.toUpper`
@@ -346,17 +281,11 @@ Returns the difference as a number.
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.
Keep each example at the level it documents:
- 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.
Provide at least one example per function, and make examples self-contained.
This is easier to understand for beginners.
It also helps with testing that it actually works especially once we introduce automation.
Example code should be such that it can be passed to `pkgs.callPackage`.
Instead of something like:

View File

@@ -15,3 +15,16 @@ In addition, it offers various options to customize parts of the builds.
There is no uniform interface for build helpers.
[Trivial build helpers](#chap-trivial-builders) and [fetchers](#chap-pkgs-fetchers) have various input types for convenience.
[Language- or framework-specific build helpers](#chap-language-support) usually follow the style of `stdenv.mkDerivation`, which accepts an attribute set or a fixed-point function taking an attribute set.
```{=include=} chapters
build-helpers/fixed-point-arguments.chapter.md
build-helpers/fetchers.chapter.md
build-helpers/trivial-build-helpers.chapter.md
build-helpers/testers.chapter.md
build-helpers/dev-shell-tools.chapter.md
build-helpers/special.md
build-helpers/images.md
hooks/index.md
languages-frameworks/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.
<!--
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.
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

View File

@@ -853,7 +853,7 @@ Used with CVS. Expects `cvsRoot`, `tag`, and `hash`.
Used with Mercurial. Expects `url`, `rev`, `hash`, overridable with [`<pkg>.overrideAttrs`](#sec-pkg-overrideAttrs).
A number of fetcher functions wrap lower-level fetchers such as `fetchurl`, `fetchzip`, and `fetchgit`. They are mainly convenience functions intended for commonly used destinations of source code in Nixpkgs. These wrapper fetchers are listed below.
A number of fetcher functions wrap part of `fetchurl` and `fetchzip`. They are mainly convenience functions intended for commonly used destinations of source code in Nixpkgs. These wrapper fetchers are listed below.
## `fetchFromGitea`, `fetchFromForgejo` and `fetchFromCodeberg` {#fetchfromgitea}
@@ -876,45 +876,6 @@ However, `fetchFromGitHub` will automatically switch to using `fetchgit` in any
When `fetchgit` is used, refer to the `fetchgit` section for documentation of its available options.
## `fetchFromHuggingFace` {#fetchfromhuggingface}
`fetchFromHuggingFace` fetches repositories from Hugging Face Hub. It expects
`repoId`, exactly one of `rev` or `tag`, and `hash`.
`repoId` must be in the form `repo` or `owner/repo`, so repositories such as
`gpt2` work as well.
::: {.example #ex-fetchfromhuggingface}
# Fetching a model repository from Hugging Face
```nix
fetchFromHuggingFace {
repoId = "hf-internal-testing/tiny-random-gpt2";
rev = "71034c5d8bde858ff824298bdedc65515b97d2b9";
backend = "lfs";
hash = "sha256-8K9B/C62GW5lXC0c8QQpQ9QAE1UMoG+kYqvGhnWIp64=";
}
```
:::
The optional `repoType` argument selects which Hugging Face Hub repository type
to use:
- `"model"` (default) fetches from `https://huggingface.co/<repo-id>`
- `"dataset"` fetches from `https://huggingface.co/datasets/<repo-id>`
- `"space"` fetches from `https://huggingface.co/spaces/<repo-id>`
To use a different Hugging Face Hub instance, use `domain`
(defaults to `"huggingface.co"`).
The optional `backend` argument defaults to `"xet"`. Because the Xet backend is
not implemented yet, callers must currently set `backend = "lfs"`, which uses
`fetchgit` with Git LFS enabled and defaults `fetchSubmodules` to `false`.
`rootDir`, `sparseCheckout`, and low-level `fetchgit` options such as
`deepClone`, `fetchTags`, `leaveDotGit`, and `branchName` are also supported.
## `fetchFromGitLab` {#fetchfromgitlab}
This is used with GitLab repositories. It behaves similarly to `fetchFromGitHub`, and expects `owner`, `repo`, `rev`, and `hash`.
@@ -988,20 +949,6 @@ fetchRadiclePatch {
}
```
## `fetchFromTangled` {#fetchfromtangled}
This is to be used with tangled repositories. `fetchFromTangled` works with
very similar arguments to `fetchFromGithub`. However, instead of a `owner` and
`repo`, a `did` argument is expected.
```nix
fetchFromTangled {
did = "did:plc:jj6ajj6duxnlthwtnob4qyuv"; # tranquil.farm/tranquil-pds
tag = "v6.6.0";
hash = "sha256-cfTsjmK/IMqT5kMKOGpwwWbBlvtrCDOerUJJ8AVI3kY=";
}
```
## `requireFile` {#requirefile}
`requireFile` allows requesting files that cannot be fetched automatically, but whose content is known.

View File

@@ -1,50 +1,48 @@
# 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
{
stdenv,
fetchurl,
}:
stdenv.mkDerivation (finalAttrs: {
pname = "hello";
version = "2.12";
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.
src = fetchurl {
url = "mirror://gnu/hello/hello-${finalAttrs.version}.tar.gz";
hash = "sha256-...";
};
})
```
## Defining a build helper with `lib.extendMkDerivation` {#sec-build-helper-extendMkDerivation}
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**.
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).
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).
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 `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
{
lib,
stdenv,
}:
preferLocalBuild ? true,
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 {
constructDrv = stdenv.mkDerivation;
excludeDrvArgNames = [
@@ -69,78 +67,4 @@ lib.extendMkDerivation {
```
:::
To apply extra changes to the result derivation, pass `transformDrv` to `lib.extendMkDerivation`:
```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
'';
});
}
```
:::
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: ...; }`.

View File

@@ -1,3 +1,12 @@
# Images {#chap-images}
This chapter describes tools for creating various types of images.
```{=include=} sections
images/appimagetools.section.md
images/dockertools.section.md
images/ocitools.section.md
images/portableservice.section.md
images/makediskimage.section.md
images/binarycache.section.md
```

View File

@@ -28,7 +28,7 @@ However, [those were unified early 2020](https://github.com/NixOS/nixpkgs/pull/8
```nix
{ appimageTools, fetchurl }:
appimageTools.wrapType2 {
let
pname = "nuclear";
version = "0.6.30";
@@ -36,7 +36,8 @@ appimageTools.wrapType2 {
url = "https://github.com/nukeop/nuclear/releases/download/v${version}/nuclear-v${version}.AppImage";
hash = "sha256-he1uGC1M/nFcKpMM9JKY4oeexJcnzV0ZRxhTjtJz6xw=";
};
}
in
appimageTools.wrapType2 { inherit pname version src; }
```
:::
@@ -55,7 +56,7 @@ There are a few ways to learn which dependencies an application needs:
```nix
{ appimageTools, fetchurl }:
appimageTools.wrapType2 {
let
pname = "irccloud";
version = "0.16.0";
@@ -63,7 +64,9 @@ appimageTools.wrapType2 {
url = "https://github.com/irccloud/irccloud-desktop/releases/download/v${version}/IRCCloud-${version}-linux-x86_64.AppImage";
hash = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
};
in
appimageTools.wrapType2 {
inherit pname version src;
extraPkgs = pkgs: [ pkgs.at-spi2-core ];
}
```
@@ -85,12 +88,12 @@ However, [those were unified early 2020](https://github.com/NixOS/nixpkgs/pull/8
# Extracting an AppImage to install extra files
`wrapType2` automatically extracts the AppImage for you and makes it available via the `contents` attribute.
Note how `finalAttrs.contents` is used in `extraInstallCommands` to install additional files that were extracted from the AppImage.
This example was adapted from a real package in Nixpkgs to show how `extract` is usually used in combination with `wrapType2`.
Note how `appimageContents` is used in `extraInstallCommands` to install additional files that were extracted from the AppImage.
```nix
{ appimageTools, fetchurl }:
appimageTools.wrapType2 (finalAttrs: {
let
pname = "irccloud";
version = "0.16.0";
@@ -99,24 +102,27 @@ appimageTools.wrapType2 (finalAttrs: {
hash = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
};
appimageContents = appimageTools.extract { inherit pname version src; };
in
appimageTools.wrapType2 {
inherit pname version src;
extraPkgs = pkgs: [ pkgs.at-spi2-core ];
extraInstallCommands = ''
mv $out/bin/irccloud-${version} $out/bin/irccloud
install -m 444 -D ${finalAttrs.contents}/irccloud.desktop $out/share/applications/irccloud.desktop
install -m 444 -D ${finalAttrs.contents}/usr/share/icons/hicolor/512x512/apps/irccloud.png \
install -m 444 -D ${appimageContents}/irccloud.desktop $out/share/applications/irccloud.desktop
install -m 444 -D ${appimageContents}/usr/share/icons/hicolor/512x512/apps/irccloud.png \
$out/share/icons/hicolor/512x512/apps/irccloud.png
substituteInPlace $out/share/applications/irccloud.desktop \
--replace-fail 'Exec=AppRun' 'Exec=irccloud'
'';
})
}
```
:::
`appimageTools` also exposes the `extract` function should you need to do it manually, requiring `pname`, `version`, and `src` arguments (`src` being the AppImage file to extract).
The arguments passed to `extract` can also contain a `postExtract` attribute, which allows you to execute additional commands after the files are extracted from the AppImage.
The argument passed to `extract` can also contain a `postExtract` attribute, which allows you to execute additional commands after the files are extracted from the AppImage.
`postExtract` must be a string with commands to run.
:::{.warning}
@@ -132,7 +138,7 @@ This is a rewrite of [](#ex-extracting-appimage) to use `postExtract` and `wrapA
```nix
{ appimageTools, fetchurl }:
appimageTools.wrapAppImage (finalAttrs: {
let
pname = "irccloud";
version = "0.16.0";
@@ -141,22 +147,30 @@ appimageTools.wrapAppImage (finalAttrs: {
hash = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
};
contents = appimageTools.extract {
inherit (finalAttrs) pname version src;
appimageContents = appimageTools.extract {
inherit pname version src;
postExtract = ''
substituteInPlace $out/irccloud.desktop --replace-fail 'Exec=AppRun' 'Exec=irccloud'
'';
};
in
appimageTools.wrapAppImage {
inherit pname version;
src = appimageContents;
extraPkgs = pkgs: [ pkgs.at-spi2-core ];
extraInstallCommands = ''
mv $out/bin/irccloud-${version} $out/bin/irccloud
install -m 444 -D ${finalAttrs.contents}/irccloud.desktop $out/share/applications/irccloud.desktop
install -m 444 -D ${finalAttrs.contents}/usr/share/icons/hicolor/512x512/apps/irccloud.png \
install -m 444 -D ${appimageContents}/irccloud.desktop $out/share/applications/irccloud.desktop
install -m 444 -D ${appimageContents}/usr/share/icons/hicolor/512x512/apps/irccloud.png \
$out/share/icons/hicolor/512x512/apps/irccloud.png
'';
})
# specify src archive for nix-update
passthru.src = src;
}
```
:::

View File

@@ -68,7 +68,7 @@ See [](#ex-portableService-hello) to understand how to use the output of `portab
: Allows you to override the package that provides {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `pkgs.squashfs-tools`.
_Default value:_ `pkgs.squashfsTools`.
`squash-compression` (String; _optional_)

View File

@@ -1,3 +1,13 @@
# Special build helpers {#chap-special}
This chapter describes several special build helpers.
```{=include=} sections
special/buildenv.section.md
special/fakenss.section.md
special/fhs-environments.section.md
special/makesetuphook.section.md
special/mkshell.section.md
special/vm-tools.section.md
special/checkpoint-build.section.md
```

View File

@@ -98,14 +98,6 @@ It has two modes:
: 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}
: An attribute set where the attribute names are regular expressions.
@@ -737,112 +729,4 @@ Notable attributes:
* `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).
- The generic tester only reads `config` and `checkDrv`. An integration may return additional attributes for its own integration-specific eval checks. Such extra attributes are optional.
`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.
`callReload` (function)
: `path -> string`.
Given a service's name `path` (the list of service names from the top-level service down to the target sub-service, e.g. `[ "reload" "inner" ]`), returns a shell command that reloads that service.
The command is embedded in `testExe` and executed with sufficient privilege to reload the service (e.g. as root in the test VM).
There is no manager-agnostic reload command, so every integration must provide this; the integration joins the `path` per its own unit-naming convention (the suite does not assume one).
On NixOS the `path` dash-joins into the systemd unit name with a `.service` suffix, so the command is `systemctl reload ${lib.concatStringsSep "-" path}.service` (a top-level service is a single-element path `[ "svc" ]` -> `svc.service`; a nested sub-service `[ "parent" "child" ]` -> `parent-child.service`).
:::{.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;
};
callReload = path: "systemctl reload ${lib.concatStringsSep "-" path}.service";
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

View File

@@ -165,7 +165,7 @@ They are useful for creating files from Nix expressions, and are all implemented
Each of these functions will cause a derivation to be produced.
When you coerce the result of each of these functions to a string with [string interpolation](https://nixos.org/manual/nix/stable/language/string-interpolation) or [`toString`](https://nixos.org/manual/nix/stable/language/builtins#builtins-toString), it will evaluate to the [store path](https://nixos.org/manual/nix/stable/store/store-path) of this derivation.
::: {.note}
:::: {.note}
Some of these functions will put the resulting files within a directory inside the [derivation output](https://nixos.org/manual/nix/stable/language/derivations#attr-outputs).
If you need to refer to the resulting files somewhere else in a Nix expression, append their path to the derivation's store path.
@@ -190,7 +190,7 @@ writeShellScript "evaluate-my-file.sh" ''
cat ${my-file}/share/my-file
''
```
:::
::::
### `makeDesktopItem` {#trivial-builder-makeDesktopItem}

View File

@@ -1,26 +0,0 @@
# How channels work {#how-channels-work}
nixpkgs uses the [channels feature](https://nixos.org/nix/manual/#sec-channels) of nix.
nixpkgs is distributed for users of Nix on non-NixOS distributions through the channel
`nixpkgs-unstable`. Users of NixOS generally use one of the `nixos-*` channels,
e.g. `nixos-22.11`, which includes all packages and modules for the stable NixOS
22.11. Stable NixOS releases are generally only given
security updates. More up to date packages and modules are available via the
`nixos-unstable` channel.
Both `nixos-unstable` and `nixpkgs-unstable` follow the `master` branch of the
nixpkgs repository, although both do lag the `master` branch by generally
[a couple of days](https://status.nixos.org/). Updates to a channel are
distributed as soon as all tests for that channel pass, e.g.
[this table](https://hydra.nixos.org/job/nixpkgs/trunk/unstable#tabs-constituents)
shows the status of tests for the `nixpkgs-unstable` channel.
The tests are conducted by a cluster called [Hydra](https://nixos.org/hydra/),
which also builds binary packages from the Nix expressions in Nixpkgs for
`x86_64-linux`, `aarch64-linux`, `x86_64-darwin` and `aarch64-darwin`.
The binaries are made available via a [binary cache](https://cache.nixos.org).
The current Nix expressions of the channels are available in the
[nixpkgs repository](https://github.com/NixOS/nixpkgs) in branches
that correspond to the channel names (e.g. `nixos-22.11-small`).

View File

@@ -1 +1,10 @@
# Contributing to Nixpkgs {#part-contributing}
```{=include=} chapters
contributing/quick-start.chapter.md
contributing/coding-conventions.chapter.md
contributing/submitting-changes.chapter.md
contributing/vulnerability-roundup.chapter.md
contributing/reviewing-contributions.chapter.md
contributing/contributing-to-documentation.chapter.md
```

View File

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

View File

@@ -4,3 +4,7 @@ This section shows you how Nixpkgs is developed and how you can interact with th
If you are interested in contributing yourself, see [CONTRIBUTING.md](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md).
<!-- In the future this section should also include: How to test pull requests, how to know if pull requests are available in channels, etc. -->
```{=include=} chapters
development/opening-issues.chapter.md
```

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

@@ -1,204 +0,0 @@
import json
import re
import sys
from pathlib import Path
from typing import TypedDict
# Coupled to where this file lives!
# Needed to resolve the relative includes file paths
DOC_ROOT = Path(__file__).resolve().parent.parent
ROOT_FILE = DOC_ROOT / "manual.md.in"
INCLUDE_RE = re.compile(r"^```\{=include=\}(?P<rest>.*)$")
FENCE_RE = re.compile(r"^(```|~~~)")
HEADING_RE = re.compile(r"^(#{1,6})\s+(.*?)\s*(?:\{#([^}]+)\})?\s*$")
class TokenIncludeBlock:
"""Represents a complete include block like:
```{=include=} sections
special/buildenv.section.md
```
As
typ = "sections"
files = [ "special/buildenv.section.md" ]
"""
kind = "include"
def __repr__(self):
# For debugging
return f"```{{=include=}} {self.typ}\n" "\n".join(self.files) + "\n```"
def __init__(self, typ, args, files, start, end):
self.typ: str = typ
self.args: list[str] = args
self.files: list[str] = files
self.start: int = start
self.end: int = end
def is_option_block(self) -> bool:
# option blocks have some special syntax which is part of another migration
# 8 coccurrences, seperate migration
return self.typ == "options"
def into_file(self) -> bool:
# into-file is trivial after the nav migration
# 2 coccurrences, can be migrated by hand
return any("html:into-file=" in arg for arg in self.args)
def keep(self) -> bool:
# Keep the include blocks that require seperate migration
return self.is_option_block() or self.into_file()
class TokenHeading:
kind = "heading"
def __init__(self, level, title, anchor):
self.level: int = level
self.title: str = title
self.anchor: str = anchor
def tokenize(src: str) -> list[TokenIncludeBlock|TokenHeading]:
"""Finds all Includes and Headings"""
lines = src.splitlines()
items = []
fenced = False
i = 0
while i < len(lines):
line = lines[i]
m = INCLUDE_RE.match(line)
if m and not fenced:
typ, *args = m.group("rest").split()
end = i + 1
while end < len(lines) and not lines[end].startswith("```"):
end += 1
if end == len(lines):
sys.exit(f"unterminated include block at line {i + 1}")
files = [f.strip() for f in lines[i + 1 : end] if f.strip()]
items.append(TokenIncludeBlock(typ, args, files, i, end))
i = end + 1
continue
if FENCE_RE.match(line):
fenced = not fenced
i += 1
continue
if not fenced:
m = HEADING_RE.match(line)
if m:
items.append(TokenHeading(len(m.group(1)), m.group(2), m.group(3)))
i += 1
return items
def read_source(source: Path) -> None | tuple[str, Path]:
"""Read a return [content,Path]
library.md is called .md.in; provided at build time via nixdoc
So the filename might differ
"""
if source.exists():
return source.read_text(), source
in_file = Path(str(source) + ".in")
if in_file.exists():
return in_file.read_text(), in_file
return None
# Make sure we process every file only once
visited = set()
# Map from filename -> line_nrs
# These lines will be deleted from the file
rewrites: dict[str, tuple[int,int]] = {}
group_ids: set[str] = set()
class Green(TypedDict):
label: str
id: str
children: list["Green"]
file: str | None
def convert_md_in(md_in: Path) -> Green:
"""Build up items for the nav.json as we recurse.
Collecting line-areas and group_ids
"""
if md_in in visited:
sys.exit(f"{md_in}: reached twice")
visited.add(md_in)
res = read_source(md_in)
rel_file = md_in.relative_to(DOC_ROOT).as_posix()
if not res:
return {"file": rel_file}
text, actual = res
token: list[TokenHeading|TokenIncludeBlock] = tokenize(text)
# Collect a list of actual files to be processed
# Recurse for files
# Do not recurse for "options", "into-file"
all_file_includes: list[TokenIncludeBlock] = [it for it in token if it.kind == "include" and not (it.is_option_block() or it.into_file())]
children = [convert_md_in((md_in.parent / f).resolve()) for b in all_file_includes for f in b.files]
# Lines to rewrite
include_blocks_to_rewrite: list[TokenIncludeBlock] = [it for it in all_file_includes if not it.keep()]
rewrites[actual] = [(b.start, b.end) for b in include_blocks_to_rewrite]
if not children:
return {"file": rel_file}
title = next((it for it in token if it.kind == "heading" and it.level == 1), None)
if title is None:
sys.exit(f"{md_in}: no level-1 heading to label its group")
if not title.anchor:
sys.exit(f"{md_in}: level-1 heading has no id")
if title.anchor in group_ids:
sys.exit(f"{md_in}: duplicate group id {title.anchor}")
group_ids.add(title.anchor)
return Green({
"label": title.title.replace("`", ""),
"id": title.anchor,
"children": [{"file": rel_file}] + children,
})
def remove_includes(path: Path, drop_lines: tuple[int,int]):
if not drop_lines:
return
lines = path.read_text().splitlines()
for start, end in sorted(drop_lines, reverse=True):
del lines[start : end + 1]
if 0 < start < len(lines) and not lines[start - 1].strip() and not lines[start].strip():
del lines[start]
while lines and not lines[-1].strip():
lines.pop()
path.write_text("\n".join(lines) + "\n")
def main():
nav = DOC_ROOT / "nav.json"
if json.loads(nav.read_text())["items"]:
sys.exit("nav.json already has items; This tool can only run once")
root = convert_md_in(ROOT_FILE)
items = root["children"][1:]
nav.write_text(json.dumps({"open": [], "items": items}, indent=2) + "\n")
for path, lines in rewrites.items():
remove_includes(path, lines)
if __name__ == "__main__":
main()

View File

@@ -73,7 +73,6 @@ stdenvNoCC.mkDerivation (
../anchor.min.js
../manpage-urls.json
../redirects.json
../nav.json
]
);
};
@@ -117,10 +116,8 @@ stdenvNoCC.mkDerivation (
--script ./highlightjs/loader.js \
--script ./anchor.min.js \
--script ./anchor-use.js \
--sidebar-depth 3 \
--experimental-config ./nav.json \
--header ${./header.html}\
--no-navheader \
--toc-depth 1 \
--section-toc-depth 1 \
manual.md \
out/index.html

View File

@@ -1,3 +1,11 @@
# Functions reference {#chap-functions}
The Nixpkgs repository has several utility functions to manipulate Nix expressions.
```{=include=} sections
functions/library.md
functions/generators.section.md
functions/debug.section.md
functions/prefer-remote-fetch.section.md
functions/nix-gitignore.section.md
```

View File

@@ -1,49 +0,0 @@
# Dev environments {#dev-environments}
Create a `shell.nix` with the following:
```nix
# shell.nix
let
nixpkgs = fetchTarball "https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz";
pkgs = import nixpkgs { };
in
pkgs.mkShell {
packages = [ pkgs.python3 ];
shellHook = ''
echo "Welcome in my nix shell"
'';
}
```
run
```sh
nix-shell
```
This activates your `shell.nix` and you should see:
```sh
unpacking 'https://github.com/NixOS/nixpkgs/archive/nixos-unstable.tar.gz' into the Git cache...
Welcome in your nix shell
```
python3 is available
```sh
$ python3 --version
```
To leave the shell
```bash
ctrl+D
```
:::{.note}
You should use [pinned nixpkgs](https://nix.dev/guides/recipes/dependency-management.html).
The example used `unstable` here for demonstration purposes only
:::
For further information check out [nix-shell](https://nix.dev/manual/nix/stable/command-ref/nix-shell)

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 +0,0 @@
# Getting started {#getting-started}

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.

3
doc/hooks/ghc.section.md Normal file
View File

@@ -0,0 +1,3 @@
# GHC {#ghc}
Creates a temporary package database and registers every Haskell build input in it (TODO: how?).

View File

@@ -4,3 +4,51 @@ Nixpkgs has several hook packages that augment the stdenv phases.
The stdenv built-in hooks are documented in [](#ssec-setup-hooks).
```{=include=} sections
autoconf.section.md
automake.section.md
autopatchcil.section.md
autopatchelf.section.md
aws-c-common.section.md
bmake.section.md
breakpoint.section.md
cernlib.section.md
cmake.section.md
desktop-file-utils.section.md
gdk-pixbuf.section.md
ghc.section.md
gnome.section.md
haredo.section.md
installShellFiles.section.md
installFonts.section.md
julec.section.md
just.section.md
libglycin.section.md
libiconv.section.md
libxml2.section.md
meson.section.md
mpi-check-hook.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
perl.section.md
pkg-config.section.md
postgresql-test-hook.section.md
premake.section.md
python.section.md
scons.section.md
tauri.section.md
tetex-tex-live.section.md
udevCheckHook.section.md
unzip.section.md
validatePkgConfig.section.md
versionCheckHook.section.md
waf.section.md
zig.section.md
xcbuild.section.md
xfce4-dev-tools.section.md
```

View File

@@ -24,10 +24,10 @@ stdenv.mkDerivation {
## Variables controlling `juce.projucerHook` {#juce-projucer-hook-variables}
### `dontUseProjucerConfigure` {#juce-dontuseprojucerconfigure}
### `dontUseProjucerConfigure`
Disables `projucerConfigurePhase`
### `dontUseProjucerInstall` {#juce-dontuseprojucerinstall}
### `dontUseProjucerInstall`
Disables `projucerInstallPhase`

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

@@ -73,7 +73,7 @@ Controls the flags passed to `cargo tauri build`.
#### `tauriBundleType` {#tauri-bundle-type}
The [bundle type](https://tauri.app/reference/javascript/api/namespaceapp/#bundletype) to build.
The [bundle type](https://tauri.app/v1/guides/building/) to build.
#### `dontTauriBuild` {#dont-tauri-build}

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` (or `nativeCheckInputs`, `nativeInstallCheckInputs`, etc.) of the package.

View File

@@ -1 +1,5 @@
# Interoperability Standards {#part-interoperability}
```{=include=} chapters
interoperability/cyclonedx.md
```

View File

@@ -39,7 +39,7 @@ The `nix:narinfo` properties should be accompanied by a `nix:store_path` propert
| `nix:narinfo:system` | The hardware and software platform on which this component is produced. |
| `nix:narinfo:sig` | Signatures claiming that this component is what it claims to be. |
| `nix:narinfo:ca` | Content address of this store object's file system object, used to compute its store path. |
| `nix:narinfo:references` | A whitespace-separated array of store paths that this component references. |
| `nix:narinfo:references` | A whitespace separated array of store paths that this component references. |
### `nix:fod` {#sec-interop.cylonedx-fod}

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