Compare commits

..

3 Commits

Author SHA1 Message Date
Raito Bezarius
95582ade4c nixos/netboot: use config.system.boot.loader.initrdFile instead of hardcoding initrd, disable compression for initrd 2024-02-11 17:50:37 +01:00
Raito Bezarius
fd110f5fea nixos/tests/netboot: add directBoot test
This verifies that we can direct boot a netboot image as expected.
2024-02-11 17:50:37 +01:00
Raito Bezarius
5c0bc727e6 nixos/virtualisation/qemu-vm: deep merge fileSystems
Sometimes, you would like to inherit from the VM framework and your user
code because you know better than the VM framework rather than replacing
wholesale the fileSystems module.

This came up for netboot testing needs.
2024-02-11 16:32:43 +01:00
56210 changed files with 2599558 additions and 4423787 deletions

View File

@@ -17,10 +17,6 @@ end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
# We want readFile .version to return the version without a newline.
[.version]
insert_final_newline = false
# see https://nixos.org/nixpkgs/manual/#chap-conventions
# Match json/lockfiles/markdown/nix/perl/python/ruby/shell/docbook files, set indent to spaces
@@ -44,11 +40,6 @@ indent_size = 4
indent_size = 2
indent_style = space
# Match package.json and package-lock.json, which are generally pulled from upstream and accept them as they are
[package{,-lock}.json]
indent_style = unset
insert_final_newline = unset
# Disable file types or individual files
# some of these files may be auto-generated and/or require significant changes
@@ -82,18 +73,38 @@ charset = unset
[eggs.nix]
trim_trailing_whitespace = unset
[nixos/modules/services/networking/ircd-hybrid/*.{conf,in}]
trim_trailing_whitespace = unset
[pkgs/build-support/dotnetenv/Wrapper/**]
end_of_line = unset
indent_style = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
[pkgs/development/compilers/elm/registry.dat]
end_of_line = unset
insert_final_newline = unset
# Keep this hint at the bottom:
# Please don't add entries for subfolders here.
# Create <subfolder>/.editorconfig instead.
# Added to avoid mass-rebuild in stable
[pkgs/build-support/kernel/paths-from-graph.pl]
[pkgs/development/haskell-modules/hackage-packages.nix]
indent_style = unset
trim_trailing_whitespace = unset
# Added to avoid mass-rebuild in stable
[pkgs/by-name/po/polkit/system_bus.conf]
[pkgs/misc/documentation-highlighter/**]
insert_final_newline = unset
[pkgs/servers/dict/wordnet_structures.py]
trim_trailing_whitespace = unset
[pkgs/tools/misc/timidity/timidity.cfg]
trim_trailing_whitespace = unset
[pkgs/tools/virtualization/ovftool/*.ova]
end_of_line = unset
insert_final_newline = unset
trim_trailing_whitespace = unset
charset = unset
[lib/tests/*.plist]
indent_style = tab
insert_final_newline = unset

View File

@@ -40,9 +40,6 @@ d1c1a0c656ccd8bd3b25d3c4287f2d075faf3cf3
# fix indentation in meteor default.nix
a37a6de881ec4c6708e6b88fd16256bbc7f26bbd
# pkgs/stdenv/make-derivation: Reindent
b4cc2a2479a7ab0f6440b2e1319221920ef72699
# treewide: automatically md-convert option descriptions
2e751c0772b9d48ff6923569adfa661b030ab6a2
@@ -99,116 +96,3 @@ fb0e5be84331188a69b3edd31679ca6576edb75a
# nixos/*: add trivial defaultText for options with simple defaults
25124556397ba17bfd70297000270de1e6523b0a
# systemd: rewrite comments
92dfeb7b3dab820ae307c56c216d175c69ee93cd
# systemd: break too long lines of Nix code
67643f8ec84bef1482204709073e417c9f07eb87
# {pkgs/development/cuda-modules,pkgs/test/cuda,pkgs/top-level/cuda-packages.nix}: reformat all CUDA files with nixfmt-rfc-style 2023-03-01
802a1b4d3338f24cbc4efd704616654456d75a94
# postgresql: move packages.nix to ext/default.nix
719034f6f6749d624faa28dff259309fc0e3e730
# php ecosystem: reformat with nixfmt-rfc-style
75ae7621330ff8db944ce4dff4374e182d5d151f
c759efa5e7f825913f9a69ef20f025f50f56dc4d
# pkgs/os-specific/bsd: Reformat with nixfmt-rfc-style 2024-03-01
3fe3b055adfc020e6a923c466b6bcd978a13069a
# k3s: format with nixfmt-rfc-style
6cfcd3c75428ede517bc6b15a353d704837a2830
# python3Packages: format with nixfmt
59b1aef59071cae6e87859dc65de973d2cc595c0
# treewide description changes (#317959)
bf995e3641950f4183c1dd9010349263dfa0123b
755b915a158c9d588f08e9b08da9f7f3422070cc
f8c4a98e8e138e21353a2c33b90db3359f539b37
# vscode-extensions.*: format with nixfmt (RFC 166)
7bf9febfa6271012b1ef86647a3a06f06875fdcf
# remove uses of mdDoc (#303841)
1a24330f792c8625746d07d842290e6fd95ae6f9
acd0e3898feb321cb9a71a0fd376f1157d0f4553
1b28414d2886c57343864326dbb745a634d3e37d
6afb255d976f85f3359e4929abd6f5149c323a02
# azure-cli: move to by-name, nixfmt #325950
96cd538b68bd1d0a0a37979356d669abbba32ebc
# poptracker: format with nixfmt-rfc-style (#326697)
ff5c8f6cc3d1f2e017e86d50965c14b71f00567b
# mangal: format with nixfmt-rfc-style #328284
3bb5e993cac3a6e1c3056d2bc9bf43eb2c7a5951
# pico-sdk: switch to finalAttrs (#329438)
8946018b0391ae594d167f1e58497b18de068968
# ollama: format with nixfmt-rfc-style (#329353)
bdfde18037f8d9f9b641a4016c8ada4dc4cbf856
# nixos/ollama: format with nixfmt-rfc-style (#329561)
246d1ee533810ac1946d863bbd9de9b525818d56
# steam: cleanup (#216972)
ad815aebfbfe1415ff6436521d545029c803c3fb
# nixos/nvidia: apply nixfmt-rfc-style (#313440)
fbdcdde04a7caa007e825a8b822c75fab9adb2d6
# treewide: reformat files which need reformatting after (#341407)
e0464e47880a69896f0fb1810f00e0de469f770a
# step-cli: format package.nix with nixfmt (#331629)
fc7a83f8b62e90de5679e993d4d49ca014ea013d
# ndn-cxx: format with nixfmt-rfc-style
160b2b769c3b8a6d1ae9947afa77520fa2887db7
# ndn-tools: format with nixfmt-rfc-style
4882ef721ce3d7bb3b5e48ff80125255db515013
# nfd: format with nixfmt-rfc-style
548c2377fa81e2abfc192fbf4f521e601251c468
# darwin.stdenv: format with nixfmt-rfc-style (#333962)
93c10ac9e561c6594d3baaeaff2341907390d9b8
# nrr: format with nixfmt-rfc-style (#334578)
cffc27daf06c77c0d76bc35d24b929cb9d68c3c9
# nixos/kanidm: inherit lib, nixfmt
8f18393d380079904d072007fb19dc64baef0a3a
# fetchurl: nixfmt-rfc-style
ce21e97a1f20dee15da85c084f9d1148d84f853b
# percona: apply nixfmt
8d14fa2886fec877690c6d28cfcdba4503dbbcea
# nixos/virtualisation: format image-related files
# Original formatting commit that was reverted
04fadac429ca7d6b92025188652376c230205730
# Revert commit
4cec81a9959ce612b653860dcca53101a36f328a
# Final commit that does the formatting
88b285c01d84de82c0b2b052fd28eaf6709c2d26
# sqlc: format with nixfmt
2bdec131b2bb2c8563f4556d741d34ccb77409e2
# treewide: migrate packages to pkgs/by-name, take 1
571c71e6f73af34a229414f51585738894211408
# treewide nixfmt reformat pass 1, master, staging and staging-next
d9d87c51960050e89c79e4025082ed965e770d68
# treewide format of all Nix files
14182c19701221692b84e7428e5b7281b099967a # !autorebase nix-shell --run treefmt

2
.gitattributes vendored
View File

@@ -16,5 +16,3 @@ nixos/doc/default.nix linguist-documentation=false
nixos/modules/module-list.nix merge=union
# pkgs/top-level/all-packages.nix merge=union
ci/OWNERS linguist-language=CODEOWNERS

346
.github/CODEOWNERS vendored Normal file
View File

@@ -0,0 +1,346 @@
# CODEOWNERS file
#
# This file is used to describe who owns what in this repository. This file does not
# replace `meta.maintainers` but is instead used for other things than derivations
# and modules, like documentation, package sets, and other assets.
#
# For documentation on this file, see https://help.github.com/articles/about-codeowners/
# Mentioned users will get code review requests.
#
# IMPORTANT NOTE: in order to actually get pinged, commit access is required.
# This also holds true for GitHub teams. Since almost none of our teams have write
# permissions, you need to list all members of the team with commit access individually.
# GitHub actions
/.github/workflows @NixOS/Security @Mic92 @zowoq
/.github/workflows/merge-staging @FRidh
# EditorConfig
/.editorconfig @Mic92 @zowoq
# Libraries
/lib @infinisil
/lib/systems @alyssais @ericson2314
/lib/generators.nix @infinisil @Profpatsch
/lib/cli.nix @infinisil @Profpatsch
/lib/debug.nix @infinisil @Profpatsch
/lib/asserts.nix @infinisil @Profpatsch
/lib/path.* @infinisil
/lib/fileset @infinisil
## Libraries / Module system
/lib/modules.nix @infinisil @roberth
/lib/types.nix @infinisil @roberth
/lib/options.nix @infinisil @roberth
/lib/tests/modules.sh @infinisil @roberth
/lib/tests/modules @infinisil @roberth
# Nixpkgs Internals
/default.nix @Ericson2314
/pkgs/top-level/default.nix @Ericson2314
/pkgs/top-level/impure.nix @Ericson2314
/pkgs/top-level/stage.nix @Ericson2314
/pkgs/top-level/splice.nix @Ericson2314
/pkgs/top-level/release-cross.nix @Ericson2314
/pkgs/stdenv/generic @Ericson2314
/pkgs/stdenv/generic/check-meta.nix @Ericson2314 @piegamesde
/pkgs/stdenv/cross @Ericson2314
/pkgs/build-support/cc-wrapper @Ericson2314
/pkgs/build-support/bintools-wrapper @Ericson2314
/pkgs/build-support/setup-hooks @Ericson2314
/pkgs/build-support/setup-hooks/auto-patchelf.sh @layus
/pkgs/build-support/setup-hooks/auto-patchelf.py @layus
/pkgs/pkgs-lib @infinisil
## Format generators/serializers
/pkgs/pkgs-lib/formats/libconfig @ckiee @h7x4
# pkgs/by-name
/pkgs/test/nixpkgs-check-by-name @infinisil
/pkgs/by-name/README.md @infinisil
/pkgs/top-level/by-name-overlay.nix @infinisil
/.github/workflows/check-by-name.yml @infinisil
# Nixpkgs build-support
/pkgs/build-support/writers @lassulus @Profpatsch
# Nixpkgs make-disk-image
/doc/build-helpers/images/makediskimage.section.md @raitobezarius
/nixos/lib/make-disk-image.nix @raitobezarius
# Nix, the package manager
pkgs/tools/package-management/nix/ @raitobezarius
nixos/modules/installer/tools/nix-fallback-paths.nix @raitobezarius
# Nixpkgs documentation
/maintainers/scripts/db-to-md.sh @jtojnar @ryantm
/maintainers/scripts/doc @jtojnar @ryantm
# Contributor documentation
/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
/maintainers/README.md @infinisil
# User-facing development documentation
/doc/development.md @infinisil
/doc/development @infinisil
# NixOS Internals
/nixos/default.nix @infinisil
/nixos/lib/from-env.nix @infinisil
/nixos/lib/eval-config.nix @infinisil
/nixos/modules/system @dasJ
/nixos/modules/system/activation/bootspec.nix @grahamc @cole-h @raitobezarius
/nixos/modules/system/activation/bootspec.cue @grahamc @cole-h @raitobezarius
# NixOS integration test driver
/nixos/lib/test-driver @tfc
# NixOS QEMU virtualisation
/nixos/virtualisation/qemu-vm.nix @raitobezarius
# Systemd
/nixos/modules/system/boot/systemd.nix @NixOS/systemd
/nixos/modules/system/boot/systemd @NixOS/systemd
/nixos/lib/systemd-*.nix @NixOS/systemd
/pkgs/os-specific/linux/systemd @NixOS/systemd
# Systemd-boot
/nixos/modules/system/boot/loader/systemd-boot @JulienMalka
# Images and installer media
/nixos/modules/installer/cd-dvd/ @samueldr
/nixos/modules/installer/sd-card/ @samueldr
# Updaters
## update.nix
/maintainers/scripts/update.nix @jtojnar
/maintainers/scripts/update.py @jtojnar
## common-updater-scripts
/pkgs/common-updater/scripts/update-source-version @jtojnar
# Python-related code and docs
/maintainers/scripts/update-python-libraries @FRidh
/pkgs/development/interpreters/python @FRidh
/doc/languages-frameworks/python.section.md @FRidh @mweinelt
/pkgs/development/interpreters/python/hooks @FRidh @jonringer
# Haskell
/doc/languages-frameworks/haskell.section.md @cdepillabout @sternenseemann @maralorn @ncfavier
/maintainers/scripts/haskell @cdepillabout @sternenseemann @maralorn @ncfavier
/pkgs/development/compilers/ghc @cdepillabout @sternenseemann @maralorn @ncfavier
/pkgs/development/haskell-modules @cdepillabout @sternenseemann @maralorn @ncfavier
/pkgs/test/haskell @cdepillabout @sternenseemann @maralorn @ncfavier
/pkgs/top-level/release-haskell.nix @cdepillabout @sternenseemann @maralorn @ncfavier
/pkgs/top-level/haskell-packages.nix @cdepillabout @sternenseemann @maralorn @ncfavier
# Perl
/pkgs/development/interpreters/perl @stigtsp @zakame @dasJ
/pkgs/top-level/perl-packages.nix @stigtsp @zakame @dasJ
/pkgs/development/perl-modules @stigtsp @zakame @dasJ
# R
/pkgs/applications/science/math/R @jbedo
/pkgs/development/r-modules @jbedo
# Ruby
/pkgs/development/interpreters/ruby @marsam
/pkgs/development/ruby-modules @marsam
# Rust
/pkgs/development/compilers/rust @Mic92 @zowoq @winterqt @figsoda
/pkgs/build-support/rust @zowoq @winterqt @figsoda
/doc/languages-frameworks/rust.section.md @zowoq @winterqt @figsoda
# C compilers
/pkgs/development/compilers/gcc
/pkgs/development/compilers/llvm @RaitoBezarius
/pkgs/development/compilers/emscripten @raitobezarius
/doc/languages-frameworks/emscripten.section.md @raitobezarius
# Audio
/nixos/modules/services/audio/botamusique.nix @mweinelt
/nixos/modules/services/audio/snapserver.nix @mweinelt
/nixos/tests/modules/services/audio/botamusique.nix @mweinelt
/nixos/tests/snapcast.nix @mweinelt
# Browsers
/pkgs/applications/networking/browsers/firefox @mweinelt
/pkgs/applications/networking/browsers/chromium @emilylange
/nixos/tests/chromium.nix @emilylange
# Certificate Authorities
pkgs/data/misc/cacert/ @ajs124 @lukegb @mweinelt
pkgs/development/libraries/nss/ @ajs124 @lukegb @mweinelt
pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
# Jetbrains
/pkgs/applications/editors/jetbrains @edwtjo
# Licenses
/lib/licenses.nix @alyssais
# Qt / KDE
/pkgs/applications/kde @ttuegel
/pkgs/desktops/plasma-5 @ttuegel
/pkgs/development/libraries/kde-frameworks @ttuegel
/pkgs/development/libraries/qt-5 @ttuegel
# PostgreSQL and related stuff
/pkgs/servers/sql/postgresql @thoughtpolice @marsam
/nixos/modules/services/databases/postgresql.xml @thoughtpolice
/nixos/modules/services/databases/postgresql.nix @thoughtpolice
/nixos/tests/postgresql.nix @thoughtpolice
# Hardened profile & related modules
/nixos/modules/profiles/hardened.nix @joachifm
/nixos/modules/security/hidepid.nix @joachifm
/nixos/modules/security/lock-kernel-modules.nix @joachifm
/nixos/modules/security/misc.nix @joachifm
/nixos/tests/hardened.nix @joachifm
/pkgs/os-specific/linux/kernel/hardened-config.nix @joachifm
# Home Automation
/nixos/modules/services/misc/home-assistant.nix @mweinelt
/nixos/modules/services/misc/zigbee2mqtt.nix @mweinelt
/nixos/tests/home-assistant.nix @mweinelt
/nixos/tests/zigbee2mqtt.nix @mweinelt
/pkgs/servers/home-assistant @mweinelt
/pkgs/tools/misc/esphome @mweinelt
# Network Time Daemons
/pkgs/tools/networking/chrony @thoughtpolice
/pkgs/tools/networking/ntp @thoughtpolice
/pkgs/tools/networking/openntpd @thoughtpolice
/nixos/modules/services/networking/ntp @thoughtpolice
# Network
/pkgs/tools/networking/octodns @Janik-Haag
/pkgs/tools/networking/kea/default.nix @mweinelt
/pkgs/tools/networking/babeld/default.nix @mweinelt
/nixos/modules/services/networking/babeld.nix @mweinelt
/nixos/modules/services/networking/kea.nix @mweinelt
/nixos/modules/services/networking/knot.nix @mweinelt
/nixos/modules/services/monitoring/prometheus/exporters/kea.nix @mweinelt
/nixos/tests/babeld.nix @mweinelt
/nixos/tests/kea.nix @mweinelt
/nixos/tests/knot.nix @mweinelt
# Web servers
/doc/packages/nginx.section.md @raitobezarius
/pkgs/servers/http/nginx/ @raitobezarius
/nixos/modules/services/web-servers/nginx/ @raitobezarius
# Dhall
/pkgs/development/dhall-modules @Gabriella439 @Profpatsch @ehmry
/pkgs/development/interpreters/dhall @Gabriella439 @Profpatsch @ehmry
# Idris
/pkgs/development/idris-modules @Infinisil
# Bazel
/pkgs/development/tools/build-managers/bazel @Profpatsch
# NixOS modules for e-mail and dns services
/nixos/modules/services/mail/mailman.nix @peti
/nixos/modules/services/mail/postfix.nix @peti
/nixos/modules/services/networking/bind.nix @peti
/nixos/modules/services/mail/rspamd.nix @peti
# Emacs
/pkgs/applications/editors/emacs/elisp-packages @adisbladis
/pkgs/applications/editors/emacs @adisbladis
/pkgs/top-level/emacs-packages.nix @adisbladis
# Neovim
/pkgs/applications/editors/neovim @figsoda @jonringer @teto
# VimPlugins
/pkgs/applications/editors/vim/plugins @figsoda @jonringer
# VsCode Extensions
/pkgs/applications/editors/vscode/extensions @jonringer
# PHP interpreter, packages, extensions, tests and documentation
/doc/languages-frameworks/php.section.md @aanderse @drupol @etu @globin @ma27 @talyz
/nixos/tests/php @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/build-support/php/build-pecl.nix @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/build-support/php @drupol @etu
/pkgs/development/interpreters/php @jtojnar @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/development/php-packages @aanderse @drupol @etu @globin @ma27 @talyz
/pkgs/top-level/php-packages.nix @jtojnar @aanderse @drupol @etu @globin @ma27 @talyz
# Docker tools
/pkgs/build-support/docker @roberth
/nixos/tests/docker-tools* @roberth
/doc/build-helpers/images/dockertools.section.md @roberth
# Blockchains
/pkgs/applications/blockchains @mmahut @RaghavSood
# Go
/doc/languages-frameworks/go.section.md @kalbasit @Mic92 @zowoq
/pkgs/build-support/go @kalbasit @Mic92 @zowoq
/pkgs/development/compilers/go @kalbasit @Mic92 @zowoq
# GNOME
/pkgs/desktops/gnome @jtojnar
/pkgs/desktops/gnome/extensions @piegamesde @jtojnar
/pkgs/build-support/make-hardcode-gsettings-patch @jtojnar
# Cinnamon
/pkgs/desktops/cinnamon @mkg20001
# nim
/pkgs/development/compilers/nim @ehmry
/pkgs/development/nim-packages @ehmry
/pkgs/top-level/nim-packages.nix @ehmry
# terraform providers
/pkgs/applications/networking/cluster/terraform-providers @zowoq
# Matrix
/pkgs/servers/heisenbridge @piegamesde
/pkgs/servers/matrix-conduit @piegamesde
/nixos/modules/services/misc/heisenbridge.nix @piegamesde
/nixos/modules/services/misc/matrix-conduit.nix @piegamesde
/nixos/tests/matrix-conduit.nix @piegamesde
# Forgejo
nixos/modules/services/misc/forgejo.nix @bendlas @emilylange
pkgs/applications/version-management/forgejo @bendlas @emilylange
# Dotnet
/pkgs/build-support/dotnet @IvarWithoutBones
/pkgs/development/compilers/dotnet @IvarWithoutBones
/pkgs/test/dotnet @IvarWithoutBones
/doc/languages-frameworks/dotnet.section.md @IvarWithoutBones
# Node.js
/pkgs/build-support/node/build-npm-package @lilyinstarlight @winterqt
/pkgs/build-support/node/fetch-npm-deps @lilyinstarlight @winterqt
/doc/languages-frameworks/javascript.section.md @lilyinstarlight @winterqt
# OCaml
/pkgs/build-support/ocaml @ulrikstrid
/pkgs/development/compilers/ocaml @ulrikstrid
/pkgs/development/ocaml-modules @ulrikstrid
# ZFS
pkgs/os-specific/linux/zfs/2_1.nix @raitobezarius
pkgs/os-specific/linux/zfs/generic.nix @raitobezarius
nixos/modules/tasks/filesystems/zfs.nix @raitobezarius
nixos/tests/zfs.nix @raitobezarius
# Zig
/pkgs/development/compilers/zig @figsoda
/doc/hooks/zig.section.md @figsoda
# Buildbot
nixos/modules/services/continuous-integration/buildbot @Mic92 @zowoq
nixos/tests/buildbot.nix @Mic92 @zowoq
pkgs/development/tools/continuous-integration/buildbot @Mic92 @zowoq

View File

@@ -8,4 +8,4 @@
## Technical details
<!-- Please insert the output of running `nix-shell -p nix-info --run "nix-info -m"` below this line -->
Please run `nix-shell -p nix-info --run "nix-info -m"` and paste the result.

View File

@@ -7,44 +7,38 @@ assignees: ''
---
## Describe the bug
<!-- A clear and concise description of what the bug is. -->
## Steps To Reproduce
### Describe the bug
A clear and concise description of what the bug is.
### Steps To Reproduce
Steps to reproduce the behavior:
1. ...
2. ...
3. ...
## Expected behavior
### Expected behavior
A clear and concise description of what you expected to happen.
<!-- A clear and concise description of what you expected to happen. -->
### Screenshots
If applicable, add screenshots to help explain your problem.
## Screenshots
### Additional context
Add any other context about the problem here.
<!-- If applicable, add screenshots to help explain your problem: -->
## Additional context
<!-- Add any other context about the problem here. -->
## Metadata
<!-- Please insert the output of running `nix-shell -p nix-info --run "nix-info -m"` below this line -->
## Notify maintainers
### Notify maintainers
<!--
Please @ people who are in the `meta.maintainers` list of the offending package or module.
If in doubt, check `git blame` for whoever last touched something.
-->
---
### Metadata
Please run `nix-shell -p nix-info --run "nix-info -m"` and paste the result.
Note for maintainers: Please tag this issue in your PR.
```console
[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
output here
```
---

View File

@@ -7,43 +7,36 @@ assignees: ''
---
## Steps To Reproduce
### Steps To Reproduce
Steps to reproduce the behavior:
1. build *X*
## Build log
<!-- insert build log in code block in collapsable section -->
<details>
<summary>Build Log</summary>
### Build log
```
log here if short otherwise a link to a gist
```
</details>
### Additional context
## Additional context
Add any other context about the problem here.
<!-- Add any other context about the problem here. -->
## Metadata
<!-- Please insert the output of running `nix-shell -p nix-info --run "nix-info -m"` below this line -->
## Notify maintainers
### Notify maintainers
<!--
Please @ people who are in the `meta.maintainers` list of the offending package or module.
If in doubt, check `git blame` for whoever last touched something.
-->
---
### Metadata
Note for maintainers: Please tag this issue in your PR.
Please run `nix-shell -p nix-info --run "nix-info -m"` and paste the result.
```console
[user@system:~]$ nix-shell -p nix-info --run "nix-info -m"
output here
```
---

View File

@@ -23,9 +23,12 @@ assignees: ''
- [ ] checked [open documentation issues] for possible duplicates
- [ ] checked [open documentation pull requests] for possible solutions
---
Note for maintainers: Please tag this issue in your PR.
[latest Nixpkgs manual]: https://nixos.org/manual/nixpkgs/unstable/
[latest NixOS manual]: https://nixos.org/manual/nixos/unstable/
[nixpkgs-source]: https://github.com/NixOS/nixpkgs/tree/master/doc
[nixos-source]: https://github.com/NixOS/nixpkgs/tree/master/nixos/doc/manual
[open documentation issues]: https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+label%3A%229.needs%3A+documentation%22
[open documentation pull requests]: https://github.com/NixOS/nixpkgs/pulls?q=is%3Aopen+is%3Apr+label%3A%228.has%3A+documentation%22%2C%226.topic%3A+documentation%22
---
@@ -33,9 +36,3 @@ Add a :+1: [reaction] to [issues you find important].
[reaction]: https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/
[issues you find important]: https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc
[latest Nixpkgs manual]: https://nixos.org/manual/nixpkgs/unstable/
[latest NixOS manual]: https://nixos.org/manual/nixos/unstable/
[nixpkgs-source]: https://github.com/NixOS/nixpkgs/tree/master/doc
[nixos-source]: https://github.com/NixOS/nixpkgs/tree/master/nixos/doc/manual
[open documentation issues]: https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+label%3A%229.needs%3A+documentation%22
[open documentation pull requests]: https://github.com/NixOS/nixpkgs/pulls?q=is%3Aopen+is%3Apr+label%3A%228.has%3A+documentation%22%2C%226.topic%3A+documentation%22

View File

@@ -1,27 +0,0 @@
---
name: Module requests
about: For NixOS modules that you would like to see
title: 'Module request: MODULENAME'
labels: '9.needs: module (new)'
assignees: ''
---
## Description
<!-- Describe what the module should accomplish: -->
## Notify maintainers
<!-- If applicable, tag the maintainers of the package that corresponds to the module. If the search.nixos.org result shows no maintainers, tag the person that last updated the package. -->
-----
Note for maintainers: Please tag this issue in your PR.
---
Add a :+1: [reaction] to [issues you find important].
[reaction]: https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/
[issues you find important]: https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+sort%3Areactions-%2B1-desc

View File

@@ -7,30 +7,23 @@ assignees: ''
---
## Package Information
<!-- Search for the package here: https://search.nixos.org/packages?channel=unstable -->
- Package name:
- Latest released version:
<!-- Search your package here: https://search.nixos.org/packages?channel=unstable -->
- Current version on the unstable channel:
- Current version on the stable/release channel:
## Checklist
<!--
Type the name of your package and try to find an open pull request for the package
If you find an open pull request, you can review it!
There's a high chance that you'll have the new version right away while helping the community!
-->
- [ ] Checked the [nixpkgs pull requests](https://github.com/NixOS/nixpkgs/pulls)
## Notify maintainers
**Notify maintainers**
<!-- If the search.nixos.org result shows no maintainers, tag the person that last updated the package. -->
---
-----
Note for maintainers: Please tag this issue in your PR.

View File

@@ -7,11 +7,11 @@ assignees: ''
---
## Project description
**Project description**
<!-- Describe the project a little: -->
## Metadata
**Metadata**
* homepage URL:
* source URL:
@@ -20,10 +20,6 @@ assignees: ''
---
Note for maintainers: Please tag this issue in your PR.
---
Add a :+1: [reaction] to [issues you find important].
[reaction]: https://github.blog/2016-03-10-add-reactions-to-pull-requests-issues-and-comments/

View File

@@ -31,12 +31,12 @@ Fixing bit-by-bit reproducibility also has additional advantages, such as
avoiding hard-to-reproduce bugs, making content-addressed storage more effective
and reducing rebuilds in such systems.
## Steps To Reproduce
### Steps To Reproduce
In the following steps, replace `<package>` with the canonical name of the
package.
### 1. Build the package
#### 1. Build the package
This step will build the package. Specific arguments are passed to the command
to keep the build artifacts so we can compare them in case of differences.
@@ -53,7 +53,7 @@ Or using the new command line style:
nix build nixpkgs#<package> && nix build nixpkgs#<package> --rebuild --keep-failed
```
### 2. Compare the build artifacts
#### 2. Compare the build artifacts
If the previous command completes successfully, no differences were found and
there's nothing to do, builds are reproducible.
@@ -67,7 +67,7 @@ metadata (*e.g. timestamp*) differences.
nix run nixpkgs#diffoscopeMinimal -- --exclude-directory-metadata recursive <Y> <Z>
```
### 3. Examine the build log
#### 3. Examine the build log
To examine the build log, use:
@@ -81,20 +81,10 @@ Or with the new command line style:
nix log $(nix path-info --derivation nixpkgs#<package>)
```
## Additional context
### Additional context
(please share the relevant fragment of the diffoscope output here, and any additional analysis you may have done)
## Notify maintainers
<!--
Please @ people who are in the `meta.maintainers` list of the offending package or module.
If in doubt, check `git blame` for whoever last touched something.
-->
---
Note for maintainers: Please tag this issue in your PR.
(please share the relevant fragment of the diffoscope output here, and any
additional analysis you may have done)
---

View File

@@ -1,7 +1,6 @@
## Description of changes
<!--
^ Please summarise the changes you have done and explain why they are necessary here ^
For package updates please link to a changelog or describe changes, this helps your fellow maintainers discover breaking updates.
For new packages please briefly describe the package or provide a link to its homepage.
-->
@@ -20,12 +19,12 @@ For new packages please briefly describe the package or provide a link to its ho
- [ ] `sandbox = true`
- [ ] Tested, as applicable:
- [NixOS test(s)](https://nixos.org/manual/nixos/unstable/index.html#sec-nixos-tests) (look inside [nixos/tests](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests))
- and/or [package tests](https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#package-tests)
- and/or [package tests](https://nixos.org/manual/nixpkgs/unstable/#sec-package-tests)
- or, for functions and "core" functionality, tests in [lib/tests](https://github.com/NixOS/nixpkgs/blob/master/lib/tests) or [pkgs/test](https://github.com/NixOS/nixpkgs/blob/master/pkgs/test)
- made sure NixOS tests are [linked](https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#linking-nixos-module-tests-to-a-package) to the relevant packages
- made sure NixOS tests are [linked](https://nixos.org/manual/nixpkgs/unstable/#ssec-nixos-tests-linking) to the relevant packages
- [ ] Tested compilation of all packages that depend on this change using `nix-shell -p nixpkgs-review --run "nixpkgs-review rev HEAD"`. Note: all changes have to be committed, also see [nixpkgs-review usage](https://github.com/Mic92/nixpkgs-review#usage)
- [ ] Tested basic functionality of all binary files (usually in `./result/bin/`)
- [24.11 Release Notes](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2411.section.md) (or backporting [23.11](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2311.section.md) and [24.05](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2405.section.md) Release notes)
- [24.05 Release Notes](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2405.section.md) (or backporting [23.05](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2305.section.md) and [23.11](https://github.com/NixOS/nixpkgs/blob/master/nixos/doc/manual/release-notes/rl-2311.section.md) Release notes)
- [ ] (Package updates) Added a release notes entry if the change is major or breaking
- [ ] (Module updates) Added a release notes entry if the change is significant
- [ ] (Module addition) Added a release notes entry if adding a new NixOS module
@@ -39,7 +38,7 @@ Reviewing helps to reduce the average time-to-merge for everyone.
Thanks a lot if you do!
List of open PRs: https://github.com/NixOS/nixpkgs/pulls
Reviewing guidelines: https://github.com/NixOS/nixpkgs/blob/master/pkgs/README.md#reviewing-contributions
Reviewing guidelines: https://nixos.org/manual/nixpkgs/unstable/#chap-reviewing-contributions
-->
---

View File

@@ -1,95 +0,0 @@
name: Get merge commit
description: 'Checks whether the Pull Request is mergeable and checks out the repo at up to two commits: The result of a temporary merge of the head branch into the target branch ("merged"), and the parent of that commit on the target branch ("target"). Handles push events and merge conflicts gracefully.'
inputs:
mergedSha:
description: "The merge commit SHA, previously collected."
type: string
merged-as-untrusted:
description: "Whether to checkout the merge commit in the ./untrusted folder."
type: boolean
targetSha:
description: "The target commit SHA, previously collected."
type: string
target-as-trusted:
description: "Whether to checkout the target commit in the ./trusted folder."
type: boolean
outputs:
mergedSha:
description: "The merge commit SHA"
value: ${{ steps.commits.outputs.mergedSha }}
targetSha:
description: "The target commit SHA"
value: ${{ steps.commits.outputs.targetSha }}
runs:
using: composite
steps:
- id: commits
if: ${{ !inputs.mergedSha && !inputs.targetSha }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
if (context.eventName == 'push') return core.setOutput('mergedSha', context.sha)
for (const retryInterval of [5, 10, 20, 40, 80]) {
console.log("Checking whether the pull request can be merged...")
const prInfo = (await github.rest.pulls.get({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
})).data
if (prInfo.state != 'open') throw new Error ("PR is not open anymore.")
if (prInfo.mergeable == null) {
console.log(`GitHub is still computing whether this PR can be merged, waiting ${retryInterval} seconds before trying again...`)
await new Promise(resolve => setTimeout(resolve, retryInterval * 1000))
continue
}
let mergedSha, targetSha
if (prInfo.mergeable) {
console.log("The PR can be merged.")
mergedSha = prInfo.merge_commit_sha
targetSha = (await github.rest.repos.getCommit({
owner: context.repo.owner,
repo: context.repo.repo,
ref: prInfo.merge_commit_sha
})).data.parents[0].sha
} else {
console.log("The PR has a merge conflict.")
mergedSha = prInfo.head.sha
targetSha = (await github.rest.repos.compareCommitsWithBasehead({
owner: context.repo.owner,
repo: context.repo.repo,
basehead: `${prInfo.base.sha}...${prInfo.head.sha}`
})).data.merge_base_commit.sha
}
console.log(`Checking the commits:\nmerged:${mergedSha}\ntarget:${targetSha}`)
core.setOutput('mergedSha', mergedSha)
core.setOutput('targetSha', targetSha)
return
}
throw new Error("Not retrying anymore. It's likely that GitHub is having internal issues: check https://www.githubstatus.com.")
- if: inputs.merged-as-untrusted && (inputs.mergedSha || steps.commits.outputs.mergedSha)
# Would be great to do the checkouts in git worktrees of the existing spare checkout instead,
# but Nix is broken with them:
# https://github.com/NixOS/nix/issues/6073
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.mergedSha || steps.commits.outputs.mergedSha }}
path: untrusted
- if: inputs.target-as-trusted && (inputs.targetSha || steps.commits.outputs.targetSha)
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.targetSha || steps.commits.outputs.targetSha }}
path: trusted

View File

@@ -1,23 +0,0 @@
# This file is used by .github/workflows/labels.yml
# This version is only run for Pull Requests from development branches like staging-next, haskell-updates or python-updates.
"4.workflow: package set update":
- any:
- head-branch:
- '-updates$'
"4.workflow: staging":
- any:
- head-branch:
- '^staging-next$'
- '^staging-next-'
"6.topic: haskell":
- any:
- head-branch:
- '^haskell-updates$'
"6.topic: python":
- any:
- head-branch:
- '^python-updates$'

View File

@@ -1,21 +0,0 @@
# This file is used by .github/workflows/labels.yml
# This version uses `sync-labels: false`, meaning that a non-match will NOT remove the label
"6.topic: policy discussion":
- any:
- changed-files:
- any-glob-to-any-file:
- .github/**/*
- CONTRIBUTING.md
- pkgs/README.md
- nixos/README.md
- maintainers/README.md
- lib/README.md
- doc/README.md
"8.has: documentation":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/**/*
- nixos/doc/**/*

623
.github/labeler.yml vendored
View File

@@ -1,559 +1,216 @@
# This file is used by .github/workflows/labels.yml
# This version uses `sync-labels: true`, meaning that a non-match will remove the label
"4.workflow: backport":
- any:
- base-branch:
- '^release-'
- '^staging-\d'
- '^staging-next-\d'
# NOTE: bsd, darwin and cross-compilation labels are handled by ofborg
"6.topic: agda":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/agda.section.md
- nixos/tests/agda.nix
- pkgs/build-support/agda/**/*
- pkgs/development/libraries/agda/**/*
- pkgs/top-level/agda-packages.nix
- doc/languages-frameworks/agda.section.md
- nixos/tests/agda.nix
- pkgs/build-support/agda/**/*
- pkgs/development/libraries/agda/**/*
- pkgs/top-level/agda-packages.nix
"6.topic: cinnamon":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/x11/desktop-managers/cinnamon.nix
- nixos/tests/cinnamon.nix
- nixos/tests/cinnamon-wayland.nix
- pkgs/by-name/ci/cinnamon-*/**/*
- pkgs/by-name/cj/cjs/**/*
- pkgs/by-name/mu/muffin/**/*
- pkgs/by-name/ne/nemo/**/*
- pkgs/by-name/ne/nemo-*/**/*
"6.topic: continuous integration":
- any:
- changed-files:
- any-glob-to-any-file:
- .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: crystal":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/development/compilers/crystal/**/*
"6.topic: cuda":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/development/cuda-modules/**/*
- pkgs/top-level/cuda-packages.nix
"6.topic: deepin":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/desktops/deepin/**/*
- pkgs/desktops/deepin/**/*
"6.topic: docker tools":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/applications/virtualization/docker/**/*
"6.topic: dotnet":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/dotnet.section.md
- maintainers/scripts/update-dotnet-lockfiles.nix
- pkgs/build-support/dotnet/**/*
- pkgs/development/compilers/dotnet/**/*
- pkgs/test/dotnet/**/*
- pkgs/top-level/dotnet-packages.nix
- pkgs/desktops/cinnamon/**/*
- nixos/modules/services/x11/desktop-managers/cinnamon.nix
- nixos/tests/cinnamon.nix
"6.topic: emacs":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/editors/emacs.nix
- nixos/modules/services/editors/emacs.xml
- nixos/tests/emacs-daemon.nix
- pkgs/applications/editors/emacs/build-support/**/*
- pkgs/applications/editors/emacs/elisp-packages/**/*
- pkgs/applications/editors/emacs/**/*
- pkgs/top-level/emacs-packages.nix
- nixos/modules/services/editors/emacs.nix
- nixos/modules/services/editors/emacs.xml
- nixos/tests/emacs-daemon.nix
- pkgs/applications/editors/emacs/elisp-packages/**/*
- pkgs/applications/editors/emacs/**/*
- pkgs/build-support/emacs/**/*
- pkgs/top-level/emacs-packages.nix
"6.topic: Enlightenment DE":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/x11/desktop-managers/enlightenment.nix
- pkgs/desktops/enlightenment/**/*
- pkgs/development/python-modules/python-efl/*
- nixos/modules/services/x11/desktop-managers/enlightenment.nix
- pkgs/desktops/enlightenment/**/*
- pkgs/development/python-modules/python-efl/*
"6.topic: erlang":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/beam.section.md
- pkgs/development/beam-modules/**/*
- pkgs/development/interpreters/elixir/**/*
- pkgs/development/interpreters/erlang/**/*
- pkgs/development/tools/build-managers/rebar/**/*
- pkgs/development/tools/build-managers/rebar3/**/*
- pkgs/development/tools/erlang/**/*
- pkgs/top-level/beam-packages.nix
- doc/languages-frameworks/beam.section.md
- pkgs/development/beam-modules/**/*
- pkgs/development/interpreters/elixir/**/*
- pkgs/development/interpreters/erlang/**/*
- pkgs/development/tools/build-managers/rebar/**/*
- pkgs/development/tools/build-managers/rebar3/**/*
- pkgs/development/tools/erlang/**/*
- pkgs/top-level/beam-packages.nix
"6.topic: fetch":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/build-support/fetch*/**/*
- pkgs/build-support/fetch*/**/*
"6.topic: flakes":
- any:
- changed-files:
- any-glob-to-any-file:
- '**/flake.nix'
- lib/systems/flake-systems.nix
- nixos/modules/config/nix-flakes.nix
"6.topic: flutter":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/build-support/flutter/*.nix
- pkgs/development/compilers/flutter/**/*.nix
"6.topic: games":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/games/**/*
- '**/flake.nix'
- lib/systems/flake-systems.nix
- nixos/modules/config/nix-flakes.nix
"6.topic: GNOME":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/gnome.section.md
- nixos/modules/services/desktops/gnome/**/*
- nixos/modules/services/x11/desktop-managers/gnome.nix
- nixos/tests/gnome-xorg.nix
- nixos/tests/gnome.nix
- pkgs/desktops/gnome/**/*
- doc/languages-frameworks/gnome.section.md
- nixos/modules/services/desktops/gnome/**/*
- nixos/modules/services/x11/desktop-managers/gnome.nix
- nixos/tests/gnome-xorg.nix
- nixos/tests/gnome.nix
- pkgs/desktops/gnome/**/*
"6.topic: golang":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/go.section.md
- pkgs/build-support/go/**/*
- pkgs/development/compilers/go/**/*
"6.topic: hardware":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/hardware/**/*
- doc/languages-frameworks/go.section.md
- pkgs/build-support/go/**/*
- pkgs/development/compilers/go/**/*
"6.topic: haskell":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/haskell.section.md
- maintainers/scripts/haskell/**/*
- pkgs/development/compilers/ghc/**/*
- pkgs/development/haskell-modules/**/*
- pkgs/development/tools/haskell/**/*
- pkgs/test/haskell/**/*
- pkgs/top-level/haskell-packages.nix
- pkgs/top-level/release-haskell.nix
"6.topic: java":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/programs/java.nix
- pkgs/development/compilers/graalvm/**/*
- pkgs/development/compilers/openjdk/**/*
- pkgs/development/compilers/temurin-bin/**/*
- pkgs/development/compilers/zulu/**/*
- pkgs/development/java-modules/**/*
- pkgs/top-level/java-packages.nix
"6.topic: jitsi":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/networking/jitsi-videobridge.nix
- nixos/modules/services/web-apps/jitsi-meet.nix
- pkgs/servers/web-apps/jitsi-meet/**/*
- pkgs/servers/jitsi-videobridge/**/*
- pkgs/applications/networking/instant-messengers/jitsi/**/*
"6.topic: julia":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/julia.section.md
- pkgs/development/compilers/julia/**/*
- pkgs/development/julia-modules/**/*
- doc/languages-frameworks/haskell.section.md
- maintainers/scripts/haskell/**/*
- pkgs/development/compilers/ghc/**/*
- pkgs/development/haskell-modules/**/*
- pkgs/development/tools/haskell/**/*
- pkgs/test/haskell/**/*
- pkgs/top-level/haskell-packages.nix
- pkgs/top-level/release-haskell.nix
"6.topic: jupyter":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/development/python-modules/jupyter*/**/*
- pkgs/development/python-modules/mkdocs-jupyter/*
- nixos/modules/services/development/jupyter/**/*
- pkgs/applications/editors/jupyter-kernels/**/*
- pkgs/applications/editors/jupyter/**/*
"6.topic: k3s":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/cluster/k3s/**/*
- nixos/tests/k3s/**/*
- pkgs/applications/networking/cluster/k3s/**/*
- pkgs/development/python-modules/jupyter*/**/*
- pkgs/development/python-modules/mkdocs-jupyter/*
- nixos/modules/services/development/jupyter/**/*
- pkgs/applications/editors/jupyter-kernels/**/*
- pkgs/applications/editors/jupyter/**/*
"6.topic: kernel":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/build-support/kernel/**/*
- pkgs/os-specific/linux/kernel/**/*
- pkgs/build-support/kernel/**/*
- pkgs/os-specific/linux/kernel/**/*
"6.topic: lib":
- any:
- changed-files:
- any-glob-to-any-file:
- lib/**
"6.topic: llvm/clang":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/development/compilers/llvm/**/*
- lib/**
"6.topic: lua":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/development/tools/misc/luarocks/*
- pkgs/development/interpreters/lua-5/**/*
- pkgs/development/interpreters/luajit/**/*
- pkgs/development/lua-modules/**/*
- pkgs/top-level/lua-packages.nix
- pkgs/development/interpreters/lua-5/**/*
- pkgs/development/interpreters/luajit/**/*
- pkgs/development/lua-modules/**/*
- pkgs/top-level/lua-packages.nix
"6.topic: Lumina DE":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/x11/desktop-managers/lumina.nix
- pkgs/desktops/lumina/**/*
- nixos/modules/services/x11/desktop-managers/lumina.nix
- pkgs/desktops/lumina/**/*
"6.topic: LXQt":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/x11/desktop-managers/lxqt.nix
- pkgs/desktops/lxqt/**/*
- nixos/modules/services/x11/desktop-managers/lxqt.nix
- pkgs/desktops/lxqt/**/*
"6.topic: mate":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/x11/desktop-managers/mate.nix
- nixos/tests/mate.nix
- pkgs/desktops/mate/**/*
- nixos/modules/services/x11/desktop-managers/mate.nix
- nixos/tests/mate.nix
- pkgs/desktops/mate/**/*
"6.topic: module system":
- any:
- changed-files:
- any-glob-to-any-file:
- lib/modules.nix
- lib/types.nix
- lib/options.nix
- lib/tests/modules.sh
- lib/tests/modules/**
"6.topic: musl":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/os-specific/linux/musl/**/*
- lib/modules.nix
- lib/types.nix
- lib/options.nix
- lib/tests/modules.sh
- lib/tests/modules/**
"6.topic: nixos":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/**/*
- pkgs/by-name/sw/switch-to-configuration-ng/**/*
- pkgs/os-specific/linux/nixos-rebuild/**/*
"6.topic: nixos-container":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/virtualisation/nixos-containers.nix
- pkgs/tools/virtualization/nixos-container/**/*
- nixos/**/*
- pkgs/os-specific/linux/nixos-rebuild/**/*
"6.topic: nim":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/nim.section.md
- pkgs/build-support/build-nim-package.nix
- pkgs/by-name/ni/nim*
- pkgs/top-level/nim-overrides.nix
- doc/languages-frameworks/nim.section.md
- pkgs/development/compilers/nim/*
- pkgs/development/nim-packages/**/*
- pkgs/top-level/nim-packages.nix
"6.topic: nodejs":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/javascript.section.md
- pkgs/build-support/node/**/*
- pkgs/development/node-packages/**/*
- pkgs/development/tools/yarn/*
- pkgs/development/tools/yarn2nix-moretea/**/*
- pkgs/development/tools/pnpm/**/*
- pkgs/development/web/nodejs/*
"6.topic: nvidia":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/hardware/video/nvidia.nix
- nixos/modules/services/hardware/nvidia-container-toolkit/**/*
- nixos/modules/services/hardware/nvidia-optimus.nix
- pkgs/os-specific/linux/nvidia-x11/**/*
- doc/languages-frameworks/javascript.section.md
- pkgs/build-support/node/**/*
- pkgs/development/node-packages/**/*
- pkgs/development/tools/yarn/*
- pkgs/development/tools/yarn2nix-moretea/**/*
- pkgs/development/web/nodejs/*
"6.topic: ocaml":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/ocaml.section.md
- pkgs/development/compilers/ocaml/**/*
- pkgs/development/compilers/reason/**/*
- pkgs/development/ocaml-modules/**/*
- pkgs/development/tools/ocaml/**/*
- pkgs/top-level/ocaml-packages.nix
- doc/languages-frameworks/ocaml.section.md
- pkgs/development/compilers/ocaml/**/*
- pkgs/development/compilers/reason/**/*
- pkgs/development/ocaml-modules/**/*
- pkgs/development/tools/ocaml/**/*
- pkgs/top-level/ocaml-packages.nix
"6.topic: pantheon":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/desktops/pantheon/**/*
- nixos/modules/services/x11/desktop-managers/pantheon.nix
- nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix
- nixos/tests/pantheon.nix
- pkgs/desktops/pantheon/**/*
- nixos/modules/services/desktops/pantheon/**/*
- nixos/modules/services/x11/desktop-managers/pantheon.nix
- nixos/modules/services/x11/display-managers/lightdm-greeters/pantheon.nix
- nixos/tests/pantheon.nix
- pkgs/desktops/pantheon/**/*
"6.topic: php":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/php.section.md
- nixos/tests/php/**/*
- pkgs/build-support/php/**/*
- pkgs/development/interpreters/php/**/*
- pkgs/development/php-packages/**/*
- pkgs/test/php/default.nix
- pkgs/top-level/php-packages.nix
"6.topic: policy discussion":
- .github/**/*
"6.topic: printing":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/services/printing/cupsd.nix
- pkgs/misc/cups/**/*
- nixos/modules/services/printing/cupsd.nix
- pkgs/misc/cups/**/*
"6.topic: python":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/python.section.md
- pkgs/development/interpreters/python/**/*
- pkgs/development/python-modules/**/*
- pkgs/top-level/python-packages.nix
- doc/languages-frameworks/python.section.md
- pkgs/development/interpreters/python/**/*
- pkgs/development/python-modules/**/*
- pkgs/top-level/python-packages.nix
"6.topic: qt/kde":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/qt.section.md
- nixos/modules/services/x11/desktop-managers/plasma5.nix
- nixos/tests/plasma5.nix
- pkgs/applications/kde/**/*
- pkgs/desktops/plasma-5/**/*
- pkgs/development/libraries/kde-frameworks/**/*
- pkgs/development/libraries/qt-5/**/*
"6.topic: R":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/applications/science/math/R/**/*
- pkgs/development/r-modules/**/*
"6.topic: rocm":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/development/rocm-modules/**/*
- doc/languages-frameworks/qt.section.md
- nixos/modules/services/x11/desktop-managers/plasma5.nix
- nixos/tests/plasma5.nix
- pkgs/applications/kde/**/*
- pkgs/desktops/plasma-5/**/*
- pkgs/development/libraries/kde-frameworks/**/*
- pkgs/development/libraries/qt-5/**/*
"6.topic: ruby":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/ruby.section.md
- pkgs/development/interpreters/ruby/**/*
- pkgs/development/ruby-modules/**/*
- doc/languages-frameworks/ruby.section.md
- pkgs/development/interpreters/ruby/**/*
- pkgs/development/ruby-modules/**/*
"6.topic: rust":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/rust.section.md
- pkgs/build-support/rust/**/*
- pkgs/development/compilers/rust/**/*
- doc/languages-frameworks/rust.section.md
- pkgs/build-support/rust/**/*
- pkgs/development/compilers/rust/**/*
"6.topic: stdenv":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/stdenv/**/*
- pkgs/stdenv/**/*
"6.topic: steam":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/games/steam/**/*
- pkgs/games/steam/**/*
"6.topic: systemd":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/os-specific/linux/systemd/**/*
- nixos/modules/system/boot/systemd*/**/*
"6.topic: tcl":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/tcl.section.md
- pkgs/development/interpreters/tcl/*
- pkgs/development/tcl-modules/**/*
- pkgs/top-level/tcl-packages.nix
- pkgs/os-specific/linux/systemd/**/*
- nixos/modules/system/boot/systemd*/**/*
"6.topic: TeX":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/texlive.section.md
- pkgs/test/texlive/**
- pkgs/tools/typesetting/tex/**/*
"6.topic: testing":
- any:
- changed-files:
- any-glob-to-any-file:
# NOTE: Let's keep the scope limited to test frameworks that are
# *developed in this repo*;
# - not individual tests
# - not packages for test frameworks
- pkgs/build-support/testers/**
- nixos/lib/testing/**
- nixos/lib/test-driver/**
- nixos/tests/nixos-test-driver/**
- nixos/lib/testing-python.nix # legacy
- nixos/tests/make-test-python.nix # legacy
# lib/debug.nix has a test framework (runTests) but it's not the main focus
"6.topic: updaters":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/common-updater/**/*
- doc/languages-frameworks/texlive.section.md
- pkgs/test/texlive/**
- pkgs/tools/typesetting/tex/**/*
"6.topic: vim":
- any:
- changed-files:
- any-glob-to-any-file:
- doc/languages-frameworks/vim.section.md
- pkgs/applications/editors/vim/**/*
- pkgs/applications/editors/vim/plugins/**/*
- nixos/modules/programs/neovim.nix
- pkgs/applications/editors/neovim/**/*
- doc/languages-frameworks/vim.section.md
- pkgs/applications/editors/vim/**/*
- pkgs/applications/editors/vim/plugins/**/*
- nixos/modules/programs/neovim.nix
- pkgs/applications/editors/neovim/**/*
"6.topic: vscode":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/applications/editors/vscode/**/*
"6.topic: windows":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/os-specific/windows/**/*
"6.topic: xen-project":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/virtualisation/xen*
- pkgs/by-name/xe/xen/*
- pkgs/by-name/qe/qemu_xen/*
- pkgs/by-name/xe/xen-guest-agent/*
- pkgs/by-name/xt/xtf/*
- pkgs/build-support/xen/*
- pkgs/development/ocaml-modules/xen*/*
- pkgs/development/ocaml-modules/vchan/*
- pkgs/applications/editors/vscode/**/*
"6.topic: xfce":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/doc/manual/configuration/xfce.xml
- nixos/modules/services/x11/desktop-managers/xfce.nix
- nixos/tests/xfce.nix
- pkgs/desktops/xfce/**/*
- nixos/doc/manual/configuration/xfce.xml
- nixos/modules/services/x11/desktop-managers/xfce.nix
- nixos/tests/xfce.nix
- pkgs/desktops/xfce/**/*
"6.topic: zig":
- any:
- changed-files:
- any-glob-to-any-file:
- pkgs/development/compilers/zig/**/*
- doc/hooks/zig.section.md
- pkgs/development/compilers/zig/**/*
- doc/hooks/zig.section.md
"8.has: changelog":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/doc/manual/release-notes/**/*
- nixos/doc/manual/release-notes/**/*
"8.has: documentation":
- doc/**/*
- nixos/doc/**/*
"8.has: module (update)":
- any:
- changed-files:
- any-glob-to-any-file:
- nixos/modules/**/*
"8.has: maintainer-list (update)":
- any:
- changed-files:
- any-glob-to-any-file:
- maintainers/maintainer-list.nix
- nixos/modules/**/*

View File

@@ -1,63 +0,0 @@
# GitHub Actions Workflows
Some architectural notes about key decisions and concepts in our workflows:
- Instead of `pull_request` we use [`pull_request_target`](https://docs.github.com/actions/writing-workflows/choosing-when-your-workflow-runs/events-that-trigger-workflows#pull_request_target) for all PR-related workflows.
This has the advantage that those workflows will run without prior approval for external contributors.
- Running on `pull_request_target` also optionally provides us with a GH_TOKEN with elevated privileges (write access), which we need to do things like adding labels, requesting reviewers or pushing branches.
**Note about security:** We need to be careful to limit the scope of elevated privileges as much as possible.
Thus they should be lowered to the minimum with `permissions: {}` in every workflow by default.
- By definition `pull_request_target` runs in the context of the **base** of the pull request.
This means, that the workflow files to run will be taken from the base branch, not the PR, and actions/checkout will not checkout the PR, but the base branch, by default.
To protect our secrets, we need to make sure to **never execute code** from the pull request and always evaluate or build nix code from the pull request with the **sandbox enabled**.
- To test the pull request's contents, we checkout the "test merge commit".
This is a temporary commit that GitHub creates automatically as "what would happen, if this PR was merged into the base branch now?".
The checkout could be done via the virtual branch `refs/pull/<pr-number>/merge`, but doing so would cause failures when this virtual branch doesn't exist (anymore).
This can happen when the PR has conflicts, in which case the virtual branch is not created, or when the PR is getting merged while workflows are still running, in which case the branch won't exist anymore at the time of checkout.
Thus, we use the `get-merge-commit.yml` workflow to check whether the PR is mergeable and the test merge commit exists and only then run the relevant jobs.
- Various workflows need to make comparisons against the base branch.
In this case, we checkout the parent of the "test merge commit" for best results.
Note, that this is not necessarily the same as the default commit that actions/checkout would use, which is also a commit from the base branch (see above), but might be older.
## Terminology
- **base commit**: The pull_request_target event's context commit, i.e. the base commit given by GitHub Actions.
Same as `github.event.pull_request.base.sha`.
- **head commit**: The HEAD commit in the pull request's branch.
Same as `github.event.pull_request.head.sha`.
- **merge commit**: The temporary "test merge commit" that GitHub Actions creates and updates for the pull request.
Same as `refs/pull/${{ github.event.pull_request.number }}/merge`.
- **target commit**: The base branch's parent of the "test merge commit" to compare against.
## Concurrency Groups
We use [GitHub's Concurrency Groups](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs) to cancel older jobs on pushes to Pull Requests.
When two workflows are in the same group, a newer workflow cancels an older workflow.
Thus, it is important how to construct the group keys:
- Because we want to run jobs for different events at same time, we add `github.event_name` to the key.
This is the case for the `pull_request` which runs on changes to the workflow files to test the new files and the same workflow from the base branch run via `pull_request_event`.
- We don't want workflows of different Pull Requests to cancel each other, so we include `github.event.pull_request.number`.
The [GitHub docs](https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/control-the-concurrency-of-workflows-and-jobs#example-using-a-fallback-value) show using `github.head_ref` for this purpose, but this doesn't work well with forks: Different users could have the same head branch name in their forks and run CI for their PRs at the same time.
- Sometimes, there is no `pull_request.number`.
To ensure non-PR runs are never cancelled, we add a fallback of `github.run_id`.
This is a unique value for each workflow run.
- Of course, we run multiple workflows at the same time, so we add `github.workflow` to the key.
Otherwise workflows would cancel each other.
- There is a special case for reusable workflows called via `workflow_call` - they will have `github.workflow` set to their parent workflow's name.
Thus, they would cancel each other.
That's why we additionally hardcode the name of the workflow as well.
This results in a key with the following semantics:
```
<running-workflow>-<triggering-workflow>-<triggered-event>-<pull-request/fallback>
```

View File

@@ -1,80 +1,35 @@
name: Backport
on:
pull_request_target:
types: [closed, labeled]
# WARNING:
# When extending this action, be aware that $GITHUB_TOKEN allows write access to
# the GitHub repository. This means that it should not evaluate user input in a
# way that allows code injection.
name: Backport
on:
pull_request_target:
types: [closed, labeled]
concurrency:
group: backport-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
permissions:
contents: read
issues: write
pull-requests: write
defaults:
run:
shell: bash
jobs:
backport:
permissions:
contents: write # for korthout/backport-action to create branch
pull-requests: write # for korthout/backport-action to create PR to backport
name: Backport Pull Request
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-24.04-arm
if: github.repository_owner == 'NixOS' && github.event.pull_request.merged == true && (github.event_name != 'labeled' || startsWith('backport', github.event.label.name))
runs-on: ubuntu-latest
steps:
# Use a GitHub App to create the PR so that CI gets triggered
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
id: app-token
with:
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
ref: ${{ github.event.pull_request.head.sha }}
token: ${{ steps.app-token.outputs.token }}
- name: Log current API rate limits
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq
- name: Create backport PRs
id: backport
uses: korthout/backport-action@0193454f0c5947491d348f33a275c119f30eb736 # v3.2.1
uses: korthout/backport-action@08bafb375e6e9a9a2b53a744b987e5d81a133191 # v2.1.1
with:
# Config README: https://github.com/korthout/backport-action#backport-action
copy_labels_pattern: 'severity:\ssecurity'
github_token: ${{ steps.app-token.outputs.token }}
pull_description: |-
Bot-based backport to `${target_branch}`, triggered by a label in #${pull_number}.
* [ ] Before merging, ensure that this backport is [acceptable for the release](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#changes-acceptable-for-releases).
* Even as a non-committer, if you find that it is not acceptable, leave a comment.
- name: Log current API rate limits
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq
- name: "Add 'has: port to stable' label"
if: steps.backport.outputs.created_pull_numbers != ''
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
# Not using the app on purpose to avoid triggering another workflow run after adding this label.
script: |
await github.rest.issues.addLabels({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.payload.pull_request.number,
labels: [ '8.has: port to stable' ]
})
* Even as a non-commiter, if you find that it is not acceptable, leave a comment.

29
.github/workflows/basic-eval.yml vendored Normal file
View File

@@ -0,0 +1,29 @@
name: Basic evaluation checks
on:
workflow_dispatch
# pull_request:
# branches:
# - master
# - release-**
# push:
# branches:
# - master
# - release-**
permissions:
contents: read
jobs:
tests:
runs-on: ubuntu-latest
# we don't limit this action to only NixOS repo since the checks are cheap and useful developer feedback
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
- uses: cachix/cachix-action@18cf96c7c98e048e10a83abd92116114cd8504be # v14
with:
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
name: nixpkgs-ci
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
# explicit list of supportedSystems is needed until aarch64-darwin becomes part of the trunk jobset
- run: nix-build pkgs/top-level/release.nix -A tarball.nixpkgs-basic-release-checks --arg supportedSystems '[ "aarch64-darwin" "aarch64-linux" "x86_64-linux" "x86_64-darwin" ]'

View File

@@ -1,92 +0,0 @@
name: Build
on:
workflow_call:
inputs:
baseBranch:
required: true
type: string
mergedSha:
required: true
type: string
secrets:
CACHIX_AUTH_TOKEN:
required: true
permissions: {}
defaults:
run:
shell: bash
jobs:
build:
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
system: x86_64-linux
builds: [shell, manual-nixos, lib-tests]
- runner: ubuntu-24.04-arm
system: aarch64-linux
builds: [shell, manual-nixos, manual-nixpkgs, manual-nixpkgs-tests]
- runner: macos-13
system: x86_64-darwin
builds: [shell]
- runner: macos-14
system: aarch64-darwin
builds: [shell]
name: ${{ matrix.system }}
runs-on: ${{ matrix.runner }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/actions
- name: Check if the PR can be merged and checkout the merge commit
uses: ./.github/actions/get-merge-commit
with:
mergedSha: ${{ inputs.mergedSha }}
merged-as-untrusted: true
- uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
name: nixpkgs-ci
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
- name: Build shell
if: contains(matrix.builds, 'shell')
run: nix-build untrusted/ci -A shell
- name: Build NixOS manual
if: |
contains(matrix.builds, 'manual-nixos') && !cancelled() &&
contains(fromJSON(inputs.baseBranch).type, 'primary')
run: nix-build untrusted/ci -A manual-nixos --argstr system ${{ matrix.system }} --out-link nixos-manual
- name: Build Nixpkgs manual
if: contains(matrix.builds, 'manual-nixpkgs') && !cancelled()
run: nix-build untrusted/ci -A manual-nixpkgs -A manual-nixpkgs-tests
- name: Build Nixpkgs manual tests
if: contains(matrix.builds, 'manual-nixpkgs-tests') && !cancelled()
run: nix-build untrusted/ci -A manual-nixpkgs-tests
- name: Build lib tests
if: contains(matrix.builds, 'lib-tests') && !cancelled()
run: nix-build untrusted/ci -A lib-tests
- name: Upload NixOS manual
if: |
contains(matrix.builds, 'manual-nixos') && !cancelled() &&
contains(fromJSON(inputs.baseBranch).type, 'primary')
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: nixos-manual-${{ matrix.system }}
path: nixos-manual
if-no-files-found: error

109
.github/workflows/check-by-name.yml vendored Normal file
View File

@@ -0,0 +1,109 @@
# Checks pkgs/by-name (see pkgs/by-name/README.md)
# using the nixpkgs-check-by-name tool (see pkgs/test/nixpkgs-check-by-name)
#
# When you make changes to this workflow, also update pkgs/test/nixpkgs-check-by-name/scripts/run-local.sh adequately
name: Check pkgs/by-name
# The tool is pinned to a pre-built version on Hydra,
# see pkgs/test/nixpkgs-check-by-name/scripts/README.md
on:
# Using pull_request_target instead of pull_request avoids having to approve first time contributors
pull_request_target
permissions:
# We need this permission to cancel the workflow run if there's a merge conflict
actions: write
jobs:
check:
# This is x86_64-linux, for which the tool is always prebuilt on the nixos-* channels,
# as specified in nixos/release-combined.nix
runs-on: ubuntu-latest
# This should take 1 minute at most, but let's be generous.
# The default of 6 hours is definitely too long
timeout-minutes: 10
steps:
# This step has to be in this file,
# because it's needed to determine which revision of the repository to fetch,
# and we can only use other files from the repository once it's fetched.
- name: Resolving the merge commit
env:
GH_TOKEN: ${{ github.token }}
run: |
# This checks for mergeability of a pull request as recommended in
# https://docs.github.com/en/rest/guides/using-the-rest-api-to-interact-with-your-git-database?apiVersion=2022-11-28#checking-mergeability-of-pull-requests
# Retry the API query this many times
retryCount=3
# Start with 5 seconds, but double every retry
retryInterval=5
while true; do
echo "Checking whether the pull request can be merged"
prInfo=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/"$GITHUB_REPOSITORY"/pulls/${{ github.event.pull_request.number }})
mergeable=$(jq -r .mergeable <<< "$prInfo")
mergedSha=$(jq -r .merge_commit_sha <<< "$prInfo")
if [[ "$mergeable" == "null" ]]; then
if (( retryCount == 0 )); then
echo "Not retrying anymore, probably GitHub is having internal issues"
exit 1
else
(( retryCount -= 1 )) || true
# null indicates that GitHub is still computing whether it's mergeable
# Wait a couple seconds before trying again
echo "GitHub is still computing whether this PR can be merged, waiting $retryInterval seconds before trying again ($retryCount retries left)"
sleep "$retryInterval"
(( retryInterval *= 2 )) || true
fi
else
break
fi
done
if [[ "$mergeable" == "true" ]]; then
echo "The PR can be merged, checking the merge commit $mergedSha"
else
echo "The PR cannot be merged, it has a merge conflict, cancelling the workflow.."
gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
/repos/"$GITHUB_REPOSITORY"/actions/runs/"$GITHUB_RUN_ID"/cancel
sleep 60
# If it's still not canceled after a minute, something probably went wrong, just exit
exit 1
fi
echo "mergedSha=$mergedSha" >> "$GITHUB_ENV"
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# pull_request_target checks out the base branch by default
ref: ${{ env.mergedSha }}
# Fetches the merge commit and its parents
fetch-depth: 2
- name: Checking out base branch
run: |
base=$(mktemp -d)
git worktree add "$base" "$(git rev-parse HEAD^1)"
echo "base=$base" >> "$GITHUB_ENV"
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
- name: Fetching the pinned tool
# Update the pinned version using pkgs/test/nixpkgs-check-by-name/scripts/update-pinned-tool.sh
run: |
# Get the direct /nix/store path from the pin to avoid having to evaluate Nixpkgs
toolPath=$(jq -r '."ci-path"' pkgs/test/nixpkgs-check-by-name/scripts/pinned-tool.json)
# This asks the substituter for the path, which should be there because Hydra will have pre-built and pushed it
nix-store --realise "$toolPath" --add-root result
- name: Running nixpkgs-check-by-name
run: |
if result/bin/nixpkgs-check-by-name --base "$base" .; then
exit 0
else
exitCode=$?
echo "To run locally: ./maintainers/scripts/check-by-name.sh $GITHUB_BASE_REF https://github.com/$GITHUB_REPOSITORY.git"
exit "$exitCode"
fi

View File

@@ -0,0 +1,24 @@
name: "Check that maintainer list is sorted"
on:
pull_request_target:
paths:
- 'maintainers/maintainer-list.nix'
permissions:
contents: read
jobs:
nixos:
runs-on: ubuntu-latest
if: github.repository_owner == 'NixOS'
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true
- name: Check that maintainer-list.nix is sorted
run: nix-instantiate --eval maintainers/scripts/check-maintainers-sorted.nix

View File

@@ -1,164 +0,0 @@
name: Check
on:
workflow_call:
inputs:
baseBranch:
required: true
type: string
headBranch:
required: true
type: string
permissions: {}
defaults:
run:
shell: bash
jobs:
no-channel-base:
name: no channel base
if: contains(fromJSON(inputs.baseBranch).type, 'channel')
runs-on: ubuntu-24.04-arm
steps:
- run: |
cat <<EOF
The nixos-* and nixpkgs-* branches are pushed to by the channel
release script and should not be merged into directly.
Please target the equivalent release-* branch or master instead.
EOF
exit 1
cherry-pick:
if: |
github.event_name == 'pull_request' ||
(fromJSON(inputs.baseBranch).stable && !contains(fromJSON(inputs.headBranch).type, 'development'))
permissions:
pull-requests: write
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
fetch-depth: 0
filter: tree:0
path: trusted
- name: Check cherry-picks
id: check
continue-on-error: true
env:
BASE_SHA: ${{ github.event.pull_request.base.sha }}
HEAD_SHA: ${{ github.event.pull_request.head.sha }}
run: |
./trusted/ci/check-cherry-picks.sh "$BASE_SHA" "$HEAD_SHA" checked-cherry-picks.md
- name: Log current API rate limits
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq
- name: Prepare review
if: steps.check.outcome == 'failure'
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { readFile, writeFile } = require('node:fs/promises')
const job_url = (await github.rest.actions.listJobsForWorkflowRun({
owner: context.repo.owner,
repo: context.repo.repo,
run_id: context.runId
})).data.jobs[0].html_url + '?pr=' + context.payload.pull_request.number
const header = await readFile('trusted/ci/check-cherry-picks.md')
const body = await readFile('checked-cherry-picks.md')
const footer =
`\n_Hint: The full diffs are also available in the [runner logs](${job_url}) with slightly better highlighting._`
const review = header + body + footer
await writeFile('review.md', review)
core.summary.addRaw(review)
core.summary.write()
- name: Request changes
if: ${{ github.event_name == 'pull_request_target' && steps.check.outcome == 'failure' }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { readFile } = require('node:fs/promises')
const body = await readFile('review.md', 'utf-8')
const pendingReview = (await github.paginate(github.rest.pulls.listReviews, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
})).find(review =>
review.user.login == 'github-actions[bot]' && (
// If a review is still pending, we can just update this instead
// of posting a new one.
review.state == 'CHANGES_REQUESTED' ||
// No need to post a new review, if an older one with the exact
// same content had already been dismissed.
review.body == body
)
)
// Either of those two requests could fail for very long comments. This can only happen
// with multiple commits all hitting the truncation limit for the diff. If you ever hit
// this case, consider just splitting up those commits into multiple PRs.
if (pendingReview) {
await github.rest.pulls.updateReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
review_id: pendingReview.id,
body
})
} else {
await github.rest.pulls.createReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
event: 'REQUEST_CHANGES',
body
})
}
- name: Dismiss old reviews
if: ${{ github.event_name == 'pull_request_target' && steps.check.outcome == 'success' }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
await Promise.all(
(await github.paginate(github.rest.pulls.listReviews, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number
})).filter(review =>
review.user.login == 'github-actions[bot]'
).map(async (review) => {
if (review.state == 'CHANGES_REQUESTED') {
await github.rest.pulls.dismissReview({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
review_id: review.id,
message: 'All cherry-picks are good now, thank you!'
})
}
await github.graphql(`mutation($node_id:ID!) {
minimizeComment(input: {
classifier: RESOLVED,
subjectId: $node_id
})
{ clientMutationId }
}`, { node_id: review.node_id })
})
)
- name: Log current API rate limits
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq

View File

@@ -1,147 +0,0 @@
# This workflow depends on two GitHub Apps with the following permissions:
# - For checking code owners:
# - Permissions:
# - Repository > Administration: read-only
# - Organization > Members: read-only
# - Install App on this repository, setting these variables:
# - OWNER_RO_APP_ID (variable)
# - OWNER_RO_APP_PRIVATE_KEY (secret)
# - For requesting code owners:
# - Permissions:
# - Repository > Administration: read-only
# - Organization > Members: read-only
# - Repository > Pull Requests: read-write
# - Install App on this repository, setting these variables:
# - OWNER_APP_ID (variable)
# - OWNER_APP_PRIVATE_KEY (secret)
#
# This split is done because checking code owners requires handling untrusted PR input,
# while requesting code owners requires PR write access, and those shouldn't be mixed.
#
# Note that the latter is also used for ./eval.yml requesting reviewers.
name: Codeowners v2
on:
pull_request:
paths:
- .github/workflows/codeowners-v2.yml
pull_request_target:
types: [opened, ready_for_review, synchronize, reopened]
concurrency:
group: codeowners-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
permissions: {}
defaults:
run:
shell: bash
env:
OWNERS_FILE: ci/OWNERS
# Don't do anything on draft PRs
DRY_MODE: ${{ github.event.pull_request.draft && '1' || '' }}
jobs:
# Check that code owners is valid
check:
name: Check
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/actions
- name: Check if the PR can be merged and checkout the merge and target commits
uses: ./.github/actions/get-merge-commit
with:
merged-as-untrusted: true
target-as-trusted: true
- uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
with:
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
name: nixpkgs-ci
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
- name: Build codeowners validator
run: nix-build trusted/ci -A codeownersValidator
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
if: github.event_name == 'pull_request_target' && vars.OWNER_RO_APP_ID
id: app-token
with:
app-id: ${{ vars.OWNER_RO_APP_ID }}
private-key: ${{ secrets.OWNER_RO_APP_PRIVATE_KEY }}
permission-administration: read
permission-members: read
- name: Log current API rate limits
if: steps.app-token.outputs.token
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq
- name: Validate codeowners
if: steps.app-token.outputs.token
env:
OWNERS_FILE: untrusted/${{ env.OWNERS_FILE }}
GITHUB_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }}
REPOSITORY_PATH: untrusted
OWNER_CHECKER_REPOSITORY: ${{ github.repository }}
# Set this to "notowned,avoid-shadowing" to check that all files are owned by somebody
EXPERIMENTAL_CHECKS: "avoid-shadowing"
run: result/bin/codeowners-validator
- name: Log current API rate limits
if: steps.app-token.outputs.token
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq
# Request reviews from code owners
request:
name: Request
runs-on: ubuntu-24.04-arm
steps:
- uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
# Important: Because we use pull_request_target, this checks out the base branch of the PR, not the PR head.
# This is intentional, because we need to request the review of owners as declared in the base branch.
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: trusted
- name: Build review request package
run: nix-build trusted/ci -A requestReviews
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
if: github.event_name == 'pull_request_target' && vars.OWNER_APP_ID
id: app-token
with:
app-id: ${{ vars.OWNER_APP_ID }}
private-key: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
permission-administration: read
permission-members: read
permission-pull-requests: write
- name: Log current API rate limits
if: steps.app-token.outputs.token
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq
- name: Request reviews
if: steps.app-token.outputs.token
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: result/bin/request-code-owner-reviews.sh ${{ github.repository }} ${{ github.event.number }} "$OWNERS_FILE"
- name: Log current API rate limits
if: steps.app-token.outputs.token
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq

View File

@@ -1,65 +0,0 @@
name: Dismissed review
on:
workflow_run:
workflows:
- Review dismissed
types: [completed]
concurrency:
group: dismissed-review-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
permissions:
pull-requests: write
defaults:
run:
shell: bash
jobs:
# The `check-cherry-picks` workflow creates review comments which reviewers
# are encouraged to manually dismiss if they're not relevant.
# When a CI-generated review is dismissed, this job automatically minimizes
# it, preventing it from cluttering the PR.
minimize:
name: Minimize as resolved
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
// 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.
// Multiple pull requests can be open from the same head commit, either via
// different base branches or head branches.
const { head_repository, head_sha, repository } = context.payload.workflow_run
await Promise.all(
(await github.paginate(github.rest.repos.listPullRequestsAssociatedWithCommit, {
owner: head_repository.owner.login,
repo: head_repository.name,
commit_sha: head_sha
}))
.filter(pull_request => pull_request.base.repo.id == repository.id)
.map(async (pull_request) =>
Promise.all(
(await github.paginate(github.rest.pulls.listReviews, {
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: pull_request.number
})).filter(review =>
review.user.login == 'github-actions[bot]' &&
review.state == 'DISMISSED'
).map(review => github.graphql(`
mutation($node_id:ID!) {
minimizeComment(input: {
classifier: RESOLVED,
subjectId: $node_id
})
{ clientMutationId }
}`,
{ node_id: review.node_id }
))
)
)
)

View File

@@ -1,58 +0,0 @@
# Some workflows depend on the base branch of the PR, but changing the base branch is not included in the default trigger events, which would be `opened`, `synchronize` or `reopened`.
# Instead it causes an `edited` event.
# Since `edited` is also triggered when PR title/body is changed, we use this wrapper workflow, to run the other workflows conditionally only.
# There are already feature requests for adding a `base_changed` event:
# - https://github.com/orgs/community/discussions/35058
# - https://github.com/orgs/community/discussions/64119
#
# Instead of adding this to each workflow's pull_request_target event, we trigger this in a separate workflow.
# This has the advantage, that we can actually skip running those jobs for simple edits like changing the title or description.
# The actual trigger happens by closing and re-opening the pull request, which triggers the default pull_request_target events.
# This is much simpler and reliable than other approaches.
name: "Edited base branch"
on:
pull_request_target:
types: [edited]
concurrency:
group: edited-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
permissions: {}
defaults:
run:
shell: bash
jobs:
base:
name: Trigger jobs
runs-on: ubuntu-24.04
if: github.event.changes.base.ref.from && github.event.changes.base.ref.from != github.event.pull_request.base.ref
steps:
# Use a GitHub App to create the PR so that CI gets triggered
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
# We only need Pull Requests: write here, but the app is also used for backports.
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
id: app-token
with:
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
permission-pull-requests: write
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ steps.app-token.outputs.token }}
script: |
function changeState(state) {
return github.rest.pulls.update({
owner: context.repo.owner,
repo: context.repo.repo,
pull_number: context.payload.pull_request.number,
state
})
}
await changeState('closed')
await changeState('open')

41
.github/workflows/editorconfig.yml vendored Normal file
View File

@@ -0,0 +1,41 @@
name: "Checking EditorConfig"
permissions: read-all
on:
# avoids approving first time contributors
pull_request_target:
branches-ignore:
- 'release-**'
jobs:
tests:
runs-on: ubuntu-latest
if: "github.repository_owner == 'NixOS' && !contains(github.event.pull_request.title, '[skip treewide]')"
steps:
- name: Get list of changed files from PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api \
repos/NixOS/nixpkgs/pulls/${{github.event.number}}/files --paginate \
| jq '.[] | select(.status != "removed") | .filename' \
> "$HOME/changed_files"
- name: print list of changed files
run: |
cat "$HOME/changed_files"
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
with:
# nixpkgs commit is pinned so that it doesn't break
# editorconfig-checker 2.4.0
nix_path: nixpkgs=https://github.com/NixOS/nixpkgs/archive/c473cc8714710179df205b153f4e9fa007107ff9.tar.gz
- name: Checking EditorConfig
run: |
cat "$HOME/changed_files" | nix-shell -p editorconfig-checker --run 'xargs -r editorconfig-checker -disable-indent-size'
- if: ${{ failure() }}
run: |
echo "::error :: Hey! It looks like your changes don't follow our editorconfig settings. Read https://editorconfig.org/#download to configure your editor so you never see this error again."

View File

@@ -1,255 +0,0 @@
name: Eval
on:
workflow_call:
inputs:
mergedSha:
required: true
type: string
targetSha:
type: string
systems:
required: true
type: string
secrets:
OWNER_APP_PRIVATE_KEY:
required: false
permissions: {}
defaults:
run:
shell: bash
jobs:
eval:
runs-on: ubuntu-24.04-arm
strategy:
fail-fast: false
matrix:
system: ${{ fromJSON(inputs.systems) }}
name: ${{ matrix.system }}
outputs:
targetRunId: ${{ steps.targetRunId.outputs.targetRunId }}
steps:
- name: Enable swap
run: |
sudo fallocate -l 10G /swap
sudo chmod 600 /swap
sudo mkswap /swap
sudo swapon /swap
- name: Check out the PR at the test merge commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.mergedSha }}
path: untrusted
- name: Install Nix
uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- name: Evaluate the ${{ matrix.system }} output paths for all derivation attributes
env:
MATRIX_SYSTEM: ${{ matrix.system }}
run: |
nix-build untrusted/ci -A eval.singleSystem \
--argstr evalSystem "$MATRIX_SYSTEM" \
--arg chunkSize 10000 \
--out-link merged
# If it uses too much memory, slightly decrease chunkSize
- name: Upload the output paths and eval stats
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: merged-${{ matrix.system }}
path: merged/*
- name: Log current API rate limits
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq
- name: Get target run id
if: inputs.targetSha
id: targetRunId
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
env:
MATRIX_SYSTEM: ${{ matrix.system }}
TARGET_SHA: ${{ inputs.targetSha }}
with:
script: |
const system = process.env.MATRIX_SYSTEM
const targetSha = process.env.TARGET_SHA
let run_id
try {
run_id = (await github.rest.actions.listWorkflowRuns({
...context.repo,
workflow_id: 'push.yml',
event: 'push',
head_sha: targetSha
})).data.workflow_runs[0].id
} catch {
throw new Error(`Could not find a push.yml workflow run for ${targetSha}.`)
}
// Waiting 120 * 5 sec = 10 min. max.
// Eval takes max 5-6 minutes, normally.
for (let i = 0; i < 120; i++) {
const result = await github.rest.actions.listWorkflowRunArtifacts({
...context.repo,
run_id,
name: `merged-${system}`
})
if (result.data.total_count > 0) {
core.setOutput('targetRunId', run_id)
return
}
await new Promise(resolve => setTimeout(resolve, 5000))
}
// No artifact found at this stage. This usually means that Eval failed on the target branch.
// This should only happen when Eval is broken on the target branch and this PR fixes it.
// Continue without targetRunId to skip the remaining steps, but pass the job.
- name: Log current API rate limits
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq
- uses: actions/download-artifact@v4
if: steps.targetRunId.outputs.targetRunId
with:
run-id: ${{ steps.targetRunId.outputs.targetRunId }}
name: merged-${{ matrix.system }}
path: target
github-token: ${{ github.token }}
merge-multiple: true
- name: Compare outpaths against the target branch
if: steps.targetRunId.outputs.targetRunId
env:
MATRIX_SYSTEM: ${{ matrix.system }}
run: |
nix-build untrusted/ci -A eval.diff \
--arg beforeDir ./target \
--arg afterDir "$(readlink ./merged)" \
--argstr evalSystem "$MATRIX_SYSTEM" \
--out-link diff
- name: Upload outpaths diff and stats
if: steps.targetRunId.outputs.targetRunId
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: diff-${{ matrix.system }}
path: diff/*
compare:
runs-on: ubuntu-24.04-arm
needs: [eval]
if: needs.eval.outputs.targetRunId
permissions:
statuses: write
steps:
- name: Download output paths and eval stats for all systems
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
pattern: diff-*
path: diff
merge-multiple: true
- name: Check out the PR at the target commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ inputs.targetSha }}
path: trusted
- name: Install Nix
uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- name: Combine all output paths and eval stats
run: |
nix-build trusted/ci -A eval.combine \
--arg diffDir ./diff \
--out-link combined
- name: Compare against the target branch
env:
AUTHOR_ID: ${{ github.event.pull_request.user.id }}
run: |
git -C trusted fetch --depth 1 origin ${{ inputs.mergedSha }}
git -C trusted diff --name-only ${{ inputs.mergedSha }} \
| jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json
# Use the target branch to get accurate maintainer info
nix-build trusted/ci -A eval.compare \
--arg combinedDir "$(realpath ./combined)" \
--arg touchedFilesJson ./touched-files.json \
--argstr githubAuthorId "$AUTHOR_ID" \
--out-link comparison
cat comparison/step-summary.md >> "$GITHUB_STEP_SUMMARY"
- name: Upload the comparison results
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
with:
name: comparison
path: comparison/*
- name: Add eval summary to commit statuses
if: ${{ github.event_name == 'pull_request_target' }}
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { readFile } = require('node:fs/promises')
const changed = JSON.parse(await readFile('comparison/changed-paths.json', 'utf-8'))
const description =
'Package: ' + [
`added ${changed.attrdiff.added.length}`,
`removed ${changed.attrdiff.removed.length}`,
`changed ${changed.attrdiff.changed.length}`
].join(', ') +
' — Rebuild: ' + [
`linux ${changed.rebuildCountByKernel.linux}`,
`darwin ${changed.rebuildCountByKernel.darwin}`
].join(', ')
const { serverUrl, repo, runId, payload } = context
const target_url =
`${serverUrl}/${repo.owner}/${repo.repo}/actions/runs/${runId}?pr=${payload.pull_request.number}`
await github.rest.repos.createCommitStatus({
...repo,
sha: payload.pull_request.head.sha,
context: 'Eval Summary',
state: 'success',
description,
target_url
})
misc:
if: ${{ github.event_name != 'push' }}
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/actions
- name: Check if the PR can be merged and checkout the merge commit
uses: ./.github/actions/get-merge-commit
with:
merged-as-untrusted: true
- name: Install Nix
uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- name: Ensure flake outputs on all systems still evaluate
run: nix flake check --all-systems --no-build ./untrusted
- name: Query nixpkgs with aliases enabled to check for basic syntax errors
run: |
time nix-env -I ./untrusted -f ./untrusted -qa '*' --option restrict-eval true --option allow-import-from-derivation false >/dev/null

View File

@@ -1,451 +1,24 @@
name: "Label PR"
on:
pull_request_target:
types: [edited, opened, synchronize, reopened]
# WARNING:
# When extending this action, be aware that $GITHUB_TOKEN allows some write
# access to the GitHub API. This means that it should not evaluate user input in
# a way that allows code injection.
name: Labels
on:
schedule:
- cron: '07,17,27,37,47,57 * * * *'
workflow_call:
inputs:
headBranch:
required: true
type: string
secrets:
NIXPKGS_CI_APP_PRIVATE_KEY:
required: true
workflow_dispatch:
concurrency:
# This explicitly avoids using `run_id` for the concurrency key to make sure that only
# *one* scheduled run can run at a time.
group: labels-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number }}
# PR-triggered runs will be cancelled, but scheduled runs will be queued.
cancel-in-progress: ${{ github.event_name != 'schedule' }}
# This is used as fallback without app only.
# This happens when testing in forks without setting up that app.
# Labels will most likely not exist in forks, yet. For this case,
# we add the issues permission only here.
permissions:
issues: write # needed to create *new* labels
contents: read
pull-requests: write
defaults:
run:
shell: bash
jobs:
update:
runs-on: ubuntu-24.04-arm
if: github.event_name != 'schedule' || github.repository_owner == 'NixOS'
labels:
runs-on: ubuntu-latest
if: "github.repository_owner == 'NixOS' && !contains(github.event.pull_request.title, '[skip treewide]')"
steps:
- name: Install dependencies
run: npm install @actions/artifact bottleneck
# 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@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
if: vars.NIXPKGS_CI_APP_ID
id: app-token
with:
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
# No issues: write permission here, because labels in Nixpkgs should
# be created explicitly via the UI with color and description.
permission-pull-requests: write
- name: Log current API rate limits
env:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq
- name: Labels from API data and Eval results
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
github-token: ${{ steps.app-token.outputs.token || github.token }}
retries: 3
script: |
const Bottleneck = require('bottleneck')
const path = require('node:path')
const { DefaultArtifactClient } = require('@actions/artifact')
const { readFile } = require('node:fs/promises')
const artifactClient = new DefaultArtifactClient()
const stats = {
prs: 0,
requests: 0,
artifacts: 0
}
// Rate-Limiting and Throttling, see for details:
// https://github.com/octokit/octokit.js/issues/1069#throttling
// https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api
const allLimits = new Bottleneck({
// Avoid concurrent requests
maxConcurrent: 1,
// Will be updated with first `updateReservoir()` call below.
reservoir: 0
})
// Pause between mutative requests
const writeLimits = new Bottleneck({ minTime: 1000 }).chain(allLimits)
github.hook.wrap('request', async (request, options) => {
// Requests to the /rate_limit endpoint do not count against the rate limit.
if (options.url == '/rate_limit') return request(options)
// Search requests are in a different resource group, which allows 30 requests / minute.
// We do less than a handful each run, so not implementing throttling for now.
if (options.url.startsWith('/search/')) return request(options)
stats.requests++
if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(options.method))
return writeLimits.schedule(request.bind(null, options))
else
return allLimits.schedule(request.bind(null, options))
})
async function updateReservoir() {
let response
try {
response = await github.rest.rateLimit.get()
} catch (err) {
core.error(`Failed updating reservoir:\n${err}`)
// Keep retrying on failed rate limit requests instead of exiting the script early.
return
}
// Always keep 1000 spare requests for other jobs to do their regular duty.
// They normally use below 100, so 1000 is *plenty* of room to work with.
const reservoir = Math.max(0, response.data.resources.core.remaining - 1000)
core.info(`Updating reservoir to: ${reservoir}`)
allLimits.updateSettings({ reservoir })
}
await updateReservoir()
// Update remaining requests every minute to account for other jobs running in parallel.
const reservoirUpdater = setInterval(updateReservoir, 60 * 1000)
async function handle(item) {
try {
const log = (k,v,skip) => {
core.info(`#${item.number} - ${k}: ${v}` + (skip ? ' (skipped)' : ''))
return skip
}
log('Last updated at', item.updated_at)
stats.prs++
log('URL', item.html_url)
const pull_number = item.number
const issue_number = item.number
// This API request is important for the merge-conflict label, because it triggers the
// creation of a new test merge commit. This is needed to actually determine the state of a PR.
const pull_request = (await github.rest.pulls.get({
...context.repo,
pull_number
})).data
const run_id = (await github.rest.actions.listWorkflowRuns({
...context.repo,
workflow_id: 'pr.yml',
event: 'pull_request_target',
exclude_pull_requests: true,
head_sha: pull_request.head.sha
})).data.workflow_runs[0]?.id ??
// TODO: Remove this after 2025-09-17, at which point all eval.yml artifacts will have expired.
(await github.rest.actions.listWorkflowRuns({
...context.repo,
// In older PRs, we need eval.yml instead of pr.yml.
workflow_id: 'eval.yml',
event: 'pull_request_target',
status: 'success',
exclude_pull_requests: true,
head_sha: pull_request.head.sha
})).data.workflow_runs[0]?.id
// Newer PRs might not have run Eval to completion, yet.
// Older PRs might not have an eval.yml workflow, yet.
// In either case we continue without fetching an artifact on a best-effort basis.
log('Last eval run', run_id ?? '<n/a>')
const artifact = run_id && (await github.rest.actions.listWorkflowRunArtifacts({
...context.repo,
run_id,
name: 'comparison'
})).data.artifacts[0]
// Instead of checking the boolean artifact.expired, we will give us a minute to
// actually download the artifact in the next step and avoid that race condition.
// Older PRs, where the workflow run was already eval.yml, but the artifact was not
// called "comparison", yet, will skip the download.
const expired = !artifact || new Date(artifact?.expires_at ?? 0) < new Date(new Date().getTime() + 60 * 1000)
log('Artifact expires at', artifact?.expires_at ?? '<n/a>')
if (!expired) {
stats.artifacts++
await artifactClient.downloadArtifact(artifact.id, {
findBy: {
repositoryName: context.repo.repo,
repositoryOwner: context.repo.owner,
token: core.getInput('github-token')
},
path: path.resolve(pull_number.toString()),
expectedHash: artifact.digest
})
}
// Create a map (Label -> Boolean) of all currently set labels.
// Each label is set to True and can be disabled later.
const before = Object.fromEntries(
(await github.paginate(github.rest.issues.listLabelsOnIssue, {
...context.repo,
issue_number
}))
.map(({ name }) => [name, true])
)
const approvals = new Set(
(await github.paginate(github.rest.pulls.listReviews, {
...context.repo,
pull_number
}))
.filter(review => review.state == 'APPROVED')
.map(review => review.user?.id)
)
const latest_event_at = new Date(
(await github.paginate(
github.rest.issues.listEventsForTimeline,
{
...context.repo,
issue_number,
per_page: 100
}
))
.filter(({ event }) => [
// These events are hand-picked from:
// https://docs.github.com/en/rest/using-the-rest-api/issue-event-types?apiVersion=2022-11-28
// Each of those causes a PR/issue to *not* be considered as stale anymore.
// Most of these use created_at.
'assigned',
'commented', // uses updated_at, because that could be > created_at
'committed', // uses committer.date
'head_ref_force_pushed',
'milestoned',
'pinned',
'ready_for_review',
'renamed',
'reopened',
'review_dismissed',
'review_requested',
'reviewed', // uses submitted_at
'unlocked',
'unmarked_as_duplicate',
].includes(event))
.map(({ created_at, updated_at, committer, submitted_at }) => new Date(updated_at ?? created_at ?? submitted_at ?? committer.date))
// Reverse sort by date value. The default sort() sorts by string representation, which is bad for dates.
.sort((a,b) => b-a)
.at(0) ?? item.created_at
)
log('latest_event_at', latest_event_at.toISOString())
const stale_at = new Date(new Date().setDate(new Date().getDate() - 180))
// After creation of a Pull Request, `merge_commit_sha` will be null initially:
// The very first merge commit will only be calculated after a little while.
// To avoid labeling the PR as conflicted before that, we wait a few minutes.
// This is intentionally less than the time that Eval takes, so that the label job
// running after Eval can indeed label the PR as conflicted if that is the case.
const merge_commit_sha_valid = new Date() - new Date(pull_request.created_at) > 3 * 60 * 1000
// Manage most of the labels, without eval results
const after = Object.assign(
{},
before,
{
// We intentionally don't use the mergeable or mergeable_state attributes.
// Those have an intermediate state while the test merge commit is created.
// This doesn't work well for us, because we might have just triggered another
// test merge commit creation by request the pull request via API at the start
// of this function.
// The attribute merge_commit_sha keeps the old value of null or the hash *until*
// the new test merge commit has either successfully been created or failed so.
// This essentially means we are updating the merge conflict label in two steps:
// On the first pass of the day, we just fetch the pull request, which triggers
// the creation. At this stage, the label is likely not updated, yet.
// The second pass will then read the result from the first pass and set the label.
'2.status: merge conflict': merge_commit_sha_valid && !pull_request.merge_commit_sha,
'2.status: stale': !before['1.severity: security'] && latest_event_at < stale_at,
'12.approvals: 1': approvals.size == 1,
'12.approvals: 2': approvals.size == 2,
'12.approvals: 3+': approvals.size >= 3,
'12.first-time contribution':
[ 'NONE', 'FIRST_TIMER', 'FIRST_TIME_CONTRIBUTOR' ].includes(pull_request.author_association),
}
)
// Manage labels based on eval results
if (!expired) {
const maintainers = new Set(Object.keys(
JSON.parse(await readFile(`${pull_number}/maintainers.json`, 'utf-8'))
).map(m => Number.parseInt(m, 10)))
const evalLabels = JSON.parse(await readFile(`${pull_number}/changed-paths.json`, 'utf-8')).labels
Object.assign(
after,
// Ignore `evalLabels` if it's an array.
// This can happen for older eval runs, before we switched to objects.
// The old eval labels would have been set by the eval run,
// so now they'll be present in `before`.
// TODO: Simplify once old eval results have expired (~2025-10)
(Array.isArray(evalLabels) ? undefined : evalLabels),
{
'12.approved-by: package-maintainer': Array.from(maintainers).some(m => approvals.has(m)),
}
)
}
// No need for an API request, if all labels are the same.
const hasChanges = Object.keys(after).some(name => (before[name] ?? false) != after[name])
if (log('Has changes', hasChanges, !hasChanges))
return;
// Skipping labeling on a pull_request event, because we have no privileges.
const labels = Object.entries(after).filter(([,value]) => value).map(([name]) => name)
if (log('Set labels', labels, context.eventName == 'pull_request'))
return;
await github.rest.issues.setLabels({
...context.repo,
issue_number,
labels
})
} catch (cause) {
throw new Error(`Labeling #${item.number} failed.`, { cause })
}
}
try {
if (context.payload.pull_request) {
await handle(context.payload.pull_request)
} else {
const workflowData = (await github.rest.actions.listWorkflowRuns({
...context.repo,
workflow_id: 'labels.yml',
event: 'schedule',
status: 'success',
exclude_pull_requests: true,
per_page: 1
})).data
// Go back as far as the last successful run of this workflow to make sure
// we are not leaving anyone behind on GHA failures.
// Defaults to go back 1 hour on the first run.
const cutoff = new Date(workflowData.workflow_runs[0]?.created_at ?? new Date().getTime() - 1 * 60 * 60 * 1000)
core.info('cutoff timestamp: ' + cutoff.toISOString())
const updatedItems = await github.paginate(
github.rest.search.issuesAndPullRequests,
{
q: [
`repo:"${process.env.GITHUB_REPOSITORY}"`,
'type:pr',
'is:open',
`updated:>=${cutoff.toISOString()}`
].join(' AND '),
// TODO: Remove in 2025-10, when it becomes the default.
advanced_search: true
}
)
// The search endpoint only allows fetching the first 1000 records, but the
// pull request list endpoint does not support counting the total number
// of results.
// Thus, we use /search for counting and /pulls for reading the response.
const { total_count: total_pulls } = (await github.rest.search.issuesAndPullRequests({
q: [
`repo:"${process.env.GITHUB_REPOSITORY}"`,
'type:pr',
'is:open'
].join(' AND '),
sort: 'created',
direction: 'asc',
// TODO: Remove in 2025-10, when it becomes the default.
advanced_search: true,
per_page: 1
})).data
const { total_count: total_runs } = workflowData
const allPulls = (await github.rest.pulls.list({
...context.repo,
state: 'open',
sort: 'created',
direction: 'asc',
per_page: 100,
// We iterate through pages of 100 items across scheduled runs. With currently ~7000 open PRs and
// up to 6*24=144 scheduled runs per day, we hit every PR twice each day.
// We might not hit every PR on one iteration, because the pages will shift slightly when
// PRs are closed or merged. We assume this to be OK on the bigger scale, because a PR which was
// missed once, would have to move through the whole page to be missed again. This is very unlikely,
// so it should certainly be hit on the next iteration.
// TODO: Evaluate after a while, whether the above holds still true and potentially implement
// an overlap between runs.
page: (total_runs % Math.ceil(total_pulls / 100)) + 1
})).data
// Some items might be in both search results, so filtering out duplicates as well.
const items = [].concat(updatedItems, allPulls)
.filter((thisItem, idx, arr) => idx == arr.findIndex(firstItem => firstItem.number == thisItem.number))
;(await Promise.allSettled(items.map(handle)))
.filter(({ status }) => status == 'rejected')
.map(({ reason }) => core.setFailed(`${reason.message}\n${reason.cause.stack}`))
core.notice(`Processed ${stats.prs} PRs, made ${stats.requests + stats.artifacts} API requests and downloaded ${stats.artifacts} artifacts.`)
}
} finally {
clearInterval(reservoirUpdater)
}
- name: Log current API rate limits
env:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
name: Labels from touched files
if: |
github.event_name == 'pull_request_target' &&
!contains(fromJSON(inputs.headBranch).type, 'development')
with:
repo-token: ${{ steps.app-token.outputs.token }}
configuration-path: .github/labeler.yml # default
sync-labels: true
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.0
name: Labels from touched files (no sync)
if: |
github.event_name == 'pull_request_target' &&
!contains(fromJSON(inputs.headBranch).type, 'development')
with:
repo-token: ${{ steps.app-token.outputs.token }}
configuration-path: .github/labeler-no-sync.yml
sync-labels: false
- uses: actions/labeler@8558fd74291d67161a8a78ce36a881fa63b766a9 # v5.0.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
# the backport labels.
if: |
github.event_name == 'pull_request_target' &&
contains(fromJSON(inputs.headBranch).type, 'development')
with:
repo-token: ${{ steps.app-token.outputs.token }}
configuration-path: .github/labeler-development-branches.yml
sync-labels: true
- name: Log current API rate limits
env:
GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }}
run: gh api /rate_limit | jq
- uses: actions/labeler@ac9175f8a1f3625fd0d4fb234536d26811351594 # v4.3.0
with:
repo-token: ${{ secrets.GITHUB_TOKEN }}
sync-labels: true

View File

@@ -1,105 +0,0 @@
name: Lint
on:
workflow_call:
inputs:
mergedSha:
required: true
type: string
targetSha:
required: true
type: string
permissions: {}
defaults:
run:
shell: bash
jobs:
treefmt:
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/actions
- name: Check if the PR can be merged and checkout the merge commit
uses: ./.github/actions/get-merge-commit
with:
mergedSha: ${{ inputs.mergedSha }}
merged-as-untrusted: true
- uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- name: Check that files are formatted
run: |
# Note that it's fine to run this on untrusted code because:
# - There's no secrets accessible here
# - The build is sandboxed
if ! nix-build untrusted/ci -A fmt.check; then
echo "Some files are not properly formatted"
echo "Please format them by going to the Nixpkgs root directory and running one of:"
echo " nix-shell --run treefmt"
echo " nix develop --command treefmt"
echo " nix fmt"
echo "Make sure your branch is up to date with master; rebase if not."
echo "If you're having trouble, please ping @NixOS/nix-formatting"
exit 1
fi
parse:
runs-on: ubuntu-24.04-arm
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/actions
- name: Check if the PR can be merged and checkout the merge commit
uses: ./.github/actions/get-merge-commit
with:
mergedSha: ${{ inputs.mergedSha }}
merged-as-untrusted: true
- uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- name: Parse all nix files
run: |
# Tests multiple versions at once, let's make sure all of them run, so keep-going.
nix-build untrusted/ci -A parse --keep-going
nixpkgs-vet:
runs-on: ubuntu-24.04-arm
# This should take 1 minute at most, but let's be generous. The default of 6 hours is definitely too long.
timeout-minutes: 10
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: .github/actions
- name: Check if the PR can be merged and checkout merged and target commits
uses: ./.github/actions/get-merge-commit
with:
mergedSha: ${{ inputs.mergedSha }}
merged-as-untrusted: true
targetSha: ${{ inputs.targetSha }}
target-as-trusted: true
- uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- name: Running nixpkgs-vet
env:
# Force terminal colors to be enabled. The library that `nixpkgs-vet` uses respects https://bixense.com/clicolors/
CLICOLOR_FORCE: 1
run: |
if nix-build untrusted/ci -A nixpkgs-vet --arg base "./trusted" --arg head "./untrusted"; then
exit 0
else
exitCode=$?
echo "To run locally: ./ci/nixpkgs-vet.sh $GITHUB_BASE_REF https://github.com/$GITHUB_REPOSITORY.git"
echo "If you're having trouble, ping @NixOS/nixpkgs-vet"
exit "$exitCode"
fi

31
.github/workflows/manual-nixos.yml vendored Normal file
View File

@@ -0,0 +1,31 @@
name: "Build NixOS manual"
permissions: read-all
on:
pull_request_target:
branches:
- master
paths:
- 'nixos/**'
jobs:
nixos:
runs-on: ubuntu-latest
if: github.repository_owner == 'NixOS'
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true
- uses: cachix/cachix-action@18cf96c7c98e048e10a83abd92116114cd8504be # v14
with:
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
name: nixpkgs-ci
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
- name: Building NixOS manual
run: NIX_PATH=nixpkgs=$(pwd) nix-build --option restrict-eval true nixos/release.nix -A manual.x86_64-linux

32
.github/workflows/manual-nixpkgs.yml vendored Normal file
View File

@@ -0,0 +1,32 @@
name: "Build Nixpkgs manual"
permissions: read-all
on:
pull_request_target:
branches:
- master
paths:
- 'doc/**'
- 'lib/**'
jobs:
nixpkgs:
runs-on: ubuntu-latest
if: github.repository_owner == 'NixOS'
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
with:
# explicitly enable sandbox
extra_nix_config: sandbox = true
- uses: cachix/cachix-action@18cf96c7c98e048e10a83abd92116114cd8504be # v14
with:
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
name: nixpkgs-ci
signingKey: '${{ secrets.CACHIX_SIGNING_KEY }}'
- name: Building Nixpkgs manual
run: NIX_PATH=nixpkgs=$(pwd) nix-build --option restrict-eval true pkgs/top-level/release.nix -A manual -A manual.tests

42
.github/workflows/nix-parse.yml vendored Normal file
View File

@@ -0,0 +1,42 @@
name: "Check whether nix files are parseable"
permissions: read-all
on:
# avoids approving first time contributors
pull_request_target:
branches-ignore:
- 'release-**'
jobs:
tests:
runs-on: ubuntu-latest
if: "github.repository_owner == 'NixOS' && !contains(github.event.pull_request.title, '[skip treewide]')"
steps:
- name: Get list of changed files from PR
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
gh api \
repos/NixOS/nixpkgs/pulls/${{github.event.number}}/files --paginate \
| jq --raw-output '.[] | select(.status != "removed" and (.filename | endswith(".nix"))) | .filename' \
> "$HOME/changed_files"
if [[ -s "$HOME/changed_files" ]]; then
echo "CHANGED_FILES=$HOME/changed_files" > "$GITHUB_ENV"
fi
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
with:
# pull_request_target checks out the base branch by default
ref: refs/pull/${{ github.event.pull_request.number }}/merge
if: ${{ env.CHANGED_FILES && env.CHANGED_FILES != '' }}
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
with:
nix_path: nixpkgs=channel:nixpkgs-unstable
- name: Parse all changed or added nix files
run: |
ret=0
while IFS= read -r file; do
out="$(nix-instantiate --parse "$file")" || { echo "$out" && ret=1; }
done < "$HOME/changed_files"
exit "$ret"
if: ${{ env.CHANGED_FILES && env.CHANGED_FILES != '' }}

26
.github/workflows/no-channel.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
name: "No channel PR"
on:
pull_request:
branches:
- 'nixos-**'
- 'nixpkgs-**'
permissions:
contents: read
jobs:
fail:
permissions:
contents: none
name: "This PR is is targeting a channel branch"
runs-on: ubuntu-latest
steps:
- run: |
cat <<EOF
The nixos-* and nixpkgs-* branches are pushed to by the channel
release script and should not be merged into directly.
Please target the equivalent release-* branch or master instead.
EOF
exit 1

33
.github/workflows/ofborg-pending.yml vendored Normal file
View File

@@ -0,0 +1,33 @@
name: "Set pending OfBorg status"
on:
pull_request_target:
# Sets the ofborg-eval status to "pending" to signal that we are waiting for
# OfBorg even if it is running late. The status will be overwritten by OfBorg
# once it starts evaluation.
# WARNING:
# When extending this action, be aware that $GITHUB_TOKEN allows (restricted) write access to
# the GitHub repository. This means that it should not evaluate user input in a
# way that allows code injection.
permissions:
contents: read
jobs:
action:
if: github.repository_owner == 'NixOS'
permissions:
statuses: write
runs-on: ubuntu-latest
steps:
- name: "Set pending OfBorg status"
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
curl \
-X POST \
-H "Accept: application/vnd.github.v3+json" \
-H "Authorization: Bearer $GITHUB_TOKEN" \
-d '{"context": "ofborg-eval", "state": "pending", "description": "Waiting for OfBorg..."}' \
"https://api.github.com/repos/NixOS/nixpkgs/commits/${{ github.event.pull_request.head.sha }}/statuses"

View File

@@ -7,22 +7,24 @@
name: "Periodic Merges (24h)"
on:
schedule:
# * is a special character in YAML so you have to quote this string
# Merge every 24 hours
- cron: '0 0 * * *'
- cron: '0 0 * * *'
workflow_dispatch:
permissions: {}
defaults:
run:
shell: bash
permissions:
contents: read
jobs:
periodic-merge:
permissions:
contents: write # for devmasx/merge-branch to merge branches
pull-requests: write # for peter-evans/create-or-update-comment to create or update comment
if: github.repository_owner == 'NixOS'
runs-on: ubuntu-latest
strategy:
# don't fail fast, so that all pairs are tried
fail-fast: false
@@ -31,14 +33,32 @@ jobs:
max-parallel: 1
matrix:
pairs:
- from: release-24.11
into: staging-next-24.11
- from: staging-next-24.11
into: staging-24.11
- from: master staging
- from: master
into: haskell-updates
uses: ./.github/workflows/periodic-merge.yml
with:
from: ${{ matrix.pairs.from }}
into: ${{ matrix.pairs.into }}
secrets: inherit
- from: release-23.05
into: staging-next-23.05
- from: staging-next-23.05
into: staging-23.05
- from: release-23.11
into: staging-next-23.11
- from: staging-next-23.11
into: staging-23.11
name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
uses: devmasx/merge-branch@854d3ac71ed1e9deb668e0074781b81fdd6e771f # 1.4.0
with:
type: now
from_branch: ${{ matrix.pairs.from }}
target_branch: ${{ matrix.pairs.into }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Comment on failure
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0
if: ${{ failure() }}
with:
issue-number: 105153
body: |
Periodic merge from `${{ matrix.pairs.from }}` into `${{ matrix.pairs.into }}` has [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}).

View File

@@ -7,22 +7,24 @@
name: "Periodic Merges (6h)"
on:
schedule:
# * is a special character in YAML so you have to quote this string
# Merge every 6 hours
- cron: '0 */6 * * *'
- cron: '0 */6 * * *'
workflow_dispatch:
permissions: {}
defaults:
run:
shell: bash
permissions:
contents: read
jobs:
periodic-merge:
permissions:
contents: write # for devmasx/merge-branch to merge branches
pull-requests: write # for peter-evans/create-or-update-comment to create or update comment
if: github.repository_owner == 'NixOS'
runs-on: ubuntu-latest
strategy:
# don't fail fast, so that all pairs are tried
fail-fast: false
@@ -35,8 +37,22 @@ jobs:
into: staging-next
- from: staging-next
into: staging
uses: ./.github/workflows/periodic-merge.yml
with:
from: ${{ matrix.pairs.from }}
into: ${{ matrix.pairs.into }}
secrets: inherit
name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- name: ${{ matrix.pairs.from }} → ${{ matrix.pairs.into }}
uses: devmasx/merge-branch@854d3ac71ed1e9deb668e0074781b81fdd6e771f # 1.4.0
with:
type: now
from_branch: ${{ matrix.pairs.from }}
target_branch: ${{ matrix.pairs.into }}
github_token: ${{ secrets.GITHUB_TOKEN }}
- name: Comment on failure
uses: peter-evans/create-or-update-comment@23ff15729ef2fc348714a3bb66d2f655ca9066f2 # v3.1.0
if: ${{ failure() }}
with:
issue-number: 105153
body: |
Periodic merge from `${{ matrix.pairs.from }}` into `${{ matrix.pairs.into }}` has [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}).

View File

@@ -1,64 +0,0 @@
name: "Merge"
on:
workflow_call:
inputs:
from:
description: Branch to merge into target branch. Can also be two branches separated by space to find the merge base between them.
required: true
type: string
into:
description: Target branch to merge into.
required: true
type: string
defaults:
run:
shell: bash
jobs:
merge:
runs-on: ubuntu-24.04-arm
name: ${{ inputs.from }} → ${{ inputs.into }}
steps:
# Use a GitHub App to create the PR so that CI gets triggered
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
id: app-token
with:
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@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
- name: Find merge base between two branches
if: contains(inputs.from, ' ')
id: merge_base
env:
branches: ${{ inputs.from }}
run: |
# turn into bash array, split on space
read -ra branches <<< "$branches"
git fetch --shallow-since="1 month ago" origin "${branches[@]}"
merge_base="$(git merge-base "refs/remotes/origin/${branches[0]}" "refs/remotes/origin/${branches[1]}")"
echo "Found merge base: $merge_base" >&2
echo "merge_base=$merge_base" >> "$GITHUB_OUTPUT"
- name: ${{ inputs.from }} → ${{ inputs.into }}
uses: devmasx/merge-branch@854d3ac71ed1e9deb668e0074781b81fdd6e771f # 1.4.0
with:
type: now
from_branch: ${{ steps.merge_base.outputs.merge_base || inputs.from }}
target_branch: ${{ inputs.into }}
github_token: ${{ steps.app-token.outputs.token }}
- name: Comment on failure
uses: peter-evans/create-or-update-comment@71345be0265236311c031f5c7866368bd1eff043 # v4.0.0
if: ${{ failure() }}
with:
issue-number: 105153
body: |
Periodic merge from `${{ inputs.from }}` into `${{ inputs.into }}` has [failed](https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}).
token: ${{ steps.app-token.outputs.token }}

View File

@@ -1,149 +0,0 @@
name: PR
on:
pull_request:
paths:
- .github/workflows/build.yml
- .github/workflows/check.yml
- .github/workflows/eval.yml
- .github/workflows/lint.yml
- .github/workflows/pr.yml
- .github/workflows/labels.yml
- .github/workflows/reviewers.yml # needs eval results from the same event type
pull_request_target:
concurrency:
group: pr-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
permissions: {}
jobs:
prepare:
runs-on: ubuntu-24.04-arm
outputs:
baseBranch: ${{ steps.branches.outputs.base }}
headBranch: ${{ steps.branches.outputs.head }}
mergedSha: ${{ steps.get-merge-commit.outputs.mergedSha }}
targetSha: ${{ steps.get-merge-commit.outputs.targetSha }}
systems: ${{ steps.systems.outputs.systems }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: |
.github/actions
ci/supportedBranches.js
ci/supportedSystems.json
- name: Check if the PR can be merged and get the test merge commit
uses: ./.github/actions/get-merge-commit
id: get-merge-commit
- name: Load supported systems
id: systems
run: |
echo "systems=$(jq -c <ci/supportedSystems.json)" >> "$GITHUB_OUTPUT"
- name: Determine branch type
id: branches
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
with:
script: |
const { classify } = require('./ci/supportedBranches.js')
const { base, head } = context.payload.pull_request
const baseClassification = classify(base.ref)
core.setOutput('base', baseClassification)
core.info('base classification:', baseClassification)
const headClassification =
(base.repo.full_name == head.repo.full_name) ?
classify(head.ref) :
// PRs from forks are always considered WIP.
{ type: ['wip'] }
core.setOutput('head', headClassification)
core.info('head classification:', headClassification)
check:
name: Check
needs: [prepare]
uses: ./.github/workflows/check.yml
permissions:
# cherry-picks
pull-requests: write
with:
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
headBranch: ${{ needs.prepare.outputs.headBranch }}
lint:
name: Lint
needs: [prepare]
uses: ./.github/workflows/lint.yml
with:
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
targetSha: ${{ needs.prepare.outputs.targetSha }}
eval:
name: Eval
needs: [prepare]
uses: ./.github/workflows/eval.yml
permissions:
# compare
statuses: write
secrets:
OWNER_APP_PRIVATE_KEY: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
with:
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
targetSha: ${{ needs.prepare.outputs.targetSha }}
systems: ${{ needs.prepare.outputs.systems }}
labels:
name: Labels
needs: [prepare, eval]
uses: ./.github/workflows/labels.yml
permissions:
issues: write
pull-requests: write
secrets:
NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
with:
headBranch: ${{ needs.prepare.outputs.headBranch }}
reviewers:
name: Reviewers
needs: [prepare, eval]
if: |
needs.prepare.outputs.targetSha &&
!contains(fromJSON(needs.prepare.outputs.headBranch).type, 'development')
uses: ./.github/workflows/reviewers.yml
secrets:
OWNER_APP_PRIVATE_KEY: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
build:
name: Build
needs: [prepare]
uses: ./.github/workflows/build.yml
secrets:
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
with:
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
# This job's only purpose is to serve as a target for the "Required Status Checks" branch ruleset.
# It "needs" all the jobs that should block merging a PR.
# If they pass, it is skipped — which counts as "success" for purposes of the branch ruleset.
# However, if any of them fail, this job will also fail — thus blocking the branch ruleset.
no-pr-failures:
# Modify this list to add or remove jobs from required status checks.
needs:
- check
- lint
- eval
- build
# WARNING:
# Do NOT change the name of this job, otherwise the rule will not catch it anymore.
# This would prevent all PRs from merging.
name: no PR failures
if: ${{ failure() }}
runs-on: ubuntu-24.04-arm
steps:
- run: exit 1

View File

@@ -1,48 +0,0 @@
name: Push
on:
pull_request:
paths:
- .github/workflows/push.yml
# eval is tested via pr.yml
push:
# Keep this synced with ci/request-reviews/dev-branches.txt
branches:
- master
- staging
- release-*
- staging-*
- haskell-updates
- python-updates
permissions: {}
jobs:
prepare:
runs-on: ubuntu-24.04-arm
outputs:
systems: ${{ steps.systems.outputs.systems }}
steps:
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
sparse-checkout: |
ci/supportedSystems.json
- name: Load supported systems
id: systems
run: |
echo "systems=$(jq -c <ci/supportedSystems.json)" >> "$GITHUB_OUTPUT"
eval:
name: Eval
needs: [prepare]
uses: ./.github/workflows/eval.yml
# Those are not actually used on push, but will throw an error if not set.
permissions:
# compare
issues: write
pull-requests: write
statuses: write
with:
mergedSha: ${{ github.sha }}
systems: ${{ needs.prepare.outputs.systems }}

View File

@@ -1,17 +0,0 @@
name: Review dismissed
on:
pull_request_review:
types: [dismissed]
permissions: {}
defaults:
run:
shell: bash
jobs:
trigger:
runs-on: ubuntu-24.04-arm
steps:
- run: echo This is a no-op only used as a trigger for workflow_run.

View File

@@ -1,144 +0,0 @@
# This workflow will request reviews from the maintainers of each package
# listed in the PR's most recent eval comparison artifact.
name: Reviewers
on:
pull_request:
paths:
- .github/workflows/reviewers.yml
pull_request_target:
types: [ready_for_review]
workflow_call:
secrets:
OWNER_APP_PRIVATE_KEY:
required: true
concurrency:
group: reviewers-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
cancel-in-progress: true
permissions: {}
defaults:
run:
shell: bash
jobs:
request:
runs-on: ubuntu-24.04-arm
steps:
- name: Check out the PR at the base commit
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
path: trusted
sparse-checkout: ci
- name: Install Nix
uses: cachix/install-nix-action@f0fe604f8a612776892427721526b4c7cfb23aba # v31
with:
extra_nix_config: sandbox = true
- name: Build the requestReviews derivation
run: nix-build trusted/ci -A requestReviews
# See ./codeowners-v2.yml, reuse the same App because we need the same permissions
# Can't use the token received from permissions above, because it can't get enough permissions
- uses: actions/create-github-app-token@df432ceedc7162793a195dd1713ff69aefc7379e # v2.0.6
if: github.event_name == 'pull_request_target' && vars.OWNER_APP_ID
id: app-token
with:
app-id: ${{ vars.OWNER_APP_ID }}
private-key: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
permission-administration: read
permission-members: read
permission-pull-requests: write
- name: Log current API rate limits (github.token)
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq
# In the regular case, this workflow is called via workflow_call from the eval workflow directly.
# In the more special case, when a PR is undrafted an eval run will have started already.
- name: Wait for comparison to be done
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
id: eval
with:
script: |
const run_id = (await github.rest.actions.listWorkflowRuns({
owner: context.repo.owner,
repo: context.repo.repo,
workflow_id: 'pr.yml',
event: context.eventName,
head_sha: context.payload.pull_request.head.sha
})).data.workflow_runs[0].id
core.setOutput('run-id', run_id)
// Waiting 120 * 5 sec = 10 min. max.
// The extreme case is an Eval run that just started when the PR is undrafted.
// Eval takes max 5-6 minutes, normally.
for (let i = 0; i < 120; i++) {
const result = await github.rest.actions.listWorkflowRunArtifacts({
owner: context.repo.owner,
repo: context.repo.repo,
run_id,
name: 'comparison'
})
if (result.data.total_count > 0) return
await new Promise(resolve => setTimeout(resolve, 5000))
}
throw new Error("No comparison artifact found.")
- name: Log current API rate limits (github.token)
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq
- name: Download the comparison results
uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
run-id: ${{ steps.eval.outputs.run-id }}
github-token: ${{ github.token }}
pattern: comparison
path: comparison
merge-multiple: true
- name: Log current API rate limits (app-token)
if: ${{ steps.app-token.outputs.token }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq
- name: Log current API rate limits (github.token)
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq
- name: Requesting maintainer reviews
if: ${{ steps.app-token.outputs.token }}
env:
GH_TOKEN: ${{ github.token }}
REPOSITORY: ${{ github.repository }}
NUMBER: ${{ github.event.number }}
AUTHOR: ${{ github.event.pull_request.user.login }}
# Don't request reviewers on draft PRs
DRY_MODE: ${{ github.event.pull_request.draft && '1' || '' }}
run: |
# maintainers.json contains GitHub IDs. Look up handles to request reviews from.
# There appears to be no API to request reviews based on GitHub IDs
jq -r 'keys[]' comparison/maintainers.json \
| while read -r id; do gh api /user/"$id" --jq .login; done \
| GH_TOKEN=${{ steps.app-token.outputs.token }} result/bin/request-reviewers.sh "$REPOSITORY" "$NUMBER" "$AUTHOR"
- name: Log current API rate limits (app-token)
if: ${{ steps.app-token.outputs.token }}
env:
GH_TOKEN: ${{ steps.app-token.outputs.token }}
run: gh api /rate_limit | jq
- name: Log current API rate limits (github.token)
env:
GH_TOKEN: ${{ github.token }}
run: gh api /rate_limit | jq

View File

@@ -0,0 +1,69 @@
name: "Update terraform-providers"
on:
#schedule:
# - cron: "0 3 * * *"
workflow_dispatch:
permissions:
contents: read
jobs:
tf-providers:
permissions:
contents: write # for peter-evans/create-pull-request to create branch
pull-requests: write # for peter-evans/create-pull-request to create a PR
if: github.repository_owner == 'NixOS' && github.ref == 'refs/heads/master' # ensure workflow_dispatch only runs on master
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1
- uses: cachix/install-nix-action@6004951b182f8860210c8d6f0d808ec5b1a33d28 # v25
with:
nix_path: nixpkgs=channel:nixpkgs-unstable
- name: setup
id: setup
run: |
echo "title=terraform-providers: update $(date -u +"%Y-%m-%d")" >> $GITHUB_OUTPUT
- name: update terraform-providers
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
git config user.name "github-actions[bot]"
echo | nix-shell \
maintainers/scripts/update.nix \
--argstr commit true \
--argstr keep-going true \
--argstr max-workers 2 \
--argstr path terraform-providers
- name: get failed updates
run: |
echo 'FAILED<<EOF' >> $GITHUB_ENV
git ls-files --others >> $GITHUB_ENV
echo 'EOF' >> $GITHUB_ENV
# cleanup logs of failed updates so they aren't included in the PR
- name: clean repo
run: |
git clean -f
- name: create PR
uses: peter-evans/create-pull-request@153407881ec5c347639a548ade7d8ad1d6740e38 # v5.0.2
with:
body: |
Automatic update by [update-terraform-providers](https://github.com/NixOS/nixpkgs/blob/master/.github/workflows/update-terraform-providers.yml) action.
https://github.com/NixOS/nixpkgs/actions/runs/${{ github.run_id }}
These providers failed to update:
```
${{ env.FAILED }}
```
Check that all providers build with:
```
@ofborg build opentofu.full
```
If there is more than ten commits in the PR `ofborg` won't build it automatically and you will need to use the above command.
branch: terraform-providers-update
delete-branch: false
title: ${{ steps.setup.outputs.title }}
token: ${{ secrets.GITHUB_TOKEN }}

8
.gitignore vendored
View File

@@ -7,21 +7,18 @@
.idea/
.nixos-test-history
.vscode/
.helix/
outputs/
result-*
result
repl-result-*
tags
!pkgs/development/python-modules/result
/doc/NEWS.html
/doc/NEWS.txt
/doc/manual.html
/doc/manual.pdf
/result
/source/
.version-suffix
.direnv
.envrc
.DS_Store
.mypy_cache
@@ -36,6 +33,3 @@ update-git-commits.txt
# JetBrains IDEA module declaration file
/nixpkgs.iml
# Usually used for manual backports
.worktree/

View File

@@ -1,28 +1,15 @@
ajs124 <git@ajs124.de> <ajs124@users.noreply.github.com>
Anderson Torres <torres.anderson.85@protonmail.com>
Atemu <git@atemu.net> <atemu.main@gmail.com>
Christina Sørensen <christina@cafkafk.com>
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>
Fabian Affolter <mail@fabian-affolter.ch> <fabian@affolter-engineering.ch>
Fiona Behrens <me@kloenk.dev>
Fiona Behrens <me@kloenk.dev> <me@kloenk.de>
goatastronaut0212 <goatastronaut0212@outlook.com> <goatastronaut0212@proton.me>
Janne Heß <janne@hess.ooo> <dasJ@users.noreply.github.com>
jopejoe1 <nixpkgs@missing.ninja>
jopejoe1 <nixpkgs@missing.ninja> <johannes@joens.email>
jopejoe1 <nixpkgs@missing.ninja> <34899572+jopejoe1@users.noreply.github.com>
Jörg Thalheim <joerg@thalheim.io> <Mic92@users.noreply.github.com>
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>
R. RyanTM <ryantm-bot@ryantm.com>
Robert Hensing <robert@roberthensing.nl> <roberth@users.noreply.github.com>
Sandro Jäckel <sandro.jaeckel@gmail.com>
Sandro Jäckel <sandro.jaeckel@gmail.com> <sandro.jaeckel@sap.com>
superherointj <5861043+superherointj@users.noreply.github.com>
Tomodachi94 <tomodachi94@protonmail.com> Tomo <68489118+Tomodachi94@users.noreply.github.com>
Vladimír Čunát <v@cunat.cz> <vcunat@gmail.com>
Vladimír Čunát <v@cunat.cz> <vladimir.cunat@nic.cz>
Yifei Sun <ysun@hey.com> StepBroBD <Hi@StepBroBD.com>

View File

@@ -1 +0,0 @@
lib/.version

1
.version Normal file
View File

@@ -0,0 +1 @@
24.05

View File

@@ -93,8 +93,6 @@ This section describes in some detail how changes can be made and proposed with
7. Respond to review comments, potential CI failures and potential merge conflicts by updating the pull request.
Always keep the pull request in a mergeable state.
This process is covered in more detail from the non-technical side in [I opened a PR, how do I get it merged?](#i-opened-a-pr-how-do-i-get-it-merged).
The custom [OfBorg](https://github.com/NixOS/ofborg) CI system will perform various checks to help ensure code quality, whose results you can see at the bottom of the pull request.
See [the OfBorg Readme](https://github.com/NixOS/ofborg#readme) for more details.
@@ -131,17 +129,19 @@ When a PR is created, it will be pre-populated with some checkboxes detailed bel
#### Tested using sandboxing
When sandbox builds are enabled, Nix will set up an isolated environment for each build process.
It is used to remove further hidden dependencies set by the build environment to improve reproducibility.
This includes access to the network during the build outside of `fetch*` functions and files outside the Nix store.
Depending on the operating system, access to other resources is blocked as well (e.g., inter-process communication is isolated on Linux); see [sandbox](https://nixos.org/manual/nix/stable/command-ref/conf-file#conf-sandbox) in the Nix manual for details.
When sandbox builds are enabled, Nix will setup an isolated environment for each build process. It is used to remove further hidden dependencies set by the build environment to improve reproducibility. This includes access to the network during the build outside of `fetch*` functions and files outside the Nix store. Depending on the operating system access to other resources are blocked as well (ex. inter process communication is isolated on Linux); see [sandbox](https://nixos.org/manual/nix/stable/command-ref/conf-file#conf-sandbox) in the Nix manual for details.
In pull requests for [nixpkgs](https://github.com/NixOS/nixpkgs/) people are asked to test builds with sandboxing enabled (see `Tested using sandboxing` in the pull request template) because in [Hydra](https://nixos.org/hydra/) sandboxing is also used.
Sandboxing is not enabled by default in Nix due to a small performance hit on each build. In pull requests for [nixpkgs](https://github.com/NixOS/nixpkgs/) people are asked to test builds with sandboxing enabled (see `Tested using sandboxing` in the pull request template) because in [Hydra](https://nixos.org/hydra/) sandboxing is also used.
If you are on Linux, sandboxing is enabled by default.
On other platforms, sandboxing is disabled by default due to a small performance hit on each build.
Depending if you use NixOS or other platforms you can use one of the following methods to enable sandboxing **before** building the package:
Please enable sandboxing **before** building the package by adding the following to: `/etc/nix/nix.conf`:
- **Globally enable sandboxing on NixOS**: add the following to `configuration.nix`
```nix
nix.settings.sandbox = true;
```
- **Globally enable sandboxing on non-NixOS platforms**: add the following to: `/etc/nix/nix.conf`
```ini
sandbox = true
@@ -195,12 +195,19 @@ The last checkbox is about whether it fits the guidelines in this `CONTRIBUTING.
[rebase]: #rebasing-between-branches-ie-from-master-to-staging
From time to time, changes between branches must be rebased, for example, if the
number of new rebuilds they would cause is too large for the target branch.
number of new rebuilds they would cause is too large for the target branch. When
rebasing, care must be taken to include only the intended changes, otherwise
many CODEOWNERS will be inadvertently requested for review. To achieve this,
rebasing should not be performed directly on the target branch, but on the merge
base between the current and target branch. As an additional precautionary measure,
you should temporarily mark the PR as draft for the duration of the operation.
This reduces the probability of mass-pinging people. (OfBorg might still
request a couple of persons for reviews though.)
In the following example, we assume that the current branch, called `feature`,
is based on `master`, and we rebase it onto the merge base between
`master` and `staging` so that the PR can be retargeted to
`staging`. The example uses `upstream` as the remote for `NixOS/nixpkgs.git`
`master` and `staging` so that the PR can eventually be retargeted to
`staging` without causing a mess. The example uses `upstream` as the remote for `NixOS/nixpkgs.git`
while `origin` is the remote you are pushing to.
@@ -229,6 +236,36 @@ git status
git push origin feature --force-with-lease
```
#### Something went wrong and a lot of people were pinged
It happens. Remember to be kind, especially to new contributors.
There is no way back, so the pull request should be closed and locked
(if possible). The changes should be re-submitted in a new PR, in which the people
originally involved in the conversation need to manually be pinged again.
No further discussion should happen on the original PR, as a lot of people
are now subscribed to it.
The following message (or a version thereof) might be left when closing to
describe the situation, since closing and locking without any explanation
is kind of rude:
```markdown
It looks like you accidentally mass-pinged a bunch of people, which are now subscribed
and getting notifications for everything in this pull request. Unfortunately, they
cannot be automatically unsubscribed from the issue (removing review request does not
unsubscribe), therefore development cannot continue in this pull request anymore.
Please open a new pull request with your changes, link back to this one and ping the
people actually involved in here over there.
In order to avoid this in the future, there are instructions for how to properly
rebase between branches in our [contribution guidelines](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#rebasing-between-branches-ie-from-master-to-staging).
Setting your pull request to draft prior to rebasing is strongly recommended.
In draft status, you can preview the list of people that are about to be requested
for review, which allows you to sidestep this issue.
This is not a bulletproof method though, as OfBorg still does review requests even on draft PRs.
```
## How to backport pull requests
[pr-backport]: #how-to-backport-pull-requests
@@ -280,46 +317,25 @@ When reviewing a pull request, please always be nice and polite. Controversial c
GitHub provides reactions as a simple and quick way to provide feedback to pull requests or any comments. The thumb-down reaction should be used with care and if possible accompanied with some explanation so the submitter has directions to improve their contribution.
When doing a review:
- Aim to drive the proposal to a timely conclusion.
- Focus on the proposed changes to keep the scope of the discussion narrow.
- Help the contributor prioritise their efforts towards getting their change merged.
If you find anything related that could be improved but is not immediately required for acceptance, consider
- Implementing the changes yourself in a follow-up pull request (and request review from the person who inspired you)
- Tracking your idea in an issue
- Offering the original contributor to review a follow-up pull request
- Making concrete [suggestions](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request) in the same pull request.
For example, follow-up changes could involve refactoring code in the affected files.
But please remember not to make such additional considerations a blocker, and communicate that to the contributor, for example by following the [conventional comments](https://conventionalcomments.org/) pattern.
If the related change is essential for the contribution at hand, make clear why you think it is important to address that first.
Pull request reviews should include a list of what has been reviewed in a comment, so other reviewers and mergers can know the state of the review.
All the review template samples provided in this section are generic and meant as examples. Their usage is optional and the reviewer is free to adapt them to their liking.
To get more information about how to review specific parts of Nixpkgs, refer to the documents linked to in the [overview section][overview].
If a pull request contains documentation changes that might require feedback from the documentation team, ping [@NixOS/documentation-team](https://github.com/orgs/nixos/teams/documentation-team) on the pull request.
If a pull request contains documentation changes that might require feedback from the documentation team, ping [@NixOS/documentation-reviewers](https://github.com/orgs/nixos/teams/documentation-reviewers) on the pull request.
If you consider having enough knowledge and experience in a topic and would like to be a long-term reviewer for related submissions, please contact the current reviewers for that topic. They will give you information about the reviewing process. The main reviewers for a topic can be hard to find as there is no list, but checking past pull requests to see who reviewed or git-blaming the code to see who committed to that topic can give some hints.
Container system, boot system and library changes are some examples of the pull requests fitting this category.
## How to merge pull requests yourself
## How to merge pull requests
[pr-merge]: #how-to-merge-pull-requests
To streamline automated updates, leverage the nixpkgs-merge-bot by simply commenting `@NixOS/nixpkgs-merge-bot merge`. The bot will verify if the following conditions are met, refusing to merge otherwise:
The *Nixpkgs committers* are people who have been given
permission to merge.
- the PR author should be @r-ryantm;
- the commenter that issued the command should be among the package maintainers;
- the package should reside in `pkgs/by-name`.
Further, nixpkgs-merge-bot will ensure all ofBorg checks (except the Darwin-related ones) are successfully completed before merging the pull request. Should the checks still be underway, the bot patiently waits for ofBorg to finish before attempting the merge again.
For other pull requests, please see [I opened a PR, how do I get it merged?](#i-opened-a-pr-how-do-i-get-it-merged).
It is possible for community members that have enough knowledge and experience on a special topic to contribute by merging pull requests.
In case the PR is stuck waiting for the original author to apply a trivial
change (a typo, capitalisation change, etc.) and the author allowed the members
@@ -333,7 +349,7 @@ The following paragraphs about how to deal with unactive contributors is just a
Please note that contributors with commit rights unactive for more than three months will have their commit rights revoked.
-->
Please see the discussion in [GitHub nixpkgs issue #321665](https://github.com/NixOS/nixpkgs/issues/321665) for information on how to proceed to be granted this level of access.
Please see the discussion in [GitHub nixpkgs issue #50105](https://github.com/NixOS/nixpkgs/issues/50105) for information on how to proceed to be granted this level of access.
In a case a contributor definitively leaves the Nix community, they should create an issue or post on [Discourse](https://discourse.nixos.org) with references of packages and modules they maintain so the maintainership can be taken over by other contributors.
@@ -345,7 +361,7 @@ See [Nix Channel Status](https://status.nixos.org/) for the current channels and
Here's a brief overview of the main Git branches and what channels they're used for:
- `master`: The main branch, used for the unstable channels such as `nixpkgs-unstable`, `nixos-unstable` and `nixos-unstable-small`.
- `release-YY.MM` (e.g. `release-24.05`): The NixOS release branches, used for the stable channels such as `nixos-24.05`, `nixos-24.05-small` and `nixpkgs-24.05-darwin`.
- `release-YY.MM` (e.g. `release-23.11`): The NixOS release branches, used for the stable channels such as `nixos-23.11`, `nixos-23.11-small` and `nixpkgs-23.11-darwin`.
When a channel is updated, a corresponding Git branch is also updated to point to the corresponding commit.
So e.g. the [`nixpkgs-unstable` branch](https://github.com/nixos/nixpkgs/tree/nixpkgs-unstable) corresponds to the Git commit from the [`nixpkgs-unstable` channel](https://channels.nixos.org/nixpkgs-unstable).
@@ -358,12 +374,10 @@ See [this section][branch] to know when to use the release branches.
[staging]: #staging
The staging workflow exists to batch Hydra builds of many packages together.
It is coordinated in the [Staging room](https://matrix.to/#/#staging:nixos.org) on Matrix.
It works by directing commits that cause [mass rebuilds][mass-rebuild] to a separate `staging` branch that isn't directly built by Hydra.
Regularly, the `staging` branch is _manually_ merged into a `staging-next` branch to be built by Hydra using the [`nixpkgs:staging-next` jobset](https://hydra.nixos.org/jobset/nixpkgs/staging-next).
The `staging-next` branch should then only receive changes that fix Hydra builds;
**for anything else, ask the [Staging room](https://matrix.to/#/#staging:nixos.org) first**.
The `staging-next` branch should then only receive direct commits in order to fix Hydra builds.
Once it is verified that there are no major regressions, it is merged into `master` using [a pull request](https://github.com/NixOS/nixpkgs/pulls?q=head%3Astaging-next).
This is done manually in order to ensure it's a good use of Hydra's computing resources.
By keeping the `staging-next` branch separate from `staging`, this batching does not block developers from merging changes into `staging`.
@@ -393,10 +407,14 @@ Here is a Git history diagram showing the flow of commits between the three bran
} }%%
gitGraph
commit id:" "
branch staging
commit id:" "
branch staging-next
branch staging
checkout master
checkout staging
checkout master
commit id:" "
checkout staging-next
merge master id:"automatic"
checkout staging
merge staging-next id:"automatic "
@@ -423,14 +441,14 @@ gitGraph
Here's an overview of the different branches:
| branch | `master` | `staging-next` | `staging` |
| branch | `master` | `staging` | `staging-next` |
| --- | --- | --- | --- |
| Used for development | ✔️ | | ✔️ |
| Built by Hydra | ✔️ | ✔️ | |
| [Mass rebuilds][mass-rebuild] | ❌ | ⚠️ Only to fix Hydra builds | ✔️ |
| Critical security fixes | ✔️ for non-mass-rebuilds | ✔️ for mass-rebuilds | ❌ |
| Automatically merged into | `staging-next` | `staging` | - |
| Manually merged into | - | `master` | `staging-next` |
| Used for development | ✔️ | ✔️ | |
| Built by Hydra | ✔️ | | ✔️ |
| [Mass rebuilds][mass-rebuild] | ❌ | ✔️ | ⚠️ Only to fix Hydra builds |
| Critical security fixes | ✔️ for non-mass-rebuilds | ❌ | ✔️ for mass-rebuilds |
| Automatically merged into | `staging-next` | - | `staging` |
| Manually merged into | - | `staging-next` | `master` |
The staging workflow is used for all main branches, `master` and `release-YY.MM`, with corresponding names:
- `master`/`release-YY.MM`
@@ -496,7 +514,6 @@ To get a sense for what changes are considered mass rebuilds, see [previously me
- Check for unnecessary whitespace with `git diff --check` before committing.
- If you have commits `pkg-name: oh, forgot to insert whitespace`: squash commits in this case. Use `git rebase -i`.
See [Squashing Commits](https://git-scm.com/book/en/v2/Git-Tools-Rewriting-History#_squashing) for additional information.
- For consistency, there should not be a period at the end of the commit message's summary line (the first line of the commit message).
@@ -512,7 +529,6 @@ To get a sense for what changes are considered mass rebuilds, see [previously me
- [Commit conventions](./doc/README.md#commit-conventions) for changes to `doc`, the Nixpkgs manual.
### Writing good commit messages
[writing-good-commit-messages]: #writing-good-commit-messages
In addition to writing properly formatted commit messages, it's important to include relevant information so other developers can later understand *why* a change was made. While this information usually can be found by digging code, mailing list/Discourse archives, pull request discussions or upstream changes, it may require a lot of work.
@@ -531,47 +547,153 @@ If you removed packages or made some major NixOS changes, write about it in the
Names of files and directories should be in lowercase, with dashes between words — not in camel case. For instance, it should be `all-packages.nix`, not `allPackages.nix` or `AllPackages.nix`.
### Formatting
CI [enforces](./.github/workflows/check-nix-format.yml) all Nix files to be
formatted using the [official Nix formatter](https://github.com/NixOS/nixfmt).
You can ensure this locally using either of these commands:
```
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 format the file with `treefmt` on save.
If you have any problems with formatting, please ping the
[formatting team](https://nixos.org/community/teams/formatting/) via
[@NixOS/nix-formatting](https://github.com/orgs/NixOS/teams/nix-formatting).
### Syntax
- Set up [editorconfig](https://editorconfig.org/) for your editor, such that [the settings](./.editorconfig) are automatically applied.
- Use 2 spaces of indentation per indentation level in Nix expressions, 4 spaces in shell scripts.
- Do not use tab characters, i.e. configure your editor to use soft tabs. For instance, use `(setq-default indent-tabs-mode nil)` in Emacs. Everybody has different tab settings so its asking for trouble.
- Use `lowerCamelCase` for variable names, not `UpperCamelCase`. Note, this rule does not apply to package attribute names, which instead follow the rules in [package naming](./pkgs/README.md#package-naming).
- Functions should list their expected arguments as precisely as possible. That is, write
- Function calls with attribute set arguments are written as
```nix
{ stdenv, fetchurl, perl }: <...>
foo {
arg = ...;
}
```
instead of
not
```nix
args: with args; <...>
foo
{
arg = ...;
}
```
Also fine is
```nix
foo { arg = ...; }
```
if it's a short call.
- In attribute sets or lists that span multiple lines, the attribute names or list elements should be aligned:
```nix
# A long list.
list = [
elem1
elem2
elem3
];
# A long attribute set.
attrs = {
attr1 = short_expr;
attr2 =
if true then big_expr else big_expr;
};
# Combined
listOfAttrs = [
{
attr1 = 3;
attr2 = "fff";
}
{
attr1 = 5;
attr2 = "ggg";
}
];
```
- Short lists or attribute sets can be written on one line:
```nix
# A short list.
list = [ elem1 elem2 elem3 ];
# A short set.
attrs = { x = 1280; y = 1024; };
```
- Breaking in the middle of a function argument can give hard-to-read code, like
```nix
someFunction { x = 1280;
y = 1024; } otherArg
yetAnotherArg
```
(especially if the argument is very large, spanning multiple lines).
Better:
```nix
someFunction
{ x = 1280; y = 1024; }
otherArg
yetAnotherArg
```
or
```nix
{ stdenv, fetchurl, perl, ... }: <...>
let res = { x = 1280; y = 1024; };
in someFunction res otherArg yetAnotherArg
```
- The bodies of functions, asserts, and withs are not indented to prevent a lot of superfluous indentation levels, i.e.
```nix
{ arg1, arg2 }:
assert system == "i686-linux";
stdenv.mkDerivation { ...
```
not
```nix
{ arg1, arg2 }:
assert system == "i686-linux";
stdenv.mkDerivation { ...
```
- Function formal arguments are written as:
```nix
{ arg1, arg2, arg3 }:
```
but if they don't fit on one line they're written as:
```nix
{ arg1, arg2, arg3
, arg4, ...
, # Some comment...
argN
}:
```
- Functions should list their expected arguments as precisely as possible. That is, write
```nix
{ stdenv, fetchurl, perl }: ...
```
instead of
```nix
args: with args; ...
```
or
```nix
{ stdenv, fetchurl, perl, ... }: ...
```
For functions that are truly generic in the number of arguments (such as wrappers around `mkDerivation`) that have some required arguments, you should write them using an `@`-pattern:
@@ -580,7 +702,7 @@ If you have any problems with formatting, please ping the
{ stdenv, doCoverageAnalysis ? false, ... } @ args:
stdenv.mkDerivation (args // {
foo = if doCoverageAnalysis then "bla" else "";
... if doCoverageAnalysis then "bla" else "" ...
})
```
@@ -590,230 +712,33 @@ If you have any problems with formatting, please ping the
args:
args.stdenv.mkDerivation (args // {
foo = if args ? doCoverageAnalysis && args.doCoverageAnalysis then "bla" else "";
... if args ? doCoverageAnalysis && args.doCoverageAnalysis then "bla" else "" ...
})
```
- Unnecessary string conversions should be avoided. Do
```nix
{
rev = version;
}
rev = version;
```
instead of
```nix
{
rev = "${version}";
}
rev = "${version}";
```
- Building lists conditionally _should_ be done with `lib.optional(s)` instead of using `if cond then [ ... ] else null` or `if cond then [ ... ] else [ ]`.
```nix
{
buildInputs = lib.optional stdenv.hostPlatform.isDarwin iconv;
}
buildInputs = lib.optional stdenv.isDarwin iconv;
```
instead of
```nix
{
buildInputs = if stdenv.hostPlatform.isDarwin then [ iconv ] else null;
}
buildInputs = if stdenv.isDarwin then [ iconv ] else null;
```
As an exception, an explicit conditional expression with null can be used when fixing a important bug without triggering a mass rebuild.
If this is done a follow up pull request _should_ be created to change the code to `lib.optional(s)`.
# Practical contributing advice
To contribute effectively and efficiently, you need to be aware of how the contributing process generally works.
This section aims to document the process as we live it in Nixpkgs to set expectations right and give practical tips on how to work with it.
## I opened a PR, how do I get it merged?
[i-opened-a-pr-how-do-i-get-it-merged]:#i-opened-a-pr-how-do-i-get-it-merged
In order for your PR to be merged, someone with merge permissions on the repository ("committer") needs to review and merge it.
Because the group of people with merge permissions is mostly a collection of independent unpaid volunteers who do this in their own free time, this can take some time to happen.
It is entirely normal for your PR to sit around without any feedback for days, weeks or sometimes even months.
We strive to avoid the latter cases of course but the reality of it is that this does happen quite frequently.
Even when you get feedback, follow-up feedback may take similarly long.
Don't be intimidated by this and kindly ask for feedback again every so often.
If your change is good it will eventually be merged at some point.
There are some things you can do to help speed up the process of your PR being merged though.
In order to speed the process up, you need to know what needs to happen before a committer will actually hit the merge button.
This section intends to give a little overview and insight of what happens after you create your PR.
### The committer's perspective
PRs have varying quality and even the best people make mistakes.
It is the role of the committer team to assess whether any PR's changes are good changes or not.
In order for any PR to be merged, at least one committer needs to be convinced of its quality enough to merge it.
Committers typically assess three aspects of your PR:
1. Whether the change's intention is necessary and desirable
2. Whether the code quality of your changes is good
3. Whether the artefacts produced by the code are good
If you want your PR to get merged quickly and smoothly, it is in your best interest to help convince committers in these three aspects.
### How to help committers assess your PR
For the committer to judge your intention, it's best to explain why you've made your change.
This does not apply to trivial changes like version updates because the intention is obvious (though linking the changelog is appreciated).
For any more nuanced changed or even major version upgrades, it helps if you explain the background behind your change a bit.
E.g. if you're adding a package, explain what it is and why it should be in Nixpkgs.
This goes hand in hand with [Writing good commit messages](#writing-good-commit-messages).
For the code quality assessment, you cannot do anything yourself as only the committer can do this and they already have your code to look at.
In order to minimise the need for back and forth though, do take a look over your code changes yourself and try to put yourself into the shoes of someone who didn't just write that code.
Would you immediately know what the code does or why it is needed by glancing at it?
If not, reviewers will notice this and will ask you to clarify the code by refactoring it and/or adding a few explanations in code comments.
Doing this preemptively can save you and the committer a lot of time.
To better convey the "story" of your change, consider dividing your change into multiple atomic commits.
There is a balance to strike however: over-fragmentation causes friction.
The code artefacts are the hardest for committers to assess because PRs touch all sorts of components: applications, libraries, NixOS modules, editor plugins and many many other things.
Any individual committer can only really assess components that they themselves know how to use however and yet they must still be convinced somehow.
There isn't a good generic solution to this but there are some ways easing the committer's job here:
- Provide smoke tests that the committer can run without much research or setup.
Committers usually don't have the time or interest to learn how your component works and how they could test its functionality.
If you can provide a quick guide on how to use the component in a meaningful way or a ready-made command that demonstrates that the component works as expected, the committer can easily convince themselves that your change is good.
If it can be automated, you could even turn this smoke test into an automated NixOS test which reviewers could simply run via Nix.
- Invite other users of the component to try it out and report their findings.
If a committer sees the testimonials of other users trying your change and it works as expected for them, that too can convince the committer of your PR's quality.
- Describe what you have done to test your PR.
If you can convince the committer that you have done sufficient quality assurance on your changes and they trust your report, this too can convince them of your PR's quality, albeit not as strongly as the methods above.
- Become a maintainer of the component.
This isn't something you can do on your first few PRs touching a component but listed maintainers generally receive more trust when it comes to changes to their maintained components and committers may opt to merge changes without deeper review when they see they're done by their respective maintainer.
Even if you adhere to all of these recommendations, it is still quite possible for your PR to be forgotten or abandoned by any given committer.
Please remain mindful of the fact that they are doing this on their own volition and unpaid in their free time and therefore [owe you nothing](https://mikemcquaid.com/open-source-maintainers-owe-you-nothing/).
Causing a stink in such a situation is a surefire way to get any other potential committer to not want to look at your PR either.
Ask them nicely whether they still intend to review your PR and find yourself another committer to look at your PR if not.
### How can I get a committer to look at my PR?
- Improve skimmability: use a simple descriptive PR title (details go in commit titles) outlining _what_ is done and _why_.
- Improve discoverability: apply all relevant labels, tick all relevant PR body checkboxes.
- Wait. Reviewers frequently browse open PRs and may happen to run across yours and take a look.
- Get non-committers to review/approve. Many committers filter open PRs for low-hanging fruit that are already been reviewed.
- [@-mention](https://github.blog/news-insights/mention-somebody-they-re-notified/) someone and ask them nicely
- Post in one of the channels made for this purpose if there has been no activity for at least one week
- The current "PRs ready for review" or "PRs already reviewed" threads in the [NixOS Discourse](https://discourse.nixos.org/c/dev/14) (of course choose the one that applies to your situation)
- The [Nixpkgs Review Requests Matrix room](https://matrix.to/#/#review-requests:nixos.org).
### CI failed or got stuck on my PR, what do I do?
First ensure that the failure is actually related to your change.
Sometimes, the CI system simply has a hiccup or the check was broken by someone else before you made your changes.
Read through the error message; it's usually quite easy to tell whether it is caused by anything you did by checking whether it mentions the component you touched anywhere.
If it is indeed caused by your change, obviously try to fix it.
Don't be afraid of asking for advice if you're uncertain how to do that, others have likely fixed such issues dozens of times and can help you out.
Your PR is unlikely to be merged if it has a known issue and it is the purpose of CI to alert you aswell as reviewers to these issues.
ofBorg builds can often get stuck, particularly in PRs targeting `staging` and in builders for the Darwin platform. Reviewers will know how to handle them or when to ignore them.
Don't worry about it.
If there is a build failure however and it happened due to a package related to your change, you need to investigate it of course.
If ofBorg reveals the build to be broken on some platform and you don't have access to that platform, you should set your package's `meta.broken` accordingly.
When in any doubt, please ask via a comment in your PR or through one of the help channels.
## I received a review on my PR, how do I get it over the finish line?
In the review process, the committer will have left some sort of feedback on your PR.
They may have immediately approved of your PR or even merged it but the more likely case is that they want you to change a few things or that they require further input.
A reviewer may have taken a look at the code and it looked good to them ("Diff LGTM") but they still need to be convinced of the artefact's quality.
They might also be waiting on input from other users of the component or its listed maintainer on whether the intention of your PR makes sense for the component.
If you know of people who could help clarify any of this, please bring the PR to their attention.
The current state of the PR is frequently not clearly communicated, so please don't hesitate to ask about it if it's unclear to you.
It's also possible for the reviewer to not be convinced that your PR is necessary or that the method you've chose to achieve your intention is the right one.
Please explain your intentions and reasoning to the committer in such a case.
There may be constraints you had to work with which they're not aware of or qualities of your approach that they didn't immediately notice.
(If these weren't clear to the reviewer, that's a good sign you should explain them in your commit message or code comments!)
There are some further pitfalls and realities which this section intends to make you aware of.
### Aim to reduce cycles
Please be prepared for it to take a while before the reviewer gets back to you after you respond.
This is simply the reality of community projects at the scale of Nixpkgs.
As such, make sure to respond to _all_ feedback, either by applying suggested changes or argue in favor of something else or no change.
It wastes everyone time waiting for a couple of days just for the reviewer to remind you to address something they asked for.
### A reviewer requested a bunch of insubstantial changes on my PR
The people involved in Nixpkgs care about code quality because, once in Nixpkgs, it needs to be maintained for many years to come.
It is therefore likely that other people will ask you to do some things in another way or adhere to some standard.
Sometimes however, they also care a bit too much and may ask you to adhere to a personal preference of theirs.
It's not always easy to tell which is which and whether the requests are critically important to merging the PR.
Sometimes another reviewer may also come along with totally different opinions on some points too.
It is convention to mark review comments that are not critical to the PR as nitpicks but this is not always followed.
As the PR author, you should still take a look at these as they will often reveal best practices and unwritten rules that usually have good reasons behind them and you may want to incorporate them into your modus operandi.
Please keep in mind that reviewers almost always mean well here.
Their intent is not to denounce your code, they want your code to be as good as it can be.
Through their experience, they may also take notice of a seemingly insignificant issues that have caused significant burden before.
Sometimes however, they can also get a bit carried away and become too perfectionistic.
If you feel some of the requests are unreasonable, out of scope, or merely a matter of personal preference, try to nicely remind the reviewers that you may not intend this code to be 100% perfect or that you have different taste in some regards and press them on whether they think that these requests are *critical* to the PR's success.
While we do have a set of [official standards for the Nix community](https://github.com/NixOS/rfcs/), we don't have standards for everything and there are often multiple valid ways to achieve the same goal.
Unless there are standards forbidding the patterns used in your code or there are serious technical, maintainability or readability issues with your code, you can insist to keep the code the way you made it and disregard the requests.
Please communicate this clearly though; a simple "I prefer it this way and see no major issue with it" can save you a lot of arguing.
If you are unsure about some change requests, please ask reviewers *why* they requested them.
This will usually reveal how important they deem it to be and will help educate you about standards, best practices, unwritten rules aswell as preferences people have and why.
Some committers may have stronger opinions on some things and therefore (understandably) may not want to merge your PR if you don't follow their requests.
It is totally fine to get yourself a second or third opinion in such a case.
### Committers work on a push-basis
It's possible for you to get a review but nothing happens afterwards, even if you reply to review comments.
A committer not following up on your PR does not necessarily mean they're disinterested or unresponsive, they may have simply forgotten to follow up on it or had some other circumstances preventing them from doing so.
Committers typically handle many other PRs besides yours and it is not realistic for them to keep up with all of them to a degree where they could reasonably remember to follow up on all PRs that they had intended following up upon.
If someone left an approving review on your PR and didn't merge a few days later, the most likely case is that they simply forgot.
Please see it as your responsibility to actively remind reviewers of your open PRs.
The easiest way to do so is to cause them a Github notification.
Github notifies people involved in the PR whenever you add a comment to your PR, push your PR or re-request their review.
Doing any of that will get you people's attention again.
Everyone deserves proper attention, and yes that includes you!
However please be mindful that committers can sadly not always give everyone the attention they deserve.
It may very well be the case that you have to do this every time you need the committer to follow up upon your PR.
Again, this is a community project so please be mindful of people's circumstances here; be nice when requesting reviews again.
It may also be the case that the committer has lost interest or isn't familiar enough with the component you're touching to be comfortable merging your PR.
They will likely not immediately state that fact however, so please ask for clarification and don't hesitate to find yourself another committer to take a look at your PR.
### Nothing helped
If you followed these guidelines but still got no results or if you feel that you have been wronged in some way, please explicitly reach out to the greater community via its communication channels.
The [NixOS Discourse](https://discourse.nixos.org/) is a great place to do this as it has historically been the asynchronous medium with the greatest concentration of committers and other people who are significantly involved in Nixpkgs.
There is a dedicated discourse thread [PRs in distress](https://discourse.nixos.org/t/prs-in-distress/3604) where you can link your PR if everything else fails.
The [Nixpkgs / NixOS contributions Matrix channel](https://matrix.to/#/#dev:nixos.org) is the best synchronous channel with the same qualities.
Please reserve these for cases where you've made a serious effort in trying to get the attention of multiple active committers and provided realistic means for them to assess your PR's quality though.
As mentioned previously, it is unfortunately perfectly normal for a PR to sit around for weeks on end due to the realities of this being a community project.
Please don't blow up situations where progress is happening but is merely not going fast enough for your tastes.
Honking in a traffic jam will not make you go any faster.

View File

@@ -1,4 +1,4 @@
Copyright (c) 2003-2024 Eelco Dolstra and the Nixpkgs/NixOS contributors
Copyright (c) 2003-2023 Eelco Dolstra and the Nixpkgs/NixOS contributors
Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the

View File

@@ -1,20 +1,19 @@
<p align="center">
<a href="https://nixos.org">
<picture>
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/NixOS/nixos-homepage/main/public/logo/nixos-hires.png">
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/NixOS/nixos-artwork/master/logo/nixos-white.png">
<img src="https://raw.githubusercontent.com/NixOS/nixos-homepage/main/public/logo/nixos-hires.png" width="500px" alt="NixOS logo">
</picture>
<a href="https://nixos.org#gh-light-mode-only">
<img src="https://raw.githubusercontent.com/NixOS/nixos-homepage/master/logo/nixos-hires.png" width="500px" alt="NixOS logo"/>
</a>
<a href="https://nixos.org#gh-dark-mode-only">
<img src="https://raw.githubusercontent.com/NixOS/nixos-artwork/master/logo/nixos-white.png" width="500px" alt="NixOS logo"/>
</a>
</p>
<p align="center">
<a href="CONTRIBUTING.md"><img src="https://img.shields.io/github/contributors-anon/NixOS/nixpkgs" alt="Contributors badge" /></a>
<a href="https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md"><img src="https://img.shields.io/github/contributors-anon/NixOS/nixpkgs" alt="Contributors badge" /></a>
<a href="https://opencollective.com/nixos"><img src="https://opencollective.com/nixos/tiers/supporter/badge.svg?label=supporters&color=brightgreen" alt="Open Collective supporters" /></a>
</p>
[Nixpkgs](https://github.com/nixos/nixpkgs) is a collection of over
100,000 software packages that can be installed with the
80,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.
@@ -29,8 +28,8 @@
* [Discourse Forum](https://discourse.nixos.org/)
* [Matrix Chat](https://matrix.to/#/#community:nixos.org)
* [NixOS Weekly](https://weekly.nixos.org/)
* [Official wiki](https://wiki.nixos.org/)
* [Community-maintained list of ways to get in touch](https://wiki.nixos.org/wiki/Get_In_Touch#Chat) (Discord, Telegram, IRC, etc.)
* [Community-maintained wiki](https://nixos.wiki/)
* [Community-maintained list of ways to get in touch](https://nixos.wiki/wiki/Get_In_Touch#Chat) (Discord, Telegram, IRC, etc.)
# Other Project Repositories
@@ -52,9 +51,9 @@ 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 24.11 release](https://hydra.nixos.org/jobset/nixos/release-24.11)
* [Continuous package builds for the NixOS 23.11 release](https://hydra.nixos.org/jobset/nixos/release-23.11)
* [Tests for unstable/master](https://hydra.nixos.org/job/nixos/trunk-combined/tested#tabs-constituents)
* [Tests for the NixOS 24.11 release](https://hydra.nixos.org/job/nixos/release-24.11/tested#tabs-constituents)
* [Tests for the NixOS 23.11 release](https://hydra.nixos.org/job/nixos/release-23.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
@@ -74,7 +73,7 @@ Community contributions are always welcome through GitHub Issues and
Pull Requests.
For more information about contributing to the project, please visit
the [contributing page](CONTRIBUTING.md).
the [contributing page](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md).
# Donations

View File

@@ -1,4 +0,0 @@
# TODO: Move to top-level via staging PR
[*.js]
indent_style = space
indent_size = 2

424
ci/OWNERS
View File

@@ -1,424 +0,0 @@
# This file is used to describe who owns what in this repository.
# Users/teams will get review requests for PRs that change their files.
#
# This file does not replace `meta.maintainers`
# but is instead used for other things than derivations and modules,
# like documentation, package sets, and other assets.
#
# This file uses the same syntax as the natively supported CODEOWNERS file,
# see https://help.github.com/articles/about-codeowners/ for documentation.
# However it comes with some notable differences:
# - There is no need for user/team listed here to have write access.
# - No reviews will be requested for PRs that target the wrong base branch.
#
# Processing of this file is implemented in workflows/codeowners-v2.yml
# CI
/.github/actions @NixOS/nixpkgs-ci
/.github/workflows @NixOS/nixpkgs-ci
/ci @NixOS/nixpkgs-ci
/ci/OWNERS @infinisil @philiptaron
# Development support
/.editorconfig @Mic92 @zowoq
/shell.nix @infinisil @NixOS/Security
# Libraries
/lib @infinisil
/lib/systems @alyssais @ericson2314 @NixOS/stdenv
/lib/generators.nix @infinisil @Profpatsch
/lib/cli.nix @infinisil @Profpatsch
/lib/debug.nix @infinisil @Profpatsch
/lib/asserts.nix @infinisil @Profpatsch
/lib/path/* @infinisil
/lib/fileset @infinisil
## Libraries / Module system
/lib/modules.nix @infinisil @roberth
/lib/types.nix @infinisil @roberth
/lib/options.nix @infinisil @roberth
/lib/tests/modules.sh @infinisil @roberth
/lib/tests/modules @infinisil @roberth
# Nixpkgs Internals
/default.nix @Ericson2314
/pkgs/top-level/default.nix @Ericson2314
/pkgs/top-level/impure.nix @Ericson2314
/pkgs/top-level/stage.nix @Ericson2314
/pkgs/top-level/splice.nix @Ericson2314
/pkgs/top-level/release-cross.nix @Ericson2314
/pkgs/top-level/by-name-overlay.nix @infinisil @philiptaron
/pkgs/stdenv @philiptaron @NixOS/stdenv
/pkgs/stdenv/generic @Ericson2314 @NixOS/stdenv
/pkgs/stdenv/generic/check-meta.nix @Ericson2314 @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/auto-patchelf.sh @layus
/pkgs/by-name/au/auto-patchelf @layus
/pkgs/pkgs-lib @infinisil
## Format generators/serializers
/pkgs/pkgs-lib/formats/libconfig @h7x4
/pkgs/pkgs-lib/formats/hocon @h7x4
# Nixpkgs build-support
/pkgs/build-support/writers @lassulus @Profpatsch
# Nixpkgs make-disk-image
/doc/build-helpers/images/makediskimage.section.md @raitobezarius
/nixos/lib/make-disk-image.nix @raitobezarius
# Nix, the package manager
# @raitobezarius is not "code owner", but is listed here to be notified of changes
# pertaining to the Nix package manager.
# i.e. no authority over those files.
pkgs/tools/package-management/nix/ @NixOS/nix-team @raitobezarius
nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobezarius
# Nixpkgs documentation
/maintainers/scripts/db-to-md.sh @jtojnar @ryantm
/maintainers/scripts/doc @jtojnar @ryantm
# Contributor documentation
/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
/doc/development @infinisil
# NixOS Internals
/nixos/default.nix @infinisil
/nixos/lib/from-env.nix @infinisil
/nixos/lib/eval-config.nix @infinisil
/nixos/modules/system/activation/bootspec.nix @grahamc @cole-h @raitobezarius
/nixos/modules/system/activation/bootspec.cue @grahamc @cole-h @raitobezarius
# NixOS integration test driver
/nixos/lib/test-driver @tfc
# NixOS QEMU virtualisation
/nixos/modules/virtualisation/qemu-vm.nix @raitobezarius
# ACME
/nixos/modules/security/acme @NixOS/acme
# Systemd
/nixos/modules/system/boot/systemd.nix @NixOS/systemd
/nixos/modules/system/boot/systemd @NixOS/systemd
/nixos/lib/systemd-*.nix @NixOS/systemd
/pkgs/os-specific/linux/systemd @NixOS/systemd
# Systemd-boot
/nixos/modules/system/boot/loader/systemd-boot @JulienMalka
# Images and installer media
/nixos/modules/profiles/installation-device.nix @ElvishJerricco
/nixos/modules/installer/cd-dvd/ @ElvishJerricco
/nixos/modules/installer/sd-card/
# Amazon
/nixos/modules/virtualisation/amazon-init.nix @arianvp
/nixos/modules/virtualisation/ec2-data.nix @arianvp
/nixos/modules/virtualisation/amazon-options.nix @arianvp
/nixos/modules/virtualisation/amazon-image.nix @arianvp
/nixos/maintainers/scripts/ec2/ @arianvp
/nixos/modules/services/misc/amazon-ssm-agent.nix @arianvp
/nixos/tests/amazon-ssm-agent.nix @arianvp
/nixos/modules/system/boot/grow-partition.nix @arianvp
# Updaters
## update.nix
/maintainers/scripts/update.nix @jtojnar
/maintainers/scripts/update.py @jtojnar
## common-updater-scripts
/pkgs/common-updater/scripts/update-source-version @jtojnar
# Python-related code and docs
/doc/languages-frameworks/python.section.md @mweinelt @natsukium
/maintainers/scripts/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
# Haskell
/doc/languages-frameworks/haskell.section.md @sternenseemann @maralorn
/maintainers/scripts/haskell @sternenseemann @maralorn
/pkgs/development/compilers/ghc @sternenseemann @maralorn
/pkgs/development/haskell-modules @sternenseemann @maralorn
/pkgs/test/haskell @sternenseemann @maralorn
/pkgs/top-level/release-haskell.nix @sternenseemann @maralorn
/pkgs/top-level/haskell-packages.nix @sternenseemann @maralorn
# Perl
/pkgs/development/interpreters/perl @stigtsp @zakame @marcusramberg
/pkgs/top-level/perl-packages.nix @stigtsp @zakame @marcusramberg
/pkgs/development/perl-modules @stigtsp @zakame @marcusramberg
# R
/pkgs/applications/science/math/R @jbedo
/pkgs/development/r-modules @jbedo
# Rust
/pkgs/development/compilers/rust @alyssais @Mic92 @zowoq @winterqt @figsoda
/pkgs/build-support/rust @zowoq @winterqt @figsoda
/doc/languages-frameworks/rust.section.md @zowoq @winterqt @figsoda
# Tcl
/pkgs/development/interpreters/tcl @fgaz
/pkgs/development/libraries/tk @fgaz
/pkgs/top-level/tcl-packages.nix @fgaz
/pkgs/development/tcl-modules @fgaz
/doc/languages-frameworks/tcl.section.md @fgaz
# C compilers
/pkgs/development/compilers/gcc
/pkgs/development/compilers/llvm @alyssais @RossComputerGuy @NixOS/llvm
/pkgs/development/compilers/emscripten @raitobezarius
/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
/pkgs/applications/networking/browsers/firefox @mweinelt
/pkgs/applications/networking/browsers/chromium @emilylange @networkException
/nixos/tests/chromium.nix @emilylange @networkException
# Certificate Authorities
pkgs/data/misc/cacert/ @ajs124 @lukegb @mweinelt
pkgs/development/libraries/nss/ @ajs124 @lukegb @mweinelt
pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
# Java
/doc/languages-frameworks/java.section.md @NixOS/java
/doc/languages-frameworks/gradle.section.md @NixOS/java
/doc/languages-frameworks/maven.section.md @NixOS/java
/pkgs/top-level/java-packages.nix @NixOS/java
# Jetbrains
/pkgs/applications/editors/jetbrains @edwtjo @leona-ya
# Licenses
/lib/licenses.nix @alyssais
# Qt
/pkgs/development/libraries/qt-5 @K900 @NickCao @SuperSandro2000 @ttuegel
/pkgs/development/libraries/qt-6 @K900 @NickCao @SuperSandro2000 @ttuegel
# KDE / Plasma 5
/pkgs/applications/kde @K900 @NickCao @SuperSandro2000 @ttuegel
/pkgs/desktops/plasma-5 @K900 @NickCao @SuperSandro2000 @ttuegel
/pkgs/development/libraries/kde-frameworks @K900 @NickCao @SuperSandro2000 @ttuegel
# KDE / Plasma 6
/pkgs/kde @K900 @NickCao @SuperSandro2000 @ttuegel
/maintainers/scripts/kde @K900 @NickCao @SuperSandro2000 @ttuegel
# PostgreSQL and related stuff
/pkgs/servers/sql/postgresql @NixOS/postgres
/nixos/modules/services/databases/postgresql.md @NixOS/postgres
/nixos/modules/services/databases/postgresql.nix @NixOS/postgres
/nixos/tests/postgresql @NixOS/postgres
# Hardened profile & related modules
/nixos/modules/profiles/hardened.nix @joachifm
/nixos/modules/security/lock-kernel-modules.nix @joachifm
/nixos/modules/security/misc.nix @joachifm
/nixos/tests/hardened.nix @joachifm
/pkgs/os-specific/linux/kernel/hardened/ @fabianhjr @joachifm
# Home Automation
/nixos/modules/services/home-automation/home-assistant.nix @mweinelt
/nixos/modules/services/home-automation/zigbee2mqtt.nix @mweinelt
/nixos/tests/home-assistant.nix @mweinelt
/nixos/tests/zigbee2mqtt.nix @mweinelt
/pkgs/servers/home-assistant @mweinelt
/pkgs/tools/misc/esphome @mweinelt
# Network Time Daemons
/pkgs/by-name/ch/chrony @thoughtpolice
/pkgs/by-name/nt/ntp @thoughtpolice
/pkgs/by-name/op/openntpd @thoughtpolice
/nixos/modules/services/networking/ntp @thoughtpolice
# Network
/pkgs/by-name/ke/kea @mweinelt
/pkgs/by-name/ba/babeld @mweinelt
/nixos/modules/services/networking/babeld.nix @mweinelt
/nixos/modules/services/networking/kea.nix @mweinelt
/nixos/modules/services/networking/knot.nix @mweinelt
/nixos/modules/services/monitoring/prometheus/exporters/kea.nix @mweinelt
/nixos/tests/babeld.nix @mweinelt
/nixos/tests/kea.nix @mweinelt
/nixos/tests/knot.nix @mweinelt
# Web servers
/doc/packages/nginx.section.md @raitobezarius
/pkgs/servers/http/nginx/ @raitobezarius
/nixos/modules/services/web-servers/nginx/ @raitobezarius
# Dhall
/pkgs/development/dhall-modules @Gabriella439 @Profpatsch
/pkgs/development/interpreters/dhall @Gabriella439 @Profpatsch
# Idris
/pkgs/development/idris-modules @Infinisil
/pkgs/development/compilers/idris2 @mattpolzin
# Bazel
/pkgs/development/tools/build-managers/bazel @Profpatsch
# NixOS modules for e-mail and dns services
/nixos/modules/services/mail/mailman.nix @peti
/nixos/modules/services/mail/postfix.nix @peti
/nixos/modules/services/networking/bind.nix @peti
/nixos/modules/services/mail/rspamd.nix @peti
# Emacs
/pkgs/applications/editors/emacs/elisp-packages @NixOS/emacs
/pkgs/applications/editors/emacs @NixOS/emacs
/pkgs/top-level/emacs-packages.nix @NixOS/emacs
/doc/packages/emacs.section.md @NixOS/emacs
/nixos/modules/services/editors/emacs.md @NixOS/emacs
# Kakoune
/pkgs/applications/editors/kakoune @philiptaron
# Neovim
/pkgs/applications/editors/neovim @NixOS/neovim
# VimPlugins
/pkgs/applications/editors/vim/plugins @NixOS/neovim
# VsCode Extensions
/pkgs/applications/editors/vscode/extensions
# PHP interpreter, packages, extensions, tests and documentation
/doc/languages-frameworks/php.section.md @aanderse @drupol @globin @ma27 @talyz
/nixos/tests/php @aanderse @drupol @globin @ma27 @talyz
/pkgs/build-support/php/build-pecl.nix @aanderse @drupol @globin @ma27 @talyz
/pkgs/build-support/php @drupol
/pkgs/development/interpreters/php @jtojnar @aanderse @drupol @globin @ma27 @talyz
/pkgs/development/php-packages @aanderse @drupol @globin @ma27 @talyz
/pkgs/top-level/php-packages.nix @jtojnar @aanderse @drupol @globin @ma27 @talyz
# Docker tools
/pkgs/build-support/docker @roberth
/nixos/tests/docker-tools* @roberth
/doc/build-helpers/images/dockertools.section.md @roberth
# Blockchains
/pkgs/applications/blockchains @mmahut @RaghavSood
# Go
/doc/languages-frameworks/go.section.md @kalbasit @katexochen @Mic92 @zowoq
/pkgs/build-support/go @kalbasit @katexochen @Mic92 @zowoq
/pkgs/development/compilers/go @kalbasit @katexochen @Mic92 @zowoq
# 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
/pkgs/by-name/cj/cjs @mkg20001
/pkgs/by-name/mu/muffin @mkg20001
/pkgs/by-name/ne/nemo @mkg20001
/pkgs/by-name/ne/nemo-* @mkg20001
# Xfce
/doc/hooks/xfce4-dev-tools.section.md @NixOS/xfce
# terraform providers
/pkgs/applications/networking/cluster/terraform-providers @zowoq
# Forgejo
nixos/modules/services/misc/forgejo.nix @adamcstephens @bendlas @emilylange
pkgs/by-name/fo/forgejo/ @adamcstephens @bendlas @emilylange
# Dotnet
/pkgs/build-support/dotnet @corngood
/pkgs/development/compilers/dotnet @corngood
/pkgs/test/dotnet @corngood
/doc/languages-frameworks/dotnet.section.md @corngood
# Node.js
/pkgs/build-support/node/build-npm-package @winterqt
/pkgs/build-support/node/fetch-npm-deps @winterqt
/doc/languages-frameworks/javascript.section.md @winterqt
/pkgs/development/tools/pnpm @Scrumplex @gepbird
# OCaml
/pkgs/build-support/ocaml @ulrikstrid
/pkgs/development/compilers/ocaml @ulrikstrid
/pkgs/development/ocaml-modules @ulrikstrid
# ZFS
/nixos/modules/tasks/filesystems/zfs.nix @adamcstephens @amarshall
/nixos/tests/zfs.nix @adamcstephens @amarshall
/pkgs/os-specific/linux/zfs @adamcstephens @amarshall
/pkgs/os-specific/linux/zfs/2_1.nix @raitobezarius
# Zig
/pkgs/development/compilers/zig @figsoda
/doc/hooks/zig.section.md @figsoda
# Buildbot
nixos/modules/services/continuous-integration/buildbot @Mic92 @zowoq
nixos/tests/buildbot.nix @Mic92 @zowoq
pkgs/development/tools/continuous-integration/buildbot @Mic92 @zowoq
# Pretix
pkgs/by-name/pr/pretix/ @mweinelt
pkgs/by-name/pr/pretalx/ @mweinelt
nixos/modules/services/web-apps/pretix.nix @mweinelt
nixos/modules/services/web-apps/pretalx.nix @mweinelt
nixos/tests/web-apps/pretix.nix @mweinelt
nixos/tests/web-apps/pretalx.nix @mweinelt
# incus/lxc
nixos/maintainers/scripts/incus/ @adamcstephens
nixos/modules/virtualisation/incus.nix @adamcstephens
nixos/modules/virtualisation/lxc* @adamcstephens
nixos/tests/incus/ @adamcstephens
pkgs/by-name/in/incus/ @adamcstephens
pkgs/by-name/lx/lxc* @adamcstephens
# ExpidusOS, Flutter
/pkgs/development/compilers/flutter @RossComputerGuy
/pkgs/desktops/expidus @RossComputerGuy
# GNU Tar & Zip
/pkgs/tools/archivers/gnutar @RossComputerGuy
/pkgs/by-name/zi/zip @RossComputerGuy
# SELinux
/pkgs/by-name/ch/checkpolicy @RossComputerGuy
/pkgs/by-name/li/libselinux @RossComputerGuy
/pkgs/by-name/li/libsepol @RossComputerGuy
# installShellFiles
/pkgs/by-name/in/installShellFiles/* @Ericson2314
/pkgs/test/install-shell-files/* @Ericson2314
/doc/hooks/installShellFiles.section.md @Ericson2314
# Darwin
/pkgs/by-name/ap/apple-sdk @NixOS/darwin-core
/pkgs/os-specific/darwin/apple-source-releases @NixOS/darwin-core
/pkgs/stdenv/darwin @NixOS/darwin-core

View File

@@ -1,52 +0,0 @@
# CI support files
This directory contains files to support CI, such as [GitHub Actions](https://github.com/NixOS/nixpkgs/tree/master/.github/workflows) and [Ofborg](https://github.com/nixos/ofborg).
This is in contrast with [`maintainers/scripts`](../maintainers/scripts) which is for human use instead.
## Pinned Nixpkgs
CI may need certain packages from Nixpkgs.
In order to ensure that the needed packages are generally available without building, [`pinned.json`](./pinned.json) contains a pinned Nixpkgs version tested by Hydra.
Run [`update-pinned.sh`](./update-pinned.sh) to update it.
## `ci/nixpkgs-vet.sh BASE_BRANCH [REPOSITORY]`
Runs the [`nixpkgs-vet` tool](https://github.com/NixOS/nixpkgs-vet) on the HEAD commit, closely matching what CI does.
This can't do exactly the same as CI, because CI needs to rely on GitHub's server-side Git history to compute the mergeability of PRs before the check can be started.
In turn, when contributors are running this tool locally, we don't want to have to push commits to test them, and we can also rely on the local Git history to do the mergeability check.
Arguments:
- `BASE_BRANCH`: The base branch to use, e.g. master or release-24.05
- `REPOSITORY`: The repository from which to fetch the base branch.
Defaults to <https://github.com/NixOS/nixpkgs.git>.
# Branch classification
For the purposes of CI, branches in the NixOS/nixpkgs repository are classified as follows:
- **Channel** branches
- `nixos-` or `nixpkgs-` prefix
- Are only updated from `master` or `release-` branches, when hydra passes.
- Otherwise not worked on, Pull Requests are not allowed.
- Long-lived, no deletion, no force push.
- **Primary development** branches
- `release-` prefix and `master`
- Pull Requests required.
- Long-lived, no deletion, no force push.
- **Secondary development** branches
- `staging-` prefix, `haskell-updates` and `python-updates`
- Pull Requests normally required, except when merging development branches into each other.
- Long-lived, no deletion, no force push.
- **Work-In-Progress** branches
- `backport-`, `revert-` and `wip-` prefixes.
- Deprecated: All other branches, not matched by channel/development.
- Pull Requests are optional.
- Short-lived, force push allowed, deleted after merge.
Some branches also have a version component, which is either `unstable` or `YY.MM`.
`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.

View File

@@ -1,7 +0,0 @@
This report is automatically generated by the `check-cherry-picks` CI workflow.
Some of the commits in this PR have not been cherry-picked exactly and require the author's and reviewer's attention.
Please make sure to follow the [backporting guidelines](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#how-to-backport-pull-requests) and cherry-pick with the `-x` flag. This requires changes to go to the unstable branches (`master` / `staging`) first, before backporting them.
Occasionally, it is not possible to cherry-pick exactly the same patch. This most frequently happens when resolving merge conflicts while cherry-picking or when updating minor versions of packages which have already advanced to the next major on unstable. If you need to merge this PR despite the warnings, please [dismiss](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/dismissing-a-pull-request-review) this review.

View File

@@ -1,152 +0,0 @@
#!/usr/bin/env bash
# Find alleged cherry-picks
set -euo pipefail
if [[ $# != "2" && $# != "3" ]] ; then
echo "usage: check-cherry-picks.sh base_rev head_rev [markdown_file]"
exit 2
fi
markdown_file="$(realpath ${3:-/dev/null})"
[ -v 3 ] && rm -f "$markdown_file"
# Make sure we are inside the nixpkgs repo, even when called from outside
cd "$(dirname "${BASH_SOURCE[0]}")"
PICKABLE_BRANCHES="master staging release-??.?? staging-??.?? haskell-updates python-updates staging-next staging-next-??.??"
problem=0
# Not everyone calls their remote "origin"
remote="$(git remote -v | grep -i 'NixOS/nixpkgs' | head -n1 | cut -f1 || true)"
commits="$(git rev-list --reverse "$1..$2")"
log() {
type="$1"
shift 1
local -A prefix
prefix[success]=" ✔ "
if [ -v GITHUB_ACTIONS ]; then
prefix[warning]="::warning::"
prefix[error]="::error::"
else
prefix[warning]=" ⚠ "
prefix[error]=" ✘ "
fi
echo "${prefix[$type]}$@"
# Only logging errors and warnings, which allows comparing the markdown file
# between pushes to the PR. Even if a new, proper cherry-pick, commit is added
# it won't change the markdown file's content and thus not trigger another comment.
if [ "$type" != "success" ]; then
local -A alert
alert[warning]="WARNING"
alert[error]="CAUTION"
echo >> $markdown_file
echo "> [!${alert[$type]}]" >> $markdown_file
echo "> $@" >> $markdown_file
fi
}
endgroup() {
if [ -v GITHUB_ACTIONS ] ; then
echo ::endgroup::
fi
}
while read -r new_commit_sha ; do
if [ -v GITHUB_ACTIONS ] ; then
echo "::group::Commit $new_commit_sha"
else
echo "================================================="
fi
git rev-list --max-count=1 --format=medium "$new_commit_sha"
echo "-------------------------------------------------"
# Using the last line with "cherry" + hash, because a chained backport
# can result in multiple of those lines. Only the last one counts.
original_commit_sha=$(
git rev-list --max-count=1 --format=format:%B "$new_commit_sha" \
| grep -Ei "cherry.*[0-9a-f]{40}" | tail -n1 \
| grep -Eoi -m1 '[0-9a-f]{40}' || true
)
if [ -z "$original_commit_sha" ] ; then
endgroup
log warning "Couldn't locate original commit hash in message of $new_commit_sha."
problem=1
continue
fi
set -f # prevent pathname expansion of patterns
for pattern in $PICKABLE_BRANCHES ; do
set +f # re-enable pathname expansion
# Reverse sorting by refname and taking one match only means we can only backport
# from unstable and the latest stable. That makes sense, because even right after
# branch-off, when we have two supported stable branches, we only ever want to cherry-pick
# **to** the older one, but never **from** it.
# This makes the job significantly faster in the case when commits can't be found,
# because it doesn't need to iterate through 20+ branches, which all need to be fetched.
branches="$(git for-each-ref --sort=-refname --format="%(refname)" \
"refs/remotes/${remote:-origin}/$pattern" | head -n1)"
while read -r picked_branch ; do
if git merge-base --is-ancestor "$original_commit_sha" "$picked_branch" ; then
range_diff_common='git --no-pager range-diff
--no-notes
--creation-factor=100
'"$original_commit_sha~..$original_commit_sha"'
'"$new_commit_sha~..$new_commit_sha"'
'
if $range_diff_common --no-color 2> /dev/null | grep -E '^ {4}[+-]{2}' > /dev/null ; then
log success "$original_commit_sha present in branch $picked_branch"
endgroup
log warning "Difference between $new_commit_sha and original $original_commit_sha may warrant inspection."
# First line contains commit SHAs, which we already printed.
$range_diff_common --color | tail -n +2
echo -e "> <details><summary>Show diff</summary>\n>" >> $markdown_file
echo '> ```diff' >> $markdown_file
# The output of `git range-diff` is indented with 4 spaces, which we need to match with the
# code blocks indent to get proper syntax highlighting on GitHub.
diff="$($range_diff_common | tail -n +2 | sed -Ee 's/^ {4}/> /g')"
# Also limit the output to 10k bytes (and remove the last, potentially incomplete line), because
# GitHub comments are limited in length. The value of 10k is arbitrary with the assumption, that
# after the range-diff becomes a certain size, a reviewer is better off reviewing the regular diff
# in GitHub's UI anyway, thus treating the commit as "new" and not cherry-picked.
# Note: This could still lead to a too lengthy comment with multiple commits touching the limit. We
# consider this too unlikely to happen, to deal with explicitly.
max_length=10000
if [ "${#diff}" -gt $max_length ]; then
printf -v diff "%s\n>\n> [...truncated...]" "$(echo "$diff" | head -c $max_length | head -n-1)"
fi
echo "$diff" >> $markdown_file
echo '> ```' >> $markdown_file
echo "> </details>" >> $markdown_file
problem=1
else
log success "$original_commit_sha present in branch $picked_branch"
log success "$original_commit_sha highly similar to $new_commit_sha"
$range_diff_common --color
endgroup
fi
# move on to next commit
continue 3
fi
done <<< "$branches"
done
endgroup
log error "$original_commit_sha given in $new_commit_sha not found in any pickable branch."
problem=1
done <<< "$commits"
exit $problem

View File

@@ -1,31 +0,0 @@
{
buildGoModule,
fetchFromGitHub,
fetchpatch,
}:
buildGoModule {
name = "codeowners-validator";
src = fetchFromGitHub {
owner = "mszostok";
repo = "codeowners-validator";
rev = "f3651e3810802a37bd965e6a9a7210728179d076";
hash = "sha256-5aSmmRTsOuPcVLWfDF6EBz+6+/Qpbj66udAmi1CLmWQ=";
};
patches = [
# https://github.com/mszostok/codeowners-validator/pull/222
(fetchpatch {
name = "user-write-access-check";
url = "https://github.com/mszostok/codeowners-validator/compare/f3651e3810802a37bd965e6a9a7210728179d076...840eeb88b4da92bda3e13c838f67f6540b9e8529.patch";
hash = "sha256-t3Dtt8SP9nbO3gBrM0nRE7+G6N/ZIaczDyVHYAG/6mU=";
})
# Undoes part of the above PR: We don't want to require write access
# to the repository, that's only needed for GitHub's native CODEOWNERS.
# Furthermore, it removes an unnecessary check from the code
# that breaks tokens generated for GitHub Apps.
./permissions.patch
# Allows setting a custom CODEOWNERS path using the OWNERS_FILE env var
./owners-file-name.patch
];
postPatch = "rm -r docs/investigation";
vendorHash = "sha256-R+pW3xcfpkTRqfS2ETVOwG8PZr0iH5ewroiF7u8hcYI=";
}

View File

@@ -1,15 +0,0 @@
diff --git a/pkg/codeowners/owners.go b/pkg/codeowners/owners.go
index 6910bd2..e0c95e9 100644
--- a/pkg/codeowners/owners.go
+++ b/pkg/codeowners/owners.go
@@ -39,6 +39,10 @@ func NewFromPath(repoPath string) ([]Entry, error) {
// openCodeownersFile finds a CODEOWNERS file and returns content.
// see: https://help.github.com/articles/about-code-owners/#codeowners-file-location
func openCodeownersFile(dir string) (io.Reader, error) {
+ if file, ok := os.LookupEnv("OWNERS_FILE"); ok {
+ return fs.Open(file)
+ }
+
var detectedFiles []string
for _, p := range []string{".", "docs", ".github"} {
pth := path.Join(dir, p)

View File

@@ -1,36 +0,0 @@
diff --git a/internal/check/valid_owner.go b/internal/check/valid_owner.go
index a264bcc..610eda8 100644
--- a/internal/check/valid_owner.go
+++ b/internal/check/valid_owner.go
@@ -16,7 +16,6 @@ import (
const scopeHeader = "X-OAuth-Scopes"
var reqScopes = map[github.Scope]struct{}{
- github.ScopeReadOrg: {},
}
type ValidOwnerConfig struct {
@@ -223,10 +222,7 @@ func (v *ValidOwner) validateTeam(ctx context.Context, name string) *validateErr
for _, t := range v.repoTeams {
// GitHub normalizes name before comparison
if strings.EqualFold(t.GetSlug(), team) {
- if t.Permissions["push"] {
- return nil
- }
- return newValidateError("Team %q cannot review PRs on %q as neither it nor any parent team has write permissions.", team, v.orgRepoName)
+ return nil
}
}
@@ -245,10 +241,7 @@ func (v *ValidOwner) validateGitHubUser(ctx context.Context, name string) *valid
for _, u := range v.repoUsers {
// GitHub normalizes name before comparison
if strings.EqualFold(u.GetLogin(), userName) {
- if u.Permissions["push"] {
- return nil
- }
- return newValidateError("User %q cannot review PRs on %q as they don't have write permissions.", userName, v.orgRepoName)
+ return nil
}
}

View File

@@ -1,114 +0,0 @@
let
pinned = (builtins.fromJSON (builtins.readFile ./pinned.json)).pins;
in
{
system ? builtins.currentSystem,
nixpkgs ? null,
}:
let
nixpkgs' =
if nixpkgs == null then
fetchTarball {
inherit (pinned.nixpkgs) url;
sha256 = pinned.nixpkgs.hash;
}
else
nixpkgs;
pkgs = import nixpkgs' {
inherit system;
config = { };
overlays = [ ];
};
fmt =
let
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.keep-sorted.enable = true;
# This uses nixfmt-rfc-style underneath,
# the default formatter for Nix code.
# See https://github.com/NixOS/nixfmt
programs.nixfmt.enable = true;
programs.yamlfmt = {
enable = true;
settings.formatter = {
retain_line_breaks = true;
};
};
settings.formatter.yamlfmt.excludes = [
# Breaks helm templating
"nixos/tests/k3s/k3s-test-chart/templates/*"
# 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"
];
settings.formatter.editorconfig-checker = {
command = "${pkgs.lib.getExe pkgs.editorconfig-checker}";
options = [ "-disable-indent-size" ];
includes = [ "*" ];
priority = 1;
};
};
fs = pkgs.lib.fileset;
nixFilesSrc = fs.toSource {
root = ../.;
fileset = fs.difference ../. (fs.maybeMissing ../.git);
};
in
{
shell = treefmtEval.config.build.devShell;
pkg = treefmtEval.config.build.wrapper;
check = treefmtEval.config.build.check nixFilesSrc;
};
in
{
inherit pkgs fmt;
requestReviews = pkgs.callPackage ./request-reviews { };
codeownersValidator = pkgs.callPackage ./codeowners-validator { };
# FIXME(lf-): it might be useful to test other Nix implementations
# (nixVersions.stable and Lix) here somehow at some point to ensure we don't
# have eval divergence.
eval = pkgs.callPackage ./eval {
nix = pkgs.nixVersions.latest;
};
# 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 { });
manual-nixpkgs-tests = (import ../doc { }).tests;
nixpkgs-vet = pkgs.callPackage ./nixpkgs-vet.nix { };
parse = pkgs.lib.recurseIntoAttrs {
latest = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.latest; };
lix = pkgs.callPackage ./parse.nix { nix = pkgs.lix; };
minimum = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.minimum; };
};
shell = import ../shell.nix { inherit nixpkgs system; };
}

View File

@@ -1,26 +0,0 @@
# Nixpkgs CI evaluation
The code in this directory is used by the [eval.yml](../../.github/workflows/eval.yml) GitHub Actions workflow to evaluate the majority of Nixpkgs for all PRs, effectively making sure that when the development branches are processed by Hydra, no evaluation failures are encountered.
Furthermore it also allows local evaluation using
```
nix-build ci -A eval.full \
--max-jobs 4 \
--cores 2 \
--arg chunkSize 10000 \
--arg evalSystems '["x86_64-linux" "aarch64-darwin"]'
```
- `--max-jobs`: The maximum number of derivations to run at the same time.
Only each [supported system](../supportedSystems.json) gets a separate derivation, so it doesn't make sense to set this higher than that number.
- `--cores`: The number of cores to use for each job.
Recommended to set this to the amount of cores on your system divided by `--max-jobs`.
- `chunkSize`: The number of attributes that are evaluated simultaneously on a single core.
Lowering this decreases memory usage at the cost of increased evaluation time.
If this is too high, there won't be enough chunks to process them in parallel, and will also increase evaluation time.
- `evalSystems`: The set of systems for which `nixpkgs` should be evaluated.
Defaults to the four official platforms (`x86_64-linux`, `aarch64-linux`, `x86_64-darwin` and `aarch64-darwin`).
A good default is to set `chunkSize` to 10000, which leads to about 3.6GB max memory usage per core, so suitable for fully utilising machines with 4 cores and 16GB memory, 8 cores and 32GB memory or 16 cores and 64GB memory.
Note that 16GB memory is the recommended minimum, while with less than 8GB memory evaluation time suffers greatly.

View File

@@ -1,154 +0,0 @@
import json
import os
from scipy.stats import ttest_rel
import pandas as pd
import numpy as np
from pathlib import Path
# Define metrics of interest (can be expanded as needed)
METRIC_PREFIXES = ("nr", "gc")
def flatten_data(json_data: dict) -> dict:
"""
Extracts and flattens metrics from JSON data.
This is needed because the JSON data can be nested.
For example, the JSON data entry might look like this:
"gc":{"cycles":13,"heapSize":5404549120,"totalBytes":9545876464}
Flattened:
"gc.cycles": 13
"gc.heapSize": 5404549120
...
Args:
json_data (dict): JSON data containing metrics.
Returns:
dict: Flattened metrics with keys as metric names.
"""
flat_metrics = {}
for k, v in json_data.items():
if isinstance(v, (int, float)):
flat_metrics[k] = v
elif isinstance(v, dict):
for sub_k, sub_v in v.items():
flat_metrics[f"{k}.{sub_k}"] = sub_v
return flat_metrics
def load_all_metrics(directory: Path) -> dict:
"""
Loads all stats JSON files in the specified directory and extracts metrics.
Args:
directory (Path): Directory containing JSON files.
Returns:
dict: Dictionary with filenames as keys and extracted metrics as values.
"""
metrics = {}
for system_dir in directory.iterdir():
assert system_dir.is_dir()
for chunk_output in system_dir.iterdir():
with chunk_output.open() as f:
data = json.load(f)
metrics[f"{system_dir.name}/${chunk_output.name}"] = flatten_data(data)
return metrics
def dataframe_to_markdown(df: pd.DataFrame) -> str:
df = df.sort_values(by=df.columns[0], ascending=True)
markdown_lines = []
# Header (get column names and format them)
header = '\n| ' + ' | '.join(df.columns) + ' |'
markdown_lines.append(header)
markdown_lines.append("| - " * (len(df.columns)) + "|") # Separator line
# Iterate over rows to build Markdown rows
for _, row in df.iterrows():
# TODO: define threshold for highlighting
highlight = False
fmt = lambda x: f"**{x}**" if highlight else f"{x}"
# Check for no change and NaN in p_value/t_stat
row_values = []
for val in row:
if isinstance(val, float) and np.isnan(val): # For NaN values in p-value or t-stat
row_values.append("-") # Custom symbol for NaN
elif isinstance(val, float) and val == 0: # For no change (mean_diff == 0)
row_values.append("-") # Custom symbol for no change
else:
row_values.append(fmt(f"{val:.4f}" if isinstance(val, float) else str(val)))
markdown_lines.append('| ' + ' | '.join(row_values) + ' |')
return '\n'.join(markdown_lines)
def perform_pairwise_tests(before_metrics: dict, after_metrics: dict) -> pd.DataFrame:
common_files = sorted(set(before_metrics) & set(after_metrics))
all_keys = sorted({ metric_keys for file_metrics in before_metrics.values() for metric_keys in file_metrics.keys() })
results = []
for key in all_keys:
before_vals, after_vals = [], []
for fname in common_files:
if key in before_metrics[fname] and key in after_metrics[fname]:
before_vals.append(before_metrics[fname][key])
after_vals.append(after_metrics[fname][key])
if len(before_vals) >= 2:
before_arr = np.array(before_vals)
after_arr = np.array(after_vals)
diff = after_arr - before_arr
pct_change = 100 * diff / before_arr
t_stat, p_val = ttest_rel(after_arr, before_arr)
results.append({
"metric": key,
"mean_before": np.mean(before_arr),
"mean_after": np.mean(after_arr),
"mean_diff": np.mean(diff),
"mean_%_change": np.mean(pct_change),
"p_value": p_val,
"t_stat": t_stat
})
df = pd.DataFrame(results).sort_values("p_value")
return df
if __name__ == "__main__":
before_dir = os.environ.get("BEFORE_DIR")
after_dir = os.environ.get("AFTER_DIR")
if not before_dir or not after_dir:
print("Error: Environment variables 'BEFORE_DIR' and 'AFTER_DIR' must be set.")
exit(1)
before_stats = Path(before_dir) / "stats"
after_stats = Path(after_dir) / "stats"
# This may happen if the pull request target does not include PR#399720 yet.
if not before_stats.exists():
print("⚠️ Skipping comparison: stats directory is missing in the target commit.")
exit(0)
# This should never happen, but we're exiting gracefully anyways
if not after_stats.exists():
print("⚠️ Skipping comparison: stats directory missing in current PR evaluation.")
exit(0)
before_metrics = load_all_metrics(before_stats)
after_metrics = load_all_metrics(after_stats)
df1 = perform_pairwise_tests(before_metrics, after_metrics)
markdown_table = dataframe_to_markdown(df1)
print(markdown_table)

View File

@@ -1,186 +0,0 @@
{
callPackage,
lib,
jq,
runCommand,
writeText,
python3,
}:
{
combinedDir,
touchedFilesJson,
githubAuthorId,
byName ? false,
}:
let
/*
Derivation that computes which packages are affected (added, changed or removed) between two revisions of nixpkgs.
Note: "platforms" are "x86_64-linux", "aarch64-darwin", ...
---
Inputs:
- beforeDir, afterDir: The evaluation result from before and after the change.
They can be obtained by running `nix-build -A ci.eval.full` on both revisions.
---
Outputs:
- changed-paths.json: Various information about the changes:
{
attrdiff: {
added: ["package1"],
changed: ["package2", "package3"],
removed: ["package4"],
},
labels: {
"10.rebuild-darwin: 1-10": true,
"10.rebuild-linux: 1-10": true
},
rebuildsByKernel: {
darwin: ["package1", "package2"],
linux: ["package1", "package2", "package3"]
},
rebuildCountByKernel: {
darwin: 2,
linux: 3,
},
rebuildsByPlatform: {
aarch64-darwin: ["package1", "package2"],
aarch64-linux: ["package1", "package2"],
x86_64-linux: ["package1", "package2", "package3"],
x86_64-darwin: ["package1"],
},
}
- step-summary.md: A markdown render of the changes
---
Implementation details:
Helper functions can be found in ./utils.nix.
Two main "types" are important:
- `packagePlatformPath`: A string of the form "<PACKAGE_PATH>.<PLATFORM>"
Example: "python312Packages.numpy.x86_64-linux"
- `packagePlatformAttr`: An attrs representation of a packagePlatformPath:
Example: { name = "python312Packages.numpy"; platform = "x86_64-linux"; }
*/
inherit (import ./utils.nix { inherit lib; })
groupByKernel
convertToPackagePlatformAttrs
groupByPlatform
extractPackageNames
getLabels
;
# Attrs
# - keys: "added", "changed" and "removed"
# - values: lists of `packagePlatformPath`s
diffAttrs = builtins.fromJSON (builtins.readFile "${combinedDir}/combined-diff.json");
rebuilds = diffAttrs.added ++ diffAttrs.changed;
rebuildsPackagePlatformAttrs = convertToPackagePlatformAttrs rebuilds;
changed-paths =
let
rebuildsByPlatform = groupByPlatform rebuildsPackagePlatformAttrs;
rebuildsByKernel = groupByKernel rebuildsPackagePlatformAttrs;
rebuildCountByKernel = lib.mapAttrs (
kernel: kernelRebuilds: lib.length kernelRebuilds
) rebuildsByKernel;
in
writeText "changed-paths.json" (
builtins.toJSON {
attrdiff = lib.mapAttrs (_: extractPackageNames) diffAttrs;
inherit
rebuildsByPlatform
rebuildsByKernel
rebuildCountByKernel
;
labels =
getLabels rebuildCountByKernel
# Sets "10.rebuild-*-stdenv" label to whether the "stdenv" attribute was changed.
// lib.mapAttrs' (
kernel: rebuilds: lib.nameValuePair "10.rebuild-${kernel}-stdenv" (lib.elem "stdenv" rebuilds)
) rebuildsByKernel
# Set the "11.by: package-maintainer" label to whether all packages directly
# changed are maintained by the PR's author.
# (https://github.com/NixOS/ofborg/blob/df400f44502d4a4a80fa283d33f2e55a4e43ee90/ofborg/src/tagger.rs#L83-L88)
// {
"11.by: package-maintainer" =
maintainers ? ${githubAuthorId}
&& lib.all (lib.flip lib.elem maintainers.${githubAuthorId}) (
lib.flatten (lib.attrValues maintainers)
);
};
}
);
maintainers = callPackage ./maintainers.nix { } {
changedattrs = lib.attrNames (lib.groupBy (a: a.name) rebuildsPackagePlatformAttrs);
changedpathsjson = touchedFilesJson;
inherit byName;
};
in
runCommand "compare"
{
nativeBuildInputs = [
jq
(python3.withPackages (
ps: with ps; [
numpy
pandas
scipy
]
))
];
maintainers = builtins.toJSON maintainers;
passAsFile = [ "maintainers" ];
env = {
BEFORE_DIR = "${combinedDir}/before";
AFTER_DIR = "${combinedDir}/after";
};
}
''
mkdir $out
cp ${changed-paths} $out/changed-paths.json
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
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
python3 ${./cmp-stats.py} >> $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
echo "# Packages"
echo
jq -r -f ${./generate-step-summary.jq} < ${changed-paths}
} >> $out/step-summary.md
cp "$maintainersPath" "$out/maintainers.json"
''

View File

@@ -1,30 +0,0 @@
def truncate(xs; n):
if xs | length > n then xs[:n] + ["..."]
else xs
end;
def itemize_packages(xs):
truncate(xs; 2000) |
map("- [\(.)](https://search.nixos.org/packages?channel=unstable&show=\(.)&from=0&size=50&sort=relevance&type=packages&query=\(.))") |
join("\n");
def get_title(s; xs):
s + " (" + (xs | length | tostring) + ")";
def section(title; xs):
"<details> <summary>" + get_title(title; xs) + "</summary>\n\n" + itemize_packages(xs) + "</details>";
def fallback_document(content; n):
if content | utf8bytelength > n then
get_title("Added packages"; .attrdiff.added) + "\n\n" +
get_title("Removed packages"; .attrdiff.removed) + "\n\n" +
get_title("Changed packages"; .attrdiff.changed)
else content
end;
# we truncate the list to stay below the GitHub limit of 1MB per step summary.
fallback_document(
section("Added packages"; .attrdiff.added) + "\n\n" +
section("Removed packages"; .attrdiff.removed) + "\n\n" +
section("Changed packages"; .attrdiff.changed); 1000 * 1000
)

View File

@@ -1,113 +0,0 @@
{
lib,
}:
# Almost directly vendored from https://github.com/NixOS/ofborg/blob/5a4e743f192fb151915fcbe8789922fa401ecf48/ofborg/src/maintainers.nix
{
changedattrs,
changedpathsjson,
byName ? false,
}:
let
pkgs = import ../../.. {
system = "x86_64-linux";
config = { };
overlays = [ ];
};
changedpaths = builtins.fromJSON (builtins.readFile changedpathsjson);
anyMatchingFile =
filename: builtins.any (changed: lib.strings.hasSuffix changed filename) changedpaths;
anyMatchingFiles = files: builtins.any anyMatchingFile files;
enrichedAttrs = builtins.map (name: {
path = lib.splitString "." name;
name = name;
}) changedattrs;
validPackageAttributes = builtins.filter (
pkg:
if (lib.attrsets.hasAttrByPath pkg.path pkgs) then
(
let
value = lib.attrsets.attrByPath pkg.path null pkgs;
in
if (builtins.tryEval value).success then
if value != null then true else builtins.trace "${pkg.name} exists but is null" false
else
builtins.trace "Failed to access ${pkg.name} even though it exists" false
)
else
builtins.trace "Failed to locate ${pkg.name}." false
) enrichedAttrs;
attrsWithPackages = builtins.map (
pkg: pkg // { package = lib.attrsets.attrByPath pkg.path null pkgs; }
) validPackageAttributes;
attrsWithMaintainers = builtins.map (
pkg:
let
meta = pkg.package.meta or { };
in
pkg
// {
# TODO: Refactor this so we can ping entire teams instead of the individual members.
# Note that this will require keeping track of GH team IDs in "maintainers/teams.nix".
maintainers = meta.maintainers or [ ];
}
) attrsWithPackages;
relevantFilenames =
drv:
(lib.lists.unique (
builtins.map (pos: lib.strings.removePrefix (toString ../..) pos.file) (
builtins.filter (x: x != null) [
(builtins.unsafeGetAttrPos "maintainers" (drv.meta or { }))
(builtins.unsafeGetAttrPos "src" drv)
# broken because name is always set by stdenv:
# # A hack to make `nix-env -qa` and `nix search` ignore broken packages.
# # TODO(@oxij): remove this assert when something like NixOS/nix#1771 gets merged into nix.
# name = assert validity.handled; name + lib.optionalString
#(builtins.unsafeGetAttrPos "name" drv)
(builtins.unsafeGetAttrPos "pname" drv)
(builtins.unsafeGetAttrPos "version" drv)
# Use ".meta.position" for cases when most of the package is
# defined in a "common" section and the only place where
# reference to the file with a derivation the "pos"
# attribute.
#
# ".meta.position" has the following form:
# "pkgs/tools/package-management/nix/default.nix:155"
# We transform it to the following:
# { file = "pkgs/tools/package-management/nix/default.nix"; }
{ file = lib.head (lib.splitString ":" (drv.meta.position or "")); }
]
)
));
attrsWithFilenames = builtins.map (
pkg: pkg // { filenames = relevantFilenames pkg.package; }
) attrsWithMaintainers;
attrsWithModifiedFiles = builtins.filter (pkg: anyMatchingFiles pkg.filenames) attrsWithFilenames;
listToPing = lib.concatMap (
pkg:
builtins.map (maintainer: {
id = maintainer.githubId;
inherit (maintainer) github;
packageName = pkg.name;
dueToFiles = pkg.filenames;
}) pkg.maintainers
) attrsWithModifiedFiles;
byMaintainer = lib.groupBy (ping: toString ping.${if byName then "github" else "id"}) listToPing;
packagesPerMaintainer = lib.attrsets.mapAttrs (
maintainer: packages: builtins.map (pkg: pkg.packageName) packages
) byMaintainer;
in
packagesPerMaintainer

View File

@@ -1,195 +0,0 @@
{ lib, ... }:
rec {
# Borrowed from https://github.com/NixOS/nixpkgs/pull/355616
uniqueStrings = list: builtins.attrNames (builtins.groupBy lib.id list);
/*
Converts a `packagePlatformPath` into a `packagePlatformAttr`
Turns
"hello.aarch64-linux"
into
{
name = "hello";
packagePath = [ "hello" ];
platform = "aarch64-linux";
}
*/
convertToPackagePlatformAttr =
packagePlatformPath:
let
# python312Packages.numpy.aarch64-linux -> ["python312Packages" "numpy" "aarch64-linux"]
splittedPath = lib.splitString "." packagePlatformPath;
# ["python312Packages" "numpy" "aarch64-linux"] -> ["python312Packages" "numpy"]
packagePath = lib.sublist 0 (lib.length splittedPath - 1) splittedPath;
# "python312Packages.numpy"
name = lib.concatStringsSep "." packagePath;
in
if name == "" then
null
else
{
# [ "python312Packages" "numpy" ]
inherit packagePath;
# python312Packages.numpy
inherit name;
# "aarch64-linux"
platform = lib.last splittedPath;
};
/*
Converts a list of `packagePlatformPath`s into a list of `packagePlatformAttr`s
Turns
[
"hello.aarch64-linux"
"hello.x86_64-linux"
"hello.aarch64-darwin"
"hello.x86_64-darwin"
"bye.x86_64-darwin"
"bye.aarch64-darwin"
"release-checks" <- Will be dropped
]
into
[
{ name = "hello"; platform = "aarch64-linux"; packagePath = [ "hello" ]; }
{ name = "hello"; platform = "x86_64-linux"; packagePath = [ "hello" ]; }
{ name = "hello"; platform = "aarch64-darwin"; packagePath = [ "hello" ]; }
{ name = "hello"; platform = "x86_64-darwin"; packagePath = [ "hello" ]; }
{ name = "bye"; platform = "aarch64-darwin"; packagePath = [ "hello" ]; }
{ name = "bye"; platform = "x86_64-darwin"; packagePath = [ "hello" ]; }
]
*/
convertToPackagePlatformAttrs =
packagePlatformPaths:
builtins.filter (x: x != null) (builtins.map convertToPackagePlatformAttr packagePlatformPaths);
/*
Converts a list of `packagePlatformPath`s directly to a list of (unique) package names
Turns
[
"hello.aarch64-linux"
"hello.x86_64-linux"
"hello.aarch64-darwin"
"hello.x86_64-darwin"
"bye.x86_64-darwin"
"bye.aarch64-darwin"
]
into
[
"hello"
"bye"
]
*/
extractPackageNames =
packagePlatformPaths:
let
packagePlatformAttrs = convertToPackagePlatformAttrs (uniqueStrings packagePlatformPaths);
in
uniqueStrings (builtins.map (p: p.name) packagePlatformAttrs);
/*
Group a list of `packagePlatformAttr`s by platforms
Turns
[
{ name = "hello"; platform = "aarch64-linux"; ... }
{ name = "hello"; platform = "x86_64-linux"; ... }
{ name = "hello"; platform = "aarch64-darwin"; ... }
{ name = "hello"; platform = "x86_64-darwin"; ... }
{ name = "bye"; platform = "aarch64-darwin"; ... }
{ name = "bye"; platform = "x86_64-darwin"; ... }
]
into
{
aarch64-linux = [ "hello" ];
x86_64-linux = [ "hello" ];
aarch64-darwin = [ "hello" "bye" ];
x86_64-darwin = [ "hello" "bye" ];
}
*/
groupByPlatform =
packagePlatformAttrs:
let
packagePlatformAttrsByPlatform = builtins.groupBy (p: p.platform) packagePlatformAttrs;
extractPackageNames = map (p: p.name);
in
lib.mapAttrs (_: extractPackageNames) packagePlatformAttrsByPlatform;
# Turns
# [
# { name = "hello"; platform = "aarch64-linux"; ... }
# { name = "hello"; platform = "x86_64-linux"; ... }
# { name = "hello"; platform = "aarch64-darwin"; ... }
# { name = "hello"; platform = "x86_64-darwin"; ... }
# { name = "bye"; platform = "aarch64-darwin"; ... }
# { name = "bye"; platform = "x86_64-darwin"; ... }
# ]
#
# into
#
# {
# linux = [ "hello" ];
# darwin = [ "hello" "bye" ];
# }
groupByKernel =
packagePlatformAttrs:
let
filterKernel =
kernel:
builtins.attrNames (
builtins.groupBy (p: p.name) (
builtins.filter (p: lib.hasSuffix kernel p.platform) packagePlatformAttrs
)
);
in
lib.genAttrs [ "linux" "darwin" ] filterKernel;
/*
Maps an attrs of `kernel - rebuild counts` mappings to an attrs of labels
Turns
{
linux = 56;
darwin = 1;
}
into
{
"10.rebuild-darwin: 1" = true;
"10.rebuild-darwin: 1-10" = true;
"10.rebuild-darwin: 11-100" = false;
# [...]
"10.rebuild-darwin: 1" = false;
"10.rebuild-darwin: 1-10" = false;
"10.rebuild-linux: 11-100" = true;
# [...]
}
*/
getLabels =
rebuildCountByKernel:
lib.mergeAttrsList (
lib.mapAttrsToList (
kernel: rebuildCount:
let
range = from: to: from <= rebuildCount && (to == null || rebuildCount <= to);
in
lib.mapAttrs' (number: lib.nameValuePair "10.rebuild-${kernel}: ${number}") {
"0" = range 0 0;
"1" = range 1 1;
"1-10" = range 1 10;
"11-100" = range 11 100;
"101-500" = range 101 500;
"501-1000" = range 501 1000;
"501+" = range 501 null;
"1001-2500" = range 1001 2500;
"2501-5000" = range 2501 5000;
"5001+" = range 5001 null;
}
) rebuildCountByKernel
);
}

View File

@@ -1,282 +0,0 @@
# Evaluates all the accessible paths in nixpkgs.
# *This only builds on Linux* since it requires the Linux sandbox isolation to
# be able to write in various places while evaluating inside the sandbox.
#
# This file is used by nixpkgs CI (see .github/workflows/eval.yml) as well as
# being used directly as an entry point in Lix's CI (in `flake.nix` in the Lix
# repo).
#
# If you know you are doing a breaking API change, please ping the nixpkgs CI
# maintainers and the Lix maintainers (`nix eval -f . lib.teams.lix`).
{
callPackage,
lib,
runCommand,
writeShellScript,
symlinkJoin,
time,
procps,
nix,
jq,
}:
let
nixpkgs =
with lib.fileset;
toSource {
root = ../..;
fileset = unions (
map (lib.path.append ../..) [
"default.nix"
"doc"
"lib"
"maintainers"
"nixos"
"pkgs"
".version"
"ci/supportedSystems.json"
]
);
};
supportedSystems = builtins.fromJSON (builtins.readFile ../supportedSystems.json);
attrpathsSuperset =
{
evalSystem,
}:
runCommand "attrpaths-superset.json"
{
src = nixpkgs;
nativeBuildInputs = [
nix
time
];
}
''
export NIX_STATE_DIR=$(mktemp -d)
mkdir $out
export GC_INITIAL_HEAP_SIZE=4g
command time -f "Attribute eval done [%MKB max resident, %Es elapsed] %C" \
nix-instantiate --eval --strict --json --show-trace \
"$src/pkgs/top-level/release-attrpaths-superset.nix" \
-A paths \
-I "$src" \
--option restrict-eval true \
--option allow-import-from-derivation false \
--option eval-system "${evalSystem}" \
--arg enableWarnings false > $out/paths.json
'';
singleSystem =
{
# The system to evaluate.
# Note that this is intentionally not called `system`,
# because `--argstr system` would only be passed to the ci/default.nix file!
evalSystem,
# The path to the `paths.json` file from `attrpathsSuperset`
attrpathFile ? "${attrpathsSuperset { inherit evalSystem; }}/paths.json",
# The number of attributes per chunk, see ./README.md for more info.
chunkSize,
checkMeta ? true,
# Don't try to eval packages marked as broken.
includeBroken ? false,
# Whether to just evaluate a single chunk for quick testing
quickTest ? false,
}:
let
singleChunk = writeShellScript "single-chunk" ''
set -euo pipefail
chunkSize=$1
myChunk=$2
system=$3
outputDir=$4
export NIX_SHOW_STATS=1
export NIX_SHOW_STATS_PATH="$outputDir/stats/$myChunk"
echo "Chunk $myChunk on $system start"
set +e
command time -o "$outputDir/timestats/$myChunk" \
-f "Chunk $myChunk on $system done [%MKB max resident, %Es elapsed] %C" \
nix-env -f "${nixpkgs}/pkgs/top-level/release-attrpaths-parallel.nix" \
--eval-system "$system" \
--option restrict-eval true \
--option allow-import-from-derivation false \
--query --available \
--out-path --json \
--show-trace \
--arg chunkSize "$chunkSize" \
--arg myChunk "$myChunk" \
--arg attrpathFile "${attrpathFile}" \
--arg systems "[ \"$system\" ]" \
--arg checkMeta ${lib.boolToString checkMeta} \
--arg includeBroken ${lib.boolToString includeBroken} \
-I ${nixpkgs} \
-I ${attrpathFile} \
> "$outputDir/result/$myChunk" \
2> "$outputDir/stderr/$myChunk"
exitCode=$?
set -e
cat "$outputDir/stderr/$myChunk"
cat "$outputDir/timestats/$myChunk"
if (( exitCode != 0 )); then
echo "Evaluation failed with exit code $exitCode"
# This immediately halts all xargs processes
kill $PPID
elif [[ -s "$outputDir/stderr/$myChunk" ]]; then
echo "Nixpkgs on $system evaluated with warnings, aborting"
kill $PPID
fi
'';
in
runCommand "nixpkgs-eval-${evalSystem}"
{
nativeBuildInputs = [
nix
time
procps
jq
];
env = {
inherit evalSystem chunkSize;
};
}
''
export NIX_STATE_DIR=$(mktemp -d)
nix-store --init
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}
# Record and print stats on free memory and swap in the background
(
while true; do
availMemory=$(free -b | grep Mem | awk '{print $7}')
freeSwap=$(free -b | grep Swap | awk '{print $4}')
echo "Available memory: $(( availMemory / 1024 / 1024 )) MiB, free swap: $(( freeSwap / 1024 / 1024 )) MiB"
if [[ ! -f "$out/${evalSystem}/min-avail-memory" ]] || (( availMemory < $(<$out/${evalSystem}/min-avail-memory) )); then
echo "$availMemory" > $out/${evalSystem}/min-avail-memory
fi
if [[ ! -f $out/${evalSystem}/min-free-swap ]] || (( availMemory < $(<$out/${evalSystem}/min-free-swap) )); then
echo "$freeSwap" > $out/${evalSystem}/min-free-swap
fi
sleep 4
done
) &
seq_end=$(( chunkCount - 1 ))
${lib.optionalString quickTest ''
seq_end=0
''}
chunkOutputDir=$(mktemp -d)
mkdir "$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"
cp -r "$chunkOutputDir"/stats $out/${evalSystem}/stats-by-chunk
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 "$chunkOutputDir"/result/* | jq -s 'add | map_values(.outputs)' > $out/${evalSystem}/paths.json
'';
diff = callPackage ./diff.nix { };
combine =
{
diffDir,
}:
runCommand "combined-eval"
{
nativeBuildInputs = [
jq
];
}
''
mkdir -p $out
# Combine output paths from all systems
cat ${diffDir}/*/diff.json | jq -s '
reduce .[] as $item ({}; {
added: (.added + $item.added),
changed: (.changed + $item.changed),
removed: (.removed + $item.removed)
})
' > $out/combined-diff.json
mkdir -p $out/before/stats
for d in ${diffDir}/before/*; do
cp -r "$d"/stats-by-chunk $out/before/stats/$(basename "$d")
done
mkdir -p $out/after/stats
for d in ${diffDir}/after/*; do
cp -r "$d"/stats-by-chunk $out/after/stats/$(basename "$d")
done
'';
compare = callPackage ./compare { };
full =
{
# Whether to evaluate on a specific set of systems, by default all are evaluated
evalSystems ? if quickTest then [ "x86_64-linux" ] else supportedSystems,
# The number of attributes per chunk, see ./README.md for more info.
chunkSize,
quickTest ? false,
}:
let
diffs = symlinkJoin {
name = "diffs";
paths = map (
evalSystem:
let
eval = singleSystem {
inherit quickTest evalSystem chunkSize;
};
in
diff {
inherit evalSystem;
# Local "full" evaluation doesn't do a real diff.
beforeDir = eval;
afterDir = eval;
}
) evalSystems;
};
in
combine {
diffDir = diffs;
};
in
{
inherit
attrpathsSuperset
singleSystem
diff
combine
compare
# The above three are used by separate VMs in a GitHub workflow,
# while the below is intended for testing on a single local machine
full
;
}

View File

@@ -1,61 +0,0 @@
{
lib,
runCommand,
writeText,
}:
{
beforeDir,
afterDir,
evalSystem,
}:
let
/*
Computes the key difference between two attrs
{
added: [ <keys only in the second object> ],
removed: [ <keys only in the first object> ],
changed: [ <keys with different values between the two objects> ],
}
*/
diff =
let
filterKeys = cond: attrs: lib.attrNames (lib.filterAttrs cond attrs);
in
old: new: {
added = filterKeys (n: _: !(old ? ${n})) new;
removed = filterKeys (n: _: !(new ? ${n})) old;
changed = filterKeys (
n: v:
# Filter out attributes that don't exist anymore
(new ? ${n})
# Filter out attributes that are the same as the new value
&& (v != (new.${n}))
) old;
};
getAttrs =
dir:
let
raw = builtins.readFile "${dir}/${evalSystem}/paths.json";
# The file contains Nix paths; we need to ignore them for evaluation purposes,
# else there will be a "is not allowed to refer to a store path" error.
data = builtins.unsafeDiscardStringContext raw;
in
builtins.fromJSON data;
beforeAttrs = getAttrs beforeDir;
afterAttrs = getAttrs afterDir;
diffAttrs = diff beforeAttrs afterAttrs;
diffJson = writeText "diff.json" (builtins.toJSON diffAttrs);
in
runCommand "diff" { } ''
mkdir -p $out/${evalSystem}
cp -r ${beforeDir} $out/before
cp -r ${afterDir} $out/after
cp ${diffJson} $out/${evalSystem}/diff.json
''

View File

@@ -1,53 +0,0 @@
{
lib,
nix,
nixpkgs-vet,
runCommand,
}:
{
base ? ../.,
head ? ../.,
}:
let
filtered =
with lib.fileset;
path:
toSource {
fileset = (gitTracked path);
root = path;
};
in
runCommand "nixpkgs-vet"
{
nativeBuildInputs = [
nixpkgs-vet
];
env.NIXPKGS_VET_NIX_PACKAGE = nix;
}
''
export NIX_STATE_DIR=$(mktemp -d)
nixpkgs-vet --base ${filtered base} ${filtered head}
# TODO: Upstream into nixpkgs-vet, see:
# https://github.com/NixOS/nixpkgs-vet/issues/164
badFiles=$(find ${filtered head}/pkgs -type f -name '*.nix' -print | xargs grep -l '^[^#]*<nixpkgs/' || true)
if [[ -n $badFiles ]]; then
echo "Nixpkgs is not allowed to use <nixpkgs> to refer to itself."
echo "The offending files:"
echo "$badFiles"
exit 1
fi
# TODO: Upstream into nixpkgs-vet, see:
# https://github.com/NixOS/nixpkgs-vet/issues/166
conflictingPaths=$(find ${filtered head} | awk '{ print $1 " " tolower($1) }' | sort -k2 | uniq -D -f 1 | cut -d ' ' -f 1)
if [[ -n $conflictingPaths ]]; then
echo "Files in nixpkgs must not vary only by case."
echo "The offending paths:"
echo "$conflictingPaths"
exit 1
fi
touch $out
''

View File

@@ -1,66 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p jq
set -o pipefail -o errexit -o nounset
trace() { echo >&2 "$@"; }
tmp=$(mktemp -d)
cleanup() {
# Don't exit early if anything fails to cleanup
set +o errexit
trace -n "Cleaning up.. "
[[ -e "$tmp/base" ]] && git worktree remove --force "$tmp/base"
[[ -e "$tmp/merged" ]] && git worktree remove --force "$tmp/merged"
rm -rf "$tmp"
trace "Done"
}
trap cleanup exit
repo=https://github.com/NixOS/nixpkgs.git
if (( $# != 0 )); then
baseBranch=$1
shift
else
trace "Usage: $0 BASE_BRANCH [REPOSITORY]"
trace "BASE_BRANCH: The base branch to use, e.g. master or release-23.11"
trace "REPOSITORY: The repository to fetch the base branch from, defaults to $repo"
exit 1
fi
if (( $# != 0 )); then
repo=$1
shift
fi
if [[ -n "$(git status --porcelain)" ]]; then
trace -e "\e[33mWarning: Dirty tree, uncommitted changes won't be taken into account\e[0m"
fi
headSha=$(git rev-parse HEAD)
trace -e "Using HEAD commit \e[34m$headSha\e[0m"
trace -n "Creating Git worktree for the HEAD commit in $tmp/merged.. "
git worktree add --detach -q "$tmp/merged" HEAD
trace "Done"
trace -n "Fetching base branch $baseBranch to compare against.. "
git fetch -q "$repo" refs/heads/"$baseBranch"
baseSha=$(git rev-parse FETCH_HEAD)
trace -e "\e[34m$baseSha\e[0m"
trace -n "Creating Git worktree for the base branch in $tmp/base.. "
git worktree add -q "$tmp/base" "$baseSha"
trace "Done"
trace -n "Merging base branch into the HEAD commit in $tmp/merged.. "
git -C "$tmp/merged" merge -q --no-edit "$baseSha"
trace -e "\e[34m$(git -C "$tmp/merged" rev-parse HEAD)\e[0m"
trace "Running nixpkgs-vet.."
nix-build ci -A nixpkgs-vet --arg base "$tmp/base" --arg head "$tmp/merged"

View File

@@ -1,43 +0,0 @@
{
lib,
nix,
runCommand,
}:
let
nixpkgs =
with lib.fileset;
toSource {
root = ../.;
fileset = (fileFilter (file: file.hasExt "nix") ../.);
};
in
runCommand "nix-parse-${nix.name}"
{
nativeBuildInputs = [
nix
];
}
''
export NIX_STORE_DIR=$TMPDIR/store
export NIX_STATE_DIR=$TMPDIR/state
cd "${nixpkgs}"
# Passes all files to nix-instantiate at once.
# Much faster, but will only show first error.
parse-all() {
find . -type f -iname '*.nix' | xargs -P $(nproc) nix-instantiate --parse >/dev/null 2>/dev/null
}
# Passes each file separately to nix-instantiate with -n1.
# Much slower, but will show all errors.
parse-each() {
find . -type f -iname '*.nix' | xargs -n1 -P $(nproc) nix-instantiate --parse >/dev/null
}
if ! parse-all; then
parse-each
fi
touch $out
''

View File

@@ -1,31 +0,0 @@
{
"pins": {
"nixpkgs": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "NixOS",
"repo": "nixpkgs"
},
"branch": "nixpkgs-unstable",
"submodules": false,
"revision": "6afe187897bef7933475e6af374c893f4c84a293",
"url": "https://github.com/NixOS/nixpkgs/archive/6afe187897bef7933475e6af374c893f4c84a293.tar.gz",
"hash": "1x3yas2aingswrw7hpn43d9anlb08bpyk42dqg6v8f3p3yk83p1b"
},
"treefmt-nix": {
"type": "Git",
"repository": {
"type": "GitHub",
"owner": "numtide",
"repo": "treefmt-nix"
},
"branch": "main",
"submodules": false,
"revision": "a05be418a1af1198ca0f63facb13c985db4cb3c5",
"url": "https://github.com/numtide/treefmt-nix/archive/a05be418a1af1198ca0f63facb13c985db4cb3c5.tar.gz",
"hash": "1yadm9disc59an4a6c1zidq82530rd7i7idzzsirv6dlwirbqk3q"
}
},
"version": 5
}

View File

@@ -1,44 +0,0 @@
{
lib,
stdenvNoCC,
makeWrapper,
coreutils,
codeowners,
jq,
curl,
github-cli,
gitMinimal,
}:
stdenvNoCC.mkDerivation {
name = "request-reviews";
src = lib.fileset.toSource {
root = ./.;
fileset = lib.fileset.unions [
./get-code-owners.sh
./request-reviewers.sh
./request-code-owner-reviews.sh
./verify-base-branch.sh
./dev-branches.txt
];
};
nativeBuildInputs = [ makeWrapper ];
dontBuild = true;
installPhase = ''
mkdir -p $out/bin
mv dev-branches.txt $out/bin
for bin in *.sh; do
mv "$bin" "$out/bin"
wrapProgram "$out/bin/$bin" \
--set PATH ${
lib.makeBinPath [
coreutils
codeowners
jq
curl
github-cli
gitMinimal
]
}
done
'';
}

View File

@@ -1,9 +0,0 @@
# Trusted development branches:
# These generally require PRs to update and are built by Hydra.
# Keep this synced with the branches in .github/workflows/eval.yml
master
staging
release-*
staging-*
haskell-updates
python-updates

View File

@@ -1,97 +0,0 @@
#!/usr/bin/env bash
# Get the code owners of the files changed by a PR, returning one username per line
set -euo pipefail
log() {
echo "$@" >&2
}
if (( "$#" < 4 )); then
log "Usage: $0 GIT_REPO OWNERS_FILE BASE_REF HEAD_REF"
exit 1
fi
gitRepo=$1
ownersFile=$2
baseRef=$3
headRef=$4
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' exit
git -C "$gitRepo" diff --name-only --merge-base "$baseRef" "$headRef" > "$tmp/touched-files"
readarray -t touchedFiles < "$tmp/touched-files"
log "This PR touches ${#touchedFiles[@]} files"
# Get the owners file from the base, because we don't want to allow PRs to
# remove code owners to avoid pinging them
git -C "$gitRepo" show "$baseRef":"$ownersFile" > "$tmp"/codeowners
# Associative array with the user as the key for easy de-duplication
# Make sure to always lowercase keys to avoid duplicates with different casings
declare -A users=()
for file in "${touchedFiles[@]}"; do
result=$(codeowners --file "$tmp"/codeowners "$file")
# Remove the file prefix and trim the surrounding spaces
read -r owners <<< "${result#"$file"}"
if [[ "$owners" == "(unowned)" ]]; then
log "File $file is unowned"
continue
fi
log "File $file is owned by $owners"
# Split up multiple owners, separated by arbitrary amounts of spaces
IFS=" " read -r -a entries <<< "$owners"
for entry in "${entries[@]}"; do
# GitHub technically also supports Emails as code owners,
# but we can't easily support that, so let's not
if [[ ! "$entry" =~ @(.*) ]]; then
warn -e "\e[33mCodeowner \"$entry\" for file $file is not valid: Must start with \"@\"\e[0m" >&2
# Don't fail, because the PR for which this script runs can't fix it,
# it has to be fixed in the base branch
continue
fi
# The first regex match is everything after the @
entry=${BASH_REMATCH[1]}
if [[ "$entry" =~ (.*)/(.*) ]]; then
# Teams look like $org/$team
org=${BASH_REMATCH[1]}
team=${BASH_REMATCH[2]}
# Instead of requesting a review from the team itself,
# we request reviews from the individual users.
# This is because once somebody from a team reviewed the PR,
# the API doesn't expose that the team was already requested for a review,
# so we wouldn't be able to avoid rerequesting reviews
# without saving some some extra state somewhere
# We could also consider implementing a more advanced heuristic
# in the future that e.g. only pings one team member,
# but escalates to somebody else if that member doesn't respond in time.
gh api \
--cache=1h \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/orgs/$org/teams/$team/members" \
--jq '.[].login' > "$tmp/team-members"
readarray -t members < "$tmp/team-members"
log "Team $entry has these members: ${members[*]}"
for user in "${members[@]}"; do
users[${user,,}]=
done
else
# Everything else is a user
users[${entry,,}]=
fi
done
done
printf "%s\n" "${!users[@]}"

View File

@@ -1,82 +0,0 @@
#!/usr/bin/env bash
# Requests reviews for a PR after verifying that the base branch is correct
set -euo pipefail
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' exit
SCRIPT_DIR=$(dirname "$0")
log() {
echo "$@" >&2
}
effect() {
if [[ -n "${DRY_MODE:-}" ]]; then
log "Skipping in dry mode:" "${@@Q}"
else
"$@"
fi
}
if (( $# < 3 )); then
log "Usage: $0 GITHUB_REPO PR_NUMBER OWNERS_FILE"
exit 1
fi
baseRepo=$1
prNumber=$2
ownersFile=$3
log "Fetching PR info"
prInfo=$(gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$baseRepo/pulls/$prNumber")
baseBranch=$(jq -r .base.ref <<< "$prInfo")
log "Base branch: $baseBranch"
prRepo=$(jq -r .head.repo.full_name <<< "$prInfo")
log "PR repo: $prRepo"
prBranch=$(jq -r .head.ref <<< "$prInfo")
log "PR branch: $prBranch"
prAuthor=$(jq -r .user.login <<< "$prInfo")
log "PR author: $prAuthor"
extraArgs=()
if pwdRepo=$(git rev-parse --show-toplevel 2>/dev/null); then
# Speedup for local runs
extraArgs+=(--reference-if-able "$pwdRepo")
fi
log "Fetching Nixpkgs commit history"
# We only need the commit history, not the contents, so we can do a tree-less clone using tree:0
# https://github.blog/open-source/git/get-up-to-speed-with-partial-clone-and-shallow-clone/#user-content-quick-summary
git clone --bare --filter=tree:0 --no-tags --origin upstream "${extraArgs[@]}" https://github.com/"$baseRepo".git "$tmp"/nixpkgs.git
log "Fetching the PR commit history"
# Fetch the PR
git -C "$tmp/nixpkgs.git" remote add fork https://github.com/"$prRepo".git
# This remote config is the same as --filter=tree:0 when cloning
git -C "$tmp/nixpkgs.git" config remote.fork.partialclonefilter tree:0
git -C "$tmp/nixpkgs.git" config remote.fork.promisor true
git -C "$tmp/nixpkgs.git" fetch --no-tags fork "$prBranch"
headRef=$(git -C "$tmp/nixpkgs.git" rev-parse refs/remotes/fork/"$prBranch")
log "Checking correctness of the base branch"
if ! "$SCRIPT_DIR"/verify-base-branch.sh "$tmp/nixpkgs.git" "$headRef" "$baseRepo" "$baseBranch" "$prRepo" "$prBranch" | tee "$tmp/invalid-base-error" >&2; then
log "Posting error as comment"
if ! response=$(effect gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$baseRepo/issues/$prNumber/comments" \
-F "body=@$tmp/invalid-base-error"); then
log "Failed to post the comment: $response"
fi
exit 1
fi
log "Requesting reviews from code owners"
"$SCRIPT_DIR"/get-code-owners.sh "$tmp/nixpkgs.git" "$ownersFile" "$baseBranch" "$headRef" | \
"$SCRIPT_DIR"/request-reviewers.sh "$baseRepo" "$prNumber" "$prAuthor"

View File

@@ -1,88 +0,0 @@
#!/usr/bin/env bash
# Request reviewers for a PR, reading line-separated usernames on stdin,
# filtering for valid reviewers before using the API endpoint to request reviews:
# https://docs.github.com/en/rest/pulls/review-requests?apiVersion=2022-11-28#request-reviewers-for-a-pull-request
set -euo pipefail
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' exit
log() {
echo "$@" >&2
}
effect() {
if [[ -n "${DRY_MODE:-}" ]]; then
log "Skipping in dry mode:" "${@@Q}"
else
"$@"
fi
}
if (( "$#" < 3 )); then
log "Usage: $0 BASE_REPO PR_NUMBER PR_AUTHOR"
exit 1
fi
baseRepo=$1
prNumber=$2
prAuthor=$3
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' exit
declare -A users=()
while read -r handle && [[ -n "$handle" ]]; do
users[${handle,,}]=
done
# Cannot request a review from the author
if [[ -v users[${prAuthor,,}] ]]; then
log "One or more files are owned by the PR author, ignoring"
unset 'users[${prAuthor,,}]'
fi
gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$baseRepo/pulls/$prNumber/reviews" \
--jq '.[].user.login' > "$tmp/already-reviewed-by"
# And we don't want to rerequest reviews from people who already reviewed
while read -r user; do
if [[ -v users[${user,,}] ]]; then
log "User $user is a potential reviewer, but has already left a review, ignoring"
unset 'users[${user,,}]'
fi
done < "$tmp/already-reviewed-by"
for user in "${!users[@]}"; do
if ! gh api \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$baseRepo/collaborators/$user" >&2; then
log "User $user is not a repository collaborator, probably missed the automated invite to the maintainers team (see <https://github.com/NixOS/nixpkgs/issues/234293>), ignoring"
unset 'users[$user]'
fi
done
if [[ "${#users[@]}" -gt 10 ]]; then
log "Too many reviewers (${!users[*]}), skipping review requests"
exit 0
fi
for user in "${!users[@]}"; do
log "Requesting review from: $user"
if ! response=$(jq -n --arg user "$user" '{ reviewers: [ $user ] }' | \
effect gh api \
--method POST \
-H "Accept: application/vnd.github+json" \
-H "X-GitHub-Api-Version: 2022-11-28" \
"/repos/$baseRepo/pulls/$prNumber/requested_reviewers" \
--input -); then
log "Failed to request review from $user: $response"
fi
done

View File

@@ -1,104 +0,0 @@
#!/usr/bin/env bash
# Check that a PR doesn't include commits from other development branches.
# Fails with next steps if it does
set -euo pipefail
tmp=$(mktemp -d)
trap 'rm -rf "$tmp"' exit
SCRIPT_DIR=$(dirname "$0")
log() {
echo "$@" >&2
}
# Small helper to check whether an element is in a list
# Usage: `elementIn foo "${list[@]}"`
elementIn() {
local e match=$1
shift
for e; do
if [[ "$e" == "$match" ]]; then
return 0
fi
done
return 1
}
if (( $# < 6 )); then
log "Usage: $0 LOCAL_REPO HEAD_REF BASE_REPO BASE_BRANCH PR_REPO PR_BRANCH"
exit 1
fi
localRepo=$1
headRef=$2
baseRepo=$3
baseBranch=$4
prRepo=$5
prBranch=$6
# All development branches
devBranchPatterns=()
while read -r pattern; do
if [[ "$pattern" != '#'* ]]; then
devBranchPatterns+=("$pattern")
fi
done < "$SCRIPT_DIR/dev-branches.txt"
git -C "$localRepo" branch --list --format "%(refname:short)" "${devBranchPatterns[@]}" > "$tmp/dev-branches"
readarray -t devBranches < "$tmp/dev-branches"
if [[ "$baseRepo" == "$prRepo" ]] && elementIn "$prBranch" "${devBranches[@]}"; then
log "This PR merges $prBranch into $baseBranch, no commit check necessary"
exit 0
fi
# The current merge base of the PR
prMergeBase=$(git -C "$localRepo" merge-base "$baseBranch" "$headRef")
log "The PR's merge base with the base branch $baseBranch is $prMergeBase"
# This is purely for debugging
git -C "$localRepo" rev-list --reverse "$baseBranch".."$headRef" > "$tmp/pr-commits"
log "The PR includes these $(wc -l < "$tmp/pr-commits") commits:"
cat <"$tmp/pr-commits" >&2
for testBranch in "${devBranches[@]}"; do
if [[ -z "$(git -C "$localRepo" rev-list -1 --since="1 month ago" "$testBranch")" ]]; then
log "Not checking $testBranch, was inactive for the last month"
continue
fi
log "Checking if commits from $testBranch are included in the PR"
# We need to check for any commits that are in the PR which are also in the test branch.
# We could check each commit from the PR individually, but that's unnecessarily slow.
#
# This does _almost_ what we want: `git rev-list --count headRef testBranch ^baseBranch`,
# except that it includes commits that are reachable from _either_ headRef or testBranch,
# instead of restricting it to ones reachable by both
# Easily fixable though, because we can use `git merge-base testBranch headRef`
# to get the least common ancestor (aka merge base) commit reachable by both.
# If the branch being tested is indeed the right base branch,
# this is then also the commit from that branch that the PR is based on top of.
testMergeBase=$(git -C "$localRepo" merge-base "$testBranch" "$headRef")
# And then use the `git rev-list --count`, but replacing the non-working
# `headRef testBranch` with the merge base of the two.
extraCommits=$(git -C "$localRepo" rev-list --count "$testMergeBase" ^"$baseBranch")
if (( extraCommits != 0 )); then
log -e "\e[33m"
echo "The PR's base branch is set to $baseBranch, but $extraCommits commits from the $testBranch branch are included. Make sure you know the [right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions), then:"
echo "- If the changes should go to the $testBranch branch, [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 $testBranch"
echo "- If the changes should go to the $baseBranch branch, rebase your PR onto the merge base with the $baseBranch branch:"
echo " \`\`\`bash"
echo " # git rebase --onto \$(git merge-base upstream/$baseBranch HEAD) \$(git merge-base upstream/$testBranch HEAD)"
echo " git rebase --onto $prMergeBase $testMergeBase"
echo " git push --force-with-lease"
echo " \`\`\`"
log -e "\e[m"
exit 1
fi
done
log "Base branch is correct, no commits from development branches are included"

View File

@@ -1,62 +0,0 @@
#!/usr/bin/env nix-shell
/*
#!nix-shell -i node -p nodejs
*/
const typeConfig = {
master: ['development', 'primary'],
release: ['development', 'primary'],
staging: ['development', 'secondary'],
'staging-next': ['development', 'secondary'],
'haskell-updates': ['development', 'secondary'],
'python-updates': ['development', 'secondary'],
nixos: ['channel'],
nixpkgs: ['channel'],
}
function split(branch) {
return { ...branch.match(/(?<prefix>.+?)(-(?<version>\d{2}\.\d{2}|unstable)(?:-(?<suffix>.*))?)?$/).groups }
}
function classify(branch) {
const { prefix, version } = split(branch)
return {
stable: (version ?? 'unstable') !== 'unstable',
type: typeConfig[prefix] ?? [ 'wip' ]
}
}
module.exports = { classify }
// If called directly via CLI, runs the following tests:
if (!module.parent) {
console.log('split(branch)')
function testSplit(branch) {
console.log(branch, split(branch))
}
testSplit('master')
testSplit('release-25.05')
testSplit('staging-next')
testSplit('staging-25.05')
testSplit('staging-next-25.05')
testSplit('nixpkgs-25.05-darwin')
testSplit('nixpkgs-unstable')
testSplit('haskell-updates')
testSplit('backport-123-to-release-25.05')
console.log('')
console.log('classify(branch)')
function testClassify(branch) {
console.log(branch, classify(branch))
}
testClassify('master')
testClassify('release-25.05')
testClassify('staging-next')
testClassify('staging-25.05')
testClassify('staging-next-25.05')
testClassify('nixpkgs-25.05-darwin')
testClassify('nixpkgs-unstable')
testClassify('haskell-updates')
testClassify('backport-123-to-release-25.05')
}

View File

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

View File

@@ -1,8 +0,0 @@
#!/usr/bin/env nix-shell
#!nix-shell -i bash -p npins
set -euo pipefail
cd "$(dirname "${BASH_SOURCE[0]}")"
npins --lock-file pinned.json update

View File

@@ -1,8 +1,6 @@
let
requiredVersion = import ./lib/minver.nix;
in
let requiredVersion = import ./lib/minver.nix; in
if !builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
if ! builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
abort ''

View File

@@ -2,20 +2,10 @@
This directory houses the sources files for the Nixpkgs reference manual.
> [!IMPORTANT]
> We are actively restructuring our documentation to follow the [Diátaxis framework](https://diataxis.fr/)
>
> 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.
Going forward, it should only contain [reference](https://nix.dev/contributing/documentation/diataxis#reference) documentation.
For tutorials, guides and explanations, contribute to <https://nix.dev/> instead.
For documentation only relevant for contributors, use Markdown files next to the source and regular code comments.
> [!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.
For documentation only relevant for contributors, use Markdown files and code comments in the source code.
Rendered documentation:
- [Unstable (from master)](https://nixos.org/manual/nixpkgs/unstable/)
@@ -72,7 +62,7 @@ Allow linking arbitrary place in the text (e.g. individual list items, sentences
They are defined using a hybrid of the link syntax with the attributes syntax known from headings, called [bracketed spans](https://github.com/jgm/commonmark-hs/blob/master/commonmark-extensions/test/bracketed_spans.md):
```markdown
- []{#ssec-gnome-hooks-glib} `glib` setup hook will populate `GSETTINGS_SCHEMAS_PATH` and then `wrapGApps*` hook will prepend it to `XDG_DATA_DIRS`.
- []{#ssec-gnome-hooks-glib} `glib` setup hook will populate `GSETTINGS_SCHEMAS_PATH` and then `wrapGAppsHook` will prepend it to `XDG_DATA_DIRS`.
```
#### Automatic links
@@ -81,11 +71,6 @@ If you **omit a link text** for a link pointing to a section, the text will be s
This syntax is taken from [MyST](https://myst-parser.readthedocs.io/en/latest/using/syntax.html#targets-and-cross-referencing).
#### HTML
Inlining HTML is not allowed. Parts of the documentation gets rendered to various non-HTML formats, such as man pages in the case of NixOS manual.
#### Roles
If you want to link to a man page, you can use `` {manpage}`nix.conf(5)` ``. The references will turn into links when a mapping exists in [`doc/manpage-urls.json`](./manpage-urls.json).
@@ -116,12 +101,12 @@ This is a warning
The following are supported:
- `caution`
- `important`
- `note`
- `tip`
- `warning`
- `example`
- [`caution`](https://tdg.docbook.org/tdg/5.0/caution.html)
- [`important`](https://tdg.docbook.org/tdg/5.0/important.html)
- [`note`](https://tdg.docbook.org/tdg/5.0/note.html)
- [`tip`](https://tdg.docbook.org/tdg/5.0/tip.html)
- [`warning`](https://tdg.docbook.org/tdg/5.0/warning.html)
- [`example`](https://tdg.docbook.org/tdg/5.0/example.html)
Example admonitions require a title to work.
If you don't provide one, the manual won't be built.
@@ -172,216 +157,57 @@ watermelon
In an effort to keep the Nixpkgs manual in a consistent style, please follow the conventions below, unless they prevent you from properly documenting something.
In that case, please open an issue about the particular documentation convention and tag it with a "needs: documentation" label.
When needed, each convention explain why it exists, so you can make a decision whether to follow it or not based on your particular case.
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.
### One sentence per line
- Put each sentence in its own line.
This makes reviews and suggestions much easier, since GitHub's review system is based on lines.
It also helps identifying long sentences at a glance.
Put each sentence in its own line.
This makes reviews and suggestions much easier, since GitHub's review system is based on lines.
It also helps identifying long sentences at a glance.
- Use the [admonition syntax](#admonitions) for callouts and examples.
### Callouts and examples
- 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.
Use the [admonition syntax](#admonitions) for callouts and examples.
Example code should be such that it can be passed to `pkgs.callPackage`.
Instead of something like:
### Provide self-contained examples
```nix
pkgs.dockerTools.buildLayeredImage {
name = "hello";
contents = [ pkgs.hello ];
}
```
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.
Write something like:
Example code should be such that it can be passed to `pkgs.callPackage`.
Instead of something like:
```nix
{ dockerTools, hello }:
dockerTools.buildLayeredImage {
name = "hello";
contents = [ hello ];
}
```
```nix
pkgs.dockerTools.buildLayeredImage {
name = "hello";
contents = [ pkgs.hello ];
}
```
- Use [definition lists](#definition-lists) to document function arguments, and the attributes of such arguments. For example:
Write something like:
```markdown
# pkgs.coolFunction
```nix
{ dockerTools, hello }:
dockerTools.buildLayeredImage {
name = "hello";
contents = [ hello ];
}
```
Description of what `coolFunction` does.
`coolFunction` expects a single argument which should be an attribute set, with the following possible attributes:
### REPLs
`name`
When showing inputs/outputs of any [REPL](https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop), such as a shell or the Nix REPL, use a format as you'd see in the REPL, while trying to visually separate inputs from outputs.
This means that for a shell, you should use a format like the following:
```shell
$ nix-build -A hello '<nixpkgs>' \
--option require-sigs false \
--option trusted-substituters file:///tmp/hello-cache \
--option substituters file:///tmp/hello-cache
/nix/store/zhl06z4lrfrkw5rp0hnjjfrgsclzvxpm-hello-2.12.1
```
Note how the input is preceded by `$` on the first line and indented on subsequent lines, and how the output is provided as you'd see on the shell.
: The name of the resulting image.
For the Nix REPL, you should use a format like the following:
```shell
nix-repl> builtins.attrNames { a = 1; b = 2; }
[ "a" "b" ]
```
Note how the input is preceded by `nix-repl>` and the output is provided as you'd see on the Nix REPL.
`tag` _optional_
### Headings for inputs, outputs and examples
: Tag of the generated image.
When documenting functions or anything that has inputs/outputs and example usage, use nested headings to clearly separate inputs, outputs, and examples.
Keep examples as the last nested heading, and link to the examples wherever applicable in the documentation.
_Default value:_ the output path's hash.
The purpose of this convention is to provide a familiar structure for navigating the manual, so any reader can expect to find content related to inputs in an "inputs" heading, examples in an "examples" heading, and so on.
An example:
```
## buildImage
Some explanation about the function here.
Describe a particular scenario, and point to [](#ex-dockerTools-buildImage), which is an example demonstrating it.
### Inputs
Documentation for the inputs of `buildImage`.
Perhaps even point to [](#ex-dockerTools-buildImage) again when talking about something specifically linked to it.
### Passthru outputs
Documentation for any passthru outputs of `buildImage`.
### Examples
Note that this is the last nested heading in the `buildImage` section.
:::{.example #ex-dockerTools-buildImage}
# Using `buildImage`
Example of how to use `buildImage` goes here.
:::
```
### Function arguments
Use [definition lists](#definition-lists) to document function arguments, and the attributes of such arguments as well as their [types](https://nixos.org/manual/nix/stable/language/values).
For example:
```markdown
# pkgs.coolFunction {#pkgs.coolFunction}
`pkgs.coolFunction` *`name`* *`config`*
Description of what `callPackage` does.
## Inputs {#pkgs-coolFunction-inputs}
If something's special about `coolFunction`'s general argument handling, you can say so here.
Otherwise, just describe the single argument or start the arguments' definition list without introduction.
*`name`* (String)
: The name of the resulting image.
*`config`* (Attribute set)
: Introduce the parameter. Maybe you have a test to make sure `{ }` is a sensible default; then you can say: these attributes are optional; `{ }` is a valid argument.
`outputHash` (String; _optional_)
: A brief explanation including when and when not to pass this attribute.
: _Default:_ the output path's hash.
```
Checklist:
- Start with a synopsis, to show the order of positional arguments.
- Metavariables are in emphasized code spans: ``` *`arg1`* ```. Metavariables are placeholders where users may write arbitrary expressions. This includes positional arguments.
- Attribute names are regular code spans: ``` `attr1` ```. These identifiers can _not_ be picked freely by users, so they are _not_ metavariables.
- _optional_ attributes have a _`Default:`_ if it's easily described as a value.
- _optional_ attributes have a _`Default behavior:`_ if it's not easily described using a value.
- Nix types aren't in code spans, because they are not code
- Nix types are capitalized, to distinguish them from the camelCase Module System types, which _are_ code and behave like functions.
#### Examples
To define a referenceable figure use the following fencing:
```markdown
:::{.example #an-attribute-set-example}
# An attribute set example
You can add text before
```nix
{ a = 1; b = 2;}
```
and after code fencing
:::
```
Defining examples through the `example` fencing class adds them to a "List of Examples" section after the Table of Contents.
Though this is not shown in the rendered documentation on nixos.org.
#### Figures
To define a referenceable figure use the following fencing:
```markdown
::: {.figure #nixos-logo}
# NixOS Logo
![NixOS logo](./nixos_logo.png)
:::
```
Defining figures through the `figure` fencing class adds them to a `List of Figures` after the `Table of Contents`.
Though this is not shown in the rendered documentation on nixos.org.
#### Footnotes
To add a foonote explanation, use the following syntax:
```markdown
Sometimes it's better to add context [^context] in a footnote.
[^context]: This explanation will be rendered at the end of the chapter.
```
#### Inline comments
Inline comments are supported with following syntax:
```markdown
<!-- This is an inline comment -->
```
The comments will not be rendered in the rendered HTML.
#### Link reference definitions
Links can reference a label, for example, to make the link target reusable:
```markdown
::: {.note}
Reference links can also be used to [shorten URLs][url-id] and keep the markdown readable.
:::
[url-id]: https://github.com/NixOS/nixpkgs/blob/19d4f7dc485f74109bd66ef74231285ff797a823/doc/README.md
```
This syntax is taken from [CommonMark](https://spec.commonmark.org/0.30/#link-reference-definitions).
#### Typographic replacements
Typographic replacements are enabled. Check the [list of possible replacement patterns check](https://github.com/executablebooks/markdown-it-py/blob/3613e8016ecafe21709471ee0032a90a4157c2d1/markdown_it/rules_core/replacements.py#L1-L15).
```
## Getting help
If you need documentation-specific help or reviews, ping [@NixOS/documentation-team](https://github.com/orgs/nixos/teams/documentation-team) on your pull request.
If you need documentation-specific help or reviews, ping [@NixOS/documentation-reviewers](https://github.com/orgs/nixos/teams/documentation-reviewers) on your pull request.

View File

@@ -1,3 +0,0 @@
document.addEventListener('DOMContentLoaded', function(event) {
anchors.add('h1[id]:not(div.note h1, div.warning h1, div.tip h1, div.caution h1, div.important h1), h2[id]:not(div.note h2, div.warning h2, div.tip h2, div.caution h2, div.important h2), h3[id]:not(div.note h3, div.warning h3, div.tip h3, div.caution h3, div.important h3), h4[id]:not(div.note h4, div.warning h4, div.tip h4, div.caution h4, div.important h4), h5[id]:not(div.note h5, div.warning h5, div.tip h5, div.caution h5, div.important h5), h6[id]:not(div.note h6, div.warning h6, div.tip h6, div.caution h6, div.important h6)');
});

9
doc/anchor.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -17,11 +17,9 @@ There is no uniform interface for build helpers.
[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

View File

@@ -1,84 +0,0 @@
# Development Shell helpers {#chap-devShellTools}
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 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 yet make use of this.
Relevant is the current status of the devShell attribute "project": https://github.com/NixOS/nix/issues/7501
-->
However, `nix-shell` is not the only way to create such environments, and even `nix-shell` itself can indirectly benefit from this library.
This library provides a set of functions that help create such environments.
## `devShellTools.valueToString` {#sec-devShellTools-valueToString}
Converts Nix values to strings in the way the [`derivation` built-in function](https://nix.dev/manual/nix/2.23/language/derivations) does.
:::{.example}
## `valueToString` usage examples
```nix
devShellTools.valueToString (builtins.toFile "foo" "bar")
# => "/nix/store/...-foo"
```
```nix
devShellTools.valueToString false
# => ""
```
:::
## `devShellTools.unstructuredDerivationInputEnv` {#sec-devShellTools-unstructuredDerivationInputEnv}
Convert a set of derivation attributes (as would be passed to [`derivation`]) to a set of environment variables that can be used in a shell script.
This function does not support `__structuredAttrs`, but does support `passAsFile`.
:::{.example}
## `unstructuredDerivationInputEnv` usage example
```nix
devShellTools.unstructuredDerivationInputEnv {
drvAttrs = {
name = "foo";
buildInputs = [
hello
figlet
];
builder = bash;
args = [
"-c"
"${./builder.sh}"
];
};
}
# => {
# name = "foo";
# buildInputs = "/nix/store/...-hello /nix/store/...-figlet";
# builder = "/nix/store/...-bash";
# }
```
Note that `args` is not included, because Nix does not added it to the builder process environment.
:::
## `devShellTools.derivationOutputEnv` {#sec-devShellTools-derivationOutputEnv}
Takes the relevant parts of a derivation and returns a set of environment variables, that would be present in the derivation.
:::{.example}
## `derivationOutputEnv` usage example
```nix
let
pkg = hello;
in
devShellTools.derivationOutputEnv {
outputList = pkg.outputs;
outputMap = pkg;
}
```
:::

View File

@@ -1,691 +1,84 @@
# Fetchers {#chap-pkgs-fetchers}
Building software with Nix often requires downloading source code and other files from the internet.
To this end, we use functions that we call _fetchers_, which obtain remote sources via various protocols and services.
Nix provides built-in fetchers such as [`builtins.fetchTarball`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-fetchTarball).
Nixpkgs provides its own fetchers, which work differently:
To this end, Nixpkgs provides *fetchers*: functions to obtain remote sources via various protocols and services.
Nixpkgs fetchers differ from built-in fetchers such as [`builtins.fetchTarball`](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-fetchTarball):
- A built-in fetcher will download and cache files at evaluation time and produce a [store path](https://nixos.org/manual/nix/stable/glossary#gloss-store-path).
A Nixpkgs fetcher will create a ([fixed-output](https://nixos.org/manual/nix/stable/glossary#gloss-fixed-output-derivation)) [derivation](https://nixos.org/manual/nix/stable/glossary#gloss-derivation), and files are downloaded at build time.
A Nixpkgs fetcher will create a ([fixed-output](https://nixos.org/manual/nix/stable/glossary#gloss-fixed-output-derivation)) [derivation](https://nixos.org/manual/nix/stable/language/derivations), and files are downloaded at build time.
- Built-in fetchers will invalidate their cache after [`tarball-ttl`](https://nixos.org/manual/nix/stable/command-ref/conf-file#conf-tarball-ttl) expires, and will require network activity to check if the cache entry is up to date.
Nixpkgs fetchers only re-download if the specified hash changes or the store object is not available.
Nixpkgs fetchers only re-download if the specified hash changes or the store object is not otherwise available.
- Built-in fetchers do not use [substituters](https://nixos.org/manual/nix/stable/command-ref/conf-file#conf-substituters).
Derivations produced by Nixpkgs fetchers will use any configured binary cache transparently.
This significantly reduces the time needed to evaluate Nixpkgs, and allows [Hydra](https://nixos.org/hydra) to retain and re-distribute sources used by Nixpkgs in the [public binary cache](https://cache.nixos.org).
For these reasons, Nix's built-in fetchers are not allowed in Nixpkgs.
This significantly reduces the time needed to evaluate the entirety of Nixpkgs, and allows [Hydra](https://nixos.org/hydra) to retain and re-distribute sources used by Nixpkgs in the [public binary cache](https://cache.nixos.org).
For these reasons, built-in fetchers are not allowed in Nixpkgs source code.
The following table summarises the differences:
The following table shows an overview of the differences:
| Fetchers | Download | Output | Cache | Re-download when |
|-|-|-|-|-|
| `builtins.fetch*` | evaluation time | store path | `/nix/store`, `~/.cache/nix` | `tarball-ttl` expires, cache miss in `~/.cache/nix`, output store object not in local store |
| `pkgs.fetch*` | build time | derivation | `/nix/store`, substituters | output store object not available |
:::{.tip}
`pkgs.fetchFrom*` helpers retrieve _snapshots_ of version-controlled sources, as opposed to the entire version history, which is more efficient.
`pkgs.fetchgit` by default also has the same behaviour, but can be changed through specific attributes given to it.
:::
## Caveats {#chap-pkgs-fetchers-caveats}
Because Nixpkgs fetchers are fixed-output derivations, an [output hash](https://nixos.org/manual/nix/stable/language/advanced-attributes#adv-attr-outputHash) has to be specified, usually indirectly through a `hash` attribute.
This hash refers to the derivation output, which can be different from the remote source itself!
This has the following implications that you should be aware of:
- Use Nix (or Nix-aware) tooling to produce the output hash.
- When changing any fetcher parameters, always update the output hash.
Use one of the methods from [](#sec-pkgs-fetchers-updating-source-hashes).
Otherwise, existing store objects that match the output hash will be re-used rather than fetching new content.
:::{.note}
A similar problem arises while testing changes to a fetcher's implementation.
If the output of the derivation already exists in the Nix store, test failures can go undetected.
The [`invalidateFetcherByDrvHash`](#tester-invalidateFetcherByDrvHash) function helps prevent reusing cached derivations.
:::
## Updating source hashes {#sec-pkgs-fetchers-updating-source-hashes}
There are several ways to obtain the hash corresponding to a remote source.
Unless you understand how the fetcher you're using calculates the hash from the downloaded contents, you should use [the fake hash method](#sec-pkgs-fetchers-updating-source-hashes-fakehash-method).
1. []{#sec-pkgs-fetchers-updating-source-hashes-fakehash-method} The fake hash method: In your package recipe, set the hash to one of
- `""`
- `lib.fakeHash`
- `lib.fakeSha256`
- `lib.fakeSha512`
Attempt to build, extract the calculated hashes from error messages, and put them into the recipe.
:::{.warning}
You must use one of these four fake hashes and not some arbitrarily-chosen hash.
See [](#sec-pkgs-fetchers-secure-hashes) for details.
:::
:::{.example #ex-fetchers-update-fod-hash}
# Update source hash with the fake hash method
Consider the following recipe that produces a plain file:
```nix
{ fetchurl }:
fetchurl {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/23.05/.version";
hash = "sha256-ZHl1emidXVojm83LCVrwULpwIzKE/mYwfztVkvpruOM=";
}
```
A common mistake is to update a fetcher parameter, such as `url`, without updating the hash:
```nix
{ fetchurl }:
fetchurl {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/.version";
hash = "sha256-ZHl1emidXVojm83LCVrwULpwIzKE/mYwfztVkvpruOM=";
}
```
**This will produce the same output as before!**
Set the hash to an empty string:
```nix
{ fetchurl }:
fetchurl {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/.version";
hash = "";
}
```
When building the package, use the error message to determine the correct hash:
```shell
$ nix-build
(some output removed for clarity)
error: hash mismatch in fixed-output derivation '/nix/store/7yynn53jpc93l76z9zdjj4xdxgynawcw-version.drv':
specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
got: sha256-BZqI7r0MNP29yGH5+yW2tjU9OOpOCEvwWKrWCv5CQ0I=
error: build of '/nix/store/bqdjcw5ij5ymfbm41dq230chk9hdhqff-version.drv' failed
```
:::
2. Prefetch the source with [`nix-prefetch-<type> <URL>`](https://search.nixos.org/packages?buckets={%22package_attr_set%22%3A[%22No%20package%20set%22]%2C%22package_license_set%22%3A[]%2C%22package_maintainers_set%22%3A[]%2C%22package_platforms%22%3A[]}&query=nix-prefetch), where `<type>` is one of
- `url`
- `git`
- `hg`
- `cvs`
- `bzr`
- `svn`
The hash is printed to stdout.
3. Prefetch by package source (with `nix-prefetch-url '<nixpkgs>' -A <package>.src`, where `<package>` is package attribute name).
The hash is printed to stdout.
This works well when you've upgraded the existing package version and want to find out new hash, but is useless if the package can't be accessed by attribute or the package has multiple sources (`.srcs`, architecture-dependent sources, etc).
4. Upstream hash: use it when upstream provides `sha256` or `sha512`.
Don't use it when upstream provides `md5`, compute `sha256` instead.
A little nuance is that `nix-prefetch-*` tools produce hashes with the `nix32` encoding (a Nix-specific base32 adaptation), but upstream usually provides hexadecimal (`base16`) encoding.
Fetchers understand both formats.
Nixpkgs does not standardise on any one format.
You can convert between hash formats with [`nix-hash`](https://nixos.org/manual/nix/stable/command-ref/nix-hash).
5. Extract the hash from a local source archive with `sha256sum`.
Use `nix-prefetch-url file:///path/to/archive` if you want the custom Nix `base32` hash.
## Obtaining hashes securely {#sec-pkgs-fetchers-secure-hashes}
It's always a good idea to avoid Man-in-the-Middle (MITM) attacks when downloading source contents.
Otherwise, you could unknowingly download malware instead of the intended source, and instead of the actual source hash, you'll end up using the hash of malware.
Here are security considerations for this scenario:
- `http://` URLs are not secure to prefetch hashes.
- Upstream hashes should be obtained via a secure protocol.
- `https://` URLs give you more protections when using `nix-prefetch-*` or for upstream hashes.
- `https://` URLs are secure when using the [fake hash method](#sec-pkgs-fetchers-updating-source-hashes-fakehash-method) *only if* you use one of the listed fake hashes.
If you use any other hash, the download will be exposed to MITM attacks even if you use HTTPS URLs.
In more concrete terms, if you use any other hash, the [`--insecure` flag](https://curl.se/docs/manpage.html#-k) will be passed to the underlying call to `curl` when downloading content.
## Proxy usage {#sec-pkgs-fetchers-proxy}
Nixpkgs fetchers can make use of a http(s) proxy. Each fetcher will automatically inherit proxy-related environment variables (`http_proxy`, `https_proxy`, etc) via [impureEnvVars](https://nixos.org/manual/nix/stable/language/advanced-attributes#adv-attr-impureEnvVars).
The environment variable `NIX_SSL_CERT_FILE` is also inherited in fetchers, and can be used to provide a custom certificate bundle to fetchers. This is usually required for a https proxy to work without certificate validation errors.
[]{#fetchurl}
## `fetchurl` {#sec-pkgs-fetchers-fetchurl}
`fetchurl` returns a [fixed-output derivation](https://nixos.org/manual/nix/stable/glossary.html#gloss-fixed-output-derivation) which downloads content from a given URL and stores the unaltered contents within the Nix store.
It uses {manpage}`curl(1)` internally, and allows its behaviour to be modified by specifying a few attributes in the argument to `fetchurl` (see the documentation for attributes `curlOpts`, `curlOptsList`, and `netrcPhase`).
The resulting [store path](https://nixos.org/manual/nix/stable/store/store-path) is determined by the hash given to `fetchurl`, and also the `name` (or `pname` and `version`) values.
If neither `name` nor `pname` and `version` are specified when calling `fetchurl`, it will default to using the [basename](https://nixos.org/manual/nix/stable/language/builtins.html#builtins-baseNameOf) of `url` or the first element of `urls`.
If `pname` and `version` are specified, `fetchurl` will use those values and will ignore `name`, even if it is also specified.
### Inputs {#sec-pkgs-fetchers-fetchurl-inputs}
`fetchurl` requires an attribute set with the following attributes:
`url` (String; _optional_)
: The URL to download from.
:::{.note}
Either `url` or `urls` must be specified, but not both.
:::
All URLs of the format [specified here](https://curl.se/docs/url-syntax.html#rfc-3986-plus) are supported.
_Default value:_ `""`.
`urls` (List of String; _optional_)
: A list of URLs, specifying download locations for the same content.
Each URL will be tried in order until one of them succeeds with some content or all of them fail.
See [](#ex-fetchers-fetchurl-nixpkgs-version-multiple-urls) to understand how this attribute affects the behaviour of `fetchurl`.
:::{.note}
Either `url` or `urls` must be specified, but not both.
:::
_Default value:_ `[]`.
`hash` (String; _optional_)
: Hash of the derivation output of `fetchurl`, following the format for integrity metadata as defined by [SRI](https://www.w3.org/TR/SRI/).
For more information, see [](#chap-pkgs-fetchers-caveats).
:::{.note}
It is recommended that you use the `hash` attribute instead of the other hash-specific attributes that exist for backwards compatibility.
If `hash` is not specified, you must specify `outputHash` and `outputHashAlgo`, or one of `sha512`, `sha256`, or `sha1`.
:::
_Default value:_ `""`.
`outputHash` (String; _optional_)
: Hash of the derivation output of `fetchurl` in the format expected by Nix.
See [the documentation on the Nix manual](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-outputHash) for more information about its format.
:::{.note}
It is recommended that you use the `hash` attribute instead.
If `outputHash` is specified, you must also specify `outputHashAlgo`.
:::
_Default value:_ `""`.
`outputHashAlgo` (String; _optional_)
: Algorithm used to generate the value specified in `outputHash`.
See [the documentation on the Nix manual](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-outputHashAlgo) for more information about the values it supports.
:::{.note}
It is recommended that you use the `hash` attribute instead.
The value specified in `outputHashAlgo` will be ignored if `outputHash` isn't also specified.
:::
_Default value:_ `""`.
`sha1` (String; _optional_)
: SHA-1 hash of the derivation output of `fetchurl` in the format expected by Nix.
See [the documentation on the Nix manual](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-outputHash) for more information about its format.
:::{.note}
It is recommended that you use the `hash` attribute instead.
:::
_Default value:_ `""`.
`sha256` (String; _optional_)
: SHA-256 hash of the derivation output of `fetchurl` in the format expected by Nix.
See [the documentation on the Nix manual](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-outputHash) for more information about its format.
:::{.note}
It is recommended that you use the `hash` attribute instead.
:::
_Default value:_ `""`.
`sha512` (String; _optional_)
: SHA-512 hash of the derivation output of `fetchurl` in the format expected by Nix.
See [the documentation on the Nix manual](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-outputHash) for more information about its format.
:::{.note}
It is recommended that you use the `hash` attribute instead.
:::
_Default value:_ `""`.
`name` (String; _optional_)
: The symbolic name of the downloaded file when saved in the Nix store.
See [the `fetchurl` overview](#sec-pkgs-fetchers-fetchurl) for details on how the name of the file is decided.
_Default value:_ `""`.
`pname` (String; _optional_)
: A base name, which will be combined with `version` to form the symbolic name of the downloaded file when saved in the Nix store.
See [the `fetchurl` overview](#sec-pkgs-fetchers-fetchurl) for details on how the name of the file is decided.
:::{.note}
If `pname` is specified, you must also specify `version`, otherwise `fetchurl` will ignore the value of `pname`.
:::
_Default value:_ `""`.
`version` (String; _optional_)
: A version, which will be combined with `pname` to form the symbolic name of the downloaded file when saved in the Nix store.
See [the `fetchurl` overview](#sec-pkgs-fetchers-fetchurl) for details on how the name of the file is decided.
_Default value:_ `""`.
`recursiveHash` (Boolean; _optional_) []{#sec-pkgs-fetchers-fetchurl-inputs-recursiveHash}
: If set to `true`, will signal to Nix that the hash given to `fetchurl` was calculated using the `"recursive"` mode.
See [the documentation on the Nix manual](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-outputHashMode) for more information about the existing modes.
By default, `fetchurl` uses `"recursive"` mode when the `executable` attribute is set to `true`, so you don't need to specify `recursiveHash` in this case.
_Default value:_ `false`.
`executable` (Boolean; _optional_)
: If `true`, sets the executable bit on the downloaded file.
_Default value_: `false`.
`downloadToTemp` (Boolean; _optional_) []{#sec-pkgs-fetchers-fetchurl-inputs-downloadToTemp}
: If `true`, saves the downloaded file to a temporary location instead of the expected Nix store location.
This is useful when used in conjunction with `postFetch` attribute, otherwise `fetchurl` will not produce any meaningful output.
The location of the downloaded file will be set in the `$downloadedFile` variable, which should be used by the script in the `postFetch` attribute.
See [](#ex-fetchers-fetchurl-nixpkgs-version-postfetch) to understand how to work with this attribute.
_Default value:_ `false`.
`postFetch` (String; _optional_)
: Script executed after the file has been downloaded successfully, and before `fetchurl` finishes running.
Useful for post-processing, to check or transform the file in some way.
See [](#ex-fetchers-fetchurl-nixpkgs-version-postfetch) to understand how to work with this attribute.
_Default value:_ `""`.
`netrcPhase` (String or Null; _optional_)
: Script executed to create a {manpage}`netrc(5)` file to be used with {manpage}`curl(1)`.
The script should create the `netrc` file (note that it does not begin with a ".") in the directory it's currently running in (`$PWD`).
The script is executed during the setup done by `fetchurl` before it runs any of its code to download the specified content.
:::{.note}
If specified, `fetchurl` will automatically alter its invocation of {manpage}`curl(1)` to use the `netrc` file, so you don't need to add anything to `curlOpts` or `curlOptsList`.
:::
:::{.caution}
Since `netrcPhase` needs to be specified in your source Nix code, any secrets that you put directly in it will be world-readable by design (both in your source code, and when the derivation gets created in the Nix store).
If you want to avoid this behaviour, see the documentation of `netrcImpureEnvVars` for an alternative way of dealing with these secrets.
:::
_Default value_: `null`.
`netrcImpureEnvVars` (List of String; _optional_)
: If specified, `fetchurl` will add these environment variable names to the list of [impure environment variables](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-impureEnvVars), which will be passed from the environment of the calling user to the builder running the `fetchurl` code.
This is useful when used with `netrcPhase` to hide any secrets that are used in it, because the script in `netrcPhase` only needs to reference the environment variables with the secrets in them instead.
However, note that these are called _impure_ variables for a reason:
the environment that starts the build needs to have these variables declared for everything to work properly, which means that additional setup is required outside what Nix controls.
_Default value:_ `[]`.
`curlOpts` (String; _optional_)
: If specified, this value will be appended to the invocation of {manpage}`curl(1)` when downloading the URL(s) given to `fetchurl`.
Multiple arguments can be separated by spaces normally, but values with whitespaces will be interpreted as multiple arguments (instead of a single value), even if the value is escaped.
See `curlOptsList` for a way to pass values with whitespaces in them.
_Default value:_ `""`.
`curlOptsList` (List of String; _optional_)
: If specified, each element of this list will be passed as an argument to the invocation of {manpage}`curl(1)` when downloading the URL(s) given to `fetchurl`.
This allows passing values that contain spaces, with no escaping needed.
_Default value:_ `[]`.
`showURLs` (Boolean; _optional_)
: If set to `true`, this will stop `fetchurl` from downloading anything at all.
Instead, it will output a list of all the URLs it would've used to download the content (after resolving `mirror://` URLs, for example).
This is useful for debugging.
_Default value:_ `false`.
`meta` (Attribute Set; _optional_)
: Specifies any [meta-attributes](#chap-meta) for the derivation returned by `fetchurl`.
_Default value:_ `{}`.
`passthru` (Attribute Set; _optional_)
: Specifies any extra [`passthru`](#chap-passthru) attributes for the derivation returned by `fetchurl`.
Note that `fetchurl` defines [`passthru` attributes of its own](#ssec-pkgs-fetchers-fetchurl-passthru-outputs).
Attributes specified in `passthru` can override the default attributes returned by `fetchurl`.
_Default value:_ `{}`.
`preferLocalBuild` (Boolean; _optional_)
: This is the same attribute as [defined in the Nix manual](https://nixos.org/manual/nix/stable/language/advanced-attributes.html#adv-attr-preferLocalBuild).
It is `true` by default because making a remote machine download the content just duplicates network traffic (since the local machine might download the results from the derivation anyway), but this could be useful in cases where network access is restricted on local machines.
_Default value:_ `true`.
`nativeBuildInputs` (List of Attribute Set; _optional_)
: Additional packages needed to download the content.
This is useful if you need extra packages for `postFetch` or `netrcPhase`, for example.
Has the same semantics as in [](#var-stdenv-nativeBuildInputs).
See [](#ex-fetchers-fetchurl-nixpkgs-version-postfetch) to understand how this can be used with `postFetch`.
_Default value:_ `[]`.
### Passthru outputs {#ssec-pkgs-fetchers-fetchurl-passthru-outputs}
`fetchurl` also defines its own [`passthru`](#chap-passthru) attributes:
`url` (String)
: The same `url` attribute passed in the argument to `fetchurl`.
### Examples {#ssec-pkgs-fetchers-fetchurl-examples}
:::{.example #ex-fetchers-fetchurl-nixpkgs-version}
# Using `fetchurl` to download a file
The following package downloads a small file from a URL and shows the most common way to use `fetchurl`:
The fact that the hash belongs to the Nix derivation output and not the file itself can lead to confusion.
For example, consider the following fetcher:
```nix
{ fetchurl }:
fetchurl {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/.version";
hash = "sha256-BZqI7r0MNP29yGH5+yW2tjU9OOpOCEvwWKrWCv5CQ0I=";
}
url = "http://www.example.org/hello-1.0.tar.gz";
hash = "sha256-lTeyxzJNQeMdu1IVdovNMtgn77jRIhSybLdMbTkf2Ww=";
};
```
After building the package, the file will be downloaded and place into the Nix store:
```shell
$ nix-build
(output removed for clarity)
/nix/store/4g9y3x851wqrvim4zcz5x2v3zivmsq8n-version
$ cat /nix/store/4g9y3x851wqrvim4zcz5x2v3zivmsq8n-version
23.11
```
:::
:::{.example #ex-fetchers-fetchurl-nixpkgs-version-multiple-urls}
# Using `fetchurl` to download a file with multiple possible URLs
The following package adapts [](#ex-fetchers-fetchurl-nixpkgs-version) to use multiple URLs.
The first URL was crafted to intentionally return an error to illustrate how `fetchurl` will try multiple URLs until it finds one that works (or all URLs fail).
A common mistake is to update a fetchers URL, or a version parameter, without updating the hash.
```nix
{ fetchurl }:
fetchurl {
urls = [
"https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/does-not-exist"
"https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/.version"
];
hash = "sha256-BZqI7r0MNP29yGH5+yW2tjU9OOpOCEvwWKrWCv5CQ0I=";
}
url = "http://www.example.org/hello-1.1.tar.gz";
hash = "sha256-lTeyxzJNQeMdu1IVdovNMtgn77jRIhSybLdMbTkf2Ww=";
};
```
After building the package, both URLs will be used to download the file:
```shell
$ nix-build
(some output removed for clarity)
trying https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/does-not-exist
(some output removed for clarity)
curl: (22) The requested URL returned error: 404
trying https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/.version
(some output removed for clarity)
/nix/store/n9asny31z32q7sdw6a8r1gllrsfy53kl-does-not-exist
$ cat /nix/store/n9asny31z32q7sdw6a8r1gllrsfy53kl-does-not-exist
23.11
```
However, note that the name of the file was derived from the first URL (this is further explained in [the `fetchurl` overview](#sec-pkgs-fetchers-fetchurl)).
To ensure the result will have the same name regardless of which URLs are used, we can modify the package:
**This will reuse the old contents**.
Remember to invalidate the hash argument, in this case by setting the `hash` attribute to an empty string.
```nix
{ fetchurl }:
fetchurl {
name = "nixpkgs-version";
urls = [
"https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/does-not-exist"
"https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/.version"
];
hash = "sha256-BZqI7r0MNP29yGH5+yW2tjU9OOpOCEvwWKrWCv5CQ0I=";
}
url = "http://www.example.org/hello-1.1.tar.gz";
hash = "";
};
```
After building the package, the result will have the name we specified:
Use the resulting error message to determine the correct hash.
```shell
$ nix-build
(output removed for clarity)
/nix/store/zczb6wl3al6jm9sm5h3pr6nqn0i5ji9z-nixpkgs-version
```
:::
error: hash mismatch in fixed-output derivation '/path/to/my.drv':
specified: sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
got: sha256-lTeyxzJNQeMdu1IVdovNMtgn77jRIhSybLdMbTkf2Ww=
```
:::{.example #ex-fetchers-fetchurl-nixpkgs-version-postfetch}
# Manipulating the content downloaded by `fetchurl`
A similar problem arises while testing changes to a fetcher's implementation. If the output of the derivation already exists in the Nix store, test failures can go undetected. The [`invalidateFetcherByDrvHash`](#tester-invalidateFetcherByDrvHash) function helps prevent reusing cached derivations.
It might be useful to manipulate the content downloaded by `fetchurl` directly in its derivation.
In this example, we'll adapt [](#ex-fetchers-fetchurl-nixpkgs-version) to append the result of running the `hello` package to the contents we download, purely to illustrate how to manipulate the content.
## `fetchurl` and `fetchzip` {#fetchurl}
Two basic fetchers are `fetchurl` and `fetchzip`. Both of these have two required arguments, a URL and a hash. The hash is typically `hash`, although many more hash algorithms are supported. Nixpkgs contributors are currently recommended to use `hash`. This hash will be used by Nix to identify your source. A typical usage of `fetchurl` is provided below.
```nix
{
fetchurl,
hello,
lib,
}:
fetchurl {
url = "https://raw.githubusercontent.com/NixOS/nixpkgs/23.11/.version";
{ stdenv, fetchurl }:
nativeBuildInputs = [ hello ];
downloadToTemp = true;
postFetch = ''
${lib.getExe hello} >> $downloadedFile
mv $downloadedFile $out
'';
hash = "sha256-ceooQQYmDx5+0nfg40uU3NNI2yKrixP7HZ/xLZUNv+w=";
stdenv.mkDerivation {
name = "hello";
src = fetchurl {
url = "http://www.example.org/hello.tar.gz";
hash = "sha256-BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB=";
};
}
```
After building the package, the resulting file will have "Hello, world!" appended to it:
```shell
$ nix-build
(output removed for clarity)
/nix/store/ifi6pp7q0ag5h7c5v9h1c1c7bhd10c7f-version
$ cat /nix/store/ifi6pp7q0ag5h7c5v9h1c1c7bhd10c7f-version
23.11
Hello, world!
```
Note that the `hash` specified in the package is different than the hash specified in [](#ex-fetchers-fetchurl-nixpkgs-version), because the contents of the output have changed (even though the actual file that was downloaded is the same).
See [](#chap-pkgs-fetchers-caveats) for more details on how to work with the `hash` attribute when the output changes.
:::
## `fetchzip` {#sec-pkgs-fetchers-fetchzip}
Returns a [fixed-output derivation](https://nixos.org/manual/nix/stable/glossary.html#gloss-fixed-output-derivation) which downloads an archive from a given URL and decompresses it.
Despite its name, `fetchzip` is not limited to `.zip` files but can also be used with [various compressed tarball formats](#tar-files) by default.
This can extended by specifying additional attributes, see [](#ex-fetchers-fetchzip-rar-archive) to understand how to do that.
### Inputs {#sec-pkgs-fetchers-fetchzip-inputs}
`fetchzip` requires an attribute set, and most attributes are passed to the underlying call to [`fetchurl`](#sec-pkgs-fetchers-fetchurl).
The attributes below are treated differently by `fetchzip` when compared to what `fetchurl` expects:
`name` (String; _optional_)
: Works as defined in `fetchurl`, but has a different default value than `fetchurl`.
_Default value:_ `"source"`.
`nativeBuildInputs` (List of Attribute Set; _optional_)
: Works as defined in `fetchurl`, but it is also augmented by `fetchzip` to include packages to deal with additional archives (such as `.zip`).
_Default value:_ `[]`.
`postFetch` (String; _optional_)
: Works as defined in `fetchurl`, but it is also augmented with the code needed to make `fetchzip` work.
:::{.caution}
It is only safe to modify files in `$out` in `postFetch`.
Consult the implementation of `fetchzip` for anything more involved.
:::
_Default value:_ `""`.
`stripRoot` (Boolean; _optional_)
: If `true`, the decompressed contents are moved one level up the directory tree.
This is useful for archives that decompress into a single directory which commonly includes some values that change with time, such as version numbers.
When this is the case (and `stripRoot` is `true`), `fetchzip` will remove this directory and make the decompressed contents available in the top-level directory.
[](#ex-fetchers-fetchzip-simple-striproot) shows what this attribute does.
This attribute is **not** passed through to `fetchurl`.
_Default value:_ `true`.
`extension` (String or Null; _optional_)
: If set, the archive downloaded by `fetchzip` will be renamed to a filename with the extension specified in this attribute.
This is useful when making `fetchzip` support additional types of archives, because the implementation may use the extension of an archive to determine whether they can decompress it.
If the URL you're using to download the contents doesn't end with the extension associated with the archive, use this attribute to fix the filename of the archive.
This attribute is **not** passed through to `fetchurl`.
_Default value:_ `null`.
`recursiveHash` (Boolean; _optional_)
: Works [as defined in `fetchurl`](#sec-pkgs-fetchers-fetchurl-inputs-recursiveHash), but its default value is different than for `fetchurl`.
_Default value:_ `true`.
`downloadToTemp` (Boolean; _optional_)
: Works [as defined in `fetchurl`](#sec-pkgs-fetchers-fetchurl-inputs-downloadToTemp), but its default value is different than for `fetchurl`.
_Default value:_ `true`.
`extraPostFetch` **DEPRECATED**
: This attribute is deprecated.
Please use `postFetch` instead.
This attribute is **not** passed through to `fetchurl`.
### Examples {#sec-pkgs-fetchers-fetchzip-examples}
::::{.example #ex-fetchers-fetchzip-simple-striproot}
# Using `fetchzip` to output contents directly
The following recipe shows how to use `fetchzip` to decompress a `.tar.gz` archive:
```nix
{ fetchzip }:
fetchzip {
url = "https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0.tar.gz";
hash = "sha256-3ABYlME9R8klcpJ7MQpyFEFwHmxDDEzIYBqu/CpDYmg=";
}
```
This archive has all its contents in a directory named `patchelf-0.18.0`.
This means that after decompressing, you'd have to enter this directory to see the contents of the archive.
However, `fetchzip` makes this easier through the attribute `stripRoot` (enabled by default).
After building the recipe, the derivation output will show all the files in the archive at the top level:
```shell
$ nix-build
(output removed for clarity)
/nix/store/1b7h3fvmgrcddvs0m299hnqxlgli1yjw-source
$ ls /nix/store/1b7h3fvmgrcddvs0m299hnqxlgli1yjw-source
aclocal.m4 completions configure.ac m4 Makefile.in patchelf.spec README.md tests
build-aux configure COPYING Makefile.am patchelf.1 patchelf.spec.in src version
```
If `stripRoot` is set to `false`, the derivation output will be the decompressed archive as-is:
```nix
{ fetchzip }:
fetchzip {
url = "https://github.com/NixOS/patchelf/releases/download/0.18.0/patchelf-0.18.0.tar.gz";
hash = "sha256-uv3FuKE4DqpHT3yfE0qcnq0gYjDNQNKZEZt2+PUAneg=";
stripRoot = false;
}
```
:::{.caution}
The hash changed!
Whenever changing attributes of a Nixpkgs fetcher, [remember to invalidate the hash](#chap-pkgs-fetchers-caveats), otherwise you won't get the results you're expecting!
:::
After building the recipe:
```shell
$ nix-build
(output removed for clarity)
/nix/store/2hy5bxw7xgbgxkn0i4x6hjr8w3dbx16c-source
$ ls /nix/store/2hy5bxw7xgbgxkn0i4x6hjr8w3dbx16c-source
patchelf-0.18.0
```
::::
::::{.example #ex-fetchers-fetchzip-rar-archive}
# Using `fetchzip` to decompress a `.rar` file
The `unrar` package provides a [setup hook](#ssec-setup-hooks) to decompress `.rar` archives during the [unpack phase](#ssec-unpack-phase), which can be used with `fetchzip` to decompress those archives:
```nix
{ fetchzip, unrar }:
fetchzip {
url = "https://archive.org/download/SpaceCadet_Plus95/Space_Cadet.rar";
hash = "sha256-fC+zsR8BY6vXpUkVd6i1jF0IZZxVKVvNi6VWCKT+pA4=";
stripRoot = false;
nativeBuildInputs = [ unrar ];
}
```
Since this particular `.rar` file doesn't put its contents in a directory inside the archive, `stripRoot` must be set to `false`.
After building the recipe, the derivation output will show the decompressed files:
```shell
$ nix-build
(output removed for clarity)
/nix/store/zpn7knxfva6rfjja2gbb4p3l9w1f0d36-source
$ ls /nix/store/zpn7knxfva6rfjja2gbb4p3l9w1f0d36-source
FONT.DAT PINBALL.DAT PINBALL.EXE PINBALL2.MID TABLE.BMP WMCONFIG.EXE
MSCREATE.DIR PINBALL.DOC PINBALL.MID Sounds WAVEMIX.INF
```
::::
The main difference between `fetchurl` and `fetchzip` is in how they store the contents. `fetchurl` will store the unaltered contents of the URL within the Nix store. `fetchzip` on the other hand, will decompress the archive for you, making files and directories directly accessible in the future. `fetchzip` can only be used with archives. Despite the name, `fetchzip` is not limited to .zip files and can also be used with any tarball.
## `fetchpatch` {#fetchpatch}
@@ -718,16 +111,15 @@ A wrapper around `fetchpatch`, which takes:
Here is an example of `fetchDebianPatch` in action:
```nix
{
lib,
fetchDebianPatch,
buildPythonPackage,
{ lib
, fetchDebianPatch
, buildPythonPackage
}:
buildPythonPackage rec {
pname = "pysimplesoap";
version = "1.16.2";
src = <...>;
src = ...;
patches = [
(fetchDebianPatch {
@@ -738,7 +130,7 @@ buildPythonPackage rec {
})
];
# ...
...
}
```
@@ -760,66 +152,25 @@ Used with Subversion. Expects `url` to a Subversion directory, `rev`, and `hash`
Used with Git. Expects `url` to a Git repo, `rev`, and `hash`. `rev` in this case can be full the git commit id (SHA1 hash) or a tag name like `refs/tags/v1.0`.
If you want to fetch a tag you should pass the `tag` parameter instead of `rev` which has the same effect as setting `rev = "refs/tags"/${version}"`.
This is safer than just setting `rev = version` w.r.t. possible branch and tag name conflicts.
Additionally, the following optional arguments can be given: `fetchSubmodules = true` makes `fetchgit` also fetch the submodules of a repository. If `deepClone` is set to true, the entire repository is cloned as opposing to just creating a shallow clone. `deepClone = true` also implies `leaveDotGit = true` which means that the `.git` directory of the clone won't be removed after checkout.
Additionally, the following optional arguments can be given:
If only parts of the repository are needed, `sparseCheckout` can be used. This will prevent git from fetching unnecessary blobs from server, see [git sparse-checkout](https://git-scm.com/docs/git-sparse-checkout) for more information:
*`fetchSubmodules`* (Boolean)
```nix
{ stdenv, fetchgit }:
: Whether to also fetch the submodules of a repository.
*`fetchLFS`* (Boolean)
: Whether to fetch LFS objects.
*`postFetch`* (String)
: Shell code executed after the file has been fetched successfully.
This can do things like check or transform the file.
*`leaveDotGit`* (Boolean)
: Whether the `.git` directory of the clone should *not* be removed after checkout.
Be warned though that the git repository format is not stable and this flag is therefore not suitable for actual use by itself.
Only use this for testing purposes or in conjunction with removing the `.git` directory in `postFetch`.
*`deepClone`* (Boolean)
: Clone the entire repository as opposing to just creating a shallow clone.
This implies `leaveDotGit`.
*`sparseCheckout`* (List of String)
: Prevent git from fetching unnecessary blobs from server.
This is useful if only parts of the repository are needed.
::: {.example #ex-fetchgit-sparseCheckout}
# Use `sparseCheckout` to only include some directories:
```nix
{ stdenv, fetchgit }:
stdenv.mkDerivation {
name = "hello";
src = fetchgit {
url = "https://...";
sparseCheckout = [
"directory/to/be/included"
"another/directory"
];
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
}
```
:::
See [git sparse-checkout](https://git-scm.com/docs/git-sparse-checkout) for more information.
Some additional parameters for niche use-cases can be found listed in the function parameters in the declaration of `fetchgit`: `pkgs/build-support/fetchgit/default.nix`.
Future parameters additions might also happen without immediately being documented here.
stdenv.mkDerivation {
name = "hello";
src = fetchgit {
url = "https://...";
sparseCheckout = [
"directory/to/be/included"
"another/directory"
];
hash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
};
}
```
## `fetchfossil` {#fetchfossil}
@@ -841,7 +192,7 @@ A number of fetcher functions wrap part of `fetchurl` and `fetchzip`. They are m
## `fetchFromGitHub` {#fetchfromgithub}
`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. If you need to fetch a tag however, you should prefer to use the `tag` parameter which achieves this in a safer way with less boilerplate. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred.
`fetchFromGitHub` expects four arguments. `owner` is a string corresponding to the GitHub user or organization that controls this repository. `repo` corresponds to the name of the software repository. These are located at the top of every GitHub HTML page as `owner`/`repo`. `rev` corresponds to the Git commit hash or tag (e.g `v1.0`) that will be downloaded from Git. Finally, `hash` corresponds to the hash of the extracted directory. Again, other hash algorithms are also available, but `hash` is currently preferred.
To use a different GitHub instance, use `githubBase` (defaults to `"github.com"`).
@@ -888,7 +239,7 @@ This is a useful last-resort workaround for license restrictions that prohibit r
If the requested file is present in the Nix store, the resulting derivation will not be built, because its expected output is already available.
Otherwise, the builder will run, but fail with a message explaining to the user how to provide the file. The following code, for example:
```nix
```
requireFile {
name = "jdk-${version}_linux-x64_bin.tar.gz";
url = "https://www.oracle.com/java/technologies/javase-jdk11-downloads.html";
@@ -907,23 +258,17 @@ or
***
```
This function should only be used by non-redistributable software with an unfree license that we need to require the user to download manually.
It produces packages that cannot be built automatically.
## `fetchtorrent` {#fetchtorrent}
`fetchtorrent` expects two arguments. `url` which can either be a Magnet URI (Magnet Link) such as `magnet:?xt=urn:btih:dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c` or an HTTP URL pointing to a `.torrent` file. It can also take a `config` argument which will craft a `settings.json` configuration file and give it to `transmission`, the underlying program that is performing the fetch. The available config options for `transmission` can be found [here](https://github.com/transmission/transmission/blob/main/docs/Editing-Configuration-Files.md#options)
```nix
```
{ fetchtorrent }:
fetchtorrent {
config = {
peer-limit-global = 100;
};
config = { peer-limit-global = 100; };
url = "magnet:?xt=urn:btih:dd8255ecdc7ca55fb0bbf81323d87062db1f6d1c";
hash = "";
sha256 = "";
}
```

View File

@@ -1,74 +0,0 @@
# Fixed-point arguments of build helpers {#chap-build-helpers-finalAttrs}
As mentioned in the beginning of this part, `stdenv.mkDerivation` could alternatively accept a fixed-point function. The input of such 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**.
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.
## Defining a build helper with `lib.extendMkDerivation` {#sec-build-helper-extendMkDerivation}
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).
Beside overriding, `lib.extendMkDerivation` also supports `excludeDrvArgNames` to optionally exclude some arguments in the input fixed-point argumnts from passing down the base build helper (specified as `constructDrv`).
:::{.example #ex-build-helpers-extendMkDerivation}
# Example definition of `mkLocalDerivation` extended from `stdenv.mkDerivation` with `lib.extendMkDerivation`
We want to define a build helper named `mkLocalDerivation` that builds locally without using substitutes by default.
Instead of taking a plain attribute set,
```nix
{
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 accepts the the attribute set's fixed point passing to the underlying `stdenv.mkDerivation`, named `finalAttrs` here:
```nix
lib.extendMkDerivation {
constructDrv = stdenv.mkDerivation;
excludeDrvArgNames = [
# Don't pass specialArg into mkDerivation.
"specialArg"
];
extendDrvArgs =
finalAttrs:
{
preferLocalBuild ? true,
allowSubstitute ? false,
specialArg ? (_: false),
...
}@args:
{
# Arguments to pass
inherit
preferLocalBuild
allowSubstitute
;
# Some expressions involving specialArg
greeting = if specialArg "hi" then "hi" else "hello";
};
}
```
:::
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

@@ -6,6 +6,7 @@ This chapter describes tools for creating various types of images.
images/appimagetools.section.md
images/dockertools.section.md
images/ocitools.section.md
images/snaptools.section.md
images/portableservice.section.md
images/makediskimage.section.md
images/binarycache.section.md

View File

@@ -33,7 +33,7 @@ let
version = "0.6.30";
src = fetchurl {
url = "https://github.com/nukeop/nuclear/releases/download/v${version}/nuclear-v${version}.AppImage";
url = "https://github.com/nukeop/nuclear/releases/download/v${version}/${pname}-v${version}.AppImage";
hash = "sha256-he1uGC1M/nFcKpMM9JKY4oeexJcnzV0ZRxhTjtJz6xw=";
};
in
@@ -64,10 +64,9 @@ let
src = fetchurl {
url = "https://github.com/irccloud/irccloud-desktop/releases/download/v${version}/IRCCloud-${version}-linux-x86_64.AppImage";
hash = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
sha256 = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
};
in
appimageTools.wrapType2 {
in appimageTools.wrapType2 {
inherit pname version src;
extraPkgs = pkgs: [ pkgs.at-spi2-core ];
}
@@ -101,14 +100,13 @@ let
src = fetchurl {
url = "https://github.com/irccloud/irccloud-desktop/releases/download/v${version}/IRCCloud-${version}-linux-x86_64.AppImage";
hash = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
sha256 = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
};
appimageContents = appimageTools.extract {
inherit pname version src;
};
in
appimageTools.wrapType2 {
in appimageTools.wrapType2 {
inherit pname version src;
extraPkgs = pkgs: [ pkgs.at-spi2-core ];
@@ -119,7 +117,7 @@ appimageTools.wrapType2 {
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=${pname}'
--replace 'Exec=AppRun' 'Exec=${pname}'
'';
}
```
@@ -143,17 +141,16 @@ let
src = fetchurl {
url = "https://github.com/irccloud/irccloud-desktop/releases/download/v${version}/IRCCloud-${version}-linux-x86_64.AppImage";
hash = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
sha256 = "sha256-/hMPvYdnVB1XjKgU2v47HnVvW4+uC3rhRjbucqin4iI=";
};
appimageContents = appimageTools.extract {
inherit pname version src;
postExtract = ''
substituteInPlace $out/irccloud.desktop --replace-fail 'Exec=AppRun' 'Exec=${pname}'
substituteInPlace $out/irccloud.desktop --replace 'Exec=AppRun' 'Exec=${pname}'
'';
};
in
appimageTools.wrapType2 {
in appimageTools.wrapType2 {
inherit pname version src;
extraPkgs = pkgs: [ pkgs.at-spi2-core ];

View File

@@ -27,7 +27,7 @@ The following derivation will construct a flat-file binary cache containing the
```nix
{ mkBinaryCache, hello }:
mkBinaryCache {
rootPaths = [ hello ];
rootPaths = [hello];
}
```

File diff suppressed because it is too large Load Diff

View File

@@ -52,23 +52,23 @@ A `deterministic` flag is available for best efforts determinism.
To produce a Nix-store only image:
```nix
let
pkgs = import <nixpkgs> { };
pkgs = import <nixpkgs> {};
lib = pkgs.lib;
make-disk-image = import <nixpkgs/nixos/lib/make-disk-image.nix>;
in
make-disk-image {
inherit pkgs lib;
config = { };
additionalPaths = [ ];
format = "qcow2";
onlyNixStore = true;
partitionTableType = "none";
installBootLoader = false;
touchEFIVars = false;
diskSize = "auto";
additionalSpace = "0M"; # Defaults to 512M.
copyChannel = false;
}
make-disk-image {
inherit pkgs lib;
config = {};
additionalPaths = [ ];
format = "qcow2";
onlyNixStore = true;
partitionTableType = "none";
installBootLoader = false;
touchEFIVars = false;
diskSize = "auto";
additionalSpace = "0M"; # Defaults to 512M.
copyChannel = false;
}
```
Some arguments can be left out, they are shown explicitly for the sake of the example.
@@ -78,36 +78,31 @@ Building this derivation will provide a QCOW2 disk image containing only the Nix
To produce a NixOS installation image disk with UEFI and bootloader installed:
```nix
let
pkgs = import <nixpkgs> { };
pkgs = import <nixpkgs> {};
lib = pkgs.lib;
make-disk-image = import <nixpkgs/nixos/lib/make-disk-image.nix>;
evalConfig = import <nixpkgs/nixos/lib/eval-config.nix>;
in
make-disk-image {
inherit pkgs lib;
inherit
(evalConfig {
make-disk-image {
inherit pkgs lib;
config = evalConfig {
modules = [
{
fileSystems."/" = {
device = "/dev/vda";
fsType = "ext4";
autoFormat = true;
};
fileSystems."/" = { device = "/dev/vda"; fsType = "ext4"; autoFormat = true; };
boot.grub.device = "/dev/vda";
}
];
})
config
;
format = "qcow2";
onlyNixStore = false;
partitionTableType = "legacy+gpt";
installBootLoader = true;
touchEFIVars = true;
diskSize = "auto";
additionalSpace = "0M"; # Defaults to 512M.
copyChannel = false;
memSize = 2048; # Qemu VM memory size in megabytes. Defaults to 1024M.
}
};
format = "qcow2";
onlyNixStore = false;
partitionTableType = "legacy+gpt";
installBootLoader = true;
touchEFIVars = true;
diskSize = "auto";
additionalSpace = "0M"; # Defaults to 512M.
copyChannel = false;
memSize = 2048; # Qemu VM memory size in megabytes. Defaults to 1024M.
}
```

View File

@@ -1,108 +1,37 @@
# pkgs.ociTools {#sec-pkgs-ociTools}
`pkgs.ociTools` is a set of functions for creating runtime container bundles according to the [OCI runtime specification v1.0.0](https://github.com/opencontainers/runtime-spec/blob/v1.0.0/spec.md).
It makes no assumptions about the container runner you choose to use to run the created container.
The set of functions in `pkgs.ociTools` currently does not handle the [OCI image specification](https://github.com/opencontainers/image-spec).
At a high-level an OCI implementation would download an OCI Image then unpack that image into an OCI Runtime filesystem bundle.
At this point the OCI Runtime Bundle would be run by an OCI Runtime.
`pkgs.ociTools` provides utilities to create OCI Runtime bundles.
`pkgs.ociTools` is a set of functions for creating containers according to the [OCI container specification v1.0.0](https://github.com/opencontainers/runtime-spec). Beyond that, it makes no assumptions about the container runner you choose to use to run the created container.
## buildContainer {#ssec-pkgs-ociTools-buildContainer}
This function creates an OCI runtime container (consisting of a `config.json` and a root filesystem directory) that runs a single command inside of it.
The nix store of the container will contain all referenced dependencies of the given command.
This function creates a simple OCI container that runs a single command inside of it. An OCI container consists of a `config.json` and a rootfs directory. The nix store of the container will contain all referenced dependencies of the given command.
This function has an assumption that the container will run on POSIX platforms, and sets configurations (such as the user running the process or certain mounts) according to this assumption.
Because of this, a container built with `buildContainer` will not work on Windows or other non-POSIX platforms without modifications to the container configuration.
These modifications aren't supported by `buildContainer`.
For `linux` platforms, `buildContainer` also configures the following namespaces (see {manpage}`unshare(1)`) to isolate the OCI container from the global namespace:
PID, network, mount, IPC, and UTS.
Note that no user namespace is created, which means that you won't be able to run the container unless you are the `root` user.
### Inputs {#ssec-pkgs-ociTools-buildContainer-inputs}
`buildContainer` expects an argument with the following attributes:
`args` (List of String)
: Specifies a set of arguments to run inside the container.
Any packages referenced by `args` will be made available inside the container.
`mounts` (Attribute Set; _optional_)
: Would specify additional mounts that the runtime must make available to the container.
:::{.warning}
As explained in [issue #290879](https://github.com/NixOS/nixpkgs/issues/290879), this attribute is currently ignored.
:::
:::{.note}
`buildContainer` includes a minimal set of necessary filesystems to be mounted into the container, and this set can't be changed with the `mounts` attribute.
:::
_Default value:_ `{}`.
`readonly` (Boolean; _optional_)
: If `true`, sets the container's root filesystem as read-only.
_Default value:_ `false`.
`os` **DEPRECATED**
: Specifies the operating system on which the container filesystem is based on.
If specified, its value should follow the [OCI Image Configuration Specification](https://github.com/opencontainers/image-spec/blob/main/config.md#properties).
According to the linked specification, all possible values for `$GOOS` in [the Go docs](https://go.dev/doc/install/source#environment) should be valid, but will commonly be one of `darwin` or `linux`.
_Default value:_ `"linux"`.
`arch` **DEPRECATED**
: Used to specify the architecture for which the binaries in the container filesystem have been compiled.
If specified, its value should follow the [OCI Image Configuration Specification](https://github.com/opencontainers/image-spec/blob/main/config.md#properties).
According to the linked specification, all possible values for `$GOARCH` in [the Go docs](https://go.dev/doc/install/source#environment) should be valid, but will commonly be one of `386`, `amd64`, `arm`, or `arm64`.
_Default value:_ `x86_64`.
### Examples {#ssec-pkgs-ociTools-buildContainer-examples}
::: {.example #ex-ociTools-buildContainer-bash}
# Creating an OCI runtime container that runs `bash`
This example uses `ociTools.buildContainer` to create a simple container that runs `bash`.
The parameters of `buildContainer` with an example value are described below:
```nix
{
ociTools,
lib,
bash,
}:
ociTools.buildContainer {
buildContainer {
args = [
(lib.getExe bash)
(with pkgs;
writeScript "run.sh" ''
#!${bash}/bin/bash
exec ${bash}/bin/bash
'').outPath
];
mounts = {
"/data" = {
type = "none";
source = "/var/lib/mydata";
options = [ "bind" ];
};
};
readonly = false;
}
```
As an example of how to run the container generated by this package, we'll use `runc` to start the container.
Any other tool that supports OCI containers could be used instead.
- `args` specifies a set of arguments to run inside the container. This is the only required argument for `buildContainer`. All referenced packages inside the derivation will be made available inside the container.
```shell
$ nix-build
(some output removed for clarity)
/nix/store/7f9hgx0arvhzp2a3qphp28rxbn748l25-join
- `mounts` specifies additional mount points chosen by the user. By default only a minimal set of necessary filesystems are mounted into the container (e.g procfs, cgroupfs)
$ cd /nix/store/7f9hgx0arvhzp2a3qphp28rxbn748l25-join
$ nix-shell -p runc
[nix-shell:/nix/store/7f9hgx0arvhzp2a3qphp28rxbn748l25-join]$ sudo runc run ocitools-example
help
GNU bash, version 5.2.26(1)-release (x86_64-pc-linux-gnu)
(some output removed for clarity)
```
:::
- `readonly` makes the container's rootfs read-only if it is set to true. The default value is false `false`.

View File

@@ -1,188 +1,81 @@
# pkgs.portableService {#sec-pkgs-portableService}
`pkgs.portableService` is a function to create [Portable Services](https://systemd.io/PORTABLE_SERVICES/) in a read-only, immutable, `squashfs` raw disk image.
This lets you use Nix to build images which can be run on many recent Linux distributions.
`pkgs.portableService` is a function to create _portable service images_,
as read-only, immutable, `squashfs` archives.
systemd supports a concept of [Portable Services](https://systemd.io/PORTABLE_SERVICES/).
Portable Services are a delivery method for system services that uses two specific features of container management:
* Applications are bundled. I.e. multiple services, their binaries and
all their dependencies are packaged in an image, and are run directly from it.
* Stricter default security policies, i.e. sandboxing of applications.
This allows using Nix to build images which can be run on many recent Linux distributions.
The primary tool for interacting with Portable Services is `portablectl`,
and they are managed by the `systemd-portabled` system service.
::: {.note}
Portable services are supported starting with systemd 239 (released on 2018-06-22).
:::
The generated image will contain the file system structure as required by the Portable Services specification, along with the packages given to `portableService` and all of their dependencies.
When generated, the image will exist in the Nix store with the `.raw` file extension, as required by the specification.
See [](#ex-portableService-hello) to understand how to use the output of `portableService`.
## Inputs {#ssec-pkgs-portableService-inputs}
`portableService` expects one argument with the following attributes:
`pname` (String)
: The name of the portable service.
The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification.
`version` (String)
: The version of the portable service.
The generated image will be named according to the template `$pname_$version.raw`, which is supported by the Portable Services specification.
`units` (List of Attribute Set)
: A list of derivations for systemd unit files.
Each derivation must produce a single file, and must have a name that starts with the value of `pname` and ends with the suffix of the unit type (e.g. ".service", ".socket", ".timer", and so on).
See [](#ex-portableService-hello) to better understand this naming constraint.
`description` (String or Null; _optional_)
: If specified, the value is added as `PORTABLE_PRETTY_NAME` to the `/etc/os-release` file in the generated image.
This could be used to provide more information to anyone inspecting the image.
_Default value:_ `null`.
`homepage` (String or Null; _optional_)
: If specified, the value is added as `HOME_URL` to the `/etc/os-release` file in the generated image.
This could be used to provide more information to anyone inspecting the image.
_Default value:_ `null`.
`symlinks` (List of Attribute Set; _optional_)
: A list of attribute sets in the format `{object, symlink}`.
For each item in the list, `portableService` will create a symlink in the path specified by `symlink` (relative to the root of the image) that points to `object`.
All packages that `object` depends on and their dependencies are automatically copied into the image.
This can be used to create symlinks for applications that assume some files to exist globally (`/etc/ssl` or `/bin/bash`, for example).
See [](#ex-portableService-symlinks) to understand how to do that.
_Default value:_ `[]`.
`contents` (List of Attribute Set; _optional_)
: A list of additional derivations to be included as-is in the image.
These derivations will be included directly in a `/nix/store` directory inside the image.
_Default value:_ `[]`.
`squashfsTools` (Attribute Set; _optional_)
: Allows you to override the package that provides {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `pkgs.squashfsTools`.
`squash-compression` (String; _optional_)
: Passed as the compression option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `"xz -Xdict-size 100%"`.
`squash-block-size` (String; _optional_)
: Passed as the block size option to {manpage}`mksquashfs(1)`, which is used internally by `portableService`.
_Default value:_ `"1M"`.
## Examples {#ssec-pkgs-portableService-examples}
A very simple example of using `portableService` is described below:
[]{#ex-pkgs-portableService}
:::{.example #ex-portableService-hello}
# Building a Portable Service image
The following example builds a Portable Service image with the `hello` package, along with a service unit that runs it.
```nix
{
lib,
writeText,
portableService,
hello,
}:
let
hello-service = writeText "hello.service" ''
[Unit]
Description=Hello world service
[Service]
Type=oneshot
ExecStart=${lib.getExe hello}
'';
in
portableService {
pname = "hello";
inherit (hello) version;
units = [ hello-service ];
pkgs.portableService {
pname = "demo";
version = "1.0";
units = [ demo-service demo-socket ];
}
```
After building the package, the generated image can be loaded into a system through {manpage}`portablectl(1)`:
The above example will build an squashfs archive image in `result/$pname_$version.raw`. The image will contain the
file system structure as required by the portable service specification, and a subset of the Nix store with all the
dependencies of the two derivations in the `units` list.
`units` must be a list of derivations, and their names must be prefixed with the service name (`"demo"` in this case).
Otherwise `systemd-portabled` will ignore them.
```shell
$ nix-build
(some output removed for clarity)
/nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1
$ portablectl attach /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw
Created directory /etc/systemd/system.attached.
Created directory /etc/systemd/system.attached/hello.service.d.
Written /etc/systemd/system.attached/hello.service.d/20-portable.conf.
Created symlink /etc/systemd/system.attached/hello.service.d/10-profile.conf → /usr/lib/systemd/portable/profile/default/service.conf.
Copied /etc/systemd/system.attached/hello.service.
Created symlink /etc/portables/hello_2.12.1.raw → /nix/store/8c20z1vh7z8w8dwagl8w87b45dn5k6iq-hello-img-2.12.1/hello_2.12.1.raw.
$ systemctl start hello
$ journalctl -u hello
Feb 28 22:39:16 hostname systemd[1]: Starting Hello world service...
Feb 28 22:39:16 hostname hello[102887]: Hello, world!
Feb 28 22:39:16 hostname systemd[1]: hello.service: Deactivated successfully.
Feb 28 22:39:16 hostname systemd[1]: Finished Hello world service.
$ portablectl detach hello_2.12.1
Removed /etc/systemd/system.attached/hello.service.
Removed /etc/systemd/system.attached/hello.service.d/10-profile.conf.
Removed /etc/systemd/system.attached/hello.service.d/20-portable.conf.
Removed /etc/systemd/system.attached/hello.service.d.
Removed /etc/portables/hello_2.12.1.raw.
Removed /etc/systemd/system.attached.
```
::: {.note}
The `.raw` file extension of the image is required by the portable services specification.
:::
:::{.example #ex-portableService-symlinks}
# Specifying symlinks when building a Portable Service image
Some other options available are:
- `description`, `homepage`
Some services may expect files or directories to be available globally.
An example is a service which expects all trusted SSL certificates to exist in a specific location by default.
Are added to the `/etc/os-release` in the image and are shown by the portable services tooling.
Default to empty values, not added to os-release.
- `symlinks`
To make things available globally, you must specify the `symlinks` attribute when using `portableService`.
The following package builds on the package from [](#ex-portableService-hello) to make `/etc/ssl` available globally (this is only for illustrative purposes, because `hello` doesn't use `/etc/ssl`).
A list of attribute sets {object, symlink}. Symlinks will be created in the root filesystem of the image to
objects in the Nix store. Defaults to an empty list.
- `contents`
A list of additional derivations to be included in the image Nix store, as-is. Defaults to an empty list.
- `squashfsTools`
Defaults to `pkgs.squashfsTools`, allows you to override the package that provides `mksquashfs`.
- `squash-compression`, `squash-block-size`
Options to `mksquashfs`. Default to `"xz -Xdict-size 100%"` and `"1M"` respectively.
A typical usage of `symlinks` would be:
```nix
{
lib,
writeText,
portableService,
hello,
cacert,
}:
let
hello-service = writeText "hello.service" ''
[Unit]
Description=Hello world service
[Service]
Type=oneshot
ExecStart=${lib.getExe hello}
'';
in
portableService {
pname = "hello";
inherit (hello) version;
units = [ hello-service ];
symlinks = [
{
object = "${cacert}/etc/ssl";
symlink = "/etc/ssl";
}
{ object = "${pkgs.cacert}/etc/ssl"; symlink = "/etc/ssl"; }
{ object = "${pkgs.bash}/bin/bash"; symlink = "/bin/sh"; }
{ object = "${pkgs.php}/bin/php"; symlink = "/usr/bin/php"; }
];
}
```
to create these symlinks for legacy applications that assume them existing globally.
Once the image is created, and deployed on a host in `/var/lib/portables/`, you can attach the image and run the service. As root run:
```console
portablectl attach demo_1.0.raw
systemctl enable --now demo.socket
systemctl enable --now demo.service
```
::: {.note}
See the [man page](https://www.freedesktop.org/software/systemd/man/portablectl.html) of `portablectl` for more info on its usage.
:::

View File

@@ -0,0 +1,71 @@
# pkgs.snapTools {#sec-pkgs-snapTools}
`pkgs.snapTools` is a set of functions for creating Snapcraft images. Snap and Snapcraft is not used to perform these operations.
## The makeSnap Function {#ssec-pkgs-snapTools-makeSnap-signature}
`makeSnap` takes a single named argument, `meta`. This argument mirrors [the upstream `snap.yaml` format](https://docs.snapcraft.io/snap-format) exactly.
The `base` should not be specified, as `makeSnap` will force set it.
Currently, `makeSnap` does not support creating GUI stubs.
## Build a Hello World Snap {#ssec-pkgs-snapTools-build-a-snap-hello}
The following expression packages GNU Hello as a Snapcraft snap.
``` {#ex-snapTools-buildSnap-hello .nix}
let
inherit (import <nixpkgs> { }) snapTools hello;
in snapTools.makeSnap {
meta = {
name = "hello";
summary = hello.meta.description;
description = hello.meta.longDescription;
architectures = [ "amd64" ];
confinement = "strict";
apps.hello.command = "${hello}/bin/hello";
};
}
```
`nix-build` this expression and install it with `snap install ./result --dangerous`. `hello` will now be the Snapcraft version of the package.
## Build a Graphical Snap {#ssec-pkgs-snapTools-build-a-snap-firefox}
Graphical programs require many more integrations with the host. This example uses Firefox as an example because it is one of the most complicated programs we could package.
``` {#ex-snapTools-buildSnap-firefox .nix}
let
inherit (import <nixpkgs> { }) snapTools firefox;
in snapTools.makeSnap {
meta = {
name = "nix-example-firefox";
summary = firefox.meta.description;
architectures = [ "amd64" ];
apps.nix-example-firefox = {
command = "${firefox}/bin/firefox";
plugs = [
"pulseaudio"
"camera"
"browser-support"
"avahi-observe"
"cups-control"
"desktop"
"desktop-legacy"
"gsettings"
"home"
"network"
"mount-observe"
"removable-media"
"x11"
];
};
confinement = "strict";
};
}
```
`nix-build` this expression and install it with `snap install ./result --dangerous`. `nix-example-firefox` will now be the Snapcraft version of the Firefox package.
The specific meaning behind plugs can be looked up in the [Snapcraft interface documentation](https://docs.snapcraft.io/supported-interfaces).

View File

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

View File

@@ -9,26 +9,20 @@ However, we can tell Nix explicitly what the previous build state was, by repres
To change a normal derivation to a checkpoint based build, these steps must be taken:
- apply `prepareCheckpointBuild` on the desired derivation, e.g.
```nix
{
checkpointArtifacts = (pkgs.checkpointBuildTools.prepareCheckpointBuild pkgs.virtualbox);
}
checkpointArtifacts = (pkgs.checkpointBuildTools.prepareCheckpointBuild pkgs.virtualbox);
```
- change something you want in the sources of the package, e.g. use a source override:
```nix
{
changedVBox = pkgs.virtualbox.overrideAttrs (old: {
src = path/to/vbox/sources;
});
}
changedVBox = pkgs.virtualbox.overrideAttrs (old: {
src = path/to/vbox/sources;
});
```
- use `mkCheckpointBuild changedVBox checkpointArtifacts`
- enjoy shorter build times
## Example {#sec-checkpoint-build-example}
```nix
{
pkgs ? import <nixpkgs> { },
}:
{ pkgs ? import <nixpkgs> {} }:
let
inherit (pkgs.checkpointBuildTools)
prepareCheckpointBuild
@@ -41,6 +35,5 @@ let
sed -i 's/Hello, world!/Hello, Nix!/g' src/hello.c
'';
});
in
mkCheckpointBuild changedHello helloCheckpoint
in mkCheckpointBuild changedHello helloCheckpoint
```

View File

@@ -1,84 +0,0 @@
# fakeNss {#sec-fakeNss}
Provides `/etc/passwd` and `/etc/group` files that contain `root` and `nobody`, allowing user/group lookups to work in binaries that insist on doing those.
This might be a better choice than a custom script running `useradd` and related utilities if you only need those files to exist with some entries.
`fakeNss` also provides `/etc/nsswitch.conf`, configuring NSS host resolution to first check `/etc/hosts` before checking DNS, since the default in the absence of a config file (`dns [!UNAVAIL=return] files`) is quite unexpected.
It also creates an empty directory at `/var/empty` because it uses that as the home directory for the `root` and `nobody` users.
The `/var/empty` directory can also be used as a `chroot` target to prevent file access in processes that do not need to access files, if your container runs such processes.
The user entries created by `fakeNss` use the `/bin/sh` shell, which is not provided by `fakeNss` because in most cases it won't be used.
If you need that to be available, see [`dockerTools.binSh`](#sssec-pkgs-dockerTools-helpers-binSh) or provide your own.
## Inputs {#sec-fakeNss-inputs}
`fakeNss` is made available in Nixpkgs as a package rather than a function, but it has two attributes that can be overridden and might be useful in particular cases.
For more details on how overriding works, see [](#ex-fakeNss-overriding) and [](#sec-pkg-override).
`extraPasswdLines` (List of Strings; _optional_)
: A list of lines that will be added to `/etc/passwd`.
Useful if extra users need to exist in the output of `fakeNss`.
If `extraPasswdLines` is specified, it will **not** override the `root` and `nobody` entries created by `fakeNss`.
Those entries will always exist.
Lines specified here must follow the format in {manpage}`passwd(5)`.
_Default value:_ `[]`.
`extraGroupLines` (List of Strings; _optional_)
: A list of lines that will be added to `/etc/group`.
Useful if extra groups need to exist in the output of `fakeNss`.
If `extraGroupLines` is specified, it will **not** override the `root` and `nobody` entries created by `fakeNss`.
Those entries will always exist.
Lines specified here must follow the format in {manpage}`group(5)`.
_Default value:_ `[]`.
## Examples {#sec-fakeNss-examples}
:::{.example #ex-fakeNss-dockerTools-buildImage}
# Using `fakeNss` with `dockerTools.buildImage`
This example shows how to use `fakeNss` as-is.
It is useful with functions in `dockerTools` to allow building Docker images that have the `/etc/passwd` and `/etc/group` files.
This example includes the `hello` binary in the image so it can do something besides just have the extra files.
```nix
{
dockerTools,
fakeNss,
hello,
}:
dockerTools.buildImage {
name = "image-with-passwd";
tag = "latest";
copyToRoot = [
fakeNss
hello
];
config = {
Cmd = [ "/bin/hello" ];
};
}
```
:::
:::{.example #ex-fakeNss-overriding}
# Using `fakeNss` with an override to add extra lines
The following code uses `override` to add extra lines to `/etc/passwd` and `/etc/group` to create another user and group entry.
```nix
{ fakeNss }:
fakeNss.override {
extraPasswdLines = [ "newuser:x:9001:9001:new user:/var/empty:/bin/sh" ];
extraGroupLines = [ "newuser:x:9001:" ];
}
```
:::

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