Merge branch 'master' into init-spoolman-service
This commit is contained in:
+1
-2
@@ -23,8 +23,7 @@ insert_final_newline = false
|
||||
|
||||
# see https://nixos.org/nixpkgs/manual/#chap-conventions
|
||||
|
||||
# Match json/lockfiles/markdown/nix/perl/python/ruby/shell/docbook files, set indent to spaces
|
||||
[*.{bash,js,json,lock,md,nix,pl,pm,py,rb,sh,xml}]
|
||||
[*.{bash,css,js,json,lock,md,nix,pl,pm,py,rb,sh,xml}]
|
||||
indent_style = space
|
||||
|
||||
# Match docbook files, set indent width of one
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
name: Checkout
|
||||
|
||||
description: 'Checkout into trusted / untrusted / pinned folders consistently.'
|
||||
|
||||
inputs:
|
||||
merged-as-untrusted-at:
|
||||
description: "Whether and which SHA to checkout for the merge commit in the ./nixpkgs/untrusted folder."
|
||||
target-as-trusted-at:
|
||||
description: "Whether and which SHA to checkout for the target commit in the ./nixpkgs/trusted folder."
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
env:
|
||||
MERGED_SHA: ${{ inputs.merged-as-untrusted-at }}
|
||||
TARGET_SHA: ${{ inputs.target-as-trusted-at }}
|
||||
with:
|
||||
script: |
|
||||
const { spawn } = require('node:child_process')
|
||||
const { join } = require('node:path')
|
||||
|
||||
async function run(cmd, ...args) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const proc = spawn(cmd, args, {
|
||||
stdio: 'inherit'
|
||||
})
|
||||
proc.on('close', (code) => {
|
||||
if (code === 0) resolve()
|
||||
else reject(code)
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
// These are set automatically by the spare checkout for .github/actions.
|
||||
// Undo them, otherwise git fetch below will not do anything.
|
||||
await run('git', 'config', 'unset', 'remote.origin.promisor')
|
||||
await run('git', 'config', 'unset', 'remote.origin.partialclonefilter')
|
||||
|
||||
// Getting the pinned SHA via API allows us to do one single fetch call for all commits.
|
||||
// Otherwise we would have to fetch merged/target first, read pinned, fetch again.
|
||||
// A single fetch call comes with a lot less overhead. The fetch takes essentially the
|
||||
// same time no matter whether its 1, 2 or 3 commits at once.
|
||||
async function getPinnedSha(ref) {
|
||||
if (!ref) return undefined
|
||||
const { content, encoding } = (await github.rest.repos.getContent({
|
||||
...context.repo,
|
||||
path: 'ci/pinned.json',
|
||||
ref,
|
||||
})).data
|
||||
const pinned = JSON.parse(Buffer.from(content, encoding).toString())
|
||||
return pinned.pins.nixpkgs.revision
|
||||
}
|
||||
|
||||
const commits = [
|
||||
{
|
||||
sha: process.env.MERGED_SHA,
|
||||
path: 'untrusted',
|
||||
},
|
||||
{
|
||||
sha: await getPinnedSha(process.env.MERGED_SHA),
|
||||
path: 'untrusted-pinned'
|
||||
},
|
||||
{
|
||||
sha: process.env.TARGET_SHA,
|
||||
path: 'trusted',
|
||||
},
|
||||
{
|
||||
sha: await getPinnedSha(process.env.TARGET_SHA),
|
||||
path: 'trusted-pinned'
|
||||
}
|
||||
].filter(({ sha }) => Boolean(sha))
|
||||
|
||||
console.log('Checking out the following commits:', commits)
|
||||
|
||||
// Fetching all commits at once is much faster than doing multiple checkouts.
|
||||
// This would fail without --refetch, because the we had a partial clone before, but changed it above.
|
||||
await run('git', 'fetch', '--depth=1', '--refetch', 'origin', ...(commits.map(({ sha }) => sha)))
|
||||
|
||||
// Checking out onto tmpfs takes 1s and is faster by at least factor 10x.
|
||||
await run('mkdir', 'nixpkgs')
|
||||
switch (process.env.RUNNER_OS) {
|
||||
case 'macOS':
|
||||
await run('sudo', 'mount_tmpfs', 'nixpkgs')
|
||||
break
|
||||
case 'Linux':
|
||||
await run('sudo', 'mount', '-t', 'tmpfs', 'tmpfs', 'nixpkgs')
|
||||
break
|
||||
}
|
||||
|
||||
// Create all worktrees in parallel.
|
||||
await Promise.all(commits.map(async ({ sha, path }) => {
|
||||
await run('git', 'worktree', 'add', join('nixpkgs', path), sha, '--no-checkout')
|
||||
await run('git', '-C', join('nixpkgs', path), 'sparse-checkout', 'disable')
|
||||
await run('git', '-C', join('nixpkgs', path), 'checkout', '--progress')
|
||||
}))
|
||||
@@ -1,80 +0,0 @@
|
||||
name: Get merge commit
|
||||
|
||||
description: 'Checks whether the Pull Request is mergeable and checks out the repo at up to two commits: The result of a temporary merge of the head branch into the target branch ("merged"), and the parent of that commit on the target branch ("target"). Handles push events and merge conflicts gracefully.'
|
||||
|
||||
inputs:
|
||||
mergedSha:
|
||||
description: "The merge commit SHA, previously collected."
|
||||
type: string
|
||||
merged-as-untrusted:
|
||||
description: "Whether to checkout the merge commit in the ./untrusted folder."
|
||||
type: boolean
|
||||
pinnedFrom:
|
||||
description: "Whether to checkout the pinned nixpkgs for CI and from where (trusted, untrusted)."
|
||||
type: string
|
||||
targetSha:
|
||||
description: "The target commit SHA, previously collected."
|
||||
type: string
|
||||
target-as-trusted:
|
||||
description: "Whether to checkout the target commit in the ./trusted folder."
|
||||
type: boolean
|
||||
|
||||
outputs:
|
||||
mergedSha:
|
||||
description: "The merge commit SHA"
|
||||
value: ${{ steps.commits.outputs.mergedSha }}
|
||||
targetSha:
|
||||
description: "The target commit SHA"
|
||||
value: ${{ steps.commits.outputs.targetSha }}
|
||||
|
||||
runs:
|
||||
using: composite
|
||||
steps:
|
||||
- id: commits
|
||||
if: ${{ !inputs.mergedSha && !inputs.targetSha }}
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
require('./ci/github-script/prepare.js')({
|
||||
github,
|
||||
context,
|
||||
core,
|
||||
})
|
||||
|
||||
- if: inputs.merged-as-untrusted && (inputs.mergedSha || steps.commits.outputs.mergedSha)
|
||||
# Would be great to do the checkouts in git worktrees of the existing spare checkout instead,
|
||||
# but Nix is broken with them:
|
||||
# https://github.com/NixOS/nix/issues/6073
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
ref: ${{ inputs.mergedSha || steps.commits.outputs.mergedSha }}
|
||||
path: untrusted
|
||||
|
||||
- if: inputs.target-as-trusted && (inputs.targetSha || steps.commits.outputs.targetSha)
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
ref: ${{ inputs.targetSha || steps.commits.outputs.targetSha }}
|
||||
path: trusted
|
||||
|
||||
- if: inputs.pinnedFrom
|
||||
id: pinned
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
env:
|
||||
PINNED_FROM: ${{ inputs.pinnedFrom }}
|
||||
with:
|
||||
script: |
|
||||
const path = require('node:path')
|
||||
const pinned = require(path.resolve(path.join(process.env.PINNED_FROM, 'ci', 'pinned.json')))
|
||||
core.setOutput('pinnedSha', pinned.pins.nixpkgs.revision)
|
||||
|
||||
- if: steps.pinned.outputs.pinnedSha
|
||||
uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
ref: ${{ steps.pinned.outputs.pinnedSha }}
|
||||
path: pinned
|
||||
sparse-checkout: |
|
||||
lib
|
||||
maintainers
|
||||
nixos/lib
|
||||
pkgs
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
- any:
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- .github/actions/*
|
||||
- .github/workflows/*
|
||||
- ci/**/*.*
|
||||
|
||||
|
||||
+3
-6
@@ -431,12 +431,9 @@
|
||||
- changed-files:
|
||||
- any-glob-to-any-file:
|
||||
- doc/languages-frameworks/qt.section.md
|
||||
- nixos/modules/services/x11/desktop-managers/plasma5.nix
|
||||
- nixos/tests/plasma5.nix
|
||||
- pkgs/applications/kde/**/*
|
||||
- pkgs/desktops/plasma-5/**/*
|
||||
- pkgs/development/libraries/kde-frameworks/**/*
|
||||
- pkgs/development/libraries/qt-5/**/*
|
||||
- nixos/modules/services/desktop-managers/plasma6.nix
|
||||
- nixos/tests/plasma6.nix
|
||||
- pkgs/kde/**/*
|
||||
|
||||
"6.topic: R":
|
||||
- any:
|
||||
|
||||
@@ -17,7 +17,7 @@ Some architectural notes about key decisions and concepts in our workflows:
|
||||
This is a temporary commit that GitHub creates automatically as "what would happen, if this PR was merged into the base branch now?".
|
||||
The checkout could be done via the virtual branch `refs/pull/<pr-number>/merge`, but doing so would cause failures when this virtual branch doesn't exist (anymore).
|
||||
This can happen when the PR has conflicts, in which case the virtual branch is not created, or when the PR is getting merged while workflows are still running, in which case the branch won't exist anymore at the time of checkout.
|
||||
Thus, we use the `get-merge-commit.yml` workflow to check whether the PR is mergeable and the test merge commit exists and only then run the relevant jobs.
|
||||
Thus, we use the `prepare` job to check whether the PR is mergeable and the test merge commit exists and only then run the relevant jobs.
|
||||
|
||||
- Various workflows need to make comparisons against the base branch.
|
||||
In this case, we checkout the parent of the "test merge commit" for best results.
|
||||
|
||||
@@ -27,7 +27,7 @@ jobs:
|
||||
steps:
|
||||
# Use a GitHub App to create the PR so that CI gets triggered
|
||||
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
|
||||
- uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
|
||||
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
|
||||
- name: Create backport PRs
|
||||
id: backport
|
||||
uses: korthout/backport-action@0193454f0c5947491d348f33a275c119f30eb736 # v3.2.1
|
||||
uses: korthout/backport-action@ca4972adce8039ff995e618f5fc02d1b7961f27a # v3.3.0
|
||||
with:
|
||||
# Config README: https://github.com/korthout/backport-action#backport-action
|
||||
copy_labels_pattern: 'severity:\ssecurity'
|
||||
|
||||
+15
-15
@@ -47,12 +47,10 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
- name: Check if the PR can be merged and checkout the merge commit
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
- name: Checkout the merge commit
|
||||
uses: ./.github/actions/checkout
|
||||
with:
|
||||
mergedSha: ${{ inputs.mergedSha }}
|
||||
merged-as-untrusted: true
|
||||
pinnedFrom: untrusted
|
||||
merged-as-untrusted-at: ${{ inputs.mergedSha }}
|
||||
|
||||
- uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
with:
|
||||
@@ -61,37 +59,39 @@ jobs:
|
||||
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
with:
|
||||
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
|
||||
name: nixpkgs-ci
|
||||
authToken: "${{ secrets.CACHIX_AUTH_TOKEN }}"
|
||||
# The nixpkgs-ci cache should not be trusted or used outside of Nixpkgs and its forks' CI.
|
||||
name: ${{ vars.CACHIX_NAME || 'nixpkgs-ci' }}
|
||||
extraPullNames: nixpkgs-ci
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
pushFilter: '(-source$|-nixpkgs-tarball-)'
|
||||
|
||||
- run: nix-env --install -f pinned -A nix-build-uncached
|
||||
- run: nix-env --install -f nixpkgs/untrusted-pinned -A nix-build-uncached
|
||||
|
||||
- name: Build shell
|
||||
if: contains(matrix.builds, 'shell')
|
||||
run: echo "${{ matrix.systems }}" | xargs -n1 nix-build-uncached untrusted/ci --arg nixpkgs ./pinned -A shell --argstr system
|
||||
run: echo "${{ matrix.systems }}" | xargs -n1 nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A shell --argstr system
|
||||
|
||||
- name: Build NixOS manual
|
||||
if: |
|
||||
contains(matrix.builds, 'manual-nixos') && !cancelled() &&
|
||||
contains(fromJSON(inputs.baseBranch).type, 'primary')
|
||||
run: nix-build-uncached untrusted/ci --arg nixpkgs ./pinned -A manual-nixos --out-link nixos-manual
|
||||
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixos --out-link nixos-manual
|
||||
|
||||
- name: Build Nixpkgs manual
|
||||
if: contains(matrix.builds, 'manual-nixpkgs') && !cancelled()
|
||||
run: nix-build-uncached untrusted/ci --arg nixpkgs ./pinned -A manual-nixpkgs -A manual-nixpkgs-tests
|
||||
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixpkgs -A manual-nixpkgs-tests
|
||||
|
||||
- name: Build Nixpkgs manual tests
|
||||
if: contains(matrix.builds, 'manual-nixpkgs-tests') && !cancelled()
|
||||
run: nix-build-uncached untrusted/ci --arg nixpkgs ./pinned -A manual-nixpkgs-tests
|
||||
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A manual-nixpkgs-tests
|
||||
|
||||
- name: Build lib tests
|
||||
if: contains(matrix.builds, 'lib-tests') && !cancelled()
|
||||
run: nix-build-uncached untrusted/ci --arg nixpkgs ./pinned -A lib-tests
|
||||
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A lib-tests
|
||||
|
||||
- name: Build tarball
|
||||
if: contains(matrix.builds, 'tarball') && !cancelled()
|
||||
run: nix-build-uncached untrusted/ci --arg nixpkgs ./pinned -A tarball
|
||||
run: nix-build-uncached nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A tarball
|
||||
|
||||
- name: Upload NixOS manual
|
||||
if: |
|
||||
|
||||
+89
-19
@@ -9,6 +9,20 @@ on:
|
||||
headBranch:
|
||||
required: true
|
||||
type: string
|
||||
mergedSha:
|
||||
required: true
|
||||
type: string
|
||||
ownersCanFail:
|
||||
required: true
|
||||
type: boolean
|
||||
targetSha:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN:
|
||||
required: true
|
||||
OWNER_RO_APP_PRIVATE_KEY:
|
||||
required: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -17,24 +31,7 @@ defaults:
|
||||
shell: bash
|
||||
|
||||
jobs:
|
||||
no-channel-base:
|
||||
name: no channel base
|
||||
if: contains(fromJSON(inputs.baseBranch).type, 'channel')
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- run: |
|
||||
cat <<EOF
|
||||
The nixos-* and nixpkgs-* branches are pushed to by the channel
|
||||
release script and should not be merged into directly.
|
||||
|
||||
Please target the equivalent release-* branch or master instead.
|
||||
EOF
|
||||
exit 1
|
||||
|
||||
cherry-pick:
|
||||
if: |
|
||||
github.event_name == 'pull_request' ||
|
||||
(fromJSON(inputs.baseBranch).stable && !contains(fromJSON(inputs.headBranch).type, 'development'))
|
||||
commits:
|
||||
permissions:
|
||||
pull-requests: write
|
||||
runs-on: ubuntu-24.04-arm
|
||||
@@ -54,19 +51,92 @@ jobs:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
- name: Check cherry-picks
|
||||
- name: Check commits
|
||||
id: check
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
env:
|
||||
TARGETS_STABLE: ${{ fromJSON(inputs.baseBranch).stable && !contains(fromJSON(inputs.headBranch).type, 'development') }}
|
||||
with:
|
||||
script: |
|
||||
const targetsStable = JSON.parse(process.env.TARGETS_STABLE)
|
||||
require('./trusted/ci/github-script/commits.js')({
|
||||
github,
|
||||
context,
|
||||
core,
|
||||
dry: context.eventName == 'pull_request',
|
||||
cherryPicks: context.eventName == 'pull_request' || targetsStable,
|
||||
})
|
||||
|
||||
- name: Log current API rate limits
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
# For checking code owners, this job depends on a GitHub App with the following permissions:
|
||||
# - Permissions:
|
||||
# - Repository > Administration: read-only
|
||||
# - Organization > Members: read-only
|
||||
# - Install App on this repository, setting these variables:
|
||||
# - OWNER_RO_APP_ID (variable)
|
||||
# - OWNER_RO_APP_PRIVATE_KEY (secret)
|
||||
#
|
||||
# This should not use the same app as the job to request reviewers, because this job requires
|
||||
# handling untrusted PR input.
|
||||
owners:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
continue-on-error: ${{ inputs.ownersCanFail }}
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
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@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
with:
|
||||
# The nixpkgs-ci cache should not be trusted or used outside of Nixpkgs and its forks' CI.
|
||||
name: ${{ vars.CACHIX_NAME || 'nixpkgs-ci' }}
|
||||
extraPullNames: nixpkgs-ci
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
pushFilter: -source$
|
||||
|
||||
- name: Build codeowners validator
|
||||
run: nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A codeownersValidator
|
||||
|
||||
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
if: github.event_name == 'pull_request_target' && vars.OWNER_RO_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.OWNER_RO_APP_ID }}
|
||||
private-key: ${{ secrets.OWNER_RO_APP_PRIVATE_KEY }}
|
||||
permission-administration: read
|
||||
permission-members: read
|
||||
|
||||
- name: Log current API rate limits
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
- name: Validate codeowners
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
OWNERS_FILE: nixpkgs/untrusted/ci/OWNERS
|
||||
GITHUB_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
REPOSITORY_PATH: nixpkgs/untrusted
|
||||
OWNER_CHECKER_REPOSITORY: ${{ github.repository }}
|
||||
# Set this to "notowned,avoid-shadowing" to check that all files are owned by somebody
|
||||
EXPERIMENTAL_CHECKS: "avoid-shadowing"
|
||||
run: result/bin/codeowners-validator
|
||||
|
||||
- name: Log current API rate limits
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
@@ -1,151 +0,0 @@
|
||||
# This workflow depends on two GitHub Apps with the following permissions:
|
||||
# - For checking code owners:
|
||||
# - Permissions:
|
||||
# - Repository > Administration: read-only
|
||||
# - Organization > Members: read-only
|
||||
# - Install App on this repository, setting these variables:
|
||||
# - OWNER_RO_APP_ID (variable)
|
||||
# - OWNER_RO_APP_PRIVATE_KEY (secret)
|
||||
# - For requesting code owners:
|
||||
# - Permissions:
|
||||
# - Repository > Administration: read-only
|
||||
# - Organization > Members: read-only
|
||||
# - Repository > Pull Requests: read-write
|
||||
# - Install App on this repository, setting these variables:
|
||||
# - OWNER_APP_ID (variable)
|
||||
# - OWNER_APP_PRIVATE_KEY (secret)
|
||||
#
|
||||
# This split is done because checking code owners requires handling untrusted PR input,
|
||||
# while requesting code owners requires PR write access, and those shouldn't be mixed.
|
||||
#
|
||||
# Note that the latter is also used for ./eval.yml requesting reviewers.
|
||||
|
||||
name: Codeowners v2
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/codeowners-v2.yml
|
||||
pull_request_target:
|
||||
types: [opened, ready_for_review, synchronize, reopened]
|
||||
|
||||
concurrency:
|
||||
group: codeowners-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
defaults:
|
||||
run:
|
||||
shell: bash
|
||||
|
||||
env:
|
||||
OWNERS_FILE: ci/OWNERS
|
||||
# Don't do anything on draft PRs
|
||||
DRY_MODE: ${{ github.event.pull_request.draft && '1' || '' }}
|
||||
|
||||
jobs:
|
||||
# Check that code owners is valid
|
||||
check:
|
||||
name: Check
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout: |
|
||||
.github/actions
|
||||
ci/github-script
|
||||
- name: Check if the PR can be merged and checkout the merge and target commits
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
with:
|
||||
merged-as-untrusted: true
|
||||
target-as-trusted: true
|
||||
|
||||
- uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
with:
|
||||
# This cache is for the nixpkgs repo checks and should not be trusted or used elsewhere.
|
||||
name: nixpkgs-ci
|
||||
authToken: '${{ secrets.CACHIX_AUTH_TOKEN }}'
|
||||
|
||||
- name: Build codeowners validator
|
||||
run: nix-build trusted/ci -A codeownersValidator
|
||||
|
||||
- uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
|
||||
if: github.event_name == 'pull_request_target' && vars.OWNER_RO_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.OWNER_RO_APP_ID }}
|
||||
private-key: ${{ secrets.OWNER_RO_APP_PRIVATE_KEY }}
|
||||
permission-administration: read
|
||||
permission-members: read
|
||||
|
||||
- name: Log current API rate limits
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
- name: Validate codeowners
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
OWNERS_FILE: untrusted/${{ env.OWNERS_FILE }}
|
||||
GITHUB_ACCESS_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
REPOSITORY_PATH: untrusted
|
||||
OWNER_CHECKER_REPOSITORY: ${{ github.repository }}
|
||||
# Set this to "notowned,avoid-shadowing" to check that all files are owned by somebody
|
||||
EXPERIMENTAL_CHECKS: "avoid-shadowing"
|
||||
run: result/bin/codeowners-validator
|
||||
|
||||
- name: Log current API rate limits
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
# Request reviews from code owners
|
||||
request:
|
||||
name: Request
|
||||
runs-on: ubuntu-24.04-arm
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
|
||||
# Important: Because we use pull_request_target, this checks out the base branch of the PR, not the PR head.
|
||||
# This is intentional, because we need to request the review of owners as declared in the base branch.
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
path: trusted
|
||||
|
||||
- name: Build review request package
|
||||
run: nix-build trusted/ci -A requestReviews
|
||||
|
||||
- uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
|
||||
if: github.event_name == 'pull_request_target' && vars.OWNER_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.OWNER_APP_ID }}
|
||||
private-key: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
|
||||
permission-administration: read
|
||||
permission-members: read
|
||||
permission-pull-requests: write
|
||||
|
||||
- name: Log current API rate limits
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
- name: Request reviews
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: result/bin/request-code-owner-reviews.sh ${{ github.repository }} ${{ github.event.number }} "$OWNERS_FILE"
|
||||
|
||||
- name: Log current API rate limits
|
||||
if: steps.app-token.outputs.token
|
||||
env:
|
||||
GH_TOKEN: ${{ steps.app-token.outputs.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
@@ -49,7 +49,7 @@ jobs:
|
||||
repo: context.repo.repo,
|
||||
pull_number: pull_request.number
|
||||
})).filter(review =>
|
||||
review.user.login == 'github-actions[bot]' &&
|
||||
review.user?.login == 'github-actions[bot]' &&
|
||||
review.state == 'DISMISSED'
|
||||
).map(review => github.graphql(`
|
||||
mutation($node_id:ID!) {
|
||||
|
||||
@@ -36,7 +36,7 @@ jobs:
|
||||
# Use a GitHub App to create the PR so that CI gets triggered
|
||||
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
|
||||
# We only need Pull Requests: write here, but the app is also used for backports.
|
||||
- uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
|
||||
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
|
||||
|
||||
+70
-101
@@ -16,8 +16,8 @@ on:
|
||||
default: false
|
||||
type: boolean
|
||||
secrets:
|
||||
OWNER_APP_PRIVATE_KEY:
|
||||
required: false
|
||||
CACHIX_AUTH_TOKEN:
|
||||
required: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -69,8 +69,6 @@ jobs:
|
||||
# to not interrupt main Eval's compare step.
|
||||
continue-on-error: ${{ matrix.version != '' }}
|
||||
name: ${{ matrix.system }}${{ matrix.version && format(' @ {0}', matrix.version) || '' }}
|
||||
outputs:
|
||||
targetRunId: ${{ steps.targetRunId.outputs.targetRunId }}
|
||||
timeout-minutes: 15
|
||||
steps:
|
||||
# This is not supposed to be used and just acts as a fallback.
|
||||
@@ -87,108 +85,81 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
- name: Check out the PR at the test merge commit
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
- name: Check out the PR at merged and target commits
|
||||
uses: ./.github/actions/checkout
|
||||
with:
|
||||
mergedSha: ${{ inputs.mergedSha }}
|
||||
merged-as-untrusted: true
|
||||
pinnedFrom: untrusted
|
||||
merged-as-untrusted-at: ${{ inputs.mergedSha }}
|
||||
target-as-trusted-at: ${{ inputs.targetSha }}
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
|
||||
- name: Evaluate the ${{ matrix.system }} output paths for all derivation attributes
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
with:
|
||||
# The nixpkgs-ci cache should not be trusted or used outside of Nixpkgs and its forks' CI.
|
||||
name: ${{ vars.CACHIX_NAME || 'nixpkgs-ci' }}
|
||||
extraPullNames: nixpkgs-ci
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
pushFilter: '(-source|-single-chunk)$'
|
||||
|
||||
- name: Evaluate the ${{ matrix.system }} output paths at the merge commit
|
||||
env:
|
||||
MATRIX_SYSTEM: ${{ matrix.system }}
|
||||
MATRIX_VERSION: ${{ matrix.version || 'nixVersions.latest' }}
|
||||
run: |
|
||||
nix-build untrusted/ci --arg nixpkgs ./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" \
|
||||
--out-link merged
|
||||
# If it uses too much memory, slightly decrease chunkSize
|
||||
# If it uses too much memory, slightly decrease chunkSize.
|
||||
# Note: Keep the same further down in sync!
|
||||
|
||||
- name: Upload the output paths and eval stats
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ matrix.version && format('{0}-', matrix.version) || '' }}merged-${{ matrix.system }}
|
||||
path: merged/*
|
||||
|
||||
- name: Log current API rate limits
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
- name: Get target run id
|
||||
# Running the attrpath generation step separately from the outpath step afterwards.
|
||||
# The idea is that, *if* Eval on the target branch has not finished, yet, we will
|
||||
# generate the attrpaths in the meantime - and the separate command command afterwards
|
||||
# will check cachix again for whether Eval has finished. If no Eval result from the
|
||||
# target branch can be found the second time, we proceed to run it in here. Attrpaths
|
||||
# generation takes roughly 30 seconds, so for every normal use-case this should be more
|
||||
# than enough of a head start for Eval on the target branch to finish.
|
||||
# This edge-case, that Eval on the target branch is delayed is unlikely to happen anyway:
|
||||
# For a commit to become the target commit of a PR, it must *already* be on the branch.
|
||||
# Normally, CI should always start running on that push event *before* it starts running
|
||||
# on the PR.
|
||||
- name: Evaluate the ${{ matrix.system }} attribute paths at the target commit
|
||||
if: inputs.targetSha
|
||||
id: targetRunId
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
env:
|
||||
MATRIX_SYSTEM: ${{ matrix.system }}
|
||||
TARGET_SHA: ${{ inputs.targetSha }}
|
||||
with:
|
||||
script: |
|
||||
const system = process.env.MATRIX_SYSTEM
|
||||
const targetSha = process.env.TARGET_SHA
|
||||
|
||||
let run_id
|
||||
try {
|
||||
run_id = (await github.rest.actions.listWorkflowRuns({
|
||||
...context.repo,
|
||||
workflow_id: 'push.yml',
|
||||
event: 'push',
|
||||
head_sha: targetSha
|
||||
})).data.workflow_runs[0].id
|
||||
} catch {
|
||||
throw new Error(`Could not find a push.yml workflow run for ${targetSha}.`)
|
||||
}
|
||||
|
||||
// Waiting 120 * 5 sec = 10 min. max.
|
||||
// Eval takes max 5-6 minutes, normally.
|
||||
for (let i = 0; i < 120; i++) {
|
||||
const result = await github.rest.actions.listWorkflowRunArtifacts({
|
||||
...context.repo,
|
||||
run_id,
|
||||
name: `merged-${system}`
|
||||
})
|
||||
if (result.data.total_count > 0) {
|
||||
core.setOutput('targetRunId', run_id)
|
||||
return
|
||||
}
|
||||
await new Promise(resolve => setTimeout(resolve, 5000))
|
||||
}
|
||||
// No artifact found at this stage. This usually means that Eval failed on the target branch.
|
||||
// This should only happen when Eval is broken on the target branch and this PR fixes it.
|
||||
// Continue without targetRunId to skip the remaining steps, but pass the job.
|
||||
|
||||
- name: Log current API rate limits
|
||||
env:
|
||||
GH_TOKEN: ${{ github.token }}
|
||||
run: gh api /rate_limit | jq
|
||||
|
||||
- uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
if: steps.targetRunId.outputs.targetRunId
|
||||
with:
|
||||
run-id: ${{ steps.targetRunId.outputs.targetRunId }}
|
||||
name: merged-${{ matrix.system }}
|
||||
path: target
|
||||
github-token: ${{ github.token }}
|
||||
merge-multiple: true
|
||||
|
||||
- name: Compare outpaths against the target branch
|
||||
if: steps.targetRunId.outputs.targetRunId
|
||||
env:
|
||||
MATRIX_SYSTEM: ${{ matrix.system }}
|
||||
run: |
|
||||
nix-build untrusted/ci --arg nixpkgs ./pinned -A eval.diff \
|
||||
--arg beforeDir ./target \
|
||||
nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.attrpathsSuperset \
|
||||
--argstr evalSystem "$MATRIX_SYSTEM" \
|
||||
--argstr nixPath "nixVersions.latest"
|
||||
|
||||
- name: Evaluate the ${{ matrix.system }} output paths at the target commit
|
||||
if: inputs.targetSha
|
||||
env:
|
||||
MATRIX_SYSTEM: ${{ matrix.system }}
|
||||
# This should be very quick, because it pulls the eval results from Cachix.
|
||||
run: |
|
||||
nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.singleSystem \
|
||||
--argstr evalSystem "$MATRIX_SYSTEM" \
|
||||
--arg chunkSize 8000 \
|
||||
--argstr nixPath "nixVersions.latest" \
|
||||
--out-link target
|
||||
|
||||
- name: Compare outpaths against the target branch
|
||||
if: inputs.targetSha
|
||||
env:
|
||||
MATRIX_SYSTEM: ${{ matrix.system }}
|
||||
run: |
|
||||
nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A eval.diff \
|
||||
--arg beforeDir "$(readlink ./target)" \
|
||||
--arg afterDir "$(readlink ./merged)" \
|
||||
--argstr evalSystem "$MATRIX_SYSTEM" \
|
||||
--out-link diff
|
||||
|
||||
- name: Upload outpaths diff and stats
|
||||
if: steps.targetRunId.outputs.targetRunId
|
||||
if: inputs.targetSha
|
||||
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
|
||||
with:
|
||||
name: ${{ matrix.version && format('{0}-', matrix.version) || '' }}diff-${{ matrix.system }}
|
||||
@@ -197,7 +168,7 @@ jobs:
|
||||
compare:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
needs: [eval]
|
||||
if: needs.eval.outputs.targetRunId && !cancelled() && !failure()
|
||||
if: inputs.targetSha && !cancelled() && !failure()
|
||||
permissions:
|
||||
statuses: write
|
||||
timeout-minutes: 5
|
||||
@@ -206,11 +177,10 @@ jobs:
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
- name: Check out the PR at the target commit
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
uses: ./.github/actions/checkout
|
||||
with:
|
||||
targetSha: ${{ inputs.targetSha }}
|
||||
target-as-trusted: true
|
||||
pinnedFrom: trusted
|
||||
merged-as-untrusted-at: ${{ inputs.mergedSha }}
|
||||
target-as-trusted-at: ${{ inputs.targetSha }}
|
||||
|
||||
- name: Download output paths and eval stats for all systems
|
||||
uses: actions/download-artifact@634f93cb2916e3fdff6788551b99b062d0335ce0 # v5.0.0
|
||||
@@ -224,7 +194,7 @@ jobs:
|
||||
|
||||
- name: Combine all output paths and eval stats
|
||||
run: |
|
||||
nix-build trusted/ci --arg nixpkgs ./pinned -A eval.combine \
|
||||
nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.combine \
|
||||
--arg diffDir ./diff \
|
||||
--out-link combined
|
||||
|
||||
@@ -232,12 +202,11 @@ jobs:
|
||||
env:
|
||||
AUTHOR_ID: ${{ github.event.pull_request.user.id }}
|
||||
run: |
|
||||
git -C trusted fetch --depth 1 origin ${{ inputs.mergedSha }}
|
||||
git -C trusted diff --name-only ${{ inputs.mergedSha }} \
|
||||
git -C nixpkgs/trusted diff --name-only ${{ inputs.mergedSha }} \
|
||||
| jq --raw-input --slurp 'split("\n")[:-1]' > touched-files.json
|
||||
|
||||
# Use the target branch to get accurate maintainer info
|
||||
nix-build trusted/ci --arg nixpkgs ./pinned -A eval.compare \
|
||||
nix-build nixpkgs/trusted/ci --arg nixpkgs ./nixpkgs/trusted-pinned -A eval.compare \
|
||||
--arg combinedDir "$(realpath ./combined)" \
|
||||
--arg touchedFilesJson ./touched-files.json \
|
||||
--argstr githubAuthorId "$AUTHOR_ID" \
|
||||
@@ -375,18 +344,18 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
- name: Check if the PR can be merged and checkout the merge commit
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
- name: Checkout the merge commit
|
||||
uses: ./.github/actions/checkout
|
||||
with:
|
||||
mergedSha: ${{ inputs.mergedSha }}
|
||||
merged-as-untrusted: true
|
||||
merged-as-untrusted-at: ${{ inputs.mergedSha }}
|
||||
|
||||
- name: Install Nix
|
||||
uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
|
||||
- name: Ensure flake outputs on all systems still evaluate
|
||||
run: nix flake check --all-systems --no-build ./untrusted
|
||||
|
||||
- name: Query nixpkgs with aliases enabled to check for basic syntax errors
|
||||
- name: Run misc eval tasks in parallel
|
||||
run: |
|
||||
time nix-env -I ./untrusted -f ./untrusted -qa '*' --option restrict-eval true --option allow-import-from-derivation false >/dev/null
|
||||
# Ensure flake outputs on all systems still evaluate
|
||||
nix flake check --all-systems --no-build './nixpkgs/untrusted?shallow=1' &
|
||||
# Query nixpkgs with aliases enabled to check for basic syntax errors
|
||||
nix-env -I ./nixpkgs/untrusted -f ./nixpkgs/untrusted -qa '*' --option restrict-eval true --option allow-import-from-derivation false >/dev/null &
|
||||
wait
|
||||
|
||||
@@ -49,8 +49,8 @@ jobs:
|
||||
run: npm install @actions/artifact bottleneck
|
||||
|
||||
# Use a GitHub App, because it has much higher rate limits: 12,500 instead of 5,000 req / hour.
|
||||
- uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
|
||||
if: vars.NIXPKGS_CI_APP_ID
|
||||
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
if: github.event_name != 'pull_request' && vars.NIXPKGS_CI_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
|
||||
|
||||
+36
-20
@@ -9,6 +9,9 @@ on:
|
||||
targetSha:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN:
|
||||
required: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -24,21 +27,23 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
- name: Check if the PR can be merged and checkout the merge commit
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
- name: Checkout the merge commit
|
||||
uses: ./.github/actions/checkout
|
||||
with:
|
||||
mergedSha: ${{ inputs.mergedSha }}
|
||||
merged-as-untrusted: true
|
||||
pinnedFrom: untrusted
|
||||
merged-as-untrusted-at: ${{ inputs.mergedSha }}
|
||||
|
||||
- uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # 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.
|
||||
# Maybe we can cache treefmt's eval-cache somehow.
|
||||
|
||||
- name: Check that files are formatted
|
||||
run: |
|
||||
# Note that it's fine to run this on untrusted code because:
|
||||
# - There's no secrets accessible here
|
||||
# - The build is sandboxed
|
||||
if ! nix-build untrusted/ci --arg nixpkgs ./pinned -A fmt.check; then
|
||||
if ! nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A fmt.check; then
|
||||
echo "Some files are not properly formatted"
|
||||
echo "Please format them by going to the Nixpkgs root directory and running one of:"
|
||||
echo " nix-shell --run treefmt"
|
||||
@@ -56,19 +61,25 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
- name: Check if the PR can be merged and checkout the merge commit
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
- name: Checkout the merge commit
|
||||
uses: ./.github/actions/checkout
|
||||
with:
|
||||
mergedSha: ${{ inputs.mergedSha }}
|
||||
merged-as-untrusted: true
|
||||
pinnedFrom: untrusted
|
||||
merged-as-untrusted-at: ${{ inputs.mergedSha }}
|
||||
|
||||
- uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
with:
|
||||
# The nixpkgs-ci cache should not be trusted or used outside of Nixpkgs and its forks' CI.
|
||||
name: ${{ vars.CACHIX_NAME || 'nixpkgs-ci' }}
|
||||
extraPullNames: nixpkgs-ci
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
pushFilter: -source$
|
||||
|
||||
- name: Parse all nix files
|
||||
run: |
|
||||
# Tests multiple versions at once, let's make sure all of them run, so keep-going.
|
||||
nix-build untrusted/ci --arg nixpkgs ./pinned -A parse --keep-going
|
||||
nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A parse --keep-going
|
||||
|
||||
nixpkgs-vet:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
@@ -77,23 +88,28 @@ jobs:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout: .github/actions
|
||||
- name: Check if the PR can be merged and checkout merged and target commits
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
- name: Checkout merge and target commits
|
||||
uses: ./.github/actions/checkout
|
||||
with:
|
||||
mergedSha: ${{ inputs.mergedSha }}
|
||||
merged-as-untrusted: true
|
||||
pinnedFrom: untrusted
|
||||
targetSha: ${{ inputs.targetSha }}
|
||||
target-as-trusted: true
|
||||
merged-as-untrusted-at: ${{ inputs.mergedSha }}
|
||||
target-as-trusted-at: ${{ inputs.targetSha }}
|
||||
|
||||
- uses: cachix/install-nix-action@fc6e360bedc9ee72d75e701397f0bb30dce77568 # v31
|
||||
|
||||
- uses: cachix/cachix-action@0fc020193b5a1fa3ac4575aa3a7d3aa6a35435ad # v16
|
||||
with:
|
||||
# The nixpkgs-ci cache should not be trusted or used outside of Nixpkgs and its forks' CI.
|
||||
name: ${{ vars.CACHIX_NAME || 'nixpkgs-ci' }}
|
||||
extraPullNames: nixpkgs-ci
|
||||
authToken: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
pushFilter: -source$
|
||||
|
||||
- name: Running nixpkgs-vet
|
||||
env:
|
||||
# Force terminal colors to be enabled. The library that `nixpkgs-vet` uses respects https://bixense.com/clicolors/
|
||||
CLICOLOR_FORCE: 1
|
||||
run: |
|
||||
if nix-build untrusted/ci --arg nixpkgs ./pinned -A nixpkgs-vet --arg base "./trusted" --arg head "./untrusted"; then
|
||||
if nix-build nixpkgs/untrusted/ci --arg nixpkgs ./nixpkgs/untrusted-pinned -A nixpkgs-vet --arg base "./nixpkgs/trusted" --arg head "./nixpkgs/untrusted"; then
|
||||
exit 0
|
||||
else
|
||||
exitCode=$?
|
||||
|
||||
@@ -2,6 +2,17 @@ name: Merge Group
|
||||
|
||||
on:
|
||||
merge_group:
|
||||
workflow_call:
|
||||
inputs:
|
||||
mergedSha:
|
||||
required: true
|
||||
type: string
|
||||
targetSha:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN:
|
||||
required: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -9,23 +20,36 @@ jobs:
|
||||
lint:
|
||||
name: Lint
|
||||
uses: ./.github/workflows/lint.yml
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
with:
|
||||
mergedSha: ${{ github.event.merge_group.head_sha }}
|
||||
targetSha: ${{ github.event.merge_group.base_sha }}
|
||||
mergedSha: ${{ inputs.mergedSha || github.event.merge_group.head_sha }}
|
||||
targetSha: ${{ inputs.targetSha || github.event.merge_group.base_sha }}
|
||||
|
||||
# This job's only purpose is to serve as a target for the "Required Status Checks" branch ruleset.
|
||||
# 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.
|
||||
# If they pass, it is skipped — which counts as "success" for purposes of the branch ruleset.
|
||||
# However, if any of them fail, this job will also fail — thus blocking the branch ruleset.
|
||||
no-pr-failures:
|
||||
unlock:
|
||||
if: github.event_name != 'pull_request'
|
||||
# Modify this list to add or remove jobs from required status checks.
|
||||
needs:
|
||||
- lint
|
||||
# WARNING:
|
||||
# Do NOT change the name of this job, otherwise the rule will not catch it anymore.
|
||||
# This would prevent all PRs from passing the merge queue.
|
||||
name: no PR failures
|
||||
if: ${{ failure() }}
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
statuses: write
|
||||
steps:
|
||||
- run: exit 1
|
||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const { serverUrl, repo, runId, payload } = context
|
||||
const target_url =
|
||||
`${serverUrl}/${repo.owner}/${repo.repo}/actions/runs/${runId}`
|
||||
await github.rest.repos.createCommitStatus({
|
||||
...repo,
|
||||
sha: payload.merge_group.head_sha,
|
||||
// WARNING:
|
||||
// Do NOT change the name of this, otherwise the rule will not catch it anymore.
|
||||
// This would prevent all PRs from merging.
|
||||
context: 'no PR failures',
|
||||
state: 'success',
|
||||
target_url,
|
||||
})
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
steps:
|
||||
# Use a GitHub App to create the PR so that CI gets triggered
|
||||
# The App is scoped to Repository > Contents and Pull Requests: write for Nixpkgs
|
||||
- uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
|
||||
- uses: actions/create-github-app-token@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
id: app-token
|
||||
with:
|
||||
app-id: ${{ vars.NIXPKGS_CI_APP_ID }}
|
||||
|
||||
+58
-73
@@ -1,17 +1,18 @@
|
||||
name: PR
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/actions/get-merge-commit/action.yml
|
||||
- .github/workflows/build.yml
|
||||
- .github/workflows/check.yml
|
||||
- .github/workflows/eval.yml
|
||||
- .github/workflows/lint.yml
|
||||
- .github/workflows/pr.yml
|
||||
- .github/workflows/labels.yml
|
||||
- .github/workflows/reviewers.yml # needs eval results from the same event type
|
||||
pull_request_target:
|
||||
workflow_call:
|
||||
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
|
||||
OWNER_RO_APP_PRIVATE_KEY:
|
||||
required: true
|
||||
|
||||
concurrency:
|
||||
group: pr-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
@@ -22,63 +23,32 @@ permissions: {}
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
# wrong branch review comment
|
||||
pull-requests: write
|
||||
outputs:
|
||||
baseBranch: ${{ steps.branches.outputs.base }}
|
||||
headBranch: ${{ steps.branches.outputs.head }}
|
||||
mergedSha: ${{ steps.get-merge-commit.outputs.mergedSha }}
|
||||
targetSha: ${{ steps.get-merge-commit.outputs.targetSha }}
|
||||
systems: ${{ steps.systems.outputs.systems }}
|
||||
touched: ${{ steps.files.outputs.touched }}
|
||||
baseBranch: ${{ steps.prepare.outputs.base }}
|
||||
headBranch: ${{ steps.prepare.outputs.head }}
|
||||
mergedSha: ${{ steps.prepare.outputs.mergedSha }}
|
||||
targetSha: ${{ steps.prepare.outputs.targetSha }}
|
||||
systems: ${{ steps.prepare.outputs.systems }}
|
||||
touched: ${{ steps.prepare.outputs.touched }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout-cone-mode: true # default, for clarity
|
||||
sparse-checkout: |
|
||||
.github/actions
|
||||
ci/github-script
|
||||
ci/supportedBranches.js
|
||||
ci/supportedSystems.json
|
||||
- name: Check if the PR can be merged and get the test merge commit
|
||||
uses: ./.github/actions/get-merge-commit
|
||||
id: get-merge-commit
|
||||
|
||||
- name: Load supported systems
|
||||
id: systems
|
||||
run: |
|
||||
echo "systems=$(jq -c <ci/supportedSystems.json)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Determine branch type
|
||||
id: branches
|
||||
- id: prepare
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const { classify } = require('./ci/supportedBranches.js')
|
||||
const { base, head } = context.payload.pull_request
|
||||
|
||||
const baseClassification = classify(base.ref)
|
||||
core.setOutput('base', baseClassification)
|
||||
core.info('base classification:', baseClassification)
|
||||
|
||||
const headClassification =
|
||||
(base.repo.full_name == head.repo.full_name) ?
|
||||
classify(head.ref) :
|
||||
// PRs from forks are always considered WIP.
|
||||
{ type: ['wip'] }
|
||||
core.setOutput('head', headClassification)
|
||||
core.info('head classification:', headClassification)
|
||||
|
||||
- name: Determine changed files
|
||||
id: files
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const files = (await github.paginate(github.rest.pulls.listFiles, {
|
||||
...context.repo,
|
||||
pull_number: context.payload.pull_request.number,
|
||||
per_page: 100,
|
||||
})).map(file => file.filename)
|
||||
|
||||
if (files.includes('ci/pinned.json')) core.setOutput('touched', ['pinned'])
|
||||
else core.setOutput('touched', [])
|
||||
require('./ci/github-script/prepare.js')({
|
||||
github,
|
||||
context,
|
||||
core,
|
||||
dry: context.eventName == 'pull_request',
|
||||
})
|
||||
|
||||
check:
|
||||
name: Check
|
||||
@@ -87,14 +57,22 @@ jobs:
|
||||
permissions:
|
||||
# cherry-picks
|
||||
pull-requests: write
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
OWNER_RO_APP_PRIVATE_KEY: ${{ secrets.OWNER_RO_APP_PRIVATE_KEY }}
|
||||
with:
|
||||
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
|
||||
headBranch: ${{ needs.prepare.outputs.headBranch }}
|
||||
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
|
||||
targetSha: ${{ needs.prepare.outputs.targetSha }}
|
||||
ownersCanFail: ${{ !contains(fromJSON(needs.prepare.outputs.touched), 'owners') }}
|
||||
|
||||
lint:
|
||||
name: Lint
|
||||
needs: [prepare]
|
||||
uses: ./.github/workflows/lint.yml
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
with:
|
||||
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
|
||||
targetSha: ${{ needs.prepare.outputs.targetSha }}
|
||||
@@ -107,7 +85,7 @@ jobs:
|
||||
# compare
|
||||
statuses: write
|
||||
secrets:
|
||||
OWNER_APP_PRIVATE_KEY: ${{ secrets.OWNER_APP_PRIVATE_KEY }}
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
with:
|
||||
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
|
||||
targetSha: ${{ needs.prepare.outputs.targetSha }}
|
||||
@@ -146,26 +124,33 @@ jobs:
|
||||
baseBranch: ${{ needs.prepare.outputs.baseBranch }}
|
||||
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
|
||||
|
||||
# This job's only purpose is to serve as a target for the "Required Status Checks" branch ruleset.
|
||||
# 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 merging a PR.
|
||||
# If they pass, it is skipped — which counts as "success" for purposes of the branch ruleset.
|
||||
# However, if any of them fail, this job will also fail — thus blocking the branch ruleset.
|
||||
no-pr-failures:
|
||||
unlock:
|
||||
if: github.event_name != 'pull_request'
|
||||
# Modify this list to add or remove jobs from required status checks.
|
||||
needs:
|
||||
- check
|
||||
- lint
|
||||
- eval
|
||||
- build
|
||||
# WARNING:
|
||||
# Do NOT change the name of this job, otherwise the rule will not catch it anymore.
|
||||
# This would prevent all PRs from merging.
|
||||
name: no PR failures
|
||||
# A single job is "cancelled" when it hits its timeout. This is not the same
|
||||
# as "skipped", which happens when the `if` condition doesn't apply.
|
||||
# The "cancelled()" function only checks the whole workflow, but not individual
|
||||
# jobs.
|
||||
if: ${{ failure() || contains(needs.*.result, 'cancelled') }}
|
||||
runs-on: ubuntu-24.04-arm
|
||||
permissions:
|
||||
statuses: write
|
||||
steps:
|
||||
- run: exit 1
|
||||
- uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const { serverUrl, repo, runId, payload } = context
|
||||
const target_url =
|
||||
`${serverUrl}/${repo.owner}/${repo.repo}/actions/runs/${runId}?pr=${payload.pull_request.number}`
|
||||
await github.rest.repos.createCommitStatus({
|
||||
...repo,
|
||||
sha: payload.pull_request.head.sha,
|
||||
// WARNING:
|
||||
// Do NOT change the name of this, otherwise the rule will not catch it anymore.
|
||||
// This would prevent all PRs from merging.
|
||||
context: 'no PR failures',
|
||||
state: 'success',
|
||||
target_url,
|
||||
})
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
name: Push
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/push.yml
|
||||
# eval is tested via pr.yml
|
||||
push:
|
||||
# Keep this synced with ci/request-reviews/dev-branches.txt
|
||||
branches:
|
||||
- master
|
||||
- staging
|
||||
- release-*
|
||||
- staging-*
|
||||
- haskell-updates
|
||||
- python-updates
|
||||
workflow_call:
|
||||
inputs:
|
||||
mergedSha:
|
||||
required: true
|
||||
type: string
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN:
|
||||
required: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
@@ -40,9 +42,9 @@ jobs:
|
||||
# Those are not actually used on push, but will throw an error if not set.
|
||||
permissions:
|
||||
# compare
|
||||
issues: write
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
with:
|
||||
mergedSha: ${{ github.sha }}
|
||||
mergedSha: ${{ inputs.mergedSha || github.sha }}
|
||||
systems: ${{ needs.prepare.outputs.systems }}
|
||||
|
||||
@@ -4,9 +4,6 @@
|
||||
name: Reviewers
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- .github/workflows/reviewers.yml
|
||||
pull_request_target:
|
||||
types: [ready_for_review]
|
||||
workflow_call:
|
||||
@@ -41,9 +38,17 @@ jobs:
|
||||
- name: Build the requestReviews derivation
|
||||
run: nix-build trusted/ci -A requestReviews
|
||||
|
||||
# See ./codeowners-v2.yml, reuse the same App because we need the same permissions
|
||||
# Can't use the token received from permissions above, because it can't get enough permissions
|
||||
- uses: actions/create-github-app-token@0f859bf9e69e887678d5bbfbee594437cb440ffe # v2.1.0
|
||||
# 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@a8d616148505b5069dccd32f177bb87d7f39123b # v2.1.1
|
||||
if: github.event_name == 'pull_request_target' && vars.OWNER_APP_ID
|
||||
id: app-token
|
||||
with:
|
||||
@@ -53,6 +58,28 @@ jobs:
|
||||
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 }}
|
||||
@@ -68,7 +95,7 @@ jobs:
|
||||
const run_id = (await github.rest.actions.listWorkflowRuns({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
workflow_id: 'pr.yml',
|
||||
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
|
||||
|
||||
@@ -0,0 +1,114 @@
|
||||
name: Test
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
|
||||
concurrency:
|
||||
group: test-${{ github.workflow }}-${{ github.event_name }}-${{ github.event.pull_request.number || github.run_id }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions: {}
|
||||
|
||||
jobs:
|
||||
prepare:
|
||||
runs-on: ubuntu-24.04-arm
|
||||
outputs:
|
||||
merge-group: ${{ steps.files.outputs.merge-group }}
|
||||
mergedSha: ${{ steps.prepare.outputs.mergedSha }}
|
||||
pr: ${{ steps.files.outputs.pr }}
|
||||
push: ${{ steps.files.outputs.push }}
|
||||
targetSha: ${{ steps.prepare.outputs.targetSha }}
|
||||
steps:
|
||||
- uses: actions/checkout@08c6903cd8c0fde910a37f88322edcfb5dd907a8 # v5.0.0
|
||||
with:
|
||||
sparse-checkout-cone-mode: true # default, for clarity
|
||||
sparse-checkout: |
|
||||
ci/github-script
|
||||
- id: prepare
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
require('./ci/github-script/prepare.js')({
|
||||
github,
|
||||
context,
|
||||
core,
|
||||
// Review comments will be posted by the main PR workflow on the pull_request_target event.
|
||||
dry: false,
|
||||
})
|
||||
|
||||
- name: Determine changed files
|
||||
id: files
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
script: |
|
||||
const files = (await github.paginate(github.rest.pulls.listFiles, {
|
||||
...context.repo,
|
||||
pull_number: context.payload.pull_request.number,
|
||||
per_page: 100,
|
||||
})).map(file => file.filename)
|
||||
|
||||
if (files.some(file => [
|
||||
'.github/workflows/lint.yml',
|
||||
'.github/workflows/merge-group.yml',
|
||||
'.github/workflows/test.yml',
|
||||
].includes(file))) core.setOutput('merge-group', true)
|
||||
|
||||
if (files.some(file => [
|
||||
'.github/actions/checkout/action.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/test.yml',
|
||||
].includes(file))) core.setOutput('pr', true)
|
||||
|
||||
if (files.some(file => [
|
||||
'.github/workflows/eval.yml',
|
||||
'.github/workflows/push.yml',
|
||||
'.github/workflows/test.yml',
|
||||
].includes(file))) core.setOutput('push', true)
|
||||
|
||||
merge-group:
|
||||
if: needs.prepare.outputs.merge-group
|
||||
name: Merge Group
|
||||
needs: [prepare]
|
||||
uses: ./.github/workflows/merge-group.yml
|
||||
# Those are actually only used on the merge_group event, but will throw an error if not set.
|
||||
permissions:
|
||||
statuses: write
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
with:
|
||||
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
|
||||
targetSha: ${{ needs.prepare.outputs.targetSha }}
|
||||
|
||||
pr:
|
||||
if: needs.prepare.outputs.pr
|
||||
name: PR
|
||||
needs: [prepare]
|
||||
uses: ./.github/workflows/pr.yml
|
||||
# Those are actually only used on the pull_request_target event, but will throw an error if not set.
|
||||
permissions:
|
||||
issues: write
|
||||
pull-requests: write
|
||||
statuses: write
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
NIXPKGS_CI_APP_PRIVATE_KEY: ${{ secrets.NIXPKGS_CI_APP_PRIVATE_KEY }}
|
||||
OWNER_RO_APP_PRIVATE_KEY: ${{ secrets.OWNER_RO_APP_PRIVATE_KEY }}
|
||||
|
||||
push:
|
||||
if: needs.prepare.outputs.push
|
||||
name: Push
|
||||
needs: [prepare]
|
||||
uses: ./.github/workflows/push.yml
|
||||
# Those are not actually used on the push or pull_request events, but will throw an error if not set.
|
||||
permissions:
|
||||
statuses: write
|
||||
secrets:
|
||||
CACHIX_AUTH_TOKEN: ${{ secrets.CACHIX_AUTH_TOKEN }}
|
||||
with:
|
||||
mergedSha: ${{ needs.prepare.outputs.mergedSha }}
|
||||
@@ -264,9 +264,7 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
|
||||
/pkgs/development/libraries/qt-5 @K900 @NickCao @SuperSandro2000 @ttuegel
|
||||
/pkgs/development/libraries/qt-6 @K900 @NickCao @SuperSandro2000 @ttuegel
|
||||
|
||||
# KDE / Plasma 5
|
||||
/pkgs/applications/kde @K900 @NickCao @SuperSandro2000 @ttuegel
|
||||
/pkgs/desktops/plasma-5 @K900 @NickCao @SuperSandro2000 @ttuegel
|
||||
# KDE Frameworks 5
|
||||
/pkgs/development/libraries/kde-frameworks @K900 @NickCao @SuperSandro2000 @ttuegel
|
||||
|
||||
# KDE / Plasma 6
|
||||
@@ -370,13 +368,12 @@ pkgs/development/python-modules/buildcatrust/ @ajs124 @lukegb @mweinelt
|
||||
/pkgs/applications/editors/vscode/extensions
|
||||
|
||||
# PHP interpreter, packages, extensions, tests and documentation
|
||||
/doc/languages-frameworks/php.section.md @aanderse @drupol @globin @ma27 @talyz
|
||||
/nixos/tests/php @aanderse @drupol @globin @ma27 @talyz
|
||||
/pkgs/build-support/php/build-pecl.nix @aanderse @drupol @globin @ma27 @talyz
|
||||
/pkgs/build-support/php @drupol
|
||||
/pkgs/development/interpreters/php @jtojnar @aanderse @drupol @globin @ma27 @talyz
|
||||
/pkgs/development/php-packages @aanderse @drupol @globin @ma27 @talyz
|
||||
/pkgs/top-level/php-packages.nix @jtojnar @aanderse @drupol @globin @ma27 @talyz
|
||||
/doc/languages-frameworks/php.section.md @aanderse @globin @ma27 @talyz
|
||||
/nixos/tests/php @aanderse @globin @ma27 @talyz
|
||||
/pkgs/build-support/php/build-pecl.nix @aanderse @globin @ma27 @talyz
|
||||
/pkgs/development/interpreters/php @jtojnar @aanderse @globin @ma27 @talyz
|
||||
/pkgs/development/php-packages @aanderse @globin @ma27 @talyz
|
||||
/pkgs/top-level/php-packages.nix @jtojnar @aanderse @globin @ma27 @talyz
|
||||
|
||||
# Docker tools
|
||||
/pkgs/build-support/docker @roberth
|
||||
@@ -499,4 +496,4 @@ pkgs/by-name/oc/octodns/ @anthonyroussel
|
||||
pkgs/by-name/te/teleport* @arianvp @justinas @sigma @tomberek @freezeboy @techknowlogick @JuliusFreudenberger
|
||||
|
||||
# Warp-terminal
|
||||
pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @donteatoreo @johnrtitor
|
||||
pkgs/by-name/wa/warp-terminal/ @emilytrau @imadnyc @FlameFlag @johnrtitor
|
||||
|
||||
+1
-1
@@ -36,7 +36,7 @@ For the purposes of CI, branches in the NixOS/nixpkgs repository are classified
|
||||
- Pull Requests required.
|
||||
- Long-lived, no deletion, no force push.
|
||||
- **Secondary development** branches
|
||||
- `staging-` prefix, `haskell-updates` and `python-updates`
|
||||
- `staging-` prefix and `haskell-updates`
|
||||
- Pull Requests normally required, except when merging development branches into each other.
|
||||
- Long-lived, no deletion, no force push.
|
||||
- **Work-In-Progress** branches
|
||||
|
||||
+30
-5
@@ -17,7 +17,12 @@ let
|
||||
else
|
||||
nixpkgs;
|
||||
|
||||
pkgs = import nixpkgs' { inherit system; };
|
||||
pkgs = import nixpkgs' {
|
||||
inherit system;
|
||||
# Nixpkgs generally — and CI specifically — do not use aliases,
|
||||
# because we want to ensure they are not load-bearing.
|
||||
allowAliases = false;
|
||||
};
|
||||
|
||||
fmt =
|
||||
let
|
||||
@@ -42,12 +47,30 @@ let
|
||||
|
||||
programs.actionlint.enable = true;
|
||||
|
||||
programs.biome = {
|
||||
enable = true;
|
||||
settings.formatter = {
|
||||
useEditorconfig = true;
|
||||
};
|
||||
settings.javascript.formatter = {
|
||||
quoteStyle = "single";
|
||||
semicolons = "asNeeded";
|
||||
};
|
||||
settings.json.formatter.enabled = false;
|
||||
};
|
||||
settings.formatter.biome.excludes = [
|
||||
"*.min.js"
|
||||
"pkgs/*"
|
||||
];
|
||||
|
||||
programs.keep-sorted.enable = true;
|
||||
|
||||
# This uses nixfmt underneath,
|
||||
# the default formatter for Nix code.
|
||||
# This uses nixfmt underneath, the default formatter for Nix code.
|
||||
# See https://github.com/NixOS/nixfmt
|
||||
programs.nixfmt.enable = true;
|
||||
programs.nixfmt = {
|
||||
enable = true;
|
||||
package = pkgs.nixfmt;
|
||||
};
|
||||
|
||||
programs.yamlfmt = {
|
||||
enable = true;
|
||||
@@ -118,7 +141,9 @@ rec {
|
||||
manual-nixos = (import ../nixos/release.nix { }).manual.${system} or null;
|
||||
manual-nixpkgs = (import ../doc { inherit pkgs; });
|
||||
manual-nixpkgs-tests = (import ../doc { inherit pkgs; }).tests;
|
||||
nixpkgs-vet = pkgs.callPackage ./nixpkgs-vet.nix { };
|
||||
nixpkgs-vet = pkgs.callPackage ./nixpkgs-vet.nix {
|
||||
nix = pkgs.nixVersions.latest;
|
||||
};
|
||||
parse = pkgs.lib.recurseIntoAttrs {
|
||||
latest = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.latest; };
|
||||
lix = pkgs.callPackage ./parse.nix { nix = pkgs.lix; };
|
||||
|
||||
@@ -30,6 +30,7 @@ let
|
||||
"doc"
|
||||
"lib"
|
||||
"maintainers"
|
||||
"modules"
|
||||
"nixos"
|
||||
"pkgs"
|
||||
".version"
|
||||
@@ -140,6 +141,8 @@ let
|
||||
env = {
|
||||
inherit evalSystem chunkSize;
|
||||
};
|
||||
__structuredAttrs = true;
|
||||
unsafeDiscardReferences.out = true;
|
||||
}
|
||||
''
|
||||
export NIX_STATE_DIR=$(mktemp -d)
|
||||
|
||||
+77
-98
@@ -1,9 +1,8 @@
|
||||
module.exports = async function ({ github, context, core, dry }) {
|
||||
module.exports = async ({ github, context, core, dry, cherryPicks }) => {
|
||||
const { execFileSync } = require('node:child_process')
|
||||
const { readFile } = require('node:fs/promises')
|
||||
const { join } = require('node:path')
|
||||
const { classify } = require('../supportedBranches.js')
|
||||
const withRateLimit = require('./withRateLimit.js')
|
||||
const { dismissReviews, postReview } = require('./reviews.js')
|
||||
|
||||
await withRateLimit({ github, core }, async (stats) => {
|
||||
stats.prs = 1
|
||||
@@ -18,13 +17,13 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
run_id: context.runId,
|
||||
per_page: 100,
|
||||
})
|
||||
).find(({ name }) => name == 'Check / cherry-pick').html_url +
|
||||
).find(({ name }) => name.endsWith('Check / commits')).html_url +
|
||||
'?pr=' +
|
||||
pull_number
|
||||
|
||||
async function extract({ sha, commit }) {
|
||||
const noCherryPick = Array.from(
|
||||
commit.message.matchAll(/^Not-cherry-picked-because: (.*)$/g)
|
||||
commit.message.matchAll(/^Not-cherry-picked-because: (.*)$/gm),
|
||||
).at(0)
|
||||
|
||||
if (noCherryPick)
|
||||
@@ -139,17 +138,20 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
}
|
||||
}
|
||||
|
||||
const commits = await github.paginate(github.rest.pulls.listCommits, {
|
||||
...context.repo,
|
||||
pull_number,
|
||||
})
|
||||
// For now we short-circuit the list of commits when cherryPicks should not be checked.
|
||||
// This will not run any checks, but still trigger the "dismiss reviews" part below.
|
||||
const commits = !cherryPicks
|
||||
? []
|
||||
: await github.paginate(github.rest.pulls.listCommits, {
|
||||
...context.repo,
|
||||
pull_number,
|
||||
})
|
||||
|
||||
const extracted = await Promise.all(commits.map(extract))
|
||||
|
||||
const fetch = extracted
|
||||
.filter(({ severity }) => !severity)
|
||||
.map(({ sha, original_sha }) => [ sha, original_sha ])
|
||||
.flat()
|
||||
.flatMap(({ sha, original_sha }) => [sha, original_sha])
|
||||
|
||||
if (fetch.length > 0) {
|
||||
// Fetching all commits we need for diff at once is much faster than any other method.
|
||||
@@ -163,85 +165,98 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
])
|
||||
}
|
||||
|
||||
const results = extracted.map(result => result.severity ? result : diff(result))
|
||||
const results = extracted.map((result) =>
|
||||
result.severity ? result : diff(result),
|
||||
)
|
||||
|
||||
// Log all results without truncation, with better highlighting and all whitespace changes to the job log.
|
||||
results.forEach(({ sha, commit, severity, message, colored_diff }) => {
|
||||
core.startGroup(`Commit ${sha}`)
|
||||
core.info(`Author: ${commit.author.name} ${commit.author.email}`)
|
||||
core.info(`Date: ${new Date(commit.author.date)}`)
|
||||
core[severity](message)
|
||||
switch (severity) {
|
||||
case 'error':
|
||||
core.error(message)
|
||||
break
|
||||
case 'warning':
|
||||
core.warning(message)
|
||||
break
|
||||
default:
|
||||
core.info(message)
|
||||
}
|
||||
core.endGroup()
|
||||
if (colored_diff) core.info(colored_diff)
|
||||
})
|
||||
|
||||
// Only create step summary below in case of warnings or errors.
|
||||
// Also clean up older reviews, when all checks are good now.
|
||||
if (results.every(({ severity }) => severity == 'info')) {
|
||||
if (!dry) {
|
||||
await Promise.all(
|
||||
(
|
||||
await github.paginate(github.rest.pulls.listReviews, {
|
||||
...context.repo,
|
||||
pull_number,
|
||||
})
|
||||
)
|
||||
.filter((review) => review.user.login == 'github-actions[bot]')
|
||||
.map(async (review) => {
|
||||
if (review.state == 'CHANGES_REQUESTED') {
|
||||
await github.rest.pulls.dismissReview({
|
||||
...context.repo,
|
||||
pull_number,
|
||||
review_id: review.id,
|
||||
message: 'All cherry-picks are good now, thank you!',
|
||||
})
|
||||
}
|
||||
await github.graphql(
|
||||
`mutation($node_id:ID!) {
|
||||
minimizeComment(input: {
|
||||
classifier: RESOLVED,
|
||||
subjectId: $node_id
|
||||
})
|
||||
{ clientMutationId }
|
||||
}`,
|
||||
{ node_id: review.node_id },
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
// An empty results array will always trigger this condition, which is helpful
|
||||
// to clean up reviews created by the prepare step when on the wrong branch.
|
||||
if (results.every(({ severity }) => severity === 'info')) {
|
||||
await dismissReviews({ github, context, dry })
|
||||
return
|
||||
}
|
||||
|
||||
// In the case of "error" severity, we also fail the job.
|
||||
// Those should be considered blocking and not be dismissable via review.
|
||||
if (results.some(({ severity }) => severity == 'error'))
|
||||
if (results.some(({ severity }) => severity === 'error'))
|
||||
process.exitCode = 1
|
||||
|
||||
core.summary.addRaw('This report is automatically generated by the `PR / Check / cherry-pick` CI workflow.', true)
|
||||
core.summary.addRaw(
|
||||
'This report is automatically generated by the `PR / Check / cherry-pick` CI workflow.',
|
||||
true,
|
||||
)
|
||||
core.summary.addEOL()
|
||||
core.summary.addRaw("Some of the commits in this PR require the author's and reviewer's attention.", true)
|
||||
core.summary.addRaw(
|
||||
"Some of the commits in this PR require the author's and reviewer's attention.",
|
||||
true,
|
||||
)
|
||||
core.summary.addEOL()
|
||||
|
||||
if (results.some(({ type }) => type === 'no-commit-hash')) {
|
||||
core.summary.addRaw('Please follow the [backporting guidelines](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#how-to-backport-pull-requests) and cherry-pick with the `-x` flag.', true)
|
||||
core.summary.addRaw('This requires changes to the unstable `master` and `staging` branches first, before backporting them.', true)
|
||||
core.summary.addRaw(
|
||||
'Please follow the [backporting guidelines](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#how-to-backport-pull-requests) and cherry-pick with the `-x` flag.',
|
||||
true,
|
||||
)
|
||||
core.summary.addRaw(
|
||||
'This requires changes to the unstable `master` and `staging` branches first, before backporting them.',
|
||||
true,
|
||||
)
|
||||
core.summary.addEOL()
|
||||
core.summary.addRaw('Occasionally, commits are not cherry-picked at all, for example when updating minor versions of packages which have already advanced to the next major on unstable.', true)
|
||||
core.summary.addRaw('These commits can optionally be marked with a `Not-cherry-picked-because: <reason>` footer.', true)
|
||||
core.summary.addRaw(
|
||||
'Occasionally, commits are not cherry-picked at all, for example when updating minor versions of packages which have already advanced to the next major on unstable.',
|
||||
true,
|
||||
)
|
||||
core.summary.addRaw(
|
||||
'These commits can optionally be marked with a `Not-cherry-picked-because: <reason>` footer.',
|
||||
true,
|
||||
)
|
||||
core.summary.addEOL()
|
||||
}
|
||||
|
||||
if (results.some(({ type }) => type === 'diff')) {
|
||||
core.summary.addRaw('Sometimes it is not possible to cherry-pick exactly the same patch.', true)
|
||||
core.summary.addRaw('This most frequently happens when resolving merge conflicts.', true)
|
||||
core.summary.addRaw('The range-diff will help to review the resolution of conflicts.', true)
|
||||
core.summary.addRaw(
|
||||
'Sometimes it is not possible to cherry-pick exactly the same patch.',
|
||||
true,
|
||||
)
|
||||
core.summary.addRaw(
|
||||
'This most frequently happens when resolving merge conflicts.',
|
||||
true,
|
||||
)
|
||||
core.summary.addRaw(
|
||||
'The range-diff will help to review the resolution of conflicts.',
|
||||
true,
|
||||
)
|
||||
core.summary.addEOL()
|
||||
}
|
||||
|
||||
core.summary.addRaw('If you need to merge this PR despite the warnings, please [dismiss](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/dismissing-a-pull-request-review) this review shortly before merging.', true)
|
||||
core.summary.addRaw(
|
||||
'If you need to merge this PR despite the warnings, please [dismiss](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/dismissing-a-pull-request-review) this review shortly before merging.',
|
||||
true,
|
||||
)
|
||||
|
||||
results.forEach(({ severity, message, diff }) => {
|
||||
if (severity == 'info') return
|
||||
if (severity === 'info') return
|
||||
|
||||
// The docs for markdown alerts only show examples with markdown blockquote syntax, like this:
|
||||
// > [!WARNING]
|
||||
@@ -256,7 +271,7 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
// Whether this is intended or just an implementation detail is unclear.
|
||||
core.summary.addRaw('<blockquote>')
|
||||
core.summary.addRaw(
|
||||
`\n\n[!${({ important: 'IMPORTANT', warning: 'WARNING', error: 'CAUTION' })[severity]}]`,
|
||||
`\n\n[!${{ important: 'IMPORTANT', warning: 'WARNING', error: 'CAUTION' }[severity]}]`,
|
||||
true,
|
||||
)
|
||||
core.summary.addRaw(`${message}`, true)
|
||||
@@ -298,45 +313,9 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
const body = core.summary.stringify()
|
||||
core.summary.write()
|
||||
|
||||
const pendingReview = (
|
||||
await github.paginate(github.rest.pulls.listReviews, {
|
||||
...context.repo,
|
||||
pull_number,
|
||||
})
|
||||
).find(
|
||||
(review) =>
|
||||
review.user.login == 'github-actions[bot]' &&
|
||||
// If a review is still pending, we can just update this instead
|
||||
// of posting a new one.
|
||||
(review.state == 'CHANGES_REQUESTED' ||
|
||||
// No need to post a new review, if an older one with the exact
|
||||
// same content had already been dismissed.
|
||||
review.body == body),
|
||||
)
|
||||
|
||||
if (dry) {
|
||||
if (pendingReview)
|
||||
core.info('pending review found: ' + pendingReview.html_url)
|
||||
else core.info('no pending review found')
|
||||
} else {
|
||||
// Either of those two requests could fail for very long comments. This can only happen
|
||||
// with multiple commits all hitting the truncation limit for the diff. If you ever hit
|
||||
// this case, consider just splitting up those commits into multiple PRs.
|
||||
if (pendingReview) {
|
||||
await github.rest.pulls.updateReview({
|
||||
...context.repo,
|
||||
pull_number,
|
||||
review_id: pendingReview.id,
|
||||
body,
|
||||
})
|
||||
} else {
|
||||
await github.rest.pulls.createReview({
|
||||
...context.repo,
|
||||
pull_number,
|
||||
event: 'REQUEST_CHANGES',
|
||||
body,
|
||||
})
|
||||
}
|
||||
}
|
||||
// Posting a review could fail for very long comments. This can only happen with
|
||||
// multiple commits all hitting the truncation limit for the diff. If you ever hit
|
||||
// this case, consider just splitting up those commits into multiple PRs.
|
||||
await postReview({ github, context, core, dry, body })
|
||||
})
|
||||
}
|
||||
|
||||
+18
-17
@@ -1,4 +1,4 @@
|
||||
module.exports = async function ({ github, context, core, dry }) {
|
||||
module.exports = async ({ github, context, core, dry }) => {
|
||||
const path = require('node:path')
|
||||
const { DefaultArtifactClient } = require('@actions/artifact')
|
||||
const { readFile, writeFile } = require('node:fs/promises')
|
||||
@@ -27,7 +27,7 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
|
||||
const approvals = new Set(
|
||||
reviews
|
||||
.filter((review) => review.state == 'APPROVED')
|
||||
.filter((review) => review.state === 'APPROVED')
|
||||
.map((review) => review.user?.id),
|
||||
)
|
||||
|
||||
@@ -37,7 +37,7 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
// This is intentionally less than the time that Eval takes, so that the label job
|
||||
// running after Eval can indeed label the PR as conflicted if that is the case.
|
||||
const merge_commit_sha_valid =
|
||||
new Date() - new Date(pull_request.created_at) > 3 * 60 * 1000
|
||||
Date.now() - new Date(pull_request.created_at) > 3 * 60 * 1000
|
||||
|
||||
const prLabels = {
|
||||
// We intentionally don't use the mergeable or mergeable_state attributes.
|
||||
@@ -53,8 +53,8 @@ module.exports = async function ({ 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,
|
||||
'12.approvals: 1': approvals.size == 1,
|
||||
'12.approvals: 2': approvals.size == 2,
|
||||
'12.approvals: 1': approvals.size === 1,
|
||||
'12.approvals: 2': approvals.size === 2,
|
||||
'12.approvals: 3+': approvals.size >= 3,
|
||||
'12.first-time contribution': [
|
||||
'NONE',
|
||||
@@ -104,8 +104,8 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
// existing reviews, too.
|
||||
'9.needs: reviewer':
|
||||
!pull_request.draft &&
|
||||
pull_request.requested_reviewers.length == 0 &&
|
||||
reviews.length == 0,
|
||||
pull_request.requested_reviewers.length === 0 &&
|
||||
reviews.length === 0,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -125,8 +125,7 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
// called "comparison", yet, will skip the download.
|
||||
const expired =
|
||||
!artifact ||
|
||||
new Date(artifact?.expires_at ?? 0) <
|
||||
new Date(new Date().getTime() + 60 * 1000)
|
||||
new Date(artifact?.expires_at ?? 0) < new Date(Date.now() + 60 * 1000)
|
||||
log('Artifact expires at', artifact?.expires_at ?? '<n/a>')
|
||||
if (!expired) {
|
||||
stats.artifacts++
|
||||
@@ -175,7 +174,7 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
async function handle({ item, stats }) {
|
||||
try {
|
||||
const log = (k, v, skip) => {
|
||||
core.info(`#${item.number} - ${k}: ${v}` + (skip ? ' (skipped)' : ''))
|
||||
core.info(`#${item.number} - ${k}: ${v}${skip ? ' (skipped)' : ''}`)
|
||||
return skip
|
||||
}
|
||||
|
||||
@@ -257,7 +256,7 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
|
||||
// No need for an API request, if all labels are the same.
|
||||
const hasChanges = Object.keys(after).some(
|
||||
(name) => (before[name] ?? false) != after[name],
|
||||
(name) => (before[name] ?? false) !== after[name],
|
||||
)
|
||||
if (log('Has changes', hasChanges, !hasChanges)) return
|
||||
|
||||
@@ -297,13 +296,15 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
// Go back as far as the last successful run of this workflow to make sure
|
||||
// we are not leaving anyone behind on GHA failures.
|
||||
// Defaults to go back 1 hour on the first run.
|
||||
new Date(lastRun?.created_at ?? new Date().getTime() - 1 * 60 * 60 * 1000).getTime(),
|
||||
new Date(
|
||||
lastRun?.created_at ?? Date.now() - 1 * 60 * 60 * 1000,
|
||||
).getTime(),
|
||||
// Go back max. 1 day to prevent hitting all API rate limits immediately,
|
||||
// when GH API returns a wrong workflow by accident.
|
||||
new Date().getTime() - 24 * 60 * 60 * 1000,
|
||||
Date.now() - 24 * 60 * 60 * 1000,
|
||||
),
|
||||
)
|
||||
core.info('cutoff timestamp: ' + cutoff.toISOString())
|
||||
core.info(`cutoff timestamp: ${cutoff.toISOString()}`)
|
||||
|
||||
const updatedItems = await github.paginate(
|
||||
github.rest.search.issuesAndPullRequests,
|
||||
@@ -400,12 +401,12 @@ module.exports = async function ({ github, context, core, dry }) {
|
||||
.concat(updatedItems, allItems.data)
|
||||
.filter(
|
||||
(thisItem, idx, arr) =>
|
||||
idx ==
|
||||
arr.findIndex((firstItem) => firstItem.number == thisItem.number),
|
||||
idx ===
|
||||
arr.findIndex((firstItem) => firstItem.number === thisItem.number),
|
||||
)
|
||||
|
||||
;(await Promise.allSettled(items.map((item) => handle({ item, stats }))))
|
||||
.filter(({ status }) => status == 'rejected')
|
||||
.filter(({ status }) => status === 'rejected')
|
||||
.map(({ reason }) =>
|
||||
core.setFailed(`${reason.message}\n${reason.cause.stack}`),
|
||||
)
|
||||
|
||||
+178
-3
@@ -1,4 +1,7 @@
|
||||
module.exports = async function ({ github, context, core }) {
|
||||
const { classify } = require('../supportedBranches.js')
|
||||
const { postReview } = require('./reviews.js')
|
||||
|
||||
module.exports = async ({ github, context, core, dry }) => {
|
||||
const pull_number = context.payload.pull_request.number
|
||||
|
||||
for (const retryInterval of [5, 10, 20, 40, 80]) {
|
||||
@@ -20,6 +23,162 @@ module.exports = async function ({ github, context, core }) {
|
||||
continue
|
||||
}
|
||||
|
||||
const { base, head } = prInfo
|
||||
|
||||
const baseClassification = classify(base.ref)
|
||||
core.setOutput('base', baseClassification)
|
||||
console.log('base classification:', baseClassification)
|
||||
|
||||
const headClassification =
|
||||
base.repo.full_name === head.repo.full_name
|
||||
? classify(head.ref)
|
||||
: // PRs from forks are always considered WIP.
|
||||
{ type: ['wip'] }
|
||||
core.setOutput('head', headClassification)
|
||||
console.log('head classification:', headClassification)
|
||||
|
||||
if (baseClassification.type.includes('channel')) {
|
||||
const { stable, version } = baseClassification
|
||||
const correctBranch = stable ? `release-${version}` : 'master'
|
||||
const body = [
|
||||
'The `nixos-*` and `nixpkgs-*` branches are pushed to by the channel release script and should not be merged into directly.',
|
||||
'',
|
||||
`Please target \`${correctBranch}\` instead.`,
|
||||
].join('\n')
|
||||
|
||||
await postReview({ github, context, core, dry, body })
|
||||
|
||||
throw new Error('The PR targets a channel branch.')
|
||||
}
|
||||
|
||||
if (headClassification.type.includes('wip')) {
|
||||
// In the following, we look at the git history to determine the base branch that
|
||||
// this Pull Request branched off of. This is *supposed* to be the branch that it
|
||||
// merges into, but humans make mistakes. Once that happens we want to error out as
|
||||
// early as possible.
|
||||
|
||||
// To determine the "real base", we are looking at the merge-base of primary development
|
||||
// branches and the head of the PR. The merge-base which results in the least number of
|
||||
// commits between that base and head is the real base. We can query for this via GitHub's
|
||||
// REST API. There can be multiple candidates for the real base with the same number of
|
||||
// commits. In this case we pick the "best" candidate by a fixed ordering of branches,
|
||||
// as defined in ci/supportedBranches.js.
|
||||
//
|
||||
// These requests take a while, when comparing against the wrong release - they need
|
||||
// to look at way more than 10k commits in that case. Thus, we try to minimize the
|
||||
// number of requests across releases:
|
||||
// - First, we look at the primary development branches only: master and release-xx.yy.
|
||||
// The branch with the fewest commits gives us the release this PR belongs to.
|
||||
// - We then compare this number against the relevant staging branches for this release
|
||||
// to find the exact branch that this belongs to.
|
||||
|
||||
// All potential development branches
|
||||
const branches = (
|
||||
await github.paginate(github.rest.repos.listBranches, {
|
||||
...context.repo,
|
||||
per_page: 100,
|
||||
})
|
||||
).map(({ name }) => classify(name))
|
||||
|
||||
// All stable primary development branches from latest to oldest.
|
||||
const releases = branches
|
||||
.filter(({ stable, type }) => type.includes('primary') && stable)
|
||||
.sort((a, b) => b.version.localeCompare(a.version))
|
||||
|
||||
async function mergeBase({ branch, order, version }) {
|
||||
const { data } = await github.rest.repos.compareCommitsWithBasehead({
|
||||
...context.repo,
|
||||
basehead: `${branch}...${head.sha}`,
|
||||
// Pagination for this endpoint is about the commits listed, which we don't care about.
|
||||
per_page: 1,
|
||||
// Taking the second page skips the list of files of this changeset.
|
||||
page: 2,
|
||||
})
|
||||
return {
|
||||
branch,
|
||||
order,
|
||||
version,
|
||||
commits: data.total_commits,
|
||||
sha: data.merge_base_commit.sha,
|
||||
}
|
||||
}
|
||||
|
||||
// Multiple branches can be OK at the same time, if the PR was created of a merge-base,
|
||||
// thus storing as array.
|
||||
let candidates = [await mergeBase(classify('master'))]
|
||||
for (const release of releases) {
|
||||
const nextCandidate = await mergeBase(release)
|
||||
if (candidates[0].commits === nextCandidate.commits)
|
||||
candidates.push(nextCandidate)
|
||||
if (candidates[0].commits > nextCandidate.commits)
|
||||
candidates = [nextCandidate]
|
||||
// The number 10000 is principally arbitrary, but the GitHub API returns this value
|
||||
// when the number of commits exceeds it in reality. The difference between two stable releases
|
||||
// is certainly more than 10k commits, thus this works for us as well: If we're targeting
|
||||
// a wrong release, the number *will* be 10000.
|
||||
if (candidates[0].commits < 10000) break
|
||||
}
|
||||
|
||||
core.info(`This PR is for NixOS ${candidates[0].version}.`)
|
||||
|
||||
// Secondary development branches for the selected version only.
|
||||
const secondary = branches.filter(
|
||||
({ branch, type, version }) =>
|
||||
type.includes('secondary') && version === candidates[0].version,
|
||||
)
|
||||
|
||||
// Make sure that we always check the current target as well, even if its a WIP branch.
|
||||
// If it's not a WIP branch, it was already included in either releases or secondary.
|
||||
if (classify(base.ref).type.includes('wip')) {
|
||||
secondary.push(classify(base.ref))
|
||||
}
|
||||
|
||||
for (const branch of secondary) {
|
||||
const nextCandidate = await mergeBase(branch)
|
||||
if (candidates[0].commits === nextCandidate.commits)
|
||||
candidates.push(nextCandidate)
|
||||
if (candidates[0].commits > nextCandidate.commits)
|
||||
candidates = [nextCandidate]
|
||||
}
|
||||
|
||||
// If the current branch is among the candidates, this is always better than any other,
|
||||
// thus sorting at -1.
|
||||
candidates = candidates
|
||||
.map((candidate) =>
|
||||
candidate.branch === base.ref
|
||||
? { ...candidate, order: -1 }
|
||||
: candidate,
|
||||
)
|
||||
.sort((a, b) => a.order - b.order)
|
||||
|
||||
const best = candidates.at(0)
|
||||
|
||||
core.info('The base branches for this PR are:')
|
||||
core.info(`github: ${base.ref}`)
|
||||
core.info(
|
||||
`candidates: ${candidates.map(({ branch }) => branch).join(',')}`,
|
||||
)
|
||||
core.info(`best candidate: ${best.branch}`)
|
||||
|
||||
if (best.branch !== base.ref) {
|
||||
const current = await mergeBase(classify(base.ref))
|
||||
const body = [
|
||||
`The PR's base branch is set to \`${current.branch}\`, but ${current.commits === 10000 ? 'at least 10000' : current.commits - best.commits} commits from the \`${best.branch}\` branch are included. Make sure you know the [right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions), then:`,
|
||||
`- If the changes should go to the \`${best.branch}\` branch, [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request).`,
|
||||
`- If the changes should go to the \`${current.branch}\` branch, rebase your PR onto the correct merge-base:`,
|
||||
' ```bash',
|
||||
` # git rebase --onto $(git merge-base upstream/${current.branch} HEAD) $(git merge-base upstream/${best.branch} HEAD)`,
|
||||
` git rebase --onto ${current.sha} ${best.sha}`,
|
||||
` git push --force-with-lease`,
|
||||
' ```',
|
||||
].join('\n')
|
||||
|
||||
await postReview({ github, context, core, dry, body })
|
||||
|
||||
throw new Error(`The PR contains commits from a different base.`)
|
||||
}
|
||||
}
|
||||
|
||||
let mergedSha, targetSha
|
||||
|
||||
if (prInfo.mergeable) {
|
||||
@@ -35,11 +194,11 @@ module.exports = async function ({ github, context, core }) {
|
||||
} else {
|
||||
core.warning('The PR has a merge conflict.')
|
||||
|
||||
mergedSha = prInfo.head.sha
|
||||
mergedSha = head.sha
|
||||
targetSha = (
|
||||
await github.rest.repos.compareCommitsWithBasehead({
|
||||
...context.repo,
|
||||
basehead: `${prInfo.base.sha}...${prInfo.head.sha}`,
|
||||
basehead: `${base.sha}...${head.sha}`,
|
||||
})
|
||||
).data.merge_base_commit.sha
|
||||
}
|
||||
@@ -49,6 +208,22 @@ module.exports = async function ({ github, context, core }) {
|
||||
)
|
||||
core.setOutput('mergedSha', mergedSha)
|
||||
core.setOutput('targetSha', targetSha)
|
||||
|
||||
core.setOutput('systems', require('../supportedSystems.json'))
|
||||
|
||||
const files = (
|
||||
await github.paginate(github.rest.pulls.listFiles, {
|
||||
...context.repo,
|
||||
pull_number: context.payload.pull_request.number,
|
||||
per_page: 100,
|
||||
})
|
||||
).map((file) => file.filename)
|
||||
|
||||
const touched = []
|
||||
if (files.includes('ci/pinned.json')) touched.push('pinned')
|
||||
if (files.includes('ci/OWNERS')) touched.push('owners')
|
||||
core.setOutput('touched', touched)
|
||||
|
||||
return
|
||||
}
|
||||
throw new Error(
|
||||
|
||||
@@ -0,0 +1,85 @@
|
||||
async function dismissReviews({ github, context, dry }) {
|
||||
const pull_number = context.payload.pull_request.number
|
||||
|
||||
if (dry) {
|
||||
return
|
||||
}
|
||||
|
||||
await Promise.all(
|
||||
(
|
||||
await github.paginate(github.rest.pulls.listReviews, {
|
||||
...context.repo,
|
||||
pull_number,
|
||||
})
|
||||
)
|
||||
.filter((review) => review.user?.login === 'github-actions[bot]')
|
||||
.map(async (review) => {
|
||||
if (review.state === 'CHANGES_REQUESTED') {
|
||||
await github.rest.pulls.dismissReview({
|
||||
...context.repo,
|
||||
pull_number,
|
||||
review_id: review.id,
|
||||
message: 'All good now, thank you!',
|
||||
})
|
||||
}
|
||||
await github.graphql(
|
||||
`mutation($node_id:ID!) {
|
||||
minimizeComment(input: {
|
||||
classifier: RESOLVED,
|
||||
subjectId: $node_id
|
||||
})
|
||||
{ clientMutationId }
|
||||
}`,
|
||||
{ node_id: review.node_id },
|
||||
)
|
||||
}),
|
||||
)
|
||||
}
|
||||
|
||||
async function postReview({ github, context, core, dry, body }) {
|
||||
const pull_number = context.payload.pull_request.number
|
||||
|
||||
const pendingReview = (
|
||||
await github.paginate(github.rest.pulls.listReviews, {
|
||||
...context.repo,
|
||||
pull_number,
|
||||
})
|
||||
).find(
|
||||
(review) =>
|
||||
review.user?.login === 'github-actions[bot]' &&
|
||||
// If a review is still pending, we can just update this instead
|
||||
// of posting a new one.
|
||||
(review.state === 'CHANGES_REQUESTED' ||
|
||||
// No need to post a new review, if an older one with the exact
|
||||
// same content had already been dismissed.
|
||||
review.body === body),
|
||||
)
|
||||
|
||||
if (dry) {
|
||||
if (pendingReview)
|
||||
core.info(`pending review found: ${pendingReview.html_url}`)
|
||||
else core.info('no pending review found')
|
||||
core.info(body)
|
||||
} else {
|
||||
if (pendingReview) {
|
||||
await github.rest.pulls.updateReview({
|
||||
...context.repo,
|
||||
pull_number,
|
||||
review_id: pendingReview.id,
|
||||
body,
|
||||
})
|
||||
} else {
|
||||
await github.rest.pulls.createReview({
|
||||
...context.repo,
|
||||
pull_number,
|
||||
event: 'REQUEST_CHANGES',
|
||||
body,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
dismissReviews,
|
||||
postReview,
|
||||
}
|
||||
+10
-7
@@ -7,7 +7,7 @@ import { program } from 'commander'
|
||||
import * as core from '@actions/core'
|
||||
import { getOctokit } from '@actions/github'
|
||||
|
||||
async function run(action, owner, repo, pull_number, dry = true) {
|
||||
async function run(action, owner, repo, pull_number, options = {}) {
|
||||
const token = execSync('gh auth token', { encoding: 'utf-8' }).trim()
|
||||
|
||||
const github = getOctokit(token)
|
||||
@@ -35,7 +35,8 @@ async function run(action, owner, repo, pull_number, dry = true) {
|
||||
},
|
||||
},
|
||||
core,
|
||||
dry,
|
||||
dry: true,
|
||||
...options,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -45,9 +46,10 @@ program
|
||||
.argument('<owner>', 'Owner of the GitHub repository to check (Example: NixOS)')
|
||||
.argument('<repo>', 'Name of the GitHub repository to check (Example: nixpkgs)')
|
||||
.argument('<pr>', 'Number of the Pull Request to check')
|
||||
.action(async (owner, repo, pr) => {
|
||||
.option('--no-dry', 'Make actual modifications')
|
||||
.action(async (owner, repo, pr, options) => {
|
||||
const prepare = (await import('./prepare.js')).default
|
||||
run(prepare, owner, repo, pr)
|
||||
await run(prepare, owner, repo, pr, options)
|
||||
})
|
||||
|
||||
program
|
||||
@@ -56,9 +58,10 @@ program
|
||||
.argument('<owner>', 'Owner of the GitHub repository to check (Example: NixOS)')
|
||||
.argument('<repo>', 'Name of the GitHub repository to check (Example: nixpkgs)')
|
||||
.argument('<pr>', 'Number of the Pull Request to check')
|
||||
.action(async (owner, repo, pr) => {
|
||||
.option('--no-cherry-picks', 'Do not expect cherry-picks.')
|
||||
.action(async (owner, repo, pr, options) => {
|
||||
const commits = (await import('./commits.js')).default
|
||||
run(commits, owner, repo, pr)
|
||||
await run(commits, owner, repo, pr, options)
|
||||
})
|
||||
|
||||
program
|
||||
@@ -74,7 +77,7 @@ program
|
||||
try {
|
||||
process.env.GITHUB_WORKSPACE = tmp
|
||||
process.chdir(tmp)
|
||||
run(labels, owner, repo, pr, options.dry)
|
||||
await run(labels, owner, repo, pr, options)
|
||||
} finally {
|
||||
rmSync(tmp, { recursive: true })
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
module.exports = async function ({ github, core }, callback) {
|
||||
module.exports = async ({ github, core }, callback) => {
|
||||
const Bottleneck = require('bottleneck')
|
||||
|
||||
const stats = {
|
||||
@@ -23,7 +23,7 @@ module.exports = async function ({ github, core }, callback) {
|
||||
// Requests to a different host do not count against the rate limit.
|
||||
if (options.url.startsWith('https://github.com')) return request(options)
|
||||
// Requests to the /rate_limit endpoint do not count against the rate limit.
|
||||
if (options.url == '/rate_limit') return request(options)
|
||||
if (options.url === '/rate_limit') return request(options)
|
||||
// Search requests are in a different resource group, which allows 30 requests / minute.
|
||||
// We do less than a handful each run, so not implementing throttling for now.
|
||||
if (options.url.startsWith('/search/')) return request(options)
|
||||
|
||||
+10
-4
@@ -13,9 +13,15 @@ let
|
||||
with lib.fileset;
|
||||
path:
|
||||
toSource {
|
||||
fileset = (gitTracked path);
|
||||
fileset = difference (gitTracked path) (unions [
|
||||
(path + /.github)
|
||||
(path + /ci)
|
||||
]);
|
||||
root = path;
|
||||
};
|
||||
|
||||
filteredBase = filtered base;
|
||||
filteredHead = filtered head;
|
||||
in
|
||||
runCommand "nixpkgs-vet"
|
||||
{
|
||||
@@ -27,11 +33,11 @@ runCommand "nixpkgs-vet"
|
||||
''
|
||||
export NIX_STATE_DIR=$(mktemp -d)
|
||||
|
||||
nixpkgs-vet --base ${filtered base} ${filtered head}
|
||||
nixpkgs-vet --base ${filteredBase} ${filteredHead}
|
||||
|
||||
# TODO: Upstream into nixpkgs-vet, see:
|
||||
# https://github.com/NixOS/nixpkgs-vet/issues/164
|
||||
badFiles=$(find ${filtered head}/pkgs -type f -name '*.nix' -print | xargs grep -l '^[^#]*<nixpkgs/' || true)
|
||||
badFiles=$(find ${filteredHead}/pkgs -type f -name '*.nix' -print | xargs grep -l '^[^#]*<nixpkgs/' || true)
|
||||
if [[ -n $badFiles ]]; then
|
||||
echo "Nixpkgs is not allowed to use <nixpkgs> to refer to itself."
|
||||
echo "The offending files:"
|
||||
@@ -41,7 +47,7 @@ runCommand "nixpkgs-vet"
|
||||
|
||||
# TODO: Upstream into nixpkgs-vet, see:
|
||||
# https://github.com/NixOS/nixpkgs-vet/issues/166
|
||||
conflictingPaths=$(find ${filtered head} | awk '{ print $1 " " tolower($1) }' | sort -k2 | uniq -D -f 1 | cut -d ' ' -f 1)
|
||||
conflictingPaths=$(find ${filteredHead} | awk '{ print $1 " " tolower($1) }' | sort -k2 | uniq -D -f 1 | cut -d ' ' -f 1)
|
||||
if [[ -n $conflictingPaths ]]; then
|
||||
echo "Files in nixpkgs must not vary only by case."
|
||||
echo "The offending paths:"
|
||||
|
||||
@@ -17,15 +17,12 @@ stdenvNoCC.mkDerivation {
|
||||
./get-code-owners.sh
|
||||
./request-reviewers.sh
|
||||
./request-code-owner-reviews.sh
|
||||
./verify-base-branch.sh
|
||||
./dev-branches.txt
|
||||
];
|
||||
};
|
||||
nativeBuildInputs = [ makeWrapper ];
|
||||
dontBuild = true;
|
||||
installPhase = ''
|
||||
mkdir -p $out/bin
|
||||
mv dev-branches.txt $out/bin
|
||||
for bin in *.sh; do
|
||||
mv "$bin" "$out/bin"
|
||||
wrapProgram "$out/bin/$bin" \
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
# Trusted development branches:
|
||||
# These generally require PRs to update and are built by Hydra.
|
||||
# Keep this synced with the branches in .github/workflows/eval.yml
|
||||
master
|
||||
staging
|
||||
release-*
|
||||
staging-*
|
||||
haskell-updates
|
||||
python-updates
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Requests reviews for a PR after verifying that the base branch is correct
|
||||
# Requests reviews for a PR
|
||||
|
||||
set -euo pipefail
|
||||
tmp=$(mktemp -d)
|
||||
@@ -11,14 +11,6 @@ log() {
|
||||
echo "$@" >&2
|
||||
}
|
||||
|
||||
effect() {
|
||||
if [[ -n "${DRY_MODE:-}" ]]; then
|
||||
log "Skipping in dry mode:" "${@@Q}"
|
||||
else
|
||||
"$@"
|
||||
fi
|
||||
}
|
||||
|
||||
if (( $# < 3 )); then
|
||||
log "Usage: $0 GITHUB_REPO PR_NUMBER OWNERS_FILE"
|
||||
exit 1
|
||||
@@ -63,20 +55,6 @@ git -C "$tmp/nixpkgs.git" config remote.fork.promisor true
|
||||
git -C "$tmp/nixpkgs.git" fetch --no-tags fork "$prBranch"
|
||||
headRef=$(git -C "$tmp/nixpkgs.git" rev-parse refs/remotes/fork/"$prBranch")
|
||||
|
||||
log "Checking correctness of the base branch"
|
||||
if ! "$SCRIPT_DIR"/verify-base-branch.sh "$tmp/nixpkgs.git" "$headRef" "$baseRepo" "$baseBranch" "$prRepo" "$prBranch" | tee "$tmp/invalid-base-error" >&2; then
|
||||
log "Posting error as comment"
|
||||
if ! response=$(effect gh api \
|
||||
--method POST \
|
||||
-H "Accept: application/vnd.github+json" \
|
||||
-H "X-GitHub-Api-Version: 2022-11-28" \
|
||||
"/repos/$baseRepo/issues/$prNumber/comments" \
|
||||
-F "body=@$tmp/invalid-base-error"); then
|
||||
log "Failed to post the comment: $response"
|
||||
fi
|
||||
exit 1
|
||||
fi
|
||||
|
||||
log "Requesting reviews from code owners"
|
||||
"$SCRIPT_DIR"/get-code-owners.sh "$tmp/nixpkgs.git" "$ownersFile" "$baseBranch" "$headRef" | \
|
||||
"$SCRIPT_DIR"/request-reviewers.sh "$baseRepo" "$prNumber" "$prAuthor"
|
||||
|
||||
@@ -1,104 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
# Check that a PR doesn't include commits from other development branches.
|
||||
# Fails with next steps if it does
|
||||
|
||||
set -euo pipefail
|
||||
tmp=$(mktemp -d)
|
||||
trap 'rm -rf "$tmp"' exit
|
||||
SCRIPT_DIR=$(dirname "$0")
|
||||
|
||||
log() {
|
||||
echo "$@" >&2
|
||||
}
|
||||
|
||||
# Small helper to check whether an element is in a list
|
||||
# Usage: `elementIn foo "${list[@]}"`
|
||||
elementIn() {
|
||||
local e match=$1
|
||||
shift
|
||||
for e; do
|
||||
if [[ "$e" == "$match" ]]; then
|
||||
return 0
|
||||
fi
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
if (( $# < 6 )); then
|
||||
log "Usage: $0 LOCAL_REPO HEAD_REF BASE_REPO BASE_BRANCH PR_REPO PR_BRANCH"
|
||||
exit 1
|
||||
fi
|
||||
localRepo=$1
|
||||
headRef=$2
|
||||
baseRepo=$3
|
||||
baseBranch=$4
|
||||
prRepo=$5
|
||||
prBranch=$6
|
||||
|
||||
# All development branches
|
||||
devBranchPatterns=()
|
||||
while read -r pattern; do
|
||||
if [[ "$pattern" != '#'* ]]; then
|
||||
devBranchPatterns+=("$pattern")
|
||||
fi
|
||||
done < "$SCRIPT_DIR/dev-branches.txt"
|
||||
|
||||
git -C "$localRepo" branch --list --format "%(refname:short)" "${devBranchPatterns[@]}" > "$tmp/dev-branches"
|
||||
readarray -t devBranches < "$tmp/dev-branches"
|
||||
|
||||
if [[ "$baseRepo" == "$prRepo" ]] && elementIn "$prBranch" "${devBranches[@]}"; then
|
||||
log "This PR merges $prBranch into $baseBranch, no commit check necessary"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# The current merge base of the PR
|
||||
prMergeBase=$(git -C "$localRepo" merge-base "$baseBranch" "$headRef")
|
||||
log "The PR's merge base with the base branch $baseBranch is $prMergeBase"
|
||||
|
||||
# This is purely for debugging
|
||||
git -C "$localRepo" rev-list --reverse "$baseBranch".."$headRef" > "$tmp/pr-commits"
|
||||
log "The PR includes these $(wc -l < "$tmp/pr-commits") commits:"
|
||||
cat <"$tmp/pr-commits" >&2
|
||||
|
||||
for testBranch in "${devBranches[@]}"; do
|
||||
|
||||
if [[ -z "$(git -C "$localRepo" rev-list -1 --since="1 month ago" "$testBranch")" ]]; then
|
||||
log "Not checking $testBranch, was inactive for the last month"
|
||||
continue
|
||||
fi
|
||||
log "Checking if commits from $testBranch are included in the PR"
|
||||
|
||||
# We need to check for any commits that are in the PR which are also in the test branch.
|
||||
# We could check each commit from the PR individually, but that's unnecessarily slow.
|
||||
#
|
||||
# This does _almost_ what we want: `git rev-list --count headRef testBranch ^baseBranch`,
|
||||
# except that it includes commits that are reachable from _either_ headRef or testBranch,
|
||||
# instead of restricting it to ones reachable by both
|
||||
|
||||
# Easily fixable though, because we can use `git merge-base testBranch headRef`
|
||||
# to get the least common ancestor (aka merge base) commit reachable by both.
|
||||
# If the branch being tested is indeed the right base branch,
|
||||
# this is then also the commit from that branch that the PR is based on top of.
|
||||
testMergeBase=$(git -C "$localRepo" merge-base "$testBranch" "$headRef")
|
||||
|
||||
# And then use the `git rev-list --count`, but replacing the non-working
|
||||
# `headRef testBranch` with the merge base of the two.
|
||||
extraCommits=$(git -C "$localRepo" rev-list --count "$testMergeBase" ^"$baseBranch")
|
||||
|
||||
if (( extraCommits != 0 )); then
|
||||
log -e "\e[33m"
|
||||
echo "The PR's base branch is set to $baseBranch, but $extraCommits commits from the $testBranch branch are included. Make sure you know the [right base branch for your changes](https://github.com/NixOS/nixpkgs/blob/master/CONTRIBUTING.md#branch-conventions), then:"
|
||||
echo "- If the changes should go to the $testBranch branch, [change the base branch](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/changing-the-base-branch-of-a-pull-request) to $testBranch"
|
||||
echo "- If the changes should go to the $baseBranch branch, rebase your PR onto the merge base with the $baseBranch branch:"
|
||||
echo " \`\`\`bash"
|
||||
echo " # git rebase --onto \$(git merge-base upstream/$baseBranch HEAD) \$(git merge-base upstream/$testBranch HEAD)"
|
||||
echo " git rebase --onto $prMergeBase $testMergeBase"
|
||||
echo " git push --force-with-lease"
|
||||
echo " \`\`\`"
|
||||
log -e "\e[m"
|
||||
exit 1
|
||||
fi
|
||||
done
|
||||
|
||||
log "Base branch is correct, no commits from development branches are included"
|
||||
+21
-3
@@ -9,20 +9,36 @@ const typeConfig = {
|
||||
staging: ['development', 'secondary'],
|
||||
'staging-next': ['development', 'secondary'],
|
||||
'haskell-updates': ['development', 'secondary'],
|
||||
'python-updates': ['development', 'secondary'],
|
||||
nixos: ['channel'],
|
||||
nixpkgs: ['channel'],
|
||||
}
|
||||
|
||||
// "order" ranks the development branches by how likely they are the intended base branch
|
||||
// when they are an otherwise equally good fit according to ci/github-script/prepare.js.
|
||||
const orderConfig = {
|
||||
master: 0,
|
||||
release: 1,
|
||||
staging: 2,
|
||||
'haskell-updates': 3,
|
||||
'staging-next': 4,
|
||||
}
|
||||
|
||||
function split(branch) {
|
||||
return { ...branch.match(/(?<prefix>.+?)(-(?<version>\d{2}\.\d{2}|unstable)(?:-(?<suffix>.*))?)?$/).groups }
|
||||
return {
|
||||
...branch.match(
|
||||
/(?<prefix>.+?)(-(?<version>\d{2}\.\d{2}|unstable)(?:-(?<suffix>.*))?)?$/,
|
||||
).groups,
|
||||
}
|
||||
}
|
||||
|
||||
function classify(branch) {
|
||||
const { prefix, version } = split(branch)
|
||||
return {
|
||||
branch,
|
||||
order: orderConfig[prefix] ?? Infinity,
|
||||
stable: (version ?? 'unstable') !== 'unstable',
|
||||
type: typeConfig[prefix] ?? [ 'wip' ]
|
||||
type: typeConfig[prefix] ?? ['wip'],
|
||||
version: version ?? 'unstable',
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +52,7 @@ if (!module.parent) {
|
||||
}
|
||||
testSplit('master')
|
||||
testSplit('release-25.05')
|
||||
testSplit('staging')
|
||||
testSplit('staging-next')
|
||||
testSplit('staging-25.05')
|
||||
testSplit('staging-next-25.05')
|
||||
@@ -52,6 +69,7 @@ if (!module.parent) {
|
||||
}
|
||||
testClassify('master')
|
||||
testClassify('release-25.05')
|
||||
testClassify('staging')
|
||||
testClassify('staging-next')
|
||||
testClassify('staging-25.05')
|
||||
testClassify('staging-next-25.05')
|
||||
|
||||
+6
-3
@@ -1,12 +1,15 @@
|
||||
let
|
||||
requiredVersion = import ./lib/minver.nix;
|
||||
missingFeatures = map ({ description, ... }: description) (import ./lib/minfeatures.nix).missing;
|
||||
in
|
||||
|
||||
if !builtins ? nixVersion || builtins.compareVersions requiredVersion builtins.nixVersion == 1 then
|
||||
if missingFeatures != [ ] then
|
||||
|
||||
abort ''
|
||||
|
||||
This version of Nixpkgs requires Nix >= ${requiredVersion}, please upgrade:
|
||||
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:
|
||||
|
||||
- If you are running NixOS, `nixos-rebuild' can be used to upgrade your system.
|
||||
|
||||
|
||||
+5
-3
@@ -1,3 +1,5 @@
|
||||
document.addEventListener('DOMContentLoaded', function(event) {
|
||||
anchors.add('h1[id]:not(div.note h1, div.warning h1, div.tip h1, div.caution h1, div.important h1), h2[id]:not(div.note h2, div.warning h2, div.tip h2, div.caution h2, div.important h2), h3[id]:not(div.note h3, div.warning h3, div.tip h3, div.caution h3, div.important h3), h4[id]:not(div.note h4, div.warning h4, div.tip h4, div.caution h4, div.important h4), h5[id]:not(div.note h5, div.warning h5, div.tip h5, div.caution h5, div.important h5), h6[id]:not(div.note h6, div.warning h6, div.tip h6, div.caution h6, div.important h6)');
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
anchors.add(
|
||||
'h1[id]:not(div.note h1, div.warning h1, div.tip h1, div.caution h1, div.important h1), h2[id]:not(div.note h2, div.warning h2, div.tip h2, div.caution h2, div.important h2), h3[id]:not(div.note h3, div.warning h3, div.tip h3, div.caution h3, div.important h3), h4[id]:not(div.note h4, div.warning h4, div.tip h4, div.caution h4, div.important h4), h5[id]:not(div.note h5, div.warning h5, div.tip h5, div.caution h5, div.important h5), h6[id]:not(div.note h6, div.warning h6, div.tip h6, div.caution h6, div.important h6)',
|
||||
)
|
||||
})
|
||||
|
||||
@@ -896,6 +896,24 @@ If `fetchSubmodules` is `true`, `fetchFromSourcehut` uses `fetchgit`
|
||||
or `fetchhg` with `fetchSubmodules` or `fetchSubrepos` set to `true`,
|
||||
respectively. Otherwise, the fetcher uses `fetchzip`.
|
||||
|
||||
## `fetchFromRadicle` {#fetchfromradicle}
|
||||
|
||||
This is used with Radicle repositories. The arguments expected are similar to `fetchgit`.
|
||||
|
||||
Requires a `seed` argument (e.g. `seed.radicle.xyz` or `rosa.radicle.xyz`) and a `repo` argument
|
||||
(the repository id *without* the `rad:` prefix). Also accepts an optional `node` argument which
|
||||
contains the id of the node from which to fetch the specified ref. If `node` is `null` (the
|
||||
default), a canonical ref is fetched instead.
|
||||
|
||||
```nix
|
||||
fetchFromRadicle {
|
||||
seed = "seed.radicle.xyz";
|
||||
repo = "z3gqcJUoA1n9HaHKufZs5FCSGazv5"; # heartwood
|
||||
tag = "releases/1.3.0";
|
||||
hash = "sha256-4o88BWKGGOjCIQy7anvzbA/kPOO+ZsLMzXJhE61odjw=";
|
||||
}
|
||||
```
|
||||
|
||||
## `requireFile` {#requirefile}
|
||||
|
||||
`requireFile` allows requesting files that cannot be fetched automatically, but whose content is known.
|
||||
|
||||
@@ -405,6 +405,22 @@ The tester produces an empty output and only succeeds when the checks using `exp
|
||||
|
||||
Check that two paths have the same contents.
|
||||
|
||||
`assertion` (string)
|
||||
|
||||
: A message that is printed before the comparison, after `Checking:`.
|
||||
|
||||
`expected` (path or value coercible to store path)
|
||||
|
||||
: The path to the expected [file system object] content
|
||||
|
||||
`actual` (value coercible to store path) <!-- path value is possible, but wrong in practice, but let's not bother readers with our predictions -->
|
||||
|
||||
: The path to the actual file system object content to check
|
||||
|
||||
`postFailureMessage` (string)
|
||||
|
||||
: A message that is printed last if the file system object contents at the two paths don't match exactly.
|
||||
|
||||
:::{.example #ex-testEqualContents-toyexample}
|
||||
|
||||
# Check that two paths have the same contents
|
||||
@@ -427,6 +443,11 @@ testers.testEqualContents {
|
||||
''
|
||||
sed -e 's/bar/baz/g' $base >$out
|
||||
'';
|
||||
# if applicable
|
||||
postFailureMessage = ''
|
||||
The bar-baz replacer produced an unexpected result.
|
||||
If the new behavior is acceptable and validated against the bar-baz specification, run ./adopt-new-bar-baz-result.sh to adjust this test and require the new behavior.
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
@@ -695,3 +716,5 @@ Notable attributes:
|
||||
* `nodes`: the evaluated NixOS configurations. Useful for debugging and exploring the configuration.
|
||||
|
||||
* `driverInteractive`: a script that launches an interactive Python session in the context of the `testScript`.
|
||||
|
||||
[file system object]: https://nix.dev/manual/nix/latest/store/file-system-object
|
||||
|
||||
@@ -15,12 +15,43 @@
|
||||
markdown-code-runner,
|
||||
roboto,
|
||||
treefmt,
|
||||
nixosOptionsDoc,
|
||||
}:
|
||||
stdenvNoCC.mkDerivation (
|
||||
finalAttrs:
|
||||
let
|
||||
inherit (finalAttrs.finalPackage.optionsDoc) optionsJSON;
|
||||
inherit (finalAttrs.finalPackage) epub lib-docs pythonInterpreterTable;
|
||||
|
||||
# Make anything from lib (the module system internals) invisible
|
||||
hide-lib =
|
||||
opt:
|
||||
opt
|
||||
// {
|
||||
visible = if lib.all (decl: decl == "lib/modules.nix") opt.declarations then false else opt.visible;
|
||||
};
|
||||
|
||||
toURL =
|
||||
decl:
|
||||
let
|
||||
declStr = toString decl;
|
||||
root = toString (../..);
|
||||
subpath = lib.removePrefix "/" (lib.removePrefix root declStr);
|
||||
in
|
||||
if lib.hasPrefix root declStr then
|
||||
{
|
||||
url = "https://github.com/NixOS/nixpkgs/blob/master/${subpath}";
|
||||
name = "nixpkgs/${subpath}";
|
||||
}
|
||||
else
|
||||
decl;
|
||||
|
||||
mapURLs = opt: opt // { declarations = map toURL opt.declarations; };
|
||||
|
||||
docs.generic.meta-maintainers = nixosOptionsDoc {
|
||||
inherit (lib.evalModules { modules = [ ../../modules/generic/meta-maintainers.nix ]; }) options;
|
||||
transformOptions = opt: hide-lib (mapURLs opt);
|
||||
};
|
||||
in
|
||||
{
|
||||
name = "nixpkgs-manual";
|
||||
@@ -49,6 +80,7 @@ stdenvNoCC.mkDerivation (
|
||||
ln -s ${optionsJSON}/share/doc/nixos/options.json ./config-options.json
|
||||
ln -s ${treefmt.functionsDoc.markdown} ./packages/treefmt-functions.section.md
|
||||
ln -s ${treefmt.optionsDoc.optionsJSON}/share/doc/nixos/options.json ./treefmt-options.json
|
||||
ln -s ${docs.generic.meta-maintainers.optionsJSON}/share/doc/nixos/options.json ./options-modules-generic-meta-maintainers.json
|
||||
'';
|
||||
|
||||
buildPhase = ''
|
||||
|
||||
@@ -125,11 +125,10 @@ To install Agda without GHC, use `ghc = null;`.
|
||||
|
||||
## Writing Agda packages {#writing-agda-packages}
|
||||
|
||||
To write a nix derivation for an Agda library, first check that the library has a `*.agda-lib` file.
|
||||
To write a nix derivation for an Agda library, first check that the library has a (single) `*.agda-lib` file.
|
||||
|
||||
A derivation can then be written using `agdaPackages.mkDerivation`. This has similar arguments to `stdenv.mkDerivation` with the following additions:
|
||||
|
||||
* `everythingFile` can be used to specify the location of the `Everything.agda` file, defaulting to `./Everything.agda`. If this file does not exist then either it should be patched in or the `buildPhase` should be overridden (see below).
|
||||
* `libraryName` should be the name that appears in the `*.agda-lib` file, defaulting to `pname`.
|
||||
* `libraryFile` should be the file name of the `*.agda-lib` file, defaulting to `${libraryName}.agda-lib`.
|
||||
|
||||
@@ -150,9 +149,9 @@ agdaPackages.mkDerivation {
|
||||
|
||||
### Building Agda packages {#building-agda-packages}
|
||||
|
||||
The default build phase for `agdaPackages.mkDerivation` runs `agda` on the `Everything.agda` file.
|
||||
The default build phase for `agdaPackages.mkDerivation` runs `agda --build-library`.
|
||||
If something else is needed to build the package (e.g. `make`) then the `buildPhase` should be overridden.
|
||||
Additionally, a `preBuild` or `configurePhase` can be used if there are steps that need to be done prior to checking the `Everything.agda` file.
|
||||
Additionally, a `preBuild` or `configurePhase` can be used if there are steps that need to be done prior to checking the library.
|
||||
`agda` and the Agda libraries contained in `buildInputs` are made available during the build phase.
|
||||
|
||||
### Installing Agda packages {#installing-agda-packages}
|
||||
@@ -180,7 +179,7 @@ the Agda package set is small and can (still) be maintained by hand.
|
||||
|
||||
### Adding Agda packages to Nixpkgs {#adding-agda-packages-to-nixpkgs}
|
||||
|
||||
To add an Agda package to `nixpkgs`, the derivation should be written to `pkgs/development/libraries/agda/${library-name}/` and an entry should be added to `pkgs/top-level/agda-packages.nix`. Here it is called in a scope with access to all other Agda libraries, so the top line of the `default.nix` can look like:
|
||||
To add an Agda package to `nixpkgs`, the derivation should be written to `pkgs/development/libraries/agda/${library-name}/default.nix` and an entry should be added to `pkgs/top-level/agda-packages.nix`. Here it is called in a scope with access to all other Agda libraries, so the derivation could look like:
|
||||
|
||||
```nix
|
||||
{
|
||||
@@ -188,45 +187,29 @@ To add an Agda package to `nixpkgs`, the derivation should be written to `pkgs/d
|
||||
standard-library,
|
||||
fetchFromGitHub,
|
||||
}:
|
||||
{ }
|
||||
|
||||
mkDerivation {
|
||||
pname = "my-library";
|
||||
version = "1.0";
|
||||
src = <...>;
|
||||
buildInputs = [ standard-library ];
|
||||
meta = <...>;
|
||||
}
|
||||
```
|
||||
|
||||
You can look at other files under `pkgs/development/libraries/agda/` for more inspiration.
|
||||
|
||||
Note that the derivation function is called with `mkDerivation` set to `agdaPackages.mkDerivation`, therefore you
|
||||
could use a similar set as in your `default.nix` from [Writing Agda Packages](#writing-agda-packages) with
|
||||
`agdaPackages.mkDerivation` replaced with `mkDerivation`.
|
||||
|
||||
Here is an example skeleton derivation for iowa-stdlib:
|
||||
|
||||
```nix
|
||||
mkDerivation {
|
||||
version = "1.5.0";
|
||||
pname = "iowa-stdlib";
|
||||
|
||||
src = <...>;
|
||||
|
||||
libraryFile = "";
|
||||
libraryName = "IAL-1.3";
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
patchShebangs find-deps.sh
|
||||
make
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
This library has a file called `.agda-lib`, and so we give an empty string to `libraryFile` as nothing precedes `.agda-lib` in the filename. This file contains `name: IAL-1.3`, and so we let `libraryName = "IAL-1.3"`. This library does not use an `Everything.agda` file and instead has a Makefile, so there is no need to set `everythingFile` and we set a custom `buildPhase`.
|
||||
|
||||
When writing an Agda package it is essential to make sure that no `.agda-lib` file gets added to the store as a single file (for example by using `writeText`). This causes Agda to think that the nix store is a Agda library and it will attempt to write to it whenever it typechecks something. See [https://github.com/agda/agda/issues/4613](https://github.com/agda/agda/issues/4613).
|
||||
|
||||
In the pull request adding this library,
|
||||
you can test whether it builds correctly by writing in a comment:
|
||||
|
||||
```
|
||||
@ofborg build agdaPackages.iowa-stdlib
|
||||
@ofborg build agdaPackages.my-library
|
||||
```
|
||||
|
||||
### Maintaining Agda packages {#agda-maintaining-packages}
|
||||
|
||||
@@ -12,11 +12,11 @@ Nixpkgs provides a number of CUDA package sets, each based on a different CUDA r
|
||||
- `cudaPackages_x`: A major-versioned alias to the major-minor-versioned CUDA package set with the latest widely supported major CUDA release.
|
||||
- `cudaPackages`: An unversioned alias to the major-versioned alias for the latest widely supported CUDA release. The package set referenced by this alias is also referred to as the "default" CUDA package set.
|
||||
|
||||
It is recommended to use the unversioned `cudaPackages` attribute. While versioned package sets are available (e.g., `cudaPackages_12_2`), they are periodically removed.
|
||||
It is recommended to use the unversioned `cudaPackages` attribute. While versioned package sets are available (e.g., `cudaPackages_12_8`), they are periodically removed.
|
||||
|
||||
Here are two examples to illustrate the naming conventions:
|
||||
|
||||
- If `cudaPackages_12_8` is the latest release in the 12.x series, but core libraries like OpenCV or ONNX Runtime fail to build with it, `cudaPackages_12` may alias `cudaPackages_12_6` instead of `cudaPackages_12_8`.
|
||||
- If `cudaPackages_12_9` is the latest release in the 12.x series, but core libraries like OpenCV or ONNX Runtime fail to build with it, `cudaPackages_12` may alias `cudaPackages_12_8` instead of `cudaPackages_12_9`.
|
||||
- If `cudaPackages_13_1` is the latest release, but core libraries like PyTorch or Torch Vision fail to build with it, `cudaPackages` may alias `cudaPackages_12` instead of `cudaPackages_13`.
|
||||
|
||||
All CUDA package sets include common CUDA packages like `libcublas`, `cudnn`, `tensorrt`, and `nccl`.
|
||||
@@ -146,7 +146,7 @@ These settings ensure that the CUDA setup hooks function as intended.
|
||||
When using `callPackage`, you can choose to pass in a different variant, e.g. when a package requires a specific version of CUDA:
|
||||
|
||||
```nix
|
||||
{ mypkg = callPackage { cudaPackages = cudaPackages_12_2; }; }
|
||||
{ mypkg = callPackage { cudaPackages = cudaPackages_12_6; }; }
|
||||
```
|
||||
|
||||
::: {.caution}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# D (Dlang) {#dlang}
|
||||
|
||||
Nixpkgs provides multiple D compilers such as `ldc`, `dmd` and `gdc`.
|
||||
Nixpkgs provides multiple D compilers such as `ldc` and `dmd`.
|
||||
These can be used like any other package during build time.
|
||||
|
||||
However, Nixpkgs provides a build helper for compiling packages using the `dub` package manager.
|
||||
|
||||
@@ -11,6 +11,7 @@ lib.md
|
||||
stdenv.md
|
||||
toolchains.md
|
||||
build-helpers.md
|
||||
modules/index.md
|
||||
development.md
|
||||
contributing.md
|
||||
interoperability.md
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
|
||||
# Generic {#modules-generic}
|
||||
|
||||
Generic modules can be imported to extend configurations of any [class].
|
||||
|
||||
## `meta-maintainers.nix` {#modules-generic-meta-maintainers}
|
||||
|
||||
The options below become available when using `imports = [ (nixpkgs + "/modules/generic/meta-maintainers.nix") ];`.
|
||||
|
||||
```{=include=} options
|
||||
id-prefix: opt-modules-generic-meta-maintainers-
|
||||
list-id: configuration-variable-list
|
||||
source: ../options-modules-generic-meta-maintainers.json
|
||||
```
|
||||
|
||||
[class]: https://nixos.org/manual/nixpkgs/unstable/#module-system-lib-evalModules-param-class
|
||||
@@ -0,0 +1,12 @@
|
||||
# Modules {#modules}
|
||||
|
||||
The Nixpkgs repository provides [Module System] modules for various purposes.
|
||||
|
||||
The following sections are organized by [module class].
|
||||
|
||||
```{=include=} chapters
|
||||
generic.chapter.md
|
||||
```
|
||||
|
||||
[Module System]: https://nixos.org/manual/nixpkgs/unstable/#module-system
|
||||
[module class]: https://nixos.org/manual/nixpkgs/unstable/#module-system-lib-evalModules-param-class
|
||||
@@ -130,6 +130,15 @@
|
||||
"minor-ghc-deprecation": [
|
||||
"index.html#minor-ghc-deprecation"
|
||||
],
|
||||
"modules": [
|
||||
"index.html#modules"
|
||||
],
|
||||
"modules-generic": [
|
||||
"index.html#modules-generic"
|
||||
],
|
||||
"modules-generic-meta-maintainers": [
|
||||
"index.html#modules-generic-meta-maintainers"
|
||||
],
|
||||
"neovim": [
|
||||
"index.html#neovim"
|
||||
],
|
||||
@@ -1657,6 +1666,9 @@
|
||||
"fetchfromsourcehut": [
|
||||
"index.html#fetchfromsourcehut"
|
||||
],
|
||||
"fetchfromradicle": [
|
||||
"index.html#fetchfromradicle"
|
||||
],
|
||||
"requirefile": [
|
||||
"index.html#requirefile"
|
||||
],
|
||||
|
||||
@@ -20,16 +20,21 @@
|
||||
|
||||
- The `offrss` package was removed due to lack of upstream maintenance since 2012. It's recommended for users to migrate to another RSS reader
|
||||
|
||||
- GCC 9, 10, 11, and 12 have been removed, as they have reached end‐of‐life upstream and are no longer supported.
|
||||
|
||||
- `base16-builder` node package has been removed due to lack of upstream maintenance.
|
||||
- `gentium` package now provides `Gentium-*.ttf` files, and not `GentiumPlus-*.ttf` files like before. The font identifiers `Gentium Plus*` are available in the `gentium-plus` package, and if you want to use the more recently updated package `gentium` [by sil](https://software.sil.org/gentium/), you should update your configuration files to use the `Gentium` font identifier.
|
||||
- `space-orbit` package has been removed due to lack of upstream maintenance. Debian upstream stopped tracking it in 2011.
|
||||
|
||||
- Derivations setting both `separateDebugInfo` and one of `allowedReferences`, `allowedRequistes`, `disallowedReferences` or `disallowedRequisites` must now set `__structuredAttrs` to `true`. The effect of reference whitelisting or blacklisting will be disabled on the `debug` output created by `separateDebugInfo`.
|
||||
|
||||
- `victoriametrics` no longer contains VictoriaLogs components. These have been separated into the new package `victorialogs`.
|
||||
|
||||
- `mx-puppet-discord` was removed from nixpkgs along with its NixOS module as it was unmaintained and was the only user of sha1 hashes in tree.
|
||||
|
||||
- `kbd` package's `outputs` now include a `man` and `scripts` outputs. The `unicode_start` and `unicode_stop` Bash scripts are now part of the `scripts` output, allowing most usages of the `kbd` package to not pull in `bash`.
|
||||
|
||||
- `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.
|
||||
|
||||
- `gnome-keyring` no longer ships with an SSH agent anymore because it has been deprecated upstream. You should use `gcr_4` instead, which provides the same features. More information on why this was done can be found on [the relevant GCR upstream PR](https://gitlab.gnome.org/GNOME/gcr/-/merge_requests/67).
|
||||
@@ -43,6 +48,8 @@
|
||||
|
||||
- Zig 0.12 has been removed.
|
||||
|
||||
- `ansible-later` has been removed because it was discontinued by the author.
|
||||
|
||||
- `stalwart-mail` since `0.13.0` "introduces a significant redesign of the MTA’s delivery and queueing subsystem". See [the upgrading announcement for the `0.13.0` release](https://github.com/stalwartlabs/stalwart/blob/89b561b5ca1c5a11f2a768b4a2cfef0f473b7a01/UPGRADING.md#upgrading-from-v012x-and-v011x-to-v013x).
|
||||
|
||||
- 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.
|
||||
@@ -69,6 +76,8 @@
|
||||
|
||||
- `mongodb-6_0` was removed as it is end of life as of 2025-07-31.
|
||||
|
||||
- CUDA versions below 12.6 have been removed, as they are unmaintained upstream and depend on end‐of‐life compilers.
|
||||
|
||||
- `vmware-horizon-client` was renamed to `omnissa-horizon-client`, following [VMware's sale of their end-user business to Omnissa](https://www.omnissa.com/insights/introducing-omnissa-the-former-vmware-end-user-computing-business/). The binary has been renamed from `vmware-view` to `horizon-client`.
|
||||
|
||||
- `neovimUtils.makeNeovimConfig` now uses `customLuaRC` parameter instead of accepting `luaRcContent`. The old usage is deprecated but still works with a warning.
|
||||
@@ -105,6 +114,10 @@
|
||||
|
||||
- `meta.mainProgram`: Changing this `meta` entry can lead to a package rebuild due to being used to determine the `NIX_MAIN_PROGRAM` environment variable.
|
||||
|
||||
- `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.
|
||||
|
||||
- `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"`.
|
||||
|
||||
@@ -127,6 +140,8 @@
|
||||
recommendation](https://clickhouse.com/docs/faq/operations/production). Users
|
||||
can continue to use the `clickhouse-lts` package if desired.
|
||||
|
||||
- `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.
|
||||
|
||||
## Nixpkgs Library {#sec-nixpkgs-release-25.11-lib}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
@@ -143,6 +158,9 @@
|
||||
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}
|
||||
|
||||
- Create the first release note entry in this section!
|
||||
|
||||
@@ -166,7 +166,7 @@ The following is a non-exhaustive list of such differences:
|
||||
- Other environment variables may be inconsistent with a `nix-build` either due to `nix-shell`'s initialization script or due to the use of `nix-shell` without the `--pure` option.
|
||||
|
||||
If the build fails differently inside the shell than in the sandbox, consider using [`breakpointHook`](#breakpointhook) and invoking `nix-build` instead.
|
||||
The [`--keep-failed`](https://nixos.org/manual/nix/unstable/command-ref/conf-file#opt--keep-failed) option for `nix-build` may also be useful to examine the build directory of a failed build.
|
||||
The [`--keep-failed`](https://nixos.org/manual/nix/unstable/command-ref/conf-file#conf-keep-failed) option for `nix-build` may also be useful to examine the build directory of a failed build.
|
||||
:::
|
||||
|
||||
## Tools provided by `stdenv` {#sec-tools-of-stdenv}
|
||||
|
||||
+205
-206
@@ -1,193 +1,193 @@
|
||||
html {
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
line-height: 1.15;
|
||||
-webkit-text-size-adjust: 100%;
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.book,
|
||||
.appendix {
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
margin: auto;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 768px) {
|
||||
.book,
|
||||
.appendix {
|
||||
max-width: 46rem;
|
||||
}
|
||||
.book,
|
||||
.appendix {
|
||||
max-width: 46rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 992px) {
|
||||
.book,
|
||||
.appendix {
|
||||
max-width: 60rem;
|
||||
}
|
||||
.book,
|
||||
.appendix {
|
||||
max-width: 60rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (min-width: 1200px) {
|
||||
.book,
|
||||
.appendix {
|
||||
max-width: 73rem;
|
||||
}
|
||||
.book,
|
||||
.appendix {
|
||||
max-width: 73rem;
|
||||
}
|
||||
}
|
||||
|
||||
.book .list-of-examples {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
font-size: 2em;
|
||||
margin: 0.67em 0;
|
||||
}
|
||||
|
||||
hr {
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
box-sizing: content-box;
|
||||
height: 0;
|
||||
overflow: visible;
|
||||
}
|
||||
|
||||
pre {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
font-family: monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
a {
|
||||
background-color: transparent;
|
||||
background-color: transparent;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bolder;
|
||||
font-weight: bolder;
|
||||
}
|
||||
|
||||
code {
|
||||
font-family: monospace, monospace;
|
||||
font-size: 1em;
|
||||
font-family: monospace;
|
||||
font-size: 1em;
|
||||
}
|
||||
|
||||
sup {
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
font-size: 75%;
|
||||
line-height: 0;
|
||||
position: relative;
|
||||
vertical-align: baseline;
|
||||
}
|
||||
|
||||
sup {
|
||||
top: -0.5em;
|
||||
top: -0.5em;
|
||||
}
|
||||
|
||||
::-webkit-file-upload-button {
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
-webkit-appearance: button;
|
||||
font: inherit;
|
||||
}
|
||||
|
||||
pre {
|
||||
overflow: auto;
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
*,
|
||||
*::before,
|
||||
*::after {
|
||||
box-sizing: border-box;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
html {
|
||||
font-size: 100%;
|
||||
line-height: 1.77777778;
|
||||
font-size: 100%;
|
||||
line-height: 1.77777778;
|
||||
}
|
||||
|
||||
@media screen and (min-width: 4000px) {
|
||||
html {
|
||||
background: #000;
|
||||
}
|
||||
html {
|
||||
background: #000;
|
||||
}
|
||||
|
||||
html body {
|
||||
margin: auto;
|
||||
max-width: 250rem;
|
||||
}
|
||||
html body {
|
||||
margin: auto;
|
||||
max-width: 250rem;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 320px) {
|
||||
html {
|
||||
font-size: calc(16 / 320 * 100vw);
|
||||
}
|
||||
html {
|
||||
font-size: calc(16 / 320 * 100vw);
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
font-size: 1rem;
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-weight: 300;
|
||||
color: var(--main-text-color);
|
||||
background-color: var(--background);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
font-size: 1rem;
|
||||
font-family: "Roboto", sans-serif;
|
||||
font-weight: 300;
|
||||
color: var(--main-text-color);
|
||||
background-color: var(--background);
|
||||
min-height: 100vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
@media screen and (max-width: 767.9px) {
|
||||
body {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
body {
|
||||
padding-left: 1rem;
|
||||
padding-right: 1rem;
|
||||
}
|
||||
}
|
||||
|
||||
a {
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid;
|
||||
color: var(--link-color);
|
||||
text-decoration: none;
|
||||
border-bottom: 1px solid;
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-left: 1rem;
|
||||
padding: 0;
|
||||
margin-top: 0;
|
||||
margin-right: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-left: 1rem;
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
thead th {
|
||||
text-align: left;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
hr {
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 1rem;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
font-size: 200%;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--heading-color);
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
font-size: 200%;
|
||||
margin-bottom: 1rem;
|
||||
color: var(--heading-color);
|
||||
}
|
||||
|
||||
h2 {
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
font-size: 170%;
|
||||
margin-bottom: 0.625rem;
|
||||
color: var(--heading-color);
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
font-size: 170%;
|
||||
margin-bottom: 0.625rem;
|
||||
color: var(--heading-color);
|
||||
}
|
||||
|
||||
h2:not(:first-child) {
|
||||
margin-top: 1rem;
|
||||
margin-top: 1rem;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 150%;
|
||||
color: var(--heading-color);
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 150%;
|
||||
color: var(--heading-color);
|
||||
}
|
||||
|
||||
.note h3,
|
||||
@@ -195,73 +195,73 @@ h3 {
|
||||
.warning h3,
|
||||
.caution h3,
|
||||
.important h3 {
|
||||
font-size: 120%;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
h4 {
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 140%;
|
||||
color: var(--heading-color);
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 140%;
|
||||
color: var(--heading-color);
|
||||
}
|
||||
|
||||
h5 {
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 130%;
|
||||
color: var(--small-heading-color);
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 130%;
|
||||
color: var(--small-heading-color);
|
||||
}
|
||||
|
||||
h6 {
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 120%;
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
font-size: 120%;
|
||||
}
|
||||
|
||||
strong {
|
||||
font-weight: bold;
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
margin-top: 0;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
dt > *:first-child,
|
||||
dd > *:first-child {
|
||||
margin-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
dt > *:last-child,
|
||||
dd > *:last-child {
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
pre,
|
||||
code {
|
||||
font-family: monospace;
|
||||
font-family: monospace;
|
||||
}
|
||||
|
||||
code {
|
||||
color: #ff8657;
|
||||
background: #f4f4f4;
|
||||
display: inline-block;
|
||||
padding: 0 0.5rem;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 0.5rem;
|
||||
line-height: 1.57777778;
|
||||
color: #ff8657;
|
||||
background: #f4f4f4;
|
||||
display: inline-block;
|
||||
padding: 0 0.5rem;
|
||||
border: 1px solid #d8d8d8;
|
||||
border-radius: 0.5rem;
|
||||
line-height: 1.57777778;
|
||||
}
|
||||
|
||||
div.book .programlisting,
|
||||
div.appendix .programlisting {
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
overflow: auto;
|
||||
background: var(--codeblock-background);
|
||||
color: var(--codeblock-text-color);
|
||||
border-radius: 0.5rem;
|
||||
padding: 1rem;
|
||||
overflow: auto;
|
||||
background: var(--codeblock-background);
|
||||
color: var(--codeblock-text-color);
|
||||
}
|
||||
|
||||
div.book .note,
|
||||
@@ -274,11 +274,11 @@ div.appendix .tip,
|
||||
div.appendix .warning,
|
||||
div.appendix .caution,
|
||||
div.appendix .important {
|
||||
margin-bottom: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
padding: 1.5rem;
|
||||
overflow: auto;
|
||||
background: #f4f4f4;
|
||||
margin-bottom: 1rem;
|
||||
border-radius: 0.5rem;
|
||||
padding: 1.5rem;
|
||||
overflow: auto;
|
||||
background: #f4f4f4;
|
||||
}
|
||||
|
||||
div.book .note > .title,
|
||||
@@ -291,11 +291,10 @@ div.appendix .tip > .title,
|
||||
div.appendix .warning > .title,
|
||||
div.appendix .caution > .title,
|
||||
div.appendix .important > .title {
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
margin-bottom: 1rem;
|
||||
color: inherit;
|
||||
margin-bottom: 0;
|
||||
font-weight: 800;
|
||||
line-height: 110%;
|
||||
color: inherit;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.book .note > :first-child,
|
||||
@@ -308,7 +307,7 @@ div.appendix .tip > :first-child,
|
||||
div.appendix .warning > :first-child,
|
||||
div.appendix .caution > :first-child,
|
||||
div.appendix .important > :first-child {
|
||||
margin-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.book .note > :last-child,
|
||||
@@ -321,122 +320,122 @@ div.appendix .tip > :last-child,
|
||||
div.appendix .warning > :last-child,
|
||||
div.appendix .caution > :last-child,
|
||||
div.appendix .important > :last-child {
|
||||
margin-bottom: 0;
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
div.book .note,
|
||||
div.book .tip,
|
||||
div.appendix .note,
|
||||
div.appendix .tip {
|
||||
color: var(--note-text-color);
|
||||
background: var(--note-background);
|
||||
color: var(--note-text-color);
|
||||
background: var(--note-background);
|
||||
}
|
||||
|
||||
div.book .warning,
|
||||
div.book .caution,
|
||||
div.appendix .warning,
|
||||
div.appendix .caution {
|
||||
color: var(--warning-text-color);
|
||||
background-color: var(--warning-background);
|
||||
color: var(--warning-text-color);
|
||||
background-color: var(--warning-background);
|
||||
}
|
||||
|
||||
div.book .section,
|
||||
div.appendix .section {
|
||||
margin-top: 2em;
|
||||
margin-top: 2em;
|
||||
}
|
||||
|
||||
div.book div.example,
|
||||
div.appendix div.example {
|
||||
margin-top: 1.5em;
|
||||
margin-top: 1.5em;
|
||||
}
|
||||
|
||||
div.book div.example details,
|
||||
div.appendix div.example details {
|
||||
padding: 5px;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
div.book div.example details[open],
|
||||
div.appendix div.example details[open] {
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
border: 1px solid #aaa;
|
||||
border-radius: 4px;
|
||||
}
|
||||
|
||||
div.book div.example details > summary,
|
||||
div.appendix div.example details > summary {
|
||||
cursor: pointer;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
div.book br.example-break,
|
||||
div.appendix br.example-break {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.book div.footnotes > hr,
|
||||
div.appendix div.footnotes > hr {
|
||||
border-color: #d8d8d8;
|
||||
border-color: #d8d8d8;
|
||||
}
|
||||
|
||||
div.book div.footnotes > br,
|
||||
div.appendix div.footnotes > br {
|
||||
display: none;
|
||||
display: none;
|
||||
}
|
||||
|
||||
div.book dt,
|
||||
div.appendix dt {
|
||||
margin-top: 1em;
|
||||
margin-top: 1em;
|
||||
}
|
||||
|
||||
div.book .toc dt,
|
||||
div.appendix .toc dt {
|
||||
margin-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.book .list-of-examples dt,
|
||||
div.appendix .list-of-examples dt {
|
||||
margin-top: 0;
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
div.book code,
|
||||
div.appendix code {
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
font-size: 100%;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
hyphens: none;
|
||||
padding: 0;
|
||||
border: 0;
|
||||
background-color: inherit;
|
||||
color: inherit;
|
||||
font-size: 100%;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
div.book div.toc,
|
||||
div.appendix div.toc {
|
||||
margin-bottom: 3em;
|
||||
border-bottom: 0.0625rem solid #d8d8d8;
|
||||
margin-bottom: 3em;
|
||||
border-bottom: 0.0625rem solid #d8d8d8;
|
||||
}
|
||||
|
||||
div.book div.toc dd,
|
||||
div.appendix div.toc dd {
|
||||
margin-left: 2em;
|
||||
margin-left: 2em;
|
||||
}
|
||||
|
||||
div.book span.command,
|
||||
div.appendix span.command {
|
||||
font-family: monospace;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
hyphens: none;
|
||||
font-family: monospace;
|
||||
-webkit-hyphens: none;
|
||||
-moz-hyphens: none;
|
||||
hyphens: none;
|
||||
}
|
||||
|
||||
div.book .informaltable th,
|
||||
div.book .informaltable td,
|
||||
div.appendix .informaltable th,
|
||||
div.appendix .informaltable td {
|
||||
padding: 0.5rem;
|
||||
padding: 0.5rem;
|
||||
}
|
||||
|
||||
div.book .variablelist .term,
|
||||
div.appendix .variablelist .term {
|
||||
font-weight: 500;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -444,50 +443,50 @@ div.appendix .variablelist .term {
|
||||
For more details, see https://highlightjs.readthedocs.io/en/latest/css-classes-reference.html#stylable-scopes
|
||||
*/
|
||||
.hljs-meta.prompt_ {
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
user-select: none;
|
||||
-webkit-user-select: none;
|
||||
}
|
||||
|
||||
:root {
|
||||
--background: #fff;
|
||||
--main-text-color: #000;
|
||||
--link-color: #405d99;
|
||||
--heading-color: #6586c8;
|
||||
--small-heading-color: #6a6a6a;
|
||||
--note-text-color: #5277c3;
|
||||
--note-background: #f2f8fd;
|
||||
--warning-text-color: #cc3900;
|
||||
--warning-background: #fff5e1;
|
||||
--codeblock-background: #f2f8fd;
|
||||
--codeblock-text-color: #000;
|
||||
--background: #fff;
|
||||
--main-text-color: #000;
|
||||
--link-color: #405d99;
|
||||
--heading-color: #6586c8;
|
||||
--small-heading-color: #6a6a6a;
|
||||
--note-text-color: #5277c3;
|
||||
--note-background: #f2f8fd;
|
||||
--warning-text-color: #cc3900;
|
||||
--warning-background: #fff5e1;
|
||||
--codeblock-background: #f2f8fd;
|
||||
--codeblock-text-color: #000;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
:root {
|
||||
--background: #242424;
|
||||
--main-text-color: #fff;
|
||||
--link-color: #6586c8;
|
||||
--small-heading-color: #fff;
|
||||
--note-background: none;
|
||||
--warning-background: none;
|
||||
--codeblock-background: #393939;
|
||||
--codeblock-text-color: #fff;
|
||||
}
|
||||
:root {
|
||||
--background: #242424;
|
||||
--main-text-color: #fff;
|
||||
--link-color: #6586c8;
|
||||
--small-heading-color: #fff;
|
||||
--note-background: none;
|
||||
--warning-background: none;
|
||||
--codeblock-background: #393939;
|
||||
--codeblock-text-color: #fff;
|
||||
}
|
||||
|
||||
div.book .note,
|
||||
div.book .tip,
|
||||
div.appendix .note,
|
||||
div.appendix .tip,
|
||||
div.book .warning,
|
||||
div.book .caution,
|
||||
div.appendix .warning,
|
||||
div.appendix .caution {
|
||||
border: 2px solid;
|
||||
font-weight: 400;
|
||||
}
|
||||
div.book .note,
|
||||
div.book .tip,
|
||||
div.appendix .note,
|
||||
div.appendix .tip,
|
||||
div.book .warning,
|
||||
div.book .caution,
|
||||
div.appendix .warning,
|
||||
div.appendix .caution {
|
||||
border: 2px solid;
|
||||
font-weight: 400;
|
||||
}
|
||||
}
|
||||
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url(Roboto.ttf);
|
||||
font-family: Roboto;
|
||||
src: url(Roboto.ttf);
|
||||
}
|
||||
|
||||
@@ -140,7 +140,7 @@ stdenv.mkDerivation {
|
||||
|
||||
### Switching the MPI implementation {#sec-overlays-alternatives-mpi}
|
||||
|
||||
All programs that are built with [MPI](https://en.wikipedia.org/wiki/Message_Passing_Interface) support use the generic attribute `mpi` as an input. At the moment Nixpkgs natively provides two different MPI implementations:
|
||||
All programs that are built with [MPI](https://en.wikipedia.org/wiki/Message_Passing_Interface) support use the generic attribute `mpi` as an input. At the moment Nixpkgs natively provides the following MPI implementations:
|
||||
|
||||
- [Open MPI](https://www.open-mpi.org/) (default), attribute name
|
||||
`openmpi`
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@ This file evaluates to an attribute set containing two separate kinds of attribu
|
||||
Example: `lib.take` is an alias for `lib.lists.take`.
|
||||
|
||||
Most files in this directory are definitions of sub-libraries, but there are a few others:
|
||||
- [`minver.nix`](minver.nix): A string of the minimum version of Nix that is required to evaluate Nixpkgs.
|
||||
- [`minfeatures.nix`](minfeatures.nix): A list of conditions for the used Nix version to match that are required to evaluate Nixpkgs.
|
||||
- [`tests`](tests): Tests, see [Running tests](#running-tests)
|
||||
- [`release.nix`](tests/release.nix): A derivation aggregating all tests
|
||||
- [`misc.nix`](tests/misc.nix): Evaluation unit tests for most sub-libraries
|
||||
|
||||
+1
-10
@@ -285,18 +285,9 @@ rec {
|
||||
arg:
|
||||
let
|
||||
loc = builtins.unsafeGetAttrPos arg fargs;
|
||||
# loc' can be removed once lib/minver.nix is >2.3.4, since that includes
|
||||
# https://github.com/NixOS/nix/pull/3468 which makes loc be non-null
|
||||
loc' =
|
||||
if loc != null then
|
||||
loc.file + ":" + toString loc.line
|
||||
else if !isFunction fn then
|
||||
toString (lib.filesystem.resolveDefaultNix fn)
|
||||
else
|
||||
"<unknown location>";
|
||||
in
|
||||
"Function called without required argument \"${arg}\" at "
|
||||
+ "${loc'}${prettySuggestions (getSuggestions arg)}";
|
||||
+ "${loc.file}:${toString loc.line}${prettySuggestions (getSuggestions arg)}";
|
||||
|
||||
# Only show the error for the first missing argument
|
||||
error = errorForArg (head (attrNames missingArgs));
|
||||
|
||||
+3
-10
@@ -112,7 +112,6 @@ let
|
||||
_intersection
|
||||
_difference
|
||||
_fromFetchGit
|
||||
_fetchGitSubmodulesMinver
|
||||
_emptyWithoutBase
|
||||
;
|
||||
|
||||
@@ -1000,16 +999,10 @@ in
|
||||
path:
|
||||
if !isBool recurseSubmodules then
|
||||
throw "lib.fileset.gitTrackedWith: Expected the attribute `recurseSubmodules` of the first argument to be a boolean, but it's a ${typeOf recurseSubmodules} instead."
|
||||
else if recurseSubmodules && versionOlder nixVersion _fetchGitSubmodulesMinver then
|
||||
throw "lib.fileset.gitTrackedWith: Setting the attribute `recurseSubmodules` to `true` is only supported for Nix version ${_fetchGitSubmodulesMinver} and after, but Nix version ${nixVersion} is used."
|
||||
else
|
||||
_fromFetchGit "gitTrackedWith" "second argument" path
|
||||
# This is the only `fetchGit` parameter that makes sense in this context.
|
||||
# We can't just pass `submodules = recurseSubmodules` here because
|
||||
# this would fail for Nix versions that don't support `submodules`.
|
||||
(
|
||||
lib.optionalAttrs recurseSubmodules {
|
||||
submodules = true;
|
||||
}
|
||||
);
|
||||
{
|
||||
submodules = recurseSubmodules;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -899,14 +899,6 @@ rec {
|
||||
${baseNameOf root} = fromFile (baseNameOf root) rootType;
|
||||
};
|
||||
|
||||
# Support for `builtins.fetchGit` with `submodules = true` was introduced in 2.4
|
||||
# https://github.com/NixOS/nix/commit/55cefd41d63368d4286568e2956afd535cb44018
|
||||
_fetchGitSubmodulesMinver = "2.4";
|
||||
|
||||
# Support for `builtins.fetchGit` with `shallow = true` was introduced in 2.4
|
||||
# https://github.com/NixOS/nix/commit/d1165d8791f559352ff6aa7348e1293b2873db1c
|
||||
_fetchGitShallowMinver = "2.4";
|
||||
|
||||
# Mirrors the contents of a Nix store path relative to a local path as a file set.
|
||||
# Some notes:
|
||||
# - The store path is read at evaluation time.
|
||||
@@ -961,16 +953,8 @@ rec {
|
||||
fetchResult = fetchGit (
|
||||
{
|
||||
url = path;
|
||||
shallow = true;
|
||||
}
|
||||
# In older Nix versions, repositories were always assumed to be deep clones, which made `fetchGit` fail for shallow clones
|
||||
# For newer versions this was fixed, but the `shallow` flag is required.
|
||||
# The only behavioral difference is that for shallow clones, `fetchGit` doesn't return a `revCount`,
|
||||
# which we don't need here, so it's fine to always pass it.
|
||||
|
||||
# Unfortunately this means older Nix versions get a poor error message for shallow repositories, and there's no good way to improve that.
|
||||
# Checking for `.git/shallow` doesn't seem worth it, especially since that's more of an implementation detail,
|
||||
# and would also require more code to handle worktrees where `.git` is a file.
|
||||
// optionalAttrs (versionAtLeast nixVersion _fetchGitShallowMinver) { shallow = true; }
|
||||
// extraFetchGitAttrs
|
||||
);
|
||||
in
|
||||
|
||||
+35
-51
@@ -1336,14 +1336,6 @@ expectFailure 'gitTrackedWith {} ./.' 'lib.fileset.gitTrackedWith: Expected the
|
||||
# recurseSubmodules has to be a boolean
|
||||
expectFailure 'gitTrackedWith { recurseSubmodules = null; } ./.' 'lib.fileset.gitTrackedWith: Expected the attribute `recurseSubmodules` of the first argument to be a boolean, but it'\''s a null instead.'
|
||||
|
||||
# recurseSubmodules = true is not supported on all Nix versions
|
||||
if [[ "$(nix-instantiate --eval --expr "$prefixExpression (versionAtLeast builtins.nixVersion _fetchGitSubmodulesMinver)")" == true ]]; then
|
||||
fetchGitSupportsSubmodules=1
|
||||
else
|
||||
fetchGitSupportsSubmodules=
|
||||
expectFailure 'gitTrackedWith { recurseSubmodules = true; } ./.' 'lib.fileset.gitTrackedWith: Setting the attribute `recurseSubmodules` to `true` is only supported for Nix version 2.4 and after, but Nix version [0-9.]+ is used.'
|
||||
fi
|
||||
|
||||
# Checks that `gitTrackedWith` contains the same files as `git ls-files`
|
||||
# for the current working directory.
|
||||
# If --recurse-submodules is passed, the flag is passed through to `git ls-files`
|
||||
@@ -1393,9 +1385,7 @@ checkGitTrackedWith() {
|
||||
# Allows testing both variants together
|
||||
checkGitTracked() {
|
||||
checkGitTrackedWith
|
||||
if [[ -n "$fetchGitSupportsSubmodules" ]]; then
|
||||
checkGitTrackedWith --recurse-submodules
|
||||
fi
|
||||
checkGitTrackedWith --recurse-submodules
|
||||
}
|
||||
|
||||
createGitRepo() {
|
||||
@@ -1430,51 +1420,45 @@ expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTracked: T
|
||||
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
|
||||
|
||||
## Even with submodules
|
||||
if [[ -n "$fetchGitSupportsSubmodules" ]]; then
|
||||
## Both the main repo with the submodule
|
||||
echo '{ fs }: fs.toSource { root = ./.; fileset = fs.gitTrackedWith { recurseSubmodules = true; } ./.; }' > default.nix
|
||||
createGitRepo sub
|
||||
git submodule add ./sub sub >/dev/null
|
||||
## But also the submodule itself
|
||||
echo '{ fs }: fs.toSource { root = ./.; fileset = fs.gitTracked ./.; }' > sub/default.nix
|
||||
git -C sub add .
|
||||
## Both the main repo with the submodule
|
||||
echo '{ fs }: fs.toSource { root = ./.; fileset = fs.gitTrackedWith { recurseSubmodules = true; } ./.; }' > default.nix
|
||||
createGitRepo sub
|
||||
git submodule add ./sub sub >/dev/null
|
||||
## But also the submodule itself
|
||||
echo '{ fs }: fs.toSource { root = ./.; fileset = fs.gitTracked ./.; }' > sub/default.nix
|
||||
git -C sub add .
|
||||
|
||||
## We can evaluate it locally just fine, `fetchGit` is used underneath to filter git-tracked files
|
||||
expectEqual '(import ./. { fs = lib.fileset; }).outPath' '(builtins.fetchGit { url = ./.; submodules = true; }).outPath'
|
||||
expectEqual '(import ./sub { fs = lib.fileset; }).outPath' '(builtins.fetchGit ./sub).outPath'
|
||||
## We can evaluate it locally just fine, `fetchGit` is used underneath to filter git-tracked files
|
||||
expectEqual '(import ./. { fs = lib.fileset; }).outPath' '(builtins.fetchGit { url = ./.; submodules = true; }).outPath'
|
||||
expectEqual '(import ./sub { fs = lib.fileset; }).outPath' '(builtins.fetchGit ./sub).outPath'
|
||||
|
||||
## We can also evaluate when importing from fetched store paths
|
||||
storePathWithSub=$(expectStorePath 'builtins.fetchGit { url = ./.; submodules = true; }')
|
||||
expectEqual '(import '"$storePathWithSub"' { fs = lib.fileset; }).outPath' \""$storePathWithSub"\"
|
||||
storePathSub=$(expectStorePath 'builtins.fetchGit ./sub')
|
||||
expectEqual '(import '"$storePathSub"' { fs = lib.fileset; }).outPath' \""$storePathSub"\"
|
||||
## We can also evaluate when importing from fetched store paths
|
||||
storePathWithSub=$(expectStorePath 'builtins.fetchGit { url = ./.; submodules = true; }')
|
||||
expectEqual '(import '"$storePathWithSub"' { fs = lib.fileset; }).outPath' \""$storePathWithSub"\"
|
||||
storePathSub=$(expectStorePath 'builtins.fetchGit ./sub')
|
||||
expectEqual '(import '"$storePathSub"' { fs = lib.fileset; }).outPath' \""$storePathSub"\"
|
||||
|
||||
## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
|
||||
expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTrackedWith: The second argument \(.*\) is a store path within a working tree of a Git repository.
|
||||
[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
|
||||
[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
|
||||
[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
|
||||
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
|
||||
expectFailure 'import "${./.}/sub" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*/sub\) is a store path within a working tree of a Git repository.
|
||||
[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
|
||||
[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
|
||||
[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
|
||||
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
|
||||
fi
|
||||
## But it fails if the path is imported with a fetcher that doesn't remove .git (like just using "${./.}")
|
||||
expectFailure 'import "${./.}" { fs = lib.fileset; }' 'lib.fileset.gitTrackedWith: The second argument \(.*\) is a store path within a working tree of a Git repository.
|
||||
[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
|
||||
[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
|
||||
[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
|
||||
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
|
||||
expectFailure 'import "${./.}/sub" { fs = lib.fileset; }' 'lib.fileset.gitTracked: The argument \(.*/sub\) is a store path within a working tree of a Git repository.
|
||||
[[:blank:]]*This indicates that a source directory was imported into the store using a method such as `import "\$\{./.\}"` or `path:.`.
|
||||
[[:blank:]]*This function currently does not support such a use case, since it currently relies on `builtins.fetchGit`.
|
||||
[[:blank:]]*You could make this work by using a fetcher such as `fetchGit` instead of copying the whole repository.
|
||||
[[:blank:]]*If you can'\''t avoid copying the repo to the store, see https://github.com/NixOS/nix/issues/9292.'
|
||||
rm -rf -- *
|
||||
|
||||
# shallow = true is not supported on all Nix versions
|
||||
# and older versions don't support shallow clones at all
|
||||
if [[ "$(nix-instantiate --eval --expr "$prefixExpression (versionAtLeast builtins.nixVersion _fetchGitShallowMinver)")" == true ]]; then
|
||||
createGitRepo full
|
||||
# Extra commit such that there's a commit that won't be in the shallow clone
|
||||
git -C full commit --allow-empty -q -m extra
|
||||
git clone -q --depth 1 "file://${PWD}/full" shallow
|
||||
cd shallow
|
||||
checkGitTracked
|
||||
cd ..
|
||||
rm -rf -- *
|
||||
fi
|
||||
createGitRepo full
|
||||
# Extra commit such that there's a commit that won't be in the shallow clone
|
||||
git -C full commit --allow-empty -q -m extra
|
||||
git clone -q --depth 1 "file://${PWD}/full" shallow
|
||||
cd shallow
|
||||
checkGitTracked
|
||||
cd ..
|
||||
rm -rf -- *
|
||||
|
||||
# Go through all stages of Git files
|
||||
# See https://www.git-scm.com/book/en/v2/Git-Basics-Recording-Changes-to-the-Repository
|
||||
|
||||
+21
-9
@@ -232,15 +232,9 @@ lib.mapAttrs mkLicense (
|
||||
fullName = "Lawrence Berkeley National Labs BSD variant license";
|
||||
};
|
||||
|
||||
bsd3TheodoreTso = {
|
||||
fullName = "BSD 3 Clause Theodore Tso Variant";
|
||||
# TODO: if the license gets accepted to spdx then
|
||||
# add spdxId
|
||||
# else
|
||||
# remove license
|
||||
# && replace all references with bsd3
|
||||
# https://tools.spdx.org/app/license_requests/442/
|
||||
# https://github.com/spdx/license-list-XML/issues/2702
|
||||
bsd3ClauseTso = {
|
||||
spdxId = "BSD-3-Clause-Tso";
|
||||
fullName = "BSD 3-Clause Tso variant";
|
||||
};
|
||||
|
||||
bsdAxisNoDisclaimerUnmodified = {
|
||||
@@ -719,6 +713,16 @@ lib.mapAttrs mkLicense (
|
||||
spdxId = "HPND-sell-variant";
|
||||
};
|
||||
|
||||
hpndDoc = {
|
||||
fullName = "Historical Permission Notice and Disclaimer - documentation variant";
|
||||
spdxId = "HPND-doc";
|
||||
};
|
||||
|
||||
hpndDocSell = {
|
||||
fullName = "Historical Permission Notice and Disclaimer - documentation sell variant";
|
||||
spdxId = "HPND-doc-sell";
|
||||
};
|
||||
|
||||
hpndUc = {
|
||||
spdxId = "HPND-UC";
|
||||
fullName = "Historical Permission Notice and Disclaimer - University of California variant";
|
||||
@@ -1311,6 +1315,14 @@ lib.mapAttrs mkLicense (
|
||||
# Marc Weber (small nix contributor)
|
||||
};
|
||||
|
||||
tekHvcLicense = {
|
||||
fullName = "TekHVC License";
|
||||
url = "https://gitlab.freedesktop.org/xorg/lib/libx11/-/blob/7f8305c779ac6948d7261764f5ffb8ae9aa975b1/COPYING#L138-171";
|
||||
# TODO: add spdxId when it gets accepted to spdx
|
||||
# https://tools.spdx.org/app/license_requests/458
|
||||
# https://github.com/spdx/license-list-XML/issues/2757
|
||||
};
|
||||
|
||||
tsl = {
|
||||
shortName = "TSL";
|
||||
fullName = "Timescale License Agreegment";
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
let
|
||||
features = [
|
||||
{
|
||||
description = "the `nixVersion` builtin";
|
||||
condition = builtins ? nixVersion;
|
||||
}
|
||||
{
|
||||
description = "`builtins.nixVersion` reports at least 2.18";
|
||||
condition = builtins ? nixVersion && builtins.compareVersions "2.18" builtins.nixVersion != 1;
|
||||
}
|
||||
];
|
||||
|
||||
evaluated = builtins.partition ({ condition, ... }: condition) features;
|
||||
in
|
||||
{
|
||||
all = features;
|
||||
supported = evaluated.right;
|
||||
missing = evaluated.wrong;
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
# Expose the minimum required version for evaluating Nixpkgs
|
||||
"2.18"
|
||||
@@ -563,6 +563,51 @@ let
|
||||
# See https://go.dev/wiki/GoArm
|
||||
GOARM = toString (lib.intersectLists [ (final.parsed.cpu.version or "") ] [ "5" "6" "7" ]);
|
||||
};
|
||||
|
||||
node = {
|
||||
# See these locations for a list of known architectures/platforms:
|
||||
# - https://nodejs.org/api/os.html#osarch
|
||||
# - https://nodejs.org/api/os.html#osplatform
|
||||
arch =
|
||||
if final.isAarch then
|
||||
"arm" + lib.optionalString final.is64bit "64"
|
||||
else if final.isMips32 then
|
||||
"mips" + lib.optionalString final.isLittleEndian "el"
|
||||
else if final.isMips64 && final.isLittleEndian then
|
||||
"mips64el"
|
||||
else if final.isPower then
|
||||
"ppc" + lib.optionalString final.is64bit "64"
|
||||
else if final.isx86_64 then
|
||||
"x64"
|
||||
else if final.isx86_32 then
|
||||
"ia32"
|
||||
else if final.isS390x then
|
||||
"s390x"
|
||||
else if final.isRiscV64 then
|
||||
"riscv64"
|
||||
else if final.isLoongArch64 then
|
||||
"loong64"
|
||||
else
|
||||
null;
|
||||
|
||||
platform =
|
||||
if final.isAndroid then
|
||||
"android"
|
||||
else if final.isDarwin then
|
||||
"darwin"
|
||||
else if final.isFreeBSD then
|
||||
"freebsd"
|
||||
else if final.isLinux then
|
||||
"linux"
|
||||
else if final.isOpenBSD then
|
||||
"openbsd"
|
||||
else if final.isSunOS then
|
||||
"sunos"
|
||||
else if final.isWindows then
|
||||
"win32"
|
||||
else
|
||||
null;
|
||||
};
|
||||
};
|
||||
in
|
||||
assert final.useAndroidPrebuilt -> final.isAndroid;
|
||||
|
||||
+156
-41
@@ -432,12 +432,6 @@
|
||||
name = "Ashish SHUKLA";
|
||||
keys = [ { fingerprint = "F682 CDCC 39DC 0FEA E116 20B6 C746 CFA9 E74F A4B0"; } ];
|
||||
};
|
||||
abbradar = {
|
||||
email = "ab@fmap.me";
|
||||
github = "abbradar";
|
||||
githubId = 1174810;
|
||||
name = "Nikolay Amiantov";
|
||||
};
|
||||
abcsds = {
|
||||
email = "abcsds@gmail.com";
|
||||
github = "abcsds";
|
||||
@@ -547,12 +541,25 @@
|
||||
github = "aciceri";
|
||||
githubId = 2318843;
|
||||
};
|
||||
acidbong = {
|
||||
name = "Acid Bong";
|
||||
email = "acidbong@tilde.club";
|
||||
github = "acid-bong";
|
||||
githubId = 94849097;
|
||||
};
|
||||
acowley = {
|
||||
email = "acowley@gmail.com";
|
||||
github = "acowley";
|
||||
githubId = 124545;
|
||||
name = "Anthony Cowley";
|
||||
};
|
||||
acture = {
|
||||
email = "acturea@gmail.com";
|
||||
github = "Acture";
|
||||
githubId = 11632382;
|
||||
name = "Acture";
|
||||
keys = [ { fingerprint = "30D9 BFA9 6998 4393 37B1 08EC B0FE 879A 0504 3C80"; } ];
|
||||
};
|
||||
acuteaangle = {
|
||||
name = "Summer Tea";
|
||||
email = "zestypurple@protonmail.com";
|
||||
@@ -1580,6 +1587,12 @@
|
||||
githubId = 587021;
|
||||
name = "André V L Matos";
|
||||
};
|
||||
andrewbastin = {
|
||||
email = "andrewbastin.k@gmail.com";
|
||||
github = "AndrewBastin";
|
||||
githubId = 9131943;
|
||||
name = "Andrew Bastin";
|
||||
};
|
||||
andrewchambers = {
|
||||
email = "ac@acha.ninja";
|
||||
github = "andrewchambers";
|
||||
@@ -2070,6 +2083,12 @@
|
||||
githubId = 29145250;
|
||||
name = "Armeen Mahdian";
|
||||
};
|
||||
armelclo = {
|
||||
email = "armel@armelclo.fr";
|
||||
github = "ArmelClo";
|
||||
githubId = 61419525;
|
||||
name = "Armel Cloarec";
|
||||
};
|
||||
armijnhemel = {
|
||||
email = "armijn@tjaldur.nl";
|
||||
github = "armijnhemel";
|
||||
@@ -5573,6 +5592,12 @@
|
||||
githubId = 217543;
|
||||
name = "Damien Cassou";
|
||||
};
|
||||
dan-kc = {
|
||||
email = "daniel@keone.dev";
|
||||
github = "dan-kc";
|
||||
githubId = 63171098;
|
||||
name = "Daniel Cox";
|
||||
};
|
||||
dan-theriault = {
|
||||
email = "nix@theriault.codes";
|
||||
github = "Dan-Theriault";
|
||||
@@ -6673,12 +6698,6 @@
|
||||
name = "Donovan Glover";
|
||||
keys = [ { fingerprint = "EE7D 158E F9E7 660E 0C33 86B2 8FC5 F7D9 0A5D 8F4D"; } ];
|
||||
};
|
||||
donteatoreo = {
|
||||
name = "DontEatOreo";
|
||||
github = "DontEatOreo";
|
||||
githubId = 57304299;
|
||||
matrix = "@donteatoreo:matrix.org";
|
||||
};
|
||||
dopplerian = {
|
||||
name = "Dopplerian";
|
||||
github = "Dopplerian";
|
||||
@@ -6838,6 +6857,12 @@
|
||||
githubId = 81854406;
|
||||
name = "Chew Cheng Hong";
|
||||
};
|
||||
drew-dirac = {
|
||||
email = "drew@diracinc.com";
|
||||
github = "drew-dirac";
|
||||
githubId = 187309685;
|
||||
name = "Drew Council";
|
||||
};
|
||||
drewrisinger = {
|
||||
email = "drisinger+nixpkgs@gmail.com";
|
||||
github = "drewrisinger";
|
||||
@@ -7281,6 +7306,12 @@
|
||||
github = "eigengrau";
|
||||
githubId = 4939947;
|
||||
};
|
||||
eihqnh = {
|
||||
email = "eihqnh@outlook.com";
|
||||
github = "eihqnh";
|
||||
githubId = 40905037;
|
||||
name = "eihqnh";
|
||||
};
|
||||
eikek = {
|
||||
email = "eike.kettner@posteo.de";
|
||||
github = "eikek";
|
||||
@@ -7746,6 +7777,13 @@
|
||||
github = "ErinvanderVeen";
|
||||
githubId = 10973664;
|
||||
};
|
||||
eripa = {
|
||||
name = "Eric Ripa";
|
||||
email = "eric@ripa.io";
|
||||
keys = [ { fingerprint = "L2IODNAzlzi0tkpCy4LHixqMUhkEas9D3+mo4a+PQZg"; } ];
|
||||
github = "eripa";
|
||||
githubId = 1429673;
|
||||
};
|
||||
ern775 = {
|
||||
email = "eren.demir2479090@gmail.com";
|
||||
github = "ern775";
|
||||
@@ -7777,12 +7815,6 @@
|
||||
githubId = 5427394;
|
||||
name = "Ersin Akinci";
|
||||
};
|
||||
ertes = {
|
||||
email = "esz@posteo.de";
|
||||
github = "ertes";
|
||||
githubId = 1855930;
|
||||
name = "Ertugrul Söylemez";
|
||||
};
|
||||
esau79p = {
|
||||
github = "EsAu79p";
|
||||
githubId = 21313906;
|
||||
@@ -8460,6 +8492,12 @@
|
||||
name = "Sebastian Neubauer";
|
||||
keys = [ { fingerprint = "2F93 661D AC17 EA98 A104 F780 ECC7 55EE 583C 1672"; } ];
|
||||
};
|
||||
FlameFlag = {
|
||||
name = "FlameFlag";
|
||||
github = "FlameFlag";
|
||||
githubId = 57304299;
|
||||
matrix = "@donteatoreo:matrix.org";
|
||||
};
|
||||
Flameopathic = {
|
||||
email = "flameopathic@gmail.com";
|
||||
github = "Flameopathic";
|
||||
@@ -9355,6 +9393,12 @@
|
||||
githubId = 471835;
|
||||
name = "Giorgio Gallo";
|
||||
};
|
||||
gipphe = {
|
||||
email = "gipphe@gmail.com";
|
||||
github = "Gipphe";
|
||||
githubId = 2266817;
|
||||
name = "Victor Nascimento Bakke";
|
||||
};
|
||||
GirardR1006 = {
|
||||
email = "julien.girard2@cea.fr";
|
||||
github = "GirardR1006";
|
||||
@@ -10765,10 +10809,10 @@
|
||||
name = "Ilham AM";
|
||||
};
|
||||
ilian = {
|
||||
email = "ilian@tuta.io";
|
||||
email = "nixos@ilian.dev";
|
||||
github = "ilian";
|
||||
githubId = 25505957;
|
||||
name = "Ilian";
|
||||
name = "ilian";
|
||||
};
|
||||
iliayar = {
|
||||
email = "iliayar3@gmail.com";
|
||||
@@ -12834,6 +12878,11 @@
|
||||
github = "juliamertz";
|
||||
githubId = 35079666;
|
||||
};
|
||||
julian-hoch = {
|
||||
name = "Julian Hoch";
|
||||
github = "julian-hoch";
|
||||
githubId = 95583314;
|
||||
};
|
||||
JulianFP = {
|
||||
name = "Julian Partanen";
|
||||
github = "JulianFP";
|
||||
@@ -13279,6 +13328,13 @@
|
||||
githubId = 9433472;
|
||||
name = "ash";
|
||||
};
|
||||
keyzox = {
|
||||
email = "nixpkgs@adjoly.fr";
|
||||
github = "keyzox71";
|
||||
matrix = "@keyzox:matrix.org";
|
||||
githubId = 18579667;
|
||||
name = "Adam J.";
|
||||
};
|
||||
kfollesdal = {
|
||||
email = "kfollesdal@gmail.com";
|
||||
github = "kfollesdal";
|
||||
@@ -14100,6 +14156,11 @@
|
||||
githubId = 61395246;
|
||||
name = "Lampros Pitsillos";
|
||||
};
|
||||
langsjo = {
|
||||
name = "langsjo";
|
||||
github = "langsjo";
|
||||
githubId = 104687438;
|
||||
};
|
||||
larsr = {
|
||||
email = "Lars.Rasmusson@gmail.com";
|
||||
github = "larsr";
|
||||
@@ -18005,6 +18066,12 @@
|
||||
githubId = 42888162;
|
||||
keys = [ { fingerprint = "A0B9 48C5 A263 55C2 035F 8567 FBB7 2A94 52D9 1A72"; } ];
|
||||
};
|
||||
neurofibromin = {
|
||||
name = "Neurofibromin";
|
||||
github = "Neurofibromin";
|
||||
githubId = 125222560;
|
||||
keys = [ { fingerprint = "9F9B FE94 618A D266 67BD 2821 4F67 1AFA D8D4 428B"; } ];
|
||||
};
|
||||
neverbehave = {
|
||||
email = "i@never.pet";
|
||||
github = "NeverBehave";
|
||||
@@ -18198,6 +18265,12 @@
|
||||
githubId = 70602908;
|
||||
github = "nikolaizombie1";
|
||||
};
|
||||
niksingh710 = {
|
||||
email = "nik.singh710@gmail.com";
|
||||
name = "Nikhil Singh";
|
||||
github = "niksingh710";
|
||||
githubId = 60490474;
|
||||
};
|
||||
nikstur = {
|
||||
email = "nikstur@outlook.com";
|
||||
name = "nikstur";
|
||||
@@ -18421,6 +18494,12 @@
|
||||
githubId = 148037;
|
||||
name = "Joachim Breitner";
|
||||
};
|
||||
nomis = {
|
||||
email = "nixpkgs@octiron.net";
|
||||
github = "nomis";
|
||||
githubId = 70171;
|
||||
name = "Simon Arlott";
|
||||
};
|
||||
nomisiv = {
|
||||
email = "simon@nomisiv.com";
|
||||
github = "NomisIV";
|
||||
@@ -18643,6 +18722,12 @@
|
||||
githubId = 51034487;
|
||||
matrix = "@nullcube:matrix.org";
|
||||
};
|
||||
nulleric = {
|
||||
email = "erichelgeson@gmail.com";
|
||||
name = "Eric Helgeson";
|
||||
github = "erichelgeson";
|
||||
githubId = 271734;
|
||||
};
|
||||
nullishamy = {
|
||||
email = "spam@amyerskine.me";
|
||||
name = "nullishamy";
|
||||
@@ -19091,12 +19176,6 @@
|
||||
name = "Oops418";
|
||||
githubId = 93655215;
|
||||
};
|
||||
oosquare = {
|
||||
name = "Justin Chen";
|
||||
email = "oosquare@outlook.com";
|
||||
github = "oosquare";
|
||||
githubId = 42143810;
|
||||
};
|
||||
opeik = {
|
||||
email = "sandro@stikic.com";
|
||||
github = "opeik";
|
||||
@@ -20464,12 +20543,6 @@
|
||||
github = "ppom0";
|
||||
githubId = 38916722;
|
||||
};
|
||||
pradeepchhetri = {
|
||||
email = "pradeep.chhetri89@gmail.com";
|
||||
github = "pradeepchhetri";
|
||||
githubId = 2232667;
|
||||
name = "Pradeep Chhetri";
|
||||
};
|
||||
pradyuman = {
|
||||
email = "me@pradyuman.co";
|
||||
github = "pradyuman";
|
||||
@@ -20796,11 +20869,10 @@
|
||||
githubId = 7279609;
|
||||
};
|
||||
pyrotelekinetic = {
|
||||
name = "Clover";
|
||||
email = "carter@isons.org";
|
||||
name = "Clover Ison";
|
||||
email = "clover@isons.org";
|
||||
github = "pyrotelekinetic";
|
||||
githubId = 29682759;
|
||||
keys = [ { fingerprint = "5963 78DB 25AA 608D 2743 D466 5D6A D9AE 71B3 F983"; } ];
|
||||
};
|
||||
pyrox0 = {
|
||||
name = "Pyrox";
|
||||
@@ -20964,12 +21036,6 @@
|
||||
githubId = 2141853;
|
||||
name = "Bang Lee";
|
||||
};
|
||||
qwqawawow = {
|
||||
email = "eihqnh@outlook.com";
|
||||
github = "qwqawawow";
|
||||
githubId = 40905037;
|
||||
name = "qwqawawow";
|
||||
};
|
||||
qxrein = {
|
||||
email = "mnv07@proton.me";
|
||||
github = "qxrein";
|
||||
@@ -21155,6 +21221,12 @@
|
||||
githubId = 5653911;
|
||||
name = "Rampoina";
|
||||
};
|
||||
randomdude = {
|
||||
name = "Random Dude";
|
||||
email = "randomdude16671@proton.me";
|
||||
github = "randomdude16671";
|
||||
githubId = 210965013;
|
||||
};
|
||||
rane = {
|
||||
name = "Rane";
|
||||
email = "rane+git@junkyard.systems";
|
||||
@@ -22466,6 +22538,13 @@
|
||||
github = "s0me1newithhand7s";
|
||||
githubId = 117505144;
|
||||
};
|
||||
s0ssh = {
|
||||
name = "s0ssh";
|
||||
email = "me@s0s.sh";
|
||||
github = "s0ssh";
|
||||
githubId = 168315776;
|
||||
keys = [ { fingerprint = "1D34 4976 77AD 462C CA9F D5F1 FF16 29B1 3E89 9C1A"; } ];
|
||||
};
|
||||
s1341 = {
|
||||
email = "s1341@shmarya.net";
|
||||
matrix = "@s1341:matrix.org";
|
||||
@@ -23235,6 +23314,12 @@
|
||||
githubId = 1588288;
|
||||
name = "Shahrukh Khan";
|
||||
};
|
||||
shakhzodkudratov = {
|
||||
email = "shakhzodkudratov@gmail.com";
|
||||
github = "shakhzodkudratov";
|
||||
githubId = 37299109;
|
||||
name = "Shakhzod Kudratov";
|
||||
};
|
||||
shamilton = {
|
||||
email = "sgn.hamilton@protonmail.com";
|
||||
github = "SCOTT-HAMILTON";
|
||||
@@ -23934,6 +24019,12 @@
|
||||
githubId = 55726;
|
||||
name = "Stanislav Ochotnický";
|
||||
};
|
||||
sodagunz = {
|
||||
name = "sodagunz";
|
||||
github = "sodagunz";
|
||||
githubId = 19618127;
|
||||
email = "sodagunz+nixpkgs@proton.me";
|
||||
};
|
||||
sodiboo = {
|
||||
name = "sodiboo";
|
||||
github = "sodiboo";
|
||||
@@ -24484,6 +24575,12 @@
|
||||
githubId = 1315818;
|
||||
name = "Felix Bühler";
|
||||
};
|
||||
stupidcomputer = {
|
||||
email = "ryan@beepboop.systems";
|
||||
github = "stupidcomputer";
|
||||
githubId = 108326967;
|
||||
name = "Ryan Marina";
|
||||
};
|
||||
stupremee = {
|
||||
email = "jutus.k@protonmail.com";
|
||||
github = "Stupremee";
|
||||
@@ -24761,6 +24858,12 @@
|
||||
githubId = 143103;
|
||||
name = "Attila Sztupak";
|
||||
};
|
||||
t-monaghan = {
|
||||
email = "tomaghan@gmail.com";
|
||||
github = "t-monaghan";
|
||||
githubId = 62273348;
|
||||
name = "Thomas Monaghan";
|
||||
};
|
||||
t184256 = {
|
||||
email = "monk@unboiled.info";
|
||||
github = "t184256";
|
||||
@@ -27617,6 +27720,12 @@
|
||||
githubId = 25372613;
|
||||
name = "Woze Parrot";
|
||||
};
|
||||
wozrer = {
|
||||
name = "wozrer";
|
||||
email = "wozrer@proton.me";
|
||||
github = "wrrrzr";
|
||||
githubId = 161970349;
|
||||
};
|
||||
wr0belj = {
|
||||
name = "Jakub Wróbel";
|
||||
email = "wrobel.jakub@protonmail.com";
|
||||
@@ -28109,6 +28218,12 @@
|
||||
githubId = 1311192;
|
||||
name = "Alexander Kiselyov";
|
||||
};
|
||||
ylannl = {
|
||||
email = "ravi@ylan.nl";
|
||||
github = "ylannl";
|
||||
githubId = 1742643;
|
||||
name = "Ravi Peters";
|
||||
};
|
||||
ylecornec = {
|
||||
email = "yves.stan.lecornec@tweag.io";
|
||||
github = "ylecornec";
|
||||
|
||||
@@ -80,13 +80,7 @@ echo "Merging https://github.com/NixOS/nixpkgs/pull/${curr_haskell_updates_pr_nu
|
||||
gh pr merge --repo NixOS/nixpkgs --merge "$curr_haskell_updates_pr_num"
|
||||
|
||||
# Update stackage, Hackage hashes, and regenerate Haskell package set
|
||||
echo "Updating Stackage..."
|
||||
./maintainers/scripts/haskell/update-stackage.sh --do-commit
|
||||
echo "Updating Hackage hashes..."
|
||||
./maintainers/scripts/haskell/update-hackage.sh --do-commit
|
||||
echo "Regenerating Hackage packages..."
|
||||
# Using fast here because after the hackage-update eval errors will likely break the transitive dependencies check.
|
||||
./maintainers/scripts/haskell/regenerate-hackage-packages.sh --fast --do-commit
|
||||
./maintainers/scripts/haskell/update-package-set.sh
|
||||
|
||||
# Push these new commits to the haskell-updates branch
|
||||
echo "Pushing commits just created to the remote $push_remote/haskell-updates branch..."
|
||||
|
||||
@@ -107,10 +107,10 @@ nixfmt pkgs/development/haskell-modules/hackage-packages.nix
|
||||
if [[ "$DO_COMMIT" -eq 1 ]]; then
|
||||
git add pkgs/development/haskell-modules/configuration-hackage2nix/transitive-broken.yaml
|
||||
git add pkgs/development/haskell-modules/hackage-packages.nix
|
||||
git commit -F - << EOF
|
||||
git commit --edit -F - << EOF
|
||||
haskellPackages: regenerate package set based on current config
|
||||
|
||||
This commit has been generated by maintainers/scripts/haskell/regenerate-hackage-packages.sh
|
||||
(generated by maintainers/scripts/haskell/regenerate-hackage-packages.sh)
|
||||
EOF
|
||||
fi
|
||||
|
||||
|
||||
@@ -1,10 +1,34 @@
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i bash -p curl jq git gnused -I nixpkgs=.
|
||||
|
||||
# See regenerate-hackage-packages.sh for details on the purpose of this script.
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Update Hackage index and hashes data exposed via pkgs.all-cabal-hashes.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Find latest revision of the commercialhaskell/all-cabal-hashes repository's
|
||||
# hackage branch and update pkgs/data/misc/hackage/pin.json accordingly.
|
||||
#
|
||||
# This data is used by hackage2nix to generate hackage-packages.nix. Since
|
||||
# hackage2nix uses the latest version of a package unless an explicit
|
||||
# constraint is configured, running this script indirectly updates packages
|
||||
# (when hackage2nix is executed afterwards).
|
||||
#
|
||||
# Prints a version difference to stdout if the pin has been updated, nothing
|
||||
# otherwise.
|
||||
#
|
||||
# EXIT STATUS
|
||||
#
|
||||
# Always exit with zero (even if nothing changed) unless there was an error.
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
if [[ "${1:-}" == "--do-commit" ]]; then
|
||||
echo "$0: --do-commit is no longer supported. Use update-package-set.sh instead."
|
||||
exit 100
|
||||
fi
|
||||
|
||||
pin_file=pkgs/data/misc/hackage/pin.json
|
||||
current_commit="$(jq -r .commit $pin_file)"
|
||||
old_date="$(jq -r .msg $pin_file | sed 's/Update from Hackage at //')"
|
||||
@@ -14,6 +38,7 @@ commit_msg="$(echo "$git_info" | jq -r .commit.commit.message)"
|
||||
new_date="$(echo "$commit_msg" | sed 's/Update from Hackage at //')"
|
||||
|
||||
if [ "$current_commit" != "$head_commit" ]; then
|
||||
echo "Updating all-cabal-hashes from $old_date to $new_date" >&2
|
||||
url="https://github.com/commercialhaskell/all-cabal-hashes/archive/$head_commit.tar.gz"
|
||||
hash="$(nix-prefetch-url "$url")"
|
||||
jq -n \
|
||||
@@ -23,13 +48,9 @@ if [ "$current_commit" != "$head_commit" ]; then
|
||||
--arg commit_msg "$commit_msg" \
|
||||
'{commit: $commit, url: $url, sha256: $hash, msg: $commit_msg}' \
|
||||
> $pin_file
|
||||
else
|
||||
echo "No new all-cabal-hashes version" >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [[ "${1:-}" == "--do-commit" ]]; then
|
||||
git add pkgs/data/misc/hackage/pin.json
|
||||
git commit -F - << EOF
|
||||
all-cabal-hashes: $old_date -> $new_date
|
||||
|
||||
This commit has been generated by maintainers/scripts/haskell/update-hackage.sh
|
||||
EOF
|
||||
fi
|
||||
echo "$old_date -> $new_date"
|
||||
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i bash
|
||||
#! nix-shell -p git -I nixpkgs=.
|
||||
set -euo pipefail
|
||||
|
||||
filesToStage=(
|
||||
'pkgs/data/misc/hackage/pin.json'
|
||||
'pkgs/development/haskell-modules/configuration-hackage2nix/stackage.yaml'
|
||||
'pkgs/development/haskell-modules/hackage-packages.nix'
|
||||
)
|
||||
|
||||
if ! git diff --quiet --cached; then
|
||||
echo "Please commit staged changes before running $0" >&2
|
||||
exit 100
|
||||
fi
|
||||
|
||||
if ! git diff --quiet -- "${filesToStage[@]}"; then
|
||||
echo -n "Please commit your changes to the following files before running $0: " >&2
|
||||
echo "${filesToStage[@]}" >&2
|
||||
exit 100
|
||||
fi
|
||||
|
||||
stackage_diff="$(./maintainers/scripts/haskell/update-stackage.sh)"
|
||||
hackage_diff="$(./maintainers/scripts/haskell/update-hackage.sh)"
|
||||
readonly stackage_diff hackage_diff
|
||||
|
||||
# Prefer Stackage version diff in the commit header, fall back to Hackage
|
||||
if [[ -n "$stackage_diff" ]]; then
|
||||
commit_message="haskellPackages: stackage $stackage_diff"
|
||||
if [[ -n "$hackage_diff" ]]; then
|
||||
commit_message="$commit_message
|
||||
|
||||
all-cabal-hashes: $hackage_diff"
|
||||
fi
|
||||
elif [[ -n "$hackage_diff" ]]; then
|
||||
commit_message="haskellPackages: hackage $hackage_diff
|
||||
|
||||
all-cabal-hashes: $hackage_diff"
|
||||
else
|
||||
echo "Neither Hackage nor Stackage changed. Nothing to do." >&2
|
||||
exit 0
|
||||
fi
|
||||
|
||||
commit_message="$commit_message
|
||||
|
||||
(generated by maintainers/scripts/haskell/update-package-set.sh)"
|
||||
|
||||
# Using fast here because after the hackage-update eval errors will likely break the transitive dependencies check.
|
||||
./maintainers/scripts/haskell/regenerate-hackage-packages.sh --fast
|
||||
|
||||
# A --do-commit flag probably doesn't make much sense
|
||||
git add -- "${filesToStage[@]}"
|
||||
git commit -m "$commit_message"
|
||||
@@ -1,9 +1,36 @@
|
||||
#! /usr/bin/env nix-shell
|
||||
#! nix-shell -i bash -p curl jq git gnused gnugrep -I nixpkgs=.
|
||||
# shellcheck shell=bash
|
||||
#
|
||||
# SYNOPSIS
|
||||
#
|
||||
# Update version constraints in hackage2nix config file from Stackage.
|
||||
#
|
||||
# DESCRIPTION
|
||||
#
|
||||
# Fetches the latest snapshot of the configured Stackage solver which is
|
||||
# configured via the SOLVER (either LTS or Nightly) and VERSION variables in
|
||||
# the script.
|
||||
#
|
||||
# VERSION is only applicable if SOLVER is LTS. SOLVER=LTS and VERSION=22
|
||||
# will cause update-stackage.sh to fetch the latest LTS-22.XX version.
|
||||
# If empty, the latest version of the solver is used.
|
||||
#
|
||||
# If the configuration file has been updated, update-stackage.sh prints a
|
||||
# version difference to stdout, e.g. 23.11 -> 23.13. Otherwise, stdout remains
|
||||
# empty.
|
||||
#
|
||||
# EXIT STATUS
|
||||
#
|
||||
# Always exit with zero (even if nothing changed) unless there was an error.
|
||||
|
||||
set -eu -o pipefail
|
||||
|
||||
if [[ "${1:-}" == "--do-commit" ]]; then
|
||||
echo "$0: --do-commit is no longer supported. Use update-package-set.sh instead."
|
||||
exit 100
|
||||
fi
|
||||
|
||||
# Stackage solver to use, LTS or Nightly
|
||||
# (should be capitalized like the display name)
|
||||
SOLVER=LTS
|
||||
@@ -31,11 +58,11 @@ old_version=$(grep '^# Stackage' $stackage_config | sed -e 's/.\+ \([A-Za-z]\+ [
|
||||
version="$SOLVER $(sed -rn "s/^--.*http:..(www.)?stackage.org.snapshot.$(toLower "$SOLVER")-//p" "$tmpfile")"
|
||||
|
||||
if [[ "$old_version" == "$version" ]]; then
|
||||
echo "No new stackage version"
|
||||
echo "No new stackage version" >&2
|
||||
exit 0 # Nothing to do
|
||||
fi
|
||||
|
||||
echo "Updating Stackage from $old_version to $version."
|
||||
echo "Updating Stackage from $old_version to $version." >&2
|
||||
|
||||
# Create a simple yaml version of the file.
|
||||
sed -r \
|
||||
@@ -78,11 +105,4 @@ sed -r \
|
||||
# ShellCheck: latest version of command-line dev tool.
|
||||
# Agda: The Agda community is fast-moving; we strive to always include the newest versions of Agda and the Agda packages in nixpkgs.
|
||||
|
||||
if [[ "${1:-}" == "--do-commit" ]]; then
|
||||
git add $stackage_config
|
||||
git commit -F - << EOF
|
||||
haskellPackages: stackage $old_version -> $version
|
||||
|
||||
This commit has been generated by maintainers/scripts/haskell/update-stackage.sh
|
||||
EOF
|
||||
fi
|
||||
echo "$old_version -> $version"
|
||||
|
||||
@@ -1023,7 +1023,6 @@ with lib.maintainers;
|
||||
php = {
|
||||
members = [
|
||||
aanderse
|
||||
drupol
|
||||
ma27
|
||||
piotrkwiecinski
|
||||
talyz
|
||||
@@ -1257,6 +1256,7 @@ with lib.maintainers;
|
||||
orzklv
|
||||
bahrom04
|
||||
bemeritus
|
||||
shakhzodkudratov
|
||||
];
|
||||
scope = "Maintain Uzbek Linux state & community packages and modules.";
|
||||
shortName = "Uzinfocom Open Source";
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
# `<nixpkgs>/modules`
|
||||
|
||||
This directory hosts subdirectories representing each module [class](https://nixos.org/manual/nixpkgs/stable/#module-system-lib-evalModules-param-class) for which the `nixpkgs` repository has user-importable modules.
|
||||
|
||||
Exceptions:
|
||||
- `_class = "nixos";` modules go in the `<nixpkgs>/nixos/modules` tree
|
||||
- modules whose only purpose is to test code in this repository
|
||||
|
||||
The emphasis is on _importable_ modules, i.e. ones that aren't inherent to and built into the Module System application.
|
||||
@@ -0,0 +1,63 @@
|
||||
# Test:
|
||||
# ./meta-maintainers/test.nix
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib)
|
||||
mkOption
|
||||
mkOptionType
|
||||
types
|
||||
;
|
||||
|
||||
maintainer = mkOptionType {
|
||||
name = "maintainer";
|
||||
check = email: lib.elem email (lib.attrValues lib.maintainers);
|
||||
merge = loc: defs: {
|
||||
# lib.last: Perhaps this could be merged instead, if "at most once per module"
|
||||
# is a problem (see option description).
|
||||
${(lib.last defs).file} = (lib.last defs).value;
|
||||
};
|
||||
};
|
||||
|
||||
listOfMaintainers = types.listOf maintainer // {
|
||||
merge =
|
||||
loc: defs:
|
||||
lib.zipAttrs (
|
||||
lib.flatten (
|
||||
lib.imap1 (
|
||||
n: def:
|
||||
lib.imap1 (
|
||||
m: def':
|
||||
maintainer.merge (loc ++ [ "[${toString n}-${toString m}]" ]) [
|
||||
{
|
||||
inherit (def) file;
|
||||
value = def';
|
||||
}
|
||||
]
|
||||
) def.value
|
||||
) defs
|
||||
)
|
||||
);
|
||||
};
|
||||
in
|
||||
{
|
||||
_class = null; # not specific to NixOS
|
||||
options = {
|
||||
meta = {
|
||||
maintainers = mkOption {
|
||||
type = listOfMaintainers;
|
||||
default = [ ];
|
||||
example = lib.literalExpression ''[ lib.maintainers.alice lib.maintainers.bob ]'';
|
||||
description = ''
|
||||
List of maintainers of each module.
|
||||
This option should be defined at most once per module.
|
||||
|
||||
The option value is not a list of maintainers, but an attribute set that maps module file names to lists of maintainers.
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
pierron
|
||||
roberth
|
||||
];
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
# Run:
|
||||
# $ nix-instantiate --eval 'modules/generic/meta-maintainers/test.nix'
|
||||
#
|
||||
# Expected output:
|
||||
# { }
|
||||
#
|
||||
# Debugging:
|
||||
# drop .test from the end of this file, then use nix repl on it
|
||||
rec {
|
||||
lib = import ../../../lib;
|
||||
|
||||
example = lib.evalModules {
|
||||
modules = [
|
||||
../meta-maintainers.nix
|
||||
{
|
||||
_file = "eelco.nix";
|
||||
meta.maintainers = [ lib.maintainers.eelco ];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
test =
|
||||
assert
|
||||
example.config.meta.maintainers == {
|
||||
${toString ../meta-maintainers.nix} = [
|
||||
lib.maintainers.pierron
|
||||
lib.maintainers.roberth
|
||||
];
|
||||
"eelco.nix" = [ lib.maintainers.eelco ];
|
||||
};
|
||||
{ };
|
||||
|
||||
}
|
||||
.test
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
We'll cover imperative container management using `nixos-container`
|
||||
first. Be aware that container management is currently only possible as
|
||||
`root`.
|
||||
`root`, and that you need to enable [](#opt-boot.enableContainers) explicitly.
|
||||
|
||||
You create a container with identifier `foo` as follows:
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ Here, we include two modules from the same directory, `vpn.nix` and
|
||||
{
|
||||
services.xserver.enable = true;
|
||||
services.displayManager.sddm.enable = true;
|
||||
services.xserver.desktopManager.plasma5.enable = true;
|
||||
services.desktopManager.plasma6.enable = true;
|
||||
environment.systemPackages = [ pkgs.vim ];
|
||||
}
|
||||
```
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# Graphical {#sec-profile-graphical}
|
||||
|
||||
Defines a NixOS configuration with the Plasma 5 desktop. It's used by the
|
||||
Defines a NixOS configuration with the Plasma 6 desktop. It's used by the
|
||||
graphical installation CD.
|
||||
|
||||
It sets [](#opt-services.xserver.enable),
|
||||
[](#opt-services.displayManager.sddm.enable),
|
||||
[](#opt-services.xserver.desktopManager.plasma5.enable),
|
||||
[](#opt-services.desktopManager.plasma6.enable),
|
||||
and [](#opt-services.libinput.enable) to true. It also
|
||||
includes glxinfo and firefox in the system packages list.
|
||||
|
||||
@@ -23,7 +23,7 @@ Thus you should pick one or more of the following lines:
|
||||
|
||||
```nix
|
||||
{
|
||||
services.xserver.desktopManager.plasma5.enable = true;
|
||||
services.desktopManager.plasma6.enable = true;
|
||||
services.xserver.desktopManager.xfce.enable = true;
|
||||
services.desktopManager.gnome.enable = true;
|
||||
services.xserver.desktopManager.mate.enable = true;
|
||||
|
||||
@@ -12,10 +12,14 @@
|
||||
|
||||
- The NetworkManager module does not ship with a default set of VPN plugins anymore. All required VPN plugins must now be explicitly configured in [`networking.networkmanager.plugins`](#opt-networking.networkmanager.plugins).
|
||||
|
||||
- The Qt 5-based versions of KDE Gear, Plasma, Maui and Deepin have been removed. Users are advised to migrate to Plasma 6 and Gear 25.08, available under `kdePackages`.
|
||||
|
||||
## New Modules {#sec-release-25.11-new-modules}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
|
||||
- [byedpi](https://github.com/hufrea/byedpi), a DPI bypass service. Available as [services.byedpi](#opt-services.byedpi.enable).
|
||||
|
||||
- [Overseerr](https://overseerr.dev), a request management and media discovery tool for the Plex ecosystem. Available as [services.overseerr](#opt-services.overseerr.enable).
|
||||
|
||||
- [gtklock](https://github.com/jovanlanik/gtklock), a GTK-based lockscreen for Wayland. Available as [programs.gtklock](#opt-programs.gtklock.enable).
|
||||
@@ -96,6 +100,10 @@
|
||||
|
||||
- [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
|
||||
developers to build scalable applications without sacrificing productivity or
|
||||
reliability. Available as [services.temporal](#opt-services.temporal.enable).
|
||||
|
||||
## Backward Incompatibilities {#sec-release-25.11-incompatibilities}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
@@ -109,6 +117,9 @@
|
||||
- The non-LTS Forgejo package (`forgejo`) has been updated to 12.0.0. This release contains breaking changes, see the [release blog post](https://forgejo.org/2025-07-release-v12-0/)
|
||||
for all the details and how to ensure smooth upgrades.
|
||||
|
||||
- `sing-box` has been updated to 1.12.3, which includes a number of breaking changes, old configurations may need updating or they will cause the tool to fail to run.
|
||||
See the [change log](https://sing-box.sagernet.org/changelog/#1123) for details and [migration](https://sing-box.sagernet.org/migration/#1120) for how to update old configurations.
|
||||
|
||||
- The Pocket ID module ([`services.pocket-id`][#opt-services.pocket-id.enable]) and package (`pocket-id`) has been updated to 1.0.0. Some environment variables have been changed or removed, see the [migration guide](https://pocket-id.org/docs/setup/migrate-to-v1/).
|
||||
|
||||
- The `zigbee2mqtt` package was updated to version 2.x, which contains breaking changes. See the [discussion](https://github.com/Koenkk/zigbee2mqtt/discussions/24198) for further information.
|
||||
@@ -133,6 +144,8 @@
|
||||
|
||||
- `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.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.
|
||||
@@ -140,6 +153,8 @@
|
||||
|
||||
- `renovate` was updated to v41. See the upstream release notes for [v40](https://github.com/renovatebot/renovate/releases/tag/40.0.0) and [v41](https://github.com/renovatebot/renovate/releases/tag/41.0.0) for breaking changes.
|
||||
|
||||
- `i18n.inputMethod.fcitx5.plasma6Support` has been removed because qt6 is the only one used for fcitx5-configtool now.
|
||||
|
||||
- The `boot.readOnlyNixStore` has been removed. Control over bind mount options on `/nix/store` is now offered by the `boot.nixStoreMountOpts` option.
|
||||
|
||||
- The Postfix module has been updated and likely requires configuration changes:
|
||||
@@ -161,6 +176,8 @@
|
||||
|
||||
- `command-not-found` package is now disabled by default; it works only for nix-channels based systems, and requires setup for it to work.
|
||||
|
||||
- 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.
|
||||
|
||||
## Other Notable Changes {#sec-release-25.11-notable-changes}
|
||||
|
||||
<!-- To avoid merge conflicts, consider adding your item at an arbitrary place in the list instead. -->
|
||||
@@ -202,10 +219,14 @@
|
||||
- `systemd.watchdog.kexecTime` was renamed to `systemd.settings.Manager.KExecWatchdogSec`
|
||||
- `systemd.enableCgroupAccounting` was removed. Cgroup accounting now needs to be disabled directly using `systemd.settings.Manager.*Accounting`.
|
||||
|
||||
- `services.logind.extraConfig` was converted to RFC42-style `services.logind.settings.Login`.
|
||||
|
||||
- `services.ntpd-rs` now performs configuration validation.
|
||||
|
||||
- Immich now has support for [VectorChord](https://github.com/tensorchord/VectorChord) when using the PostgreSQL configuration provided by `services.immich.database.enable`, which replaces `pgvecto-rs`. VectorChord support can be toggled with the option `services.immich.database.enableVectorChord`. Additionally, `pgvecto-rs` support is now disabled from NixOS 25.11 onwards using the option `services.immich.database.enableVectors`. This option will be removed fully in the future once Immich drops support for `pgvecto-rs` fully. See [Immich migration instructions](#module-services-immich-vectorchord-migration)
|
||||
|
||||
- `services.restic.backups` now includes a `command` option for passing a command to the [--stdin-from-command](https://github.com/restic/restic/pull/4410) flag.
|
||||
|
||||
- `services.postsrsd` now automatically integrates with the local Postfix instance, when enabled. This behavior can disabled using the [services.postsrsd.configurePostfix](#opt-services.postsrsd.configurePostfix) option.
|
||||
|
||||
- `services.pfix-srsd` now automatically integrates with the local Postfix instance, when enabled. This behavior can disabled using the [services.pfix-srsd.configurePostfix](#opt-services.pfix-srsd.configurePostfix) option.
|
||||
|
||||
@@ -49,6 +49,7 @@ let
|
||||
version = release;
|
||||
revision = "release-${release}";
|
||||
prefix = modulesPath;
|
||||
extraSources = [ (dirOf nixosPath) ];
|
||||
};
|
||||
in
|
||||
docs.optionsNix
|
||||
|
||||
@@ -76,6 +76,10 @@ stdenv.mkDerivation {
|
||||
name = isoName;
|
||||
__structuredAttrs = true;
|
||||
|
||||
# the image will be self-contained so we can drop references
|
||||
# to the closure that was used to build it
|
||||
unsafeDiscardReferences.out = true;
|
||||
|
||||
buildCommandPath = ./make-iso9660-image.sh;
|
||||
nativeBuildInputs = [
|
||||
xorriso
|
||||
|
||||
@@ -27,6 +27,10 @@ stdenv.mkDerivation {
|
||||
name = "${fileName}${lib.optionalString (!hydraBuildProduct) ".img"}";
|
||||
__structuredAttrs = true;
|
||||
|
||||
# the image will be self-contained so we can drop references
|
||||
# to the closure that was used to build it
|
||||
unsafeDiscardReferences.out = true;
|
||||
|
||||
nativeBuildInputs = [ squashfsTools ];
|
||||
|
||||
buildCommand = ''
|
||||
|
||||
@@ -39,7 +39,13 @@ in
|
||||
|
||||
stdenv.mkDerivation {
|
||||
name = "tarball";
|
||||
builder = ./make-system-tarball.sh;
|
||||
__structuredAttrs = true;
|
||||
|
||||
# the tarball will be self-contained so we can drop references
|
||||
# to the closure that was used to build it
|
||||
unsafeDiscardReferences.out = true;
|
||||
|
||||
buildCommandPath = ./make-system-tarball.sh;
|
||||
nativeBuildInputs = extraInputs;
|
||||
|
||||
inherit
|
||||
@@ -49,11 +55,9 @@ stdenv.mkDerivation {
|
||||
compressCommand
|
||||
;
|
||||
|
||||
# !!! should use XML.
|
||||
sources = map (x: x.source) contents;
|
||||
targets = map (x: x.target) contents;
|
||||
|
||||
# !!! should use XML.
|
||||
inherit symlinks objects;
|
||||
|
||||
closureInfo = closureInfo {
|
||||
|
||||
@@ -1,10 +1,3 @@
|
||||
sources_=($sources)
|
||||
targets_=($targets)
|
||||
|
||||
objects=($objects)
|
||||
symlinks=($symlinks)
|
||||
|
||||
|
||||
# Remove the initial slash from a path, since genisofs likes it that way.
|
||||
stripSlash() {
|
||||
res="$1"
|
||||
@@ -12,10 +5,10 @@ stripSlash() {
|
||||
}
|
||||
|
||||
# Add the individual files.
|
||||
for ((i = 0; i < ${#targets_[@]}; i++)); do
|
||||
stripSlash "${targets_[$i]}"
|
||||
for ((i = 0; i < ${#targets[@]}; i++)); do
|
||||
stripSlash "${targets[$i]}"
|
||||
mkdir -p "$(dirname "$res")"
|
||||
cp -a "${sources_[$i]}" "$res"
|
||||
cp -a "${sources[$i]}" "$res"
|
||||
done
|
||||
|
||||
|
||||
|
||||
@@ -524,7 +524,6 @@ rec {
|
||||
# Stupid misc. symlinks.
|
||||
ln -s ${cfg.defaultUnit} $out/default.target
|
||||
ln -s ${cfg.ctrlAltDelUnit} $out/ctrl-alt-del.target
|
||||
ln -s rescue.target $out/kbrequest.target
|
||||
|
||||
ln -s ../remote-fs.target $out/multi-user.target.wants/
|
||||
''}
|
||||
|
||||
@@ -95,7 +95,7 @@ let
|
||||
minimal, "recommended" includes "required", and
|
||||
"suggested" includes "recommended".
|
||||
|
||||
See: https://systemd.io/ELF_DLOPEN_METADATA/
|
||||
See: <https://systemd.io/ELF_DLOPEN_METADATA/>
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -17,11 +17,6 @@ let
|
||||
qt6Packages.qt6gtk2
|
||||
];
|
||||
kde = [
|
||||
libsForQt5.kio
|
||||
libsForQt5.plasma-integration
|
||||
libsForQt5.systemsettings
|
||||
];
|
||||
kde6 = [
|
||||
kdePackages.kio
|
||||
kdePackages.plasma-integration
|
||||
kdePackages.systemsettings
|
||||
@@ -36,11 +31,6 @@ let
|
||||
];
|
||||
};
|
||||
|
||||
# Maps style names to their QT_QPA_PLATFORMTHEME, if necessary.
|
||||
styleNames = {
|
||||
kde6 = "kde";
|
||||
};
|
||||
|
||||
stylePackages = with pkgs; {
|
||||
bb10bright = [ libsForQt5.qtstyleplugins ];
|
||||
bb10dark = [ libsForQt5.qtstyleplugins ];
|
||||
@@ -71,8 +61,8 @@ let
|
||||
];
|
||||
|
||||
breeze = [
|
||||
libsForQt5.breeze-qt5
|
||||
kdePackages.breeze
|
||||
kdePackages.breeze.qt5
|
||||
];
|
||||
|
||||
kvantum = [
|
||||
@@ -111,10 +101,6 @@ in
|
||||
relatedPackages = [
|
||||
"qgnomeplatform"
|
||||
"qgnomeplatform-qt6"
|
||||
[
|
||||
"libsForQt5"
|
||||
"plasma-integration"
|
||||
]
|
||||
[
|
||||
"libsForQt5"
|
||||
"qt5ct"
|
||||
@@ -123,10 +109,6 @@ in
|
||||
"libsForQt5"
|
||||
"qtstyleplugins"
|
||||
]
|
||||
[
|
||||
"libsForQt5"
|
||||
"systemsettings"
|
||||
]
|
||||
[
|
||||
"kdePackages"
|
||||
"plasma-integration"
|
||||
@@ -158,8 +140,7 @@ in
|
||||
The options are
|
||||
- `gnome`: Use GNOME theme with [qgnomeplatform](https://github.com/FedoraQt/QGnomePlatform)
|
||||
- `gtk2`: Use GTK theme with [qtstyleplugins](https://github.com/qt/qtstyleplugins)
|
||||
- `kde`: Use Qt settings from Plasma 5.
|
||||
- `kde6`: Use Qt settings from Plasma 6.
|
||||
- `kde`: Use Qt settings from Plasma.
|
||||
- `lxqt`: Use LXQt style set using the [lxqt-config-appearance](https://github.com/lxqt/lxqt-config)
|
||||
application.
|
||||
- `qt5ct`: Use Qt style set using the [qt5ct](https://sourceforge.net/projects/qt5ct/)
|
||||
@@ -174,10 +155,6 @@ in
|
||||
relatedPackages = [
|
||||
"adwaita-qt"
|
||||
"adwaita-qt6"
|
||||
[
|
||||
"libsForQt5"
|
||||
"breeze-qt5"
|
||||
]
|
||||
[
|
||||
"libsForQt5"
|
||||
"qtstyleplugin-kvantum"
|
||||
@@ -236,9 +213,7 @@ in
|
||||
];
|
||||
|
||||
environment.variables = {
|
||||
QT_QPA_PLATFORMTHEME =
|
||||
lib.mkIf (cfg.platformTheme != null)
|
||||
styleNames.${cfg.platformTheme} or cfg.platformTheme;
|
||||
QT_QPA_PLATFORMTHEME = lib.mkIf (cfg.platformTheme != null) cfg.platformTheme;
|
||||
QT_STYLE_OVERRIDE = lib.mkIf (cfg.style != null) cfg.style;
|
||||
};
|
||||
|
||||
|
||||
@@ -27,7 +27,7 @@ in
|
||||
config = lib.mkOption {
|
||||
default = { };
|
||||
description = ''
|
||||
Additional config entries for the fw-fanctrl service (documentation: https://github.com/TamtamHero/fw-fanctrl/blob/main/doc/configuration.md)
|
||||
Additional config entries for the fw-fanctrl service (documentation: <https://github.com/TamtamHero/fw-fanctrl/blob/main/doc/configuration.md>)
|
||||
'';
|
||||
type = lib.types.submodule {
|
||||
freeformType = configFormat.type;
|
||||
|
||||
@@ -139,7 +139,7 @@ in
|
||||
default = defaultSettings;
|
||||
description = ''
|
||||
Configuration to be written to the libncf-nci configuration files.
|
||||
To understand the configuration format, refer to https://github.com/NXPNFCLinux/linux_libnfc-nci/tree/master/conf.
|
||||
To understand the configuration format, refer to <https://github.com/NXPNFCLinux/linux_libnfc-nci/tree/master/conf>.
|
||||
'';
|
||||
type = lib.types.attrs;
|
||||
};
|
||||
|
||||
@@ -229,7 +229,7 @@ in
|
||||
|
||||
Warning: This feature is relatively new, depending on your system this might
|
||||
work poorly. AMD support, especially so.
|
||||
See: https://forums.developer.nvidia.com/t/the-all-new-outputsink-feature-aka-reverse-prime/129828
|
||||
See: <https://forums.developer.nvidia.com/t/the-all-new-outputsink-feature-aka-reverse-prime/129828>
|
||||
|
||||
Note that this option only has any effect if the "nvidia" driver is specified
|
||||
in {option}`services.xserver.videoDrivers`, and it should preferably
|
||||
|
||||
@@ -22,13 +22,12 @@ let
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
buildInputs = [
|
||||
pkgs.gtk2
|
||||
cfg.package
|
||||
];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/etc/gtk-2.0/
|
||||
GTK_PATH=${cfg.package}/lib/gtk-2.0/ gtk-query-immodules-2.0 > $out/etc/gtk-2.0/immodules.cache
|
||||
GTK_PATH=${cfg.package}/lib/gtk-2.0/ ${pkgs.stdenv.hostPlatform.emulator pkgs.buildPackages} ${lib.getExe' pkgs.gtk2.dev "gtk-query-immodules-2.0"} > $out/etc/gtk-2.0/immodules.cache
|
||||
'';
|
||||
|
||||
gtk3_cache =
|
||||
@@ -37,13 +36,12 @@ let
|
||||
preferLocalBuild = true;
|
||||
allowSubstitutes = false;
|
||||
buildInputs = [
|
||||
pkgs.gtk3
|
||||
cfg.package
|
||||
];
|
||||
}
|
||||
''
|
||||
mkdir -p $out/etc/gtk-3.0/
|
||||
GTK_PATH=${cfg.package}/lib/gtk-3.0/ gtk-query-immodules-3.0 > $out/etc/gtk-3.0/immodules.cache
|
||||
GTK_PATH=${cfg.package}/lib/gtk-3.0/ ${pkgs.stdenv.hostPlatform.emulator pkgs.buildPackages} ${lib.getExe' pkgs.gtk3.dev "gtk-query-immodules-3.0"} > $out/etc/gtk-3.0/immodules.cache
|
||||
'';
|
||||
|
||||
in
|
||||
@@ -107,8 +105,12 @@ in
|
||||
environment.systemPackages = [
|
||||
cfg.package
|
||||
]
|
||||
++ lib.optional cfg.enableGtk2 gtk2_cache
|
||||
++ lib.optional cfg.enableGtk3 gtk3_cache;
|
||||
++ lib.optional (
|
||||
cfg.enableGtk2 && (pkgs.stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages)
|
||||
) gtk2_cache
|
||||
++ lib.optional (
|
||||
cfg.enableGtk3 && (pkgs.stdenv.hostPlatform.emulatorAvailable pkgs.buildPackages)
|
||||
) gtk3_cache;
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -7,11 +7,7 @@
|
||||
let
|
||||
imcfg = config.i18n.inputMethod;
|
||||
cfg = imcfg.fcitx5;
|
||||
fcitx5Package =
|
||||
if cfg.plasma6Support then
|
||||
pkgs.qt6Packages.fcitx5-with-addons.override { inherit (cfg) addons; }
|
||||
else
|
||||
pkgs.libsForQt5.fcitx5-with-addons.override { inherit (cfg) addons; };
|
||||
fcitx5Package = pkgs.qt6Packages.fcitx5-with-addons.override { inherit (cfg) addons; };
|
||||
settingsFormat = pkgs.formats.ini { };
|
||||
in
|
||||
{
|
||||
@@ -33,15 +29,6 @@ in
|
||||
See [Using Fcitx 5 on Wayland](https://fcitx-im.org/wiki/Using_Fcitx_5_on_Wayland).
|
||||
'';
|
||||
};
|
||||
plasma6Support = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = config.services.desktopManager.plasma6.enable;
|
||||
defaultText = lib.literalExpression "config.services.desktopManager.plasma6.enable";
|
||||
description = ''
|
||||
Use qt6 versions of fcitx5 packages.
|
||||
Required for configuring fcitx5 in KDE System Settings.
|
||||
'';
|
||||
};
|
||||
quickPhrase = lib.mkOption {
|
||||
type = with lib.types; attrsOf str;
|
||||
default = { };
|
||||
@@ -109,6 +96,9 @@ in
|
||||
(lib.mkRemovedOptionModule [ "i18n" "inputMethod" "fcitx5" "enableRimeData" ] ''
|
||||
RIME data is now included in `fcitx5-rime` by default, and can be customized using `fcitx5-rime.override { rimeDataPkgs = ...; }`
|
||||
'')
|
||||
(lib.mkRemovedOptionModule [ "i18n" "inputMethod" "fcitx5" "plasma6Support" ] ''
|
||||
qt6 is the only one used for fcitx5-configtool now.
|
||||
'')
|
||||
];
|
||||
|
||||
config = lib.mkIf (imcfg.enable && imcfg.type == "fcitx5") {
|
||||
|
||||
@@ -53,7 +53,7 @@ in
|
||||
panel = lib.mkOption {
|
||||
type = with lib.types; nullOr path;
|
||||
default = null;
|
||||
example = lib.literalExpression ''"''${pkgs.plasma5Packages.plasma-desktop}/libexec/kimpanel-ibus-panel"'';
|
||||
example = lib.literalExpression ''"''${pkgs.kdePackages.plasma-desktop}/libexec/kimpanel-ibus-panel"'';
|
||||
description = "Replace the IBus panel with another panel.";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
# This module defines a NixOS installation CD that contains X11 and
|
||||
# Plasma 5.
|
||||
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./installation-cd-graphical-calamares.nix ];
|
||||
|
||||
isoImage.edition = lib.mkDefault "plasma5";
|
||||
|
||||
services.xserver.desktopManager.plasma5 = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Automatically login as nixos.
|
||||
services.displayManager = {
|
||||
sddm.enable = true;
|
||||
autoLogin = {
|
||||
enable = true;
|
||||
user = "nixos";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Graphical text editor
|
||||
plasma5Packages.kate
|
||||
];
|
||||
|
||||
system.activationScripts.installerDesktop =
|
||||
let
|
||||
|
||||
# Comes from documentation.nix when xserver and nixos.enable are true.
|
||||
manualDesktopFile = "/run/current-system/sw/share/applications/nixos-manual.desktop";
|
||||
|
||||
homeDir = "/home/nixos/";
|
||||
desktopDir = homeDir + "Desktop/";
|
||||
|
||||
in
|
||||
''
|
||||
mkdir -p ${desktopDir}
|
||||
chown nixos ${homeDir} ${desktopDir}
|
||||
|
||||
ln -sfT ${manualDesktopFile} ${desktopDir + "nixos-manual.desktop"}
|
||||
ln -sfT ${pkgs.gparted}/share/applications/gparted.desktop ${desktopDir + "gparted.desktop"}
|
||||
ln -sfT ${pkgs.plasma5Packages.konsole}/share/applications/org.kde.konsole.desktop ${
|
||||
desktopDir + "org.kde.konsole.desktop"
|
||||
}
|
||||
ln -sfT ${pkgs.calamares-nixos}/share/applications/calamares.desktop ${
|
||||
desktopDir + "calamares.desktop"
|
||||
}
|
||||
'';
|
||||
|
||||
}
|
||||
@@ -1,7 +0,0 @@
|
||||
{ pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./installation-cd-graphical-plasma5.nix ];
|
||||
|
||||
boot.kernelPackages = pkgs.linuxPackages_latest;
|
||||
}
|
||||
@@ -1,50 +0,0 @@
|
||||
# This module defines a NixOS installation CD that contains X11 and
|
||||
# Plasma 5.
|
||||
|
||||
{ lib, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports = [ ./installation-cd-graphical-base.nix ];
|
||||
|
||||
isoImage.edition = lib.mkDefault "plasma5";
|
||||
|
||||
services.xserver.desktopManager.plasma5 = {
|
||||
enable = true;
|
||||
};
|
||||
|
||||
# Automatically login as nixos.
|
||||
services.displayManager = {
|
||||
sddm.enable = true;
|
||||
autoLogin = {
|
||||
enable = true;
|
||||
user = "nixos";
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# Graphical text editor
|
||||
plasma5Packages.kate
|
||||
];
|
||||
|
||||
system.activationScripts.installerDesktop =
|
||||
let
|
||||
|
||||
# Comes from documentation.nix when xserver and nixos.enable are true.
|
||||
manualDesktopFile = "/run/current-system/sw/share/applications/nixos-manual.desktop";
|
||||
|
||||
homeDir = "/home/nixos/";
|
||||
desktopDir = homeDir + "Desktop/";
|
||||
|
||||
in
|
||||
''
|
||||
mkdir -p ${desktopDir}
|
||||
chown nixos ${homeDir} ${desktopDir}
|
||||
|
||||
ln -sfT ${manualDesktopFile} ${desktopDir + "nixos-manual.desktop"}
|
||||
ln -sfT ${pkgs.gparted}/share/applications/gparted.desktop ${desktopDir + "gparted.desktop"}
|
||||
ln -sfT ${pkgs.plasma5Packages.konsole}/share/applications/org.kde.konsole.desktop ${
|
||||
desktopDir + "org.kde.konsole.desktop"
|
||||
}
|
||||
'';
|
||||
|
||||
}
|
||||
@@ -116,18 +116,34 @@ let
|
||||
&& (t == "directory" -> baseNameOf n != "tests")
|
||||
&& (t == "file" -> hasSuffix ".nix" n)
|
||||
);
|
||||
prefixRegex = "^" + lib.strings.escapeRegex (toString pkgs.path) + "($|/(modules|nixos)($|/.*))";
|
||||
filteredModules = builtins.path {
|
||||
name = "source";
|
||||
inherit (pkgs) path;
|
||||
filter =
|
||||
n: t:
|
||||
builtins.match prefixRegex n != null
|
||||
&& cleanSourceFilter n t
|
||||
&& (t == "directory" -> baseNameOf n != "tests")
|
||||
&& (t == "file" -> hasSuffix ".nix" n);
|
||||
};
|
||||
in
|
||||
pkgs.runCommand "lazy-options.json"
|
||||
{
|
||||
rec {
|
||||
libPath = filter (pkgs.path + "/lib");
|
||||
pkgsLibPath = filter (pkgs.path + "/pkgs/pkgs-lib");
|
||||
nixosPath = filter (pkgs.path + "/nixos");
|
||||
nixosPath = filteredModules + "/nixos";
|
||||
NIX_ABORT_ON_WARN = warningsAreErrors;
|
||||
modules =
|
||||
"[ "
|
||||
+ concatMapStringsSep " " (p: ''"${removePrefix "${modulesPath}/" (toString p)}"'') docModules.lazy
|
||||
+ " ]";
|
||||
passAsFile = [ "modules" ];
|
||||
disallowedReferences = [
|
||||
filteredModules
|
||||
libPath
|
||||
pkgsLibPath
|
||||
];
|
||||
}
|
||||
''
|
||||
export NIX_STORE_DIR=$TMPDIR/store
|
||||
|
||||
@@ -246,7 +246,7 @@ in
|
||||
subsonic = 204;
|
||||
# riak = 205; # unused, remove 2022-07-22
|
||||
#shout = 206; # dynamically allocated as of 2021-09-18, module removed 2024-10-19
|
||||
gateone = 207;
|
||||
#gateone = 207; # removed 2025-08-21
|
||||
namecoin = 208;
|
||||
#lxd = 210; # unused
|
||||
#kibana = 211;# dynamically allocated as of 2021-09-03
|
||||
@@ -582,7 +582,7 @@ in
|
||||
subsonic = 204;
|
||||
# riak = 205;#unused, removed 2022-06-22
|
||||
#shout = 206; #unused
|
||||
gateone = 207;
|
||||
#gateone = 207; #removed 2025-08-21
|
||||
namecoin = 208;
|
||||
#lxd = 210; # unused
|
||||
#kibana = 211;
|
||||
|
||||
@@ -1,39 +1,5 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
maintainer = lib.mkOptionType {
|
||||
name = "maintainer";
|
||||
check = email: lib.elem email (lib.attrValues lib.maintainers);
|
||||
merge =
|
||||
loc: defs:
|
||||
lib.listToAttrs (lib.singleton (lib.nameValuePair (lib.last defs).file (lib.last defs).value));
|
||||
};
|
||||
|
||||
listOfMaintainers = lib.types.listOf maintainer // {
|
||||
# Returns list of
|
||||
# { "module-file" = [
|
||||
# "maintainer1 <first@nixos.org>"
|
||||
# "maintainer2 <second@nixos.org>" ];
|
||||
# }
|
||||
merge =
|
||||
loc: defs:
|
||||
lib.zipAttrs (
|
||||
lib.flatten (
|
||||
lib.imap1 (
|
||||
n: def:
|
||||
lib.imap1 (
|
||||
m: def':
|
||||
maintainer.merge (loc ++ [ "[${toString n}-${toString m}]" ]) [
|
||||
{
|
||||
inherit (def) file;
|
||||
value = def';
|
||||
}
|
||||
]
|
||||
) def.value
|
||||
) defs
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
docFile = lib.types.path // {
|
||||
# Returns tuples of
|
||||
# { file = "module location"; value = <path/to/doc.xml>; }
|
||||
@@ -42,20 +8,11 @@ let
|
||||
in
|
||||
|
||||
{
|
||||
imports = [ ../../../modules/generic/meta-maintainers.nix ];
|
||||
|
||||
options = {
|
||||
meta = {
|
||||
|
||||
maintainers = lib.mkOption {
|
||||
type = listOfMaintainers;
|
||||
internal = true;
|
||||
default = [ ];
|
||||
example = lib.literalExpression ''[ lib.maintainers.all ]'';
|
||||
description = ''
|
||||
List of maintainers of each module. This option should be defined at
|
||||
most once per module.
|
||||
'';
|
||||
};
|
||||
|
||||
doc = lib.mkOption {
|
||||
type = docFile;
|
||||
internal = true;
|
||||
@@ -84,5 +41,8 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
meta.maintainers = lib.singleton lib.maintainers.pierron;
|
||||
meta.maintainers = with lib.maintainers; [
|
||||
pierron
|
||||
roberth
|
||||
];
|
||||
}
|
||||
|
||||
@@ -484,6 +484,7 @@
|
||||
./services/cluster/patroni/default.nix
|
||||
./services/cluster/rke2/default.nix
|
||||
./services/cluster/spark/default.nix
|
||||
./services/cluster/temporal/default.nix
|
||||
./services/computing/boinc/client.nix
|
||||
./services/computing/foldingathome/client.nix
|
||||
./services/computing/slurm/slurm.nix
|
||||
@@ -543,10 +544,6 @@
|
||||
./services/desktops/blueman.nix
|
||||
./services/desktops/bonsaid.nix
|
||||
./services/desktops/cpupower-gui.nix
|
||||
./services/desktops/deepin/app-services.nix
|
||||
./services/desktops/deepin/dde-api.nix
|
||||
./services/desktops/deepin/dde-daemon.nix
|
||||
./services/desktops/deepin/deepin-anything.nix
|
||||
./services/desktops/dleyna.nix
|
||||
./services/desktops/espanso.nix
|
||||
./services/desktops/flatpak.nix
|
||||
@@ -1099,6 +1096,7 @@
|
||||
./services/networking/bitlbee.nix
|
||||
./services/networking/blockbook-frontend.nix
|
||||
./services/networking/blocky.nix
|
||||
./services/networking/byedpi.nix
|
||||
./services/networking/cato-client.nix
|
||||
./services/networking/centrifugo.nix
|
||||
./services/networking/cgit.nix
|
||||
@@ -1159,7 +1157,6 @@
|
||||
./services/networking/frp.nix
|
||||
./services/networking/frr.nix
|
||||
./services/networking/g3proxy.nix
|
||||
./services/networking/gateone.nix
|
||||
./services/networking/gdomap.nix
|
||||
./services/networking/ghostunnel.nix
|
||||
./services/networking/git-daemon.nix
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# This module defines a NixOS configuration with the Plasma 5 desktop.
|
||||
# This module defines a NixOS configuration with the Plasma 6 desktop.
|
||||
# It's used by the graphical installation CD.
|
||||
|
||||
{ pkgs, ... }:
|
||||
@@ -6,7 +6,7 @@
|
||||
{
|
||||
services.xserver = {
|
||||
enable = true;
|
||||
desktopManager.plasma5.enable = true;
|
||||
desktopManager.plasma6.enable = true;
|
||||
};
|
||||
|
||||
services = {
|
||||
|
||||
@@ -34,7 +34,7 @@ in
|
||||
];
|
||||
};
|
||||
|
||||
boot.kernelPackages = mkDefault pkgs.linuxPackages_hardened;
|
||||
boot.kernelPackages = mkDefault pkgs.linuxKernel.packages.linux_hardened;
|
||||
|
||||
nix.settings.allowed-users = mkDefault [ "@users" ];
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user