diff --git a/ci/eval/compare/default.nix b/ci/eval/compare/default.nix index 9b71c6656914..04676476f4b2 100644 --- a/ci/eval/compare/default.nix +++ b/ci/eval/compare/default.nix @@ -9,6 +9,7 @@ beforeResultDir, afterResultDir, touchedFilesJson, + byName ? false, }: let /* @@ -119,6 +120,7 @@ let maintainers = import ./maintainers.nix { changedattrs = lib.attrNames (lib.groupBy (a: a.name) rebuildsPackagePlatformAttrs); changedpathsjson = touchedFilesJson; + inherit byName; }; in runCommand "compare" diff --git a/ci/eval/compare/maintainers.nix b/ci/eval/compare/maintainers.nix index 69748a629cff..8fb43be4d8e7 100644 --- a/ci/eval/compare/maintainers.nix +++ b/ci/eval/compare/maintainers.nix @@ -1,5 +1,9 @@ # Almost directly vendored from https://github.com/NixOS/ofborg/blob/5a4e743f192fb151915fcbe8789922fa401ecf48/ofborg/src/maintainers.nix -{ changedattrs, changedpathsjson }: +{ + changedattrs, + changedpathsjson, + byName ? false, +}: let pkgs = import ../../.. { system = "x86_64-linux"; @@ -41,7 +45,18 @@ let ) validPackageAttributes; attrsWithMaintainers = builtins.map ( - pkg: pkg // { maintainers = (pkg.package.meta or { }).maintainers or [ ]; } + 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 [ ] + ++ lib.flatten (map (team: team.members or [ ]) (meta.teams or [ ])); + } ) attrsWithPackages; relevantFilenames = @@ -83,12 +98,13 @@ let 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.id) listToPing; + 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 diff --git a/doc/redirects.json b/doc/redirects.json index 46eb54c6c67b..627b4137281d 100644 --- a/doc/redirects.json +++ b/doc/redirects.json @@ -431,6 +431,9 @@ "typst-package-scope-and-usage": [ "index.html#typst-package-scope-and-usage" ], + "var-meta-teams": [ + "index.html#var-meta-teams" + ], "variables-specifying-dependencies": [ "index.html#variables-specifying-dependencies" ], diff --git a/doc/stdenv/meta.chapter.md b/doc/stdenv/meta.chapter.md index 2e29c75e7a99..908b97cac224 100644 --- a/doc/stdenv/meta.chapter.md +++ b/doc/stdenv/meta.chapter.md @@ -91,6 +91,10 @@ For details, see [Source provenance](#sec-meta-sourceProvenance). A list of the maintainers of this Nix expression. Maintainers are defined in [`nixpkgs/maintainers/maintainer-list.nix`](https://github.com/NixOS/nixpkgs/blob/master/maintainers/maintainer-list.nix). There is no restriction to becoming a maintainer, just add yourself to that list in a separate commit titled “maintainers: add alice” in the same pull request, and reference maintainers with `maintainers = with lib.maintainers; [ alice bob ]`. +### `teams` {#var-meta-teams} + +A list of the teams of this Nix expression. Teams are defined in [`nixpkgs/maintainers/team-list.nix`](https://github.com/NixOS/nixpkgs/blob/master/maintainers/team-list.nix), and can be defined in a package with `meta.teams = with lib.teams; [ team1 team2 ]`. + ### `mainProgram` {#var-meta-mainProgram} The name of the main binary for the package. This affects the binary `nix run` executes. Example: `"rg"` diff --git a/maintainers/scripts/README.md b/maintainers/scripts/README.md index 44a5fc9bc590..d2ab587fb397 100644 --- a/maintainers/scripts/README.md +++ b/maintainers/scripts/README.md @@ -57,6 +57,17 @@ The maintainer is designated by a `selector` which must be one of: [`maintainer-list.nix`]: ../maintainer-list.nix +### `get-maintainer-pings-between.sh` + +Gets which maintainers would be pinged between two Nixpkgs revisions. +Outputs a JSON object on stdout mapping GitHub usernames to the attributes +that they would be getting pinged for. + +Example: + +```sh +maintainers/scripts/get-maintainer-pings-between.sh HEAD^ HEAD +``` ## Conventions diff --git a/maintainers/scripts/get-maintainer-pings-between.sh b/maintainers/scripts/get-maintainer-pings-between.sh new file mode 100755 index 000000000000..4b6d7ff78052 --- /dev/null +++ b/maintainers/scripts/get-maintainer-pings-between.sh @@ -0,0 +1,78 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p git jq + +# Outputs a list of maintainers that would be pinged across two nixpkgs revisions. +# Authors: +# Morgan Jones (@numinit) +# Tristan Ross (@RossComputerGuy) + +set -euo pipefail + +if [ $# -lt 2 ]; then + echo "Usage: $0 " >&2 + exit 1 +fi + +repo="$(git rev-parse --show-toplevel)" +system="$(nix-instantiate --eval --expr builtins.currentSystem)" +rev1="$(git -C "$repo" rev-parse "$1")" +rev2="$(git -C "$repo" rev-parse "$2")" + +echo "Touched files:" >&2 +git -C "$repo" diff --name-only "$rev1" "$rev2" \ + | jq --raw-input --slurp 'split("\n")[:-1]' | tee "$TMPDIR/touched-files.json" >&2 + +# Runs an eval in the given worktree, outputting the path to $TMPDIR/$1.path. +# $1: The revision SHA. +eval_in_worktree() ( + mkdir -p .worktree + local rev="$1" + local tree=".worktree/$rev" + if [ ! -d "$tree" ]; then + git -C "$repo" worktree add -f -d "$tree" "$rev" >&2 + fi + cd "$tree" + + local workdir="$TMPDIR/$rev" + rm -rf "$workdir" + mkdir -p "$workdir" + + nix-build ci -A eval.attrpathsSuperset -o "$workdir/paths" >&2 + mkdir -p "$workdir/intermediates" + nix-build ci -A eval.singleSystem \ + --arg evalSystem "$system" \ + --arg attrpathFile "$workdir/paths/paths.json" \ + --arg chunkSize ${CHUNK_SIZE:-10000} \ + -o "$workdir/intermediates/.intermediate-1" >&2 + + # eval.combine nix-build needs a directory, not a symlink + cp -RL "$workdir/intermediates/.intermediate-1" "$workdir/intermediates/intermediate-1" + chmod -R +w "$workdir/intermediates/intermediate-1" + rm -rf "$workdir/intermediates/.intermediate-1" + + nix-build ci -A eval.combine \ + --arg resultsDir "$workdir/intermediates" \ + -o "$workdir/result" >&2 +) + +eval_in_worktree "$rev1" & +pid1=$! +eval_in_worktree "$rev2" & +pid2=$! + +wait $pid1 +wait $pid2 + +path1="$TMPDIR/$rev1" +path2="$TMPDIR/$rev2" + +# Use the repo this script was executed in to get accurate maintainer info +nix-build "$repo/ci" -A eval.compare \ + --arg beforeResultDir "$path1/result" \ + --arg afterResultDir "$path2/result" \ + --arg touchedFilesJson "$TMPDIR/touched-files.json" \ + --arg byName true \ + -o comparison + +echo "Pinged maintainers (check $repo/comparison for more details)" >&2 +jq < comparison/maintainers.json diff --git a/pkgs/stdenv/generic/check-meta.nix b/pkgs/stdenv/generic/check-meta.nix index 192f668b5ae8..0d6db8985019 100644 --- a/pkgs/stdenv/generic/check-meta.nix +++ b/pkgs/stdenv/generic/check-meta.nix @@ -108,7 +108,10 @@ let hasUnfreeLicense = attrs: hasLicense attrs && isUnfree attrs.meta.license; - hasNoMaintainers = attrs: attrs ? meta.maintainers && (length attrs.meta.maintainers) == 0; + hasNoMaintainers = + attrs: + (attrs ? meta.maintainers && (length attrs.meta.maintainers) == 0) + && (attrs ? meta.teams && (length attrs.meta.teams) == 0); isMarkedBroken = attrs: attrs.meta.broken or false; @@ -368,6 +371,7 @@ let ]; sourceProvenance = listOf attrs; maintainers = listOf (attrsOf any); # TODO use the maintainer type from lib/tests/maintainer-module.nix + teams = listOf (attrsOf any); # TODO similar to maintainers, use a teams type priority = int; pkgConfigModules = listOf str; inherit platforms; @@ -534,7 +538,7 @@ let { valid = "warn"; reason = "maintainerless"; - errormsg = "has no maintainers"; + errormsg = "has no maintainers or teams"; } # ----- else