diff --git a/.editorconfig b/.editorconfig index 2d877d20b825..6844b559c7b5 100644 --- a/.editorconfig +++ b/.editorconfig @@ -89,6 +89,13 @@ trim_trailing_whitespace = unset end_of_line = unset insert_final_newline = unset +# see https://manual.jule.dev/project/code-style.html#indentions +[*.jule] +indent_style = tab + +[jule.mod] +insert_final_newline = unset + # Keep this hint at the bottom: # Please don't add entries for subfolders here. # Create /.editorconfig instead. diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 21b1a014d933..9685de407b97 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -193,6 +193,10 @@ cffc27daf06c77c0d76bc35d24b929cb9d68c3c9 # nixos/kanidm: inherit lib, nixfmt 8f18393d380079904d072007fb19dc64baef0a3a +# fetchgit, fetchurl, fetchzip: +# format after refactoring with lib.extendMkDerivation (#455994) +aeddd850c6d3485fc1af2edfb111e58141d18dc1 + # fetchhg: format after refactoring with lib.extendMkDerivation and make overridable (#423539) 34a5b1eb23129f8fb62c677e3760903f6d43228f @@ -300,3 +304,6 @@ f7611cad5154a9096faa26d156a4079577bfae17 90e7159c559021ac4f4cc1222000f08a91feff69 # !autorebase nix-shell --run treefmt c283f32d296564fd649ef3ed268c1f1f7b199c49 # !autorebase nix-shell --run treefmt 91a8fee3aaf79348aa2dc1552a29fc1b786c5133 # !autorebase nix-shell --run treefmt + +# aliases: keep-sorted +48ce0739044bd6eba83c3a43bd4ad1046399cdad # !autorebase nix-shell --run treefmt diff --git a/.github/labeler-development-branches.yml b/.github/labeler-development-branches.yml index 5ce799c2f8d4..bb1c47a23fa0 100644 --- a/.github/labeler-development-branches.yml +++ b/.github/labeler-development-branches.yml @@ -1,4 +1,4 @@ -# This file is used by .github/workflows/labels.yml +# This file is used by .github/workflows/bot.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": diff --git a/.github/labeler-no-sync.yml b/.github/labeler-no-sync.yml index 65d54e81a0b2..99d1b85c3c7b 100644 --- a/.github/labeler-no-sync.yml +++ b/.github/labeler-no-sync.yml @@ -1,4 +1,4 @@ -# This file is used by .github/workflows/labels.yml +# This file is used by .github/workflows/bot.yml # This version uses `sync-labels: false`, meaning that a non-match will NOT remove the label # keep-sorted start case=no numeric=yes newline_separated=yes skip_lines=1 @@ -29,5 +29,6 @@ - .github/actions/* - .github/workflows/* - ci/**/*.* + - maintainers/github-teams.json # keep-sorted end diff --git a/.github/labeler.yml b/.github/labeler.yml index adfc49ef6ee2..abec7c37288c 100644 --- a/.github/labeler.yml +++ b/.github/labeler.yml @@ -1,4 +1,4 @@ -# This file is used by .github/workflows/labels.yml +# This file is used by .github/workflows/bot.yml # This version uses `sync-labels: true`, meaning that a non-match will remove the label # keep-sorted start case=no numeric=yes newline_separated=yes skip_lines=1 diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 2c739bd56129..4aed9617cae4 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -64,7 +64,7 @@ This results in a key with the following semantics: ## Required Status Checks -The "Required Status Checks" branch ruleset is implemented in two top-level workflows: `pr.yml` and `merge-group.yml`. +The "Required Status Checks" branch ruleset is implemented in two top-level workflows: `pull-request-target.yml` and `merge-group.yml`. The PR workflow defines all checks that need to succeed to add a Pull Request to the Merge Queue. If no Merge Queue is set up for a branch, the PR workflow defines the checks required to merge into the target branch. diff --git a/.github/workflows/backport.yml b/.github/workflows/backport.yml index fc2b80041ce7..b08714a31f12 100644 --- a/.github/workflows/backport.yml +++ b/.github/workflows/backport.yml @@ -40,6 +40,7 @@ jobs: with: ref: ${{ github.event.pull_request.head.sha }} token: ${{ steps.app-token.outputs.token }} + persist-credentials: true - name: Log current API rate limits env: @@ -48,7 +49,7 @@ jobs: - name: Create backport PRs id: backport - uses: korthout/backport-action@ca4972adce8039ff995e618f5fc02d1b7961f27a # v3.3.0 + uses: korthout/backport-action@d07416681cab29bf2661702f925f020aaa962997 # v3.4.1 with: # Config README: https://github.com/korthout/backport-action#backport-action copy_labels_pattern: 'severity:\ssecurity' @@ -56,8 +57,9 @@ jobs: 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. + **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: diff --git a/.github/workflows/labels.yml b/.github/workflows/bot.yml similarity index 90% rename from .github/workflows/labels.yml rename to .github/workflows/bot.yml index 3e520139bc28..6366f666de13 100644 --- a/.github/workflows/labels.yml +++ b/.github/workflows/bot.yml @@ -3,11 +3,13 @@ # access to the GitHub API. This means that it should not evaluate user input in # a way that allows code injection. -name: Labels +name: Bot on: schedule: - - cron: '07,17,27,37,47,57 * * * *' + # Run every 10m + # i.e., at each of the listed minutes, every hour + - cron: '05,15,25,35,45,55 * * * *' workflow_call: inputs: headBranch: @@ -21,7 +23,7 @@ on: 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 }} + group: bot-${{ 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' }} @@ -36,7 +38,7 @@ defaults: shell: bash jobs: - update: + run: runs-on: ubuntu-24.04-arm if: github.event_name != 'schedule' || github.repository_owner == 'NixOS' env: @@ -46,6 +48,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: | ci/github-script @@ -59,7 +62,10 @@ jobs: with: app-id: ${{ vars.NIXPKGS_CI_APP_ID }} private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} + permission-administration: read + permission-contents: write permission-issues: write + permission-members: read permission-pull-requests: write - name: Log current API rate limits @@ -67,13 +73,13 @@ jobs: GH_TOKEN: ${{ steps.app-token.outputs.token || github.token }} run: gh api /rate_limit | jq - - name: Labels from API data and Eval results + - name: Run bot uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: github-token: ${{ steps.app-token.outputs.token || github.token }} retries: 3 script: | - require('./ci/github-script/labels.js')({ + require('./ci/github-script/bot.js')({ github, context, core, diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 3f27b3e46538..701ac0b80b92 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -3,6 +3,9 @@ name: Build on: workflow_call: inputs: + artifact-prefix: + required: true + type: string baseBranch: required: true type: string @@ -46,13 +49,14 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Checkout the merge commit uses: ./.github/actions/checkout with: merged-as-untrusted-at: ${{ inputs.mergedSha }} - - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + - uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 with: # Sandbox is disabled on MacOS by default. extra_nix_config: sandbox = true @@ -97,7 +101,7 @@ jobs: if: | contains(matrix.builds, 'manual-nixos') && !cancelled() && contains(fromJSON(inputs.baseBranch).type, 'primary') - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: - name: nixos-manual-${{ matrix.name }} + name: ${{ inputs.artifact-prefix }}nixos-manual-${{ matrix.name }} path: nixos-manual diff --git a/.github/workflows/check.yml b/.github/workflows/check.yml index cc36502c89cf..e317903c2f8d 100644 --- a/.github/workflows/check.yml +++ b/.github/workflows/check.yml @@ -34,6 +34,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false path: trusted sparse-checkout: | ci/github-script @@ -73,13 +74,15 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Checkout merge and target commits uses: ./.github/actions/checkout with: merged-as-untrusted-at: ${{ inputs.mergedSha }} + target-as-trusted-at: ${{ inputs.targetSha }} - - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + - uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 with: @@ -90,7 +93,7 @@ jobs: pushFilter: -source$ - name: Build codeowners validator - run: nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A codeownersValidator + run: nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A codeownersValidator - name: Validate codeowners env: diff --git a/.github/workflows/comment.yml b/.github/workflows/comment.yml new file mode 100644 index 000000000000..d09df6956c8c --- /dev/null +++ b/.github/workflows/comment.yml @@ -0,0 +1,54 @@ +name: Comment + +on: + issue_comment: + types: [created] + +# This is used as fallback without app only. +# This happens when testing in forks without setting up that app. +permissions: + pull-requests: write + +defaults: + run: + shell: bash + +jobs: + # The `bot` workflow reacts to comments with @NixOS/nixpkgs-merge-bot references, but might only + # pick up a comment after up to 10 minutes. To give the user instant feedback, this job adds + # a reaction to these comments. + react: + name: React with eyes + runs-on: ubuntu-24.04-arm + timeout-minutes: 2 + if: contains(github.event.comment.body, '@NixOS/nixpkgs-merge-bot merge') + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + sparse-checkout: | + ci/github-script + + # Use the GitHub App to make sure the reaction happens with the same user who will later merge. + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_APP_ID + 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@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + github-token: ${{ steps.app-token.outputs.token || github.token }} + retries: 3 + script: | + const { handleMergeComment } = require('./ci/github-script/merge.js') + const { body, node_id } = context.payload.comment + + await handleMergeComment({ + github, + body, + node_id, + reaction: 'EYES', + }) diff --git a/.github/workflows/dismissed-review.yml b/.github/workflows/dismissed-review.yml deleted file mode 100644 index db5799c80913..000000000000 --- a/.github/workflows/dismissed-review.yml +++ /dev/null @@ -1,66 +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 - timeout-minutes: 2 - steps: - - uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - 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 } - )) - ) - ) - ) diff --git a/.github/workflows/eval.yml b/.github/workflows/eval.yml index f2c7a2c13568..ccd58fe1e9a9 100644 --- a/.github/workflows/eval.yml +++ b/.github/workflows/eval.yml @@ -3,6 +3,9 @@ name: Eval on: workflow_call: inputs: + artifact-prefix: + required: true + type: string mergedSha: required: true type: string @@ -11,9 +14,6 @@ on: systems: required: true type: string - defaultVersion: - required: true - type: string testVersions: required: false default: false @@ -37,6 +37,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false path: trusted sparse-checkout: | ci/supportedVersions.nix @@ -44,13 +45,14 @@ jobs: - name: Check out the PR at the test merge commit uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false ref: ${{ inputs.mergedSha }} path: untrusted sparse-checkout: | ci/pinned.json - name: Install Nix - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 - name: Load supported versions id: versions @@ -87,6 +89,7 @@ jobs: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Check out the PR at merged and target commits uses: ./.github/actions/checkout @@ -95,7 +98,7 @@ jobs: target-as-trusted-at: ${{ inputs.targetSha }} - name: Install Nix - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 with: @@ -108,9 +111,9 @@ jobs: - name: Evaluate the ${{ matrix.system }} output paths at the merge commit env: MATRIX_SYSTEM: ${{ matrix.system }} - MATRIX_VERSION: ${{ matrix.version || inputs.defaultVersion }} + MATRIX_VERSION: ${{ matrix.version || 'nixVersions.latest' }} run: | - nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A eval.singleSystem \ + nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A eval.singleSystem \ --argstr evalSystem "$MATRIX_SYSTEM" \ --arg chunkSize 8000 \ --argstr nixPath "$MATRIX_VERSION" \ @@ -119,21 +122,29 @@ jobs: # Note: Keep the same further down in sync! - name: Evaluate the ${{ matrix.system }} output paths at the target commit - if: inputs.targetSha env: MATRIX_SYSTEM: ${{ matrix.system }} - # This must match the default version set in the Merge Queue. - VERSION: lixPackageSets.latest.lix - # This is very quick, because it pulls the eval results from Cachix. run: | - nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.singleSystem \ + TARGET_DRV=$(nix-instantiate nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.singleSystem \ --argstr evalSystem "$MATRIX_SYSTEM" \ --arg chunkSize 8000 \ - --argstr nixPath "$VERSION" \ - --out-link target + --argstr nixPath "nixVersions.latest") + + # Try to fetch this from Cachix a few times, for up to 30 seconds. This avoids running Eval + # twice in the Merge Queue, when a later item finishes Eval at the merge commit earlier. + for _i in {1..6}; do + # Using --max-jobs 0 will cause nix-build to fail if this can't be substituted from cachix. + if nix-build "$TARGET_DRV" --max-jobs 0; then + break + fi + sleep 5 + done + + # Either fetches from Cachix or runs Eval itself. The fallback is required + # for pull requests into wip-branches without merge queue. + nix-build "$TARGET_DRV" --out-link target - name: Compare outpaths against the target branch - if: inputs.targetSha env: MATRIX_SYSTEM: ${{ matrix.system }} run: | @@ -144,22 +155,22 @@ jobs: --out-link diff - name: Upload outpaths diff and stats - if: inputs.targetSha - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: - name: ${{ matrix.version && format('{0}-', matrix.version) || '' }}diff-${{ matrix.system }} + name: ${{ inputs.artifact-prefix }}${{ matrix.version && format('{0}-', matrix.version) || '' }}diff-${{ matrix.system }} path: diff/* compare: runs-on: ubuntu-24.04-arm needs: [eval] - if: inputs.targetSha && !cancelled() && !failure() + if: ${{ !cancelled() && !failure() }} permissions: statuses: write timeout-minutes: 5 steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Check out the PR at the target commit uses: ./.github/actions/checkout @@ -168,14 +179,14 @@ jobs: target-as-trusted-at: ${{ inputs.targetSha }} - name: Download output paths and eval stats for all systems - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: - pattern: diff-* + pattern: ${{ inputs.artifact-prefix }}diff-* path: diff merge-multiple: true - name: Install Nix - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 - name: Combine all output paths and eval stats run: | @@ -183,26 +194,31 @@ jobs: --arg diffDir ./diff \ --out-link combined + - name: Upload the maintainer list + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 + with: + name: ${{ inputs.artifact-prefix }}maintainers + path: combined/maintainers.json + - name: Compare against the target branch env: - AUTHOR_ID: ${{ github.event.pull_request.user.id }} + TARGET_SHA: ${{ inputs.mergedSha }} run: | - git -C nixpkgs/trusted diff --name-only ${{ inputs.mergedSha }} \ + git -C nixpkgs/trusted diff --name-only "$TARGET_SHA" \ | jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json # Use the target branch to get accurate maintainer info nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.compare \ --arg combinedDir ./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 + uses: actions/upload-artifact@330a01c490aca151604b8cf639adc76d48f6c5d4 # v5.0.0 with: - name: comparison + name: ${{ inputs.artifact-prefix }}comparison path: comparison/* - name: Add eval summary to commit statuses @@ -242,7 +258,7 @@ jobs: needs: [versions, eval] steps: - name: Download output paths and eval stats for all versions - uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 + uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 with: pattern: "*-diff-*" path: versions @@ -250,6 +266,7 @@ jobs: - name: Add version comparison table to job summary uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 env: + ARTIFACT_PREFIX: ${{ inputs.artifact-prefix }} SYSTEMS: ${{ inputs.systems }} VERSIONS: ${{ needs.versions.outputs.versions }} with: @@ -257,6 +274,7 @@ jobs: const { readFileSync } = require('node:fs') const path = require('node:path') + const prefix = process.env.ARTIFACT_PREFIX const systems = JSON.parse(process.env.SYSTEMS) const versions = JSON.parse(process.env.VERSIONS) @@ -272,7 +290,7 @@ jobs: [{ data: version }].concat( systems.map((system) => { try { - const artifact = path.join('versions', `${version}-diff-${system}`) + const artifact = path.join('versions', `${prefix}${version}-diff-${system}`) const time = Math.round( parseFloat( readFileSync( @@ -284,16 +302,11 @@ jobs: const diff = JSON.parse( readFileSync(path.join(artifact, system, 'diff.json'), 'utf-8'), ) - const attrs = [].concat( - diff.added, - diff.removed, - diff.changed, - diff.rebuilds - ).filter(attr => - // Exceptions related to dev shells, which changed at some time between 2.18 and 2.24. - !attr.startsWith('tests.devShellTools.nixos.') && - !attr.startsWith('tests.devShellTools.unstructuredDerivationInputEnv.') - ) + const attrs = [] + .concat(diff.added, diff.removed, diff.changed, diff.rebuilds) + // There are some special attributes, which are ignored for rebuilds. + // These only have a single path component, because they lack the `.` suffix. + .filter((attr) => attr.split('.').length > 1) if (attrs.length > 0) { core.setFailed( `${version} on ${system} has changed outpaths!\nNote: Please make sure to update ci/pinned.json separately from changes to other packages.`, @@ -328,6 +341,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Checkout the merge commit uses: ./.github/actions/checkout @@ -335,7 +349,7 @@ jobs: merged-as-untrusted-at: ${{ inputs.mergedSha }} - name: Install Nix - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 - name: Run misc eval tasks in parallel run: | diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 1858f463ad83..486dac20207c 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -26,13 +26,14 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Checkout the merge commit uses: ./.github/actions/checkout with: merged-as-untrusted-at: ${{ inputs.mergedSha }} - - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + - uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 # TODO: Figure out how to best enable caching for the treefmt job. Cachix won't work well, # because the cache would be invalidated on every commit - treefmt checks every file. @@ -60,13 +61,14 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Checkout the merge commit uses: ./.github/actions/checkout with: merged-as-untrusted-at: ${{ inputs.mergedSha }} - - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + - uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 with: @@ -87,6 +89,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: .github/actions - name: Checkout merge and target commits uses: ./.github/actions/checkout @@ -94,7 +97,7 @@ jobs: merged-as-untrusted-at: ${{ inputs.mergedSha }} target-as-trusted-at: ${{ inputs.targetSha }} - - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 + - uses: cachix/install-nix-action@456688f15bc354bef6d396e4a35f4f89d40bf2b7 # v31 - uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16 with: diff --git a/.github/workflows/merge-group.yml b/.github/workflows/merge-group.yml index 6298aaa4424d..fe3d8fcc27d0 100644 --- a/.github/workflows/merge-group.yml +++ b/.github/workflows/merge-group.yml @@ -4,6 +4,9 @@ on: merge_group: workflow_call: inputs: + artifact-prefix: + required: true + type: string mergedSha: required: true type: string @@ -24,6 +27,7 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout: | ci/supportedSystems.json @@ -53,10 +57,10 @@ jobs: secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} with: + artifact-prefix: ${{ inputs.artifact-prefix }} mergedSha: ${{ inputs.mergedSha || github.event.merge_group.head_sha }} + targetSha: ${{ inputs.targetSha || github.event.merge_group.base_sha }} systems: ${{ needs.prepare.outputs.systems }} - # This must match the version in Eval's target step. - defaultVersion: lixPackageSets.latest.lix # This job's only purpose is to create the target for the "Required Status Checks" branch ruleset. # It "needs" all the jobs that should block the Merge Queue. diff --git a/.github/workflows/periodic-merge-24h.yml b/.github/workflows/periodic-merge-24h.yml index 63e3dfd13887..481a54191349 100644 --- a/.github/workflows/periodic-merge-24h.yml +++ b/.github/workflows/periodic-merge-24h.yml @@ -43,4 +43,5 @@ jobs: from: ${{ matrix.pairs.from }} into: ${{ matrix.pairs.into }} name: ${{ matrix.pairs.name || format('{0} → {1}', matrix.pairs.from, matrix.pairs.into) }} - secrets: inherit + secrets: + NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} diff --git a/.github/workflows/periodic-merge-6h.yml b/.github/workflows/periodic-merge-6h.yml index 054ac713fe74..edd4cb0b2df6 100644 --- a/.github/workflows/periodic-merge-6h.yml +++ b/.github/workflows/periodic-merge-6h.yml @@ -42,4 +42,5 @@ jobs: from: ${{ matrix.pairs.from }} into: ${{ matrix.pairs.into }} name: ${{ format('{0} → {1}', matrix.pairs.from, matrix.pairs.into) }} - secrets: inherit + secrets: + NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} diff --git a/.github/workflows/periodic-merge.yml b/.github/workflows/periodic-merge.yml index 04c80ae9735c..606c03866e6f 100644 --- a/.github/workflows/periodic-merge.yml +++ b/.github/workflows/periodic-merge.yml @@ -11,6 +11,9 @@ on: description: Target branch to merge into. required: true type: string + secrets: + NIXPKGS_CI_APP_PRIVATE_KEY: + required: true defaults: run: @@ -32,6 +35,8 @@ jobs: permission-pull-requests: write - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false - name: Find merge base between two branches if: contains(inputs.from, ' ') diff --git a/.github/workflows/pr.yml b/.github/workflows/pull-request-target.yml similarity index 85% rename from .github/workflows/pr.yml rename to .github/workflows/pull-request-target.yml index a9d40fcdcf5d..f74ce93de354 100644 --- a/.github/workflows/pr.yml +++ b/.github/workflows/pull-request-target.yml @@ -3,14 +3,15 @@ name: PR on: pull_request_target: workflow_call: + inputs: + artifact-prefix: + required: true + type: string secrets: CACHIX_AUTH_TOKEN: required: true NIXPKGS_CI_APP_PRIVATE_KEY: required: true - OWNER_APP_PRIVATE_KEY: - # The Test workflow should not actually request reviews from owners. - required: false concurrency: group: pr-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }} @@ -34,12 +35,19 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout-cone-mode: true # default, for clarity sparse-checkout: | ci/github-script - id: prepare uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: + retries: 10 + # The default for this includes code 422, which happens regularly for us when comparing commits: + # 422 - Server Error: Sorry, this diff is taking too long to generate. + # Listing all other values from here to effectively remove 422: + # https://github.com/octokit/plugin-retry.js/blob/9a2443746c350b3beedec35cf26e197ea318a261/src/index.ts#L14 + retry-exempt-status-codes: 400,401,403,404 script: | require('./ci/github-script/prepare.js')({ github, @@ -83,16 +91,16 @@ jobs: secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} with: + artifact-prefix: ${{ inputs.artifact-prefix }} mergedSha: ${{ needs.prepare.outputs.mergedSha }} targetSha: ${{ needs.prepare.outputs.targetSha }} systems: ${{ needs.prepare.outputs.systems }} - defaultVersion: nixVersions.latest testVersions: ${{ contains(fromJSON(needs.prepare.outputs.touched), 'pinned') && !contains(fromJSON(needs.prepare.outputs.headBranch).type, 'development') }} - labels: - name: Labels + bot: + name: Bot needs: [prepare, eval] - uses: ./.github/workflows/labels.yml + uses: ./.github/workflows/bot.yml permissions: issues: write pull-requests: write @@ -101,16 +109,6 @@ jobs: 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] @@ -118,6 +116,7 @@ jobs: secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} with: + artifact-prefix: ${{ inputs.artifact-prefix }} baseBranch: ${{ needs.prepare.outputs.baseBranch }} mergedSha: ${{ needs.prepare.outputs.mergedSha }} diff --git a/.github/workflows/review.yml b/.github/workflows/review.yml new file mode 100644 index 000000000000..44ac3f0088d4 --- /dev/null +++ b/.github/workflows/review.yml @@ -0,0 +1,92 @@ +name: Review + +on: + workflow_run: + workflows: + - Reviewed + types: [completed] + +# This is used as fallback without app only. +# This happens when testing in forks without setting up that app. +permissions: + pull-requests: write + +defaults: + run: + shell: bash + +jobs: + process: + runs-on: ubuntu-24.04-arm + timeout-minutes: 2 + steps: + - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + sparse-checkout: | + ci/github-script + + # Use the GitHub App to make sure the reaction happens with the same user who will later merge. + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_APP_ID + 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@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + github-token: ${{ steps.app-token.outputs.token || github.token }} + retries: 3 + script: | + const { handleMergeComment } = require('./ci/github-script/merge.js') + + // PRs from forks don't have any PRs associated by default. + // Thus, we request the PR number with an API call *to* the fork's repo. + // 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 + })).map(review => { + // The `check` 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. + if (review.user?.login == 'github-actions[bot]' && review.state == 'DISMISSED') + return github.graphql(` + mutation($node_id:ID!) { + minimizeComment(input: { + classifier: RESOLVED, + subjectId: $node_id + }) + { clientMutationId } + }`, + { node_id: review.node_id } + ) + + // The `bot` workflow reacts to comments with @NixOS/nixpkgs-merge-bot references, but might only + // pick up a comment after up to 10 minutes. To give the user instant feedback, this job adds + // a reaction to these comments. + return handleMergeComment({ + github, + body: review.body, + node_id: review.node_id, + reaction: 'EYES', + }) + }) + ) + ) + ) diff --git a/.github/workflows/review-dismissed.yml b/.github/workflows/reviewed.yml similarity index 81% rename from .github/workflows/review-dismissed.yml rename to .github/workflows/reviewed.yml index 988b4a47df14..d7d368739eaa 100644 --- a/.github/workflows/review-dismissed.yml +++ b/.github/workflows/reviewed.yml @@ -1,8 +1,8 @@ -name: Review dismissed +name: Reviewed on: pull_request_review: - types: [dismissed] + types: [submitted, dismissed] permissions: {} diff --git a/.github/workflows/reviewers.yml b/.github/workflows/reviewers.yml deleted file mode 100644 index 32290c179130..000000000000 --- a/.github/workflows/reviewers.yml +++ /dev/null @@ -1,170 +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_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 - timeout-minutes: 20 - steps: - - name: Check out the PR at the base commit - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 - with: - path: trusted - sparse-checkout: ci - - - name: Install Nix - uses: cachix/install-nix-action@7ab6e7fd29da88e74b1e314a4ae9ac6b5cda3801 # v31 - - - name: Build the requestReviews derivation - run: nix-build trusted/ci -A requestReviews - - # For requesting reviewers, this job depends on a GitHub App with the following permissions: - # - 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) - # - # Can't use the token received from permissions above, because it can't get enough permissions. - - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 - 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 (app-token) - if: ${{ steps.app-token.outputs.token }} - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - run: gh api /rate_limit | jq - - - name: Requesting code owner reviews - if: steps.app-token.outputs.token - env: - GH_TOKEN: ${{ steps.app-token.outputs.token }} - REPOSITORY: ${{ github.repository }} - NUMBER: ${{ github.event.number }} - # Don't do anything on draft PRs - DRY_MODE: ${{ github.event.pull_request.draft && '1' || '' }} - run: result/bin/request-code-owner-reviews.sh "$REPOSITORY" "$NUMBER" ci/OWNERS - - - 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 - - # 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@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 - id: eval - with: - script: | - const run_id = (await github.rest.actions.listWorkflowRuns({ - owner: context.repo.owner, - repo: context.repo.repo, - workflow_id: context.eventName === 'pull_request' ? 'test.yml' : '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@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0 - 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 diff --git a/.github/workflows/teams.yml b/.github/workflows/teams.yml new file mode 100644 index 000000000000..b848983b5aa2 --- /dev/null +++ b/.github/workflows/teams.yml @@ -0,0 +1,79 @@ +name: Teams + +on: + schedule: + # Every Tuesday at 19:42 (randomly chosen) + - cron: '42 19 * * 1' + workflow_dispatch: + +permissions: {} + +defaults: + run: + shell: bash + +jobs: + sync: + runs-on: ubuntu-24.04-arm + steps: + # Use a GitHub App to create the PR so that CI gets triggered and to + # request team member lists. + - uses: actions/create-github-app-token@67018539274d69449ef7c02e8e71183d1719ab42 # v2.1.4 + id: app-token + with: + app-id: ${{ vars.NIXPKGS_CI_APP_ID }} + private-key: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} + permission-administration: read + permission-contents: write + permission-members: read + permission-pull-requests: write + + - name: Fetch source + uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 + with: + persist-credentials: false + sparse-checkout: | + ci/github-script + maintainers/github-teams.json + + - name: Install dependencies + run: npm install bottleneck + + - name: Synchronise teams + uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 + with: + github-token: ${{ steps.app-token.outputs.token }} + script: | + require('./ci/github-script/get-teams.js')({ + github, + context, + core, + outFile: "maintainers/github-teams.json" + }) + + - name: Get GitHub App User Git String + id: user + env: + GH_TOKEN: ${{ steps.app-token.outputs.token }} + APP_SLUG: ${{ steps.app-token.outputs.app-slug }} + run: | + name="${APP_SLUG}[bot]" + userId=$(gh api "/users/$name" --jq .id) + email="$userId+$name@users.noreply.github.com" + echo "git-string=$name <$email>" >> "$GITHUB_OUTPUT" + + - name: Create Pull Request + uses: peter-evans/create-pull-request@271a8d0340265f705b14b6d32b9829c1cb33d45e # v7.0.8 + with: + token: ${{ steps.app-token.outputs.token }} + add-paths: maintainers/github-teams.json + author: ${{ steps.user.outputs.git-string }} + committer: ${{ steps.user.outputs.git-string }} + commit-message: "maintainers/github-teams.json: Automated sync" + branch: pr/github-team-sync + title: "maintainers/github-teams.json: Automated sync" + body: | + This is an automated PR to sync the GitHub teams with access to this repository to the `lib.teams` list. + + This PR can be merged without taking any further action. + diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 0d5f20e3b57b..727a9f965845 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -21,12 +21,19 @@ jobs: steps: - uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0 with: + persist-credentials: false sparse-checkout-cone-mode: true # default, for clarity sparse-checkout: | ci/github-script - id: prepare uses: actions/github-script@ed597411d8f924073f98dfc5c65a23a2325f34cd # v8.0.0 with: + retries: 10 + # The default for this includes code 422, which happens regularly for us when comparing commits: + # 422 - Server Error: Sorry, this diff is taking too long to generate. + # Listing all other values from here to effectively remove 422: + # https://github.com/octokit/plugin-retry.js/blob/9a2443746c350b3beedec35cf26e197ea318a261/src/index.ts#L14 + retry-exempt-status-codes: 400,401,403,404 script: | require('./ci/github-script/prepare.js')({ github, @@ -56,14 +63,16 @@ jobs: if (files.some(file => [ '.github/actions/checkout/action.yml', + '.github/workflows/bot.yml', '.github/workflows/build.yml', '.github/workflows/check.yml', '.github/workflows/eval.yml', - '.github/workflows/labels.yml', '.github/workflows/lint.yml', - '.github/workflows/pr.yml', - '.github/workflows/reviewers.yml', + '.github/workflows/pull-request-target.yml', '.github/workflows/test.yml', + 'ci/github-script/bot.js', + 'ci/github-script/merge.js', + 'ci/github-script/withRateLimit.js', ].includes(file))) core.setOutput('pr', true) merge-group: @@ -77,6 +86,7 @@ jobs: secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} with: + artifact-prefix: mg- mergedSha: ${{ needs.prepare.outputs.mergedSha }} targetSha: ${{ needs.prepare.outputs.targetSha }} @@ -84,7 +94,7 @@ jobs: if: needs.prepare.outputs.pr name: PR needs: [prepare] - uses: ./.github/workflows/pr.yml + uses: ./.github/workflows/pull-request-target.yml # Those are actually only used on the pull_request_target event, but will throw an error if not set. permissions: issues: write @@ -93,3 +103,5 @@ jobs: secrets: CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }} NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }} + with: + artifact-prefix: pr- diff --git a/.github/zizmor.yml b/.github/zizmor.yml new file mode 100644 index 000000000000..f1b71580ebca --- /dev/null +++ b/.github/zizmor.yml @@ -0,0 +1,12 @@ +# This file defines the ignore rules for zizmor. +# +# For rules that contain a high number of false positives, prefer listing them here +# instead of adding ignore comments. Note that zizmor cannot ignore by line-within-a-string, so +# there are some ignore items that encompass multiple problems within one `run` block. An issue +# tracking this is at https://github.com/woodruffw/zizmor/issues/648. +# +# For more info, see the documentation: https://woodruffw.github.io/zizmor/usage/#ignoring-results + +rules: + dangerous-triggers: + disable: true diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d7a59925f5b0..d86cafd010fb 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -430,7 +430,7 @@ gitGraph Here's an overview of the different branches: -| branch | `master` | `staging-next` | `staging` | [`staging-nixos`](#test-driver-rebuild) | +| branch | `master` | `staging-next` | `staging` | [`staging-nixos`][test-driver-rebuild] | | --- | --- | --- | --- | --- | | Used for development | ✔️ | ❌ | ✔️ | ✔️ | | Built by Hydra | ✔️ | ✔️ | ❌ | ❌ | @@ -501,7 +501,7 @@ Please note that changes to the Linux kernel are an exception to this rule. These PRs go to `staging-nixos`, see [the next section for more context](#changes-rebuilding-all-tests). ### Changes rebuilding all NixOS tests -[test-driver-rebuild]: #changes-rebuilding-all-tests +[test-driver-rebuild]: #changes-rebuilding-all-nixos-tests Changes causing a rebuild of all NixOS tests get a special [`10.rebuild-nixos-tests`](https://github.com/NixOS/nixpkgs/issues?q=state%3Aopen%20label%3A10.rebuild-nixos-tests) label. These changes pose a significant impact on the build infrastructure. diff --git a/ci/OWNERS b/ci/OWNERS index c21cb14fe11e..6edaa4beab9d 100644 --- a/ci/OWNERS +++ b/ci/OWNERS @@ -32,6 +32,8 @@ /lib/asserts.nix @infinisil @hsjobeki @Profpatsch /lib/path/* @infinisil @hsjobeki /lib/fileset @infinisil @hsjobeki +/maintainers/github-teams.json @infinisil +/maintainers/computed-team-list.nix @infinisil ## Standard environment–related libraries /lib/customisation.nix @alyssais @NixOS/stdenv /lib/derivations.nix @alyssais @NixOS/stdenv @@ -56,7 +58,8 @@ /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/generic/check-meta.nix @Ericson2314 @adisbladis @NixOS/stdenv +/pkgs/stdenv/generic/meta-types.nix @adisbladis @NixOS/stdenv /pkgs/stdenv/cross @Ericson2314 @NixOS/stdenv /pkgs/build-support @philiptaron /pkgs/build-support/cc-wrapper @Ericson2314 @@ -212,10 +215,10 @@ nixos/modules/installer/tools/nix-fallback-paths.nix @NixOS/nix-team @raitobeza /pkgs/development/r-modules @jbedo # Rust -/pkgs/development/compilers/rust @alyssais @Mic92 @zowoq @winterqt @figsoda -/pkgs/build-support/rust @zowoq @winterqt @figsoda +/pkgs/development/compilers/rust @alyssais @Mic92 @zowoq @winterqt +/pkgs/build-support/rust @zowoq @winterqt /pkgs/build-support/rust/fetch-cargo-vendor* @TomaSajt -/doc/languages-frameworks/rust.section.md @zowoq @winterqt @figsoda +/doc/languages-frameworks/rust.section.md @zowoq @winterqt # Tcl /pkgs/development/interpreters/tcl @fgaz @@ -341,7 +344,7 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt /pkgs/top-level/agda-packages.nix @NixOS/agda /pkgs/development/libraries/agda @NixOS/agda /doc/languages-frameworks/agda.section.md @NixOS/agda -/nixos/tests/agda.nix @NixOS/agda +/nixos/tests/agda @NixOS/agda # Idris /pkgs/development/idris-modules @Infinisil @@ -444,8 +447,8 @@ pkgs/by-name/fo/forgejo/ @adamcstephens @bendlas @emilylange /pkgs/os-specific/linux/zfs @adamcstephens @amarshall # Zig -/pkgs/development/compilers/zig @figsoda @RossComputerGuy -/doc/hooks/zig.section.md @figsoda @RossComputerGuy +/pkgs/development/compilers/zig @RossComputerGuy +/doc/hooks/zig.section.md @RossComputerGuy # Buildbot nixos/modules/services/continuous-integration/buildbot @Mic92 @zowoq diff --git a/ci/README.md b/ci/README.md index 797f231aea62..df5b196c49a4 100644 --- a/ci/README.md +++ b/ci/README.md @@ -10,6 +10,53 @@ In order to ensure that the needed packages are generally available without buil Run [`update-pinned.sh`](./update-pinned.sh) to update it. +## GitHub specific code + +Some of the code is specific to GitHub. +This code is currently spread out over multiple places and written in both Bash and JavaScript. +The goal is to eventually have all GitHub specific code in `ci/github-script` and written in JavaScript via `actions/github-script`. +A lot of code has already been migrated, but some Bash code still remains. +New CI features need to be introduced in JavaScript, not Bash. + +## Nixpkgs merge bot + +The Nixpkgs merge bot empowers package maintainers by enabling them to merge PRs related to their own packages. +It serves as a bridge for maintainers to quickly respond to user feedback, facilitating a more self-reliant approach. +Especially when considering there are roughly 20 maintainers for every committer, this bot is a game-changer. + +Following [RFC 172] the merge bot was originally implemented as a [python webapp](https://github.com/NixOS/nixpkgs-merge-bot), which has now been integrated into [`ci/github-script/bot.js`](./github-script/bot.js) and [`ci/github-script/merge.js`](./github-script/merge.js). + +### Using the merge bot + +To merge a PR, maintainers can simply comment: +```gfm +@NixOS/nixpkgs-merge-bot merge +``` + +The next time the bot runs it will verify the below constraints, then (if satisfied) merge the PR. + +The merge bot will reference [#306934](https://github.com/NixOS/nixpkgs/issues/306934) on PRs it merges successfully, [#305350](https://github.com/NixOS/nixpkgs/issues/305350) for unsuccessful attempts, or [#371492](https://github.com/NixOS/nixpkgs/issues/371492) if an error occurs. +These issues effectively list PRs the merge bot has interacted with. + +### Merge bot constraints + +To ensure security and a focused utility, the bot adheres to specific limitations: + +- The PR targets one of the [development branches](#branch-classification). +- The PR only touches files of packages located under `pkgs/by-name/*`. +- The PR is either: + - approved by a [committer][@NixOS/nixpkgs-committers]. + - backported via label. + - opened by a [committer][@NixOS/nixpkgs-committers]. + - opened by [@r-ryantm](https://nix-community.github.io/nixpkgs-update/r-ryantm/). +- The user attempting to merge is a member of [@NixOS/nixpkgs-maintainers]. +- The user attempting to merge is a maintainer of all packages touched by the PR. + +### Approving merge bot changes + +Changes to the bot can usually be approved by the [@NixOS/nixpkgs-ci] team, as with other CI changes. +However, additional acknowledgement from the [@NixOS/nixpkgs-core] team is required for changes to what the merge bot will merge, who is eligible to use the merge bot, or similar changes in scope. + ## `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. @@ -50,3 +97,10 @@ Some branches also have a version component, which is either `unstable` or `YY.M `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. + + +[@NixOS/nixpkgs-maintainers]: https://github.com/orgs/NixOS/teams/nixpkgs-maintainers +[@NixOS/nixpkgs-committers]: https://github.com/orgs/NixOS/teams/nixpkgs-committers +[@NixOS/nixpkgs-ci]: https://github.com/orgs/NixOS/teams/nixpkgs-ci +[@NixOS/nixpkgs-core]: https://github.com/orgs/NixOS/teams/nixpkgs-core +[RFC 172]: https://github.com/NixOS/rfcs/pull/172 diff --git a/ci/default.nix b/ci/default.nix index 7b7424f4f5be..8712a44e0584 100644 --- a/ci/default.nix +++ b/ci/default.nix @@ -49,6 +49,8 @@ let programs.biome = { enable = true; + # Disable settings validation because its inputs are liable to hash mismatch + validate.enable = false; settings.formatter = { useEditorconfig = true; }; @@ -136,6 +138,8 @@ let [ "--config=${config}" ]; includes = [ "*.md" ]; }; + + programs.zizmor.enable = true; }; fs = pkgs.lib.fileset; nixFilesSrc = fs.toSource { @@ -152,7 +156,6 @@ let in rec { inherit pkgs fmt; - requestReviews = pkgs.callPackage ./request-reviews { }; codeownersValidator = pkgs.callPackage ./codeowners-validator { }; # FIXME(lf-): it might be useful to test other Nix implementations diff --git a/ci/eval/attrpaths.nix b/ci/eval/attrpaths.nix index 6938e5dfe3cb..ff1bdabbb350 100644 --- a/ci/eval/attrpaths.nix +++ b/ci/eval/attrpaths.nix @@ -18,6 +18,7 @@ lib ? import (path + "/lib"), trace ? false, path ? ./../.., + extraNixpkgsConfigJson ? "{}", }: let @@ -46,6 +47,7 @@ let outpaths = import ./outpaths.nix { inherit path; + extraNixpkgsConfig = builtins.fromJSON extraNixpkgsConfigJson; attrNamesOnly = true; }; diff --git a/ci/eval/chunk.nix b/ci/eval/chunk.nix index 43c684074602..e1759c2c6615 100644 --- a/ci/eval/chunk.nix +++ b/ci/eval/chunk.nix @@ -8,6 +8,7 @@ myChunk, includeBroken, systems, + extraNixpkgsConfigJson, }: let @@ -17,6 +18,7 @@ let unfiltered = import ./outpaths.nix { inherit path; inherit includeBroken systems; + extraNixpkgsConfig = builtins.fromJSON extraNixpkgsConfigJson; }; # Turns the unfiltered recursive attribute set into one that is limited to myAttrpaths diff --git a/ci/eval/compare/default.nix b/ci/eval/compare/default.nix index 3a025a0238f6..9791d26e9550 100644 --- a/ci/eval/compare/default.nix +++ b/ci/eval/compare/default.nix @@ -7,6 +7,7 @@ python3, stdenvNoCC, makeWrapper, + codeowners, }: let python = python3.withPackages (ps: [ @@ -48,8 +49,7 @@ in { combinedDir, touchedFilesJson, - githubAuthorId, - byName ? false, + ownersFile ? ../../OWNERS, }: let # Usually we expect a derivation, but when evaluating in multiple separate steps, we pass @@ -156,23 +156,19 @@ let # Only set this label when no other label with indication for staging has been set. # This avoids confusion whether to target staging or batch this with kernel updates. lib.last (lib.sort lib.lessThan (lib.attrValues rebuildCountByKernel)) <= 500; - # Set the "11.by: package-maintainer" label to whether all packages directly - # changed are maintained by the PR's author. - "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) changedPackagePlatformAttrs); - changedpathsjson = touchedFilesJson; - removedattrs = lib.attrNames (lib.groupBy (a: a.name) removedPackagePlatformAttrs); - inherit byName; - }; + inherit + (callPackage ./maintainers.nix { } { + changedattrs = lib.attrNames (lib.groupBy (a: a.name) changedPackagePlatformAttrs); + changedpathsjson = touchedFilesJson; + removedattrs = lib.attrNames (lib.groupBy (a: a.name) removedPackagePlatformAttrs); + }) + maintainers + packages + ; in runCommand "compare" { @@ -180,9 +176,14 @@ runCommand "compare" nativeBuildInputs = map lib.getBin [ jq cmp-stats + codeowners ]; maintainers = builtins.toJSON maintainers; - passAsFile = [ "maintainers" ]; + packages = builtins.toJSON packages; + passAsFile = [ + "maintainers" + "packages" + ]; } '' mkdir $out @@ -224,5 +225,43 @@ runCommand "compare" } >> $out/step-summary.md fi + jq -r '.[]' "${touchedFilesJson}" > ./touched-files + readarray -t touchedFiles < ./touched-files + echo "This PR touches ''${#touchedFiles[@]} files" + + # TODO: Move ci/OWNERS to Nix and produce owners.json instead of owners.txt. + touch "$out/owners.txt" + for file in "''${touchedFiles[@]}"; do + result=$(codeowners --file "${ownersFile}" "$file") + + # Remove the file prefix and trim the surrounding spaces + read -r owners <<< "''${result#"$file"}" + if [[ "$owners" == "(unowned)" ]]; then + echo "File $file is unowned" + continue + fi + echo "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 + echo -e "\e[33mCodeowner \"$entry\" for file $file is not valid: Must start with \"@\"\e[0m" + # 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]} + + echo "$entry" >> "$out/owners.txt" + done + + done + cp "$maintainersPath" "$out/maintainers.json" + cp "$packagesPath" "$out/packages.json" '' diff --git a/ci/eval/compare/maintainers.nix b/ci/eval/compare/maintainers.nix index c3caf7403784..7f945f2c387f 100644 --- a/ci/eval/compare/maintainers.nix +++ b/ci/eval/compare/maintainers.nix @@ -5,33 +5,52 @@ changedattrs, changedpathsjson, removedattrs, - byName ? false, }: let pkgs = import ../../.. { system = "x86_64-linux"; - config = { }; - overlays = [ ]; + # We should never try to ping maintainers through package aliases, this can only lead to errors. + # One example case is, where an attribute is a throw alias, but then re-introduced in a PR. + # This would trigger the throw. By disabling aliases, we can fallback gracefully below. + config.allowAliases = false; }; - changedpaths = builtins.fromJSON (builtins.readFile changedpathsjson); + changedpaths = lib.importJSON changedpathsjson; - anyMatchingFile = - filename: builtins.any (changed: lib.strings.hasSuffix changed filename) changedpaths; + # Extract attributes that changed from by-name paths. + # This allows pinging reviewers for pure refactors. + touchedattrs = lib.pipe changedpaths [ + (lib.filter (changed: lib.hasPrefix "pkgs/by-name/" changed)) + (map (lib.splitString "/")) + (map (path: lib.elemAt path 3)) + lib.unique + ]; - anyMatchingFiles = files: builtins.any anyMatchingFile files; + anyMatchingFile = filename: lib.any (lib.hasPrefix filename) changedpaths; - attrsWithMaintainers = lib.pipe (changedattrs ++ removedattrs) [ + anyMatchingFiles = files: lib.any anyMatchingFile files; + + sharded = name: "${lib.substring 0 2 name}/${name}"; + + attrsWithMaintainers = lib.pipe (changedattrs ++ removedattrs ++ touchedattrs) [ + # An attribute can appear in changed/removed *and* touched + lib.unique (map ( name: let + path = lib.splitString "." name; # Some packages might be reported as changed on a different platform, but # not even have an attribute on the platform the maintainers are requested on. # Fallback to `null` for these to filter them out below. - package = lib.attrByPath (lib.splitString "." name) null pkgs; + package = lib.attrByPath path null pkgs; in { inherit name package; + # Adds all files in by-name to each package, no matter whether they are discoverable + # via meta attributes below. For example, this allows pinging maintainers for + # updates to .json files. + # TODO: Support by-name package sets. + filenames = lib.optional (lib.length path == 1) "pkgs/by-name/${sharded (lib.head path)}/"; # 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 = package.meta.maintainers or [ ]; @@ -40,25 +59,21 @@ let # No need to match up packages without maintainers with their files. # This also filters out attributes where `packge = null`, which is the # case for libintl, for example. - (builtins.filter (pkg: pkg.maintainers != [ ])) + (lib.filter (pkg: pkg.maintainers != [ ])) ]; relevantFilenames = drv: - (lib.lists.unique ( - map (pos: lib.strings.removePrefix (toString ../..) pos.file) ( - builtins.filter (x: x != null) [ - ((drv.meta or { }).maintainersPosition or null) - ((drv.meta or { }).teamsPosition or null) - (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) - + (lib.unique ( + map (pos: lib.removePrefix "${toString ../../..}/" pos.file) ( + lib.filter (x: x != null) [ + (drv.meta.maintainersPosition or null) + (drv.meta.teamsPosition or null) + (lib.unsafeGetAttrPos "src" drv) + (lib.unsafeGetAttrPos "pname" drv) + (lib.unsafeGetAttrPos "version" drv) + ] + ++ lib.optionals (drv ? meta.position) [ # 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" @@ -68,16 +83,16 @@ let # "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 "")); } + { file = lib.head (lib.splitString ":" drv.meta.position); } ] ) )); attrsWithFilenames = map ( - pkg: pkg // { filenames = relevantFilenames pkg.package; } + pkg: pkg // { filenames = pkg.filenames ++ relevantFilenames pkg.package; } ) attrsWithMaintainers; - attrsWithModifiedFiles = builtins.filter (pkg: anyMatchingFiles pkg.filenames) attrsWithFilenames; + attrsWithModifiedFiles = lib.filter (pkg: anyMatchingFiles pkg.filenames) attrsWithFilenames; listToPing = lib.concatMap ( pkg: @@ -89,10 +104,10 @@ let }) pkg.maintainers ) attrsWithModifiedFiles; - byMaintainer = lib.groupBy (ping: toString ping.${if byName then "github" else "id"}) listToPing; - - packagesPerMaintainer = lib.attrsets.mapAttrs ( - maintainer: packages: map (pkg: pkg.packageName) packages - ) byMaintainer; + byMaintainer = lib.groupBy (ping: toString ping.id) listToPing; in -packagesPerMaintainer +{ + maintainers = lib.mapAttrs (_: lib.catAttrs "packageName") byMaintainer; + + packages = lib.catAttrs "packageName" listToPing; +} diff --git a/ci/eval/compare/utils.nix b/ci/eval/compare/utils.nix index 65a558d8be60..969622ee16f1 100644 --- a/ci/eval/compare/utils.nix +++ b/ci/eval/compare/utils.nix @@ -22,7 +22,7 @@ rec { splittedPath = lib.splitString "." packagePlatformPath; # ["python312Packages" "numpy" "aarch64-linux"] -> ["python312Packages" "numpy"] - packagePath = lib.sublist 0 (lib.length splittedPath - 1) splittedPath; + packagePath = lib.init splittedPath; # "python312Packages.numpy" name = lib.concatStringsSep "." packagePath; diff --git a/ci/eval/default.nix b/ci/eval/default.nix index c7310a5052d0..b8d3d3224a04 100644 --- a/ci/eval/default.nix +++ b/ci/eval/default.nix @@ -19,6 +19,17 @@ nix, }: +{ + # The number of attributes per chunk, see ./README.md for more info. + chunkSize ? 5000, + # Whether to just evaluate a single chunk for quick testing + quickTest ? false, + # Don't try to eval packages marked as broken. + includeBroken ? false, + # Customize the config used to evaluate nixpkgs + extraNixpkgsConfig ? { }, +}: + let nixpkgs = with lib.fileset; @@ -66,6 +77,7 @@ let "$src/ci/eval/attrpaths.nix" \ -A paths \ -I "$src" \ + --argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \ --option restrict-eval true \ --option allow-import-from-derivation false \ --option eval-system "${evalSystem}" > $out/paths.json @@ -79,13 +91,6 @@ let evalSystem ? builtins.currentSystem, # 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 ? 5000, - - # 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" '' @@ -95,6 +100,10 @@ let system=$3 outputDir=$4 + # Default is 5, higher values effectively disable the warning. + # This randomly breaks Eval. + export GC_LARGE_ALLOC_WARN_INTERVAL=1000 + export NIX_SHOW_STATS=1 export NIX_SHOW_STATS_PATH="$outputDir/stats/$myChunk" echo "Chunk $myChunk on $system start" @@ -107,12 +116,14 @@ let --option allow-import-from-derivation false \ --query --available \ --out-path --json \ + --meta \ --show-trace \ --arg chunkSize "$chunkSize" \ --arg myChunk "$myChunk" \ --arg attrpathFile "${attrpathFile}" \ --arg systems "[ \"$system\" ]" \ --arg includeBroken ${lib.boolToString includeBroken} \ + --argstr extraNixpkgsConfigJson ${lib.escapeShellArg (builtins.toJSON extraNixpkgsConfig)} \ -I ${nixpkgs} \ -I ${attrpathFile} \ > "$outputDir/result/$myChunk" \ @@ -200,6 +211,7 @@ let fi cat "$chunkOutputDir"/result/* | jq -s 'add | map_values(.outputs)' > $out/${evalSystem}/paths.json + cat "$chunkOutputDir"/result/* | jq -s 'add | map_values(.meta)' > $out/${evalSystem}/meta.json ''; diff = callPackage ./diff.nix { }; @@ -228,6 +240,14 @@ let }) ' > $out/combined-diff.json + # Combine maintainers from all systems + cat ${diffDir}/*/maintainers.json | jq -s ' + add | group_by(.package) | map({ + key: .[0].package, + value: map(.maintainers) | flatten | unique + }) | from_entries + ' > $out/maintainers.json + mkdir -p $out/before/stats for d in ${diffDir}/before/*; do cp -r "$d"/stats-by-chunk $out/before/stats/$(basename "$d") @@ -245,16 +265,13 @@ let { # Whether to evaluate on a specific set of systems, by default all are evaluated evalSystems ? if quickTest then [ "x86_64-linux" ] else supportedSystems, - # The number of attributes per chunk, see ./README.md for more info. - chunkSize ? 5000, - quickTest ? false, }: symlinkJoin { name = "nixpkgs-eval-baseline"; paths = map ( evalSystem: singleSystem { - inherit quickTest evalSystem chunkSize; + inherit evalSystem; } ) evalSystems; }; @@ -263,13 +280,7 @@ let { # 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 ? 5000, - quickTest ? false, baseline, - # Which maintainer should be considered the author? - # Defaults to nixpkgs-ci which is not a maintainer and skips the check. - githubAuthorId ? "nixpkgs-ci", # What files have been touched? Defaults to none; use the expression below to calculate it. # ``` # git diff --name-only --merge-base master HEAD \ @@ -286,14 +297,14 @@ let inherit evalSystem; beforeDir = baseline; afterDir = singleSystem { - inherit quickTest evalSystem chunkSize; + inherit evalSystem; }; } ) evalSystems; }; comparisonReport = compare { combinedDir = combine { diffDir = diffs; }; - inherit touchedFilesJson githubAuthorId; + inherit touchedFilesJson; }; in comparisonReport; diff --git a/ci/eval/diff.nix b/ci/eval/diff.nix index 692e2ec60194..bb8ba8088c7f 100644 --- a/ci/eval/diff.nix +++ b/ci/eval/diff.nix @@ -76,11 +76,36 @@ let afterAttrs = getAttrs after; diffAttrs = diff beforeAttrs afterAttrs; diffJson = writeText "diff.json" (builtins.toJSON diffAttrs); + + # The maintainer list is not diffed, but just taken as is, to provide a map + # of maintainers on the target branch. A list of GitHub IDs is sufficient for + # all our purposes and reduces size massively. + meta = lib.importJSON "${after}/${evalSystem}/meta.json"; + maintainers = lib.pipe meta [ + (lib.mapAttrsToList ( + k: v: { + # splits off the platform suffix + package = lib.pipe k [ + (lib.splitString ".") + lib.init + (lib.concatStringsSep ".") + ]; + maintainers = map (m: m.githubId) v.maintainers or [ ]; + } + )) + # Some paths don't have a platform suffix, those will appear with an empty package here. + (lib.filter ({ package, maintainers }: package != "" && maintainers != [ ])) + ]; + maintainersJson = writeText "maintainers.json" (builtins.toJSON maintainers); in runCommand "diff" { } '' mkdir -p $out/${evalSystem} - cp -r ${before} $out/before - cp -r ${after} $out/after + cp -r --no-preserve=mode ${before} $out/before + cp -r --no-preserve=mode ${after} $out/after + # JSON files will be processed above explicitly, so avoid copying over + # the source files to keep the artifacts smaller. + find $out/before $out/after -iname '*.json' -delete cp ${diffJson} $out/${evalSystem}/diff.json + cp ${maintainersJson} $out/${evalSystem}/maintainers.json '' diff --git a/ci/eval/outpaths.nix b/ci/eval/outpaths.nix index 6d003dafc3c9..9abe08e1b165 100644 --- a/ci/eval/outpaths.nix +++ b/ci/eval/outpaths.nix @@ -11,6 +11,9 @@ # Set this to `null` to build for builtins.currentSystem only systems ? builtins.fromJSON (builtins.readFile ../supportedSystems.json), + + # Customize the config used to evaluate nixpkgs + extraNixpkgsConfig ? { }, }: let lib = import (path + "/lib"); @@ -55,7 +58,8 @@ let true; inHydra = true; - }; + } + // extraNixpkgsConfig; __allowFileset = false; }; diff --git a/ci/github-script/labels.js b/ci/github-script/bot.js similarity index 58% rename from ci/github-script/labels.js rename to ci/github-script/bot.js index faf7693c0f04..2b52955307ae 100644 --- a/ci/github-script/labels.js +++ b/ci/github-script/bot.js @@ -3,10 +3,142 @@ module.exports = async ({ github, context, core, dry }) => { const { DefaultArtifactClient } = require('@actions/artifact') const { readFile, writeFile } = require('node:fs/promises') const withRateLimit = require('./withRateLimit.js') + const { classify } = require('../supportedBranches.js') + const { handleMerge } = require('./merge.js') + const { handleReviewers } = require('./reviewers.js') const artifactClient = new DefaultArtifactClient() - async function handlePullRequest({ item, stats }) { + async function downloadMaintainerMap(branch) { + let run + + const commits = ( + await github.rest.repos.listCommits({ + ...context.repo, + sha: branch, + // We look at 10 commits to find a maintainer map, but this is an arbitrary number. The + // head commit might not have a map, if the queue was bypassed to merge it. This happens + // frequently on staging-esque branches. The branch with the highest chance of getting + // 10 consecutive bypassing commits is the stable staging-next branch. Luckily, this + // also means that the number of PRs open towards that branch is very low, so falling + // back to slightly imprecise maintainer data from master only has a marginal effect. + per_page: 10, + }) + ).data + + for (const commit of commits) { + const run = ( + await github.rest.actions.listWorkflowRuns({ + ...context.repo, + workflow_id: 'merge-group.yml', + status: 'success', + exclude_pull_requests: true, + per_page: 1, + head_sha: commit.sha, + }) + ).data.workflow_runs[0] + if (!run) continue + + const artifact = ( + await github.rest.actions.listWorkflowRunArtifacts({ + ...context.repo, + run_id: run.id, + name: 'maintainers', + }) + ).data.artifacts[0] + if (!artifact) continue + + await artifactClient.downloadArtifact(artifact.id, { + findBy: { + repositoryName: context.repo.repo, + repositoryOwner: context.repo.owner, + token: core.getInput('github-token'), + }, + path: path.resolve(path.join('branches', branch)), + expectedHash: artifact.digest, + }) + + return JSON.parse( + await readFile( + path.resolve(path.join('branches', branch, 'maintainers.json')), + 'utf-8', + ), + ) + } + + // We get here when none of the 10 commits we looked at contained a maintainer map. + // For the master branch, we don't have any fallback options, so we error out. + // For other branches, we select a suitable fallback below. + if (branch === 'master') throw new Error('No maintainer map found.') + + const { stable, version } = classify(branch) + + const release = `release-${version}` + if (stable && branch !== release) { + // Only fallback to the release branch from *other* stable branches. + // Explicitly avoids infinite recursion. + return await getMaintainerMap(release) + } else { + // Falling back to master as last resort. + // This can either be the case for unstable staging-esque or wip branches, + // or for the primary stable branch (release-XX.YY). + return await getMaintainerMap('master') + } + } + + // Simple cache for maintainer maps to avoid downloading the same artifacts + // over and over again. Ultimately returns a promise, so the result must be + // awaited for. + const maintainerMaps = {} + function getMaintainerMap(branch) { + if (!maintainerMaps[branch]) { + maintainerMaps[branch] = downloadMaintainerMap(branch) + } + return maintainerMaps[branch] + } + + // Caching the list of team members saves API requests when running the bot on the schedule and + // processing many PRs at once. + const members = {} + function getTeamMembers(team_slug) { + if (context.eventName === 'pull_request') { + // We have no chance of getting a token in the pull_request context with the right + // permissions to access the members endpoint below. Thus, we're pretending to have + // no members. This is OK; because this is only for the Test workflow, not for + // real use. + return [] + } + + if (!members[team_slug]) { + members[team_slug] = github.paginate(github.rest.teams.listMembersInOrg, { + org: context.repo.owner, + team_slug, + per_page: 100, + }) + } + + return members[team_slug] + } + + // Caching users saves API requests when running the bot on the schedule and processing + // many PRs at once. It also helps to encapsulate the special logic we need, because + // actions/github doesn't support that endpoint fully, yet. + const users = {} + function getUser(id) { + if (!users[id]) { + users[id] = github + .request({ + method: 'GET', + url: '/user/{id}', + id, + }) + .then((resp) => resp.data) + } + + return users[id] + } + + async function handlePullRequest({ item, stats, events }) { const log = (k, v) => core.info(`PR #${item.number} - ${k}: ${v}`) const pull_number = item.number @@ -20,11 +152,75 @@ module.exports = async ({ github, context, core, dry }) => { }) ).data - const reviews = await github.paginate(github.rest.pulls.listReviews, { - ...context.repo, - pull_number, + const maintainers = await getMaintainerMap(pull_request.base.ref) + + const merge_bot_eligible = await handleMerge({ + github, + context, + core, + log, + dry, + pull_request, + events, + maintainers, + getTeamMembers, + getUser, }) + // When the same change has already been merged to the target branch, a PR will still be + // open and display the same changes - but will not actually have any effect. This causes + // strange CI behavior, because the diff of the merge-commit is empty, no rebuilds will + // be detected, no maintainers pinged. + // We can just check the temporary merge commit, and if it's empty the PR can safely be + // closed - there are no further changes. + // We only do this for PRs, which are non-empty to start with. This avoids closing PRs + // which have been created with an empty commit for notification purposes, for example + // the yearly election notification for voters. + if (pull_request.merge_commit_sha && pull_request.changed_files > 0) { + const commit = ( + await github.rest.repos.getCommit({ + ...context.repo, + ref: pull_request.merge_commit_sha, + }) + ).data + + if (commit.files.length === 0) { + const body = [ + `The diff for the temporary merge commit ${pull_request.merge_commit_sha} is empty.`, + 'The changes in this PR have almost certainly already been merged to the target branch.', + ].join('\n') + + core.info(`PR #${item.number}: closed`) + + if (!dry) { + await github.rest.issues.createComment({ + ...context.repo, + issue_number: pull_number, + body, + }) + + await github.rest.pulls.update({ + ...context.repo, + pull_number, + state: 'closed', + }) + } + + return {} + } + } + + // Check for any human reviews other than GitHub actions and other GitHub apps. + // Accounts could be deleted as well, so don't count them. + const reviews = ( + await github.paginate(github.rest.pulls.listReviews, { + ...context.repo, + pull_number, + }) + ).filter( + (r) => r.user && !r.user.login.endsWith('[bot]') && r.user.type !== 'Bot', + ) + const approvals = new Set( reviews .filter((review) => review.state === 'APPROVED') @@ -53,6 +249,7 @@ module.exports = async ({ github, context, core, dry }) => { // 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: merge-bot eligible': merge_bot_eligible, '12.approvals: 1': approvals.size === 1, '12.approvals: 2': approvals.size === 2, '12.approvals: 3+': approvals.size >= 3, @@ -67,12 +264,24 @@ module.exports = async ({ github, context, core, dry }) => { ( await github.rest.actions.listWorkflowRuns({ ...context.repo, + workflow_id: 'pull-request-target.yml', + event: 'pull_request_target', + exclude_pull_requests: true, + head_sha: pull_request.head.sha, + }) + ).data.workflow_runs[0] ?? + // TODO: Remove this after 2026-02-01, at which point all pr.yml artifacts will have expired. + ( + await github.rest.actions.listWorkflowRuns({ + ...context.repo, + // In older PRs, we need pr.yml instead of pull-request-target.yml. workflow_id: 'pr.yml', event: 'pull_request_target', exclude_pull_requests: true, head_sha: pull_request.head.sha, }) - ).data.workflow_runs[0] ?? {} + ).data.workflow_runs[0] ?? + {} // Newer PRs might not have run Eval to completion, yet. // Older PRs might not have an eval.yml workflow, yet. @@ -80,13 +289,6 @@ module.exports = async ({ github, context, core, dry }) => { log('Last eval run', run_id ?? '') if (conclusion === 'success') { - // Check for any human reviews other than GitHub actions and other GitHub apps. - // Accounts could be deleted as well, so don't count them. - const humanReviews = reviews.filter( - (r) => - r.user && !r.user.login.endsWith('[bot]') && r.user.type !== 'Bot', - ) - Object.assign(prLabels, { // We only set this label if the latest eval run was successful, because if it was not, it // *could* have requested reviewers. We will let the PR author fix CI first, before "escalating" @@ -99,7 +301,7 @@ module.exports = async ({ github, context, core, dry }) => { '9.needs: reviewer': !pull_request.draft && pull_request.requested_reviewers.length === 0 && - humanReviews.length === 0, + reviews.length === 0, }) } @@ -134,22 +336,78 @@ module.exports = async ({ github, context, core, dry }) => { expectedHash: artifact.digest, }) - 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 + // TODO: Get "changed packages" information from list of changed by-name files + // in addition to just the Eval results, to make this work for these packages + // when Eval results have expired as well. + let packages + try { + packages = JSON.parse( + await readFile(`${pull_number}/packages.json`, 'utf-8'), + ) + } catch (e) { + if (e.code !== 'ENOENT') throw e + // TODO: Remove this fallback code once all old artifacts without packages.json + // have expired. This should be the case in ~ February 2026. + packages = Array.from( + new Set( + Object.values( + JSON.parse( + await readFile(`${pull_number}/maintainers.json`, 'utf-8'), + ), + ).flat(1), + ), + ) + } + Object.assign(prLabels, evalLabels, { - '12.approved-by: package-maintainer': - maintainers.intersection(approvals).size > 0, + '11.by: package-maintainer': + Boolean(packages.length) && + packages.every((pkg) => + maintainers[pkg]?.includes(pull_request.user.id), + ), + '12.approved-by: package-maintainer': packages.some((pkg) => + maintainers[pkg]?.some((m) => approvals.has(m)), + ), }) + + if (!pull_request.draft) { + let owners = [] + try { + // TODO: Create owner map similar to maintainer map. + owners = (await readFile(`${pull_number}/owners.txt`, 'utf-8')).split( + '\n', + ) + } catch (e) { + // Older artifacts don't have the owners.txt, yet. + if (e.code !== 'ENOENT') throw e + } + + // We set this label earlier already, but the current PR state can be very different + // after handleReviewers has requested reviews, so update it in this case to prevent + // this label from flip-flopping. + prLabels['9.needs: reviewer'] = await handleReviewers({ + github, + context, + core, + log, + dry, + pull_request, + reviews, + // TODO: Use maintainer map instead of the artifact. + maintainers: Object.keys( + JSON.parse( + await readFile(`${pull_number}/maintainers.json`, 'utf-8'), + ), + ).map((id) => parseInt(id)), + owners, + getTeamMembers, + getUser, + }) + } } return prLabels @@ -210,9 +468,21 @@ module.exports = async ({ github, context, core, dry }) => { const itemLabels = {} + const events = await github.paginate( + github.rest.issues.listEventsForTimeline, + { + ...context.repo, + issue_number, + per_page: 100, + }, + ) + if (item.pull_request || context.payload.pull_request) { stats.prs++ - Object.assign(itemLabels, await handlePullRequest({ item, stats })) + Object.assign( + itemLabels, + await handlePullRequest({ item, stats, events }), + ) } else { stats.issues++ if (item.labels.some(({ name }) => name === '4.workflow: auto-close')) { @@ -224,13 +494,7 @@ module.exports = async ({ github, context, core, dry }) => { } const latest_event_at = new Date( - ( - await github.paginate(github.rest.issues.listEventsForTimeline, { - ...context.repo, - issue_number, - per_page: 100, - }) - ) + events .filter(({ event }) => [ // These events are hand-picked from: @@ -292,7 +556,7 @@ module.exports = async ({ github, context, core, dry }) => { const hasChanges = Object.keys(after).some( (name) => (before[name] ?? false) !== after[name], ) - if (log('Has changes', hasChanges, !hasChanges)) return + if (log('Has label changes', hasChanges, !hasChanges)) return // Skipping labeling on a pull_request event, because we have no privileges. const labels = Object.entries(after) @@ -310,14 +574,21 @@ module.exports = async ({ github, context, core, dry }) => { } } - await withRateLimit({ github, core }, async (stats) => { + // Controls level of parallelism. Applies to both the number of concurrent requests + // as well as the number of concurrent workers going through the list of PRs. + // We'll only boost concurrency when we're running many PRs in parallel on a schedule, + // but not for single PRs. This avoids things going wild, when we accidentally make + // too many API requests on treewides. + const maxConcurrent = context.payload.pull_request ? 1 : 20 + + await withRateLimit({ github, core, maxConcurrent }, async (stats) => { if (context.payload.pull_request) { await handle({ item: context.payload.pull_request, stats }) } else { const lastRun = ( await github.rest.actions.listWorkflowRuns({ ...context.repo, - workflow_id: 'labels.yml', + workflow_id: 'bot.yml', event: 'schedule', status: 'success', exclude_pull_requests: true, @@ -439,11 +710,23 @@ module.exports = async ({ github, context, core, dry }) => { arr.findIndex((firstItem) => firstItem.number === thisItem.number), ) - ;(await Promise.allSettled(items.map((item) => handle({ item, stats })))) - .filter(({ status }) => status === 'rejected') - .map(({ reason }) => - core.setFailed(`${reason.message}\n${reason.cause.stack}`), - ) + // Instead of handling all items in parallel we set up some workers to handle the queue + // with more controlled parallelism. This avoids problems with `pull_request` fetched at + // the beginning getting out of date towards the end, because it took the whole job 20 + // minutes or more to go through 100's of PRs. + await Promise.all( + Array.from({ length: maxConcurrent }, async () => { + while (true) { + const item = items.pop() + if (!item) break + try { + await handle({ item, stats }) + } catch (e) { + core.setFailed(`${e.message}\n${e.cause.stack}`) + } + } + }), + ) } }) } diff --git a/ci/github-script/get-teams.js b/ci/github-script/get-teams.js new file mode 100644 index 000000000000..0a097d23eb2f --- /dev/null +++ b/ci/github-script/get-teams.js @@ -0,0 +1,85 @@ +const excludeTeams = [ + /^voters.*$/, + /^nixpkgs-maintainers$/, + /^nixpkgs-committers$/, +] + +module.exports = async ({ github, context, core, outFile }) => { + const withRateLimit = require('./withRateLimit.js') + const { writeFileSync } = require('node:fs') + + const org = context.repo.owner + + const result = {} + + await withRateLimit({ github, core }, async () => { + // Turn an Array of users into an Object, mapping user.login -> user.id + function makeUserSet(users) { + // Sort in-place and build result by mutation + users.sort((a, b) => (a.login > b.login ? 1 : -1)) + + return users.reduce((acc, user) => { + acc[user.login] = user.id + return acc + }, {}) + } + + // Process a list of teams and append to the result variable + async function processTeams(teams) { + for (const team of teams) { + core.notice(`Processing team ${team.slug}`) + if (!excludeTeams.some((regex) => team.slug.match(regex))) { + const members = makeUserSet( + await github.paginate(github.rest.teams.listMembersInOrg, { + org, + team_slug: team.slug, + role: 'member', + }), + ) + const maintainers = makeUserSet( + await github.paginate(github.rest.teams.listMembersInOrg, { + org, + team_slug: team.slug, + role: 'maintainer', + }), + ) + result[team.slug] = { + description: team.description, + id: team.id, + maintainers, + members, + name: team.name, + } + } + await processTeams( + await github.paginate(github.rest.teams.listChildInOrg, { + org, + team_slug: team.slug, + }), + ) + } + } + + const teams = await github.paginate(github.rest.repos.listTeams, { + ...context.repo, + }) + + await processTeams(teams) + }) + + // Sort the teams by team name + const sorted = Object.keys(result) + .sort() + .reduce((acc, key) => { + acc[key] = result[key] + return acc + }, {}) + + const json = `${JSON.stringify(sorted, null, 2)}\n` + + if (outFile) { + writeFileSync(outFile, json) + } else { + console.log(json) + } +} diff --git a/ci/github-script/merge.js b/ci/github-script/merge.js new file mode 100644 index 000000000000..14d6fd3762ab --- /dev/null +++ b/ci/github-script/merge.js @@ -0,0 +1,347 @@ +const { classify } = require('../supportedBranches.js') + +function runChecklist({ + committers, + events, + files, + pull_request, + log, + maintainers, + user, + userIsMaintainer, +}) { + const allByName = files.every( + ({ filename }) => + filename.startsWith('pkgs/by-name/') && filename.split('/').length > 4, + ) + + const packages = files + .filter(({ filename }) => filename.startsWith('pkgs/by-name/')) + .map(({ filename }) => filename.split('/')[3]) + .filter(Boolean) + + const eligible = !packages.length + ? new Set() + : packages + .map((pkg) => new Set(maintainers[pkg])) + .reduce((acc, cur) => acc?.intersection(cur) ?? cur) + + const approvals = new Set( + events + .filter( + ({ event, state, commit_id }) => + event === 'reviewed' && + state === 'approved' && + // Only approvals for the current head SHA count, otherwise authors could push + // bad code between the approval and the merge. + commit_id === pull_request.head.sha, + ) + .map(({ user }) => user?.id) + // Some users have been deleted, so filter these out. + .filter(Boolean), + ) + + const checklist = { + 'PR targets a [development branch](https://github.com/NixOS/nixpkgs/blob/-/ci/README.md#branch-classification).': + classify(pull_request.base.ref).type.includes('development'), + 'PR touches only files of packages in `pkgs/by-name/`.': allByName, + 'PR is at least one of:': { + 'Approved by a committer.': committers.intersection(approvals).size > 0, + 'Backported via label.': + pull_request.user.login === 'nixpkgs-ci[bot]' && + pull_request.head.ref.startsWith('backport-'), + 'Opened by a committer.': committers.has(pull_request.user.id), + 'Opened by r-ryantm.': pull_request.user.login === 'r-ryantm', + }, + } + + if (user) { + checklist[ + `${user.login} is a member of [@NixOS/nixpkgs-maintainers](https://github.com/orgs/NixOS/teams/nixpkgs-maintainers).` + ] = userIsMaintainer + if (allByName) { + // We can only determine the below, if all packages are in by-name, since + // we can't reliably relate changed files to packages outside by-name. + checklist[`${user.login} is a maintainer of all touched packages.`] = + eligible.has(user.id) + } + } else { + // This is only used when no user is passed, i.e. for labeling. + checklist['PR has maintainers eligible to merge.'] = eligible.size > 0 + } + + const result = Object.values(checklist).every((v) => + typeof v === 'boolean' ? v : Object.values(v).some(Boolean), + ) + + log('checklist', JSON.stringify(checklist)) + log('eligible', JSON.stringify(Array.from(eligible))) + log('result', result) + + return { + checklist, + eligible, + result, + } +} + +// The merge command must be on a separate line and not within codeblocks or html comments. +// Codeblocks can have any number of ` larger than 3 to open/close. We only look at code +// blocks that are not indented, because the later regex wouldn't match those anyway. +function hasMergeCommand(body) { + return (body ?? '') + .replace(//gms, '') + .replace(/(^`{3,})[^`].*?\1/gms, '') + .match(/^@NixOS\/nixpkgs-merge-bot merge\s*$/m) +} + +async function handleMergeComment({ github, body, node_id, reaction }) { + if (!hasMergeCommand(body)) return + + await github.graphql( + `mutation($node_id: ID!, $reaction: ReactionContent!) { + addReaction(input: { + content: $reaction, + subjectId: $node_id + }) + { clientMutationId } + }`, + { node_id, reaction }, + ) +} + +async function handleMerge({ + github, + context, + core, + log, + dry, + pull_request, + events, + maintainers, + getTeamMembers, + getUser, +}) { + const pull_number = pull_request.number + + const committers = new Set( + (await getTeamMembers('nixpkgs-committers')).map(({ id }) => id), + ) + + const files = ( + await github.rest.pulls.listFiles({ + ...context.repo, + pull_number, + per_page: 100, + }) + ).data + + // Early exit to prevent treewides from using up a lot of API requests (and time!) to list + // all the files in the pull request. For now, the merge-bot will not work when 100 or more + // files are touched in a PR - which should be more than fine. + // TODO: Find a more efficient way of downloading all the *names* of the touched files, + // including an early exit when the first non-by-name file is found. + if (files.length >= 100) return false + + // Only look through comments *after* the latest (force) push. + const lastPush = events.findLastIndex( + ({ event, sha, commit_id }) => + ['committed', 'head_ref_force_pushed'].includes(event) && + (sha ?? commit_id) === pull_request.head.sha, + ) + + const comments = events.slice(lastPush + 1).filter( + ({ event, body, user, node_id }) => + ['commented', 'reviewed'].includes(event) && + hasMergeCommand(body) && + // Ignore comments where the user has been deleted already. + user && + // Ignore comments which had already been responded to by the bot. + (dry || + !events.some( + ({ event, body }) => + ['commented'].includes(event) && + // We're only testing this hidden reference, but not the author of the comment. + // We'll just assume that nobody creates comments with this marker on purpose. + // Additionally checking the author is quite annoying for local debugging. + body.match(new RegExp(`^$`, 'm')), + )), + ) + + async function merge() { + if (dry) { + core.info(`Merging #${pull_number}... (dry)`) + return 'Merge completed (dry)' + } + + // Using GraphQL mutations instead of the REST /merge endpoint, because the latter + // doesn't work with Merge Queues. We now have merge queues enabled on all development + // branches, so we don't need a fallback for regular merges. + try { + const resp = await github.graphql( + `mutation($node_id: ID!, $sha: GitObjectID) { + enqueuePullRequest(input: { + expectedHeadOid: $sha, + pullRequestId: $node_id + }) + { + clientMutationId, + mergeQueueEntry { mergeQueue { url } } + } + }`, + { node_id: pull_request.node_id, sha: pull_request.head.sha }, + ) + return [ + `:heavy_check_mark: [Queued](${resp.enqueuePullRequest.mergeQueueEntry.mergeQueue.url}) for merge (#306934)`, + ] + } catch (e) { + log('Enqueing failed', e.response.errors[0].message) + } + + // If required status checks are not satisfied, yet, the above will fail. In this case + // we can enable auto-merge. We could also only use auto-merge, but this often gets + // stuck for no apparent reason. + try { + await github.graphql( + `mutation($node_id: ID!, $sha: GitObjectID) { + enablePullRequestAutoMerge(input: { + expectedHeadOid: $sha, + pullRequestId: $node_id + }) + { clientMutationId } + }`, + { node_id: pull_request.node_id, sha: pull_request.head.sha }, + ) + return [ + `:heavy_check_mark: Enabled Auto Merge (#306934)`, + '', + '> [!TIP]', + '> Sometimes GitHub gets stuck after enabling Auto Merge. In this case, leaving another approval should trigger the merge.', + ] + } catch (e) { + log('Auto Merge failed', e.response.errors[0].message) + throw new Error(e.response.errors[0].message) + } + } + + for (const comment of comments) { + log('comment', comment.node_id) + + async function react(reaction) { + if (dry) { + core.info(`Reaction ${reaction} on ${comment.node_id} (dry)`) + return + } + + await handleMergeComment({ + github, + body: comment.body, + node_id: comment.node_id, + reaction, + }) + } + + async function isMaintainer(username) { + try { + return ( + ( + await github.rest.teams.getMembershipForUserInOrg({ + org: context.repo.owner, + team_slug: 'nixpkgs-maintainers', + username, + }) + ).data.state === 'active' + ) + } catch (e) { + if (e.status === 404) return false + else throw e + } + } + + const { result, eligible, checklist } = runChecklist({ + committers, + events, + files, + pull_request, + log, + maintainers, + user: comment.user, + userIsMaintainer: await isMaintainer(comment.user.login), + }) + + const body = [ + ``, + `@${comment.user.login} wants to merge this PR.`, + '', + 'Requirements to merge this PR with `@NixOS/nixpkgs-merge-bot merge`:', + ...Object.entries(checklist).flatMap(([msg, res]) => + typeof res === 'boolean' + ? `- :${res ? 'white_check_mark' : 'x'}: ${msg}` + : [ + `- :${Object.values(res).some(Boolean) ? 'white_check_mark' : 'x'}: ${msg}`, + ...Object.entries(res).map( + ([msg, res]) => + ` - ${res ? ':white_check_mark:' : ':white_large_square:'} ${msg}`, + ), + ], + ), + '', + ] + + if (eligible.size > 0 && !eligible.has(comment.user.id)) { + const users = await Promise.all( + Array.from(eligible, async (id) => (await getUser(id)).login), + ) + body.push( + '> [!TIP]', + '> Maintainers eligible to merge are:', + ...users.map((login) => `> - ${login}`), + '', + ) + } + + if (result) { + await react('ROCKET') + try { + body.push(...(await merge())) + } catch (e) { + // Remove the HTML comment with node_id reference to allow retrying this merge on the next run. + body.shift() + body.push(`:x: Merge failed with: ${e} (#371492)`) + } + } else { + await react('THUMBS_DOWN') + body.push(':x: Pull Request could not be merged (#305350)') + } + + if (dry) { + core.info(body.join('\n')) + } else { + await github.rest.issues.createComment({ + ...context.repo, + issue_number: pull_number, + body: body.join('\n'), + }) + } + + if (result) break + } + + const { result } = runChecklist({ + committers, + events, + files, + pull_request, + log, + maintainers, + }) + + // Returns a boolean, which indicates whether the PR is merge-bot eligible in principle. + // This is used to set the respective label in bot.js. + return result +} + +module.exports = { + handleMerge, + handleMergeComment, +} diff --git a/ci/github-script/reviewers.js b/ci/github-script/reviewers.js new file mode 100644 index 000000000000..07a77a5fec0d --- /dev/null +++ b/ci/github-script/reviewers.js @@ -0,0 +1,143 @@ +async function handleReviewers({ + github, + context, + core, + log, + dry, + pull_request, + reviews, + maintainers, + owners, + getTeamMembers, + getUser, +}) { + const pull_number = pull_request.number + + const requested_reviewers = new Set( + pull_request.requested_reviewers.map(({ login }) => login), + ) + log( + 'reviewers - requested_reviewers', + Array.from(requested_reviewers).join(', '), + ) + + const existing_reviewers = new Set( + reviews.map(({ user }) => user?.login).filter(Boolean), + ) + log( + 'reviewers - existing_reviewers', + Array.from(existing_reviewers).join(', '), + ) + + // Early sanity check, before we start making any API requests. The list of maintainers + // does not have duplicates so the only user to filter out from this list would be the + // PR author. Therefore, we check for a limit of 15+1, where 15 is the limit we check + // further down again. + // This is to protect against huge treewides consuming all our API requests for no + // reason. + if (maintainers.length > 16) { + core.warning('Too many potential reviewers, skipping review requests.') + // Return a boolean on whether the "needs: reviewers" label should be set. + return existing_reviewers.size === 0 && requested_reviewers.size === 0 + } + + const users = new Set([ + ...(await Promise.all( + maintainers.map(async (id) => (await getUser(id)).login), + )), + ...owners.filter((handle) => handle && !handle.includes('/')), + ]) + log('reviewers - users', Array.from(users).join(', ')) + + const teams = new Set( + owners + .map((handle) => handle.split('/')) + .filter(([org, slug]) => org === context.repo.owner && slug) + .map(([, slug]) => slug), + ) + log('reviewers - teams', Array.from(teams).join(', ')) + + const team_members = new Set( + (await Promise.all(Array.from(teams, getTeamMembers))) + .flat(1) + .map(({ login }) => login), + ) + log('reviewers - team_members', Array.from(team_members).join(', ')) + + const new_reviewers = users + .union(team_members) + // We can't request a review from the author. + .difference(new Set([pull_request.user?.login])) + log('reviewers - new_reviewers', Array.from(new_reviewers).join(', ')) + + // Filter users to repository collaborators. If they're not, they can't be requested + // for review. In that case, they probably missed their invite to the maintainers team. + const reviewers = ( + await Promise.all( + Array.from(new_reviewers, async (username) => { + // TODO: Restructure this file to only do the collaborator check for those users + // who were not already part of a team. Being a member of a team makes them + // collaborators by definition. + try { + await github.rest.repos.checkCollaborator({ + ...context.repo, + username, + }) + return username + } catch (e) { + if (e.status !== 404) throw e + core.warning( + `PR #${pull_number}: User ${username} cannot be requested for review because they don't exist or are not a repository collaborator, ignoring. They probably missed the automated invite to the maintainers team (see ).`, + ) + } + }), + ) + ).filter(Boolean) + log('reviewers - reviewers', reviewers.join(', ')) + + if (reviewers.length > 15) { + core.warning( + `Too many reviewers (${reviewers.join(', ')}), skipping review requests.`, + ) + // Return a boolean on whether the "needs: reviewers" label should be set. + return existing_reviewers.size === 0 && requested_reviewers.size === 0 + } + + const non_requested_reviewers = new Set(reviewers) + .difference(requested_reviewers) + // We don't want to rerequest reviews from people who already reviewed. + .difference(existing_reviewers) + log( + 'reviewers - non_requested_reviewers', + Array.from(non_requested_reviewers).join(', '), + ) + + if (non_requested_reviewers.size === 0) { + log('Has reviewer changes', 'false (skipped)') + } else if (dry) { + core.info( + `Requesting reviewers for #${pull_number}: ${Array.from(non_requested_reviewers).join(', ')} (dry)`, + ) + } else { + // We had tried the "request all reviewers at once" thing in the past, but it didn't work out: + // https://github.com/NixOS/nixpkgs/commit/034613f860fcd339bd2c20c8f6bc259a2f9dc034 + // If we're hitting API errors here again, we'll need to investigate - and possibly reverse + // course. + await github.rest.pulls.requestReviewers({ + ...context.repo, + pull_number, + reviewers, + }) + } + + // Return a boolean on whether the "needs: reviewers" label should be set. + return ( + non_requested_reviewers.size === 0 && + existing_reviewers.size === 0 && + requested_reviewers.size === 0 + ) +} + +module.exports = { + handleReviewers, +} diff --git a/ci/github-script/run b/ci/github-script/run index 1d974cf5355f..8a2906606cac 100755 --- a/ci/github-script/run +++ b/ci/github-script/run @@ -65,22 +65,33 @@ program }) program - .command('labels') - .description('Manage labels on pull requests.') + .command('bot') + .description('Run automation on pull requests and issues.') .argument('', 'Owner of the GitHub repository to label (Example: NixOS)') .argument('', 'Name of the GitHub repository to label (Example: nixpkgs)') .argument('[pr]', 'Number of the Pull Request to label') .option('--no-dry', 'Make actual modifications') .action(async (owner, repo, pr, options) => { - const labels = (await import('./labels.js')).default + const bot = (await import('./bot.js')).default const tmp = mkdtempSync(join(tmpdir(), 'github-script-')) try { process.env.GITHUB_WORKSPACE = tmp process.chdir(tmp) - await run(labels, owner, repo, pr, options) + await run(bot, owner, repo, pr, options) } finally { rmSync(tmp, { recursive: true }) } }) +program + .command('get-teams') + .description('Fetch the list of teams with GitHub and output it to a file') + .argument('', 'Owner of the GitHub repository to label (Example: NixOS)') + .argument('', 'Name of the GitHub repository to label (Example: nixpkgs)') + .argument('[outFile]', 'Path to the output file (Example: github-teams.json). If not set, prints to stdout') + .action(async (owner, repo, outFile, options) => { + const getTeams = (await import('./get-teams.js')).default + await run(getTeams, owner, repo, undefined, { ...options, outFile }) + }) + await program.parse() diff --git a/ci/github-script/withRateLimit.js b/ci/github-script/withRateLimit.js index efc63057beb7..d1b1c756ea09 100644 --- a/ci/github-script/withRateLimit.js +++ b/ci/github-script/withRateLimit.js @@ -1,4 +1,4 @@ -module.exports = async ({ github, core }, callback) => { +module.exports = async ({ github, core, maxConcurrent = 1 }, callback) => { const Bottleneck = require('bottleneck') const stats = { @@ -13,7 +13,7 @@ module.exports = async ({ github, core }, callback) => { // 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, + maxConcurrent, // Will be updated with first `updateReservoir()` call below. reservoir: 0, }) diff --git a/ci/nixpkgs-vet.nix b/ci/nixpkgs-vet.nix index 7c11dffc4f9b..6bdf92eedb3f 100644 --- a/ci/nixpkgs-vet.nix +++ b/ci/nixpkgs-vet.nix @@ -32,6 +32,7 @@ runCommand "nixpkgs-vet" } '' export NIX_STATE_DIR=$(mktemp -d) + $NIXPKGS_VET_NIX_PACKAGE/bin/nix-store --init nixpkgs-vet --base ${filteredBase} ${filteredHead} diff --git a/ci/parse.nix b/ci/parse.nix index 26ac0f785fd4..14fd1e719547 100644 --- a/ci/parse.nix +++ b/ci/parse.nix @@ -20,24 +20,15 @@ runCommand "nix-parse-${nix.name}" '' export NIX_STORE_DIR=$TMPDIR/store export NIX_STATE_DIR=$TMPDIR/state + nix-store --init 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 + # This will only show the first parse error, not all of them. That's fine, because + # the other CI jobs will report in more detail. This job is about checking parsing + # across different implementations / versions, not about providing the best DX. + # Returning all parse errors requires significantly more resources. + find . -type f -iname '*.nix' | xargs -P $(nproc) nix-instantiate --parse >/dev/null touch $out '' diff --git a/ci/pinned.json b/ci/pinned.json index 4d5456837b2c..fa58242b75ab 100644 --- a/ci/pinned.json +++ b/ci/pinned.json @@ -9,9 +9,9 @@ }, "branch": "nixpkgs-unstable", "submodules": false, - "revision": "e57b3b16ad8758fd681511a078f35c416a8cc939", - "url": "https://github.com/NixOS/nixpkgs/archive/e57b3b16ad8758fd681511a078f35c416a8cc939.tar.gz", - "hash": "04zp6jjd4xr6jfps84p8yh5ym5962mii4825fn75lqk14sz4rq56" + "revision": "12c1f0253aa9a54fdf8ec8aecaafada64a111e24", + "url": "https://github.com/NixOS/nixpkgs/archive/12c1f0253aa9a54fdf8ec8aecaafada64a111e24.tar.gz", + "hash": "0zr033ybqjc5spwh7xnzkhbqgc6gh8waw6z76rpvadxckyqlfgiq" }, "treefmt-nix": { "type": "Git", @@ -22,9 +22,9 @@ }, "branch": "main", "submodules": false, - "revision": "5eda4ee8121f97b218f7cc73f5172098d458f1d1", - "url": "https://github.com/numtide/treefmt-nix/archive/5eda4ee8121f97b218f7cc73f5172098d458f1d1.tar.gz", - "hash": "1vqns9hjhmbnhdq2xvcmdxng11jrmcn9lpk2ncfh1f969z9lj8y9" + "revision": "4ef3dfdbb5ddfb9e39999a2f2b0c2637277859d4", + "url": "https://github.com/numtide/treefmt-nix/archive/4ef3dfdbb5ddfb9e39999a2f2b0c2637277859d4.tar.gz", + "hash": "0dhvpzcknsr2ybi3zz9mjggs93aqkfr24radvlw74y9620dziqw4" } }, "version": 5 diff --git a/ci/request-reviews/default.nix b/ci/request-reviews/default.nix deleted file mode 100644 index 075ff52fd564..000000000000 --- a/ci/request-reviews/default.nix +++ /dev/null @@ -1,41 +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 - ]; - }; - nativeBuildInputs = [ makeWrapper ]; - dontBuild = true; - installPhase = '' - mkdir -p $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 - ''; -} diff --git a/ci/request-reviews/get-code-owners.sh b/ci/request-reviews/get-code-owners.sh deleted file mode 100755 index 13a377429b92..000000000000 --- a/ci/request-reviews/get-code-owners.sh +++ /dev/null @@ -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[@]}" diff --git a/ci/request-reviews/request-code-owner-reviews.sh b/ci/request-reviews/request-code-owner-reviews.sh deleted file mode 100755 index 663285ae03fe..000000000000 --- a/ci/request-reviews/request-code-owner-reviews.sh +++ /dev/null @@ -1,60 +0,0 @@ -#!/usr/bin/env bash - -# Requests reviews for a PR - -set -euo pipefail -tmp=$(mktemp -d) -trap 'rm -rf "$tmp"' exit -SCRIPT_DIR=$(dirname "$0") - -log() { - echo "$@" >&2 -} - -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 "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" diff --git a/ci/request-reviews/request-reviewers.sh b/ci/request-reviews/request-reviewers.sh deleted file mode 100755 index 1c105e385d28..000000000000 --- a/ci/request-reviews/request-reviewers.sh +++ /dev/null @@ -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 ), 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 diff --git a/default.nix b/default.nix index 5f759c13014d..747bdf57e74f 100644 --- a/default.nix +++ b/default.nix @@ -9,7 +9,7 @@ if missingFeatures != [ ] then This version of Nixpkgs requires an implementation of Nix with the following features: - ${builtins.concatStringsSep "\n- " missingFeatures} - Your are evaluating with Nix ${builtins.nixVersion or "(too old to know)"}, please upgrade: + You are evaluating with Nix ${builtins.nixVersion or "(too old to know)"}, please upgrade: - If you are running NixOS, `nixos-rebuild' can be used to upgrade your system. diff --git a/doc/build-helpers/images/dockertools.section.md b/doc/build-helpers/images/dockertools.section.md index fc6cc0fb4d35..f0b561d480e5 100644 --- a/doc/build-helpers/images/dockertools.section.md +++ b/doc/build-helpers/images/dockertools.section.md @@ -1,6 +1,6 @@ # pkgs.dockerTools {#sec-pkgs-dockerTools} -`pkgs.dockerTools` is a set of functions for creating and manipulating Docker images according to the [Docker Image Specification v1.3.0](https://github.com/moby/moby/blob/46f7ab808b9504d735d600e259ca0723f76fb164/image/spec/spec.md#image-json-field-descriptions). +`pkgs.dockerTools` is a set of functions for creating and manipulating Docker images according to the [Docker Image Specification v1.3.1](https://github.com/moby/docker-image-spec/blob/v1.3.1/spec.md). Docker itself is not used to perform any of the operations done by these functions. ## buildImage {#ssec-pkgs-dockerTools-buildImage} @@ -130,7 +130,7 @@ Similarly, if you encounter errors similar to `Error_Protocol ("certificate has `config` (Attribute Set or Null; _optional_) : Used to specify the configuration of the containers that will be started off the generated image. - Must be an attribute set, with each attribute as listed in the [Docker Image Specification v1.3.0](https://github.com/moby/moby/blob/46f7ab808b9504d735d600e259ca0723f76fb164/image/spec/spec.md#image-json-field-descriptions). + Must be an attribute set, with each attribute as listed in the [Docker Image Specification v1.3.1](https://github.com/moby/docker-image-spec/blob/v1.3.1/spec.md#image-json-field-descriptions). _Default value:_ `null`. @@ -138,7 +138,7 @@ Similarly, if you encounter errors similar to `Error_Protocol ("certificate has : Used to specify the image architecture. This is useful for multi-architecture builds that don't need cross compiling. - If specified, its value should follow the [OCI Image Configuration Specification](https://github.com/opencontainers/image-spec/blob/main/config.md#properties), which should still be compatible with Docker. + If specified, its value should follow the [OCI Image Configuration Specification](https://github.com/opencontainers/image-spec/blob/v1.1.1/config.md#properties), which should still be compatible with Docker. 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:_ the same value from `pkgs.go.GOARCH`. @@ -202,6 +202,10 @@ Similarly, if you encounter errors similar to `Error_Protocol ("certificate has _Default value:_ `false`. +`meta` (Attribute Set) + +: The `meta` attribute of the resulting derivation, as in `stdenv.mkDerivation`. Accepts `description`, `maintainers` and any other `meta` attributes. + `contents` **DEPRECATED** : This attribute is deprecated, and users are encouraged to use `copyToRoot` instead. @@ -635,6 +639,10 @@ This allows the function to produce reproducible images. _Default value:_ `false`. +`meta` (Attribute Set) + +: The `meta` attribute of the resulting derivation, as in `stdenv.mkDerivation`. Accepts `description`, `maintainers` and any other `meta` attributes. + `passthru` (Attribute Set; _optional_) : Use this to pass any attributes as [`passthru`](#chap-passthru) for the resulting derivation. diff --git a/doc/build-helpers/testers.chapter.md b/doc/build-helpers/testers.chapter.md index e4e8ddbb2c17..49407c6e9b8e 100644 --- a/doc/build-helpers/testers.chapter.md +++ b/doc/build-helpers/testers.chapter.md @@ -421,6 +421,11 @@ Check that two paths have the same contents. : A message that is printed last if the file system object contents at the two paths don't match exactly. +`checkMetadata` (boolean) + +: Whether to fail on metadata differences, such as permissions or ownership. + Defaults to `true`. + :::{.example #ex-testEqualContents-toyexample} # Check that two paths have the same contents diff --git a/doc/hooks/cmake.section.md b/doc/hooks/cmake.section.md index 427a03a73986..afaa5b21bcf1 100644 --- a/doc/hooks/cmake.section.md +++ b/doc/hooks/cmake.section.md @@ -30,6 +30,14 @@ This setting has no tangible effect when running the build in a sandboxed deriva The default value is `build`. +#### `cmakeBuildType` {#cmake-build-type} + +Build type of cmake output. + +Internally populates the `CMAKE_BUILD_TYPE` cmake flag. + +The default value is `Release`. + #### `dontUseCmakeConfigure` {#dont-use-cmake-configure} When set to true, don't use the predefined `cmakeConfigurePhase`. diff --git a/doc/hooks/index.md b/doc/hooks/index.md index cd04fd84495a..cd769cec0373 100644 --- a/doc/hooks/index.md +++ b/doc/hooks/index.md @@ -20,6 +20,7 @@ ghc.section.md gnome.section.md haredo.section.md installShellFiles.section.md +julec.section.md just.section.md libiconv.section.md libxml2.section.md diff --git a/doc/hooks/julec.section.md b/doc/hooks/julec.section.md new file mode 100644 index 000000000000..f85619ac39e7 --- /dev/null +++ b/doc/hooks/julec.section.md @@ -0,0 +1,77 @@ +# julec.hook {#julec-hook} + +[Jule](https://jule.dev) is an effective programming language designed to build efficient, fast, reliable and safe software while maintaining simplicity. + +In Nixpkgs, `jule.hook` overrides the default build, check and install phases. + +## Example code snippet {#julec-hook-example-code-snippet} + +```nix +{ + julec, + clangStdenv, +}: + +clangStdenv.mkDerivation (finalAttrs: { + # ... + + nativeBuildInputs = [ julec.hook ]; + + # Customize filenames if needed + JULE_SRC_DIR = "./src"; + JULE_OUT_DIR = "./bin"; + JULE_OUT_NAME = "hello-jule"; + JULE_TEST_DIR = "./tests"; + JULE_TEST_OUT_DIR = "./test-bin"; + JULE_TEST_OUT_NAME = "hello-jule-test"; + + # ... +}) +``` + +## Variables controlling julec.hook {#julec-hook-variables} + +### `JULE_SRC_DIR` {#julec-hook-variable-jule-src-dir} + +Specifies the source directory containing `main.jule`. +Default is `./src`. + +### `JULE_OUT_DIR` {#julec-hook-variable-jule-out-dir} + +Specifies the output directory for the compiled binary. +Default is `./bin`. + +### `JULE_OUT_NAME` {#julec-hook-variable-jule-out-name} + +Specifies the name of the compiled binary. +Default is `output`. + +### `JULE_TEST_DIR` {#julec-hook-variable-jule-test-dir} + +Specifies the directory containing test files. +Default is the value of [`JULE_SRC_DIR`](#julec-hook-variable-jule-src-dir). + +### `JULE_TEST_OUT_DIR` {#julec-hook-variable-jule-test-out-dir} + +Specifies the output directory for compiled test binaries. +Default is the value of [`JULE_OUT_DIR`](#julec-hook-variable-jule-out-dir). + +### `JULE_TEST_OUT_NAME` {#julec-hook-variable-jule-test-out-name} + +Specifies the name of the compiled test binary. +Default is the value of [`JULE_OUT_NAME`](#julec-hook-variable-jule-out-name) with `-test` suffix. + +### `dontUseJulecBuild` {#julec-hook-variable-dontusejulecbuild} + +When set to true, doesn't use the predefined `julecBuildHook`. +Default is false. + +### `dontUseJulecCheck` {#julec-hook-variable-dontusejuleccheck} + +When set to true, doesn't use the predefined `julecCheckHook`. +Default is false. + +### `dontUseJulecInstall` {#julec-hook-variable-dontusejulecinstall} + +When set to true, doesn't use the predefined `julecInstallHook`. +Default is false. diff --git a/doc/languages-frameworks/cuda.section.md b/doc/languages-frameworks/cuda.section.md index a469cdd42188..01b70402cf48 100644 --- a/doc/languages-frameworks/cuda.section.md +++ b/doc/languages-frameworks/cuda.section.md @@ -26,23 +26,9 @@ All CUDA package sets include common CUDA packages like `libcublas`, `cudnn`, `t CUDA support is not enabled by default in Nixpkgs. To enable CUDA support, make sure Nixpkgs is imported with a configuration similar to the following: ```nix +{ pkgs }: { - allowUnfreePredicate = - let - ensureList = x: if builtins.isList x then x else [ x ]; - in - package: - builtins.all ( - license: - license.free - || builtins.elem license.shortName [ - "CUDA EULA" - "cuDNN EULA" - "cuSPARSELt EULA" - "cuTENSOR EULA" - "NVidia OptiX EULA" - ] - ) (ensureList package.meta.license); + allowUnfreePredicate = pkgs._cuda.lib.allowUnfreeCudaPredicate; cudaCapabilities = [ ]; cudaForwardCompat = true; cudaSupport = true; @@ -63,45 +49,23 @@ The `cudaForwardCompat` boolean configuration option determines whether PTX supp ### Modifying CUDA package sets {#cuda-modifying-cuda-package-sets} -CUDA package sets are created by using `callPackage` on `pkgs/top-level/cuda-packages.nix` with an explicit argument for `cudaMajorMinorVersion`, a string of the form `"."` (e.g., `"12.2"`), which informs the CUDA package set tooling which version of CUDA to use. The majority of the CUDA package set tooling is available through the top-level attribute set `_cuda`, a fixed-point defined outside the CUDA package sets. +CUDA package sets are defined in `pkgs/top-level/cuda-packages.nix`. A CUDA package set is created by `callPackage`-ing `pkgs/development/cuda-modules/default.nix` with an attribute set `manifests`, containing NVIDIA manifests for each redistributable. The manifests for supported redistributables are available through `_cuda.manifests` and live in `pkgs/development/cuda-modules/_cuda/manifests`. -::: {.caution} -The `cudaMajorMinorVersion` and `_cuda` attributes are not part of the CUDA package set fixed-point, but are instead provided by `callPackage` from the top-level in the construction of the package set. As such, they must be modified via the package set's `override` attribute. -::: +The majority of the CUDA package set tooling is available through the top-level attribute set `_cuda`, a fixed-point defined outside the CUDA package sets. As a fixed-point, `_cuda` should be modified through its `extend` attribute. ::: {.caution} As indicated by the underscore prefix, `_cuda` is an implementation detail and no guarantees are provided with respect to its stability or API. The `_cuda` attribute set is exposed only to ease creation or modification of CUDA package sets by expert, out-of-tree users. ::: +Out-of-tree modifications of packages should use `overrideAttrs` to make any necessary modifications to the package expression. + ::: {.note} -The `_cuda` attribute set fixed-point should be modified through its `extend` attribute. +The `_cuda` attribute set previously exposed `fixups`, an attribute set mapping from package name (`pname`) to a `callPackage`-compatible expression which provided to `overrideAttrs` on the result of a generic redistributable builder. This functionality has been removed in favor of including full package expressions for each redistributable package to ensure consistent attribute set membership across supported CUDA releases, platforms, and configurations. ::: -The `_cuda.fixups` attribute set is a mapping from package name (`pname`) to a `callPackage`-compatible expression which will be provided to `overrideAttrs` on the result of our generic builder. - -::: {.caution} -Fixups are chosen from `_cuda.fixups` by `pname`. As a result, packages with multiple versions (e.g., `cudnn`, `cudnn_8_9`, etc.) all share a single fixup function (i.e., `_cuda.fixups.cudnn`, which is `pkgs/development/cuda-modules/fixups/cudnn.nix`). -::: - -As an example, you can change the fixup function used for cuDNN for only the default CUDA package set with this overlay: - -```nix -final: prev: { - cudaPackages = prev.cudaPackages.override (prevArgs: { - _cuda = prevArgs._cuda.extend ( - _: prevAttrs: { - fixups = prevAttrs.fixups // { - cudnn = ; - }; - } - ); - }); -} -``` - ### Extending CUDA package sets {#cuda-extending-cuda-package-sets} -CUDA package sets are scopes and provide the usual `overrideScope` attribute for overriding package attributes (see the note about `cudaMajorMinorVersion` and `_cuda` in [Configuring CUDA package sets](#cuda-modifying-cuda-package-sets)). +CUDA package sets are scopes and provide the usual `overrideScope` attribute for overriding package attributes (see the note about `_cuda` in [Configuring CUDA package sets](#cuda-modifying-cuda-package-sets)). Inspired by `pythonPackagesExtensions`, the `_cuda.extensions` attribute is a list of extensions applied to every version of the CUDA package set, allowing modification of all versions of the CUDA package set without needing to know their names or explicitly enumerate and modify them. As an example, disabling `cuda_compat` across all CUDA package sets can be accomplished with this overlay: @@ -115,6 +79,8 @@ final: prev: { } ``` +Redistributable packages are constructed by the `buildRedist` helper; see `pkgs/development/cuda-modules/buildRedist/default.nix` for the implementation. + ### Using `cudaPackages` {#cuda-using-cudapackages} ::: {.caution} @@ -194,7 +160,7 @@ In `pkgsForCudaArch`, the `cudaForwardCompat` option is set to `false` because e ::: {.caution} Not every version of CUDA supports every architecture! -To illustrate: support for Blackwell (e.g., `sm_100`) was added in CUDA 12.8. Assume our Nixpkgs' default CUDA package set is to CUDA 12.6. Then the Nixpkgs variant available through `pkgsForCudaArch.sm_100` is useless, since packages like `pkgsForCudaArch.sm_100.opencv` and `pkgsForCudaArch.sm_100.python3Packages.torch` will try to generate code for `sm_100`, an architecture unknown to CUDA 12.6. In that case, you should use `pkgsForCudaArch.sm_100.cudaPackages_12_8.pkgs` instead (see [Using cudaPackages.pkgs](#cuda-using-cudapackages-pkgs) for more details). +To illustrate: support for Blackwell (e.g., `sm_100`) was added in CUDA 12.8. Assume our Nixpkgs' default CUDA package set is to CUDA 12.6. Then the Nixpkgs variant available through `pkgsForCudaArch.sm_100` is useless, since packages like `pkgsForCudaArch.sm_100.opencv` and `pkgsForCudaArch.sm_100.python3Packages.torch` will try to generate code for `sm_100`, an architecture unknown to CUDA 12.6. In that case, you should use `pkgsForCudaArch.sm_100.cudaPackages_12_8.pkgs` instead (see [Using `cudaPackages.pkgs`](#cuda-using-cudapackages-pkgs) for more details). ::: The `pkgsForCudaArch` attribute set makes it possible to access packages built for a specific architecture without needing to manually call `pkgs.extend` and supply a new `config`. As an example, `pkgsForCudaArch.sm_89.python3Packages.torch` provides PyTorch built for Ada Lovelace GPUs. @@ -306,82 +272,41 @@ This section of the docs is still very much in progress. Feedback is welcome in ### Package set maintenance {#cuda-package-set-maintenance} -The CUDA Toolkit is a suite of CUDA libraries and software meant to provide a development environment for CUDA-accelerated applications. Until the release of CUDA 11.4, NVIDIA had only made the CUDA Toolkit available as a multi-gigabyte runfile installer, which we provide through the [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit) attribute. From CUDA 11.4 and onwards, NVIDIA has also provided CUDA redistributables (“CUDA-redist”): individually packaged CUDA Toolkit components meant to facilitate redistribution and inclusion in downstream projects. These packages are available in the [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) package set. +The CUDA Toolkit is a suite of CUDA libraries and software meant to provide a development environment for CUDA-accelerated applications. Until the release of CUDA 11.4, NVIDIA had only made the CUDA Toolkit available as a multi-gigabyte runfile installer. From CUDA 11.4 and onwards, NVIDIA has also provided CUDA redistributables (“CUDA-redist”): individually packaged CUDA Toolkit components meant to facilitate redistribution and inclusion in downstream projects. These packages are available in the [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) package set. -All new projects should use the CUDA redistributables available in [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) in place of [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit), as they are much easier to maintain and update. +While the monolithic CUDA Toolkit runfile installer is no longer provided, [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit) provides a `symlinkJoin`-ed approximation which common libraries. The use of [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit) is discouraged: all new projects should use the CUDA redistributables available in [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) instead, as they are much easier to maintain and update. #### Updating redistributables {#cuda-updating-redistributables} -1. Go to NVIDIA's index of CUDA redistributables: -2. Make a note of the new version of CUDA available. -3. Run +Whenever a new version of a redistributable manifest is made available: - ```bash - nix run github:connorbaker/cuda-redist-find-features -- \ - download-manifests \ - --log-level DEBUG \ - --version \ - https://developer.download.nvidia.com/compute/cuda/redist \ - ./pkgs/development/cuda-modules/cuda/manifests - ``` +1. Check the corresponding README.md in `pkgs/development/cuda-modules/_cuda/manifests` for the URL to use when vendoring manifests. +2. Update the manifest version used in construction of each CUDA package set in `pkgs/top-level/cuda-packages.nix`. +3. Update package expressions in `pkgs/development/cuda-modules/packages`. - This will download a copy of the manifest for the new version of CUDA. -4. Run +Updating package expressions amounts to: - ```bash - nix run github:connorbaker/cuda-redist-find-features -- \ - process-manifests \ - --log-level DEBUG \ - --version \ - https://developer.download.nvidia.com/compute/cuda/redist \ - ./pkgs/development/cuda-modules/cuda/manifests - ``` - - This will generate a `redistrib_features_.json` file in the same directory as the manifest. -5. Update the `cudaVersionMap` attribute set in `pkgs/development/cuda-modules/cuda/extension.nix`. - -#### Updating cuTensor {#cuda-updating-cutensor} - -1. Repeat the steps present in [Updating CUDA redistributables](#cuda-updating-redistributables) with the following changes: - - Use the index of cuTensor redistributables: - - Use the newest version of cuTensor available instead of the newest version of CUDA. - - Use `pkgs/development/cuda-modules/cutensor/manifests` instead of `pkgs/development/cuda-modules/cuda/manifests`. - - Skip the step of updating `cudaVersionMap` in `pkgs/development/cuda-modules/cuda/extension.nix`. +- adding fixes conditioned on newer releases, like added or removed dependencies +- adding package expressions for new packages +- updating `passthru.brokenConditions` and `passthru.badPlatformsConditions` with various constraints, (e.g., new releases removing support for various architectures) #### Updating supported compilers and GPUs {#cuda-updating-supported-compilers-and-gpus} -1. Update `nvccCompatibilities` in `pkgs/development/cuda-modules/_cuda/data/nvcc.nix` to include the newest release of NVCC, as well as any newly supported host compilers. -2. Update `cudaCapabilityToInfo` in `pkgs/development/cuda-modules/_cuda/data/cuda.nix` to include any new GPUs supported by the new release of CUDA. - -#### Updating the CUDA Toolkit runfile installer {#cuda-updating-the-cuda-toolkit} - -::: {.warning} -While the CUDA Toolkit runfile installer is still available in Nixpkgs as the [`cudaPackages.cudatoolkit`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages.cudatoolkit) attribute, its use is not recommended, and it should be considered deprecated. Please migrate to the CUDA redistributables provided by the [`cudaPackages`](https://search.nixos.org/packages?channel=unstable&type=packages&query=cudaPackages) package set. - -To ensure packages relying on the CUDA Toolkit runfile installer continue to build, it will continue to be updated until a migration path is available. -::: - -1. Go to NVIDIA's CUDA Toolkit runfile installer download page: -2. Select the appropriate OS, architecture, distribution, and version, and installer type. - - - For example: Linux, x86_64, Ubuntu, 22.04, runfile (local) - - NOTE: Typically, we use the Ubuntu runfile. It is unclear if the runfile for other distributions will work. - -3. Take the link provided by the installer instructions on the webpage after selecting the installer type and get its hash by running: - - ```bash - nix store prefetch-file --hash-type sha256 - ``` - -4. Update `pkgs/development/cuda-modules/cudatoolkit/releases.nix` to include the release. +1. Update `nvccCompatibilities` in `pkgs/development/cuda-modules/_cuda/db/bootstrap/nvcc.nix` to include the newest release of NVCC, as well as any newly supported host compilers. +2. Update `cudaCapabilityToInfo` in `pkgs/development/cuda-modules/_cuda/db/bootstrap/cuda.nix` to include any new GPUs supported by the new release of CUDA. #### Updating the CUDA package set {#cuda-updating-the-cuda-package-set} -1. Include a new `cudaPackages__` package set in `pkgs/top-level/all-packages.nix`. +::: {.note} +Changing the default CUDA package set should occur in a separate PR, allowing time for additional testing. +::: - - NOTE: Changing the default CUDA package set should occur in a separate PR, allowing time for additional testing. +::: {.warning} +As described in [Using `cudaPackages.pkgs`](#cuda-using-cudapackages-pkgs), the current implementation fix for package set leakage involves creating a new instance for each non-default CUDA package sets. As such, We should limit the number of CUDA package sets which have `recurseForDerivations` set to true: `lib.recurseIntoAttrs` should only be applied to the default CUDA package set. +::: -2. Successfully build the closure of the new package set, updating `pkgs/development/cuda-modules/cuda/overrides.nix` as needed. Below are some common failures: +1. Include a new `cudaPackages__` package set in `pkgs/top-level/cuda-packages.nix` and inherit it in `pkgs/top-level/all-packages.nix`. +2. Successfully build the closure of the new package set, updating expressions in `pkgs/development/cuda-modules/packages` as needed. Below are some common failures: | Unable to ... | During ... | Reason | Solution | Note | | -------------- | -------------------------------- | ------------------------------------------------ | -------------------------- | ------------------------------------------------------------ | @@ -389,6 +314,13 @@ To ensure packages relying on the CUDA Toolkit runfile installer continue to bui | Find libraries | `configurePhase` | Missing dependency on a `dev` output | Add the missing dependency | The `dev` output typically contains CMake configuration files | | Find libraries | `buildPhase` or `patchelf` | Missing dependency on a `lib` or `static` output | Add the missing dependency | The `lib` or `static` output typically contains the libraries | +::: {.note} +Two utility derivations ease testing updates to the package set: + +- `cudaPackages.tests.redists-unpacked`: the `src` of each redistributable package unpacked and `symlinkJoin`-ed +- `cudaPackages.tests.redists-installed`: each output of each redistributable package `symlinkJoin`-ed +::: + Failure to run the resulting binary is typically the most challenging to diagnose, as it may involve a combination of the aforementioned issues. This type of failure typically occurs when a library attempts to load or open a library it depends on that it does not declare in its `DT_NEEDED` section. Try the following debugging steps: 1. First ensure that dependencies are patched with [`autoAddDriverRunpath`](https://search.nixos.org/packages?channel=unstable&type=packages&query=autoAddDriverRunpath). diff --git a/doc/languages-frameworks/gradle.section.md b/doc/languages-frameworks/gradle.section.md index d99fe9337ecc..37e840935689 100644 --- a/doc/languages-frameworks/gradle.section.md +++ b/doc/languages-frameworks/gradle.section.md @@ -129,7 +129,7 @@ The update script does the following: `fetchDeps` takes the following arguments: - `attrPath` - the path to the package in nixpkgs (for example, - `"javaPackages.openjfx22"`). Used for update script metadata. + `"javaPackages.openjfx25"`). Used for update script metadata. - `pname` - an alias for `attrPath` for convenience. This is what you will generally use instead of `pkg` or `attrPath`. - `pkg` - the package to be used for fetching the dependencies. Defaults diff --git a/doc/languages-frameworks/haskell.section.md b/doc/languages-frameworks/haskell.section.md index d9246994676d..f81c1b77d84e 100644 --- a/doc/languages-frameworks/haskell.section.md +++ b/doc/languages-frameworks/haskell.section.md @@ -260,6 +260,14 @@ the same package with the `previousIntermediates` argument to support incremental builds. See [“Incremental builds”](#haskell-incremental-builds) for more information. Defaults to `false`. +`dontConvertCabalFileToUnix` +: By default, `haskellPackages.mkDerivation` converts the `.cabal` file of a +given package to Unix line endings. +This is intended to work around +[Hackage converting revised `.cabal` files to DOS line endings](https://github.com/haskell/hackage-server/issues/316) +which frequently causes patches to stop applying. +You can pass `true` to disable this behavior. + `enableLibraryProfiling` : Whether to enable [profiling][profiling] for libraries contained in the package. Enabled by default if supported. @@ -1249,8 +1257,8 @@ it does for the unstable branches. ### Why is topic X not covered in this section? Why is section Y missing? {#haskell-why-not-covered} We have been working on [moving the nixpkgs Haskell documentation back into the -nixpkgs manual](https://github.com/NixOS/nixpkgs/issues/121403). Since this -process has not been completed yet, you may find some topics missing here +nixpkgs manual](https://github.com/NixOS/nixpkgs/issues/121403). +Since this process has not been completed yet, you may find some topics missing here covered in the old [haskell4nix docs](https://haskell4nix.readthedocs.io/). If you feel any important topic is not documented at all, feel free to comment diff --git a/doc/languages-frameworks/idris2.section.md b/doc/languages-frameworks/idris2.section.md index 953222b9b315..a9b524250a37 100644 --- a/doc/languages-frameworks/idris2.section.md +++ b/doc/languages-frameworks/idris2.section.md @@ -1,5 +1,57 @@ # Idris2 {#sec-idris2} +When developing using Idris2, by default the Idris compiler only has the minimal support libraries in its environment. This means that it will not attempt to read any libraries installed +globally, for example in the `$HOME` directory. The recommended way to use Idris2 is to wrap the compiler in an environment that provides these packages per-project, for example in a +devShell. + +```nix +{ + pkgs ? import { }, +}: +pkgs.mkShell { + packages = [ (idris2.withPackages (p: [ p.idris2Api ])) ]; +} +``` +or, alternatively if Nix is used to build the Idris2 project: + +```nix +{ + pkgs ? import { }, +}: +pkgs.mkShell { + inputsFrom = [ (pkgs.callPackage ./package.nix { }) ]; +} +``` + +By default, the Idris2 compiler provided by Nixpkgs does not read globally installed packages, nor can install them. Running `idris2 --install` will fail because the Nix store is +a read-only file-system. If globally-installed packages are desired rather than the above strategy, one can set `IDRIS2_PREFIX`, or additional `IDRIS2_PACKAGE_PATH` entries +for the compiler to read from. The following snippet will append `$HOME/.idris2` to `$IDRIS2_PACKAGE_PATH`, and if such a variable does not exist, create it. The Nixpkg's Idris2 +compiler append a few required libraries to this path variable, but any paths in the user's environment will be prefixed to those libraries. + +```nix +{ + pkgs ? import { }, +}: +pkgs.mkShell { + packages = [ (idris2.withPackages (p: [ p.idris2Api ])) ]; + shellHook = '' + IDRIS2_PACKAGE_PATH="''${IDRIS2_PACKAGE_PATH:+$IDRIS2_PACKAGE_PATH}$HOME/.idris2" + ''; +} +``` +The following snippet will allow the Idris2 to run `idris2 --install` successfully: +```nix +{ + pkgs ? import { }, +}: +pkgs.mkShell { + packages = [ (idris2.withPackages (p: [ p.idris2Api ])) ]; + shellHook = '' + IDRIS2_PREFIX="$HOME/.idris2" + ''; +} +``` + In addition to exposing the Idris2 compiler itself, Nixpkgs exposes an `idris2Packages.buildIdris` helper to make it a bit more ergonomic to build Idris2 executables or libraries. The `buildIdris` function takes an attribute set that defines at a minimum the `src` and `ipkgName` of the package to be built and any `idrisLibraries` required to build it. The `src` is the same source you're familiar with and the `ipkgName` must be the name of the `ipkg` file for the project (omitting the `.ipkg` extension). The `idrisLibraries` is a list of other library derivations created with `buildIdris`. You can optionally specify other derivation properties as needed but sensible defaults for `configurePhase`, `buildPhase`, and `installPhase` are provided. @@ -56,3 +108,20 @@ lspPkg.executable ``` The above uses the default value of `withSource = false` for the `idris2Api` but could be modified to include that library's source by passing `(idris2Api { withSource = true; })` to `idrisLibraries` instead. `idris2Api` in the above derivation comes built in with `idris2Packages`. This library exposes many of the otherwise internal APIs of the Idris2 compiler. + +The compiler package can be instantiated with packages on its `IDRIS2_PACKAGES` path from the `idris2Packages` set. + +```nix +{ + idris2, + devShell, +}: +let + myIdris = idris2.withPackages (p: [ p.idris2Api ]); +in +devShell { + packages = [ myIdris ]; +} +``` + +This search path is extended from the path already in the user's environment. diff --git a/doc/languages-frameworks/index.md b/doc/languages-frameworks/index.md index 71269aa6c030..3f4b6c48e764 100644 --- a/doc/languages-frameworks/index.md +++ b/doc/languages-frameworks/index.md @@ -20,7 +20,7 @@ Each supported language or software ecosystem has its own package set named `' -I nixpkgs=channel:nixpkgs-unstable nix-repl> javaPackages. javaPackages.compiler javaPackages.openjfx15 javaPackages.openjfx21 javaPackages.recurseForDerivations - javaPackages.jogl_2_4_0 javaPackages.openjfx17 javaPackages.openjfx22 + javaPackages.jogl_2_4_0 javaPackages.openjfx17 javaPackages.openjfx25 javaPackages.mavenfod javaPackages.openjfx19 javaPackages.override javaPackages.openjfx11 javaPackages.openjfx20 javaPackages.overrideDerivation ``` diff --git a/doc/languages-frameworks/php.section.md b/doc/languages-frameworks/php.section.md index 9f221679ce22..988fa659f0aa 100644 --- a/doc/languages-frameworks/php.section.md +++ b/doc/languages-frameworks/php.section.md @@ -214,6 +214,12 @@ code, while others choose not to. In Nix, there are multiple approaches to building a Composer-based project. +::: {.warning} +`buildComposerProject2` has a [known bug](https://github.com/NixOS/nixpkgs/issues/451395) +where the `vendorHash` changes every time a Composer release happens that changes the +`autoload.php` or vendored composer code. +::: + One such method is the `php.buildComposerProject2` helper function, which serves as a wrapper around `mkDerivation`. diff --git a/doc/languages-frameworks/python.section.md b/doc/languages-frameworks/python.section.md index 61c211c0dfcb..fad930c8206d 100644 --- a/doc/languages-frameworks/python.section.md +++ b/doc/languages-frameworks/python.section.md @@ -557,6 +557,19 @@ are used in [`buildPythonPackage`](#buildpythonpackage-function). with the `pipInstallHook`. - `unittestCheckHook` will run tests with `python -m unittest discover`. See [example usage](#using-unittestcheckhook). +#### Overriding build helpers {#overriding-python-build-helpers} + +Like many of the build helpers provided by Nixpkgs, Python build helpers typically provide a `.override` attribute. +It works like [`.override`](#sec-pkg-override), and can be used to override the dependencies of each build helper. + +This allows specifying the stdenv to be used by `buildPythonPackage` or `buildPythonApplication`. The default (`python.stdenv`) can be overridden as follows: + +```nix +buildPythonPackage.override { stdenv = customStdenv; } { + # package attrs... +} +``` + ## User Guide {#user-guide} ### Using Python {#using-python} diff --git a/doc/languages-frameworks/ruby.section.md b/doc/languages-frameworks/ruby.section.md index 62ab8b309635..cf2062845426 100644 --- a/doc/languages-frameworks/ruby.section.md +++ b/doc/languages-frameworks/ruby.section.md @@ -273,6 +273,8 @@ To test that it works, you can then try using the gem with: NIX_PATH=nixpkgs=$PWD nix-shell -p "ruby.withPackages (ps: with ps; [ name-of-your-gem ])" ``` +To check the gems for any security vulnerabilities, run `./maintainers/scripts/audit-ruby-packages/audit-ruby-packages.bash`. + ### Packaging applications {#packaging-applications} A common task is to add a Ruby executable to Nixpkgs; popular examples would be `chef`, `jekyll`, or `sass`. A good way to do that is to use the `bundlerApp` function, that allows you to make a package that only exposes the listed executables. Otherwise, the package may cause conflicts through common paths like `bin/rake` or `bin/bundler` that aren't meant to be used. diff --git a/doc/languages-frameworks/texlive.section.md b/doc/languages-frameworks/texlive.section.md index b4fb5d067f0d..b3305e259044 100644 --- a/doc/languages-frameworks/texlive.section.md +++ b/doc/languages-frameworks/texlive.section.md @@ -235,7 +235,7 @@ runCommand "test.pdf" { nativeBuildInputs = [ latex_with_foiltex ]; } '' The font cache for LuaLaTeX is written to `$HOME`. Therefore, it is necessary to set `$HOME` to a writable path, e.g. [before using LuaLaTeX in nix derivations](https://github.com/NixOS/nixpkgs/issues/180639): ```nix -runCommandNoCC "lualatex-hello-world" { buildInputs = [ texliveFull ]; } '' +runCommand "lualatex-hello-world" { buildInputs = [ texliveFull ]; } '' mkdir $out echo '\documentclass{article} \begin{document} Hello world \end{document}' > main.tex env HOME=$(mktemp -d) lualatex -interaction=nonstopmode -output-format=pdf -output-directory=$out ./main.tex diff --git a/doc/old/cross.txt b/doc/old/cross.txt deleted file mode 100644 index 0f958e772b78..000000000000 --- a/doc/old/cross.txt +++ /dev/null @@ -1,329 +0,0 @@ -Setting up a cross compiler with Nix - -"Cross compilation" means compiling a program on one machine for another -type of machine. A typical use of cross compilation is to compile programs -for embedded devices. These devices often don't have the computing power -and memory to compile programs natively. - -For a fully working cross compiler the following are needed: - -* cross binutils: assembler, archiver, linker, etcetera that understand -the format of the target system - -* cross compiler: a compiler that can generate binary code and object files -for the target platform - -* cross C library: a library to link object files with to create fully -functional programs - -Cross compilers are difficult to set up. A lot of people report that they -cannot succeed in building a cross toolchain successfully. The answers -usually consist of "download this pre-built toolchain", which is equally -unhelpful. - -A toolchain is set up in five steps: - -1. build binutils to that can run on the host platform, but generate code -for the target platform - -2. build Linux kernel headers for the target platform - -3. build a minimal C only version of GCC, that can run on the host platform -and generate code for the target platform - -4. build a C library for the target platform. This includes the dynamic -linker, C library, etc. - -5. build a full GCC - -**** -NB: - -Keep in mind that many programs are not very well suited for cross -compilation. Either they are not intended to run on other platforms, -because the code is highly platform specific, or the configuration process -is not written with cross compilation in mind. - -Nix will not solve these problems for you! -*** - -This document describes to set up a cross compiler to generate code for -arm-linux with uClibc and runs on i686-linux. The "stdenv" used is the -default from the standard Nix packages collection. - -Step 1: build binutils for arm-linux in the stdenv for i686-linux - ---- -{stdenv, fetchurl, noSysDirs}: - -stdenv.mkDerivation { - name = "binutils-2.16.1-arm"; - builder = ./builder.sh; - src = fetchurl { - url = "http://ftp.nluug.nl/gnu/binutils/binutils-2.16.1.tar.bz2"; - hash = "sha256-14pv+YKrL3NyFwbnv9MoWsZHgEZk5+pHhuZtAfkcVsU="; - }; - inherit noSysDirs; - configureFlags = [ "--target=arm-linux" ]; -} ---- - -This will compile binutils that will run on i686-linux, but knows the -format used by arm-linux. - -Step 2: build kernel headers for the target architecture - - default.nix for kernel-headers-arm: - ---- -{stdenv, fetchurl}: - -assert stdenv.buildPlatform.system == "i686-linux"; - -stdenv.mkDerivation { - name = "linux-headers-2.6.13.1-arm"; - builder = ./builder.sh; - src = fetchurl { - url = "http://www.kernel.org/pub/linux/kernel/v2.6/linux-2.6.13.1.tar.bz2"; - hash = "sha256-qtICDjfiA1HxWBrHqtB5DCv9s9/HyznKV1C6IxCrHYs="; - }; -} ---- - - builder.sh for kernel-headers-arm: - ---- -source $stdenv/setup - - -buildPhase() { - make include/linux/version.h -} - -buildPhase=buildPhase - - -installPhase() { - mkdir $out - mkdir $out/include - #cd $out/include - #ln -s asm-arm asm - make include/asm ARCH=arm - cp -prvd include/linux include/asm include/asm-arm include/asm-generic $out/include - echo -n > $out/include/linux/autoconf.h -} - -installPhase=installPhase - - -genericBuild ---- - -Step 3: build a minimal GCC - -Extra/different parameters include the target platform and the kernel -headers argument (this needs a major cleanup, as well as the name, it -needs to be different!). Profiled compilers are disabled. The tarball -used here is just gcc-core. For some reason it doesn't install nicely -if the whole tarball is used (or is this some braino on my side? -- AH). - -Only C is used, because for other languages (such as C++) extra libraries -need to be compiled, for which libraries compiled for the target system -are needed. - -There is a bit of evilness going on. The cross compiled utilities need -to be either copied to or be linked from the output tree of the compiler. -(Is this really true? Back this up with arguments! -- AH) - -Symbolic links are not something we want inside the Nix store. - ---- -{ stdenv, fetchurl, noSysDirs -, langC ? true, langCC ? true, langF77 ? false -, profiledCompiler ? false -, binutilsArm -, kernelHeadersArm -}: - -assert langC; - -stdenv.mkDerivation { - name = "gcc-4.0.2-arm"; - builder = ./builder.sh; - src = fetchurl { - url = "ftp://ftp.nluug.nl/pub/gnu/gcc/gcc-4.0.2/gcc-core-4.0.2.tar.bz2"; - hash = "sha256-LANmXRS7/fN2zF5JUJVd8OjNA5aCDsGLQKhSpxWA3Qk="; - }; - # !!! apply only if noSysDirs is set - patches = [./no-sys-dirs.patch ./gcc-inhibit.patch]; - inherit noSysDirs langC langCC langF77 profiledCompiler; - buildInputs = [binutilsArm]; - inherit kernelHeadersArm binutilsArm; - platform = "arm-linux"; -} ---- - -The builder.sh for a cross-compiler. Note that the binutils are prefixed -with the architecture name, so arm-linux-ld instead of ld, etc. This is -necessary because when we cross-compile a lot of programs look for these -tools with these specific names. The standard gcc-wrapper does not take this -into account yet. - ---- -source $stdenv/setup - - -export NIX_FIXINC_DUMMY=$NIX_BUILD_TOP/dummy -mkdir $NIX_FIXINC_DUMMY - - -if test "$noSysDirs" = "1"; then - - if test "$noSysDirs" = "1"; then - # Figure out what extra flags to pass to the gcc compilers - # being generated to make sure that they use our glibc. - if test -e $NIX_CC/nix-support/orig-glibc; then - glibc=$(cat $NIX_CC/nix-support/orig-glibc) - # Ugh. Copied from gcc-wrapper/builder.sh. We can't just - # source in $NIX_CC/nix-support/add-flags, since that - # would cause *this* GCC to be linked against the - # *previous* GCC. Need some more modularity there. - extraCFlags="-B$glibc/lib -isystem $glibc/include" - extraLDFlags="-B$glibc/lib -L$glibc/lib -Wl,-s \ - -Wl,-dynamic-linker,$glibc/lib/ld-linux.so.2" - - # Oh, what a hack. I should be shot for this. - # In stage 1, we should link against the previous GCC, but - # not afterwards. Otherwise we retain a dependency. - # However, ld-wrapper, which adds the linker flags for the - # previous GCC, is also used in stage 2/3. We can prevent - # it from adding them by NIX_GLIBC_FLAGS_SET, but then - # gcc-wrapper will also not add them, thereby causing - # stage 1 to fail. So we use a trick to only set the - # flags in gcc-wrapper. - hook=$(pwd)/ld-wrapper-hook - echo "NIX_GLIBC_FLAGS_SET=1" > $hook - export NIX_LD_WRAPPER_START_HOOK=$hook - fi - - export NIX_EXTRA_CFLAGS=$extraCFlags - export NIX_EXTRA_LDFLAGS=$extraLDFlags - export CFLAGS=$extraCFlags - export CXXFLAGS=$extraCFlags - export LDFLAGS=$extraLDFlags - fi - -else - patches="" -fi - - -preConfigure=preConfigure -preConfigure() { - - # Determine the frontends to build. - langs="c" - if test -n "$langCC"; then - langs="$langs,c++" - fi - if test -n "$langF77"; then - langs="$langs,f77" - fi - - # Cross compiler evilness - mkdir -p $out - mkdir -p $out/arm-linux - mkdir -p $out/arm-linux/bin - ln -s $binutilsArm/arm-linux/bin/as $out/arm-linux/bin/as - ln -s $binutilsArm/arm-linux/bin/ld $out/arm-linux/bin/ld - ln -s $binutilsArm/arm-linux/bin/ar $out/arm-linux/bin/ar - ln -s $binutilsArm/arm-linux/bin/ranlib $out/arm-linux/bin/ranlib - - # Perform the build in a different directory. - mkdir ../build - cd ../build - - configureScript=../$sourceRoot/configure - configureFlags="--enable-languages=$langs --target=$platform --disable-threads --disable-libmudflap --disable-shared --with-headers=$kernelHeadersArm/include --disable-multilib" -} - - -postInstall=postInstall -postInstall() { - # Remove precompiled headers for now. They are very big and - # probably not very useful yet. - find $out/include -name "*.gch" -exec rm -rf {} \; -prune - - # Remove `fixincl' to prevent a retained dependency on the - # previous gcc. - rm -rf $out/libexec/gcc/*/*/install-tools -} - - -#if test -z "$profiledCompiler"; then - #makeFlags="bootstrap" -#else - #makeFlags="profiledbootstrap" -#fi - -genericBuild ---- - -Step 4: build a C library for the target platform. - -The previous steps are enough to compile a C library. In our case we take -uClibc. It's intended to be a small sized replacement for glibc. It is widely -used in embedded environments. - -... - -Step 5: Build a compiler to link with the newly built C library. - -... - -If we restrict the compiler to just C programs it is relatively easy, -since we only need to wrap the GCC we built in the previous step with all -the right tools and the right C library. Successfully compiled programs with -this compiler and verified to be working on a HP Jornada 820 running Linux -are "patch", "make" and "wget". - -If we want to build C++ programs it gets a lot more difficult. GCC has a -three step compilation process. In the first step a simple compiler, called -xgcc, that can compile only C programs is built. With that compiler it -compiles itself two more times: one time to build a full compiler, and another -time to build a full compiler once again with the freshly built compiler from -step 2. In the second and third step support for C++ is compiled, if this -is configured. - -One of the libraries that has to be built for C++ support step is libstdc++. -This library uses xgcc, even when cross compiling, since libstdc++ has to be -compiled for arm-linux. - -One of the compiler flags that GCC uses for this compiler is called X_CFLAGS. -This is used by the Nix build process to set the dynamic linker, glibc -in the case of i686-linux using the default Nix packages collection. - -Obviously, since we need to compile libstc++ for arm-linux with uClibc linking -will not be done correctly: you can't link object files built for arm-linux -with a glibc built for i686-linux. - -Setting X_CFLAGS to use the uClibc libraries and dynamic linker will fail -too. Earlier on in the build process these flags are used to compile important -files like libgcc.a by the host system gcc, which does need to be linked -to glibc. To make this work correctly you will need to carefully juggle -with compilation flags. This is still work in progress for Nix. - - ---- - -After successfully completing the whole toolchain you can start building -packages with the newly built tools. To make everything build correctly -you will need a stdenv for your target platform. Setting up this platform -will take some effort. Right now there is a very experimental setup for -arm-linux, which needs to be cleaned up before it is production ready. - -Please note that many packages are not well suited for cross-compilation. -Even though the package itself might be very well portable often the -buildscripts are not. One thing that we have seen that causes frequent -build failures is the use of the LD variable. This is often set to 'ld' -and not $(CROSS)-ld. diff --git a/doc/packages/darwin-builder.section.md b/doc/packages/darwin-builder.section.md index fb71a78d6eb3..da46e0ee8f7d 100644 --- a/doc/packages/darwin-builder.section.md +++ b/doc/packages/darwin-builder.section.md @@ -64,13 +64,15 @@ builders = ssh-ng://builder@linux-builder ${ARCH}-linux /etc/nix/builder_ed25519 builders-use-substitutes = true ``` -To allow Nix to connect to a remote builder not running on port 22, you will also need to create a new file at `/etc/ssh/ssh_config.d/100-linux-builder.conf`: +To allow Nix to connect to the default remote builder, which does not run on port 22, you will also need to create a new file at `/etc/ssh/ssh_config.d/100-linux-builder.conf`: ``` Host linux-builder Hostname localhost HostKeyAlias linux-builder Port 31022 + User builder + IdentityFile /etc/nix/builder_ed25519 ``` … and then restart your Nix daemon to apply the change: @@ -79,6 +81,8 @@ Host linux-builder $ sudo launchctl kickstart -k system/org.nixos.nix-daemon ``` +Note that if the builder is running and you have created the above ssh conf file, you can ssh into the builder with `sudo ssh builder@linux-builder`. + ## Example flake usage {#sec-darwin-builder-example-flake} ```nix diff --git a/doc/packages/index.md b/doc/packages/index.md index 623fbe357d54..dbfe60ca3227 100644 --- a/doc/packages/index.md +++ b/doc/packages/index.md @@ -22,6 +22,7 @@ lhapdf.section.md locales.section.md etc-files.section.md nginx.section.md +nrfutil.section.md opengl.section.md shell-helpers.section.md python-tree-sitter.section.md diff --git a/doc/packages/linux.section.md b/doc/packages/linux.section.md index 8551c77d940d..9722b22fd2f5 100644 --- a/doc/packages/linux.section.md +++ b/doc/packages/linux.section.md @@ -5,7 +5,7 @@ The Nix expressions to build the Linux kernel are in [`pkgs/os-specific/linux/ke The function [`pkgs.buildLinux`](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/generic.nix) builds a kernel with [common configuration values](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/common-config.nix). This is the preferred option unless you have a very specific use case. Most kernels packaged in Nixpkgs are built that way, and it will also generate kernels suitable for NixOS. -[`pkgs.linuxManualConfig`](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/manual-config.nix) requires a complete configuration to be passed. +[`pkgs.linuxManualConfig`](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/build.nix) requires a complete configuration to be passed. It has fewer additional features than `pkgs.buildLinux`, which provides common configuration values and exposes the `features` attribute, as explained below. Both functions have an argument `kernelPatches` which should be a list of `{name, patch, extraConfig}` attribute sets, where `name` is the name of the patch (which is included in the kernel’s `meta.description` attribute), `patch` is the patch itself (possibly compressed), and `extraConfig` (optional) is a string specifying extra options to be concatenated to the kernel configuration file (`.config`). @@ -75,7 +75,7 @@ pkgs.linuxPackages_custom { ::: -Additional attributes can be used with `linuxManualConfig` for further customisation instead of `linuxPackages_custom`. You're encouraged to read [the `pkgs.linuxManualConfig` source code](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/manual-config.nix) to understand how to use them. +Additional attributes can be used with `linuxManualConfig` for further customisation instead of `linuxPackages_custom`. You're encouraged to read [the `pkgs.linuxManualConfig` source code](https://github.com/NixOS/nixpkgs/blob/d77bda728d5041c1294a68fb25c79e2d161f62b9/pkgs/os-specific/linux/kernel/build.nix) to understand how to use them. To edit the `.config` file for Linux X.Y from within Nix, proceed as follows: diff --git a/doc/packages/nrfutil.section.md b/doc/packages/nrfutil.section.md new file mode 100644 index 000000000000..5767b0e0b946 --- /dev/null +++ b/doc/packages/nrfutil.section.md @@ -0,0 +1,13 @@ +# nrfutil {#sec-nrfutil} + +nrfutil can be built with its installables as following: + +```nix +(nrfutil.withExtensions [ + "nrfutil-completion" + "nrfutil-device" + "nrfutil-trace" +]) +``` + +Keep in mind that all installables might not be available for every supported platform. diff --git a/doc/redirects.json b/doc/redirects.json index bb9f1188f88a..2570eec68018 100644 --- a/doc/redirects.json +++ b/doc/redirects.json @@ -58,9 +58,8 @@ ], "cuda-updating-redistributables": [ "index.html#cuda-updating-redistributables", - "index.html#updating-cuda-redistributables" - ], - "cuda-updating-cutensor": [ + "index.html#updating-cuda-redistributables", + "index.html#updating-the-cuda-toolkit", "index.html#cuda-updating-cutensor", "index.html#updating-cutensor" ], @@ -72,10 +71,6 @@ "index.html#cuda-updating-the-cuda-package-set", "index.html#updating-the-cuda-package-set" ], - "cuda-updating-the-cuda-toolkit": [ - "index.html#cuda-updating-the-cuda-toolkit", - "index.html#updating-the-cuda-toolkit" - ], "cuda-user-guide": [ "index.html#cuda-user-guide" ], @@ -124,6 +119,48 @@ "inkscape-plugins": [ "index.html#inkscape-plugins" ], + "libcxxhardeningextensive": [ + "index.html#libcxxhardeningextensive" + ], + "libcxxhardeningfast": [ + "index.html#libcxxhardeningfast" + ], + "julec-hook": [ + "index.html#julec-hook" + ], + "julec-hook-example-code-snippet": [ + "index.html#julec-hook-example-code-snippet" + ], + "julec-hook-variable-dontusejulecbuild": [ + "index.html#julec-hook-variable-dontusejulecbuild" + ], + "julec-hook-variable-dontusejuleccheck": [ + "index.html#julec-hook-variable-dontusejuleccheck" + ], + "julec-hook-variable-dontusejulecinstall": [ + "index.html#julec-hook-variable-dontusejulecinstall" + ], + "julec-hook-variable-jule-out-dir": [ + "index.html#julec-hook-variable-jule-out-dir" + ], + "julec-hook-variable-jule-out-name": [ + "index.html#julec-hook-variable-jule-out-name" + ], + "julec-hook-variable-jule-src-dir": [ + "index.html#julec-hook-variable-jule-src-dir" + ], + "julec-hook-variable-jule-test-dir": [ + "index.html#julec-hook-variable-jule-test-dir" + ], + "julec-hook-variable-jule-test-out-dir": [ + "index.html#julec-hook-variable-jule-test-out-dir" + ], + "julec-hook-variable-jule-test-out-name": [ + "index.html#julec-hook-variable-jule-test-out-name" + ], + "julec-hook-variables": [ + "index.html#julec-hook-variables" + ], "major-ghc-deprecation": [ "index.html#major-ghc-deprecation" ], @@ -216,6 +253,9 @@ "sec-building-packages-with-llvm-using-clang-stdenv": [ "index.html#sec-building-packages-with-llvm-using-clang-stdenv" ], + "sec-darwin-availability-checks": [ + "index.html#sec-darwin-availability-checks" + ], "sec-darwin-libcxx-deployment-targets": [ "index.html#sec-darwin-libcxx-deployment-targets" ], @@ -322,6 +362,9 @@ "sec-nixpkgs-release-25.05-notable-changes": [ "release-notes.html#sec-nixpkgs-release-25.05-notable-changes" ], + "sec-nrfutil": [ + "index.html#sec-nrfutil" + ], "sec-overlays-install": [ "index.html#sec-overlays-install" ], @@ -355,6 +398,24 @@ "sec-pkg-overrideDerivation": [ "index.html#sec-pkg-overrideDerivation" ], + "sec-platform-breakdown": [ + "index.html#sec-platform-breakdown" + ], + "sec-platform-tier1": [ + "index.html#sec-platform-tier1" + ], + "sec-platform-tier2": [ + "index.html#sec-platform-tier2" + ], + "sec-platform-tier3": [ + "index.html#sec-platform-tier3" + ], + "sec-platform-tier4-7": [ + "index.html#sec-platform-tier4-7" + ], + "sec-platform-tiers": [ + "index.html#sec-platform-tiers" + ], "sec-lib-makeOverridable": [ "index.html#sec-lib-makeOverridable" ], @@ -1190,7 +1251,8 @@ "index.html#sec-purity-in-nixpkgs" ], "sec-hardening-in-nixpkgs": [ - "index.html#sec-hardening-in-nixpkgs" + "index.html#sec-hardening-in-nixpkgs", + "index.html#pie" ], "sec-hardening-flags-enabled-by-default": [ "index.html#sec-hardening-flags-enabled-by-default" @@ -1225,9 +1287,6 @@ "sec-hardening-flags-disabled-by-default": [ "index.html#sec-hardening-flags-disabled-by-default" ], - "pie": [ - "index.html#pie" - ], "shadowstack": [ "index.html#shadowstack" ], @@ -2366,6 +2425,9 @@ "cmake-build-dir": [ "index.html#cmake-build-dir" ], + "cmake-build-type": [ + "index.html#cmake-build-type" + ], "dont-use-cmake-configure": [ "index.html#dont-use-cmake-configure" ], @@ -3765,6 +3827,9 @@ "buildpythonpackage-parameters": [ "index.html#buildpythonpackage-parameters" ], + "overriding-python-build-helpers": [ + "index.html#overriding-python-build-helpers" + ], "overriding-python-packages": [ "index.html#overriding-python-packages" ], diff --git a/doc/release-notes/rl-2511.section.md b/doc/release-notes/rl-2511.section.md index 1d469c87dc7d..98d9f0826060 100644 --- a/doc/release-notes/rl-2511.section.md +++ b/doc/release-notes/rl-2511.section.md @@ -12,6 +12,18 @@ - The default GHC version has been updated from 9.8 to 9.10. `haskellPackages` correspondingly uses Stackage LTS 24 (instead of LTS 23) as a baseline. +- **This release of Nixpkgs requires macOS Sonoma 14.0 or newer, as announced in the 25.05 release notes.** + The default SDK is now 14.4, but the minimum version is 14.0. + cc-wrapper will enforce that availability annotations are used or an appropriate deployment target is set. + See the Darwin platform notes for details. + +- **We expect to drop support for `x86_64-darwin` by Nixpkgs 26.11,** in light of Apple’s announcement that macOS 26 will be the final version to support Intel Macs. + When support is fully removed, we will no longer build packages for the platform or guarantee that it can build at all. + This may happen in stages, depending on our available build and maintenance resources and decisions made by projects we rely on. + + By the time of 26.11’s release, Homebrew will offer only limited [Tier 3](https://docs.brew.sh/Support-Tiers#tier-3) support for the platform, but MacPorts will likely continue to support it for a long time. + We also recommend users consider installing NixOS, which should continue to run on essentially all Intel Macs, especially after Apple stops security support for macOS 26 in 2028. + - Darwin has switched to using the system libc++. This was done for improved compatibility and to avoid ODR violations. If a newer C++ library feature is not available on the default deployment target, you will need to increase the deployment target. See the Darwin platform documentation for more details. @@ -30,6 +42,11 @@ - Everything related to `bower` was removed, as it is deprecated and not used by anything in nixpkgs. +- `reaction` has been updated to version 2, which includes some breaking changes. + For more information, [check the release article](https://blog.ppom.me/en-reaction-v2). + +- `mealie` has been updated to 3.0.2: This update introduces breaking changes in some API endpoints (see the [release changelog](https://github.com/mealie-recipes/mealie/releases/tag/v3.0.0)). + - The `offrss` package was removed due to lack of upstream maintenance since 2012. It's recommended for users to migrate to another RSS reader - `installShellFiles`: Allow installManPage to take a piped input, add the `--name` flag for renaming the file when installed. Can also append `--` to opt-out of all subsequent parsing. @@ -38,10 +55,16 @@ - LLVM 12, 13, 14, 15, 16, and 17 have been removed, as they have reached end‐of‐life upstream and are no longer supported. +- The `vlock` output from kbd has been removed. Instead a new package `kbdVlock` has been introduced. Use this package now instead of the output. + - GHCJS 8.10, exposed via `haskell.compiler.ghcjs` and `haskell.compiler.ghcjs810`, has been removed. Downstream users should migrate their projects to the new JavaScript backend of GHC proper which can be used via `pkgsCross.ghcjs` from Nixpkgs. Haskell packaging code, like `haskellPackages.mkDerivation`, `ghcWithPackages` and `hoogleWithPackages`, also no longer supports GHCJS. - GHC 8.6, 8.10, 9.0, 9.2, and their package sets have been removed. +- The `haskellPackages.mkDerivation` builder now converts packages' cabal files to Unix line endings before `patchPhase`. This behavior can be disabled using `dontConvertCabalFileToUnix`. + +- `webkitgtk_4_0` has been removed because it depends on an unmaintained version of security-critical libsoup library (`libsoup_2`) and the support will be [dropped upstream soon](https://webkitgtk.org/2025/10/07/webkitgtk-soup2-deprecation.html). + - Support for bootstrapping native GHC compilers on 32‐bit ARM and little‐endian 64‐bit PowerPC has been dropped. The latter was probably broken anyway. If there is interest in restoring support for these architectures, it should be possible to cross‐compile a bootstrap GHC binary. @@ -59,6 +82,9 @@ - `base16-builder` node package has been removed due to lack of upstream maintenance. +- The default glibc ELF ABI for the powerpc64-linux platform has been changed from ELFv2 back to ELFv1, due to the latter having less remaining issues when bootstrapping & building Nixpkgs packages on hardware. + If glibc ELFv2 is desired, use a fuller target triplet like `powerpc64-unknown-linux-gnuabielfv2` or the provided `ppc64-elfv2` platform example. + - `python3Packages.bjoern` has been removed, as the upstream is unmaintained and it depends on a 14-year-old version of http-parser with numerous vulnerabilities. - `buildGoModule` removes the compatibility layer of `CGO_ENABLED` not specified via `env`. @@ -90,10 +116,16 @@ - `forgejo` main program has been renamed to `bin/forgejo` from the previous `bin/gitea`. +- the "pie" hardening flag has been removed. compilers are expected to enable PIE by default, as has been common practice since 2016 outside of nixpkgs. If a package needs "pie" disabled pass `-no-pie` in `CFLAGS`. It is unlikely this will be necessary in many cases; due to the prevalance of default PIE toolchains most packages incompatible with PIE already pass no-pie. + +- `wayclip` now uses the `ext-data-control-v1` Wayland protocol instead of `wlr-data-control-unstable-v1`. + - `cudaPackages.cudatoolkit-legacy-runfile` has been removed. - `conduwuit` was removed due to upstream ceasing development and deleting their repository. For existing data, a migration to `matrix-conduit`, `matrix-continuwuity` or `matrix-tuwunel` may be possible. +- `asciidoctor-with-extension` had its `asciidoctor-mathematical` extension removed, because it fails to build, and it is not maintained properly. + - The `ghcInfo` and `controlPhases` functions have been removed from `haskell.lib.compose` and `haskell.lib`. They were unused and would return incorrect results. - Instead of using `controlPhases`, the `doCheck` attribute of derivations can be accessed which is more accurate. `doBenchmark` can't be introspected at the moment. @@ -121,6 +153,8 @@ - Zig 0.12 has been removed. +- `services.forgejo.dump.age` now defaults to `4w`, which deletes dumps older than 4 weeks. This new behaviour could result in older backups being deleted. + - `ansible-later` has been removed because it was discontinued by the author. - `k3s` airgap images passthru attributes have changed: @@ -134,8 +168,12 @@ - `meilisearch_1_11` has been removed, as it is no longer supported. +- `budgie-desktop` has been updated [10.9.3](https://github.com/BuddiesOfBudgie/budgie-desktop/releases/tag/v10.9.3), this changes `XDG_CURRENT_DESKTOP` from `Budgie:GNOME` to `Budgie`. + - Greetd and its original greeters (`tuigreet`, `gtkgreet`, `qtgreet`, `regreet`, `wlgreet`) were moved from `greetd` namespace to top level (`greetd.tuigreet` -> `tuigreet`, `greetd.greetd` -> `greetd`, etc). The original attrs are available for compatibility as passthrus of `greetd`, but will emit a warning. They will be removed in future releases. +- `carla` no longer support `gtk2` override. + - The `archipelago-minecraft` package was removed, as upstream no longer provides support for the Minecraft APWorld. - `pcp` has been removed because the upstream repo was archived and it hasn't been updated since 2021. @@ -168,6 +206,8 @@ - `proton-caller` has been removed due to lack of upstream maintenance. +- `android-udev-rules` has been removed, as it is effectively superseded by built-in uaccess rules in systemd. + - `lima` package now only includes the guest agent for the host's architecture by default. If your guest VM's architecture differs from your Lima host's, you'll need to enable the `lima-additional-guestagents` package by setting `withAdditionalGuestAgents = true` when overriding lima with this input. - `mongodb-6_0` was removed as it is end of life as of 2025-07-31. @@ -188,12 +228,15 @@ - `sail-riscv` 0.8 follows [upstream](https://github.com/riscv/sail-riscv/blob/7cc4620eb1a57bfe04832baccdcf5727e9459bd4/doc/ChangeLog.md) and provides only a single binary, `sail_riscv_sim`. +- `moar` has been updated from `1.33.0` to `2.0.0`, and renamed to `moor` following an upstream decision. See the [release notes](https://github.com/walles/moor/releases/tag/v2.0.0) for more. + - `podofo` has been updated from `0.9.8` to `1.0.0`. These releases are by nature very incompatible due to major API changes. The legacy versions can be found under `podofo_0_10` and `podofo_0_9`. Changelog: https://github.com/podofo/podofo/blob/1.0.0/CHANGELOG.md, API-Migration-Guide: https://github.com/podofo/podofo/blob/1.0.0/API-MIGRATION.md. -- NetBox was updated to `>= 4.3.0`. Have a look at the breaking changes - of the [4.3 release](https://github.com/netbox-community/netbox/releases/tag/v4.2.0), - make the required changes to your database, if needed, then upgrade by setting `services.netbox.package = pkgs.netbox_4_3;` in your configuration. +- NetBox was updated to `>= 4.4.0`. Have a look at the breaking changes + of the [4.3 release](https://github.com/netbox-community/netbox/releases/tag/v4.3.0) + and the [4.4 release](https://github.com/netbox-community/netbox/releases/tag/v4.4.0), + make the required changes to your database, if needed, then upgrade by setting `services.netbox.package = pkgs.netbox_4_4;` in your configuration. - `privatebin` has been updated to `2.0.0`. This release changes configuration defaults including switching the template and removing legacy features. See the [v2.0.0 changelog entry](https://github.com/PrivateBin/PrivateBin/releases/tag/2.0.0) for details on how to upgrade. @@ -207,6 +250,8 @@ - [private-gpt](https://github.com/zylon-ai/private-gpt) service has been removed by lack of maintenance upstream. +- `rabbitmq-server` has been updated from 4.0.9 to 4.1.4. The 4.1.0 release includes breaking changes. For more information read the [changelog of 4.1.0](https://github.com/rabbitmq/rabbitmq-server/releases/tag/v4.1.0) + - `lxde` scope has been removed, and its packages have been moved the top-level. - `pulsemeeter` has been updated to `2.0.0`. The configuration file from older versions has to be deleted. For more information and instructions see the [v2.0.0 changelog entry](https://github.com/theRealCarneiro/pulsemeeter/releases/tag/v2.0.0). @@ -217,6 +262,8 @@ - The main binary of `tomlq` has been renamed from `tomlq` to `tq`. +- `opensoldat` binaries and user configuration directory names have been prefixed by 'open', becoming opensoldat and opensoldatserver. Configuration will be moved automatically before launch when possible. + - `emacs-macport` has been moved to a fork of Mitsuharu Yamamoto's patched source code starting with Emacs v30 as the original project seems to be currently dormant. All older versions of this package have been dropped. This introduces some backwards‐incompatible changes; see the NEWS for details. NEWS can be viewed from Emacs by typing `C-h n`, or by clicking `Help->Emacs News` from the menu bar. @@ -228,6 +275,14 @@ - `nodePackages.rimraf` has been removed, as it is a Javascript library, and packages that want to use it should depend directly on it instead. +- `mariadb` now defaults to `mariadb_114` instead of `mariadb_1011`, meaning the default version was upgraded from 10.11.x to 11.4.x. See the [upgrade notes](https://mariadb.com/kb/en/upgrading-from-mariadb-10-11-to-mariadb-11-4/) for potential issues. + +- `qt5.full` and `qt6.full` aliases have been removed. Their use has always been discouraged, and downstream projects should use `qtN.env` with the right set of packages. + +- `python3Packages.duckduckgo-search` has been updated to v9+ and therefore has been renamed to ddgs. + Use `python3Packages.ddgs` instead. + See [release note for v9.0.0](https://github.com/deedy5/ddgs/releases/tag/v9.0.0) + ## Other Notable Changes {#sec-nixpkgs-release-25.11-notable-changes} @@ -237,17 +292,29 @@ - Added `gitConfig` and `gitConfigFile` option to the nixpkgs `config`, to allow for setting a default `gitConfigFile` for all `fetchgit` invocations. +- Added `npmRegistryOverrides` and `npmRegistryOverridesString` option to the nixpkgs `config`, to allow for setting a default `npmRegistryOverridesString` for all `fetchNpmDeps` invocations. + - The `dockerTools.streamLayeredImage` builder now uses a better algorithm for generating layered docker images, such that much more sharing is possible when the number of store paths exceeds the layer limit. It gives each of the largest store paths its own layer and adds dependencies to those layers when they aren't used elsewhere. - The systemd initrd will now respect `x-systemd.wants` and `x-systemd.requires` for reliably unlocking multi-disk bcachefs volumes. +- `neovim`: Added support for the `vim.o.exrc` option, the `VIMINIT` environment variable, and sourcing of `sysinit.vim`. + + See the neovim help page [`:help startup`](https://neovim.io/doc/user/starting.html#startup) for more information, as well as [the nixpkgs neovim wrapper documentation](#neovim-custom-configuration). + +- `cloudflare-ddns`: Added package cloudflare-ddns. + +- `clickhouse`: Added `serverConfig`, `usersConfig` configuration options accepting Nix attribute sets. Also added `extraServerConfig` and `extraUsersConfig` options accepting plain text (expecting XML configuration). + - [`homebox` 0.20.0](https://github.com/sysadminsmedia/homebox/releases/tag/v0.20.0) changed how assets are stored and hashed. It is recommended to back up your database before this update. In particular, `--storage-data` was replaced with `--storage-conn-string` and `--storage-prefix-path`. If your configuration set `HBOX_STORAGE_DATA` manually, you must migrate it to `HBOX_STORAGE_CONN_STRING` and `HBOX_STORAGE_PREFIX_PATH`. - GIMP now defaults to version 3. Use `gimp2` for the old version. - `installShellCompletion`: now supports Nushell completion files -- New hardening flags, `strictflexarrays1` and `strictflexarrays3` were made available, corresponding to the gcc/clang options `-fstrict-flex-arrays=1` and `-fstrict-flex-arrays=3` respectively. +- `idris2` supports being instantiated with a package environment with `idris.withPackages (p: [ ])` + +- New hardening flags `strictflexarrays1`, `strictflexarrays3`, `glibcxxassertions`, `libcxxhardeningfast` and `libcxxhardeningextensive` were made available. - `gramps` has been updated to 6.0.0 Upstream recommends [backing up your Family Trees](https://gramps-project.org/wiki/index.php/Gramps_6.0_Wiki_Manual_-_Manage_Family_Trees#Backing_up_a_Family_Tree) before upgrading. @@ -256,6 +323,8 @@ - `forgejo-runner`: The upgrade to version 11 brings a license change from MIT to GPLv3-or-later. +- `waydroid-nftables`: New variant of `waydroid` that supports nftables instead of iptables. + - `lisp-modules` were brought in sync with the [June 2025 Quicklisp release](http://blog.quicklisp.org/2025/07/june-2025-quicklisp-dist-now-available.html). - `ffmpeg_8`, `ffmpeg_8-headless`, and `ffmpeg_8-full` have been added. The default version of FFmpeg remains ffmpeg_7 for now, though this may change before release. @@ -263,7 +332,12 @@ - `searx` was updated to use `envsubst` instead of `sed` for parsing secrets from environment variables. If your previous configuration included a secret reference like `server.secret_key = "@SEARX_SECRET_KEY@"`, you must migrate to the new envsubst syntax: `server.secret_key = "$SEARX_SECRET_KEY"`. -- A new hardening flag, `glibcxxassertions` was made available, corresponding to the glibc `_GLIBCXX_ASSERTIONS` option. +- `jellyfin` was updated to `10.11.x`, which includes heavy backend changes. + Make sure to backup your data and configuration directories + and read the [Jellyfin 10.11.0 release announcement](https://jellyfin.org/posts/jellyfin-release-10.11.0/). + **Important:** make sure you're running Jellyfin version `10.10.7` before upgrading, + and beware that the migration may take several hours depending on your library size and state. + The process must not be interrupted. - `versionCheckHook`: Packages that previously relied solely on `pname` to locate the program used to version check, but have a differing `meta.mainProgram` entry, might now fail. @@ -281,6 +355,8 @@ - `nix-prefetch-git`: Added a `--no-add-path` argument to disable adding the path to the store; this is useful when working with a [read-only store](https://nix.dev/manual/nix/2.28/command-ref/new-cli/nix3-help-stores#store-experimental-local-overlay-store-read-only). +- `fetchNpmDeps`: Add `npmRegistryOverridesString` argument to pass NPM registry overrides to the fetcher. + - `sftpman` has been updated to version 2, a rewrite in Rust which is mostly backward compatible but does include some changes to the CLI. For more information, [check the project's README](https://github.com/spantaleev/sftpman-rs#is-sftpman-v2-compatible-with-sftpman-v1). @@ -290,39 +366,55 @@ - `emacs` now disables the GC mark trace buffer by default. This improves GC performance by 5%, but can make GC issues harder to debug. This is configurable with `withGcMarkTrace`. +- Passing `stdenv` to `buildPythonPackage` or `buildPythonApplication` has been deprecated and will trigger an error in a future release. + Instead, you should _override_ the python build helper, e.g., `(buildPythonPackage.override { stdenv = customStdenv; })`. + See [](#overriding-python-build-helpers). + - `buildPythonPackage` and `buildPythonApplication` now default to `nix-update-script` as their default `updateScript`. This should improve automated updates, since nix-update is better maintained than the in-tree update script and has more robust fetcher support. +- `plasma6`: Fixed the `ksycoca` cache not being re-built when `$XDG_CACHE_HOME` is set to something that isn't `$HOME/.cache`. + ## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib} -- `mealie` has been updated to 3.0.2: This update introduces breaking changes in some API endpoints (see the [release changelog](https://github.com/mealie-recipes/mealie/releases/tag/v3.0.0)). - ### Breaking changes {#sec-nixpkgs-release-25.11-lib-breaking} -- `reaction` has been updated to version 2, which includes some breaking changes. - For more information, [check the release article](https://blog.ppom.me/en-reaction-v2). +- `lib.literalExample` has been removed, use `lib.literalExpression` instead, or use `lib.literalMD` for a non-Nix description. + +- `lib.replaceChars` has been removed, it was a deprecated alias of `lib.replaceStrings`. + +- `lib.readPathsFromFile` has been removed, use a list instead - `lib.mapAttrsFlatten` has been removed, following its deprecation in NixOS 24.11. Use `lib.attrsets.mapAttrsToList` instead. +- `lib.strings.isCoercibleToString` has been in favor of either `lib.strings.isStringLike` or `lib.strings.isConvertibleWithToString`. Only use the latter if it needs to return true for null, numbers, booleans, or a list of those. + +- `lib.types.string` has been removed. See [this pull request](https://github.com/NixOS/nixpkgs/pull/66346) for better alternative types like `lib.types.str`. + +- `lib.modules.defaultPriority` has been removed, please use `lib.modules.defaultOverridePriority` instead. + - `lib.attrsets.cartesianProductOfSets` has been removed, following its deprecation in NixOS 24.11. Use `lib.attrsets.cartesianProduct` instead. +- `lib.sources.pathType`, `lib.sources.pathIsDirectory` and `lib.sources.pathIsRegularFile` have been replaced by `lib.filesystem.pathType`, `lib.filesystem.pathIsDirectory` and `lib.filesystem.pathIsRegularFile` respectively. + - `lib.attrsets.zip` has been removed, following its deprecation in 2013. Use `lib.attrsets.zipAttrsWith` instead. - `lib.attrsets.zipWithNames` has been removed, following its deprecation in 2009. Use `lib.attrsets.zipAttrsWithNames` instead. - `lib.options.mkPackageOptionMD` has been removed, following its deprecation in NixOS 24.11. Use `lib.options.mkPackageOption` instead. +- `haskell.lib.addOptparseApplicativeCompletionScripts` has been removed, use `haskellPackages.generateOptparseApplicativeCompletions` instead. + - The `buildPythonPackage` and `buildPythonApplication` functions now require an explicit `format` attribute. Previously the default format used setuptools and called `setup.py` from the source tree, which is deprecated. The modern alternative is to configure `pyproject = true` with `build-system = [ setuptools ]`. -- `boot.enableContainers` is only turned on when a declarative NixOS container is defined in `containers`. - If you use the `nixos-container` tool for imperative container management, set `boot.enableContainers = true;` explicitly. - ### Deprecations {#sec-nixpkgs-release-25.11-lib-deprecations} +- `lib.options.mkAliasOptionModuleMD` is now obsolete; use the identical [`lib.options.mkAliasOptionModule`] instead. + - `types.either` silently accepted mismatching types when used in `freeformType`. Module maintainers should fix the used type In most cases wrapping `either` with `attrsOf` should be sufficient. @@ -331,10 +423,13 @@ - `number` - `numbers.*` +- `lib.cli.toGNUCommandLine` and `lib.cli.toGNUCommandLineShell` have been deprecated in favor of `lib.cli.toCommandLine`, `lib.cli.toCommandLineShell`, `lib.cli.toCommandLineGNU` and `lib.cli.toCommandLineShellGNU`. + ### Additions and Improvements {#sec-nixpkgs-release-25.11-lib-additions-improvements} -- `neovim`: Added support for the `vim.o.exrc` option, the `VIMINIT` environment variable, and sourcing of `sysinit.vim`. +- `lib.cli.toCommandLine`, `lib.cli.toCommandLineShell`, `lib.cli.toCommandLineGNU` and `lib.cli.toCommandLineShellGNU` have been added to address multiple issues in `lib.cli.toGNUCommandLine` and `lib.cli.toGNUCommandLineShell`. - See the neovim help page [`:help startup`](https://neovim.io/doc/user/starting.html#startup) for more information, as well as [the nixpkgs neovim wrapper documentation](#neovim-custom-configuration). +- `ugrep`: Added `wrapWithFilterUtils` package flag for optionally wrapping `ugrep+` and `ug+` with filter utilities for grepping other file types. + +- `ugrep`: Added `createGrepReplacementLinks` package flag for optionally creating drop-in replacement symlinks for `gnugrep`. -- `cloudflare-ddns`: Added package cloudflare-ddns. diff --git a/doc/stdenv/platform-notes.chapter.md b/doc/stdenv/platform-notes.chapter.md index 06662bbc76fa..99d7cf33fa48 100644 --- a/doc/stdenv/platform-notes.chapter.md +++ b/doc/stdenv/platform-notes.chapter.md @@ -47,6 +47,17 @@ See below for how to use a newer deployment target. For example, `std::print` depends on features that are only available on macOS 13.3 or newer. To make them available, set the deployment target to 13.3 using `darwinMinVersionHook`. +#### Package fails to build due to missing API availability checks {#sec-darwin-availability-checks} + +This is normally a bug in the package or a misconfigured deployment target. +* If it is using an API from a newer release (e.g., from macOS 26.0 while targeting macOS 14.0), it needs to use an availability check. + The code should be patched to use [`__builtin_available`](https://clang.llvm.org/docs/LanguageExtensions.html#objective-c-available). + Note that while the linked documentation is for Objective-C, it is applicable to C and C++ except that you use `__builtin_available` in place of `@available`. +* If the package intends to require the newer platform (i.e., it does not support running on older versions with reduced functionality), use `darwinMinVersionHook` to set the deployment target to the required version. + See below for how to use a newer deployment target. +* If the package actually handles this through some other mechanism (e.g., MoltenVK relies on the running platform’s MSL version), the error can be suppressed. + To suppress the error, add `-Wno-error=unguarded-availability` to `env.NIX_CFLAGS_COMPILE`. + #### Package requires a non-default SDK or fails to build due to missing frameworks or symbols {#sec-darwin-troubleshooting-using-sdks} In some cases, you may have to use a non-default SDK. @@ -106,13 +117,10 @@ The following is a list of Xcode versions, the SDK version in Nixpkgs, and the a Check your package’s documentation (platform support or installation instructions) to find which Xcode or SDK version to use. Generally, only the last SDK release for a major version is packaged. -| Xcode version | SDK version | Nixpkgs attribute | -|--------------------|--------------------|------------------------------| -| 12.0–12.5.1 | 11.3 | `apple-sdk_11` / `apple-sdk` | -| 13.0–13.4.1 | 12.3 | `apple-sdk_12` | -| 14.0–14.3.1 | 13.3 | `apple-sdk_13` | -| 15.0–15.4 | 14.4 | `apple-sdk_14` | -| 16.0 | 15.0 | `apple-sdk_15` | +| Xcode version | SDK version | Nixpkgs attribute | +|--------------------|--------------------|-------------------------------| +| 15.0–15.4 | 14.4 | `apple-sdk_14` / `apple-sdk` | +| 16.0 | 15.0 | `apple-sdk_15` | #### Darwin Default SDK versions {#sec-darwin-troubleshooting-darwin-defaults} diff --git a/doc/stdenv/stdenv.chapter.md b/doc/stdenv/stdenv.chapter.md index 24536c35b2c3..2a0b239740c0 100644 --- a/doc/stdenv/stdenv.chapter.md +++ b/doc/stdenv/stdenv.chapter.md @@ -1631,19 +1631,6 @@ The following flags are disabled by default and should be enabled with `hardenin This flag adds the `-fno-strict-aliasing` compiler option, which prevents the compiler from assuming code has been written strictly following the standard in regards to pointer aliasing and therefore performing optimizations that may be unsafe for code that has not followed these rules. -#### `pie` {#pie} - -This flag is disabled by default for normal `glibc` based NixOS package builds, but enabled by default for - - - `musl`-based package builds, except on Aarch64 and Aarch32, where there are issues. - - - Statically-linked for OpenBSD builds, where it appears to be required to get a working binary. - -Adds the `-fPIE` compiler and `-pie` linker options. Position Independent Executables are needed to take advantage of Address Space Layout Randomization, supported by modern kernel versions. While ASLR can already be enforced for data areas in the stack and heap (brk and mmap), the code areas must be compiled as position-independent. Shared libraries already do this with the `pic` flag, so they gain ASLR automatically, but binary .text regions need to be build with `pie` to gain ASLR. When this happens, ROP attacks are much harder since there are no static locations to bounce off of during a memory corruption attack. - -Static libraries need to be compiled with `-fPIE` so that executables can link them in with the `-pie` linker option. -If the libraries lack `-fPIE`, you will get the error `recompile with -fPIE`. - #### `strictflexarrays1` {#strictflexarrays1} This flag adds the `-fstrict-flex-arrays=1` compiler option, which reduces the cases the compiler treats as "flexible arrays" to those declared with length `[1]`, `[0]` or (the correct) `[]`. This increases the coverage of fortify checks, because such arrays declared as the trailing element of a structure can normally not have their intended length determined by the compiler. @@ -1688,6 +1675,18 @@ Adds the `-D_GLIBCXX_ASSERTIONS` compiler flag. This flag only has an effect on These checks may have an impact on performance in some cases. +#### `libcxxhardeningfast` {#libcxxhardeningfast} + +Adds the `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST` compiler flag. This flag only has an effect on libc++ targets, and when defined, enables a set of assertions that prevent undefined behavior caused by violating preconditions of the standard library. libc++ provides several hardening modes, and this "fast" mode contains a set of security-critical checks that can be done with relatively little overhead in constant time. + +Disabling `libcxxhardeningfast` implies disablement of checks from `libcxxhardeningextensive`. + +#### `libcxxhardeningextensive` {#libcxxhardeningextensive} + +Adds the `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE` compiler flag. This flag only has an effect on libc++ targets, and when defined, enables a set of assertions that prevent undefined behavior caused by violating preconditions of the standard library. libc++ provides several hardening modes, and this "extensive" mode adds checks for undefined behavior that incur relatively little overhead but aren’t security-critical. The additional rigour impacts performance more than fast mode: benchmarking is recommended to determine if it is acceptable for a particular application. + +Enabling this flag implies enablement of checks from `libcxxhardeningfast`. Disabling this flag does not imply disablement of checks from `libcxxhardeningfast`. + #### `pacret` {#pacret} This flag adds the `-mbranch-protection=pac-ret` compiler option on aarch64-linux targets. This uses ARM v8.3's Pointer Authentication feature to sign function return pointers before adding them to the stack. The pointer's authenticity is then validated before returning to its destination. This dramatically increases the difficulty of ROP exploitation techniques. diff --git a/doc/tests/manpage-urls.nix b/doc/tests/manpage-urls.nix index 913aebe4ebe8..74778c7f9847 100644 --- a/doc/tests/manpage-urls.nix +++ b/doc/tests/manpage-urls.nix @@ -2,12 +2,12 @@ { lib, runCommand, - invalidateFetcherByDrvHash, + testers, cacert, python3, }: -invalidateFetcherByDrvHash ( +testers.invalidateFetcherByDrvHash ( { name ? "manual_check-manpage-urls", script ? ./manpage-urls.py, diff --git a/doc/using/platform-support.chapter.md b/doc/using/platform-support.chapter.md index 3f91b3d5d980..d5a985c90d35 100644 --- a/doc/using/platform-support.chapter.md +++ b/doc/using/platform-support.chapter.md @@ -1,18 +1,49 @@ # Platform Support {#chap-platform-support} -Packages receive varying degrees of support, both in terms of maintainer attention and available computation resources for continuous integration (CI). +Packages receive varying degrees of support, both in terms of maintainer attention and available computation resources for continuous integration (CI). We have 7 defined tiers denoting how well supported each platform is. -Below is the list of the best supported platforms: +## Tiers {#sec-platform-tiers} -- `x86_64-linux`: Highest level of support. -- `aarch64-linux`: Well supported, with most packages building successfully in CI. -- `aarch64-darwin`: Receives better support than `x86_64-darwin`. -- `x86_64-darwin`: Receives some support. +### Tier 1 {#sec-platform-tier1} -There are many other platforms with varying levels of support. -The provisional platform list in [Appendix A] of [RFC046], while not up to date, can be used as guidance. +[Tier 1](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-1) platforms receive the highest level of support where problems can block updates, platform-specific patches are freely applied, and most packages are expected to work. -A more formal definition of the platform support tiers is provided in [RFC046], but has not been fully implemented yet. +### Tier 2 {#sec-platform-tier2} -[RFC046]: https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md -[Appendix A]: https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#appendix-a-non-normative-description-of-platforms-in-november-2019 +[Tier 2](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-2) platforms are expected to remain functional with updates, receive platform-specific patches as needed, and have many packages built by Hydra with full ofBorg support. + +### Tier 3 {#sec-platform-tier3} + +[Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) platforms may receive non-intrusive platform-specific fixes, have native bootstrap tools available with cross-build toolchains in binary cache, but updates might break builds on these platforms. + +### Tier 4-7 {#sec-platform-tier4-7} + +Platform Tiers [4 through 7](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-4) indicate varying levels of minimal support going from receiving only limited fixes to platforms with no support, but a path to support. + +## Breakdown {#sec-platform-breakdown} + +| Triple | Support Tier | Channel Blockers | Hydra Support | Ofborg Support | Bootstrap Tarballs | Cross Compiling Support | +| ------------------------------------- | ------------ | ---------------- | ------------- | -------------- | ------------------ | ----------------------- | +| `x86_64-unknown-linux-gnu` | [Tier 1](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-1) | Many | ✔️ | ✔️ | ✔️ | ✔️ | +| `aarch64-unknown-linux-gnu` | [Tier 2](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-2) | Some | ✔️ | ✔️ | ✔️ | ✔️ | +| `x86_64-unknown-linux-musl` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | Limited | ❌ | ✔️ | ✔️ | +| `aarch64-unknown-linux-musl` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | Limited | ❌ | ✔️ | ✔️ | +| `x86_64-unknown-unknown-freebsd` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `arm64-apple-darwin` | [Tier 2](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-2) | Some | ✔️ | ✔️ | ✔️ | ❌\* | +| `x86_64-apple-darwin` | [Tier 2](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-2) | Some | ✔️ | ✔️ | ✔️ | ❌\* | +| `i686-unknown-linux-gnu` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | Limited | ❌ | ✔️ | ✔️ | +| `riscv32-unknown-linux-gnu` | [Tier 4](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-4) | None | ❌ | ❌ | ❌ | ✔️ | +| `riscv64-unknown-linux-gnu` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `loongarch64-unknown-linux-gnu` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `armv6l-unknown-linux-gnueabihf` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `armv6l-unknown-linux-musleabihf` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `armv7l-unknown-linux-gnueabihf` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `armv5tel-unknown-linux-gnueabi` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `mips64el-unknown-linux-gnuabi64` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `mips64el-unknown-linux-gnuabin32` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `mipsel-unknown-linux-gnu` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `powerpc64-unknown-linux-gnuabielfv2` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `powerpc64le-unknown-linux-gnu` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | +| `s390x-unknown-linux-gnu` | [Tier 3](https://github.com/NixOS/rfcs/blob/master/rfcs/0046-platform-support-tiers.md#tier-3) | None | ❌ | ❌ | ✔️ | ✔️ | + +\* - Cross compiling is only supported on Darwin hosts. diff --git a/lib/cli.nix b/lib/cli.nix index 590ba691d386..f0ebeb76c4c2 100644 --- a/lib/cli.nix +++ b/lib/cli.nix @@ -1,6 +1,6 @@ { lib }: -rec { +{ /** Automatically convert an attribute set to command-line options. @@ -20,6 +20,7 @@ rec { : The attributes to transform into arguments. # Examples + :::{.example} ## `lib.cli.toGNUCommandLineShell` usage example @@ -38,7 +39,10 @@ rec { ::: */ - toGNUCommandLineShell = options: attrs: lib.escapeShellArgs (toGNUCommandLine options attrs); + toGNUCommandLineShell = + lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2511) + "lib.cli.toGNUCommandLineShell is deprecated, please use lib.cli.toCommandLineShell or lib.cli.toCommandLineShellGNU instead." + (options: attrs: lib.escapeShellArgs (lib.cli.toGNUCommandLine options attrs)); /** Automatically convert an attribute set to a list of command-line options. @@ -55,7 +59,7 @@ rec { : The attributes to transform into arguments. - # Options + ## Options `mkOptionName` @@ -85,6 +89,7 @@ rec { This is useful if the command requires equals, for example, `-c=5`. # Examples + :::{.example} ## `lib.cli.toGNUCommandLine` usage example @@ -111,38 +116,224 @@ rec { ::: */ toGNUCommandLine = + lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2511) + "lib.cli.toGNUCommandLine is deprecated, please use lib.cli.toCommandLine or lib.cli.toCommandLineShellGNU instead." + ( + { + mkOptionName ? k: if builtins.stringLength k == 1 then "-${k}" else "--${k}", + + mkBool ? k: v: lib.optional v (mkOptionName k), + + mkList ? k: v: lib.concatMap (mkOption k) v, + + mkOption ? + k: v: + if v == null then + [ ] + else if optionValueSeparator == null then + [ + (mkOptionName k) + (lib.generators.mkValueStringDefault { } v) + ] + else + [ "${mkOptionName k}${optionValueSeparator}${lib.generators.mkValueStringDefault { } v}" ], + + optionValueSeparator ? null, + }: + options: + let + render = + k: v: + if builtins.isBool v then + mkBool k v + else if builtins.isList v then + mkList k v + else + mkOption k v; + + in + builtins.concatLists (lib.mapAttrsToList render options) + ); + + /** + Converts the given attributes into a single shell-escaped command-line string. + Similar to `toCommandLineGNU`, but returns a single escaped string instead of an array of arguments. + For further reference see: [`lib.cli.toCommandLineGNU`](#function-library-lib.cli.toCommandLineGNU) + */ + toCommandLineShellGNU = + options: attrs: lib.escapeShellArgs (lib.cli.toCommandLineGNU options attrs); + + /** + Converts an attribute set into a list of GNU-style command line options. + + `toCommandLineGNU` returns a list of string arguments. + + # Inputs + + `options` + + : Options, see below. + + `attrs` + + : The attributes to transform into arguments. + + ## Options + + `isLong` + + : A function that determines whether an option is long or short. + + `explicitBool` + + : Whether or not boolean option arguments should be formatted explicitly. + + `formatArg` + + : A function that turns the option argument into a string. + + # Examples + + :::{.example} + ## `lib.cli.toCommandLineGNU` usage example + + ```nix + lib.cli.toCommandLineGNU {} { + v = true; + verbose = [true true false null]; + i = ".bak"; + testsuite = ["unit" "integration"]; + e = ["s/a/b/" "s/b/c/"]; + n = false; + data = builtins.toJSON {id = 0;}; + } + => [ + "--data={\"id\":0}" + "-es/a/b/" + "-es/b/c/" + "-i.bak" + "--testsuite=unit" + "--testsuite=integration" + "-v" + "--verbose" + "--verbose" + ] + ``` + + ::: + */ + toCommandLineGNU = { - mkOptionName ? k: if builtins.stringLength k == 1 then "-${k}" else "--${k}", - - mkBool ? k: v: lib.optional v (mkOptionName k), - - mkList ? k: v: lib.concatMap (mkOption k) v, - - mkOption ? - k: v: - if v == null then - [ ] - else if optionValueSeparator == null then - [ - (mkOptionName k) - (lib.generators.mkValueStringDefault { } v) - ] - else - [ "${mkOptionName k}${optionValueSeparator}${lib.generators.mkValueStringDefault { } v}" ], - - optionValueSeparator ? null, + isLong ? optionName: builtins.stringLength optionName > 1, + explicitBool ? false, + formatArg ? lib.generators.mkValueStringDefault { }, }: - options: let - render = - k: v: - if builtins.isBool v then - mkBool k v - else if builtins.isList v then - mkList k v - else - mkOption k v; - + optionFormat = optionName: { + option = if isLong optionName then "--${optionName}" else "-${optionName}"; + sep = if isLong optionName then "=" else ""; + inherit explicitBool formatArg; + }; in - builtins.concatLists (lib.mapAttrsToList render options); + lib.cli.toCommandLine optionFormat; + + /** + Converts the given attributes into a single shell-escaped command-line string. + Similar to `toCommandLine`, but returns a single escaped string instead of an array of arguments. + For further reference see: [`lib.cli.toCommandLine`](#function-library-lib.cli.toCommandLine) + */ + toCommandLineShell = + optionFormat: attrs: lib.escapeShellArgs (lib.cli.toCommandLine optionFormat attrs); + + /** + Converts an attribute set into a list of command line options. + + `toCommandLine` returns a list of string arguments. + + # Inputs + + `optionFormat` + + : The option format that describes how options and their arguments should be formatted. + + `attrs` + + : The attributes to transform into arguments. + + # Examples + :::{.example} + ## `lib.cli.toCommandLine` usage example + + ```nix + let + optionFormat = optionName: { + option = "-${optionName}"; + sep = "="; + explicitBool = true; + }; + in lib.cli.toCommandLine optionFormat { + v = true; + verbose = [true true false null]; + i = ".bak"; + testsuite = ["unit" "integration"]; + e = ["s/a/b/" "s/b/c/"]; + n = false; + data = builtins.toJSON {id = 0;}; + } + => [ + "-data={\"id\":0}" + "-e=s/a/b/" + "-e=s/b/c/" + "-i=.bak" + "-n=false" + "-testsuite=unit" + "-testsuite=integration" + "-v=true" + "-verbose=true" + "-verbose=true" + "-verbose=false" + ] + ``` + + ::: + */ + toCommandLine = + optionFormat: attrs: + let + handlePair = + k: v: + if k == "" then + lib.throw "lib.cli.toCommandLine only accepts non-empty option names." + else if builtins.isList v then + builtins.concatMap (handleOption k) v + else + handleOption k v; + + handleOption = k: renderOption (optionFormat k) k; + + renderOption = + { + option, + sep, + explicitBool, + formatArg ? lib.generators.mkValueStringDefault { }, + }: + k: v: + if v == null || (!explicitBool && v == false) then + [ ] + else if !explicitBool && v == true then + [ option ] + else + let + arg = formatArg v; + in + if sep != null then + [ "${option}${sep}${arg}" ] + else + [ + option + arg + ]; + in + builtins.concatLists (lib.mapAttrsToList handlePair attrs); } diff --git a/lib/customisation.nix b/lib/customisation.nix index 5fb39fdfe1d2..6159ce8ea27a 100644 --- a/lib/customisation.nix +++ b/lib/customisation.nix @@ -22,7 +22,6 @@ let filterAttrs optionalString flip - pathIsDirectory head pipe isDerivation @@ -305,9 +304,10 @@ rec { arg: let loc = unsafeGetAttrPos arg fargs; + loc' = if loc != null then loc.file + ":" + toString loc.line else ""; in "Function called without required argument \"${arg}\" at " - + "${loc.file}:${toString loc.line}${prettySuggestions (getSuggestions arg)}"; + + "${loc'}${prettySuggestions (getSuggestions arg)}"; # Only show the error for the first missing argument error = errorForArg (head (attrNames missingArgs)); @@ -763,11 +763,26 @@ rec { # Inputs `extendMkDerivation`-specific configurations - : `constructDrv`: Base build helper, the `mkDerivation`-like build helper to extend. - : `excludeDrvArgNames`: Argument names not to pass from the input fixed-point arguments to `constructDrv`. Note: It doesn't apply to the updating arguments returned by `extendDrvArgs`. - : `extendDrvArgs` : An extension (overlay) of the argument set, like the one taken by [overrideAttrs](#sec-pkg-overrideAttrs) but applied before passing to `constructDrv`. - : `inheritFunctionArgs`: Whether to inherit `__functionArgs` from the base build helper (default to `true`). - : `transformDrv`: Function to apply to the result derivation (default to `lib.id`). + : `constructDrv` (required) + : Base build helper, the `mkDerivation`-like build helper to extend. + + `excludeDrvArgNames` (default to `[ ]`) + : Argument names not to pass from the input fixed-point arguments to `constructDrv`. + It doesn't apply to the updating arguments returned by `extendDrvArgs`. + + `excludeFunctionArgNames` (default to `[ ]`) + : `__functionArgs` attribute names to remove from the result build helper. + `excludeFunctionArgNames` is useful for argument deprecation while avoiding ellipses. + + `extendDrvArgs` (required) + : An extension (overlay) of the argument set, like the one taken by [overrideAttrs](#sec-pkg-overrideAttrs) but applied before passing to `constructDrv`. + + `inheritFunctionArgs` (default to `true`) + : Whether to inherit `__functionArgs` from the base build helper. + Set `inheritFunctionArgs` to `false` when `extendDrvArgs`'s `args` set pattern does not contain an ellipsis. + + `transformDrv` (default to `lib.id`) + : Function to apply to the result derivation. # Type @@ -776,6 +791,7 @@ rec { { constructDrv :: ((FixedPointArgs | AttrSet) -> a) excludeDrvArgNames :: [ String ], + excludeFunctionArgNames :: [ String ] extendDrvArgs :: (AttrSet -> AttrSet -> AttrSet) inheritFunctionArgs :: Bool, transformDrv :: a -> a, @@ -836,6 +852,7 @@ rec { { constructDrv, excludeDrvArgNames ? [ ], + excludeFunctionArgNames ? [ ], extendDrvArgs, inheritFunctionArgs ? true, transformDrv ? id, @@ -850,10 +867,12 @@ rec { ) # Add __functionArgs ( - # Inherit the __functionArgs from the base build helper - optionalAttrs inheritFunctionArgs (removeAttrs (functionArgs constructDrv) excludeDrvArgNames) - # Recover the __functionArgs from the derived build helper - // functionArgs (extendDrvArgs { }) + removeAttrs ( + # Inherit the __functionArgs from the base build helper + optionalAttrs inheritFunctionArgs (removeAttrs (functionArgs constructDrv) excludeDrvArgNames) + # Recover the __functionArgs from the derived build helper + // functionArgs (extendDrvArgs { }) + ) excludeFunctionArgNames ) // { inherit @@ -864,4 +883,139 @@ rec { transformDrv ; }; + + /** + Removes a prefix from the attribute names of a cross index. + + A cross index (short for "Cross Platform Pair Index") is a 6-field structure + organizing values by cross-compilation platform relationships. + + # Inputs + + `prefix` + : The prefix to remove from cross index attribute names + + `crossIndex` + : A cross index with prefixed names + + # Type + + ``` + renameCrossIndexFrom :: String -> AttrSet -> AttrSet + ``` + + # Examples + + :::{.example} + ## `lib.customisation.renameCrossIndexFrom` usage example + + ```nix + renameCrossIndexFrom "pkgs" { pkgsBuildBuild = ...; pkgsBuildHost = ...; ... } + => { buildBuild = ...; buildHost = ...; ... } + ``` + ::: + */ + renameCrossIndexFrom = prefix: x: { + buildBuild = x."${prefix}BuildBuild"; + buildHost = x."${prefix}BuildHost"; + buildTarget = x."${prefix}BuildTarget"; + hostHost = x."${prefix}HostHost"; + hostTarget = x."${prefix}HostTarget"; + targetTarget = x."${prefix}TargetTarget"; + }; + + /** + Adds a prefix to the attribute names of a cross index. + + A cross index (short for "Cross Platform Pair Index") is a 6-field structure + organizing values by cross-compilation platform relationships. + + # Inputs + + `prefix` + : The prefix to add to cross index attribute names + + `crossIndex` + : A cross index to be prefixed + + # Type + + ``` + renameCrossIndexTo :: String -> AttrSet -> AttrSet + ``` + + # Examples + + :::{.example} + ## `lib.customisation.renameCrossIndexTo` usage example + + ```nix + renameCrossIndexTo "self" { buildBuild = ...; buildHost = ...; ... } + => { selfBuildBuild = ...; selfBuildHost = ...; ... } + ``` + ::: + */ + renameCrossIndexTo = prefix: x: { + "${prefix}BuildBuild" = x.buildBuild; + "${prefix}BuildHost" = x.buildHost; + "${prefix}BuildTarget" = x.buildTarget; + "${prefix}HostHost" = x.hostHost; + "${prefix}HostTarget" = x.hostTarget; + "${prefix}TargetTarget" = x.targetTarget; + }; + + /** + Takes a function and applies it pointwise to each field of a cross index. + + A cross index (short for "Cross Platform Pair Index") is a 6-field structure + organizing values by cross-compilation platform relationships. + + # Inputs + + `f` + : Function to apply to each cross index value + + `crossIndex` + : A cross index to transform + + # Type + + ``` + mapCrossIndex :: (a -> b) -> AttrSet -> AttrSet + ``` + + # Examples + + :::{.example} + ## `lib.customisation.mapCrossIndex` usage example + + ```nix + mapCrossIndex (x: x * 10) { buildBuild = 1; buildHost = 2; ... } + => { buildBuild = 10; buildHost = 20; ... } + ``` + + ```nix + # Extract a package from package sets + mapCrossIndex (pkgs: pkgs.hello) crossIndexedPackageSets + ``` + ::: + */ + mapCrossIndex = + f: + { + buildBuild, + buildHost, + buildTarget, + hostHost, + hostTarget, + targetTarget, + }: + { + buildBuild = f buildBuild; + buildHost = f buildHost; + buildTarget = f buildTarget; + hostHost = f hostHost; + hostTarget = f hostTarget; + targetTarget = f targetTarget; + }; } diff --git a/lib/default.nix b/lib/default.nix index cbb58e302504..e10332ca58dd 100644 --- a/lib/default.nix +++ b/lib/default.nix @@ -63,7 +63,7 @@ let customisation = callLibs ./customisation.nix; derivations = callLibs ./derivations.nix; maintainers = import ../maintainers/maintainer-list.nix; - teams = callLibs ../maintainers/team-list.nix; + teams = callLibs ../maintainers/computed-team-list.nix; meta = callLibs ./meta.nix; versions = callLibs ./versions.nix; @@ -344,7 +344,6 @@ let escapeRegex escapeURL escapeXML - replaceChars lowerChars upperChars toLower @@ -377,7 +376,6 @@ let fixedWidthNumber toInt toIntBase10 - readPathsFromFile fileContents ; inherit (self.stringsWithDeps) @@ -399,6 +397,9 @@ let makeScopeWithSplicing makeScopeWithSplicing' extendMkDerivation + renameCrossIndexFrom + renameCrossIndexTo + mapCrossIndex ; inherit (self.derivations) lazyDerivation optionalDrvAttr warnOnInstantiate; inherit (self.generators) mkLuaInline; @@ -495,7 +496,6 @@ let optionAttrSetToDocList' scrubOptionValue literalExpression - literalExample showOption showOptionWithDefLocs showFiles diff --git a/lib/fileset/default.nix b/lib/fileset/default.nix index 3c51c6d4dab4..32bc00a227b3 100644 --- a/lib/fileset/default.nix +++ b/lib/fileset/default.nix @@ -101,6 +101,7 @@ let inherit (import ./internal.nix { inherit lib; }) _coerce + _coerceResult _singleton _coerceMany _toSourceFilter @@ -1005,4 +1006,49 @@ in { submodules = recurseSubmodules; }; + + /** + The empty fileset. It can be useful as a default value or as starting accumulator for a folding operation. + + # Type + + ``` + empty :: FileSet + ``` + */ + empty = _emptyWithoutBase; + + /** + Tests whether a given value is a fileset, or can be used in place of a fileset. + + # Inputs + + `value` + + : The value to test + + # Type + + ``` + isFileset :: Any -> Bool + ``` + + # Examples + :::{.example} + ## `lib.fileset.isFileset` usage example + + ```nix + isFileset ./. + => true + + isFileset (unions [ ]) + => true + + isFileset 1 + => false + ``` + + ::: + */ + isFileset = x: (_coerceResult "" x).success; } diff --git a/lib/fileset/internal.nix b/lib/fileset/internal.nix index 59b8408ae8d6..342b284e1f71 100644 --- a/lib/fileset/internal.nix +++ b/lib/fileset/internal.nix @@ -165,14 +165,27 @@ rec { _noEval = throw _noEvalMessage; }; - # Coerce a value to a fileset, erroring when the value cannot be coerced. - # The string gives the context for error messages. - # Type: String -> (fileset | Path) -> fileset - _coerce = + # Coerce a value to a fileset. Return a set containing the attribute `success` + # indicating whether coercing succeeded, and either `value` when `success == + # true`, or an error `message` when `success == false`. The string gives the + # context for error messages. + # + # Type: String -> (fileset | Path) -> { success :: Bool, value :: fileset } ] -> { success :: Bool, message :: String } + _coerceResult = + let + ok = value: { + success = true; + inherit value; + }; + error = message: { + success = false; + inherit message; + }; + in context: value: if value._type or "" == "fileset" then if value._internalVersion > _currentVersion then - throw '' + error '' ${context} is a file set created from a future version of the file set library with a different internal representation: - Internal version of the file set: ${toString value._internalVersion} - Internal version of the library: ${toString _currentVersion} @@ -184,27 +197,37 @@ rec { _currentVersion - value._internalVersion ) migrations; in - foldl' (value: migration: migration value) value migrationsToApply + ok (foldl' (value: migration: migration value) value migrationsToApply) else - value + ok value else if !isPath value then if value ? _isLibCleanSourceWith then - throw '' + error '' ${context} is a `lib.sources`-based value, but it should be a file set or a path instead. To convert a `lib.sources`-based value to a file set you can use `lib.fileset.fromSource`. Note that this only works for sources created from paths.'' else if isStringLike value then - throw '' + error '' ${context} ("${toString value}") is a string-like value, but it should be a file set or a path instead. Paths represented as strings are not supported by `lib.fileset`, use `lib.sources` or derivations instead.'' else - throw ''${context} is of type ${typeOf value}, but it should be a file set or a path instead.'' + error ''${context} is of type ${typeOf value}, but it should be a file set or a path instead.'' else if !pathExists value then - throw '' + error '' ${context} (${toString value}) is a path that does not exist. To create a file set from a path that may not exist, use `lib.fileset.maybeMissing`.'' else - _singleton value; + ok (_singleton value); + + # Coerce a value to a fileset, erroring when the value cannot be coerced. + # The string gives the context for error messages. + # Type: String -> (fileset | Path) -> fileset + _coerce = + context: value: + let + result = _coerceResult context value; + in + if result.success then result.value else throw result.message; # Coerce many values to filesets, erroring when any value cannot be coerced, # or if the filesystem root of the values doesn't match. diff --git a/lib/licenses.nix b/lib/licenses.nix index 09d708b570d2..c38379ed405b 100644 --- a/lib/licenses.nix +++ b/lib/licenses.nix @@ -172,6 +172,11 @@ lib.mapAttrs mkLicense ( fullName = "Baekmuk License"; }; + bitstreamCharter = { + spdxId = "Bitstream-Charter"; + fullName = "Bitstream Charter Font License"; + }; + bitstreamVera = { spdxId = "Bitstream-Vera"; fullName = "Bitstream Vera Font License"; @@ -615,11 +620,6 @@ lib.mapAttrs mkLicense ( fullName = "Unspecified free software license"; }; - freeimage = { - spdxId = "FreeImage"; - fullName = "FreeImage Public License v1.0"; - }; - fsl11Mit = { fullName = "Functional Source License, Version 1.1, MIT Future License"; spdxId = "FSL-1.1-MIT"; @@ -665,6 +665,11 @@ lib.mapAttrs mkLicense ( url = "https://www.gust.org.pl/projects/e-foundry/licenses/GUST-FONT-SOURCE-LICENSE.txt"; }; + gnuplot = { + spdxId = "gnuplot"; + fullName = "gnuplot License"; + }; + gpl1Only = { spdxId = "GPL-1.0-only"; fullName = "GNU General Public License v1.0 only"; @@ -791,6 +796,12 @@ lib.mapAttrs mkLicense ( free = false; }; + intel-eula = { + fullName = "Intel End User License Agreement for Developer Tools"; + url = "https://software.intel.com/sites/manageability/AMT_Implementation_and_Reference_Guide/WordDocuments/intelamtsdklicense.htm"; + free = false; + }; + interbase = { spdxId = "Interbase-1.0"; fullName = "Interbase Public License v1.0"; @@ -982,6 +993,11 @@ lib.mapAttrs mkLicense ( fullName = "CMU License"; }; + mit-enna = { + spdxId = "MIT-enna"; + fullName = "enna License"; + }; + mit-feh = { spdxId = "MIT-feh"; fullName = "feh License"; diff --git a/lib/modules.nix b/lib/modules.nix index 5fc00e2acee8..a78bd1a92488 100644 --- a/lib/modules.nix +++ b/lib/modules.nix @@ -1126,6 +1126,29 @@ let __toString = _: showOption loc; }; + # Check that a type with v2 merge has a coherent check attribute. + # Throws an error if the type uses an ad-hoc `type // { check }` override. + # Returns the last argument like `seq`, allowing usage: checkV2MergeCoherence loc type expr + checkV2MergeCoherence = + loc: type: result: + if type.check.isV2MergeCoherent or false then + result + else + throw '' + The option `${showOption loc}' has a type `${type.description}' that uses + an ad-hoc `type // { check = ...; }' override, which is incompatible with + the v2 merge mechanism. + + Please use `lib.types.addCheck` instead of `type // { check }' to add + custom validation. For example: + + lib.types.addCheck baseType (value: /* your check */) + + instead of: + + baseType // { check = value: /* your check */; } + ''; + # Merge definitions of a value of a given type. mergeDefinitions = loc: type: defs: rec { defsFinal' = @@ -1201,10 +1224,13 @@ let ( if type.merge ? v2 then let - r = type.merge.v2 { - inherit loc; - defs = defsFinal; - }; + # Check for v2 merge coherence + r = checkV2MergeCoherence loc type ( + type.merge.v2 { + inherit loc; + defs = defsFinal; + } + ); in r // { @@ -1468,11 +1494,6 @@ let mkForce = mkOverride 50; mkVMOverride = mkOverride 10; # used by ‘nixos-rebuild build-vm’ - defaultPriority = - warnIf (oldestSupportedReleaseIsAtLeast 2305) - "lib.modules.defaultPriority is deprecated, please use lib.modules.defaultOverridePriority instead." - defaultOverridePriority; - mkFixStrictness = warn "lib.mkFixStrictness has no effect and will be removed. It returns its argument unmodified, so you can just remove any calls." id; mkOrder = priority: content: { @@ -1787,11 +1808,10 @@ let }; /** - Transitional version of mkAliasOptionModule that uses MD docs. - - This function is no longer necessary and merely an alias of `mkAliasOptionModule`. + Deprecated alias of mkAliasOptionModule that uses MD docs. + This function is no longer necessary will be removed in 26.05`. */ - mkAliasOptionModuleMD = mkAliasOptionModule; + mkAliasOptionModuleMD = lib.warn "mkAliasOptionModuleMD is deprecated and will be removed in 26.05; please use mkAliasOptionModule." mkAliasOptionModule; /** mkDerivedConfig : Option a -> (a -> Definition b) -> Definition b @@ -2163,7 +2183,6 @@ private inherit defaultOrderPriority defaultOverridePriority - defaultPriority doRename evalModules evalOptionValue # for use by lib.types diff --git a/lib/options.nix b/lib/options.nix index 75f8bfa2535c..b1db6ff76e46 100644 --- a/lib/options.nix +++ b/lib/options.nix @@ -684,8 +684,6 @@ rec { inherit text; }; - literalExample = lib.warn "lib.literalExample is deprecated, use lib.literalExpression instead, or use lib.literalMD for a non-Nix description." literalExpression; - /** For use in the `defaultText` and `example` option attributes. Causes the given MD text to be inserted verbatim in the documentation, for when diff --git a/lib/sources.nix b/lib/sources.nix index 4d67ea30b62c..78335bd9f06d 100644 --- a/lib/sources.nix +++ b/lib/sources.nix @@ -509,22 +509,6 @@ let in { - - pathType = - lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305) - "lib.sources.pathType has been moved to lib.filesystem.pathType." - lib.filesystem.pathType; - - pathIsDirectory = - lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305) - "lib.sources.pathIsDirectory has been moved to lib.filesystem.pathIsDirectory." - lib.filesystem.pathIsDirectory; - - pathIsRegularFile = - lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305) - "lib.sources.pathIsRegularFile has been moved to lib.filesystem.pathIsRegularFile." - lib.filesystem.pathIsRegularFile; - inherit pathIsGitRepo commitIdFromGitRepo diff --git a/lib/strings.nix b/lib/strings.nix index 77d7bb939eb5..5d3183bcef06 100644 --- a/lib/strings.nix +++ b/lib/strings.nix @@ -1467,9 +1467,6 @@ rec { [ "\"" "'" "<" ">" "&" ] [ """ "'" "<" ">" "&" ]; - # warning added 12-12-2022 - replaceChars = lib.warn "lib.replaceChars is a deprecated alias of lib.replaceStrings." builtins.replaceStrings; - # Case conversion utilities. lowerChars = stringToCharacters "abcdefghijklmnopqrstuvwxyz"; upperChars = stringToCharacters "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; @@ -2578,30 +2575,6 @@ rec { in lib.warnIf (!precise) "Imprecise conversion from float to string ${result}" result; - /** - Check whether a value `val` can be coerced to a string. - - :::{.warning} - Soft-deprecated function. While the original implementation is available as - `isConvertibleWithToString`, consider using `isStringLike` instead, if suitable. - ::: - - # Inputs - - `val` - : 1\. Function argument - - # Type - - ``` - isCoercibleToString :: a -> bool - ``` - */ - isCoercibleToString = - lib.warnIf (lib.oldestSupportedReleaseIsAtLeast 2305) - "lib.strings.isCoercibleToString is deprecated in favor of either isStringLike or isConvertibleWithToString. Only use the latter if it needs to return true for null, numbers, booleans and list of similarly coercibles." - isConvertibleWithToString; - /** Check whether a list or other value `x` can be passed to toString. @@ -2842,60 +2815,6 @@ rec { else parsedInput; - /** - Read a list of paths from `file`, relative to the `rootPath`. - Lines beginning with `#` are treated as comments and ignored. - Whitespace is significant. - - :::{.warning} - This function is deprecated and should be avoided. - ::: - - :::{.note} - This function is not performant and should be avoided. - ::: - - # Inputs - - `rootPath` - : 1\. Function argument - - `file` - : 2\. Function argument - - # Type - - ``` - readPathsFromFile :: string -> string -> [string] - ``` - - # Examples - :::{.example} - ## `lib.strings.readPathsFromFile` usage example - - ```nix - readPathsFromFile /prefix - ./pkgs/development/libraries/qt-5/5.4/qtbase/series - => [ "/prefix/dlopen-resolv.patch" "/prefix/tzdir.patch" - "/prefix/dlopen-libXcursor.patch" "/prefix/dlopen-openssl.patch" - "/prefix/dlopen-dbus.patch" "/prefix/xdg-config-dirs.patch" - "/prefix/nix-profiles-library-paths.patch" - "/prefix/compose-search-path.patch" ] - ``` - - ::: - */ - readPathsFromFile = lib.warn "lib.readPathsFromFile is deprecated, use a list instead." ( - rootPath: file: - let - lines = lib.splitString "\n" (readFile file); - removeComments = lib.filter (line: line != "" && !(lib.hasPrefix "#" line)); - relativePaths = removeComments lines; - absolutePaths = map (path: rootPath + "/${path}") relativePaths; - in - absolutePaths - ); - /** Read the contents of a file removing the trailing \n diff --git a/lib/systems/default.nix b/lib/systems/default.nix index 7e78ceb4827a..cd1448d811fa 100644 --- a/lib/systems/default.nix +++ b/lib/systems/default.nix @@ -360,8 +360,8 @@ let null; # The canonical name for this attribute is darwinSdkVersion, but some # platforms define the old name "sdkVer". - darwinSdkVersion = final.sdkVer or "11.3"; - darwinMinVersion = final.darwinSdkVersion; + darwinSdkVersion = final.sdkVer or "14.4"; + darwinMinVersion = "14.0"; darwinMinVersionVariable = if final.isMacOS then "MACOSX_DEPLOYMENT_TARGET" @@ -491,6 +491,13 @@ let } .${cpu.name} or cpu.name; vendor_ = final.rust.platform.vendor; + abi_ = + # We're very explicit about the POWER ELF ABI w/ glibc in our parsing, while Rust is not. + # TODO: Somehow ensure that Rust actually *uses* the correct ABI, and not just a libc-based default. + if (lib.strings.hasPrefix "powerpc" cpu.name) && (lib.strings.hasPrefix "gnuabielfv" abi.name) then + "gnu" + else + abi.name; in # TODO: deprecate args.rustc in favour of args.rust after 23.05 is EOL. args.rust.rustcTarget or args.rustc.config or ( @@ -501,7 +508,7 @@ let if final.isWasi then "${cpu_}-wasip1" else - "${cpu_}-${vendor_}-${kernel.name}${optionalString (abi.name != "unknown") "-${abi.name}"}" + "${cpu_}-${vendor_}-${kernel.name}${optionalString (abi.name != "unknown") "-${abi_}"}" ); # The name of the rust target if it is standard, or the json file diff --git a/lib/systems/examples.nix b/lib/systems/examples.nix index cdd28b1ddde1..d05c05910523 100644 --- a/lib/systems/examples.nix +++ b/lib/systems/examples.nix @@ -23,7 +23,6 @@ rec { ppc64-elfv1 = { config = "powerpc64-unknown-linux-gnuabielfv1"; - rust.rustcTarget = "powerpc64-unknown-linux-gnu"; }; ppc64-elfv2 = { config = "powerpc64-unknown-linux-gnuabielfv2"; @@ -303,15 +302,6 @@ rec { libc = "newlib"; }; - # - # Redox - # - - x86_64-unknown-redox = { - config = "x86_64-unknown-redox"; - libc = "relibc"; - }; - # # Darwin # diff --git a/lib/systems/parse.nix b/lib/systems/parse.nix index bbb0fa9d5582..c76aa592fc28 100644 --- a/lib/systems/parse.nix +++ b/lib/systems/parse.nix @@ -919,9 +919,9 @@ rec { else if isLinux parsed || isWindows parsed then if isAarch32 parsed then if versionAtLeast (parsed.cpu.version or "0") "6" then abis.gnueabihf else abis.gnueabi - # Default ppc64 BE to ELFv2 + # Default ppc64 BE to ELFv1 else if isPower64 parsed && isBigEndian parsed then - abis.gnuabielfv2 + abis.gnuabielfv1 else abis.gnu else diff --git a/lib/tests/misc.nix b/lib/tests/misc.nix index 59fbb1ccd63b..2ec670262649 100644 --- a/lib/tests/misc.nix +++ b/lib/tests/misc.nix @@ -3106,6 +3106,86 @@ runTests { expected = "-X PUT --data '{\"id\":0}' --retry 3 --url https://example.com/foo --url https://example.com/bar --verbose"; }; + testToCommandLine = { + expr = + let + optionFormat = optionName: { + option = "-${optionName}"; + sep = "="; + explicitBool = true; + }; + in + cli.toCommandLine optionFormat { + v = true; + verbose = [ + true + true + false + null + ]; + i = ".bak"; + testsuite = [ + "unit" + "integration" + ]; + e = [ + "s/a/b/" + "s/b/c/" + ]; + n = false; + data = builtins.toJSON { id = 0; }; + }; + + expected = [ + "-data={\"id\":0}" + "-e=s/a/b/" + "-e=s/b/c/" + "-i=.bak" + "-n=false" + "-testsuite=unit" + "-testsuite=integration" + "-v=true" + "-verbose=true" + "-verbose=true" + "-verbose=false" + ]; + }; + + testToCommandLineGNU = { + expr = cli.toCommandLineGNU { } { + v = true; + verbose = [ + true + true + false + null + ]; + i = ".bak"; + testsuite = [ + "unit" + "integration" + ]; + e = [ + "s/a/b/" + "s/b/c/" + ]; + n = false; + data = builtins.toJSON { id = 0; }; + }; + + expected = [ + "--data={\"id\":0}" + "-es/a/b/" + "-es/b/c/" + "-i.bak" + "--testsuite=unit" + "--testsuite=integration" + "-v" + "--verbose" + "--verbose" + ]; + }; + testSanitizeDerivationNameLeadingDots = testSanitizeDerivationName { name = "..foo"; expected = "foo"; @@ -4661,4 +4741,82 @@ runTests { expected = "/non-existent/this/does/not/exist/for/real/please-dont-mess-with-your-local-fs/default.nix"; }; + # Tests for cross index utilities + + testRenameCrossIndexFrom = { + expr = lib.renameCrossIndexFrom "pkgs" { + pkgsBuildBuild = "dummy-build-build"; + pkgsBuildHost = "dummy-build-host"; + pkgsBuildTarget = "dummy-build-target"; + pkgsHostHost = "dummy-host-host"; + pkgsHostTarget = "dummy-host-target"; + pkgsTargetTarget = "dummy-target-target"; + }; + expected = { + buildBuild = "dummy-build-build"; + buildHost = "dummy-build-host"; + buildTarget = "dummy-build-target"; + hostHost = "dummy-host-host"; + hostTarget = "dummy-host-target"; + targetTarget = "dummy-target-target"; + }; + }; + + testRenameCrossIndexTo = { + expr = lib.renameCrossIndexTo "self" { + buildBuild = "dummy-build-build"; + buildHost = "dummy-build-host"; + buildTarget = "dummy-build-target"; + hostHost = "dummy-host-host"; + hostTarget = "dummy-host-target"; + targetTarget = "dummy-target-target"; + }; + expected = { + selfBuildBuild = "dummy-build-build"; + selfBuildHost = "dummy-build-host"; + selfBuildTarget = "dummy-build-target"; + selfHostHost = "dummy-host-host"; + selfHostTarget = "dummy-host-target"; + selfTargetTarget = "dummy-target-target"; + }; + }; + + testMapCrossIndex = { + expr = lib.mapCrossIndex (x: x * 10) { + buildBuild = 1; + buildHost = 2; + buildTarget = 3; + hostHost = 4; + hostTarget = 5; + targetTarget = 6; + }; + expected = { + buildBuild = 10; + buildHost = 20; + buildTarget = 30; + hostHost = 40; + hostTarget = 50; + targetTarget = 60; + }; + }; + + testMapCrossIndexString = { + expr = lib.mapCrossIndex (x: "prefix-${x}") { + buildBuild = "bb"; + buildHost = "bh"; + buildTarget = "bt"; + hostHost = "hh"; + hostTarget = "ht"; + targetTarget = "tt"; + }; + expected = { + buildBuild = "prefix-bb"; + buildHost = "prefix-bh"; + buildTarget = "prefix-bt"; + hostHost = "prefix-hh"; + hostTarget = "prefix-ht"; + targetTarget = "prefix-tt"; + }; + }; + } diff --git a/lib/tests/modules.sh b/lib/tests/modules.sh index 5cd781752317..505c1c5a5fe4 100755 --- a/lib/tests/modules.sh +++ b/lib/tests/modules.sh @@ -223,6 +223,26 @@ checkConfigError 'A definition for option .* is not of type .path in the Nix sto checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: ".*/store/.links"' config.pathInStore.bad4 ./types.nix checkConfigError 'A definition for option .* is not of type .path in the Nix store.. Definition values:\n\s*- In .*: "/foo/bar"' config.pathInStore.bad5 ./types.nix +# types.externalPath +checkConfigOutput '".*/foo/bar"' config.externalPath.ok1 ./types.nix +checkConfigOutput '".*/"' config.externalPath.ok2 ./types.nix +checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad1 ./types.nix +checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad2 ./types.nix +checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad3 ./types.nix +checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad4 ./types.nix +checkConfigError 'A definition for option .* is not of type .absolute path not in the Nix store.' config.externalPath.bad5 ./types.nix + +# types.fileset +checkConfigOutput '^0$' config.filesetCardinal.ok1 ./fileset.nix +checkConfigOutput '^1$' config.filesetCardinal.ok2 ./fileset.nix +checkConfigOutput '^1$' config.filesetCardinal.ok3 ./fileset.nix +checkConfigOutput '^1$' config.filesetCardinal.ok4 ./fileset.nix +checkConfigOutput '^0$' config.filesetCardinal.ok5 ./fileset.nix +checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err1 ./fileset.nix +checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err2 ./fileset.nix +checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err3 ./fileset.nix +checkConfigError 'A definition for option .* is not of type .fileset.. Definition values:\n.*' config.filesetCardinal.err4 ./fileset.nix + # Check boolean option. checkConfigOutput '^false$' config.enable ./declare-enable.nix checkConfigError 'The option .* does not exist. Definition values:\n\s*- In .*: true' config.enable ./define-enable.nix @@ -806,6 +826,25 @@ checkConfigError 'A definition for option .* is not of type .signed integer.*' c checkConfigOutput '^true$' config.v2checkedPass ./add-check.nix checkConfigError 'A definition for option .* is not of type .attribute set of signed integer.*' config.v2checkedFail ./add-check.nix +# v2 merge check coherence +# Tests checkV2MergeCoherence call in modules.nix (mergeDefinitions for lazyAttrsOf) +checkConfigError 'ad-hoc.*override.*incompatible' config.adhocFail.foo ./v2-check-coherence.nix +# Tests checkV2MergeCoherence call in modules.nix (mergeDefinitions for lazyAttrsOf) +checkConfigError 'ad-hoc.*override.*incompatible' config.adhocOuterFail.bar ./v2-check-coherence.nix +# Tests checkV2MergeCoherence call in types.nix (either t1) +checkConfigError 'ad-hoc.*override.*incompatible' config.eitherLeftFail ./v2-check-coherence.nix +# Tests checkV2MergeCoherence call in types.nix (either t2) +checkConfigError 'ad-hoc.*override.*incompatible' config.eitherRightFail ./v2-check-coherence.nix +# Tests checkV2MergeCoherence call in types.nix (coercedTo coercedType) +checkConfigError 'ad-hoc.*override.*incompatible' config.coercedFromFail.bar ./v2-check-coherence.nix +# Tests checkV2MergeCoherence call in types.nix (coercedTo finalType) +checkConfigError 'ad-hoc.*override.*incompatible' config.coercedToFail.foo ./v2-check-coherence.nix +# Tests checkV2MergeCoherence call in types.nix (addCheck elemType) +checkConfigError 'ad-hoc.*override.*incompatible' config.addCheckNested.foo ./v2-check-coherence.nix +checkConfigError 'Please use.*lib.types.addCheck.*instead' config.adhocFail.foo ./v2-check-coherence.nix +checkConfigError 'A definition for option .* is not of type .*' config.addCheckFail.bar.baz ./v2-check-coherence.nix +checkConfigOutput '^true$' config.result ./v2-check-coherence.nix + cat <`. +`maintainer-list.nix` in a separate commit titled `maintainers: add `. ### Losing maintainer status @@ -158,13 +158,17 @@ If the team lists no specific membership policy, feel free to merge changes to t > [!IMPORTANT] > If a team says it is a closed group, do not merge additions to the team without an approval by at least one existing member. -A corresponding GitHub team can be created by any org member. +#### Synced GitHub teams + +As an alternative to tracking team members in `team-list.nix`, a corresponding GitHub team can be created by any org member and its members subsequently managed directly on GitHub. When creating the team it should be created with the `nixpkgs-maintainers` team as parent. Once approved, the team will have the right privileges to be pinged and requested for review in Nixpkgs. > [!TIP] > The team name should be as short as possible; because it is nested under the maintainers group, no -maintainers suffix is needed. +After the first [weekly team sync](../.github/workflows/team-sync.yml) with the new team, it's then also possible to link it to the entry in `team-list.nix` by setting its `github` field to the GitHub team name. + # Maintainer scripts Various utility scripts, which are mainly useful for nixpkgs maintainers, are available under `./scripts/`. diff --git a/maintainers/computed-team-list.nix b/maintainers/computed-team-list.nix new file mode 100644 index 000000000000..7ee37f4283e3 --- /dev/null +++ b/maintainers/computed-team-list.nix @@ -0,0 +1,59 @@ +# Extends ./team-list.nix with synced GitHub information from ./github-teams.json +{ lib }: +let + githubTeams = lib.importJSON ./github-teams.json; + teams = import ./team-list.nix { inherit lib; }; + + # A fast maintainer id lookup table + maintainersById = lib.pipe lib.maintainers [ + lib.attrValues + (lib.groupBy (attrs: toString attrs.githubId)) + (lib.mapAttrs (_: lib.head)) + ]; + + maintainerSetToList = + githubTeam: + lib.mapAttrsToList ( + login: id: + maintainersById.${toString id} + or (throw "lib.teams: No maintainer entry for GitHub user @${login} who's part of the @NixOS/${githubTeam} team") + ); + +in +# TODO: Consider automatically exposing all GitHub teams under `lib.teams`, +# so that no manual PRs are necessary to add such teams anymore +lib.mapAttrs ( + name: attrs: + if attrs ? github then + let + githubTeam = + githubTeams.${attrs.github} + or (throw "lib.teams.${name}: Corresponding GitHub team ${attrs.github} not known yet, make sure to create it and wait for the regular team sync"); + in + # TODO: Consider specifying `githubId` in team-list.nix and inferring `github` from it (or even dropping it) + # This would make renames easier because no additional place needs to keep track of them. + # Though in a future where all Nixpkgs GitHub teams are automatically exposed under `lib.teams`, + # this would also not be an issue anymore. + assert lib.assertMsg (!attrs ? githubId) + "lib.teams.${name}: Both `githubId` and `github` is set, but the former is synced from the latter"; + assert lib.assertMsg (!attrs ? shortName) + "lib.teams.${name}: Both `shortName` and `github` is set, but the former is synced from the latter"; + assert lib.assertMsg ( + !attrs ? scope + ) "lib.teams.${name}: Both `scope` and `github` is set, but the former is synced from the latter"; + assert lib.assertMsg ( + !attrs ? members + ) "lib.teams.${name}: Both `members` and `github` is set, but the former is synced from the latter"; + attrs + // { + githubId = githubTeam.id; + shortName = githubTeam.name; + scope = githubTeam.description; + members = + maintainerSetToList attrs.github githubTeam.maintainers + ++ maintainerSetToList attrs.github githubTeam.members; + githubMaintainers = maintainerSetToList attrs.github githubTeam.maintainers; + } + else + attrs +) teams diff --git a/maintainers/github-teams.json b/maintainers/github-teams.json new file mode 100644 index 000000000000..289edd306687 --- /dev/null +++ b/maintainers/github-teams.json @@ -0,0 +1,985 @@ +{ + "acme": { + "description": "Maintain ACME-related packages and modules.", + "id": 3806126, + "maintainers": {}, + "members": { + "arianvp": 628387, + "emilazy": 18535642, + "m1cr0man": 3044438 + }, + "name": "ACME" + }, + "agda": { + "description": "Maintain Agda-related packages and modules", + "id": 14416551, + "maintainers": { + "alexarice": 17208985, + "ncfavier": 4323933, + "turion": 303489 + }, + "members": { + "phijor": 10487782 + }, + "name": "agda" + }, + "android": { + "description": "Maintain Android-related tooling in nixpkgs", + "id": 11821955, + "maintainers": { + "RossComputerGuy": 19699320, + "numinit": 369111 + }, + "members": { + "JohnRTitor": 50095635, + "adrian-gierakowski": 330177, + "hadilq": 5190539 + }, + "name": "Android" + }, + "bazel": { + "description": "Maintenance of https://bazel.build/ and related packages", + "id": 5468470, + "maintainers": { + "Profpatsch": 3153638 + }, + "members": { + "aherrmann": 732652, + "avdv": 3471749, + "ethercrow": 222467, + "groodt": 343415, + "kalbasit": 87115, + "mboes": 51356, + "uri-canva": 33242106 + }, + "name": "Bazel" + }, + "beam": { + "description": "Maintain BEAM-related packages and modules.", + "id": 4502493, + "maintainers": { + "happysalada": 5317234 + }, + "members": { + "Br1ght0ne": 12615679, + "DianaOlympos": 15774340, + "adamcstephens": 2071575, + "ankhers": 750786, + "gleber": 33185, + "minijackson": 1200507, + "savtrip": 42227195, + "yurrriq": 1866448 + }, + "name": "Beam" + }, + "bootstrapping": { + "description": "coordinates efforts towards bootstrappable builds (see https://bootstrappable.org/)", + "id": 9141350, + "maintainers": { + "zeuner": 2545850 + }, + "members": { + "philiptaron": 43863 + }, + "name": "bootstrapping" + }, + "categorization": { + "description": "Maintain the categorization system in Nixpkgs, per RFC 0146. This team has authority over all categorization issues in Nixpkgs. Matrix: https://matrix.to/#/%23nixpkgs-categorization:matrix.org", + "id": 11723948, + "maintainers": { + "7c6f434c": 1891350, + "Aleksanaa": 42209822, + "GetPsyched": 43472218, + "Lyndeno": 13490857, + "SigmaSquadron": 174749595, + "fgaz": 8182846, + "natsukium": 25083790, + "philiptaron": 43863, + "pyrotelekinetic": 29682759, + "tomodachi94": 68489118 + }, + "members": {}, + "name": "Categorization" + }, + "channel-updaters": { + "description": "Users who can update the Nixpkgs/NixOS channels", + "id": 3475569, + "maintainers": {}, + "members": { + "nixos-channel-bot": 56695723 + }, + "name": "channel-updaters" + }, + "coq": { + "description": "Coq proof assistant and package maintainers", + "id": 7617261, + "maintainers": { + "Alizter": 8614547, + "Zimmi48": 1108325, + "vbgl": 2612464 + }, + "members": {}, + "name": "Coq" + }, + "cosmic": { + "description": "Maintain the COSMIC DE and related packages.", + "id": 12734494, + "maintainers": { + "alyssais": 2768870, + "nyabinary": 97130632 + }, + "members": { + "HeitorAugustoLN": 44377258, + "Pandapip1": 45835846, + "a-kenji": 65275785, + "ahoneybun": 4884946, + "drakon64": 6444703, + "michaelBelsanti": 62124625, + "thefossguy": 44400303 + }, + "name": "COSMIC" + }, + "crystal-lang": { + "description": "The Crystal Lang eco-system", + "id": 3806663, + "maintainers": { + "peterhoeg": 722550 + }, + "members": { + "Br1ght0ne": 12615679, + "manveru": 3507 + }, + "name": "crystal-lang" + }, + "cuda-maintainers": { + "description": "Maintain CUDA-enabled packages", + "id": 5704451, + "maintainers": { + "ConnorBaker": 3880346, + "SomeoneSerge": 9720532, + "samuela": 226872 + }, + "members": { + "GaetanLepage": 33058747, + "prusnak": 42201 + }, + "name": "cuda-maintainers" + }, + "darwin-core": { + "description": "Maintain core platform support and packages for macOS and other Apple platforms", + "id": 11265438, + "maintainers": { + "emilazy": 18535642 + }, + "members": { + "reckenrode": 7413633, + "toonn": 1486805 + }, + "name": "darwin-core" + }, + "darwin-maintainers": { + "description": "Improve Darwin-support across Nixpkgs and help maintainers without access to Darwin hardware. Apply to join through https://github.com/NixOS/nixpkgs/issues/323144 to keep the process transparent.", + "id": 2385202, + "maintainers": { + "toonn": 1486805 + }, + "members": { + "0xMRTT": 105598867, + "21CSM": 81891917, + "Aleksanaa": 42209822, + "CorbanR": 1918683, + "Emin017": 99674037, + "Et7f3": 29592775, + "FlameFlag": 57304299, + "Guanran928": 68757440, + "LnL7": 689294, + "Mastermindaxe": 33257997, + "Moraxyc": 69713071, + "Prince213": 25235514, + "Samasaur1": 30577766, + "Sciencentistguy": 4983935, + "Steven0351": 24440751, + "afh": 16507, + "azuwis": 9315, + "booxter": 90200, + "carlossless": 498906, + "cideM": 4246921, + "cidkidnix": 67574902, + "copumpkin": 2623, + "devusb": 4951663, + "domenkozar": 126339, + "donn": 12652988, + "dwt": 57199, + "emilazy": 18535642, + "ethancedwards8": 60861925, + "fiddlerwoaroof": 808745, + "frogamic": 10263813, + "gador": 1883533, + "griff": 4368, + "groodt": 343415, + "gshpychka": 23005347, + "hexagonal-sun": 222664, + "heywoodlh": 18178614, + "iedame": 60272, + "isabelroses": 71222764, + "jonhermansen": 660911, + "juliusrickert": 5007494, + "jwiegley": 8460, + "kashw2": 15855440, + "kevingriffin": 209729, + "khaneliman": 1778670, + "kloenk": 12898828, + "konradmalik": 13033392, + "kubukoz": 894884, + "lutzmor": 9321736, + "magistau": 43097806, + "maljub01": 350635, + "martinjlowm": 110860, + "matteo-pacini": 3139724, + "matthewbauer": 19036, + "mexisme": 329349, + "mikroskeem": 3490861, + "mirkolenz": 5160954, + "mstone": 412508, + "n8henrie": 1234956, + "niklaskorz": 590517, + "ofalvai": 1694986, + "pasqui23": 6931743, + "prusnak": 42201, + "pupbrained": 33522919, + "reckenrode": 7413633, + "ryand56": 22267679, + "samrose": 115821, + "sarahec": 11277967, + "shaunsingh": 71196912, + "sikmir": 688044, + "siraben": 8219659, + "siriobalmelli": 23038812, + "starcraft66": 1858154, + "stepbrobd": 81826728, + "stephank": 89950, + "stephenstubbs": 18033664, + "t-monaghan": 62273348, + "thefloweringash": 42933, + "tricktron": 16036882, + "uncenter": 47499684, + "uri-canva": 33242106, + "usertam": 22500027, + "veprbl": 245573, + "viraptor": 188063, + "wegank": 9713184, + "willcohen": 5185341, + "willjr": 5904828, + "wldhx": 15619766, + "yeongsheng-tan": 809030, + "youhaveme9": 58213083, + "yzx9": 41458459, + "zachcoyle": 908716 + }, + "name": "darwin-maintainers" + }, + "documentation-team": { + "description": "Maintain nixpkgs/NixOS documentation and tools for building it. https://nixos.org/community/teams/documentation", + "id": 6590023, + "maintainers": { + "alejandrosame": 1078000 + }, + "members": { + "hsjobeki": 50398876, + "wamirez": 24505474 + }, + "name": "Documentation Team" + }, + "dotnet": { + "description": "Maintain the .NET ecosystem in nixpkgs", + "id": 8173604, + "maintainers": { + "corngood": 3077118, + "mdarocha": 11572618 + }, + "members": { + "GGG-KILLER": 5892127, + "IvarWithoutBones": 41924494, + "JamieMagee": 1358764, + "anpin": 6060545, + "meenzen": 22305878, + "raphaelr": 121178 + }, + "name": "Dotnet" + }, + "emacs": { + "description": "", + "id": 2516946, + "maintainers": { + "jian-lin": 75130626, + "matthewbauer": 19036 + }, + "members": { + "AndersonTorres": 5954806, + "adisbladis": 63286, + "panchoh": 471059, + "ttuegel": 563054 + }, + "name": "emacs" + }, + "enlightenment": { + "description": "Maintain Enlightenment desktop environment and related packages", + "id": 5937665, + "maintainers": { + "romildo": 1217934 + }, + "members": {}, + "name": "Enlightenment" + }, + "exotic-platform-maintainers": { + "description": "", + "id": 3727378, + "maintainers": { + "Ericson2314": 1055245, + "matthewbauer": 19036 + }, + "members": { + "aaronjanse": 16829510, + "alyssais": 2768870, + "emilytrau": 13267947, + "minijackson": 1200507, + "r-burns": 52847440, + "siraben": 8219659, + "sternenseemann": 3154475 + }, + "name": "exotic-platform-maintainers" + }, + "flutter": { + "description": "Maintain Flutter and Dart-related packages and build tools", + "id": 7718198, + "maintainers": { + "RossComputerGuy": 19699320 + }, + "members": { + "FlafyDev": 44374434, + "hacker1024": 20849728, + "mkg20001": 7735145 + }, + "name": "Flutter" + }, + "freedesktop": { + "description": "Maintain Freedesktop.org packages for graphical desktop.", + "id": 3806136, + "maintainers": {}, + "members": { + "jtojnar": 705123 + }, + "name": "Freedesktop" + }, + "geospatial": { + "description": "Maintain geospatial, remote sensing and OpenStreetMap software", + "id": 7084621, + "maintainers": { + "imincik": 476346 + }, + "members": { + "autra": 1576598, + "l0b0": 168301, + "nh2": 399535, + "nialov": 47318483, + "sikmir": 688044, + "willcohen": 5185341 + }, + "name": "Geospatial" + }, + "gitlab": { + "description": "Maintain GitLab-related packages and modules", + "id": 8157777, + "maintainers": { + "leona-ya": 11006031, + "xanderio": 6298052, + "yayayayaka": 73759599 + }, + "members": { + "talyz": 63433 + }, + "name": "GitLab" + }, + "gnome": { + "description": "Maintain GNOME desktop environment and platform.", + "id": 3806133, + "maintainers": {}, + "members": { + "bobby285271": 20080233, + "dasj19": 7589338, + "hedning": 71978, + "jtojnar": 705123 + }, + "name": "GNOME" + }, + "golang": { + "description": "Maintain Golang compilers", + "id": 4020424, + "maintainers": { + "Mic92": 96200, + "kalbasit": 87115, + "zowoq": 59103226 + }, + "members": { + "katexochen": 49727155, + "mfrw": 4929861, + "qbit": 68368 + }, + "name": "golang" + }, + "haskell": { + "description": "Maintain Haskell packages and infrastructure", + "id": 4769723, + "maintainers": { + "cdepillabout": 64804, + "maralorn": 1651325, + "sternenseemann": 3154475 + }, + "members": { + "wolfgangwalther": 9132420 + }, + "name": "Haskell" + }, + "hyprland": { + "description": "Maintain Hyprland compositor and ecosystem.", + "id": 12048885, + "maintainers": { + "khaneliman": 1778670 + }, + "members": { + "JohnRTitor": 50095635, + "NotAShelf": 62766066, + "donovanglover": 2374245, + "fufexan": 36706276 + }, + "name": "hyprland" + }, + "java": { + "description": "Maintainers of the Nixpkgs Java ecosystem (JDK, JVM, Java, Gradle, Maven, Ant, and adjacent projects); frequently lingering in #jvm:nixos.org on Matrix", + "id": 11412419, + "maintainers": { + "FliegendeWurst": 12560461, + "Infinidoge": 22727114, + "chayleaf": 9590981, + "tomodachi94": 68489118 + }, + "members": { + "msgilligan": 61612 + }, + "name": "Java" + }, + "k3s": { + "description": "Maintain K3s package, NixOS module, NixOS tests, update script", + "id": 7725877, + "maintainers": { + "Mic92": 96200, + "euank": 2147649, + "marcusramberg": 5526, + "wrmilling": 6162814 + }, + "members": { + "frederictobiasc": 26125115, + "heywoodlh": 18178614, + "rorosen": 76747196 + }, + "name": "k3s" + }, + "kodi": { + "description": "Maintain Kodi related packages.", + "id": 4642467, + "maintainers": { + "aanderse": 7755101 + }, + "members": { + "cpages": 411324, + "edwtjo": 54799, + "minijackson": 1200507, + "peterhoeg": 722550, + "sephalon": 893474 + }, + "name": "kodi" + }, + "kubernetes": { + "description": "Maintain the Kubernetes package and module", + "id": 5536808, + "maintainers": { + "johanot": 998763, + "offlinehacker": 585547, + "saschagrunert": 695473, + "srhb": 219362 + }, + "members": {}, + "name": "kubernetes" + }, + "linux-kernel": { + "description": "Maintain the Linux kernel", + "id": 13371617, + "maintainers": { + "alyssais": 2768870 + }, + "members": { + "K900": 386765, + "Ma27": 6025220, + "NeQuissimus": 628342, + "TredwellGit": 61860346 + }, + "name": "Linux kernel" + }, + "lisp": { + "description": "Maintain the Lisp ecosystem", + "id": 7678368, + "maintainers": { + "7c6f434c": 1891350, + "Uthar": 15697697, + "hraban": 137852, + "lukego": 13791, + "nagy": 692274 + }, + "members": {}, + "name": "lisp" + }, + "lix-maintainers": { + "description": "Lix maintainers in nixpkgs/NixOS", + "id": 13838744, + "maintainers": { + "lf-": 6652840 + }, + "members": { + "9999years": 15312184, + "Qyriad": 1542224, + "RaitoBezarius": 314564, + "alois31": 36605164 + }, + "name": "Lix maintainers" + }, + "llvm": { + "description": "Maintain LLVM package sets and related packages", + "id": 9955829, + "maintainers": { + "RossComputerGuy": 19699320, + "alyssais": 2768870 + }, + "members": { + "Ericson2314": 1055245, + "dtzWill": 817330, + "emilazy": 18535642, + "lovek323": 265084, + "rrbutani": 7833358, + "sternenseemann": 3154475 + }, + "name": "LLVM" + }, + "loongarch64": { + "description": "Maintain LoongArch64 related packages and code", + "id": 13371619, + "maintainers": { + "Aleksanaa": 42209822 + }, + "members": { + "Cryolitia": 23723294, + "darkyzhou": 7220778, + "dramforever": 2818072, + "wegank": 9713184 + }, + "name": "loongarch64" + }, + "lua": { + "description": "Maintain the lua ecosystem", + "id": 5255750, + "maintainers": { + "teto": 886074 + }, + "members": { + "7c6f434c": 1891350, + "Shados": 338268, + "khaneliman": 1778670, + "spencerpogo": 34356756 + }, + "name": "lua" + }, + "lumina": { + "description": "Maintain lumina desktop environment and related packages", + "id": 5937661, + "maintainers": { + "romildo": 1217934 + }, + "members": {}, + "name": "Lumina" + }, + "lxc": { + "description": "LXC, LXD, Incus", + "id": 9223525, + "maintainers": { + "adamcstephens": 2071575 + }, + "members": { + "aanderse": 7755101, + "jnsgruk": 668505, + "megheaiulian": 1788114, + "mkg20001": 7735145 + }, + "name": "LXC" + }, + "lxqt": { + "description": "Maintain LXQt desktop environment and related packages", + "id": 5937679, + "maintainers": { + "romildo": 1217934 + }, + "members": {}, + "name": "LXQt" + }, + "marketing-team": { + "description": "Marketing team [leader=@djacu]", + "id": 7709512, + "maintainers": { + "djacu": 7043297, + "tomberek": 178444 + }, + "members": { + "flyfloh": 74379, + "thilobillerbeck": 7442383 + }, + "name": "Marketing Team" + }, + "mate": { + "description": "Maintainers of the MATE Desktop Environment", + "id": 5937667, + "maintainers": { + "romildo": 1217934 + }, + "members": { + "bobby285271": 20080233 + }, + "name": "MATE" + }, + "neovim": { + "description": "Maintain the vim and neovim text editors and related packages", + "id": 6748534, + "maintainers": { + "GaetanLepage": 33058747 + }, + "members": { + "PerchunPak": 68118654, + "khaneliman": 1778670, + "mrcjkb": 12857160 + }, + "name": "neovim" + }, + "nix-formatting": { + "description": "Maintain the official Nix formatter and apply it to Nixpkgs: https://nixos.org/community/teams/formatting/", + "id": 9676823, + "maintainers": { + "infinisil": 20525370, + "jfly": 277474 + }, + "members": { + "0x4A6F": 9675338, + "MattSturgeon": 5046562, + "Sereja313": 112060595, + "dasJ": 4971975, + "piegamesde": 14054505 + }, + "name": "nix-formatting" + }, + "nix-team": { + "description": "", + "id": 174820, + "maintainers": { + "tomberek": 178444 + }, + "members": { + "Ericson2314": 1055245, + "Mic92": 96200, + "edolstra": 1148549, + "xokdvium": 145775305 + }, + "name": "Nix team" + }, + "nixos-release-managers": { + "description": "Manage the current nixpkgs/NixOS release", + "id": 3620128, + "maintainers": { + "jopejoe1": 34899572, + "leona-ya": 11006031 + }, + "members": {}, + "name": "nixos-release-managers" + }, + "nixpkgs-ci": { + "description": "Maintain Nixpkgs' in-tree Continuous Integration, including GitHub Actions", + "id": 13362067, + "maintainers": { + "philiptaron": 43863, + "wolfgangwalther": 9132420 + }, + "members": { + "MattSturgeon": 5046562, + "Mic92": 96200, + "zowoq": 59103226 + }, + "name": "Nixpkgs CI" + }, + "nixpkgs-core": { + "description": "Provides leadership for and has authority over Nixpkgs.", + "id": 14317027, + "maintainers": { + "alyssais": 2768870, + "emilazy": 18535642, + "wolfgangwalther": 9132420 + }, + "members": {}, + "name": "Nixpkgs core" + }, + "nixpkgs-merge-bot": { + "description": "This team exists as a target for triggering the nixpkgs merge bot.", + "id": 13926892, + "maintainers": {}, + "members": {}, + "name": "nixpkgs-merge-bot" + }, + "node": { + "description": "Maintains Node.js runtimes and build tooling.\r\n\r\n\"JS is hecked, thanks for coming to my TED Talk\" - @lilyinstarlight", + "id": 7309872, + "maintainers": { + "lilyinstarlight": 298109, + "winterqt": 78392041 + }, + "members": {}, + "name": "Node" + }, + "ocaml": { + "description": "Maintain the OCaml compiler and package set", + "id": 7553013, + "maintainers": { + "Alizter": 8614547, + "romildo": 1217934, + "ulrikstrid": 1607770 + }, + "members": { + "redianthus": 16472988 + }, + "name": "OCaml" + }, + "pantheon": { + "description": "Maintain Pantheon desktop environment and platform", + "id": 4786995, + "maintainers": { + "davidak": 91113 + }, + "members": { + "bobby285271": 20080233 + }, + "name": "Pantheon" + }, + "php": { + "description": "Maintain PHP related packages and extensions.", + "id": 3806182, + "maintainers": {}, + "members": { + "Ma27": 6025220, + "aanderse": 7755101, + "piotrkwiecinski": 2151333, + "talyz": 63433 + }, + "name": "php" + }, + "podman": { + "description": "Maintain Podman and CRI-O related packages and modules.", + "id": 3806184, + "maintainers": {}, + "members": { + "saschagrunert": 695473, + "vdemeester": 6508 + }, + "name": "podman" + }, + "postgres": { + "description": "Maintain the PostgreSQL package and plugins along with the NixOS module.", + "id": 11455958, + "maintainers": { + "Ma27": 6025220, + "thoughtpolice": 3416, + "wolfgangwalther": 9132420 + }, + "members": {}, + "name": "postgres" + }, + "qt-kde": { + "description": "Maintain the Qt framework, KDE application suite, Plasma desktop environment and related projects", + "id": 4341481, + "maintainers": { + "ttuegel": 563054 + }, + "members": { + "FRidh": 2129135, + "K900": 386765, + "LunNova": 782440, + "NickCao": 15247171, + "SCOTT-HAMILTON": 24496705, + "SuperSandro2000": 7258858, + "bkchr": 5718007, + "ilya-fedin": 17829319, + "mjm": 1181, + "nyanloutre": 7677321, + "peterhoeg": 722550 + }, + "name": "Qt-KDE" + }, + "reproducible": { + "description": "Team that is interested in reproducible builds", + "id": 7625643, + "maintainers": { + "raboof": 131856, + "zimbatm": 3248 + }, + "members": { + "Artturin": 56650223, + "Atemu": 18599032, + "RaitoBezarius": 314564, + "davidak": 91113, + "mschwaig": 3856390 + }, + "name": "reproducible" + }, + "risc-v": { + "description": "RISC-V team", + "id": 13425811, + "maintainers": { + "0x4A6F": 9675338 + }, + "members": { + "DarkKirb": 23011243, + "dramforever": 2818072, + "fgaz": 8182846, + "jonhermansen": 660911 + }, + "name": "RISC-V" + }, + "rocm": { + "description": "Maintain ROCm and related packages", + "id": 6921873, + "maintainers": { + "mschwaig": 3856390 + }, + "members": { + "Flakebi": 6499211, + "GZGavinZhao": 74938940, + "LunNova": 782440 + }, + "name": "rocm" + }, + "rust": { + "description": "Maintain the Rust compiler toolchain and nixpkgs integration", + "id": 7304571, + "maintainers": { + "Mic92": 96200, + "winterqt": 78392041, + "zowoq": 59103226 + }, + "members": { + "tjni": 3806110 + }, + "name": "rust" + }, + "scala": { + "description": "Maintain Scala-related packages and modules.", + "id": 11193149, + "maintainers": { + "dottybot": 12519979, + "hamzaremmal": 56235032 + }, + "members": { + "natsukagami": 9061737 + }, + "name": "Scala" + }, + "sdl": { + "description": "Maintain core SDL libraries", + "id": 13033942, + "maintainers": { + "pbsds": 140964 + }, + "members": { + "LordGrimmauld": 49513131, + "evysgarden": 92547295, + "jansol": 2588851, + "marcin-serwin": 12128106 + }, + "name": "SDL" + }, + "static": { + "description": "People interested in static builds (creation of `.a` files, fully static executables, etc.) and keeping them working", + "id": 5906550, + "maintainers": { + "nh2": 399535 + }, + "members": { + "Ericson2314": 1055245, + "aherrmann": 732652, + "alyssais": 2768870, + "basvandijk": 576355, + "cdepillabout": 64804, + "dtzWill": 817330, + "lorenzleutgeb": 542154, + "matthewbauer": 19036, + "r-burns": 52847440, + "rnhmjoj": 2817565, + "sternenseemann": 3154475 + }, + "name": "static" + }, + "stdenv": { + "description": "Maintain the standard environment and its surrounding logic.", + "id": 11265412, + "maintainers": { + "RossComputerGuy": 19699320 + }, + "members": { + "Artturin": 56650223, + "Ericson2314": 1055245, + "emilazy": 18535642, + "philiptaron": 43863, + "reckenrode": 7413633 + }, + "name": "stdenv" + }, + "systemd": { + "description": "Maintain systemd for NixOS", + "id": 3894007, + "maintainers": { + "flokli": 183879 + }, + "members": { + "ElvishJerricco": 1365692, + "LordGrimmauld": 49513131, + "aanderse": 7755101, + "arianvp": 628387 + }, + "name": "systemd" + }, + "xen-project": { + "description": "Maintain the Xen Project Hypervisor and the related tooling ecosystem. Members listed as \"Maintainers\" are recipients of Xen Security Advisories sent to xsa@nixos.org.", + "id": 11127725, + "maintainers": { + "CertainLach": 6235312, + "SigmaSquadron": 174749595, + "hehongbo": 665472 + }, + "members": { + "digitalrane": 1829286 + }, + "name": "Xen Project" + }, + "xfce": { + "description": "Maintainers of the Xfce Desktop Environment", + "id": 5421745, + "maintainers": { + "romildo": 1217934 + }, + "members": { + "bobby285271": 20080233 + }, + "name": "Xfce" + } +} diff --git a/maintainers/maintainer-list.nix b/maintainers/maintainer-list.nix index a07d0e41b379..535ef1d43934 100644 --- a/maintainers/maintainer-list.nix +++ b/maintainers/maintainer-list.nix @@ -587,7 +587,7 @@ }; adamperkowski = { name = "Adam Perkowski"; - email = "adas1per@protonmail.com"; + email = "me@adamperkowski.dev"; matrix = "@xx0a_q:matrix.org"; github = "adamperkowski"; githubId = 75480869; @@ -685,12 +685,6 @@ githubId = 260983; name = "Adrien Lemaire"; }; - AdsonCicilioti = { - name = "Adson Cicilioti"; - email = "adson.cicilioti@live.com"; - github = "AdsonCicilioti"; - githubId = 6278398; - }; adsr = { email = "as@php.net"; github = "adsr"; @@ -1075,6 +1069,13 @@ } ]; }; + alch-emi = { + email = "emi@alchemi.dev"; + github = "Alch-Emi"; + githubId = 38897201; + name = "Emi"; + matrix = "@emi:the-apothecary.club"; + }; aldenparker = { github = "aldenparker"; githubId = 32986873; @@ -1112,6 +1113,12 @@ githubId = 83360; name = "Aleksey Sidorov"; }; + alemonmk = { + email = "almk@rmntn.net"; + github = "alemonmk"; + githubId = 3955369; + name = "Lemon Lam"; + }; alerque = { email = "caleb@alerque.com"; github = "alerque"; @@ -1644,6 +1651,14 @@ githubId = 106511; name = "Andrew Kelley"; }; + andrewzah = { + name = "Andrew Zah"; + github = "andrewzah"; + githubId = 9789467; + email = "nix@andrewzah.com"; + matrix = "@andrewzah:matrix.abare.party"; + keys = [ { fingerprint = "D87B D9DC F11B ACD6 CDB4 0CB2 1373 2FB1 3E61 E0BE"; } ]; + }; Andy3153 = { name = "Andrei Dobrete"; email = "andy3153@protonmail.com"; @@ -2329,7 +2344,7 @@ email = "assistant.moetron@gmail.com"; github = "Assistant"; githubId = 2748721; - matrix = "@assistant:pygmalion.chat"; + matrix = "@self:assistant.moe"; name = "Assistant Moetron"; }; astavie = { @@ -2358,12 +2373,6 @@ name = "Vincent Fischer"; keys = [ { fingerprint = "BF47 81E1 F304 1ADF 18CE C401 DE16 C7D1 536D A72F"; } ]; }; - astronaut0212 = { - email = "goatastronaut0212@outlook.com"; - github = "goatastronaut0212"; - githubId = 119769817; - name = "goatastronaut0212"; - }; asymmetric = { email = "lorenzo@mailbox.org"; github = "asymmetric"; @@ -2487,6 +2496,7 @@ github = "auscyber"; name = "Ivy Pierlot"; githubId = 12080502; + matrix = "@ivy:faggot.sh"; }; austin-artificial = { email = "austin.platt@artificial.io"; @@ -2630,13 +2640,6 @@ github = "aware70"; githubId = 7832566; }; - awwpotato = { - email = "awwpotato@voidq.com"; - matrix = "@awwpotato:envs.net"; - github = "awwpotato"; - githubId = 153149335; - name = "awwpotato"; - }; axertheaxe = { email = "axertheaxe@proton.me"; github = "AxerTheAxe"; @@ -2874,12 +2877,6 @@ githubId = 127523; name = "Herman Fries"; }; - BarinovMaxim = { - name = "Barinov Maxim"; - email = "barinov274@gmail.com"; - github = "barinov274"; - githubId = 54442153; - }; BarrOff = { name = "BarrOff"; github = "BarrOff"; @@ -3837,6 +3834,11 @@ githubId = 40476330; name = "brokenpip3"; }; + BronzeDeer = { + github = "BronzeDeer"; + githubId = 74385045; + name = "Joël Pepper"; + }; brpaz = { email = "oss@brunopaz.dev"; github = "brpaz"; @@ -4252,6 +4254,11 @@ githubId = 498906; name = "Karolis Stasaitis"; }; + carlostome = { + name = "Carlos Tomé Cortiñas"; + github = "carlostome"; + githubId = 2206578; + }; carlsverre = { email = "accounts@carlsverre.com"; github = "carlsverre"; @@ -4920,12 +4927,6 @@ githubId = 640797; name = "Roger Qiu"; }; - cmfwyp = { - email = "cmfwyp@riseup.net"; - github = "cmfwyp"; - githubId = 20808761; - name = "cmfwyp"; - }; cmm = { email = "repo@cmm.kakpryg.net"; github = "cmm"; @@ -5032,12 +5033,6 @@ githubId = 27779510; keys = [ { fingerprint = "FDF5 EF67 8CC1 FE22 1845 6A22 CF7B BB5B C756 1BD3"; } ]; }; - codsl = { - email = "codsl@riseup.net"; - github = "codsl"; - githubId = 6402559; - name = "codsl"; - }; codyopel = { email = "codyopel@gmail.com"; github = "codyopel"; @@ -5244,12 +5239,6 @@ githubId = 3077118; name = "David McFarland"; }; - coroa = { - email = "jonas@chaoflow.net"; - github = "coroa"; - githubId = 2552981; - name = "Jonas Hörsch"; - }; costrouc = { email = "chris.ostrouchov@gmail.com"; github = "costrouc"; @@ -5316,12 +5305,6 @@ githubId = 1957293; name = "Casey Ransom"; }; - CrazedProgrammer = { - email = "crazedprogrammer@gmail.com"; - github = "CrazedProgrammer"; - githubId = 12202789; - name = "CrazedProgrammer"; - }; creator54 = { email = "hi.creator54@gmail.com"; github = "Creator54"; @@ -5578,6 +5561,13 @@ githubId = 102048662; name = "Dalton Luce"; }; + da157 = { + email = "da157@voidq.com"; + matrix = "@da157:catgirl.cloud"; + github = "0xda157"; + githubId = 153149335; + name = "0xda157"; + }; dabao1955 = { email = "dabao1955@163.com"; github = "dabao1955"; @@ -5859,6 +5849,12 @@ { fingerprint = "E8F9 0B80 908E 723D 0EDF 0916 5803 CDA5 9C26 A96A"; } ]; }; + datosh = { + email = "fabian@kammel.dev"; + github = "datosh"; + githubId = 6423339; + name = "Fabian Kammel"; + }; dav-wolff = { email = "nixpkgs@dav.dev"; github = "dav-wolff"; @@ -5970,6 +5966,12 @@ githubId = 49904992; name = "Dawid Sowa"; }; + dawnofmidnight = { + email = "dawnofmidnight@duck.com"; + github = "dawnofmidnight"; + githubId = 78233879; + name = "whispers"; + }; dawoox = { email = "contact@antoinebellanger.fr"; github = "Dawoox"; @@ -6276,6 +6278,12 @@ githubId = 19733; name = "Moritz Heidkamp"; }; + DerHalbGrieche = { + email = "vasilis12.manetas@gmail.com"; + github = "DerHalbGrieche"; + githubId = 77843198; + name = "Vasilis Manetas"; + }; DerickEddington = { email = "derick.eddington@pm.me"; github = "DerickEddington"; @@ -7027,6 +7035,13 @@ name = "Will Dietz"; keys = [ { fingerprint = "389A 78CB CD88 5E0C 4701 DEB9 FD42 C7D0 D414 94C8"; } ]; }; + dudeofawesome = { + email = "tourist-04.iced@icloud.com"; + github = "dudeofawesome"; + githubId = 1683595; + name = "Louis Orleans"; + keys = [ { fingerprint = "llSOkL8Tn5+LOmWa4PDci+dQXZIRy11NSumDiFzNkAM"; } ]; + }; dudymas = { email = "jeremy.white@cloudposse.com"; github = "dudymas"; @@ -7127,6 +7142,12 @@ githubId = 90563298; name = "Dovydas Kersys"; }; + dyegoaurelio = { + name = "Dyego Aurelio"; + email = "d@dyego.email"; + github = "dyegoaurelio"; + githubId = 42411160; + }; dylan-gonzalez = { email = "dylcg10@gmail.com"; github = "dylan-gonzalez"; @@ -7245,6 +7266,11 @@ githubId = 8146736; name = "Florentin Eckl"; }; + eclairevoyant = { + githubId = 848000; + github = "eclairevoyant"; + name = "éclairevoyant"; + }; edanaher = { email = "nixos@edanaher.net"; github = "edanaher"; @@ -7730,6 +7756,13 @@ githubId = 3422442; name = "Ruben Maher"; }; + er0k = { + email = "er0k@er0k.net"; + github = "er0k"; + githubId = 916239; + name = "er0k"; + keys = [ { fingerprint = "60DE 4570 2E31 81A2 AF87 F075 B005 BA3C 8EE8 108D"; } ]; + }; eraserhd = { email = "jason.m.felice@gmail.com"; github = "eraserhd"; @@ -7872,6 +7905,12 @@ githubId = 21313906; name = "EsAu"; }; + esch = { + name = "Austin Eschweiler"; + github = "Eschguy"; + githubId = 8880292; + email = "austin.eschweiler@gmail.com"; + }; esclear = { github = "esclear"; githubId = 7432848; @@ -7977,7 +8016,7 @@ }; euxane = { name = "euxane"; - email = "r9uhdi.nixpkgs@euxane.net"; + email = "r9uhdi.nixpkgs@euxane.eu"; github = "pacien"; githubId = 1449319; }; @@ -8456,13 +8495,6 @@ githubId = 52276064; name = "figboy9"; }; - figsoda = { - email = "figsoda@pm.me"; - matrix = "@figsoda:matrix.org"; - github = "figsoda"; - githubId = 40620903; - name = "figsoda"; - }; fionera = { email = "nix@fionera.de"; github = "fionera"; @@ -9031,6 +9063,12 @@ githubId = 1313787; name = "Gabriella Gonzalez"; }; + GabrielMaguire = { + email = "gabrielmaguire@proton.me"; + github = "GabrielMaguire"; + githubId = 39974571; + name = "Gabriel Maguire"; + }; gabyx = { email = "gnuetzi@gmail.com"; github = "gabyx"; @@ -9071,6 +9109,12 @@ githubId = 7047019; name = "Florent Becker"; }; + galabovaa = { + name = "Ivet Galabova"; + email = "galabovaa@gmail.com"; + github = "galabovaa"; + githubId = 4016566; + }; galagora = { email = "lightningstrikeiv@gmail.com"; github = "Galagora"; @@ -10965,6 +11009,12 @@ githubId = 993484; name = "Greg Hale"; }; + imatpot = { + email = "nixpkgs@brnk.vc"; + github = "imatpot"; + githubId = 39416660; + name = "Mladen Branković"; + }; imgabe = { email = "gabrielpmonte@hotmail.com"; github = "ImGabe"; @@ -11700,6 +11750,12 @@ githubId = 29395089; name = "Jay Rovacsek"; }; + jaysa68 = { + email = "gh@jaysa.net"; + github = "jaysa68"; + githubId = 114126812; + name = "Jaysa Maria Garcia"; + }; jb55 = { email = "jb55@jb55.com"; github = "jb55"; @@ -12890,6 +12946,12 @@ github = "jthulhu"; githubId = 23179762; }; + jtliang24 = { + name = "Jiatao Liang"; + email = "jtliang24@gmail.com"; + github = "jtliang24"; + githubId = 170479425; + }; jtobin = { email = "jared@jtobin.io"; github = "jtobin"; @@ -13943,6 +14005,14 @@ githubId = 4032; name = "Kristoffer Thømt Ravneberg"; }; + krishnans2006 = { + email = "krishnans2006@gmail.com"; + matrix = "@krishnans2006:matrix.org"; + github = "krishnans2006"; + githubId = 62958782; + name = "Krishnan Shankar"; + keys = [ { fingerprint = "A30C 1843 F470 4843 5D54 3D68 29CB 06A8 40D0 E14A"; } ]; + }; kristian-brucaj = { email = "kbrucaj@gmail.com"; github = "Flameslice"; @@ -13998,6 +14068,12 @@ name = "Tomas Krupka"; matrix = "@krupkat:matrix.org"; }; + kruziikrel13 = { + github = "kruziikrel13"; + name = "Michael Petersen"; + email = "dev@michaelpetersen.io"; + githubId = 72793125; + }; krzaczek = { name = "Pawel Krzaczkowski"; email = "pawel@printu.pl"; @@ -14066,6 +14142,12 @@ githubId = 629430; keys = [ { fingerprint = "2843 750C B1AB E256 94BE 40E2 D843 D30B 42CA 0E2D"; } ]; }; + KunyaKud = { + name = "KunyaKud"; + email = "wafuu@posteo.net"; + github = "KunyaKud"; + githubId = 238898928; + }; kupac = { github = "Kupac"; githubId = 8224569; @@ -14253,6 +14335,17 @@ githubId = 55911173; name = "Gwendolyn Quasebarth"; }; + lajp = { + email = "lajp@iki.fi"; + github = "lajp"; + githubId = 31856315; + name = "Luukas Pörtfors"; + keys = [ + { + fingerprint = "24E8 E4CC 0295 F4ED B9E0 B4A6 C913 9B8D EA65 BD82"; + } + ]; + }; lamarios = { matrix = "@lamarios:matrix.org"; github = "lamarios"; @@ -14435,6 +14528,12 @@ githubId = 4701504; name = "James Robinson"; }; + leha44581 = { + email = "leha55481@gmail.com"; + github = "Leha44581"; + githubId = 70238465; + name = "Leha"; + }; leifhelm = { email = "jakob.leifhelm@gmail.com"; github = "leifhelm"; @@ -14537,6 +14636,12 @@ githubId = 737767; name = "Thomas Gerbet"; }; + letgamer = { + github = "Letgamer"; + githubId = 62446107; + matrix = "@letgamer:tchncs.de"; + name = "Alex Stephan"; + }; lethalman = { email = "lucabru@src.gnome.org"; github = "lucabrunox"; @@ -14712,12 +14817,26 @@ githubId = 67327023; keys = [ { fingerprint = "8185 29F9 BB4C 33F0 69BB 9782 D1AC CDCF 2B9B 9799"; } ]; }; + lillecarl = { + name = "Carl Andersson"; + github = "lillecarl"; + githubId = 207073; + email = "nixos@lillecarl.com"; + matrix = "@lillecarl:matrix.org"; + }; lillycham = { email = "lillycat332@gmail.com"; github = "lillycham"; githubId = 54189319; name = "Lilly Cham"; }; + lilyball = { + email = "lily@ballards.net"; + github = "lilyball"; + githubId = 714; + matrix = "@esperlily:matrix.org"; + name = "Lily Ballard"; + }; limeytexan = { email = "limeytexan@gmail.com"; github = "limeytexan"; @@ -14757,12 +14876,6 @@ matrix = "@link2xt:matrix.org"; name = "link2xt"; }; - linquize = { - email = "linquize@yahoo.com.hk"; - github = "linquize"; - githubId = 791115; - name = "Linquize"; - }; linsui = { email = "linsui555@gmail.com"; github = "linsui"; @@ -14782,6 +14895,12 @@ githubId = 74221543; name = "Moritz Goltdammer"; }; + linuxmobile = { + email = "bdiez19@gmail.com"; + github = "linuxmobile"; + githubId = 10554636; + name = "Braian A. Diez"; + }; linuxwhata = { email = "linuxwhata@qq.com"; matrix = "@lwa:envs.net"; @@ -15540,12 +15659,6 @@ githubId = 1140462; name = "magenbluten"; }; - maggesi = { - email = "marco.maggesi@gmail.com"; - github = "maggesi"; - githubId = 1809783; - name = "Marco Maggesi"; - }; magicquark = { name = "magicquark"; github = "magicquark"; @@ -15879,6 +15992,12 @@ githubId = 1913876; name = "Markus Scherer"; }; + MarkusZoppelt = { + email = "markus@zoppelt.net"; + github = "MarkusZoppelt"; + githubId = 2495125; + name = "Markus Zoppelt"; + }; marmolak = { email = "hack.robin@gmail.com"; github = "marmolak"; @@ -17258,6 +17377,17 @@ githubId = 7831184; name = "John Mercier"; }; + mochienya = { + name = "mochienya"; + github = "mochienya"; + githubId = 187453775; + matrix = "@mochienya:matrix.org"; + keys = [ + { + fingerprint = "7A49 5110 84F4 EAF1 BE30 5CF0 CC3B E964 564F 9554"; + } + ]; + }; mockersf = { email = "francois.mockers@vleue.com"; github = "mockersf"; @@ -17282,12 +17412,6 @@ githubId = 64710; name = "Matthew O'Gorman"; }; - Mogria = { - email = "m0gr14@gmail.com"; - github = "mogria"; - githubId = 754512; - name = "Mogria"; - }; mohe2015 = { name = "Moritz Hedtke"; email = "Moritz.Hedtke@t-online.de"; @@ -17573,6 +17697,12 @@ name = "Sean Gilligan"; keys = [ { fingerprint = "3B66 ACFA D10F 02AA B1D5  2CB1 8DD0 D81D 7D1F C61A"; } ]; }; + mshnwq = { + email = "mshnwq.com@gmail.com"; + github = "mshnwq"; + githubId = 68467027; + name = "Hayan Al-Machnouk"; + }; msiedlarek = { email = "mikolaj@siedlarek.pl"; github = "msiedlarek"; @@ -17986,6 +18116,12 @@ name = "Nasir Hussain"; keys = [ { fingerprint = "7A10 AB8E 0BEC 566B 090C 9BE3 D812 6E55 9CE7 C35D"; } ]; }; + nasrally = { + email = "suffer.ring@ya.ru"; + github = "nasrally"; + githubId = 50599445; + name = "Nikita Grishko"; + }; nat-418 = { github = "nat-418"; githubId = 93013864; @@ -18657,6 +18793,12 @@ github = "noahgitsham"; githubId = 73707948; }; + nobbele = { + name = "nobbele"; + email = "realnobbele@gmail.com"; + github = "nobbele"; + githubId = 17962514; + }; nobbz = { name = "Norbert Melzer"; email = "timmelzer+nixpkgs@gmail.com"; @@ -18986,6 +19128,12 @@ githubId = 1348; name = "Nate Smith"; }; + nxm = { + email = "szturomski@jakub.app"; + name = "Jakub Szturomski"; + github = "nxm"; + githubId = 22380073; + }; nyabinary = { name = "Niko Cantero"; email = "nyanbinary@keemail.me"; @@ -19190,12 +19338,6 @@ githubId = 5339261; keys = [ { fingerprint = "4258 3FE7 12E9 6071 E84D 53C7 6E1D A270 0B72 746D"; } ]; }; - oida = { - email = "oida@posteo.de"; - github = "oida"; - githubId = 7249506; - name = "oida"; - }; oidro = { github = "oidro"; githubId = 31112680; @@ -19474,6 +19616,12 @@ githubId = 52569953; name = "Oskar Manhart"; }; + oskarwires = { + email = "me@usbcable.io"; + github = "oskarwires"; + githubId = 115482671; + name = "Oskar"; + }; osnyx = { email = "os@flyingcircus.io"; github = "osnyx"; @@ -19926,12 +20074,6 @@ githubId = 6498458; name = "pebble kite"; }; - pbogdan = { - email = "ppbogdan@gmail.com"; - github = "pbogdan"; - githubId = 157610; - name = "Piotr Bogdan"; - }; pborzenkov = { email = "pavel@borzenkov.net"; github = "pborzenkov"; @@ -20840,12 +20982,6 @@ githubId = 88623613; name = "ProggerX"; }; - proglodyte = { - email = "proglodyte23@gmail.com"; - github = "proglodyte"; - githubId = 18549627; - name = "Proglodyte"; - }; proglottis = { email = "proglottis@gmail.com"; github = "proglottis"; @@ -21239,6 +21375,12 @@ githubId = 39039420; name = "Quinn Dougherty"; }; + quinneden = { + email = "quinn@qeden.dev"; + github = "quinneden"; + githubId = 125415641; + name = "Quinn Edenfield"; + }; QuiNzX = { name = "QuiNz-"; github = "QuiNzX"; @@ -21284,6 +21426,11 @@ matrix = "@qyriad:katesiria.org"; name = "Qyriad"; }; + qzylinra = { + github = "qzylinra"; + githubId = 225773816; + name = "qzylinra"; + }; r-aizawa = { github = "Xantibody"; githubId = 109563705; @@ -21659,12 +21806,6 @@ { fingerprint = "01D7 5486 3A6D 64EA AC77 0D26 FBF1 9A98 2CCE 0048"; } ]; }; - redbaron = { - email = "ivanov.maxim@gmail.com"; - github = "redbaron"; - githubId = 16624; - name = "Maxim Ivanov"; - }; redfish64 = { email = "engler@gmail.com"; github = "redfish64"; @@ -21855,6 +21996,11 @@ githubId = 32239737; keys = [ { fingerprint = "91EB E870 1639 1323 642A 6803 B966 009D 57E6 9CC6"; } ]; }; + rexies = { + name = "Rexiel Scarlet"; + github = "Rexcrazy804"; + githubId = 37258415; + }; rexxDigital = { email = "joellarssonpriv@gmail.com"; github = "rexxDigital"; @@ -22005,12 +22151,6 @@ githubId = 1810487; name = "Rika"; }; - rileyinman = { - email = "rileyminman@gmail.com"; - github = "rileyinman"; - githubId = 37246692; - name = "Riley Inman"; - }; rinx = { email = "rintaro.okamura@gmail.com"; github = "rinx"; @@ -23057,18 +23197,17 @@ githubId = 73446695; name = "Savinien Petitjean"; }; - savannidgerinel = { - email = "savanni@luminescent-dreams.com"; - github = "savannidgerinel"; - githubId = 8534888; - name = "Savanni D'Gerinel"; - }; savedra1 = { email = "michaelsavedra@gmail.com"; github = "savedra1"; githubId = 99875823; name = "Michael Savedra"; }; + savtrip = { + github = "savtrip"; + githubId = 42227195; + name = "Sav Tripodi"; + }; savyajha = { email = "savya.jha@hawkradius.com"; github = "savyajha"; @@ -23468,6 +23607,14 @@ githubId = 5791019; name = "Jiuyang Liu"; }; + Sereja313 = { + name = "Sergey Gulin"; + github = "Sereja313"; + githubId = 112060595; + email = "sergeygulin96@gmail.com"; + matrix = "@sereja:sereja.xyz"; + keys = [ { fingerprint = "AEF0 79C6 7618 8929 4124 22DB 3AB4 2DF3 F50E 3420"; } ]; + }; serge = { email = "sb@canva.com"; github = "serge-belov"; @@ -24114,6 +24261,11 @@ name = "Sebastian Kowalak"; matrix = "@scl:tchncs.de"; }; + skwig = { + name = "skwig"; + github = "skwig"; + githubId = 16136203; + }; skyesoss = { name = "Skye Soss"; matrix = "@skyesoss:matrix.org"; @@ -25651,12 +25803,6 @@ githubId = 102452; name = "Niclas Thall"; }; - thammers = { - email = "jawr@gmx.de"; - github = "tobias-hammerschmidt"; - githubId = 2543259; - name = "Tobias Hammerschmidt"; - }; thanegill = { email = "me@thanegill.com"; github = "thanegill"; @@ -25749,11 +25895,10 @@ github = "thefossguy"; githubId = 44400303; }; - thehans255 = { - name = "Hans Jorgensen"; - email = "foss-contact@thehans255.com"; - github = "thehans255"; - githubId = 15896573; + thegu5 = { + name = "Gus"; + github = "thegu5"; + githubId = 58223632; }; thekostins = { name = "Konstantin"; @@ -25794,10 +25939,10 @@ }; theobori = { name = "Théo Bori"; - email = "theo1.bori@epitech.eu"; + email = "theobori@disroot.org"; github = "theobori"; githubId = 71843723; - keys = [ { fingerprint = "EEFB CC3A C529 CFD1 943D A75C BDD5 7BE9 9D55 5965"; } ]; + keys = [ { fingerprint = "0636 56A5 6E31 5FFD BE46 8522 6D22 B068 2CCF 9294"; } ]; }; theonlymrcat = { name = "Max Guppy"; @@ -25856,6 +26001,11 @@ githubId = 91203390; name = "Felix Kimmel"; }; + thesn = { + github = "thesn10"; + githubId = 38666407; + name = "TheSN"; + }; thesola10 = { email = "me@thesola.io"; github = "Thesola10"; @@ -26023,6 +26173,12 @@ githubId = 1761259; name = "Eric Roberts"; }; + thrix = { + email = "mvadkert@redhat.com"; + github = "thrix"; + githubId = 633969; + name = "Miroslav Vadkerti"; + }; thtrf = { email = "thtrf@proton.me"; github = "thtrf"; @@ -27014,6 +27170,11 @@ githubId = 5155100; name = "Utkarsh Gupta"; }; + utopiatopia = { + github = "utopiatopia"; + githubId = 98685984; + name = "utopiatopia"; + }; uvnikita = { email = "uv.nikita@gmail.com"; github = "uvNikita"; @@ -27377,12 +27538,6 @@ githubId = 1476338; name = "Viktor Illmer"; }; - vklquevs = { - email = "vklquevs@gmail.com"; - github = "vklquevs"; - githubId = 1771234; - name = "vklquevs"; - }; vlaci = { email = "laszlo.vasko@outlook.com"; github = "vlaci"; @@ -27578,12 +27733,6 @@ githubId = 988849; name = "Vasiliy Yorkin"; }; - vyp = { - email = "elisp.vim@gmail.com"; - github = "vyp"; - githubId = 3889405; - name = "vyp"; - }; w-lfchen = { email = "w-lfchen@posteo.net"; github = "w-lfchen"; @@ -27747,6 +27896,12 @@ githubId = 43357387; keys = [ { fingerprint = "F844 80B2 0CA9 D6CC C7F5 2479 A776 D2AD 099E 8BC0"; } ]; }; + wetisobe = { + name = "Martin Woods"; + github = "wetisobe"; + email = "weti.sobe@pen-net.de"; + githubId = 172606048; + }; wetrustinprize = { email = "git@wetrustinprize.com"; github = "wetrustinprize"; @@ -28662,6 +28817,12 @@ githubId = 7040031; name = "Yannik Sander"; }; + yuannan = { + email = "brandon@emergence.ltd"; + github = "yuannan"; + githubId = 8006928; + name = "Yuannan (Brandon) Lin"; + }; yuka = { email = "yuka@yuka.dev"; matrix = "@yuka:yuka.dev"; @@ -28939,6 +29100,13 @@ github = "zeri42"; githubId = 68825133; }; + zerodya = { + name = "Nicola"; + email = "nicola.pagliuca@pm.me"; + matrix = "@zerodya:beeper.com"; + github = "Zerodya"; + githubId = 73220426; + }; zestsystem = { email = "mk337337@gmail.com"; github = "zestsystem"; @@ -28956,6 +29124,11 @@ githubId = 1329212; name = "Andy Zhang"; }; + zhaithizaliel = { + name = "Zhaith Izaliel"; + github = "Zhaith-Izaliel"; + githubId = 39216756; + }; zhaofengli = { email = "hello@zhaofeng.li"; matrix = "@zhaofeng:zhaofeng.li"; @@ -29101,6 +29274,12 @@ githubId = 332534; name = "Zach Shipko"; }; + zstg = { + email = "zestig@duck.com"; + github = "zstg"; + githubId = 69384921; + name = "ZeStig"; + }; ztzg = { email = "dd@crosstwine.com"; github = "ztzg"; diff --git a/maintainers/scripts/README.md b/maintainers/scripts/README.md index 6ae6cb851bc4..fd6e8bd21f64 100644 --- a/maintainers/scripts/README.md +++ b/maintainers/scripts/README.md @@ -52,17 +52,6 @@ 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 ### `sha-to-sri.py` diff --git a/maintainers/scripts/audit-ruby-packages/audit-ruby-packages.bash b/maintainers/scripts/audit-ruby-packages/audit-ruby-packages.bash new file mode 100755 index 000000000000..6459e38d9842 --- /dev/null +++ b/maintainers/scripts/audit-ruby-packages/audit-ruby-packages.bash @@ -0,0 +1,6 @@ +#!/usr/bin/env nix-shell +#!nix-shell -i bash -p bundler-audit + +set -o errexit -o nounset -o pipefail + +bundle-audit check "$(nix-build --no-out-link maintainers/scripts/audit-ruby-packages/default.nix)" diff --git a/maintainers/scripts/audit-ruby-packages/default.nix b/maintainers/scripts/audit-ruby-packages/default.nix new file mode 100644 index 000000000000..47d394cb7875 --- /dev/null +++ b/maintainers/scripts/audit-ruby-packages/default.nix @@ -0,0 +1,15 @@ +let + pkgs = import ../../.. { }; + lockFileBody = pkgs.lib.concatStringsSep "\n" ( + pkgs.lib.mapAttrsToList (name: props: " ${name} (${props.version})") ( + pkgs.lib.filterAttrs (name: _props: name != "recurseForDerivations") pkgs.rubyPackages + ) + ); +in +pkgs.runCommand "bundle-audit" { } '' + mkdir "$out" + echo 'GEM' > "$out/Gemfile.lock" + echo ' remote: https://rubygems.org/' >> "$out/Gemfile.lock" + echo ' specs:' >> "$out/Gemfile.lock" + echo '${lockFileBody}' >> "$out/Gemfile.lock" +'' diff --git a/maintainers/scripts/feature-freeze-teams.pl b/maintainers/scripts/feature-freeze-teams.pl index 7d7574837ed7..4b1dd409b794 100755 --- a/maintainers/scripts/feature-freeze-teams.pl +++ b/maintainers/scripts/feature-freeze-teams.pl @@ -1,11 +1,11 @@ #!/usr/bin/env nix-shell -#!nix-shell -i perl -p perl -p perlPackages.JSON perlPackages.LWPUserAgent perlPackages.LWPProtocolHttps perlPackages.TermReadKey +#!nix-shell -i perl -p perl -p perlPackages.JSON github-cli # This script generates a list of teams to ping for the Feature Freeze announcement on Discourse. # It's intended to be used by Release Managers before creating such posts. # -# The script interactively reads a GitHub username and a corresponding GitHub Personal Access token. -# This is required to access the GitHub Teams API so the token needs at least the read:org privilege. +# The script uses the credentials from the GitHub CLI (gh) +# This is required to access the GitHub Teams API so it needs at least the read:org privilege. ## no critic (InputOutput::RequireCheckedSyscalls, InputOutput::ProhibitBacktickOperators) use strict; @@ -14,39 +14,21 @@ use Carp; use Cwd 'abs_path'; use File::Basename; use JSON qw(decode_json); -use LWP::UserAgent; -use Term::ReadKey qw(ReadLine ReadMode); sub github_team_members { - my ($team_name, $username, $token) = @_; + my ($team_name) = @_; my @ret; - my $req = HTTP::Request->new('GET', "https://api.github.com/orgs/NixOS/teams/$team_name/members", [ 'Accept' => 'application/vnd.github.v3+json' ]); - $req->authorization_basic($username, $token); - my $response = LWP::UserAgent->new->request($req); - - if ($response->is_success) { - my $content = decode_json($response->decoded_content); - foreach (@{$content}) { - push @ret, $_->{'login'}; - } - } else { - print {*STDERR} "!! Requesting members of GitHub Team '$team_name' failed: " . $response->status_line; + my $content = decode_json(`gh api orgs/NixOS/teams/$team_name/members`); + foreach (@{$content}) { + push @ret, $_->{'login'}; } return \@ret; } -# Read GitHub credentials -print {*STDERR} 'GitHub username: '; -my $github_user = ReadLine(0); -ReadMode('noecho'); -print {*STDERR} 'GitHub personal access token (no echo): '; -my $github_token = ReadLine(0); -ReadMode('restore'); -print {*STDERR} "\n"; -chomp $github_user; -chomp $github_token; +`gh auth status` or die "`gh` comes from `pkgs.github-cli`, or in one command: +nix-shell -p github-cli --run 'gh auth login'\n"; # Read nix output my $nix_version = `nix --version`; @@ -60,7 +42,6 @@ if ($nix_version =~ m/2[.]3[.]/msx) { my $data = decode_json($out); # Process teams -print {*STDERR} "\n"; while (my ($team_nix_key, $team_config) = each %{$data}) { # Ignore teams that don't want to be or can't be pinged if (not defined $team_config->{enableFeatureFreezePing} or not $team_config->{enableFeatureFreezePing}) { @@ -71,12 +52,12 @@ while (my ($team_nix_key, $team_config) = each %{$data}) { next; } # Team name - print {*STDERR} "$team_config->{shortName}:"; + print {*STDOUT} "$team_config->{shortName}:"; # GitHub Teams my @github_members; if (defined $team_config->{github}) { - print {*STDERR} " \@NixOS/$team_config->{github}"; - push @github_members, @{github_team_members($team_config->{github}, $github_user, $github_token)}; + print {*STDOUT} " \@NixOS/$team_config->{github}"; + push @github_members, @{github_team_members($team_config->{github})}; } my %github_members = map { $_ => 1 } @github_members; # Members @@ -88,9 +69,11 @@ while (my ($team_nix_key, $team_config) = each %{$data}) { if (defined $github_members{$github_handle}) { next; } - print {*STDERR} " \@$github_handle"; + print {*STDOUT} " \@$github_handle"; } } - print {*STDERR} "\n"; + print {*STDOUT} "\n"; } + +print {*STDOUT} "Everyone else: \@NixOS/nixpkgs-committers\n"; diff --git a/maintainers/scripts/get-maintainer-pings-between.sh b/maintainers/scripts/get-maintainer-pings-between.sh deleted file mode 100755 index 4b6d7ff78052..000000000000 --- a/maintainers/scripts/get-maintainer-pings-between.sh +++ /dev/null @@ -1,78 +0,0 @@ -#!/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/maintainers/scripts/haskell/update-stackage.sh b/maintainers/scripts/haskell/update-stackage.sh index 0889f7e1d9ed..e049064c7564 100755 --- a/maintainers/scripts/haskell/update-stackage.sh +++ b/maintainers/scripts/haskell/update-stackage.sh @@ -99,6 +99,11 @@ sed -r \ -e '/ Agda /d' \ -e '/ stack /d' \ -e '/ git-annex /d' \ + -e '/ hledger /d' \ + -e '/ hledger-iadd /d' \ + -e '/ hledger-lib /d' \ + -e '/ hledger-ui /d' \ + -e '/ hledger-web /d' \ < "${tmpfile_new}" >> $stackage_config # Explanations: # cabal2nix, distribution-nixpkgs, jailbreak-cabal, language-nix: These are our packages and we know what we are doing. diff --git a/maintainers/scripts/luarocks-packages.csv b/maintainers/scripts/luarocks-packages.csv index 817e95c48407..2acc4786f130 100644 --- a/maintainers/scripts/luarocks-packages.csv +++ b/maintainers/scripts/luarocks-packages.csv @@ -41,12 +41,12 @@ llscheck,,,,,,mrcjkb lmathx,,,,,5.3,alexshpilkin lmpfrlib,,,,,5.3,alexshpilkin loadkit,,,,,,alerque -lpeg,,,,,,vyp +lpeg,,,,,, lpeg_patterns,,,,,, lpeglabel,,,,1.6.0,, lrexlib-gnu,,,,,, lrexlib-oniguruma,,,,,,junestepp -lrexlib-pcre,,,,,,vyp +lrexlib-pcre,,,,,, lrexlib-posix,,,,,, lsp-progress.nvim,,,,,,gepbird lua-cjson,,,,,, @@ -86,7 +86,7 @@ lualdap,,,,,,aanderse lualine.nvim,,,http://luarocks.org/dev,,, lualogging,,,,,, luaossl,,,,,5.1, -luaposix,,,,34.1.1-1,,vyp lblasc +luaposix,,,,34.1.1-1,,lblasc luaprompt,,,,,,Freed-Wu luarepl,,,,,, luarocks,,,,,,mrcjkb teto @@ -96,7 +96,7 @@ luarocks-build-treesitter-parser-cpp,,,,,,mrcjkb luasec,,,,,,flosse luasnip,,,,,, luasocket,,,,,, -luasql-sqlite3,,,,,,vyp +luasql-sqlite3,,,,,, luassert,,,,,, luasystem,,,,,, luatext,,,,,, @@ -148,7 +148,7 @@ sofa,,,,,,f4z3r sqlite,,,,,, std._debug,,,,,, std.normalize,,,,,, -stdlib,,,,41.2.2,,vyp +stdlib,,,,41.2.2,, teal-language-server,,,,,, telescope-manix,,,,,, telescope.nvim,,,,,5.1, @@ -159,5 +159,5 @@ tree-sitter-http,,,,0.0.33-1,, tree-sitter-norg,,,,,5.1,mrcjkb tree-sitter-orgmode,,,,,, vstruct,,,,,, -vusted,,,,,,figsoda +vusted,,,,,, xml2lua,,,,,,teto diff --git a/maintainers/scripts/remove-old-aliases.py b/maintainers/scripts/remove-old-aliases.py index 3c5f8edc50ad..bceee1074844 100755 --- a/maintainers/scripts/remove-old-aliases.py +++ b/maintainers/scripts/remove-old-aliases.py @@ -1,7 +1,7 @@ #!/usr/bin/env nix-shell #!nix-shell -i python3 -p "python3.withPackages(ps: with ps; [ ])" nix """ -A program to remove old aliases or convert old aliases to throws +Converts old aliases to warnings, converts old warnings to throws, and removes old throws. Example usage: ./maintainers/scripts/remove-old-aliases.py --year 2018 --file ./pkgs/top-level/aliases.nix @@ -31,22 +31,42 @@ def process_args() -> argparse.Namespace: arg_parser.add_argument( "--only-throws", action="store_true", - help="only operate on throws. e.g remove throws older than $date", + help="Deprecated, use --only throws instead", + ) + arg_parser.add_argument( + "--only", + choices=["aliases", "warnings", "throws"], + help="Only act on the specified types" + "(i.e. only act on entries that are 'normal' aliases, warnings, or throws)." + "Can be repeated.", + action="append", + dest="operate_on", ) arg_parser.add_argument("--file", required=True, type=Path, help="alias file") arg_parser.add_argument( "--dry-run", action="store_true", help="don't modify files, only print results" ) - return arg_parser.parse_args() + + parsed = arg_parser.parse_args() + + if parsed.only_throws: + parsed.operate_on.append("throws") + + if parsed.operate_on is None: + parsed.operate_on = ["aliases", "warnings", "throws"] + + return parsed def get_date_lists( - txt: list[str], cutoffdate: datetimedate, only_throws: bool -) -> tuple[list[str], list[str], list[str]]: + txt: list[str], cutoffdate: datetimedate +) -> tuple[list[str], list[str], list[str], list[str], list[str]]: """get a list of lines in which the date is older than $cutoffdate""" date_older_list: list[str] = [] date_older_throw_list: list[str] = [] + date_older_warning_list: list[str] = [] date_sep_line_list: list[str] = [] + date_too_complex_list: list[str] = [] for lineno, line in enumerate(txt, start=1): line = line.rstrip() @@ -69,68 +89,104 @@ def get_date_lists( ): continue - if "=" not in line: - date_sep_line_list.append(f"{lineno} {line}") + if line.lstrip().startswith("inherit (") and ";" in line: + date_older_list.append(line) + elif "=" not in line: + date_sep_line_list.append(f"{lineno:>5} {line}") # 'if' lines could be complicated elif "if " in line and "if =" not in line: - print(f"RESOLVE MANUALLY {line}") - elif "throw" in line: + date_too_complex_list.append(f"{lineno:>5} {line}") + elif "= with " in line: + date_too_complex_list.append(f"{lineno:>5} {line}") + elif "warnAlias" in line or "warning" in line: + if 'warnAlias "' in line: + date_older_warning_list.append(line) + else: + date_too_complex_list.append(f"{lineno:>5} {line}") + elif " = throw" in line: date_older_throw_list.append(line) - elif not only_throws: + else: date_older_list.append(line) return ( date_older_list, date_sep_line_list, + date_too_complex_list, date_older_throw_list, + date_older_warning_list, ) -def convert_to_throw(date_older_list: list[str]) -> list[tuple[str, str]]: - """convert a list of lines to throws""" - converted_list = [] - for line in date_older_list.copy(): +def convert(lines: list[str], convert_to: str) -> list[tuple[str, str]]: + """convert a list of lines to either "throws" or "warnings".""" + converted_lines = {} + for line in lines.copy(): indent: str = " " * (len(line) - len(line.lstrip())) - before_equal = "" - after_equal = "" - try: - before_equal, after_equal = (x.strip() for x in line.split("=", maxsplit=2)) - except ValueError as err: - print(err, line, "\n") - date_older_list.remove(line) - continue - alias = before_equal - alias_unquoted = before_equal.strip('"') - replacement = next(x.strip(";:") for x in after_equal.split()) + if "=" not in line: + assert "inherit (" in line + before, sep, after = line.partition("inherit (") + inside, sep, after = after.partition(")") + if not sep: + print(f"FAILED ON {line}") + continue + alias, *_ = after.strip().split(";")[0].split() + replacement = f"{inside.strip()}.{alias}" + + else: + before_equal = "" + after_equal = "" + try: + before_equal, after_equal = ( + x.strip() for x in line.split("=", maxsplit=2) + ) + if after_equal.startswith("warnAlias"): + after_equal = after_equal.split("\"", maxsplit=3)[2].strip() + except ValueError as err: + print(err, line, "\n") + lines.remove(line) + continue + + alias = before_equal + replacement = next(x.strip(";:") for x in after_equal.split()) + + alias_unquoted = alias.strip('"') replacement = replacement.removeprefix("pkgs.") - converted = ( - f"{indent}{alias} = throw \"'{alias_unquoted}' has been" - f" renamed to/replaced by '{replacement}'\";" - f" # Converted to throw {datetime.today().strftime('%Y-%m-%d')}" - ) - converted_list.append((line, converted)) + if convert_to == "throws": + converted = ( + f"{indent}{alias} = throw \"'{alias_unquoted}' has been" + f" renamed to/replaced by '{replacement}'\";" + f" # Converted to throw {datetime.today().strftime('%Y-%m-%d')}" + ) + converted_lines[line] = converted + elif convert_to == "warnings": + converted = ( + f"{indent}{alias} = warnAlias \"'{alias_unquoted}' has been" + f" renamed to/replaced by '{replacement}'\" {replacement};" + f" # Converted to warning {datetime.today().strftime('%Y-%m-%d')}" + ) + converted_lines[line] = converted + else: + raise ValueError("'convert_to' must be either 'throws' or 'warnings'") - return converted_list + return converted_lines def generate_text_to_write( txt: list[str], - date_older_list: list[str], - converted_to_throw: list[tuple[str, str]], - date_older_throw_list: list[str], + converted_lines: dict[str, str], ) -> list[str]: """generate a list of text to be written to the aliasfile""" text_to_write: list[str] = [] for line in txt: text_to_append: str = "" - if converted_to_throw: - for tupl in converted_to_throw: - if line == tupl[0]: - text_to_append = f"{tupl[1]}\n" - if line not in date_older_list and line not in date_older_throw_list: - text_to_append = f"{line}\n" + try: + new_line = converted_lines[line] + if new_line is not None: + text_to_write.append(f"{new_line}\n") + except KeyError: + text_to_write.append(f"{line}\n") if text_to_append: text_to_write.append(text_to_append) @@ -171,30 +227,48 @@ def main() -> None: """main""" args = process_args() - only_throws = args.only_throws aliasfile = Path(args.file).absolute() cutoffdate = (datetime.strptime(f"{args.year}-{args.month}-01", "%Y-%m-%d")).date() txt: list[str] = (aliasfile.read_text(encoding="utf-8")).splitlines() date_older_list: list[str] = [] - date_sep_line_list: list[str] = [] + date_older_warning_list: list[str] = [] date_older_throw_list: list[str] = [] + date_sep_line_list: list[str] = [] + date_too_complex_list: list[str] = [] - date_older_list, date_sep_line_list, date_older_throw_list = get_date_lists( - txt, cutoffdate, only_throws - ) + ( + date_older_list, + date_sep_line_list, + date_too_complex_list, + date_older_throw_list, + date_older_warning_list, + ) = get_date_lists(txt, cutoffdate) - converted_to_throw: list[tuple[str, str]] = [] - if date_older_list: - converted_to_throw = convert_to_throw(date_older_list) - print(" Will be converted to throws. ".center(100, "-")) + converted_lines: dict[str, str] = {} + + if date_older_list and "aliases" in args.operate_on: + converted_lines.update(convert(date_older_list, "warnings")) + print(" Will be converted to warnings. ".center(100, "-")) for l_n in date_older_list: print(l_n) - if date_older_throw_list: + if date_older_warning_list and "warnings" in args.operate_on: + converted_lines.update(convert(date_older_warning_list, "throws")) + print(" Will be converted to throws. ".center(100, "-")) + for l_n in date_older_warning_list: + print(l_n) + + if date_older_throw_list and "throws" in args.operate_on: print(" Will be removed. ".center(100, "-")) for l_n in date_older_throw_list: + converted_lines[l_n] = None + print(l_n) + + if date_too_complex_list: + print(" Too complex, resolve manually. ".center(100, "-")) + for l_n in date_too_complex_list: print(l_n) if date_sep_line_list: @@ -203,9 +277,7 @@ def main() -> None: print(l_n) if not args.dry_run: - text_to_write = generate_text_to_write( - txt, date_older_list, converted_to_throw, date_older_throw_list - ) + text_to_write = generate_text_to_write(txt, converted_lines) write_file(aliasfile, text_to_write) diff --git a/maintainers/scripts/update-typst-packages.py b/maintainers/scripts/update-typst-packages.py index 2264f97d7706..f7b05dae7203 100755 --- a/maintainers/scripts/update-typst-packages.py +++ b/maintainers/scripts/update-typst-packages.py @@ -78,7 +78,14 @@ class TypstPackage: "nix-command", ] result = subprocess.run(cmd + [url], capture_output=True, text=True) - hash = re.search(r"hash\s+\'(sha256-.{44})\'", result.stderr).groups()[0] + # We currently rely on Typst Universe's github repository to + # track package dependencies. However, there might be an + # inconsistency between the registry and the repository. We + # skip packages that cannot be fetched from the registry. + if re.search(r"error: unable to download", result.stderr): + return url, None + else: + hash = re.search(r"hash\s+\'(sha256-.{44})\'", result.stderr).groups()[0] return url, hash def to_name_full(self): @@ -86,10 +93,14 @@ class TypstPackage: def to_attrs(self): deps = set() - excludes = list(map( - lambda e: os.path.join(self.path, e), - self.meta["package"]["exclude"] if "exclude" in self.meta["package"] else [], - )) + excludes = list( + map( + lambda e: os.path.join(self.path, e), + self.meta["package"]["exclude"] + if "exclude" in self.meta["package"] + else [], + ) + ) for root, _, files in os.walk(self.path): for file in filter(lambda f: f.split(".")[-1] == "typ", files): file_path = os.path.join(root, file) @@ -110,6 +121,9 @@ class TypstPackage: ) source_url, source_hash = self.source() + if not source_hash: + return None + return dict( url=source_url, hash=source_hash, @@ -152,11 +166,12 @@ def generate_typst_packages(preview_dir, output_file): def generate_package(pname, package_subtree): sorted_keys = sorted(package_subtree.keys(), key=Version, reverse=True) print(f"Generating metadata for {pname}") - return { - pname: OrderedDict( - (k, package_subtree[k].to_attrs()) for k in sorted_keys - ) - } + version_set = OrderedDict( + (k, a) + for k, a in [(k, package_subtree[k].to_attrs()) for k in sorted_keys] + if a is not None + ) + return {pname: version_set} if len(version_set) > 0 else {} with concurrent.futures.ThreadPoolExecutor(max_workers=100) as executor: sorted_packages = sorted(package_tree.items(), key=lambda x: x[0]) diff --git a/maintainers/scripts/update.py b/maintainers/scripts/update.py index 10d197d5fe78..ca35f04d1285 100644 --- a/maintainers/scripts/update.py +++ b/maintainers/scripts/update.py @@ -92,7 +92,15 @@ async def attr_instantiation_worker( ) -> tuple[Path, str]: async with semaphore: eprint(f"Instantiating {attr_path}…") - return (await nix_instantiate(attr_path), attr_path) + try: + return (await nix_instantiate(attr_path), attr_path) + except Exception as e: + # Failure should normally terminate the script but + # looks like Python is buggy so we need to do it ourselves. + eprint(f"Failed to instantiate {attr_path}") + if e.stderr: + eprint(e.stderr.decode("utf-8")) + sys.exit(1) async def requisites_worker( diff --git a/maintainers/team-list.nix b/maintainers/team-list.nix index cb0c001ccd8b..857e84b7d286 100644 --- a/maintainers/team-list.nix +++ b/maintainers/team-list.nix @@ -1,11 +1,9 @@ /* List of maintainer teams. name = { - # Required members = [ maintainer1 maintainer2 ]; scope = "Maintain foo packages."; shortName = "foo"; - # Optional enableFeatureFreezePing = true; github = "my-subsystem"; }; @@ -18,7 +16,12 @@ - `enableFeatureFreezePing` will ping this team during the Feature Freeze announcements on releases - There is limited mention capacity in a single post, so this should be reserved for critical components or larger ecosystems within nixpkgs. - - `github` will ping the specified GitHub team as well + - `github` will ping the specified GitHub team and sync the `members`, `scope` and `shortName` fields from it + - `githubId` will be set automatically based on `github` + + If `github` is specified and you'd like to be added to the team, contact one of the `githubMaintainers` of the team: + + nix eval -f lib teams.someTeam.githubMaintainers --json | jq More fields may be added in the future. @@ -37,7 +40,6 @@ with lib.maintainers; aanderse arianvp emily - flokli m1cr0man ]; scope = "Maintain ACME-related packages and modules."; @@ -46,27 +48,11 @@ with lib.maintainers; }; agda = { - members = [ - alexarice - ncfavier - phijor - turion - ]; - scope = "Maintain Agda-related packages and modules."; - shortName = "Agda"; + github = "agda"; }; android = { - members = [ - adrian-gierakowski - hadilq - johnrtitor - numinit - RossComputerGuy - ]; - scope = "Maintain Android-related tooling in nixpkgs."; github = "android"; - shortName = "Android"; enableFeatureFreezePing = true; }; @@ -107,19 +93,7 @@ with lib.maintainers; }; beam = { - members = [ - adamcstephens - ankhers - Br1ght0ne - DianaOlympos - gleber - happysalada - minijackson - yurrriq - ]; github = "beam"; - scope = "Maintain BEAM-related packages and modules."; - shortName = "BEAM"; enableFeatureFreezePing = true; }; @@ -193,34 +167,11 @@ with lib.maintainers; }; categorization = { - members = [ - aleksana - fgaz - getpsyched - lyndeno - natsukium - philiptaron - pyrotelekinetic - raskin - sigmasquadron - tomodachi94 - ]; github = "categorization"; - scope = "Maintain the categorization system in Nixpkgs, per RFC 146. This team has authority over all categorization issues in Nixpkgs."; - shortName = "Categorization"; }; ci = { - members = [ - MattSturgeon - mic92 - philiptaron - wolfgangwalther - zowoq - ]; github = "nixpkgs-ci"; - scope = "Maintain Nixpkgs' in-tree Continuous Integration, including GitHub Actions."; - shortName = "CI"; }; cinnamon = { @@ -237,7 +188,6 @@ with lib.maintainers; members = [ floriansanderscc ]; scope = "Maintain Clever Cloud related packages."; shortName = "CleverCloud"; - github = "CleverCloud"; }; cloudposse = { @@ -263,21 +213,7 @@ with lib.maintainers; }; cosmic = { - members = [ - a-kenji - ahoneybun - drakon64 - griffi-gh - HeitorAugustoLN - nyabinary - pandapip1 - qyliss - thefossguy - michaelBelsanti - ]; github = "cosmic"; - shortName = "cosmic"; - scope = "Maintain the COSMIC DE and related packages."; enableFeatureFreezePing = true; }; @@ -291,15 +227,6 @@ with lib.maintainers; }; cuda = { - members = [ - connorbaker - GaetanLepage - prusnak - samuela - SomeoneSerge - ]; - scope = "Maintain CUDA-enabled packages"; - shortName = "Cuda"; github = "cuda-maintainers"; }; @@ -309,20 +236,14 @@ with lib.maintainers; xanderio blitz snu + e1mo ]; scope = "Team for Cyberus Technology employees who collectively maintain packages."; shortName = "Cyberus Technology employees"; }; darwin = { - members = [ - emily - reckenrode - toonn - ]; github = "darwin-core"; - scope = "Maintain core platform support and packages for macOS and other Apple platforms."; - shortName = "Darwin"; enableFeatureFreezePing = true; }; @@ -366,10 +287,7 @@ with lib.maintainers; }; docs = { - members = [ ]; github = "documentation-team"; - scope = "Maintain nixpkgs/NixOS documentation and tools for building it."; - shortName = "Docs"; enableFeatureFreezePing = true; }; @@ -387,6 +305,17 @@ with lib.maintainers; shortName = "dotnet"; }; + electron = { + members = [ + tomasajt + yayayayaka + teutat3s + ]; + scope = "Maintainers of electron packages"; + shortName = "electron"; + enableFeatureFreezePing = true; + }; + emacs = { members = [ AndersonTorres @@ -399,31 +328,11 @@ with lib.maintainers; }; enlightenment = { - members = [ romildo ]; github = "enlightenment"; - scope = "Maintain Enlightenment desktop environment and related packages."; - shortName = "Enlightenment"; - enableFeatureFreezePing = true; - }; - - # Dummy group for the "everyone else" section - feature-freeze-everyone-else = { - members = [ ]; - github = "nixpkgs-committers"; - scope = "Dummy team for the #everyone else' section during feture freezes, not to be used as package maintainers!"; - shortName = "Everyone else"; enableFeatureFreezePing = true; }; flutter = { - members = [ - mkg20001 - RossComputerGuy - FlafyDev - hacker1024 - ]; - scope = "Maintain Flutter and Dart-related packages and build tools"; - shortName = "flutter"; enableFeatureFreezePing = false; github = "flutter"; }; @@ -442,24 +351,11 @@ with lib.maintainers; }; formatter = { - members = [ - piegames - infinisil - das_j - _0x4A6F - MattSturgeon - jfly - # Not in the maintainer list - # Sereja313 - ]; - scope = "Nix formatting team: https://nixos.org/community/teams/formatting/"; - shortName = "Nix formatting team"; + github = "nix-formatting"; }; freedesktop = { - members = [ jtojnar ]; - scope = "Maintain Freedesktop.org packages for graphical desktop."; - shortName = "freedesktop.org packaging"; + github = "freedesktop"; }; fslabs = { @@ -484,18 +380,7 @@ with lib.maintainers; }; geospatial = { - members = [ - autra - imincik - l0b0 - nh2 - nialov - sikmir - willcohen - ]; github = "geospatial"; - scope = "Maintain geospatial, remote sensing and OpenStreetMap software."; - shortName = "Geospatial"; enableFeatureFreezePing = true; }; @@ -512,15 +397,7 @@ with lib.maintainers; }; gnome = { - members = [ - bobby285271 - hedning - jtojnar - dasj19 - ]; github = "gnome"; - scope = "Maintain GNOME desktop environment and platform."; - shortName = "GNOME"; enableFeatureFreezePing = true; }; @@ -535,17 +412,7 @@ with lib.maintainers; }; golang = { - members = [ - kalbasit - katexochen - mic92 - zowoq - qbit - mfrw - ]; github = "golang"; - scope = "Maintain Golang compilers."; - shortName = "Go"; enableFeatureFreezePing = true; }; @@ -561,15 +428,7 @@ with lib.maintainers; }; haskell = { - members = [ - cdepillabout - maralorn - sternenseemann - wolfgangwalther - ]; github = "haskell"; - scope = "Maintain Haskell packages and infrastructure."; - shortName = "Haskell"; enableFeatureFreezePing = true; }; @@ -595,16 +454,7 @@ with lib.maintainers; }; hyprland = { - members = [ - donovanglover - fufexan - johnrtitor - khaneliman - NotAShelf - ]; github = "hyprland"; - scope = "Maintain Hyprland compositor and ecosystem"; - shortName = "Hyprland"; enableFeatureFreezePing = true; }; @@ -626,14 +476,6 @@ with lib.maintainers; java = { github = "java"; - members = [ - chayleaf - fliegendewurst - infinidoge - tomodachi94 - ]; - shortName = "Java"; - scope = "Maintainers of the Nixpkgs Java ecosystem (JDK, JVM, Java, Gradle, Maven, Ant, and adjacent projects)"; enableFeatureFreezePing = true; }; @@ -651,7 +493,6 @@ with lib.maintainers; jitsi = { members = [ - cleeyv novmar ryantm lassulus @@ -673,17 +514,6 @@ with lib.maintainers; k3s = { github = "k3s"; - members = [ - euank - frederictobiasc - heywoodlh - marcusramberg - mic92 - rorosen - wrmilling - ]; - scope = "Maintain K3s package, NixOS module, NixOS tests, update script"; - shortName = "K3s"; }; kodi = { @@ -701,14 +531,7 @@ with lib.maintainers; }; kubernetes = { - members = [ - johanot - offline - saschagrunert - srhb - ]; - scope = "Maintain the Kubernetes package and module"; - shortName = "Kubernetes"; + github = "kubernetes"; }; libretro = { @@ -723,58 +546,21 @@ with lib.maintainers; }; linux-kernel = { - members = [ - TredwellGit - k900 - ma27 - nequissimus - qyliss - ]; - scope = "Maintain the Linux kernel."; - shortName = "Linux Kernel"; + github = "linux-kernel"; }; lisp = { - members = [ - raskin - lukego - nagy - uthar - hraban - ]; github = "lisp"; - scope = "Maintain the Lisp ecosystem."; - shortName = "lisp"; enableFeatureFreezePing = true; }; lix = { - members = [ - raitobezarius - qyriad - _9999years - lf- - alois31 - ]; - scope = "Maintain the Lix package manager inside of Nixpkgs."; - shortName = "Lix ecosystem"; + github = "lix-maintainers"; enableFeatureFreezePing = true; }; llvm = { - members = [ - dtzWill - emily - ericson2314 - lovek323 - qyliss - RossComputerGuy - rrbutani - sternenseemann - ]; github = "llvm"; - scope = "Maintain LLVM package sets and related packages"; - shortName = "LLVM"; enableFeatureFreezePing = true; }; @@ -786,23 +572,12 @@ with lib.maintainers; }; loongarch64 = { - members = [ - aleksana - Cryolitia - darkyzhou - dramforever - wegank - ]; github = "loongarch64"; - scope = "Maintain LoongArch64 related packages and code"; - shortName = "LoongArch64"; enableFeatureFreezePing = true; }; lua = { github = "lua"; - scope = "Maintain the lua ecosystem."; - shortName = "lua"; enableFeatureFreezePing = true; }; @@ -817,10 +592,7 @@ with lib.maintainers; }; lumina = { - members = [ romildo ]; github = "lumina"; - scope = "Maintain lumina desktop environment and related packages."; - shortName = "Lumina"; enableFeatureFreezePing = true; }; @@ -836,23 +608,12 @@ with lib.maintainers; }; lxqt = { - members = [ romildo ]; github = "lxqt"; - scope = "Maintain LXQt desktop environment and related packages."; - shortName = "LXQt"; enableFeatureFreezePing = true; }; marketing = { - members = [ - djacu - flyfloh - thilobillerbeck - tomberek - ]; github = "marketing-team"; - scope = "Marketing of Nix/NixOS/nixpkgs."; - shortName = "Marketing"; enableFeatureFreezePing = true; }; @@ -916,15 +677,7 @@ with lib.maintainers; }; neovim = { - members = [ - GaetanLepage - khaneliman - mrcjkb - perchun - ]; github = "neovim"; - scope = "Maintain the vim and neovim text editors and related packages."; - shortName = "Vim/Neovim"; }; nextcloud = { @@ -982,10 +735,7 @@ with lib.maintainers; }; ocaml = { - members = [ alizter ]; github = "ocaml"; - scope = "Maintain the OCaml compiler and package set."; - shortName = "OCaml"; enableFeatureFreezePing = true; }; @@ -1017,13 +767,7 @@ with lib.maintainers; }; pantheon = { - members = [ - davidak - bobby285271 - ]; github = "pantheon"; - scope = "Maintain Pantheon desktop environment and platform."; - shortName = "Pantheon"; enableFeatureFreezePing = true; }; @@ -1039,36 +783,16 @@ with lib.maintainers; }; php = { - members = [ - aanderse - ma27 - piotrkwiecinski - talyz - ]; github = "php"; - scope = "Maintain PHP related packages and extensions."; - shortName = "PHP"; enableFeatureFreezePing = true; }; podman = { - members = [ - saschagrunert - vdemeester - ]; github = "podman"; - scope = "Maintain Podman and CRI-O related packages and modules."; - shortName = "Podman"; }; postgres = { - members = [ - thoughtpolice - ma27 - wolfgangwalther - ]; - scope = "Maintain the PostgreSQL package and plugins along with the NixOS module."; - shortName = "PostgreSQL"; + github = "postgres"; enableFeatureFreezePing = true; }; @@ -1083,18 +807,7 @@ with lib.maintainers; }; qt-kde = { - members = [ - ilya-fedin - k900 - LunNova - mjm - nickcao - SuperSandro2000 - ttuegel - ]; github = "qt-kde"; - scope = "Maintain the Qt framework, KDE application suite, Plasma desktop environment and related projects."; - shortName = "Qt / KDE"; enableFeatureFreezePing = true; }; @@ -1120,43 +833,12 @@ with lib.maintainers; shortName = "Red Code Labs"; }; - release = { - members = [ ]; - github = "nixos-release-managers"; - scope = "Manage the current nixpkgs/NixOS release."; - shortName = "Release"; - }; - rocm = { - members = [ - Flakebi - GZGavinZhao - LunNova - mschwaig - ]; github = "rocm"; - scope = "Maintain ROCm and related packages."; - shortName = "ROCm"; - }; - - ruby = { - members = [ ]; - scope = "Maintain the Ruby interpreter and related packages."; - shortName = "Ruby"; - enableFeatureFreezePing = true; }; rust = { - members = [ - figsoda - mic92 - tjni - winter - zowoq - ]; github = "rust"; - scope = "Maintain the Rust compiler toolchain and nixpkgs integration."; - shortName = "Rust"; enableFeatureFreezePing = true; }; @@ -1171,16 +853,7 @@ with lib.maintainers; }; sdl = { - members = [ - evythedemon - grimmauld - jansol - marcin-serwin - pbsds - ]; - github = "SDL"; - scope = "Maintain core SDL libraries."; - shortName = "SDL"; + github = "sdl"; enableFeatureFreezePing = true; }; @@ -1207,16 +880,6 @@ with lib.maintainers; }; stdenv = { - members = [ - artturin - emily - ericson2314 - philiptaron - reckenrode - RossComputerGuy - ]; - scope = "Maintain the standard environment and its surrounding logic."; - shortName = "stdenv"; enableFeatureFreezePing = true; github = "stdenv"; }; @@ -1246,23 +909,13 @@ with lib.maintainers; samasaur stephank trepetti - trundle ]; scope = "Maintain Swift compiler suite for NixOS."; shortName = "Swift"; }; systemd = { - members = [ - flokli - arianvp - elvishjerricco - aanderse - grimmauld - ]; github = "systemd"; - scope = "Maintain systemd for NixOS."; - shortName = "systemd"; enableFeatureFreezePing = true; }; @@ -1312,14 +965,6 @@ with lib.maintainers; }; xen = { - members = [ - hehongbo - lach - sigmasquadron - rane - ]; - scope = "Maintain the Xen Project Hypervisor and the related tooling ecosystem."; - shortName = "Xen Project Hypervisor"; enableFeatureFreezePing = true; github = "xen-project"; }; @@ -1337,7 +982,6 @@ with lib.maintainers; zig = { members = [ - figsoda RossComputerGuy ]; scope = "Maintain the Zig compiler toolchain and nixpkgs integration."; diff --git a/nixos/doc/manual/development/option-types.section.md b/nixos/doc/manual/development/option-types.section.md index b7b9f04acd95..707e2e3d1345 100644 --- a/nixos/doc/manual/development/option-types.section.md +++ b/nixos/doc/manual/development/option-types.section.md @@ -31,6 +31,21 @@ merging is handled. : A path that is contained in the Nix store. This can be a top-level store path like `pkgs.hello` or a descendant like `"${pkgs.hello}/bin/hello"`. +`types.externalPath` + +: A path that is not contained in the Nix store. Typical use cases are: + secrets, password or any other external file. + +::: {.warning} +This type only validates that the path is not *currently* in the Nix store. +It does NOT prevent the value from being copied to the store later when: +- Referenced in a derivation +- Used in certain path operations (e.g., `${path}` interpolation) +- Passed to functions that copy to the store + +Users must still be careful about how they reference these paths. +::: + `types.pathWith` { *`inStore`* ? `null`, *`absolute`* ? `null` } : A filesystem path. Either a string or something that can be coerced @@ -316,22 +331,34 @@ A union of types is a type such that a value is valid when it is valid for at le If some values are instances of more than one of the types, it is not possible to distinguish which type they are meant to be instances of. If that's needed, consider using a [sum type](#sec-option-types-sums). + `types.either` *`t1 t2`* : Type *`t1`* or type *`t2`*, e.g. `with types; either int str`. Multiple definitions cannot be merged. + ::: {.warning} + `either` and `oneOf` eagerly decide the active type based on the passed types' shallow check method. For composite types like `attrsOf` and `submodule`, which both match all attribute set definitions, the first type argument will be chosen for the returned option value, and this therefore also decides how nested values are checked and merged. For example, `either (attrsOf int) (submodule {...})` will always use `attrsOf int` for any attribute set value, even if it was intended as a submodule. This behavior is a trade-off that keeps the implementation simple and the evaluation order predictable, avoiding unexpected strictness problems such as infinite recursions. When proper type discrimination is needed, consider using a [sum type](#sec-option-types-sums) like `attrTag` instead. + ::: + + `types.oneOf` \[ *`t1 t2`* ... \] : Type *`t1`* or type *`t2`* and so forth, e.g. `with types; oneOf [ int str bool ]`. Multiple definitions cannot be merged. + ::: {.warning} + `either` and `oneOf` eagerly decide the active type based on the passed types' shallow check method. For composite types like `attrsOf` and `submodule`, which both match all attribute set definitions, the first matching type in the list will be chosen for the returned option value, and this therefore also decides how nested values are checked and merged. For example, `oneOf [ (attrsOf int) (submodule {...}) ]` will always use `attrsOf int` for any attribute set value, even if it was intended as a submodule. This behavior is a trade-off that keeps the implementation simple and the evaluation order predictable, avoiding unexpected strictness problems such as infinite recursions. When proper type discrimination is needed, consider using a [sum type](#sec-option-types-sums) like `attrTag` instead. + ::: + `types.nullOr` *`t`* : `null` or type *`t`*. Multiple definitions are merged according to type *`t`*. + This is mostly equivalent to `either (enum [ null ]) t`, but `nullOr` provides a `null` fallback for attribute values with `mkIf false` definitions in `lazyAttrsOf (nullOr t)`, whereas `either` would throw an error when the attribute is accessed. + ## Sum types {#sec-option-types-sums} diff --git a/nixos/doc/manual/development/settings-options.section.md b/nixos/doc/manual/development/settings-options.section.md index c46c9fac3606..424613abbb77 100644 --- a/nixos/doc/manual/development/settings-options.section.md +++ b/nixos/doc/manual/development/settings-options.section.md @@ -358,6 +358,16 @@ have a predefined type and string generator already declared under : Outputs the xml with header. +`pkgs.formats.plist` { escape ? true } + +: A function taking an attribute set with values + + `escape` + + : Whether to escape XML special characters in string values and keys. + + It returns a set with Property list (plist) specific attributes `type` and `generate` as specified [below](#pkgs-formats-result). + `pkgs.formats.pythonVars` { } : A function taking an empty attribute set (for future extensibility) diff --git a/nixos/doc/manual/redirects.json b/nixos/doc/manual/redirects.json index 3ddfa1b1c385..e7a60706ecfe 100644 --- a/nixos/doc/manual/redirects.json +++ b/nixos/doc/manual/redirects.json @@ -824,12 +824,6 @@ "module-services-glance-quickstart": [ "index.html#module-services-glance-quickstart" ], - "module-services-filesender": [ - "index.html#module-services-filesender" - ], - "module-services-filesender-quickstart": [ - "index.html#module-services-filesender-quickstart" - ], "module-services-discourse": [ "index.html#module-services-discourse" ], diff --git a/nixos/doc/manual/release-notes/rl-2111.section.md b/nixos/doc/manual/release-notes/rl-2111.section.md index bf39afd98627..40a1a37483d7 100644 --- a/nixos/doc/manual/release-notes/rl-2111.section.md +++ b/nixos/doc/manual/release-notes/rl-2111.section.md @@ -166,6 +166,8 @@ In addition to numerous new and upgraded packages, this release has the followin - [twingate](https://docs.twingate.com/docs/linux), a high performance, easy to use zero trust solution that enables access to private resources from any device with better security than a VPN. +- [iio-niri](https://github.com/Zhaith-Izaliel/iio-niri), a utils that listens to `iio-sensor-proxy` and updates Niri output orientation depending on the accelerometer orientation. + ## Backward Incompatibilities {#sec-release-21.11-incompatibilities} - The NixOS VM test framework, `pkgs.nixosTest`/`make-test-python.nix` (`pkgs.testers.nixosTest` since 22.05), now requires detaching commands such as `succeed("foo &")` and `succeed("foo | xclip -i")` to close stdout. diff --git a/nixos/doc/manual/release-notes/rl-2405.section.md b/nixos/doc/manual/release-notes/rl-2405.section.md index 1cbf71a7aad8..7f2e0f622c62 100644 --- a/nixos/doc/manual/release-notes/rl-2405.section.md +++ b/nixos/doc/manual/release-notes/rl-2405.section.md @@ -92,7 +92,7 @@ The pre-existing `services.ankisyncd` has been marked deprecated and will be dro - [FCast Receiver](https://fcast.org), an open-source alternative to Chromecast and AirPlay. Available as [programs.fcast-receiver](#opt-programs.fcast-receiver.enable). -- [FileSender](https://filesender.org/), a file sharing software. Available as [services.filesender](#opt-services.filesender.enable). +- [FileSender](https://filesender.org/), a file sharing software. Available as `services.filesender`. - [Firefly-iii](https://www.firefly-iii.org), a free and open source personal finance manager. Available as [services.firefly-iii](#opt-services.firefly-iii.enable). @@ -178,7 +178,7 @@ The pre-existing `services.ankisyncd` has been marked deprecated and will be dro - [Scrutiny](https://github.com/AnalogJ/scrutiny), a S.M.A.R.T monitoring tool for hard disks with a web frontend. Available as [services.scrutiny](#opt-services.scrutiny.enable). -- [SimpleSAMLphp](https://simplesamlphp.org/), an application written in native PHP that deals with authentication (SQL, .htpasswd, YubiKey, LDAP, PAPI, Radius). Available as [services.simplesamlphp](#opt-services.simplesamlphp). +- [SimpleSAMLphp](https://simplesamlphp.org/), an application written in native PHP that deals with authentication (SQL, .htpasswd, YubiKey, LDAP, PAPI, Radius). Available as `services.simplesamlphp`. - `systemd`'s `gateway`, `upload`, and `remote` services, which provide ways of sending journals across the network. Enable using [services.journald.gateway](#opt-services.journald.gateway.enable), [services.journald.upload](#opt-services.journald.upload.enable), and [services.journald.remote](#opt-services.journald.remote.enable). diff --git a/nixos/doc/manual/release-notes/rl-2505.section.md b/nixos/doc/manual/release-notes/rl-2505.section.md index 421e363b2260..869eb3f0fda5 100644 --- a/nixos/doc/manual/release-notes/rl-2505.section.md +++ b/nixos/doc/manual/release-notes/rl-2505.section.md @@ -379,6 +379,8 @@ Alongside many enhancements to NixOS modules and general system improvements, th - `virtualisation.azure.agent` option provided by `azure-agent.nix` is replaced by `services.waagent`, and will be removed in a future release. +- Netdata removed support for non cloud deployments in version 2, so the `withCloud` option has been removed. + - The ZFS import service now respects `fileSystems.*.options = [ "noauto" ];` and does not add that pool's import service to `zfs-import.target`, meaning it will not be automatically imported at boot. - Default file names of images generated by several builders in `system.build` have been changed as outlined in the table below. diff --git a/nixos/doc/manual/release-notes/rl-2511.section.md b/nixos/doc/manual/release-notes/rl-2511.section.md index a030c95c8f8e..58e666ddc773 100644 --- a/nixos/doc/manual/release-notes/rl-2511.section.md +++ b/nixos/doc/manual/release-notes/rl-2511.section.md @@ -22,6 +22,14 @@ - COSMIC DE has been updated to the beta version, bringing it closer to its first stable release. This includes updates to its core components, applications, and overall stability. +- GNOME has been updated to version 49. + + - Removes X11 session support. Though you can still run X11 apps using XWayland. + - gnome-session’s custom service manager was removed in favour of using systemd. + - GDM now allows multiple seats, which is useful for e.g. remote logins. Though we currently [limit this to five greeter instances](https://github.com/NixOS/nixpkgs/issues/458058). + + Refer to the [GNOME release notes](https://release.gnome.org/49/) for more details. + ## New Modules {#sec-release-25.11-new-modules} @@ -30,9 +38,13 @@ - [Overseerr](https://overseerr.dev), a request management and media discovery tool for the Plex ecosystem. Available as [services.overseerr](#opt-services.overseerr.enable). +- [services.rsync](options.html#opt-services.rsync) has been added to simplify periodic directory syncing. + - [gtklock](https://github.com/jovanlanik/gtklock), a GTK-based lockscreen for Wayland. Available as [programs.gtklock](#opt-programs.gtklock.enable). - [Chrysalis](https://github.com/keyboardio/Chrysalis), a graphical configurator for Kaleidoscope-powered keyboards. Available as [programs.chrysalis](#opt-programs.chrysalis.enable). +- [wayvnc](https://github.com/any1/wayvnc), VNC server for wlroots based Wayland compositors. Available as [programs.wayvnc](#opt-programs.wayvnc.enable). + - [Pi-hole](https://pi-hole.net/), a DNS sinkhole for advertisements based on Dnsmasq. Available as [services.pihole-ftl](#opt-services.pihole-ftl.enable), and [services.pihole-web](#opt-services.pihole-web.enable) for the web GUI and API. - [Fediwall](https://fediwall.social), a web application for live displaying toots from mastodon, inspired by mastowall. Available as [services.fediwall](#opt-services.fediwall.enable). @@ -45,6 +57,8 @@ - [Homebridge](https://github.com/homebridge/homebridge), a lightweight Node.js server you can run on your home network that emulates the iOS HomeKit API. Available as [services.homebridge](#opt-services.homebridge.enable). +- [XPPen](https://www.xp-pen.com/), the official closed-source driver for XP Pen tablets. Available as [programs.xppen](#opt-programs.xppen.enable). + - [LACT](https://github.com/ilya-zlobintsev/LACT), a GPU monitoring and configuration tool, can now be enabled through [services.lact.enable](#opt-services.lact.enable). Note that for LACT to work properly on AMD GPU systems, you need to enable [hardware.amdgpu.overdrive.enable](#opt-hardware.amdgpu.overdrive.enable). @@ -78,6 +92,8 @@ - [Corteza](https://cortezaproject.org/), a low-code platform. Available as [services.corteza](#opt-services.corteza.enable). +- [Warpgate](https://warpgate.null.page), a SSH, HTTPS, MySQL and Postgres bastion. Available as [services.warpgate](#opt-services.warpgate.enable). Note that you need to run `warpgate recover-access` to recover builtin admin account, as the initialisation script uses a throwaway value to initialise its database. + - [TuneD](https://tuned-project.org/), a system tuning service for Linux. Available as [services.tuned](#opt-services.tuned.enable). - [yubikey-manager](https://github.com/Yubico/yubikey-manager), a tool for configuring YubiKey devices. Available as [programs.yubikey-manager](#opt-programs.yubikey-manager.enable). @@ -92,6 +108,8 @@ - [crowdsec](https://www.crowdsec.net/), a free, open-source and collaborative IPS. Available as [services.crowdsec](#opt-services.crowdsec.enable). +- [crowdsec-firewall-bouncer](https://www.crowdsec.net/), the CrowdSec Remediation Component for fetching new and old decisions from a CrowdSec API and adding them to a blocklist used by supported firewalls. Available as [services.crowdsec-firewall-bouncer](#opt-services.crowdsec-firewall-bouncer.enable). + - [tsidp](https://github.com/tailscale/tsidp), a simple OIDC / OAuth Identity Provider (IdP) server for your tailnet. Available as [services.tsidp](#opt-services.tsidp.enable). - [Newt](https://github.com/fosrl/newt), a fully user space WireGuard tunnel client and TCP/UDP proxy, designed to securely expose private resources controlled by Pangolin. Available as [services.newt](options.html#opt-services.newt.enable). @@ -112,6 +130,8 @@ - [ente](https://github.com/ente-io/ente), a service that provides a fully open source, end-to-end encrypted platform for photos and videos. Available as [services.ente.api](#opt-services.ente.api.enable) and [services.ente.web](#opt-services.ente.web.enable). +- [PairDrop](https://github.com/schlagmichdoch/pairdrop), a peer-to-peer file transfer web app. Available as [services.pairdrop](#opt-services.pairdrop.enable). + - [SuiteNumérique Docs](https://github.com/suitenumerique/docs), a collaborative note taking, wiki and documentation web platform and alternative to Notion or Outline. Available as [services.lasuite-docs](#opt-services.lasuite-docs.enable). - [dwl](https://codeberg.org/dwl/dwl), a compact, hackable compositor for Wayland based on wlroots. Available as [programs.dwl](#opt-programs.dwl.enable). @@ -144,6 +164,8 @@ - [KMinion](https://github.com/redpanda-data/kminion), feature-rich Prometheus exporter for Apache Kafka. Available as [services.prometheus.exporters.kafka](options.html#opt-services.prometheus.exporters.kafka). +- [Beszel](https://beszel.dev), a lightweight server monitoring hub with historical data, docker stats, and alerts. Available as [`services.beszel.agent`](options.html#opt-services.beszel.agent.enable) and [`services.beszel.hub`](options.html#opt-services.beszel.hub.enable). + - [Spoolman](https://github.com/Donkie/Spoolman), a inventory management system for Filament spools. Available as [services.spoolman](#opt-services.spoolman.enable). - [Temporal](https://temporal.io/), a durable execution platform that enables @@ -162,6 +184,8 @@ - [Tenstorrent](https://tenstorrent.com) hardware module has been added. +- [nixbit](https://github.com/pbek/nixbit), a GUI application for updating your NixOS system from a Nix Flakes Git repository. Available as [programs.nixbit](#opt-programs.nixbit.enable). + ## Backward Incompatibilities {#sec-release-25.11-incompatibilities} @@ -172,8 +196,15 @@ - `hardware.amdgpu.amdvlk` and the `amdvlk` package have been removed, as they have been deprecated by AMD. These have been replaced with the RADV driver from Mesa, which is enabled by default. +- Linux 5.4 and all its variants have been removed since mainline will reach its end of life within the support-span of 25.11. + - The `services.polipo` module has been removed as `polipo` is unmaintained and archived upstream. +- `boot.enableContainers` is only turned on when a declarative NixOS container is defined in `containers`. + If you use the `nixos-container` tool for imperative container management, set `boot.enableContainers = true;` explicitly. + +- `services.parsoid` and the `nodePackages.parsoid` package have been removed, as the JavaScript-based version this module uses is not compatible with modern MediaWiki versions. + - `virtualisation.lxd` has been removed due to lack of Nixpkgs maintenance. Users can migrate to `virtualisation.incus`, a fork of LXD, as a replacement. See [Incus migration documentation](https://linuxcontainers.org/incus/docs/main/howto/server_migrate_lxd/) for migration information. - `virtualisation.libvirtd` now uses OVMF images shipped with QEMU for UEFI machines. `virtualisation.libvirtd.qemu.ovmf` has been removed. @@ -232,10 +263,14 @@ - The `yeahwm` package and `services.xserver.windowManager.yeahwm` module were removed due to the package being broken and unmaintained upstream. +- `services.nixseparatedebuginfod.enable = true;` has been replaced by `services.nixseparatedebuginfod2.enable = true`. If you only use the official binary cache `https://cache.nixos.org` then no further configuration should be needed. If you have other https substituters, you can add them to `services.nixseparatedebuginfod2.subsituters`. SSH substituters are not supported by nixseparatedebuginfod2. Consider running nixseparatedebuginfod2 on the substituter instead, and pointing to it with the new option `environment.debuginfodServers`. + - The `services.snapserver` module has been migrated to use the settings option and render a configuration file instead of passing every option over the command line. - The `services.meilisearch` module now always defaults to the latest version of meilisearch, as the previous `meilisearch_1_11` package was removed. This is only an issue if you were using the old version. +- `services.journald.gateway.user` and `services.journald.gateway.system` now defaults to `false`. This new behaviour matches the default behaviour of the [`systemd-journal-gatewayd`](https://www.freedesktop.org/software/systemd/man/latest/systemd-journal-gatewayd.service.html) service itself. + - The `services.postgresql` module now sets up a systemd unit `postgresql.target`. Depending on `postgresql.target` guarantees that postgres is in read-write mode and initial/ensure scripts were executed. Depending on `postgresql.service` only guarantees a read-only connection. - The `services.mysql` module now restarts the database `on-abnormal`, which means that it now will be restarted in certain situations, it wasn't before. For example an OOM-kill. @@ -244,12 +279,20 @@ - The `services.siproxd` module has been removed as `siproxd` is unmaintained and broken with libosip 5.x. +- The `services.postfixadmin` module has been removed due to a lack of active maintainers. + - `services.tor.torsocks.enable` no longer defaults to true if Tor and Tor client functionality is enabled. - `netbox-manage` script created by the `netbox` module no longer uses `sudo -u netbox` internally. It can be run as root and will change it's user to `netbox` using `runuser` - `services.gateone` has been removed as the package was removed such that it does not work. +- `services.quorum` has been removed as the `quorum` package was broken and abandoned upstream. + +- `teleport` has been upgraded from major version 17 to major version 18. +Refer to [upstream upgrade instructions](https://goteleport.com/docs/upgrading/overview/) +and [release notes for v18](https://goteleport.com/docs/changelog/#1800-070325). + - `services.dwm-status.extraConfig` was replaced by [RFC0042](https://github.com/NixOS/rfcs/blob/master/rfcs/0042-config-option.md)-compliant [](#opt-services.dwm-status.settings), which is used to generate the config file. `services.dwm-status.order` is now moved to [](#opt-services.dwm-status.settings.order), as it's a part of the config file. - `gitversion` was updated to 6.3.0, which includes a number of breaking changes, old configurations may need updating or they will cause the tool to fail to run. @@ -286,6 +329,8 @@ - `vmalert` now supports multiple instances with the option `services.vmalert.instances."".enable` +- [`virtualisation.waydroid.package`](#opt-virtualisation.waydroid.package) now defaults to `waydroid-nftables` on systems with nftables enabled. + - [`services.victorialogs.package`](#opt-services.victorialogs.package) now defaults to `victorialogs`, as `victoriametrics` no longer contains the VictoriaLogs binaries. - The `services.traccar.settings` attribute has been reworked. Instead of the previous flat attribute set the new implementation uses nested attribute sets. You need to update you configuration manually. For instance, `services.traccar.settings.loggerConsole` becomes `services.traccar.settings.logger.console`. @@ -294,6 +339,8 @@ - [private-gpt](https://github.com/zylon-ai/private-gpt) service has been removed by lack of maintenance upstream. +- The `asterisk-lts` package was changed to v22 from v18. The default `asterisk` package was changed to v22 from v20. Asterisk version 18 has been dropped due to being EOL. The `asterisk-stable` (v20) package was unchanged. You may need to update /var/lib/asterisk to match the template files in `${asterisk-...}/var/lib/asterisk`. + - NixOS display manager modules now strictly use tty1, where many of them previously used tty7. Options to configure display managers' VT have been dropped. A configuration with a display manager enabled will not start `getty@tty1.service`, even if the system is forced to boot into `multi-user.target` instead of `graphical.target`. - `river` 0.3.x has been renamed to `river-classic` upstream, and the package renamed accordingly. `programs.river` has been renamed to `programs.river-classic`. @@ -302,6 +349,8 @@ - The systemd target `kbrequest.target` is now unset by default, instead of being forcibly symlinked to `rescue.target`. In case you were relying on this behavior (Alt + ArrowUp on the tty causing the current target to be changed to `rescue.target`), you can restore it by setting `systemd.targets.rescue.aliases = [ "kbrequest.target" ];` in your configuration. +- `miniflux` no longer uses the hstore PostgreSQL extension. Having the extension would prevent Miniflux from starting. In case you are managing your `miniflux` PostgreSQL database externally, disable the extension with `DROP EXTENSION IF EXISTS hstore;`. + ## Other Notable Changes {#sec-release-25.11-notable-changes} @@ -325,6 +374,8 @@ - `services.dnscrypt-proxy` gains a `package` option to specify dnscrypt-proxy package to use. +- `boot.plymouth` now has a [`package`](#opt-boot.plymouth.package) option to specify the package used in the module. + - `services.limesurvey` now supports nginx as reverse-proxy. Available through [services.limesurvey.webserver](#opt-services.limesurvey.webserver). - `services.nextcloud.configureRedis` now defaults to `true` in accordance with upstream recommendations to have caching for file locking. See the [upstream doc](https://docs.nextcloud.com/server/31/admin_manual/configuration_files/files_locking_transactional.html) for further details. @@ -342,10 +393,16 @@ - Due to [deprecation of gnome-session X11 support](https://blogs.gnome.org/alatiera/2025/06/08/the-x11-session-removal/), `services.desktopManager.pantheon` now defaults to pantheon-wayland session. The X11 session has been removed, see [this issue](https://github.com/elementary/session-settings/issues/91) for details. -- `bcachefs` file systems will now use the out-of-tree module for supported kernels. The in-tree module is unmaintained and users are strongly recommended to switch to kernels that support the out-of-tree module. +- `bcachefs` file systems will now use the out-of-tree module for supported kernels. The in-tree module has been removed, and users will need to switch to kernels that support the out-of-tree module. + +- `services.filesender` and the package `filesender` have been removed because they depend on `simplesamlphp`. - `services.gitea` supports sending notifications with sendmail again. To do this, activate the parameter `services.gitea.mailerUseSendmail` and configure SMTP server. +- `services.mattermost` has been updated to use the 10.11 ESR instead of 10.5. While this shouldn't break anyone, we also now package Mattermost 11 as mattermostLatest. Note that Mattermost 11 drops support for MySQL. The Mattermost module will assertion fail if you try to use MySQL with Mattermost 11; support for using MySQL with Mattermost will fully be removed in NixOS 26. + +- `simplesamlphp` has been removed since the package was severely outdated, unmaintained in nixpkgs and having known vulnerabilities. + - `networking.wireless.networks.` now has an option to specify SSID, hence allowing duplicated SSID setup. The BSSID option is added along side with this. - Revamp of the ACME certificate acquisication and renewal process to help scale systems with lots (100+) of certificates. @@ -399,6 +456,8 @@ - `services.xserver.desktopManager.deepin` and associated packages have been removed due to being unmaintained. See issue [#422090](https://github.com/NixOS/nixpkgs/issues/422090) for more details. +- `services.matter-server` now hosts a debug dashboard on the configured port. Open the port on the firewall with `services.matter-server.openFirewall`. + - The new option [networking.ipips](#opt-networking.ipips) has been added to create IP within IP kind of tunnels (including 4in6, ip6ip6 and ipip). With the existing [networking.sits](#opt-networking.sits) option (6in4), it is now possible to create all combinations of IPv4 and IPv6 encapsulation. @@ -429,3 +488,5 @@ - The `open-webui` package's postgres support have been moved to optional dependencies to comply with upstream changes in 0.6.26. - `prl-tools` has been moved out of `linuxPackages` because Parallels Guest Tools become driverless since 26.1.0. + +- `services.opentelemetry-collector` has a new option `validateConfigFile` option that checks the configuration file during build. It is enabled by default if the configuration file is in the Nix store. diff --git a/nixos/lib/testing/driver.nix b/nixos/lib/testing/driver.nix index 6abfac7b3191..9eb7f8b7e3e8 100644 --- a/nixos/lib/testing/driver.nix +++ b/nixos/lib/testing/driver.nix @@ -202,7 +202,7 @@ in _module.args = { hostPkgs = # Comment is in nixos/modules/misc/nixpkgs.nix - lib.mkOverride lib.modules.defaultOverridePriority config.hostPkgs.__splicedPackages; + lib.mkOverride lib.modules.defaultOverridePriority config.hostPkgs; }; driver = withChecks driver; diff --git a/nixos/modules/config/getaddrinfo.nix b/nixos/modules/config/getaddrinfo.nix index f18651a9e031..ddea509bfa78 100644 --- a/nixos/modules/config/getaddrinfo.nix +++ b/nixos/modules/config/getaddrinfo.nix @@ -18,7 +18,7 @@ let [ "# Generated by NixOS module networking.getaddrinfo" "# Do not edit manually!" - "reload ${if cfg.reload then "yes" else "no"}" + "reload ${lib.boolToYesNo cfg.reload}" ] ++ formatTableEntries "label" cfg.label ++ formatTableEntries "precedence" cfg.precedence diff --git a/nixos/modules/config/i18n.nix b/nixos/modules/config/i18n.nix index 1e6c35a4ea31..196160ee481a 100644 --- a/nixos/modules/config/i18n.nix +++ b/nixos/modules/config/i18n.nix @@ -12,7 +12,7 @@ let ] ++ lib.pipe config.i18n.extraLocaleSettings [ # See description of extraLocaleSettings for why is this ignored here. - (lib.filterAttrs (n: v: n != "LANGUAGE")) + (x: lib.removeAttrs x [ "LANGUAGE" ]) (lib.mapAttrs (n: v: (sanitizeUTF8Capitalization v))) (lib.mapAttrsToList (LCRole: lang: lang + "/" + (config.i18n.localeCharsets.${LCRole} or "UTF-8"))) ] @@ -30,12 +30,12 @@ in glibcLocales = lib.mkOption { type = lib.types.path; default = pkgs.glibcLocales.override { - allLocales = lib.any (x: x == "all") config.i18n.supportedLocales; + allLocales = lib.elem "all" config.i18n.supportedLocales; locales = config.i18n.supportedLocales; }; defaultText = lib.literalExpression '' pkgs.glibcLocales.override { - allLocales = lib.any (x: x == "all") config.i18n.supportedLocales; + allLocales = lib.elem "all" config.i18n.supportedLocales; locales = config.i18n.supportedLocales; } ''; @@ -149,7 +149,7 @@ in ( !( (lib.subtractLists config.i18n.supportedLocales aggregatedLocales) == [ ] - || lib.any (x: x == "all") config.i18n.supportedLocales + || lib.elem "all" config.i18n.supportedLocales ) ) '' diff --git a/nixos/modules/config/users-groups.nix b/nixos/modules/config/users-groups.nix index 59f1b44483df..0399962418ad 100644 --- a/nixos/modules/config/users-groups.nix +++ b/nixos/modules/config/users-groups.nix @@ -30,7 +30,7 @@ let mapAttrs' mapAttrsToList match - mkAliasOptionModuleMD + mkAliasOptionModule mkDefault mkIf mkMerge @@ -96,8 +96,8 @@ let only one of {option}`hashedPassword`, {option}`password`, or {option}`hashedPasswordFile` will be set. - In a system where [](#opt-systemd.sysusers.enable) is `true`, typically - only one of {option}`initialPassword`, {option}`initialHashedPassword`, + In a system where [](#opt-systemd.sysusers.enable) or [](#opt-services.userborn.enable) is `true`, + typically only one of {option}`initialPassword`, {option}`initialHashedPassword`, or {option}`hashedPasswordFile` will be set. If the option {option}`users.mutableUsers` is true, the password defined @@ -377,7 +377,7 @@ let hashedPasswordFile = mkOption { type = with types; nullOr str; - default = cfg.users.${name}.passwordFile; + default = config.passwordFile; defaultText = literalExpression "null"; description = '' The full path to a file that contains the hash of the user's @@ -666,8 +666,8 @@ let in { imports = [ - (mkAliasOptionModuleMD [ "users" "extraUsers" ] [ "users" "users" ]) - (mkAliasOptionModuleMD [ "users" "extraGroups" ] [ "users" "groups" ]) + (mkAliasOptionModule [ "users" "extraUsers" ] [ "users" "users" ]) + (mkAliasOptionModule [ "users" "extraGroups" ] [ "users" "groups" ]) (mkRenamedOptionModule [ "security" "initialRootPassword" ] [ "users" "users" "root" "initialHashedPassword" ] @@ -871,10 +871,11 @@ in render.gid = ids.gids.render; sgx.gid = ids.gids.sgx; shadow.gid = ids.gids.shadow; + clock.gid = ids.gids.clock; }; system.activationScripts.users = - if !config.systemd.sysusers.enable then + if !config.systemd.sysusers.enable && !config.services.userborn.enable then { supportsDryActivation = true; text = '' @@ -925,7 +926,7 @@ in # This does not work when the users and groups are created by # systemd-sysusers because the users are created too late then. system.activationScripts.hashes = - if !config.systemd.sysusers.enable then + if !config.systemd.sysusers.enable && !config.services.userborn.enable then { deps = [ "users" ]; text = '' @@ -1033,6 +1034,7 @@ in cdrom = { }; tape = { }; kvm = { }; + clock = { }; }; }; diff --git a/nixos/modules/config/vte.nix b/nixos/modules/config/vte.nix index f7c639b627a0..75ac3bae4be3 100644 --- a/nixos/modules/config/vte.nix +++ b/nixos/modules/config/vte.nix @@ -9,7 +9,7 @@ let vteInitSnippet = '' # Show current working directory in VTE terminals window title. # Supports both bash and zsh, requires interactive shell. - . ${pkgs.vte.override { gtkVersion = null; }}/etc/profile.d/vte.sh + . ${pkgs.vte-gtk4}/etc/profile.d/vte.sh ''; in diff --git a/nixos/modules/config/xdg/mime.nix b/nixos/modules/config/xdg/mime.nix index 9fe91fb6896d..2b2905bb2f0c 100644 --- a/nixos/modules/config/xdg/mime.nix +++ b/nixos/modules/config/xdg/mime.nix @@ -13,7 +13,7 @@ in { meta = { - maintainers = lib.teams.freedesktop.members ++ (with lib.maintainers; [ figsoda ]); + maintainers = lib.teams.freedesktop.members ++ [ ]; }; options = { diff --git a/nixos/modules/hardware/facter/default.nix b/nixos/modules/hardware/facter/default.nix index 0d3163185b98..f3bd58443dc7 100644 --- a/nixos/modules/hardware/facter/default.nix +++ b/nixos/modules/hardware/facter/default.nix @@ -4,6 +4,15 @@ ... }: { + imports = [ + ./disk.nix + ./firmware.nix + ./keyboard.nix + ./networking + ./system.nix + ./virtualisation.nix + ]; + meta.maintainers = with lib.maintainers; [ mic92 ]; options.hardware.facter = with lib; { diff --git a/nixos/modules/hardware/facter/disk.nix b/nixos/modules/hardware/facter/disk.nix new file mode 100644 index 000000000000..4bb76f16366d --- /dev/null +++ b/nixos/modules/hardware/facter/disk.nix @@ -0,0 +1,28 @@ +{ lib, config, ... }: +let + facterLib = import ./lib.nix lib; + + inherit (config.hardware.facter) report; +in +{ + options.hardware.facter.detected.boot.disk.kernelModules = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = lib.uniqueStrings ( + facterLib.collectDrivers ( + # A disk might be attached. + (report.hardware.firewire_controller or [ ]) + # definitely important + ++ (report.hardware.disk or [ ]) + ++ (report.hardware.storage_controller or [ ]) + ) + ); + defaultText = "hardware dependent"; + description = '' + List of kernel modules that are needed to access the disk. + ''; + }; + + config = { + boot.initrd.availableKernelModules = config.hardware.facter.detected.boot.disk.kernelModules; + }; +} diff --git a/nixos/modules/hardware/facter/firmware.nix b/nixos/modules/hardware/facter/firmware.nix new file mode 100644 index 000000000000..10962018890c --- /dev/null +++ b/nixos/modules/hardware/facter/firmware.nix @@ -0,0 +1,24 @@ +{ lib, config, ... }: +let + facterLib = import ./lib.nix lib; + + inherit (config.hardware.facter) report; + isBaremetal = config.hardware.facter.detected.virtualisation.none.enable; + hasAmdCpu = facterLib.hasAmdCpu report; + hasIntelCpu = facterLib.hasIntelCpu report; +in +{ + config = lib.mkIf isBaremetal { + # none (e.g. bare-metal) + # provide firmware for devices that might not have been detected by nixos-facter + hardware.enableRedistributableFirmware = lib.mkDefault true; + + # update microcode + hardware.cpu.amd.updateMicrocode = lib.mkIf hasAmdCpu ( + lib.mkDefault config.hardware.enableRedistributableFirmware + ); + hardware.cpu.intel.updateMicrocode = lib.mkIf hasIntelCpu ( + lib.mkDefault config.hardware.enableRedistributableFirmware + ); + }; +} diff --git a/nixos/modules/hardware/facter/keyboard.nix b/nixos/modules/hardware/facter/keyboard.nix new file mode 100644 index 000000000000..d19e17cd6901 --- /dev/null +++ b/nixos/modules/hardware/facter/keyboard.nix @@ -0,0 +1,21 @@ +{ lib, config, ... }: +let + facterLib = import ./lib.nix lib; + + inherit (config.hardware.facter) report; +in +{ + options.hardware.facter.detected.boot.keyboard.kernelModules = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = lib.uniqueStrings (facterLib.collectDrivers (report.hardware.usb_controller or [ ])); + defaultText = "hardware dependent"; + example = [ "usbhid" ]; + description = '' + List of kernel modules to include in the initrd to support the keyboard. + ''; + }; + + config = { + boot.initrd.availableKernelModules = config.hardware.facter.detected.boot.keyboard.kernelModules; + }; +} diff --git a/nixos/modules/hardware/facter/lib.nix b/nixos/modules/hardware/facter/lib.nix new file mode 100644 index 000000000000..099254cbce8d --- /dev/null +++ b/nixos/modules/hardware/facter/lib.nix @@ -0,0 +1,59 @@ +# Internal library functions for hardware.facter modules +# Eventually we can think about moving this under lib/ +# These are facter-specific helpers for querying nixos-facter reports +lib: +let + + inherit (lib) assertMsg; + + # Query if a facter report contains a CPU with the given vendor name + hasCpu = + name: + { + hardware ? { }, + ... + }: + let + cpus = hardware.cpu or [ ]; + in + assert assertMsg (hardware != { }) "no hardware entries found in the report"; + assert assertMsg (cpus != [ ]) "no cpu entries found in the report"; + builtins.any ( + { + vendor_name ? null, + ... + }: + assert assertMsg (vendor_name != null) "detail.vendor_name not found in cpu entry"; + vendor_name == name + ) cpus; + + # Extract all driver_modules from a list of hardware entries + collectDrivers = list: lib.catAttrs "driver_modules" list; + + # Convert number to zero-padded 4-digit hex string (for USB device IDs) + toZeroPaddedHex = + n: + let + hex = lib.toHexString n; + len = builtins.stringLength hex; + in + if len == 1 then + "000${hex}" + else if len == 2 then + "00${hex}" + else if len == 3 then + "0${hex}" + else + hex; +in +{ + inherit + hasCpu + collectDrivers + toZeroPaddedHex + ; + + hasAmdCpu = hasCpu "AuthenticAMD"; + hasIntelCpu = hasCpu "GenuineIntel"; + +} diff --git a/nixos/modules/hardware/facter/networking/default.nix b/nixos/modules/hardware/facter/networking/default.nix new file mode 100644 index 000000000000..dfbc54c8396d --- /dev/null +++ b/nixos/modules/hardware/facter/networking/default.nix @@ -0,0 +1,69 @@ +{ config, lib, ... }: +let + # Filter network interfaces from facter report to only those suitable for DHCP + physicalInterfaces = lib.filter ( + iface: + # Only include network interfaces suitable for DHCP: + # - Ethernet (most common) + # - WLAN (WiFi) + # - USB-Link (USB network adapters, tethering) + # - Network Interface (generic/unknown type) + # This implicitly excludes: Loopback, mainframe-specific interfaces (CTC, IUCV, HSI, ESCON) + # See: https://github.com/numtide/hwinfo/blob/ea251a74b88dcd53aebdd381194ab43d10fbbd79/src/ids/src/class#L817-L874 + let + validTypes = [ + "Ethernet" + "WLAN" + "USB-Link" + "Network Interface" + ]; + in + lib.elem (iface.sub_class.name or "") validTypes + ) (config.hardware.facter.report.hardware.network_interface or [ ]); + + # Extract interface names from unix_device_names + detectedInterfaceNames = lib.concatMap (iface: iface.unix_device_names or [ ]) physicalInterfaces; + + # Get the interface names from the configuration (which defaults to detectedInterfaceNames) + interfaceNames = config.hardware.facter.detected.dhcp.interfaces; + + # Generate per-interface DHCP config + perInterfaceConfig = lib.listToAttrs ( + lib.map (name: { + inherit name; + value = { + useDHCP = lib.mkDefault true; + }; + }) interfaceNames + ); +in +{ + imports = [ + ./initrd.nix + ./intel.nix + ]; + + options.hardware.facter.detected.dhcp = { + enable = lib.mkEnableOption "Facter dhcp module" // { + default = builtins.length config.hardware.facter.report.hardware.network_interface or [ ] > 0; + defaultText = "hardware dependent"; + }; + + interfaces = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = detectedInterfaceNames; + defaultText = lib.literalExpression "automatically detected from facter report"; + description = "List of network interface names to configure with DHCP. Defaults to auto-detected physical interfaces."; + example = [ + "eth0" + "wlan0" + ]; + }; + }; + config = lib.mkIf config.hardware.facter.detected.dhcp.enable { + networking.useDHCP = lib.mkDefault true; + + # Per-interface DHCP configuration + networking.interfaces = perInterfaceConfig; + }; +} diff --git a/nixos/modules/hardware/facter/networking/initrd.nix b/nixos/modules/hardware/facter/networking/initrd.nix new file mode 100644 index 000000000000..56be802b7cd9 --- /dev/null +++ b/nixos/modules/hardware/facter/networking/initrd.nix @@ -0,0 +1,20 @@ +{ lib, config, ... }: +let + facterLib = import ../lib.nix lib; + + inherit (config.hardware.facter) report; +in +{ + options.hardware.facter.detected.boot.initrd.networking.kernelModules = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = lib.uniqueStrings (facterLib.collectDrivers (report.hardware.network_controller or [ ])); + defaultText = "hardware dependent"; + description = '' + List of kernel modules to include in the initrd to support networking. + ''; + }; + + config = lib.mkIf config.boot.initrd.network.enable { + boot.initrd.kernelModules = config.hardware.facter.detected.boot.initrd.networking.kernelModules; + }; +} diff --git a/nixos/modules/hardware/facter/networking/intel.nix b/nixos/modules/hardware/facter/networking/intel.nix new file mode 100644 index 000000000000..4ae693a3c636 --- /dev/null +++ b/nixos/modules/hardware/facter/networking/intel.nix @@ -0,0 +1,57 @@ +{ lib, config, ... }: +let + inherit (config.hardware.facter) report; + cfg = config.hardware.facter.detected.networking.intel; +in +{ + options.hardware.facter.detected.networking.intel = with lib; { + _2200BG.enable = mkEnableOption "the Facter Intel 2200BG module" // { + + default = lib.any ( + { + vendor ? { }, + device ? { }, + ... + }: + # vendor (0x8086) Intel Corp. + (vendor.value or 0) == 32902 + && (lib.elem (device.value or 0) [ + 4163 # 0x1043 + 4175 # 0x104f + 16928 # 0x4220 + 16929 # 0x4221 + 16931 # 0x4223 + 16932 # 0x4224 + ]) + ) (report.hardware.network_controller or [ ]); + + defaultText = "hardware dependent"; + }; + _3945ABG.enable = mkEnableOption "the Facter Intel 3945ABG module" // { + + default = lib.any ( + { + vendor ? { }, + device ? { }, + ... + }: + # vendor (0x8086) Intel Corp. + (vendor.value or 0) == 32902 + && (lib.elem (device.value or 0) [ + 16937 # 0x4229 + 16938 # 0x4230 + 16930 # 0x4222 + 16935 # 0x4227 + ]) + ) (report.hardware.network_controller or [ ]); + + defaultText = "hardware dependent"; + }; + }; + + config = { + networking.enableIntel2200BGFirmware = lib.mkIf cfg._2200BG.enable (lib.mkDefault true); + hardware.enableRedistributableFirmware = lib.mkIf cfg._3945ABG.enable (lib.mkDefault true); + }; + +} diff --git a/nixos/modules/hardware/facter/system.nix b/nixos/modules/hardware/facter/system.nix new file mode 100644 index 000000000000..ef51b0e44f1d --- /dev/null +++ b/nixos/modules/hardware/facter/system.nix @@ -0,0 +1,15 @@ +{ + config, + options, + lib, + ... +}: +{ + # Skip setting hostPlatform if it's read-only + nixpkgs = + lib.optionalAttrs + (config.hardware.facter.report.system or null != null && !options.nixpkgs.hostPlatform.readOnly) + { + hostPlatform = lib.mkDefault config.hardware.facter.report.system; + }; +} diff --git a/nixos/modules/hardware/facter/virtualisation.nix b/nixos/modules/hardware/facter/virtualisation.nix new file mode 100644 index 000000000000..15cf6bab5aee --- /dev/null +++ b/nixos/modules/hardware/facter/virtualisation.nix @@ -0,0 +1,104 @@ +{ + lib, + config, + options, + ... +}: +let + inherit (config.hardware.facter) report; + cfg = config.hardware.facter.detected.virtualisation; +in +{ + options.hardware.facter.detected.virtualisation = { + virtio_scsi.enable = lib.mkEnableOption "Enable the Facter Virtualisation Virtio SCSI module" // { + default = lib.any ( + { vendor, device, ... }: + # vendor (0x1af4) Red Hat, Inc. + (vendor.value or 0) == 6900 + && + # device (0x1004, 0x1048) Virtio SCSI + (lib.elem (device.value or 0) [ + 4100 + 4168 + ]) + ) (report.hardware.scsi or [ ]); + defaultText = "hardware dependent"; + }; + oracle.enable = lib.mkEnableOption "Enable the Facter Virtualisation Oracle module" // { + default = report.virtualisation or null == "oracle"; + defaultText = "environment dependent"; + }; + parallels.enable = lib.mkEnableOption "Enable the Facter Virtualisation Parallels module" // { + default = report.virtualisation or null == "parallels"; + defaultText = "environment dependent"; + }; + qemu.enable = lib.mkEnableOption "Enable the Facter Virtualisation Qemu module" // { + default = builtins.elem (report.virtualisation or null) [ + "qemu" + "kvm" + "bochs" + ]; + defaultText = "environment dependent"; + }; + hyperv.enable = lib.mkEnableOption "Enable the Facter Virtualisation Hyper-V module" // { + default = report.virtualisation or null == "microsoft"; + defaultText = "environment dependent"; + }; + # no virtualisation detected + none.enable = lib.mkEnableOption "Enable the Facter Virtualisation None module" // { + default = report.virtualisation or null == "none"; + defaultText = "environment dependent"; + }; + }; + + config = { + + # KVM support + boot.kernelModules = + let + hasCPUFeature = + feature: lib.any ({ features, ... }: lib.elem feature features) (report.hardware.cpu or [ ]); + in + lib.mkMerge [ + (lib.mkIf (hasCPUFeature "vmx") [ "kvm-intel" ]) + (lib.mkIf (hasCPUFeature "svm") [ "kvm-amd" ]) + ]; + + # virtio & qemu + boot.initrd = { + kernelModules = lib.optionals cfg.qemu.enable [ + "virtio_balloon" + "virtio_console" + "virtio_rng" + "virtio_gpu" + ]; + + availableKernelModules = lib.mkMerge [ + (lib.mkIf cfg.qemu.enable [ + "virtio_net" + "virtio_pci" + "virtio_mmio" + "virtio_blk" + "9p" + "9pnet_virtio" + ]) + (lib.mkIf cfg.virtio_scsi.enable [ + "virtio_scsi" + ]) + ]; + }; + + virtualisation = { + # oracle + virtualbox.guest.enable = lib.mkIf cfg.oracle.enable (lib.mkDefault true); + # hyper-v + hypervGuest.enable = lib.mkIf cfg.hyperv.enable (lib.mkDefault true); + }; + + # parallels + hardware.parallels.enable = lib.mkIf cfg.parallels.enable (lib.mkDefault true); + nixpkgs.config = lib.mkIf (!options.nixpkgs.pkgs.isDefined && cfg.parallels.enable) { + allowUnfreePredicate = pkg: builtins.elem (lib.getName pkg) [ "prl-tools" ]; + }; + }; +} diff --git a/nixos/modules/hardware/keyboard/qmk.nix b/nixos/modules/hardware/keyboard/qmk.nix index 6690deca3506..b3fb02858b1d 100644 --- a/nixos/modules/hardware/keyboard/qmk.nix +++ b/nixos/modules/hardware/keyboard/qmk.nix @@ -8,15 +8,18 @@ let cfg = config.hardware.keyboard.qmk; inherit (lib) mkEnableOption mkIf; - in { options.hardware.keyboard.qmk = { enable = mkEnableOption "non-root access to the firmware of QMK keyboards"; + keychronSupport = mkEnableOption "udev rules for keychron QMK based keyboards"; }; config = mkIf cfg.enable { - services.udev.packages = [ pkgs.qmk-udev-rules ]; + services.udev.packages = [ + pkgs.qmk-udev-rules + ] + ++ lib.optionals cfg.keychronSupport [ pkgs.keychron-udev-rules ]; users.groups.plugdev = { }; }; } diff --git a/nixos/modules/hardware/printers.nix b/nixos/modules/hardware/printers.nix index 8dbfea78a516..23f656579fe6 100644 --- a/nixos/modules/hardware/printers.nix +++ b/nixos/modules/hardware/printers.nix @@ -10,7 +10,7 @@ let ensurePrinter = p: let - args = lib.cli.toGNUCommandLineShell { } ( + args = lib.cli.toCommandLineShellGNU { } ( { p = p.name; v = p.deviceUri; diff --git a/nixos/modules/image/repart.nix b/nixos/modules/image/repart.nix index 1f276590f9c2..8f892b96438b 100644 --- a/nixos/modules/image/repart.nix +++ b/nixos/modules/image/repart.nix @@ -223,7 +223,7 @@ in } repartConfig = { Type = "esp"; - Format = "fat"; + Format = "vfat"; }; }; "20-root" = { diff --git a/nixos/modules/installer/cd-dvd/iso-image.nix b/nixos/modules/installer/cd-dvd/iso-image.nix index 76a1517d9dae..60ba783b0466 100644 --- a/nixos/modules/installer/cd-dvd/iso-image.nix +++ b/nixos/modules/installer/cd-dvd/iso-image.nix @@ -459,6 +459,11 @@ let } fi ''} + ${lib.optionalString config.boot.loader.grub.memtest86.enable '' + menuentry 'Memtest86+' --class debug { + linux (\$root)/boot/memtest.bin ${toString config.boot.loader.grub.memtest86.params} + } + ''} menuentry 'Firmware Setup' --class settings { fwsetup clear diff --git a/nixos/modules/installer/cd-dvd/latest-kernel.nix b/nixos/modules/installer/cd-dvd/latest-kernel.nix index 53b9af38ba0b..20190ebd2531 100644 --- a/nixos/modules/installer/cd-dvd/latest-kernel.nix +++ b/nixos/modules/installer/cd-dvd/latest-kernel.nix @@ -2,6 +2,7 @@ { boot.kernelPackages = pkgs.linuxPackages_latest; boot.supportedFilesystems.zfs = false; + boot.supportedFilesystems.bcachefs = true; environment.etc."nixos-generate-config.conf".text = '' [Defaults] Kernel=latest diff --git a/nixos/modules/misc/ids.nix b/nixos/modules/misc/ids.nix index 949531d9a83c..b3cf6a063356 100644 --- a/nixos/modules/misc/ids.nix +++ b/nixos/modules/misc/ids.nix @@ -690,6 +690,7 @@ in rstudio-server = 324; localtimed = 325; automatic-timezoned = 326; + clock = 327; # When adding a gid, make sure it doesn't match an existing # uid. Users and groups with the same name should have equal diff --git a/nixos/modules/misc/locate.nix b/nixos/modules/misc/locate.nix index 092852330437..0980e6f385a2 100644 --- a/nixos/modules/misc/locate.nix +++ b/nixos/modules/misc/locate.nix @@ -241,7 +241,7 @@ in PRUNEFS="${lib.concatStringsSep " " cfg.pruneFS}" PRUNENAMES="${lib.concatStringsSep " " cfg.pruneNames}" PRUNEPATHS="${lib.concatStringsSep " " cfg.prunePaths}" - PRUNE_BIND_MOUNTS="${if cfg.pruneBindMounts then "yes" else "no"}" + PRUNE_BIND_MOUNTS="${lib.boolToYesNo cfg.pruneBindMounts}" ''; systemPackages = [ cfg.package ]; @@ -267,7 +267,7 @@ in '' exec ${cfg.package}/bin/updatedb \ --output ${toString cfg.output} ${lib.concatStringsSep " " args} \ - --prune-bind-mounts ${if cfg.pruneBindMounts then "yes" else "no"} \ + --prune-bind-mounts ${lib.boolToYesNo cfg.pruneBindMounts} \ ${lib.concatStringsSep " " cfg.extraFlags} ''; serviceConfig = { diff --git a/nixos/modules/misc/man-db.nix b/nixos/modules/misc/man-db.nix index dc6af4fe9692..50ae6d790789 100644 --- a/nixos/modules/misc/man-db.nix +++ b/nixos/modules/misc/man-db.nix @@ -82,6 +82,7 @@ in pkgs.runCommand "man-cache" { nativeBuildInputs = [ buildPackage ]; + preferLocalBuild = true; } '' echo "MANDB_MAP ${cfg.manualPages}/share/man $out" > man.conf diff --git a/nixos/modules/misc/nixpkgs.nix b/nixos/modules/misc/nixpkgs.nix index 07845a4ece8e..12b4a6453449 100644 --- a/nixos/modules/misc/nixpkgs.nix +++ b/nixos/modules/misc/nixpkgs.nix @@ -355,7 +355,7 @@ in # which is somewhat costly for Nixpkgs. With an explicit priority, we only # evaluate the wrapper to find out that the priority is lower, and then we # don't need to evaluate `finalPkgs`. - lib.mkOverride lib.modules.defaultOverridePriority finalPkgs.__splicedPackages; + lib.mkOverride lib.modules.defaultOverridePriority finalPkgs; }; assertions = diff --git a/nixos/modules/misc/nixpkgs/read-only.nix b/nixos/modules/misc/nixpkgs/read-only.nix index db43615c12f0..fa372d13e545 100644 --- a/nixos/modules/misc/nixpkgs/read-only.nix +++ b/nixos/modules/misc/nixpkgs/read-only.nix @@ -63,7 +63,7 @@ in # find mistaken definitions builtins.seq cfg.config builtins.seq cfg.overlays builtins.seq cfg.hostPlatform builtins.seq cfg.buildPlatform - cfg.pkgs.__splicedPackages; + cfg.pkgs; nixpkgs.config = cfg.pkgs.config; nixpkgs.overlays = cfg.pkgs.overlays; nixpkgs.hostPlatform = cfg.pkgs.stdenv.hostPlatform; diff --git a/nixos/modules/module-list.nix b/nixos/modules/module-list.nix index 871244a929c0..2c58f4e2d2e2 100644 --- a/nixos/modules/module-list.nix +++ b/nixos/modules/module-list.nix @@ -277,6 +277,7 @@ ./programs/nix-index.nix ./programs/nix-ld.nix ./programs/nix-required-mounts.nix + ./programs/nixbit.nix ./programs/nm-applet.nix ./programs/nncp.nix ./programs/noisetorch.nix @@ -352,6 +353,7 @@ ./programs/wayland/uwsm.nix ./programs/wayland/waybar.nix ./programs/wayland/wayfire.nix + ./programs/wayland/wayvnc.nix ./programs/weylus.nix ./programs/winbox.nix ./programs/wireshark.nix @@ -360,6 +362,7 @@ ./programs/xfconf.nix ./programs/xfs_quota.nix ./programs/xonsh.nix + ./programs/xppen.nix ./programs/xss-lock.nix ./programs/xwayland.nix ./programs/yazi.nix @@ -397,7 +400,6 @@ ./security/pam_mount.nix ./security/please.nix ./security/polkit.nix - ./security/rngd.nix ./security/rtkit.nix ./security/soteria.nix ./security/sudo-rs.nix @@ -567,6 +569,7 @@ ./services/desktops/gnome/gnome-online-miners.nix ./services/desktops/gnome/gnome-remote-desktop.nix ./services/desktops/gnome/gnome-settings-daemon.nix + ./services/desktops/gnome/gnome-software.nix ./services/desktops/gnome/gnome-user-share.nix ./services/desktops/gnome/localsearch.nix ./services/desktops/gnome/rygel.nix @@ -599,7 +602,6 @@ ./services/development/livebook.nix ./services/development/lorri.nix ./services/development/nixseparatedebuginfod2.nix - ./services/development/nixseparatedebuginfod.nix ./services/development/rstudio-server/default.nix ./services/development/vsmartcard-vpcd.nix ./services/development/zammad.nix @@ -857,6 +859,7 @@ ./services/misc/heisenbridge.nix ./services/misc/homepage-dashboard.nix ./services/misc/ihaskell.nix + ./services/misc/iio-niri.nix ./services/misc/input-remapper.nix ./services/misc/invidious-router.nix ./services/misc/irkerd.nix @@ -900,7 +903,6 @@ ./services/misc/packagekit.nix ./services/misc/paisa.nix ./services/misc/paperless.nix - ./services/misc/parsoid.nix ./services/misc/persistent-evdev.nix ./services/misc/pghero.nix ./services/misc/pinchflat.nix @@ -924,6 +926,7 @@ ./services/misc/rkvm.nix ./services/misc/rmfakecloud.nix ./services/misc/rshim.nix + ./services/misc/rsync.nix ./services/misc/safeeyes.nix ./services/misc/sdrplay.nix ./services/misc/servarr/lidarr.nix @@ -973,6 +976,8 @@ ./services/monitoring/apcupsd.nix ./services/monitoring/arbtt.nix ./services/monitoring/below.nix + ./services/monitoring/beszel-agent.nix + ./services/monitoring/beszel-hub.nix ./services/monitoring/bosun.nix ./services/monitoring/cadvisor.nix ./services/monitoring/certspotter.nix @@ -987,6 +992,7 @@ ./services/monitoring/gitwatch.nix ./services/monitoring/glances.nix ./services/monitoring/glpi-agent.nix + ./services/monitoring/go-csp-collector.nix ./services/monitoring/goss.nix ./services/monitoring/grafana-image-renderer.nix ./services/monitoring/grafana-reporter.nix @@ -1296,6 +1302,7 @@ ./services/networking/openconnect.nix ./services/networking/opengfw.nix ./services/networking/openvpn.nix + ./services/networking/opkssh/opkssh.nix ./services/networking/ostinato.nix ./services/networking/owamp.nix ./services/networking/pangolin.nix @@ -1313,7 +1320,6 @@ ./services/networking/pyload.nix ./services/networking/quassel.nix ./services/networking/quicktun.nix - ./services/networking/quorum.nix ./services/networking/r53-ddns.nix ./services/networking/radicale.nix ./services/networking/radvd.nix @@ -1454,6 +1460,7 @@ ./services/security/certmgr.nix ./services/security/cfssl.nix ./services/security/clamav.nix + ./services/security/crowdsec-firewall-bouncer.nix ./services/security/crowdsec.nix ./services/security/e-imzo.nix ./services/security/endlessh-go.nix @@ -1494,6 +1501,7 @@ ./services/security/vault-agent.nix ./services/security/vault.nix ./services/security/vaultwarden/default.nix + ./services/security/warpgate.nix ./services/security/yubikey-agent.nix ./services/system/automatic-timezoned.nix ./services/system/bpftune.nix @@ -1586,7 +1594,6 @@ ./services/web-apps/fediwall.nix ./services/web-apps/fider.nix ./services/web-apps/filebrowser.nix - ./services/web-apps/filesender.nix ./services/web-apps/firefly-iii-data-importer.nix ./services/web-apps/firefly-iii.nix ./services/web-apps/flarum.nix @@ -1634,6 +1641,7 @@ ./services/web-apps/lasuite-docs.nix ./services/web-apps/lasuite-meet.nix ./services/web-apps/lemmy.nix + ./services/web-apps/librespeed.nix ./services/web-apps/libretranslate.nix ./services/web-apps/limesurvey.nix ./services/web-apps/linkwarden.nix @@ -1671,6 +1679,7 @@ ./services/web-apps/openvscode-server.nix ./services/web-apps/openwebrx.nix ./services/web-apps/outline.nix + ./services/web-apps/pairdrop.nix ./services/web-apps/part-db.nix ./services/web-apps/peering-manager.nix ./services/web-apps/peertube-runner.nix @@ -1702,7 +1711,6 @@ ./services/web-apps/shiori.nix ./services/web-apps/sillytavern.nix ./services/web-apps/silverbullet.nix - ./services/web-apps/simplesamlphp.nix ./services/web-apps/slskd.nix ./services/web-apps/snipe-it.nix ./services/web-apps/snips-sh.nix diff --git a/nixos/modules/programs/_1password-gui.nix b/nixos/modules/programs/_1password-gui.nix index f840dbbe8a73..cc27e46fcc7d 100644 --- a/nixos/modules/programs/_1password-gui.nix +++ b/nixos/modules/programs/_1password-gui.nix @@ -6,9 +6,7 @@ }: let - cfg = config.programs._1password-gui; - in { imports = [ @@ -30,31 +28,32 @@ in ''; }; - package = lib.mkPackageOption pkgs "1Password GUI" { - default = [ "_1password-gui" ]; - }; + package = + lib.mkPackageOption pkgs "1Password GUI" { + default = [ "_1password-gui" ]; + } + // { + apply = + pkg: + pkg.override { + inherit (cfg) polkitPolicyOwners; + }; + }; }; }; - config = - let - package = cfg.package.override { - polkitPolicyOwners = cfg.polkitPolicyOwners; - }; - in - lib.mkIf cfg.enable { - environment.systemPackages = [ package ]; - users.groups.onepassword.gid = config.ids.gids.onepassword; + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + users.groups.onepassword.gid = config.ids.gids.onepassword; - security.wrappers = { - "1Password-BrowserSupport" = { - source = "${package}/share/1password/1Password-BrowserSupport"; - owner = "root"; - group = "onepassword"; - setuid = false; - setgid = true; - }; + security.wrappers = { + "1Password-BrowserSupport" = { + source = "${cfg.package}/share/1password/1Password-BrowserSupport"; + owner = "root"; + group = "onepassword"; + setuid = false; + setgid = true; }; - }; + }; } diff --git a/nixos/modules/programs/adb.nix b/nixos/modules/programs/adb.nix index 28182df9cc23..4ae2569049ed 100644 --- a/nixos/modules/programs/adb.nix +++ b/nixos/modules/programs/adb.nix @@ -16,8 +16,6 @@ type = lib.types.bool; description = '' Whether to configure system to use Android Debug Bridge (adb). - To grant access to a user, it must be part of adbusers group: - `users.users.alice.extraGroups = ["adbusers"];` ''; }; }; @@ -25,8 +23,6 @@ ###### implementation config = lib.mkIf config.programs.adb.enable { - services.udev.packages = [ pkgs.android-udev-rules ]; environment.systemPackages = [ pkgs.android-tools ]; - users.groups.adbusers = { }; }; } diff --git a/nixos/modules/programs/coolercontrol.nix b/nixos/modules/programs/coolercontrol.nix index 03aa774ad846..7103526d79b5 100644 --- a/nixos/modules/programs/coolercontrol.nix +++ b/nixos/modules/programs/coolercontrol.nix @@ -13,18 +13,16 @@ in options = { programs.coolercontrol = { enable = lib.mkEnableOption "CoolerControl GUI & its background services"; - - nvidiaSupport = lib.mkOption { - type = lib.types.bool; - default = lib.elem "nvidia" config.services.xserver.videoDrivers; - defaultText = lib.literalExpression "lib.elem \"nvidia\" config.services.xserver.videoDrivers"; - description = '' - Enable support for Nvidia GPUs. - ''; - }; }; }; + imports = [ + # Added 2025-10-25 + (lib.mkRemovedOptionModule [ "programs" "coolercontrol" "nvidiaSupport" ] '' + This option is deprecated as Nvidia drivers are automatically loaded at runtime. + '') + ]; + ##### implementation config = lib.mkIf cfg.enable ( lib.mkMerge [ @@ -36,29 +34,15 @@ in systemd = { packages = with pkgs.coolercontrol; [ - coolercontrol-liqctld coolercontrold ]; # https://github.com/NixOS/nixpkgs/issues/81138 services = { - coolercontrol-liqctld.wantedBy = [ "multi-user.target" ]; coolercontrold.wantedBy = [ "multi-user.target" ]; }; }; } - - # Nvidia support - (lib.mkIf cfg.nvidiaSupport { - systemd.services.coolercontrold.path = - let - nvidiaPkg = config.hardware.nvidia.package; - in - [ - nvidiaPkg # nvidia-smi - nvidiaPkg.settings # nvidia-settings - ]; - }) ] ); diff --git a/nixos/modules/programs/envision.nix b/nixos/modules/programs/envision.nix index 02f7ba5fdbeb..b31980f03eb8 100644 --- a/nixos/modules/programs/envision.nix +++ b/nixos/modules/programs/envision.nix @@ -34,7 +34,6 @@ in services.udev = { enable = true; packages = with pkgs; [ - android-udev-rules xr-hardware ]; }; diff --git a/nixos/modules/programs/git.nix b/nixos/modules/programs/git.nix index f9da88376ee9..e247ff1a7a33 100644 --- a/nixos/modules/programs/git.nix +++ b/nixos/modules/programs/git.nix @@ -115,5 +115,5 @@ in }) ]; - meta.maintainers = with lib.maintainers; [ figsoda ]; + meta.maintainers = [ ]; } diff --git a/nixos/modules/programs/kdeconnect.nix b/nixos/modules/programs/kdeconnect.nix index f51eeb9c6ced..c1029c46b4ce 100644 --- a/nixos/modules/programs/kdeconnect.nix +++ b/nixos/modules/programs/kdeconnect.nix @@ -16,6 +16,7 @@ implementation if you use Gnome ''; package = lib.mkPackageOption pkgs [ "kdePackages" "kdeconnect-kde" ] { + nullable = true; example = "gnomeExtensions.gsconnect"; }; }; @@ -24,7 +25,7 @@ cfg = config.programs.kdeconnect; in lib.mkIf cfg.enable { - environment.systemPackages = [ + environment.systemPackages = lib.optionals (cfg.package != null) [ cfg.package ]; networking.firewall = rec { diff --git a/nixos/modules/programs/nixbit.nix b/nixos/modules/programs/nixbit.nix new file mode 100644 index 000000000000..23bc5273409a --- /dev/null +++ b/nixos/modules/programs/nixbit.nix @@ -0,0 +1,49 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + inherit (lib) + mkEnableOption + mkIf + mkOption + mkPackageOption + types + ; + cfg = config.programs.nixbit; +in +{ + options.programs.nixbit = { + enable = mkEnableOption "Nixbit configuration"; + + package = mkPackageOption pkgs "nixbit" { }; + + repository = mkOption { + type = types.str; + description = "Git repository URL for Nixbit"; + }; + + forceAutostart = mkEnableOption "" // { + description = "Force creation of autostart desktop entry when application starts"; + }; + }; + + config = mkIf cfg.enable { + environment = { + systemPackages = [ cfg.package ]; + + etc."nixbit.conf".text = + lib.optionalString (cfg.repository != "") '' + [Repository] + Url = ${cfg.repository} + '' + + '' + [Autostart] + Force = ${if cfg.forceAutostart then "true" else "false"} + ''; + }; + }; +} diff --git a/nixos/modules/programs/pay-respects.nix b/nixos/modules/programs/pay-respects.nix index 71d5c8f0e51d..b8fc8e374936 100644 --- a/nixos/modules/programs/pay-respects.nix +++ b/nixos/modules/programs/pay-respects.nix @@ -16,7 +16,7 @@ let mkOption mkPackageOption optionalString - replaceChars + replaceStrings substring toLower types @@ -142,7 +142,7 @@ in description = "The model used by `pay-respects` to generate command corrections."; }; locale = mkOption { - default = toLower (replaceChars [ "_" ] [ "-" ] (substring 0 5 config.i18n.defaultLocale)); + default = toLower (replaceStrings [ "_" ] [ "-" ] (substring 0 5 config.i18n.defaultLocale)); example = "nl-be"; type = str; description = '' diff --git a/nixos/modules/programs/rust-motd.nix b/nixos/modules/programs/rust-motd.nix index 994b5a61fb66..40ff445a2f5e 100644 --- a/nixos/modules/programs/rust-motd.nix +++ b/nixos/modules/programs/rust-motd.nix @@ -113,7 +113,7 @@ in } ]; systemd.services.rust-motd = { - path = with pkgs; [ bash ]; + path = with pkgs; [ bash ] ++ lib.optional (cfg.settings.fail_2_ban or { } != { }) fail2ban; documentation = [ "https://github.com/rust-motd/rust-motd/blob/v${pkgs.rust-motd.version}/README.md" ]; diff --git a/nixos/modules/programs/sniffnet.nix b/nixos/modules/programs/sniffnet.nix index 36c298b84e72..91d56871dac6 100644 --- a/nixos/modules/programs/sniffnet.nix +++ b/nixos/modules/programs/sniffnet.nix @@ -25,5 +25,5 @@ in }; }; - meta.maintainers = with lib.maintainers; [ figsoda ]; + meta.maintainers = [ ]; } diff --git a/nixos/modules/programs/ssh.nix b/nixos/modules/programs/ssh.nix index 63d2bd865758..508d1961c770 100644 --- a/nixos/modules/programs/ssh.nix +++ b/nixos/modules/programs/ssh.nix @@ -339,37 +339,37 @@ in # SSH configuration. Slight duplication of the sshd_config # generation in the sshd service. - environment.etc."ssh/ssh_config".text = '' + environment.etc."ssh/ssh_config".text = lib.concatStringsSep "\n" ( # Custom options from `extraConfig`, to override generated options - ${cfg.extraConfig} - - # Generated options from other settings - Host * - ${lib.optionalString cfg.systemd-ssh-proxy.enable '' + lib.optional (cfg.extraConfig != "") cfg.extraConfig + ++ [ + '' + # Generated options from other settings + Host * + '' + ] + ++ lib.optional cfg.systemd-ssh-proxy.enable '' # See systemd-ssh-proxy(1) Include ${config.systemd.package}/lib/systemd/ssh_config.d/20-systemd-ssh-proxy.conf - ''} - - GlobalKnownHostsFile ${builtins.concatStringsSep " " knownHostsFiles} - - ${lib.optionalString (!config.networking.enableIPv6) "AddressFamily inet"} - ${lib.optionalString cfg.setXAuthLocation "XAuthLocation ${pkgs.xorg.xauth}/bin/xauth"} - ${lib.optionalString (cfg.forwardX11 != null) - "ForwardX11 ${if cfg.forwardX11 then "yes" else "no"}" - } - - ${lib.optionalString ( + '' + ++ [ + "GlobalKnownHostsFile ${builtins.concatStringsSep " " knownHostsFiles}" + ] + ++ lib.optional (!config.networking.enableIPv6) "AddressFamily inet" + ++ lib.optional cfg.setXAuthLocation "XAuthLocation ${pkgs.xorg.xauth}/bin/xauth" + ++ lib.optional (cfg.forwardX11 != null) "ForwardX11 ${lib.boolToYesNo cfg.forwardX11}" + ++ lib.optional ( cfg.pubkeyAcceptedKeyTypes != [ ] - ) "PubkeyAcceptedKeyTypes ${builtins.concatStringsSep "," cfg.pubkeyAcceptedKeyTypes}"} - ${lib.optionalString ( + ) "PubkeyAcceptedKeyTypes ${builtins.concatStringsSep "," cfg.pubkeyAcceptedKeyTypes}" + ++ lib.optional ( cfg.hostKeyAlgorithms != [ ] - ) "HostKeyAlgorithms ${builtins.concatStringsSep "," cfg.hostKeyAlgorithms}"} - ${lib.optionalString ( + ) "HostKeyAlgorithms ${builtins.concatStringsSep "," cfg.hostKeyAlgorithms}" + ++ lib.optional ( cfg.kexAlgorithms != null - ) "KexAlgorithms ${builtins.concatStringsSep "," cfg.kexAlgorithms}"} - ${lib.optionalString (cfg.ciphers != null) "Ciphers ${builtins.concatStringsSep "," cfg.ciphers}"} - ${lib.optionalString (cfg.macs != null) "MACs ${builtins.concatStringsSep "," cfg.macs}"} - ''; + ) "KexAlgorithms ${builtins.concatStringsSep "," cfg.kexAlgorithms}" + ++ lib.optional (cfg.ciphers != null) "Ciphers ${builtins.concatStringsSep "," cfg.ciphers}" + ++ lib.optional (cfg.macs != null) "MACs ${builtins.concatStringsSep "," cfg.macs}" + ); environment.etc."ssh/ssh_known_hosts".text = knownHostsText; diff --git a/nixos/modules/programs/steam.nix b/nixos/modules/programs/steam.nix index a8d1b7aefc70..5a791d0cea0f 100644 --- a/nixos/modules/programs/steam.nix +++ b/nixos/modules/programs/steam.nix @@ -256,7 +256,16 @@ in }) (lib.mkIf cfg.remotePlay.openFirewall { - allowedTCPPorts = [ 27036 ]; + # https://help.steampowered.com/en/faqs/view/3E3D-BE6B-787D-A5D2 + # https://help.steampowered.com/en/faqs/view/2EA8-4D75-DA21-31EB + allowedTCPPorts = [ + 27036 + 27037 + ]; + allowedUDPPorts = [ + 10400 + 10401 + ]; allowedUDPPortRanges = [ { from = 27031; diff --git a/nixos/modules/programs/trippy.nix b/nixos/modules/programs/trippy.nix index 6b906cb58f52..0de14f44cb22 100644 --- a/nixos/modules/programs/trippy.nix +++ b/nixos/modules/programs/trippy.nix @@ -25,5 +25,5 @@ in }; }; - meta.maintainers = with lib.maintainers; [ figsoda ]; + meta.maintainers = [ ]; } diff --git a/nixos/modules/programs/wayland/uwsm.nix b/nixos/modules/programs/wayland/uwsm.nix index cbabccb5d9c9..ee61c2ebad3e 100644 --- a/nixos/modules/programs/wayland/uwsm.nix +++ b/nixos/modules/programs/wayland/uwsm.nix @@ -16,7 +16,7 @@ let [Desktop Entry] Name=${opts.prettyName} (UWSM) Comment=${opts.comment} - Exec=${lib.getExe cfg.package} start -F ${opts.binPath} + Exec=${lib.getExe cfg.package} start -F -- ${opts.binPath} ${lib.strings.escapeShellArgs opts.extraArgs} Type=Application ''; destination = "/share/wayland-sessions/${opts.name}-uwsm.desktop"; @@ -84,6 +84,13 @@ in ''; example = "/run/current-system/sw/bin/ExampleCompositor"; }; + extraArgs = lib.mkOption { + type = with lib.types; listOf str; + default = [ ]; + description = '' + Extra command-line arguments pass to to the compsitor. + ''; + }; }; } ) @@ -117,7 +124,12 @@ in name: value: mk_uwsm_desktop_entry { inherit name; - inherit (value) prettyName comment binPath; + inherit (value) + prettyName + comment + binPath + extraArgs + ; } ) cfg.waylandCompositors; }; diff --git a/nixos/modules/programs/wayland/wayvnc.nix b/nixos/modules/programs/wayland/wayvnc.nix new file mode 100644 index 000000000000..0a19541c098d --- /dev/null +++ b/nixos/modules/programs/wayland/wayvnc.nix @@ -0,0 +1,25 @@ +{ + lib, + pkgs, + config, + ... +}: + +let + cfg = config.programs.wayvnc; +in +{ + options.programs.wayvnc = { + enable = lib.mkEnableOption "wayvnc, VNC server for wlroots based Wayland compositors"; + package = lib.mkPackageOption pkgs "wayvnc" { }; + }; + + config = lib.mkIf cfg.enable { + environment.systemPackages = [ cfg.package ]; + + # https://github.com/any1/wayvnc/blob/master/src/pam_auth.c + security.pam.services.wayvnc = { }; + }; + + meta.maintainers = with lib.maintainers; [ qusic ]; +} diff --git a/nixos/modules/programs/xppen.nix b/nixos/modules/programs/xppen.nix new file mode 100644 index 000000000000..e3ce1f7f314f --- /dev/null +++ b/nixos/modules/programs/xppen.nix @@ -0,0 +1,55 @@ +{ + config, + lib, + pkgs, + ... +}: + +let + cfg = config.programs.xppen; +in + +{ + options.programs.xppen = { + enable = lib.mkEnableOption "XPPen PenTablet application"; + package = lib.mkPackageOption pkgs "xppen_4" { + example = "pkgs.xppen_3"; + extraDescription = '' + Use xppen_4 for newer and xppen_3 for older tablets. + To check which version of the driver you need, go to + https://www.xp-pen.com/download/ then select your tablet + and look for the major version in the available files for Linux. + ''; + }; + }; + + config = lib.mkIf cfg.enable { + hardware.uinput.enable = true; + + environment.systemPackages = [ cfg.package ]; + + services.udev.packages = [ cfg.package ]; + + systemd.tmpfiles.rules = [ + "d /var/lib/pentablet/conf/xppen 0777 - - -" + ]; + + systemd.services.xppen-create-config-dir = { + restartTriggers = [ cfg.package ]; + wantedBy = [ "multi-user.target" ]; + serviceConfig = { + Type = "oneshot"; + TimeoutSec = 60; + ExecStart = pkgs.writeShellScript "xppen-create-config-dir" '' + readarray -d "" files < <(find ${cfg.package}/usr/lib/pentablet/conf -type f -print0) + for file in "''${files[@]}"; do + file_new="/var''${file#${cfg.package + "/usr"}}" + if [ ! -f $file_new ]; then + install -m 666 "''$file" "''$file_new" + fi + done + ''; + }; + }; + }; +} diff --git a/nixos/modules/programs/zoom-us.nix b/nixos/modules/programs/zoom-us.nix index 9d31c8e3086a..f1626849215b 100644 --- a/nixos/modules/programs/zoom-us.nix +++ b/nixos/modules/programs/zoom-us.nix @@ -17,7 +17,11 @@ # configuration elsewhere. config.programs.zoom-us.package.override (prev: { # Support pulseaudio if it's enabled on the system. - pulseaudioSupport = prev.pulseaudioSupport or config.services.pulseaudio.enable; + pulseaudioSupport = + prev.pulseaudioSupport or ( + config.services.pulseaudio.enable + || (config.services.pipewire.enable && config.services.pipewire.pulse.enable) + ); # Support Plasma 6 desktop environment if it's enabled on the system. plasma6XdgDesktopPortalSupport = diff --git a/nixos/modules/rename.nix b/nixos/modules/rename.nix index a4ed680bd552..d7759c232fea 100644 --- a/nixos/modules/rename.nix +++ b/nixos/modules/rename.nix @@ -2,7 +2,7 @@ let inherit (lib) - mkAliasOptionModuleMD + mkAliasOptionModule mkRemovedOptionModule ; in @@ -18,7 +18,7 @@ in # This alias module can't be where _module.check is defined because it would # be added to submodules as well there - (mkAliasOptionModuleMD [ "environment" "checkConfigurationOptions" ] [ "_module" "check" ]) + (mkAliasOptionModule [ "environment" "checkConfigurationOptions" ] [ "_module" "check" ]) # Completely removed modules (mkRemovedOptionModule [ "boot" "loader" "raspberryPi" ] @@ -228,9 +228,16 @@ in "services.morty has been removed from NixOS. As the morty package was unmaintained and removed and searxng, its main consumer, dropped support for it." ) (mkRemovedOptionModule [ "services" "mwlib" ] "The corresponding package was removed from nixpkgs.") + (mkRemovedOptionModule [ "services" "nixseparatedebuginfod" ] + "Use `services.nixseparatedebuginfod2.enable = true;` instead. If you only use the official binary cache, no additional configuration should be needed." + ) (mkRemovedOptionModule [ "services" "pantheon" "files" ] '' This module was removed, please add pkgs.pantheon.elementary-files to environment.systemPackages directly. '') + (mkRemovedOptionModule [ "services" "parsoid" ] '' + The Javascript version of Parsoid configured through this module does not work with modern MediaWiki versions, + and has been deprecated by upstream, so it has been removed. MediaWiki comes with a new PHP-based parser built-in, so there is no need for this module. + '') (mkRemovedOptionModule [ "services" "polipo" ] '' The polipo project is unmaintained and archived upstream. '') @@ -241,6 +248,9 @@ in "services" "quagga" ] "the corresponding package has been removed from nixpkgs") + (mkRemovedOptionModule [ "services" "quorum" ] '' + The corresponding package was broken, abandoned upstream and thus removed from nixpkgs. + '') (mkRemovedOptionModule [ "services" "railcar" @@ -401,10 +411,22 @@ in services.invoiceplane has been removed since the service only supported PHP 8.1 which is EOL and removed from nixpkgs. '') + (mkRemovedOptionModule [ "services" "filesender" ] '' + services.filesender has been removed since it depends on simplesamlphp which was severely unmaintained. + '') (mkRemovedOptionModule [ "services" "postfixadmin" ] '' services.postfixadmin has been removed since it was unmaintained in nixpkgs and the version available only supported PHP 8.1 which is EOL. '') + (mkRemovedOptionModule [ "services" "simplesamlphp" ] '' + services.simplesamlphp has been vulnerable and unmaintained in nixpkgs. + '') + (mkRemovedOptionModule [ "security" "rngd" ] '' + rngd is not necessary for any device that the kernel recognises + as an hardware RNG, as it will automatically run the krngd task + to periodically collect random data from the device and mix it + into the kernel's RNG. + '') # Do NOT add any option renames here, see top of the file ]; } diff --git a/nixos/modules/security/apparmor.nix b/nixos/modules/security/apparmor.nix index 5875d13bf786..d7e9ab7ab162 100644 --- a/nixos/modules/security/apparmor.nix +++ b/nixos/modules/security/apparmor.nix @@ -1,4 +1,5 @@ { + options, config, lib, pkgs, @@ -10,11 +11,6 @@ let cfg = config.security.apparmor; enabledPolicies = lib.filterAttrs (n: p: p.state != "disable") cfg.policies; buildPolicyPath = n: p: lib.defaultTo (pkgs.writeText n p.profile) p.path; - - # Accessing submodule options when not defined results in an error thunk rather than a regular option object - # We can emulate the behavior of `