···11+[run]
22+indent_style = space
33+indent_size = 2
+13
ci/github-script/README.md
···11+# GitHub specific CI scripts
22+33+This folder contains [`actions/github-script`](https://github.com/actions/github-script)-based JavaScript code.
44+It provides a `nix-shell` environment to run and test these actions locally.
55+66+To run any of the scripts locally:
77+88+- Enter `nix-shell` in `./ci/github-script`.
99+- Ensure `gh` is authenticated.
1010+1111+## Labeler
1212+1313+Run `./run labels OWNER REPO`, where OWNER is your username or "NixOS" and REPO the name of your fork or "nixpkgs".
···11+module.exports = async function ({ github, core }, callback) {
22+ const Bottleneck = require('bottleneck')
33+44+ const stats = {
55+ issues: 0,
66+ prs: 0,
77+ requests: 0,
88+ artifacts: 0,
99+ }
1010+1111+ // Rate-Limiting and Throttling, see for details:
1212+ // https://github.com/octokit/octokit.js/issues/1069#throttling
1313+ // https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api
1414+ const allLimits = new Bottleneck({
1515+ // Avoid concurrent requests
1616+ maxConcurrent: 1,
1717+ // Will be updated with first `updateReservoir()` call below.
1818+ reservoir: 0,
1919+ })
2020+ // Pause between mutative requests
2121+ const writeLimits = new Bottleneck({ minTime: 1000 }).chain(allLimits)
2222+ github.hook.wrap('request', async (request, options) => {
2323+ // Requests to the /rate_limit endpoint do not count against the rate limit.
2424+ if (options.url == '/rate_limit') return request(options)
2525+ // Search requests are in a different resource group, which allows 30 requests / minute.
2626+ // We do less than a handful each run, so not implementing throttling for now.
2727+ if (options.url.startsWith('/search/')) return request(options)
2828+ stats.requests++
2929+ if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(options.method))
3030+ return writeLimits.schedule(request.bind(null, options))
3131+ else return allLimits.schedule(request.bind(null, options))
3232+ })
3333+3434+ async function updateReservoir() {
3535+ let response
3636+ try {
3737+ response = await github.rest.rateLimit.get()
3838+ } catch (err) {
3939+ core.error(`Failed updating reservoir:\n${err}`)
4040+ // Keep retrying on failed rate limit requests instead of exiting the script early.
4141+ return
4242+ }
4343+ // Always keep 1000 spare requests for other jobs to do their regular duty.
4444+ // They normally use below 100, so 1000 is *plenty* of room to work with.
4545+ const reservoir = Math.max(0, response.data.resources.core.remaining - 1000)
4646+ core.info(`Updating reservoir to: ${reservoir}`)
4747+ allLimits.updateSettings({ reservoir })
4848+ }
4949+ await updateReservoir()
5050+ // Update remaining requests every minute to account for other jobs running in parallel.
5151+ const reservoirUpdater = setInterval(updateReservoir, 60 * 1000)
5252+5353+ try {
5454+ await callback(stats)
5555+ } finally {
5656+ clearInterval(reservoirUpdater)
5757+ core.notice(
5858+ `Processed ${stats.prs} PRs, ${stats.issues} Issues, made ${stats.requests + stats.artifacts} API requests and downloaded ${stats.artifacts} artifacts.`,
5959+ )
6060+ }
6161+}
-4
ci/labels/.editorconfig
···11-# TODO: Move to <top-level>/.editorconfig, once ci/.editorconfig has made its way through staging.
22-[*.cjs]
33-indent_style = space
44-indent_size = 2
ci/labels/.gitignore
ci/github-script/.gitignore
ci/labels/.npmrc
ci/github-script/.npmrc
-4
ci/labels/README.md
···11-To test the labeler locally:
22-- Provide `gh` on `PATH` and make sure it's authenticated.
33-- Enter `nix-shell` in `./ci/labels`.
44-- Run `./run.js OWNER REPO`, where OWNER is your username or "NixOS" and REPO the name of your fork or "nixpkgs".
+8-63
ci/labels/labels.cjs
ci/github-script/labels.js
···11module.exports = async function ({ github, context, core, dry }) {
22- const Bottleneck = require('bottleneck')
32 const path = require('node:path')
43 const { DefaultArtifactClient } = require('@actions/artifact')
54 const { readFile, writeFile } = require('node:fs/promises')
55+ const withRateLimit = require('./withRateLimit.js')
6677 const artifactClient = new DefaultArtifactClient()
8899- const stats = {
1010- issues: 0,
1111- prs: 0,
1212- requests: 0,
1313- artifacts: 0,
1414- }
1515-1616- // Rate-Limiting and Throttling, see for details:
1717- // https://github.com/octokit/octokit.js/issues/1069#throttling
1818- // https://docs.github.com/en/rest/using-the-rest-api/best-practices-for-using-the-rest-api
1919- const allLimits = new Bottleneck({
2020- // Avoid concurrent requests
2121- maxConcurrent: 1,
2222- // Will be updated with first `updateReservoir()` call below.
2323- reservoir: 0,
2424- })
2525- // Pause between mutative requests
2626- const writeLimits = new Bottleneck({ minTime: 1000 }).chain(allLimits)
2727- github.hook.wrap('request', async (request, options) => {
2828- // Requests to the /rate_limit endpoint do not count against the rate limit.
2929- if (options.url == '/rate_limit') return request(options)
3030- // Search requests are in a different resource group, which allows 30 requests / minute.
3131- // We do less than a handful each run, so not implementing throttling for now.
3232- if (options.url.startsWith('/search/')) return request(options)
3333- stats.requests++
3434- if (['POST', 'PUT', 'PATCH', 'DELETE'].includes(options.method))
3535- return writeLimits.schedule(request.bind(null, options))
3636- else return allLimits.schedule(request.bind(null, options))
3737- })
3838-3939- async function updateReservoir() {
4040- let response
4141- try {
4242- response = await github.rest.rateLimit.get()
4343- } catch (err) {
4444- core.error(`Failed updating reservoir:\n${err}`)
4545- // Keep retrying on failed rate limit requests instead of exiting the script early.
4646- return
4747- }
4848- // Always keep 1000 spare requests for other jobs to do their regular duty.
4949- // They normally use below 100, so 1000 is *plenty* of room to work with.
5050- const reservoir = Math.max(0, response.data.resources.core.remaining - 1000)
5151- core.info(`Updating reservoir to: ${reservoir}`)
5252- allLimits.updateSettings({ reservoir })
5353- }
5454- await updateReservoir()
5555- // Update remaining requests every minute to account for other jobs running in parallel.
5656- const reservoirUpdater = setInterval(updateReservoir, 60 * 1000)
5757-5858- async function handlePullRequest(item) {
99+ async function handlePullRequest({ item, stats }) {
5910 const log = (k, v) => core.info(`PR #${item.number} - ${k}: ${v}`)
60116112 const pull_number = item.number
···221172 return prLabels
222173 }
223174224224- async function handle(item) {
175175+ async function handle({ item, stats }) {
225176 try {
226177 const log = (k, v, skip) => {
227178 core.info(`#${item.number} - ${k}: ${v}` + (skip ? ' (skipped)' : ''))
···237188238189 if (item.pull_request || context.payload.pull_request) {
239190 stats.prs++
240240- Object.assign(itemLabels, await handlePullRequest(item))
191191+ Object.assign(itemLabels, await handlePullRequest({ item, stats }))
241192 } else {
242193 stats.issues++
243194 }
···326277 }
327278 }
328279329329- try {
280280+ await withRateLimit({ github, core }, async (stats) => {
330281 if (context.payload.pull_request) {
331331- await handle(context.payload.pull_request)
282282+ await handle({ item: context.payload.pull_request, stats })
332283 } else {
333284 const lastRun = (
334285 await github.rest.actions.listWorkflowRuns({
···447398 arr.findIndex((firstItem) => firstItem.number == thisItem.number),
448399 )
449400450450- ;(await Promise.allSettled(items.map(handle)))
401401+ ;(await Promise.allSettled(items.map((item) => handle({ item, stats }))))
451402 .filter(({ status }) => status == 'rejected')
452403 .map(({ reason }) =>
453404 core.setFailed(`${reason.message}\n${reason.cause.stack}`),
454405 )
455455-456456- core.notice(
457457- `Processed ${stats.prs} PRs, ${stats.issues} Issues, made ${stats.requests + stats.artifacts} API requests and downloaded ${stats.artifacts} artifacts.`,
458458- )
459406 }
460460- } finally {
461461- clearInterval(reservoirUpdater)
462462- }
407407+ })
463408}
···443443444444 pnpmDeps = pnpm.fetchDeps {
445445 inherit (finalAttrs) pname version src;
446446- hash = "...";
447446 fetcherVersion = 2;
447447+ hash = "...";
448448 };
449449})
450450```
···568568 # ...
569569 pnpmDeps = pnpm.fetchDeps {
570570 # ...
571571- hash = "..."; # you can use your already set hash here
572571 fetcherVersion = 1;
572572+ hash = "..."; # you can use your already set hash here
573573 };
574574}
575575```
···581581 # ...
582582 pnpmDeps = pnpm.fetchDeps {
583583 # ...
584584- hash = "..."; # clear this hash and generate a new one
585584 fetcherVersion = 2;
585585+ hash = "..."; # clear this hash and generate a new one
586586 };
587587}
588588```
+2
nixos/doc/manual/release-notes/rl-2511.section.md
···131131- [](#opt-services.gnome.gnome-keyring.enable) does not ship with an SSH agent anymore, as this is now handled by the `gcr_4` package instead of `gnome-keyring`. A new module has been added to support this, under [](#opt-services.gnome.gcr-ssh-agent.enable) (its default value has been set to [](#opt-services.gnome.gnome-keyring.enable) to ensure a smooth transition). See the [relevant upstream PR](https://gitlab.gnome.org/GNOME/gcr/-/merge_requests/67) for more details.
132132133133- The `nettools` package (ifconfig, arp, mii-tool, netstat, route) is not installed by default anymore. The suite is unmaintained and users should migrate to `iproute2` and `ethtool` instead.
134134+135135+- `sparkleshare` has been removed as it no longer builds and has been abandoned upstream.
+33
nixos/modules/hardware/kryoflux.nix
···11+{
22+ config,
33+ lib,
44+ pkgs,
55+ ...
66+}:
77+88+let
99+ cfg = config.programs.kryoflux;
1010+1111+in
1212+{
1313+ options.programs.kryoflux = {
1414+ enable = lib.mkOption {
1515+ type = lib.types.bool;
1616+ default = false;
1717+ description = ''
1818+ Enables kryoflux udev rules, ensures 'floppy' group exists. This is a
1919+ prerequisite to using devices supported by kryoflux without being root,
2020+ since kryoflux device descriptors will be owned by floppy through udev.
2121+ '';
2222+ };
2323+ package = lib.mkPackageOption pkgs "kryoflux" { };
2424+ };
2525+2626+ config = lib.mkIf cfg.enable {
2727+ services.udev.packages = [ cfg.package ];
2828+ environment.systemPackages = [ cfg.package ];
2929+ users.groups.floppy = { };
3030+ };
3131+3232+ meta.maintainers = with lib.maintainers; [ matthewcroughan ];
3333+}
···11diff --git a/scripts/msmtpq/msmtpq b/scripts/msmtpq/msmtpq
22-index bcb384e..dbaf1b5 100755
22+index 28d0754..3eaac58 100755
33--- a/scripts/msmtpq/msmtpq
44+++ b/scripts/msmtpq/msmtpq
55-@@ -92,6 +92,8 @@ if [ ! -v MSMTPQ_LOG ] ; then
66- fi
55+@@ -182,6 +182,8 @@ if [ -n "$MSMTPQ_LOG" ] ; then
66+ unset msmptq_log_dir
77 fi
88- [ -d "$(dirname "$MSMTPQ_LOG")" ] || mkdir -p "$(dirname "$MSMTPQ_LOG")"
99-+
88+109+JOURNAL=@journal@
1111- ## ======================================================================================
1010++
1111+ umask 077 # set secure permissions on created directories and files
12121313- ## msmtpq can use the following environment variables :
1414-@@ -144,6 +146,7 @@ on_exit() { # unlock the queue on exit if the lock was
1313+ declare -i CNT # a count of mail(s) currently in the queue
1414+@@ -214,6 +216,7 @@ on_exit() { # unlock the queue on exit if the lock was
1515 ## display msg to user, as well
1616 ##
1717 log() {
···1919 local ARG RC PFX
2020 PFX="$('date' +'%Y %d %b %H:%M:%S')"
2121 # time stamp prefix - "2008 13 Mar 03:59:45 "
2222-@@ -161,10 +164,19 @@ log() {
2222+@@ -233,10 +236,19 @@ log() {
2323 done
2424 fi
2525
···65656666rustPlatform.buildRustPackage {
6767 pname = "servo";
6868- version = "0-unstable-2025-07-08";
6868+ version = "0-unstable-2025-07-13";
69697070 src = fetchFromGitHub {
7171 owner = "servo";
7272 repo = "servo";
7373- rev = "c3f441d7abe7243a31150bf424babf0f1679ea88";
7474- hash = "sha256-rFROwsU/x8LsD8vpCcmLyQMYCl9AQwgbv/kHk7JTa4c=";
7373+ rev = "93e5b672a78247205c431d5741952bdf23c3fcc2";
7474+ hash = "sha256-0826hNZ45BXXNzdZKbyUW/CfwVRZmpYU1e6efaACh4o=";
7575 # Breaks reproducibility depending on whether the picked commit
7676 # has other ref-names or not, which may change over time, i.e. with
7777 # "ref-names: HEAD -> main" as long this commit is the branch HEAD
···8282 };
83838484 useFetchCargoVendor = true;
8585- cargoHash = "sha256-2J6ByE2kmoHBGWgwYU2FWgTt47cw+s8IPcm4ElRVWMc=";
8585+ cargoHash = "sha256-uB5eTGiSq+DV7VwYoyLR2HH3DQpSV4xnP7C7iXZa7S0=";
86868787 # set `HOME` to a temp dir for write access
8888 # Fix invalid option errors during linking (https://github.com/mozilla/nixpkgs-mozilla/commit/c72ff151a3e25f14182569679ed4cd22ef352328)