Merge remote-tracking branch 'origin/master' into staging-nixos
This commit is contained in:
@@ -150,6 +150,8 @@
|
||||
|
||||
- `python3Packages.gradio` has been updated to version 6. See upstream's migration guide at https://www.gradio.app/main/guides/gradio-6-migration-guide.
|
||||
|
||||
- `python3Packages.pikepdf` no longer builds with mupdf support by default, which may be nice in Jupyter and iPython. Build with `withMupdf = true` if this is required.
|
||||
|
||||
- `vicinae` has been updated to v0.20. This includes, among several other breaking changes, a complete overhaul of the configuration system. For update instructions, see the [upstream configuration documentation](https://docs.vicinae.com/config#migration-from-v0-16-x-to-v0-17-x).
|
||||
|
||||
- The `man-pages` package's outputs have been split. The manual pages are installed into the `man` output, which is installed by default. Binaries (including `diffman-git`, `mansect`, `pdfman`, and `sortman`) are installed into the `out` output, which is not installed by default.
|
||||
@@ -229,6 +231,8 @@
|
||||
If your SQLite database is corrupted, the migration might fail and require [manual intervention](https://github.com/louislam/uptime-kuma/issues/5281).
|
||||
See the [migration guide](https://github.com/louislam/uptime-kuma/wiki/Migration-From-v1-To-v2) for more information.
|
||||
|
||||
- The `libcxxhardeningextensive` hardening flag has been **disabled** by default. Enabling it by default in 25.11 was unintentional and may have had a negative effect on performance in some cases. `libcxxhardeningfast` remains enabled by default.
|
||||
|
||||
- Switch inhibitors were introduced, which add a pre-switch check that compares a list of strings between the previous and the new generation, and refuses to switch into the new generation when there is a difference between the two lists. This allows to avoid switching into a system when for instance the systemd version changed by adding `config.systemd.package.version` to the switch inhibitors for your system. You can still forcefully switch into any generation by setting `NIXOS_NO_CHECK=1`.
|
||||
|
||||
- GNU Taler has been updated to version 1.3.
|
||||
@@ -239,7 +243,7 @@
|
||||
|
||||
- `fetchPnpmDeps` and `pnpmConfigHook` were added as top-level attributes, replacing the now deprecated `pnpm.fetchDeps` and `pnpm.configHook` attributes.
|
||||
|
||||
- `buildNpmPackage` now supports `npmDepsCacheVersion`. Set to `2` to enable packument caching, which fixes builds for projects using npm workspaces.
|
||||
- `buildNpmPackage` now supports `npmDepsFetcherVersion` (and `fetchNpmDeps` now supports `fetcherVersion`). Set to `2` to enable packument caching, which fixes builds for projects using npm workspaces.
|
||||
|
||||
- Added `dell-bios-fan-control` package and service.
|
||||
|
||||
|
||||
@@ -1631,13 +1631,11 @@ Adds the `-fzero-call-used-regs=used-gpr` compiler option. This causes the gener
|
||||
|
||||
This flag adds the `-fstack-clash-protection` compiler option, which causes growth of a program's stack to access each successive page in order. This should force the guard page to be accessed and cause an attempt to "jump over" this guard page to crash.
|
||||
|
||||
### Hardening flags disabled by default {#sec-hardening-flags-disabled-by-default}
|
||||
#### `libcxxhardeningfast` {#libcxxhardeningfast}
|
||||
|
||||
The following flags are disabled by default and should be enabled with `hardeningEnable` for packages that take untrusted input like network services.
|
||||
Adds the `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST` compiler flag. This flag only has an effect on libc++ targets, and when defined, enables a set of assertions that prevent undefined behavior caused by violating preconditions of the standard library. libc++ provides several hardening modes, and this "fast" mode contains a set of security-critical checks that can be done with relatively little overhead in constant time.
|
||||
|
||||
#### `nostrictaliasing` {#nostrictaliasing}
|
||||
|
||||
This flag adds the `-fno-strict-aliasing` compiler option, which prevents the compiler from assuming code has been written strictly following the standard in regards to pointer aliasing and therefore performing optimizations that may be unsafe for code that has not followed these rules.
|
||||
Disabling `libcxxhardeningfast` implies disablement of checks from `libcxxhardeningextensive`.
|
||||
|
||||
#### `strictflexarrays1` {#strictflexarrays1}
|
||||
|
||||
@@ -1647,6 +1645,14 @@ Enabling this flag on packages that still use length declarations of flexible ar
|
||||
|
||||
Disabling `strictflexarrays1` implies disablement of `strictflexarrays3`.
|
||||
|
||||
### Hardening flags disabled by default {#sec-hardening-flags-disabled-by-default}
|
||||
|
||||
The following flags are disabled by default and should be enabled with `hardeningEnable` for packages that take untrusted input like network services.
|
||||
|
||||
#### `nostrictaliasing` {#nostrictaliasing}
|
||||
|
||||
This flag adds the `-fno-strict-aliasing` compiler option, which prevents the compiler from assuming code has been written strictly following the standard in regards to pointer aliasing and therefore performing optimizations that may be unsafe for code that has not followed these rules.
|
||||
|
||||
#### `strictflexarrays3` {#strictflexarrays3}
|
||||
|
||||
This flag adds the `-fstrict-flex-arrays=3` compiler option, which reduces the cases the compiler treats as "flexible arrays" to only those declared with length as (the correct) `[]`. This increases the coverage of fortify checks, because such arrays declared as the trailing element of a structure can normally not have their intended length determined by the compiler.
|
||||
@@ -1683,12 +1689,6 @@ Adds the `-D_GLIBCXX_ASSERTIONS` compiler flag. This flag only has an effect on
|
||||
|
||||
These checks may have an impact on performance in some cases.
|
||||
|
||||
#### `libcxxhardeningfast` {#libcxxhardeningfast}
|
||||
|
||||
Adds the `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_FAST` compiler flag. This flag only has an effect on libc++ targets, and when defined, enables a set of assertions that prevent undefined behavior caused by violating preconditions of the standard library. libc++ provides several hardening modes, and this "fast" mode contains a set of security-critical checks that can be done with relatively little overhead in constant time.
|
||||
|
||||
Disabling `libcxxhardeningfast` implies disablement of checks from `libcxxhardeningextensive`.
|
||||
|
||||
#### `libcxxhardeningextensive` {#libcxxhardeningextensive}
|
||||
|
||||
Adds the `-D_LIBCPP_HARDENING_MODE=_LIBCPP_HARDENING_MODE_EXTENSIVE` compiler flag. This flag only has an effect on libc++ targets, and when defined, enables a set of assertions that prevent undefined behavior caused by violating preconditions of the standard library. libc++ provides several hardening modes, and this "extensive" mode adds checks for undefined behavior that incur relatively little overhead but aren’t security-critical. The additional rigour impacts performance more than fast mode: benchmarking is recommended to determine if it is acceptable for a particular application.
|
||||
|
||||
@@ -13697,6 +13697,13 @@
|
||||
github = "karaolidis";
|
||||
githubId = 46189100;
|
||||
};
|
||||
karlbeecken = {
|
||||
name = "Karl Beecken";
|
||||
email = "karl@beecken.berlin";
|
||||
github = "karlbeecken";
|
||||
githubId = 32744028;
|
||||
keys = [ { fingerprint = "7577 13A4 9609 0C2F 51C4 018C B5C8 89A2 F195 28F6"; } ];
|
||||
};
|
||||
KarlJoad = {
|
||||
email = "karl@hallsby.com";
|
||||
github = "KarlJoad";
|
||||
|
||||
@@ -10,6 +10,17 @@ $ ./result/bin/nixos-test-driver
|
||||
>>>
|
||||
```
|
||||
|
||||
::: {.note}
|
||||
Tests using `systemd-nspawn` container machines require root privileges to run interactively,
|
||||
since the driver calls `systemd-nspawn` directly to start the containers:
|
||||
|
||||
```
|
||||
$ sudo ./result/bin/nixos-test-driver
|
||||
[...]
|
||||
>>>
|
||||
```
|
||||
:::
|
||||
|
||||
::: {.note}
|
||||
By executing the test driver in this way,
|
||||
the VMs executed may gain network & Internet access via their backdoor control interface,
|
||||
@@ -30,7 +41,7 @@ back into the test driver command line upon its completion. This allows
|
||||
you to inspect the state of the VMs after the test (e.g. to debug the
|
||||
test script).
|
||||
|
||||
## Shell access in interactive mode {#sec-nixos-test-shell-access}
|
||||
## Shell access to VMs in interactive mode {#sec-nixos-test-shell-access}
|
||||
|
||||
The function `<yourmachine>.shell_interact()` grants access to a shell running
|
||||
inside a virtual machine. To use it, replace `<yourmachine>` with the name of a
|
||||
@@ -63,7 +74,7 @@ using:
|
||||
Once the connection is established, you can enter commands in the socat terminal
|
||||
where socat is running.
|
||||
|
||||
## SSH Access for test machines {#sec-nixos-test-ssh-access}
|
||||
## SSH Access for test VMs {#sec-nixos-test-ssh-access}
|
||||
|
||||
An SSH-based backdoor to log into machines can be enabled with
|
||||
|
||||
@@ -149,10 +160,10 @@ must be configured to allow these connections.
|
||||
## Reuse VM state {#sec-nixos-test-reuse-vm-state}
|
||||
|
||||
You can re-use the VM states coming from a previous run by setting the
|
||||
`--keep-vm-state` flag.
|
||||
`--keep-machine-state` flag.
|
||||
|
||||
```ShellSession
|
||||
$ ./result/bin/nixos-test-driver --keep-vm-state
|
||||
$ ./result/bin/nixos-test-driver --keep-machine-state
|
||||
```
|
||||
|
||||
The machine state is stored in the `$TMPDIR/vm-state-machinename`
|
||||
|
||||
@@ -21,10 +21,44 @@ $ nix-store --read-log result
|
||||
|
||||
## System Requirements {#sec-running-nixos-tests-requirements}
|
||||
|
||||
NixOS tests require virtualization support.
|
||||
NixOS tests using QEMU virtual machine [`nodes`](#test-opt-nodes) require virtualization support.
|
||||
This means that the machine must have `kvm` in its [system features](https://nixos.org/manual/nix/stable/command-ref/conf-file.html?highlight=system-features#conf-system-features) list, or `apple-virt` in case of macOS.
|
||||
These features are autodetected locally, but `apple-virt` is only autodetected since Nix 2.19.0.
|
||||
|
||||
Features of **remote builders** must additionally be configured manually on the client, e.g. on NixOS with [`nix.buildMachines.*.supportedFeatures`](https://search.nixos.org/options?show=nix.buildMachines.*.supportedFeatures&sort=alpha_asc&query=nix.buildMachines) or through general [Nix configuration](https://nixos.org/manual/nix/stable/advanced-topics/distributed-builds).
|
||||
|
||||
If you run the tests on a **macOS** machine, you also need a "remote" builder for Linux; possibly a VM. [nix-darwin](https://daiderd.com/nix-darwin/) users may enable [`nix.linux-builder.enable`](https://daiderd.com/nix-darwin/manual/index.html#opt-nix.linux-builder.enable) to launch such a VM.
|
||||
|
||||
NixOS tests using `systemd-nspawn` [`containers`](#test-opt-containers) require the Nix daemon to be
|
||||
configured with the following settings:
|
||||
|
||||
```nix
|
||||
{
|
||||
nix.settings = {
|
||||
auto-allocate-uids = true;
|
||||
extra-system-features = [ "uid-range" ];
|
||||
experimental-features = [
|
||||
"auto-allocate-uids"
|
||||
"cgroups"
|
||||
];
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
See the documentation of the settings
|
||||
[`auto-allocate-uids`](https://nix.dev/manual/nix/stable/command-ref/conf-file#conf-auto-allocate-uids),
|
||||
[`uid-range`](https://nix.dev/manual/nix/stable/command-ref/conf-file.html?highlight=uid-range#conf-system-features), and
|
||||
[`cgroups`](https://nix.dev/manual/nix/stable/development/experimental-features#xp-feature-cgroups)
|
||||
for more information.
|
||||
|
||||
If the test uses both `systemd-nspawn` [`containers`](#test-opt-containers) and QEMU virtual machine [`nodes`](#test-opt-nodes)
|
||||
and requires them share a common VLAN,
|
||||
`/dev/net` must be present in the sandbox.
|
||||
This allows them to be bridged over a TAP interface.
|
||||
To make this path available, set the following option:
|
||||
|
||||
```nix
|
||||
{
|
||||
nix.settings.sandbox-paths = [ "/dev/net" ];
|
||||
}
|
||||
```
|
||||
|
||||
@@ -4,15 +4,14 @@ A NixOS test is a module that has the following structure:
|
||||
|
||||
```nix
|
||||
{
|
||||
|
||||
# One or more machines:
|
||||
# QEMU virtual machines:
|
||||
nodes = {
|
||||
machine =
|
||||
vm1 =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
# ...
|
||||
};
|
||||
machine2 =
|
||||
vm2 =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
# ...
|
||||
@@ -20,6 +19,20 @@ A NixOS test is a module that has the following structure:
|
||||
# …
|
||||
};
|
||||
|
||||
# systemd-nspawn containers:
|
||||
containers = {
|
||||
container1 =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
# ...
|
||||
};
|
||||
container2 =
|
||||
{ config, pkgs, ... }:
|
||||
{
|
||||
# ...
|
||||
};
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
Python code…
|
||||
'';
|
||||
@@ -27,12 +40,13 @@ A NixOS test is a module that has the following structure:
|
||||
```
|
||||
|
||||
We refer to the whole test above as a test module, whereas the values
|
||||
in [`nodes.<name>`](#test-opt-nodes) are NixOS modules themselves.
|
||||
in [`nodes.<name>`](#test-opt-nodes) and [`containers.<name>`](#test-opt-containers)
|
||||
are NixOS modules themselves.
|
||||
|
||||
The option [`testScript`](#test-opt-testScript) is a piece of Python code that executes the
|
||||
test (described below). During the test, it will start one or more
|
||||
virtual machines, the configuration of which is described by
|
||||
the option [`nodes`](#test-opt-nodes).
|
||||
test (described [below](#ssec-test-script)). During the test, it will start one or more
|
||||
virtual machines and/or `systemd-nspawn` containers, the configuration of which is described by
|
||||
the options [`nodes`](#test-opt-nodes) and [`containers`](#test-opt-containers), respectively.
|
||||
|
||||
An example of a single-node test is
|
||||
[`login.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/login.nix).
|
||||
@@ -42,6 +56,12 @@ when switching between consoles, and so on. An interesting multi-node test is
|
||||
[`nfs/simple.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nfs/simple.nix).
|
||||
It uses two client nodes to test correct locking across server crashes.
|
||||
|
||||
A test can contain both virtual machines and containers.
|
||||
If configured to share a common VLAN,
|
||||
they can reach each other over the network.
|
||||
See [](https://github.com/applicative-systems/nixpkgs/blob/78100f9077ab50604ab9c9514e442bbc7ac7ca5b/nixos/tests/nixos-test-driver/containers.nix)
|
||||
for an example of this and [](#sec-running-nixos-tests-requirements) for the system requirements for this scenario.
|
||||
|
||||
## Calling a test {#sec-calling-nixos-tests}
|
||||
|
||||
Tests are invoked differently depending on whether the test is part of NixOS or lives in a different project.
|
||||
@@ -90,13 +110,54 @@ pkgs.testers.runNixOSTest {
|
||||
|
||||
`runNixOSTest` returns a derivation that runs the test.
|
||||
|
||||
## Configuring the nodes {#sec-nixos-test-nodes}
|
||||
## Test machines {#ssec-nixos-test-machines}
|
||||
|
||||
There are a few special NixOS options for test VMs:
|
||||
A NixOS test usually consists of one or more test machines. Each machine is either a
|
||||
QEMU virtual machine or a `systemd-nspawn` container.
|
||||
|
||||
`virtualisation.memorySize`
|
||||
QEMU virtual machines are defined in the
|
||||
[`nodes`](#test-opt-nodes) attribute set, whereas `systemd-nspawn` containers are defined in the
|
||||
[`containers`](#test-opt-containers) attribute set.
|
||||
|
||||
: The memory of the VM in MiB (1024×1024 bytes).
|
||||
To set NixOS options for all machines in the test, use the attribute
|
||||
[`defaults`](#test-opt-defaults). These options are applied to both virtual machines
|
||||
and containers. You can set separate defaults for virtual machines and containers
|
||||
using the attributes [`nodeDefaults`](#test-opt-nodeDefaults) and
|
||||
[`containerDefaults`](#test-opt-containerDefaults), respectively.
|
||||
|
||||
### Virtual machines vs. containers {#sec-nixos-test-vms-vs-containers}
|
||||
|
||||
QEMU virtual machines and `systemd-nspawn` containers offer different
|
||||
trade-offs which make them suitable for different use cases.
|
||||
|
||||
Some advantages of containers over virtual machines are:
|
||||
|
||||
- Containers share the kernel of the host system; they are
|
||||
significantly faster to start up than virtual machines.
|
||||
- Containers are more lightweight in terms of resource usage, which
|
||||
allows running more of them in parallel on a single host.
|
||||
- Containers can easily be run in virtualised environments, e.g., CI systems.
|
||||
- Containers allow direct bind-mounting of host device nodes, which enables
|
||||
testing of GPU code (CUDA), for example.
|
||||
|
||||
Some advantages of virtual machines over containers are:
|
||||
|
||||
- Virtual machines run a separate kernel, which allows testing kernel features
|
||||
(kernel modules, etc.).
|
||||
- Virtual machines support testing graphical applications on X11.
|
||||
- Virtual machines allow testing NixOS modules that use systemd's namespacing options (such as `ProtectSystem=` or `MountAPIVFS=`).
|
||||
- Virtual machines allow testing [`spcialisation`](options.html#opt-specialisation).
|
||||
(Switching to a specialisation requires the creation of SUID/SGID wrappers, which is disallowed in `systemd-nspawn` within the Nix sandbox.)
|
||||
- Virtual machines allow the execution of `setuid` binaries.
|
||||
|
||||
Refer to the sections on [QEMU virtual machines](#ssec-nixos-test-qemu-vms)
|
||||
and [systemd-nspawn containers](#ssec-nixos-test-nspawn-containers) below
|
||||
for more details on configuring each type of machine.
|
||||
|
||||
### Configuring test machines {#sec-nixos-test-machines-config}
|
||||
|
||||
The following special NixOS option can be used to configure
|
||||
machines in a NixOS test, whether they are virtual machines or containers:
|
||||
|
||||
`virtualisation.vlans`
|
||||
|
||||
@@ -104,6 +165,35 @@ There are a few special NixOS options for test VMs:
|
||||
[`nat.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/tests/nat.nix)
|
||||
for an example.
|
||||
|
||||
#### Configuring `systemd-nspawn` containers {#ssec-nixos-test-nspawn-containers}
|
||||
|
||||
Some options are specific to `systemd-nspawn` containers:
|
||||
|
||||
`virtualisation.systemd-nspawn.options`
|
||||
|
||||
: A list of additional command-line options to pass to
|
||||
`systemd-nspawn` when starting the container. For example, to
|
||||
bind mount a directory from the host into the container, you could
|
||||
use: `[ "--bind=/host/dir:/container/dir" ]`.
|
||||
|
||||
For more options, see the module
|
||||
[`nspawn-container`](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/nspawn-container/default.nix).
|
||||
|
||||
Note that the paths used in `--bind` or `--bind-ro` options have to be accessible from within the Nix sandbox.
|
||||
Use the Nix option
|
||||
[`sandbox-paths`](https://nix.dev/manual/nix/stable/command-ref/conf-file#conf-sandbox-paths)
|
||||
and/or the module [`programs.nix-required-mounts`](#opt-programs.nix-required-mounts.enable) on the host
|
||||
to add additional paths to the sandbox.
|
||||
|
||||
#### Configuring QEMU virtual machines {#ssec-nixos-test-qemu-vms}
|
||||
|
||||
Some options are specific to QEMU virtual machines:
|
||||
|
||||
`virtualisation.memorySize`
|
||||
|
||||
: The memory of the VM in MiB (1024×1024 bytes).
|
||||
|
||||
|
||||
`virtualisation.writableStore`
|
||||
|
||||
: By default, the Nix store in the VM is not writable. If you enable
|
||||
@@ -114,13 +204,15 @@ There are a few special NixOS options for test VMs:
|
||||
For more options, see the module
|
||||
[`qemu-vm.nix`](https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/virtualisation/qemu-vm.nix).
|
||||
|
||||
## Writing the test script {#ssec-test-script}
|
||||
|
||||
The test script is a sequence of Python statements that perform various
|
||||
actions, such as starting VMs, executing commands in the VMs, and so on.
|
||||
Each virtual machine is represented as an object stored in the variable
|
||||
`name` if this is also the identifier of the machine in the declarative
|
||||
config. If you specified a node `nodes.machine`, the following example starts the
|
||||
machine, waits until it has finished booting, then executes a command
|
||||
and checks that the output is more-or-less correct:
|
||||
actions, such as starting machines, executing commands in them, and so on. For
|
||||
example, if you specified a virtual machine in `nodes.machine`, there will be
|
||||
a Python variable `machine` available in the test script that represents that
|
||||
virtual machine. The following example would start the machine, wait until it
|
||||
has finished booting, and then execute a command and check that the output is
|
||||
more-or-less correct:
|
||||
|
||||
```py
|
||||
machine.start()
|
||||
@@ -139,17 +231,20 @@ start_all()
|
||||
|
||||
Under the variable `t`, all assertions from [`unittest.TestCase`](https://docs.python.org/3/library/unittest.html) are available.
|
||||
|
||||
If the hostname of a node contains characters that can't be used in a
|
||||
If the hostname of a machine contains characters that can't be used in a
|
||||
Python variable name, those characters will be replaced with
|
||||
underscores in the variable name, so `nodes.machine-a` will be exposed
|
||||
to Python as `machine_a`.
|
||||
|
||||
## Machine objects {#ssec-machine-objects}
|
||||
### Methods available on machine objects {#ssec-machine-objects}
|
||||
|
||||
The following methods are available on machine objects:
|
||||
The following methods are available on machine objects (like `machine` in
|
||||
the examples above):
|
||||
|
||||
@PYTHON_MACHINE_METHODS@
|
||||
|
||||
### Testing user units {#ssec-testing-user-units}
|
||||
|
||||
To test user units declared by `systemd.user.services` the optional
|
||||
`user` argument can be used:
|
||||
|
||||
@@ -162,6 +257,84 @@ machine.wait_for_unit("xautolock.service", "x-session-user")
|
||||
This applies to `systemctl`, `get_unit_info`, `wait_for_unit`,
|
||||
`start_job` and `stop_job`.
|
||||
|
||||
### Failing tests early {#ssec-failing-tests-early}
|
||||
|
||||
To fail tests early when certain invariants are no longer met (instead of waiting for the build to time out), the decorator `polling_condition` is provided. For example, if we are testing a program `foo` that should not quit after being started, we might write the following:
|
||||
|
||||
```py
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
|
||||
|
||||
machine.succeed("foo --start")
|
||||
machine.wait_until_succeeds("pgrep -x foo")
|
||||
|
||||
with foo_running:
|
||||
... # Put `foo` through its paces
|
||||
```
|
||||
|
||||
`polling_condition` takes the following (optional) arguments:
|
||||
|
||||
`seconds_interval`
|
||||
|
||||
: specifies how often the condition should be polled:
|
||||
|
||||
```py
|
||||
@polling_condition(seconds_interval=10)
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
`description`
|
||||
|
||||
: is used in the log when the condition is checked. If this is not provided, the description is pulled from the docstring of the function. These two are therefore equivalent:
|
||||
|
||||
```py
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
"check that foo is running"
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
```py
|
||||
@polling_condition(description="check that foo is running")
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
### Adding Python packages to the test script {#ssec-python-packages-in-test-script}
|
||||
|
||||
When additional Python libraries are required in the test script, they can be
|
||||
added using the parameter `extraPythonPackages`. For example, you could add
|
||||
`numpy` like this:
|
||||
|
||||
```nix
|
||||
{
|
||||
extraPythonPackages = p: [ p.numpy ];
|
||||
|
||||
nodes = { };
|
||||
|
||||
# Type checking on extra packages doesn't work yet
|
||||
skipTypeCheck = true;
|
||||
|
||||
testScript = ''
|
||||
import numpy as np
|
||||
assert str(np.zeros(4)) == "[0. 0. 0. 0.]"
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
In that case, `numpy` is chosen from the generic `python3Packages`.
|
||||
|
||||
### Linting and type checking test scripts {#ssec-test-script-checks}
|
||||
|
||||
Test scripts are automatically linted with
|
||||
[Pyflakes](https://pypi.org/project/pyflakes/) and type-checked with
|
||||
[Mypy](https://mypy.readthedocs.io/en/stable/).
|
||||
If there are any linting or type checking errors, the test will
|
||||
fail to evaluate.
|
||||
|
||||
For faster dev cycles it's also possible to disable the code-linters
|
||||
(this shouldn't be committed though):
|
||||
|
||||
@@ -209,76 +382,6 @@ way:
|
||||
}
|
||||
```
|
||||
|
||||
## Failing tests early {#ssec-failing-tests-early}
|
||||
|
||||
To fail tests early when certain invariants are no longer met (instead of waiting for the build to time out), the decorator `polling_condition` is provided. For example, if we are testing a program `foo` that should not quit after being started, we might write the following:
|
||||
|
||||
```py
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
|
||||
|
||||
machine.succeed("foo --start")
|
||||
machine.wait_until_succeeds("pgrep -x foo")
|
||||
|
||||
with foo_running:
|
||||
... # Put `foo` through its paces
|
||||
```
|
||||
|
||||
`polling_condition` takes the following (optional) arguments:
|
||||
|
||||
`seconds_interval`
|
||||
|
||||
: specifies how often the condition should be polled:
|
||||
|
||||
```py
|
||||
@polling_condition(seconds_interval=10)
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
`description`
|
||||
|
||||
: is used in the log when the condition is checked. If this is not provided, the description is pulled from the docstring of the function. These two are therefore equivalent:
|
||||
|
||||
```py
|
||||
@polling_condition
|
||||
def foo_running():
|
||||
"check that foo is running"
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
```py
|
||||
@polling_condition(description="check that foo is running")
|
||||
def foo_running():
|
||||
machine.succeed("pgrep -x foo")
|
||||
```
|
||||
|
||||
## Adding Python packages to the test script {#ssec-python-packages-in-test-script}
|
||||
|
||||
When additional Python libraries are required in the test script, they can be
|
||||
added using the parameter `extraPythonPackages`. For example, you could add
|
||||
`numpy` like this:
|
||||
|
||||
```nix
|
||||
{
|
||||
extraPythonPackages = p: [ p.numpy ];
|
||||
|
||||
nodes = { };
|
||||
|
||||
# Type checking on extra packages doesn't work yet
|
||||
skipTypeCheck = true;
|
||||
|
||||
testScript = ''
|
||||
import numpy as np
|
||||
assert str(np.zeros(4)) == "[0. 0. 0. 0.]"
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
In that case, `numpy` is chosen from the generic `python3Packages`.
|
||||
|
||||
## Overriding a test {#sec-override-nixos-test}
|
||||
|
||||
The NixOS test framework returns tests with multiple overriding methods.
|
||||
@@ -297,7 +400,7 @@ The NixOS test framework returns tests with multiple overriding methods.
|
||||
: Evaluates the test with additional NixOS modules and/or arguments.
|
||||
|
||||
`module`
|
||||
: A NixOS module to add to all the nodes in the test. Sets test option [`extraBaseModules`](#test-opt-extraBaseModules).
|
||||
: A NixOS module to add to all the machines in the test. Sets test option [`extraBaseModules`](#test-opt-extraBaseModules).
|
||||
|
||||
`specialArgs`
|
||||
: An attribute set of arguments to pass to all NixOS modules. These override the existing arguments, as well as any `_module.args.<name>` that the modules may define. Sets test option [`node.specialArgs`](#test-opt-node.specialArgs).
|
||||
@@ -345,7 +448,52 @@ list-id: test-options-list
|
||||
source: @NIXOS_TEST_OPTIONS_JSON@
|
||||
```
|
||||
|
||||
## Accessing VMs in the sandbox with SSH {#sec-test-sandbox-breakpoint}
|
||||
## Debugging test machines {#sec-test-sandbox-breakpoint}
|
||||
|
||||
You can set the [`enableDebugHook`](#test-opt-enableDebugHook) option to pause
|
||||
a test on the first failure and have it print instructions on how to enter the
|
||||
sandbox shell of the test. Suppose you have the following test module:
|
||||
|
||||
```nix
|
||||
{
|
||||
name = "foo";
|
||||
|
||||
nodes.machine = { };
|
||||
|
||||
enableDebugHook = true;
|
||||
sshBackdoor.enable = true;
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.succeed("false") # this will fail
|
||||
'';
|
||||
}
|
||||
```
|
||||
|
||||
The test will fail with an output like this:
|
||||
|
||||
```
|
||||
vm-test-run-foo> !!! Breakpoint reached, run 'sudo /nix/store/eeeee-attach/bin/attach <PID>'
|
||||
```
|
||||
|
||||
You can then enter the sandbox shell:
|
||||
|
||||
```
|
||||
$ sudo /nix/store/eeeee-attach/bin/attach <PID>
|
||||
bash#
|
||||
```
|
||||
|
||||
There, you can attach to a [`pdb`](https://docs.python.org/3/library/pdb.html) session
|
||||
to step through the Python test script:
|
||||
|
||||
```
|
||||
bash# telnet 127.0.0.1 4444
|
||||
pdb$
|
||||
```
|
||||
|
||||
Note that it is also possible to set breakpoints in the test script using `debug.breakpoint()`.
|
||||
|
||||
### SSH access to test VMs {#sec-test-vm-ssh-access}
|
||||
|
||||
::: {.note}
|
||||
For debugging with SSH access into the machines, it's recommended to try using
|
||||
@@ -356,24 +504,15 @@ This feature is mostly intended to debug flaky test failures that aren't
|
||||
reproducible elsewhere.
|
||||
:::
|
||||
|
||||
As explained in [](#sec-nixos-test-ssh-access), it's possible to configure an
|
||||
SSH backdoor based on AF_VSOCK. This can be used to SSH into a VM of a running
|
||||
build in a sandbox.
|
||||
|
||||
This can be done when something in the test fails, e.g.
|
||||
If you set the [`sshBackdoor.enable`](#test-opt-sshBackdoor.enable) option,
|
||||
QEMU virtual machines will open an SSH backdoor based on AF_VSOCK
|
||||
(see [](#sec-nixos-test-ssh-access)).
|
||||
Once you are in the sandbox shell, you can access the VMs (for example, `machine`)
|
||||
with SSH over vsock:
|
||||
|
||||
```nix
|
||||
{
|
||||
nodes.machine = { };
|
||||
|
||||
sshBackdoor.enable = true;
|
||||
enableDebugHook = true;
|
||||
|
||||
testScript = ''
|
||||
start_all()
|
||||
machine.succeed("false") # this will fail
|
||||
'';
|
||||
}
|
||||
```
|
||||
bash# ssh -F ./ssh_config vsock/3
|
||||
```
|
||||
|
||||
For the AF_VSOCK feature to work, `/dev/vhost-vsock` is needed in the sandbox
|
||||
@@ -383,24 +522,24 @@ which can be done with e.g.
|
||||
nix-build -A nixosTests.foo --option sandbox-paths /dev/vhost-vsock
|
||||
```
|
||||
|
||||
This will halt the test execution on a test-failure and print instructions
|
||||
on how to enter the sandbox shell of the VM test. Inside, one can log into
|
||||
e.g. `machine` with
|
||||
|
||||
```
|
||||
ssh -F ./ssh_config vsock/3
|
||||
```
|
||||
|
||||
As described in [](#sec-nixos-test-ssh-access), the numbers for vsock start at
|
||||
`3` instead of `1`. So the first VM in the network (sorted alphabetically) can
|
||||
be accessed with `vsock/3`.
|
||||
|
||||
Alternatively, it's possible to explicitly set a breakpoint with
|
||||
`debug.breakpoint()`. This also has the benefit, that one can step through
|
||||
`testScript` with `pdb` like this:
|
||||
### SSH access to test containers {#sec-test-container-ssh-access}
|
||||
|
||||
If you set the [`sshBackdoor.enable`](#test-opt-sshBackdoor.enable) option,
|
||||
each `systemd-nspawn` container will open an SSH backdoor.
|
||||
Once the container starts,
|
||||
it will print instructions on how to log into the container via SSH.
|
||||
If the test fails,
|
||||
attach to the sandbox as described above,
|
||||
and then use the provided SSH command to log into the container.
|
||||
For example:
|
||||
|
||||
```
|
||||
$ sudo /nix/store/eeeee-attach <id>
|
||||
bash# telnet 127.0.0.1 4444
|
||||
pdb$ …
|
||||
$ sudo /nix/store/eeeee-attach <PID>
|
||||
bash# ssh -o User=root -o ProxyCommand="socat - UNIX-CLIENT:/run/systemd/nspawn/unix-export/machine/ssh" bash
|
||||
[root@machine:~]# hostname
|
||||
machine
|
||||
```
|
||||
|
||||
@@ -88,6 +88,9 @@
|
||||
"module-virtualisation-xen-introduction": [
|
||||
"index.html#module-virtualisation-xen-introduction"
|
||||
],
|
||||
"sec-nixos-test-vms-vs-containers": [
|
||||
"index.html#sec-nixos-test-vms-vs-containers"
|
||||
],
|
||||
"sec-override-nixos-test": [
|
||||
"index.html#sec-override-nixos-test"
|
||||
],
|
||||
@@ -100,6 +103,51 @@
|
||||
"sec-wireless-imperative": [
|
||||
"index.html#sec-wireless-imperative"
|
||||
],
|
||||
"sec-test-container-ssh-access": [
|
||||
"index.html#sec-test-container-ssh-access"
|
||||
],
|
||||
"sec-test-vm-ssh-access": [
|
||||
"index.html#sec-test-vm-ssh-access"
|
||||
],
|
||||
"ssec-all-machine-objects": [
|
||||
"index.html#ssec-all-machine-objects"
|
||||
],
|
||||
"ssec-nixos-test-machines": [
|
||||
"index.html#ssec-nixos-test-machines"
|
||||
],
|
||||
"ssec-nixos-test-nspawn-containers": [
|
||||
"index.html#ssec-nixos-test-nspawn-containers"
|
||||
],
|
||||
"ssec-nixos-test-qemu-vms": [
|
||||
"index.html#ssec-nixos-test-qemu-vms"
|
||||
],
|
||||
"ssec-nspawn-machine-objects": [
|
||||
"index.html#ssec-nspawn-machine-objects"
|
||||
],
|
||||
"ssec-qemu-machine-objects": [
|
||||
"index.html#ssec-qemu-machine-objects"
|
||||
],
|
||||
"ssec-test-script": [
|
||||
"index.html#ssec-test-script"
|
||||
],
|
||||
"ssec-test-script-checks": [
|
||||
"index.html#ssec-test-script-checks"
|
||||
],
|
||||
"ssec-testing-user-units": [
|
||||
"index.html#ssec-testing-user-units"
|
||||
],
|
||||
"test-opt-containerDefaults": [
|
||||
"index.html#test-opt-containerDefaults"
|
||||
],
|
||||
"test-opt-containers": [
|
||||
"index.html#test-opt-containers"
|
||||
],
|
||||
"test-opt-extraBaseModules": [
|
||||
"index.html#test-opt-extraBaseModules"
|
||||
],
|
||||
"test-opt-nodeDefaults": [
|
||||
"index.html#test-opt-nodeDefaults"
|
||||
],
|
||||
"test-opt-rawTestDerivationArg": [
|
||||
"index.html#test-opt-rawTestDerivationArg"
|
||||
],
|
||||
@@ -2037,7 +2085,8 @@
|
||||
"sec-call-nixos-test-outside-nixos": [
|
||||
"index.html#sec-call-nixos-test-outside-nixos"
|
||||
],
|
||||
"sec-nixos-test-nodes": [
|
||||
"sec-nixos-test-machines-config": [
|
||||
"index.html#sec-nixos-test-machines-config",
|
||||
"index.html#sec-nixos-test-nodes"
|
||||
],
|
||||
"ssec-machine-objects": [
|
||||
@@ -2070,8 +2119,8 @@
|
||||
"test-opt-enableOCR": [
|
||||
"index.html#test-opt-enableOCR"
|
||||
],
|
||||
"test-opt-extraBaseModules": [
|
||||
"index.html#test-opt-extraBaseModules"
|
||||
"test-opt-extraBaseNodeModules": [
|
||||
"index.html#test-opt-extraBaseNodeModules"
|
||||
],
|
||||
"test-opt-extraDriverArgs": [
|
||||
"index.html#test-opt-extraDriverArgs"
|
||||
|
||||
@@ -247,6 +247,8 @@ See <https://github.com/NixOS/nixpkgs/issues/481673>.
|
||||
|
||||
- `services.caddy` now supports setting `httpPort` and `httpsPort` and opening them in the firewall via `openFirewall`.
|
||||
|
||||
- `boot.initrd.secrets` is now deprecated in favour of `boot.initrd.secretPaths` and `boot.initrd.extraSecretsHook`.
|
||||
|
||||
- The latest available version of Nextcloud is v33 (available as `pkgs.nextcloud33`). The installation logic is as follows:
|
||||
- If [`services.nextcloud.package`](#opt-services.nextcloud.package) is specified explicitly, this package will be installed (**recommended**)
|
||||
- If [`system.stateVersion`](#opt-system.stateVersion) is >=26.05, `pkgs.nextcloud33` will be installed by default.
|
||||
@@ -306,3 +308,5 @@ See <https://github.com/NixOS/nixpkgs/issues/481673>.
|
||||
```
|
||||
|
||||
**Do not set this globally!** This makes your setup inherently less secure.
|
||||
|
||||
- `services.radicle` now supports importing the private key and passphrase as systemd creds.
|
||||
|
||||
@@ -3,12 +3,8 @@
|
||||
let
|
||||
inherit (systemdUtils.lib)
|
||||
assertValueOneOf
|
||||
automountConfig
|
||||
checkUnitConfig
|
||||
makeJobScript
|
||||
mountConfig
|
||||
serviceConfig
|
||||
unitConfig
|
||||
unitNameType
|
||||
;
|
||||
|
||||
|
||||
@@ -42,6 +42,43 @@ some_function(param1, param2)
|
||||
"""
|
||||
|
||||
|
||||
def function_docstrings(functions: list[ast.FunctionDef]) -> str | None:
|
||||
"""Extracts docstrings from a list of function definitions."""
|
||||
documented_functions = [f for f in functions if ast.get_docstring(f) is not None]
|
||||
|
||||
if not documented_functions:
|
||||
return None
|
||||
|
||||
docstrings = []
|
||||
for function in documented_functions:
|
||||
docstr = ast.get_docstring(function)
|
||||
assert docstr is not None
|
||||
|
||||
args = ", ".join(a.arg for a in function.args.args[1:])
|
||||
args = f"({args})"
|
||||
|
||||
docstr = "\n".join(f" {line}" for line in docstr.strip().splitlines())
|
||||
|
||||
docstrings.append(f"{function.name}{args}\n\n:{docstr[1:]}\n")
|
||||
return "\n".join(docstrings)
|
||||
|
||||
|
||||
def machine_methods(
|
||||
class_name: str, class_definitions: list[ast.ClassDef]
|
||||
) -> list[ast.FunctionDef]:
|
||||
"""Given a class name and a list of class definitions, returns the list of function definitions
|
||||
for the class matching the given name.
|
||||
"""
|
||||
machine_class = next(filter(lambda x: x.name == class_name, class_definitions))
|
||||
assert machine_class is not None
|
||||
|
||||
function_definitions = [
|
||||
node for node in machine_class.body if isinstance(node, ast.FunctionDef)
|
||||
]
|
||||
function_definitions.sort(key=lambda x: x.name)
|
||||
return function_definitions
|
||||
|
||||
|
||||
def main() -> None:
|
||||
if len(sys.argv) != 2:
|
||||
print(f"Usage: {sys.argv[0]} <path-to-test-driver>")
|
||||
@@ -49,25 +86,35 @@ def main() -> None:
|
||||
|
||||
module = ast.parse(Path(sys.argv[1]).read_text())
|
||||
|
||||
class_definitions = (node for node in module.body if isinstance(node, ast.ClassDef))
|
||||
class_definitions = [node for node in module.body if isinstance(node, ast.ClassDef)]
|
||||
|
||||
machine_class = next(filter(lambda x: x.name == "BaseMachine", class_definitions))
|
||||
assert machine_class is not None
|
||||
base_machine_methods = machine_methods("BaseMachine", class_definitions)
|
||||
base_method_names = {method.name for method in base_machine_methods}
|
||||
|
||||
function_definitions = [
|
||||
node for node in machine_class.body if isinstance(node, ast.FunctionDef)
|
||||
qemu_machine_methods = [
|
||||
method
|
||||
for method in machine_methods("QemuMachine", class_definitions)
|
||||
if method.name not in base_method_names
|
||||
]
|
||||
function_definitions.sort(key=lambda x: x.name)
|
||||
|
||||
for function in function_definitions:
|
||||
docstr = ast.get_docstring(function)
|
||||
if docstr is not None:
|
||||
args = ", ".join(a.arg for a in function.args.args[1:])
|
||||
args = f"({args})"
|
||||
nspawn_machine_methods = [
|
||||
method
|
||||
for method in machine_methods("NspawnMachine", class_definitions)
|
||||
if method.name not in base_method_names
|
||||
]
|
||||
|
||||
docstr = "\n".join(f" {line}" for line in docstr.strip().splitlines())
|
||||
|
||||
print(f"{function.name}{args}\n\n:{docstr[1:]}\n")
|
||||
print("#### Generic machine objects {#ssec-all-machine-objects} \n")
|
||||
print(function_docstrings(base_machine_methods))
|
||||
print("#### QEMU VM objects {#ssec-qemu-machine-objects}\n")
|
||||
print(
|
||||
function_docstrings(qemu_machine_methods)
|
||||
or "No methods specific to QEMU virtual machines."
|
||||
)
|
||||
print("#### `systemd-nspawn` container objects {#ssec-nspawn-machine-objects}\n")
|
||||
print(
|
||||
function_docstrings(nspawn_machine_methods)
|
||||
or "No methods specific to `systemd-nspawn` containers."
|
||||
)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Executable → Regular
@@ -271,10 +271,24 @@ class BaseMachine(ABC):
|
||||
def is_up(self) -> bool: ...
|
||||
|
||||
@abstractmethod
|
||||
def start(self) -> None: ...
|
||||
def start(self) -> None:
|
||||
"""
|
||||
Start the machine. This method is asynchronous --- it does
|
||||
not wait for the machine to finish booting.
|
||||
"""
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def wait_for_shutdown(self) -> None: ...
|
||||
def wait_for_shutdown(self) -> None:
|
||||
"""Wait for the machine to power off. This does *not* initiate a shutdown;
|
||||
that's usually done via `shutdown()`.
|
||||
"""
|
||||
...
|
||||
|
||||
@abstractmethod
|
||||
def shutdown(self) -> None:
|
||||
"""Shutdown the machine gracefully, waiting for it to exit."""
|
||||
...
|
||||
|
||||
def systemctl(self, q: str, user: str | None = None) -> tuple[int, str]:
|
||||
"""
|
||||
@@ -558,6 +572,38 @@ class BaseMachine(ABC):
|
||||
check_output: bool = True,
|
||||
timeout: int | None = 900,
|
||||
) -> tuple[int, str]:
|
||||
"""
|
||||
Execute a shell command, returning a list `(status, stdout)`.
|
||||
|
||||
Commands are run with `set -euo pipefail` set:
|
||||
|
||||
- If several commands are separated by `;` and one fails, the
|
||||
command as a whole will fail.
|
||||
|
||||
- For pipelines, the last non-zero exit status will be returned
|
||||
(if there is one; otherwise zero will be returned).
|
||||
|
||||
- Dereferencing unset variables fails the command.
|
||||
|
||||
- It will wait for stdout to be closed.
|
||||
|
||||
If the command detaches, it must close stdout, as `execute` will wait
|
||||
for this to consume all output reliably. This can be achieved by
|
||||
redirecting stdout to stderr `>&2`, to `/dev/console`, `/dev/null` or
|
||||
a file. Examples of detaching commands are `sleep 365d &`, where the
|
||||
shell forks a new process that can write to stdout and `xclip -i`, where
|
||||
the `xclip` command itself forks without closing stdout.
|
||||
|
||||
Takes an optional parameter `check_return` that defaults to `True`.
|
||||
Setting this parameter to `False` will not check for the return code
|
||||
and return -1 instead. This can be used for commands that shut down
|
||||
the machine and would therefore break the pipe that would be used for
|
||||
retrieving the return code.
|
||||
|
||||
A timeout for the command can be specified (in seconds) using the optional
|
||||
`timeout` parameter, e.g., `execute(cmd, timeout=10)` or
|
||||
`execute(cmd, timeout=None)`. The default is 900 seconds.
|
||||
"""
|
||||
self.run_callbacks()
|
||||
return self._execute(
|
||||
command=command,
|
||||
@@ -806,38 +852,6 @@ class QemuMachine(BaseMachine):
|
||||
check_output: bool = True,
|
||||
timeout: int | None = 900,
|
||||
) -> tuple[int, str]:
|
||||
"""
|
||||
Execute a shell command, returning a list `(status, stdout)`.
|
||||
|
||||
Commands are run with `set -euo pipefail` set:
|
||||
|
||||
- If several commands are separated by `;` and one fails, the
|
||||
command as a whole will fail.
|
||||
|
||||
- For pipelines, the last non-zero exit status will be returned
|
||||
(if there is one; otherwise zero will be returned).
|
||||
|
||||
- Dereferencing unset variables fails the command.
|
||||
|
||||
- It will wait for stdout to be closed.
|
||||
|
||||
If the command detaches, it must close stdout, as `execute` will wait
|
||||
for this to consume all output reliably. This can be achieved by
|
||||
redirecting stdout to stderr `>&2`, to `/dev/console`, `/dev/null` or
|
||||
a file. Examples of detaching commands are `sleep 365d &`, where the
|
||||
shell forks a new process that can write to stdout and `xclip -i`, where
|
||||
the `xclip` command itself forks without closing stdout.
|
||||
|
||||
Takes an optional parameter `check_return` that defaults to `True`.
|
||||
Setting this parameter to `False` will not check for the return code
|
||||
and return -1 instead. This can be used for commands that shut down
|
||||
the machine and would therefore break the pipe that would be used for
|
||||
retrieving the return code.
|
||||
|
||||
A timeout for the command can be specified (in seconds) using the optional
|
||||
`timeout` parameter, e.g., `execute(cmd, timeout=10)` or
|
||||
`execute(cmd, timeout=None)`. The default is 900 seconds.
|
||||
"""
|
||||
self.connect()
|
||||
|
||||
# Always run command with shell opts
|
||||
@@ -1599,6 +1613,10 @@ class NspawnMachine(BaseMachine):
|
||||
time.sleep(1)
|
||||
|
||||
def start(self) -> None:
|
||||
"""
|
||||
Start the systemd-nspawn container. This method is asynchronous --- it does
|
||||
not wait for the container to finish booting.
|
||||
"""
|
||||
if self.process is not None:
|
||||
return
|
||||
|
||||
@@ -1627,7 +1645,20 @@ class NspawnMachine(BaseMachine):
|
||||
journal_thread = threading.Thread(target=self._stream_journal, daemon=True)
|
||||
journal_thread.start()
|
||||
|
||||
def shutdown(self) -> None:
|
||||
"""
|
||||
Shut down the container, waiting for it to exit.
|
||||
"""
|
||||
if self.process is None:
|
||||
return
|
||||
self.systemctl("poweroff")
|
||||
self.wait_for_shutdown()
|
||||
|
||||
def wait_for_shutdown(self) -> None:
|
||||
"""
|
||||
Wait for the container to power off. This does *not* initiate a shutdown;
|
||||
that's usually done via `shutdown()`.
|
||||
"""
|
||||
if self.process is None:
|
||||
return
|
||||
|
||||
|
||||
@@ -172,7 +172,7 @@ in
|
||||
|
||||
They are assigned network addresses according to the `nixos/lib/testing/network.nix` module.
|
||||
|
||||
A few special options are available, that aren't in a plain NixOS configuration. See [Configuring the nodes](#sec-nixos-test-nodes)
|
||||
A few special options are available, that aren't in a plain NixOS configuration. See [Configuring virtual machines](#ssec-nixos-test-qemu-vms)
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -193,7 +193,7 @@ in
|
||||
|
||||
They are assigned network addresses according to the `nixos/lib/testing/network.nix` module.
|
||||
|
||||
A few special options are available, that aren't in a plain NixOS configuration. See [Configuring the nodes](#sec-nixos-test-nodes)
|
||||
A few special options are available, that aren't in a plain NixOS configuration. See [Configuring containers](#ssec-nixos-test-nspawn-containers)
|
||||
'';
|
||||
};
|
||||
|
||||
|
||||
@@ -214,6 +214,7 @@ in
|
||||
postBuild = ''
|
||||
# Remove wrapped binaries, they shouldn't be accessible via PATH.
|
||||
find $out/bin -maxdepth 1 -name ".*-wrapped" -type l -delete
|
||||
find $out/bin -maxdepth 1 -name ".*-wrapped_*" -type l -delete
|
||||
|
||||
if [ -x $out/bin/glib-compile-schemas -a -w $out/share/glib-2.0/schemas ]; then
|
||||
$out/bin/glib-compile-schemas $out/share/glib-2.0/schemas
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{ config, lib, ... }:
|
||||
# unixODBC drivers (this solution is not perfect.. Because the user has to
|
||||
# unixodbc drivers (this solution is not perfect.. Because the user has to
|
||||
# ask the admin to add a driver.. but it's simple and works
|
||||
|
||||
let
|
||||
@@ -17,11 +17,11 @@ in
|
||||
environment.unixODBCDrivers = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.package;
|
||||
default = [ ];
|
||||
example = lib.literalExpression "with pkgs.unixODBCDrivers; [ sqlite psql ]";
|
||||
example = lib.literalExpression "with pkgs.unixodbcDrivers; [ sqlite psql ]";
|
||||
description = ''
|
||||
Specifies Unix ODBC drivers to be registered in
|
||||
{file}`/etc/odbcinst.ini`. You may also want to
|
||||
add `pkgs.unixODBC` to the system path to get
|
||||
add `pkgs.unixodbc` to the system path to get
|
||||
a command line client to connect to ODBC databases.
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -566,6 +566,16 @@ in
|
||||
'';
|
||||
};
|
||||
|
||||
finalPackage = mkOption {
|
||||
default = package;
|
||||
internal = true;
|
||||
readOnly = true;
|
||||
type = types.package;
|
||||
description = ''
|
||||
The final Home Assistant package which is being used in the service.
|
||||
'';
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
default = false;
|
||||
type = types.bool;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}:
|
||||
let
|
||||
@@ -15,6 +16,11 @@ let
|
||||
RAD_HOME = HOME;
|
||||
};
|
||||
|
||||
credentials = {
|
||||
privateKey = "xyz.radicle.node.secret";
|
||||
privateKeyPassphrase = "xyz.radicle.node.passphrase";
|
||||
};
|
||||
|
||||
# Convenient wrapper to run `rad` in the namespaces of `radicle-node.service`
|
||||
rad-system = pkgs.writeShellScriptBin "rad-system" ''
|
||||
set -o allexport
|
||||
@@ -131,16 +137,34 @@ in
|
||||
services.radicle = {
|
||||
enable = lib.mkEnableOption "Radicle Seed Node";
|
||||
package = lib.mkPackageOption pkgs "radicle-node" { };
|
||||
privateKeyFile = lib.mkOption {
|
||||
# Note that a key encrypted by systemd-creds is not a path but a str.
|
||||
type = with lib.types; either path str;
|
||||
privateKey = lib.mkOption {
|
||||
type = with lib.types; nullOr (either path str);
|
||||
default = null;
|
||||
description = ''
|
||||
Absolute file path to an SSH private key,
|
||||
An SSH private key (as an absolute file path or Systemd credential name),
|
||||
usually generated by `rad auth`.
|
||||
|
||||
If it contains a colon (`:`) the string before the colon
|
||||
is taken as the credential name
|
||||
and the string after as a path encrypted with `systemd-creds`.
|
||||
If set to the default value of `null`, radicle will import the private key from a credential
|
||||
named `${credentials.privateKey}`.
|
||||
|
||||
If configured as a credential name it will be imported via `ImportCredential=` in the service configuration.
|
||||
Refer to the systemd-creds documentation for more details <https://systemd.io/CREDENTIALS/>
|
||||
'';
|
||||
};
|
||||
privateKeyPassphrase = lib.mkOption {
|
||||
type = with lib.types; nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
A passphrase for an SSH private key (as a Systemd credential name),
|
||||
usually provided on generation of the key with `rad auth`.
|
||||
|
||||
If set to the default value of `null`, radicle will optionally import the passphrase from a
|
||||
credential named `${credentials.privateKeyPassphrase}`.
|
||||
|
||||
If the passphrase is not set, radicle will prompt for it.
|
||||
|
||||
If configured as a credential name it will be imported via `ImportCredential=` in the service configuration.
|
||||
Refer to the systemd-creds documentation for more details <https://systemd.io/CREDENTIALS/>
|
||||
'';
|
||||
};
|
||||
publicKey = lib.mkOption {
|
||||
@@ -304,23 +328,28 @@ in
|
||||
# Give only access to the private key to radicle-node.
|
||||
{
|
||||
serviceConfig =
|
||||
let
|
||||
keyCred = builtins.split ":" "${cfg.privateKeyFile}";
|
||||
in
|
||||
if lib.length keyCred > 1 then
|
||||
if cfg.privateKey == null then
|
||||
{
|
||||
LoadCredentialEncrypted = [ cfg.privateKeyFile ];
|
||||
# Note that neither %d nor ${CREDENTIALS_DIRECTORY} works in BindReadOnlyPaths=
|
||||
BindReadOnlyPaths = [
|
||||
"/run/credentials/radicle-node.service/${lib.head keyCred}:${env.RAD_HOME}/keys/radicle"
|
||||
];
|
||||
ImportCredential = [ credentials.privateKey ];
|
||||
}
|
||||
else if lib.types.path.check cfg.privateKey then
|
||||
{
|
||||
LoadCredential = [ "${credentials.privateKey}:${cfg.privateKey}" ];
|
||||
}
|
||||
else
|
||||
{
|
||||
LoadCredential = [ "radicle:${cfg.privateKeyFile}" ];
|
||||
BindReadOnlyPaths = [
|
||||
"/run/credentials/radicle-node.service/radicle:${env.RAD_HOME}/keys/radicle"
|
||||
];
|
||||
ImportCredential = [ "${cfg.privateKey}:${credentials.privateKey}" ];
|
||||
};
|
||||
}
|
||||
{
|
||||
serviceConfig =
|
||||
if cfg.privateKeyPassphrase == null then
|
||||
{
|
||||
ImportCredential = [ credentials.privateKeyPassphrase ];
|
||||
}
|
||||
else
|
||||
{
|
||||
ImportCredential = [ "${cfg.privateKeyPassphrase}:${credentials.privateKeyPassphrase}" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
@@ -86,7 +86,7 @@ in
|
||||
description = ''
|
||||
Append an additional file's contents to `/etc/iscsid.conf`. Use a non-store path
|
||||
and store passwords in this file. Note: the file specified here must be available
|
||||
in the initrd, see: `boot.initrd.secrets`.
|
||||
in the initrd, see: `boot.initrd.secretPaths`.
|
||||
'';
|
||||
default = null;
|
||||
type = nullOr str;
|
||||
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
let
|
||||
cfg = config.services.murmur;
|
||||
acmeHostDir = config.security.acme.certs."${cfg.tls.useACMEHost}".directory;
|
||||
|
||||
forking = cfg.logToFile;
|
||||
configFile = pkgs.writeText "murmurd.ini" ''
|
||||
database=${cfg.stateDir}/murmur.sqlite
|
||||
@@ -41,9 +43,9 @@ let
|
||||
${lib.optionalString (cfg.registerHostname != "") "registerHostname=${cfg.registerHostname}"}
|
||||
|
||||
certrequired=${lib.boolToString cfg.clientCertRequired}
|
||||
${lib.optionalString (cfg.sslCert != null) "sslCert=${cfg.sslCert}"}
|
||||
${lib.optionalString (cfg.sslKey != null) "sslKey=${cfg.sslKey}"}
|
||||
${lib.optionalString (cfg.sslCa != null) "sslCA=${cfg.sslCa}"}
|
||||
${lib.optionalString (cfg.tls.certPath != null) "sslCert=${cfg.tls.certPath}"}
|
||||
${lib.optionalString (cfg.tls.keyPath != null) "sslKey=${cfg.tls.keyPath}"}
|
||||
${lib.optionalString (cfg.tls.caPath != null) "sslCA=${cfg.tls.caPath}"}
|
||||
|
||||
${lib.optionalString (cfg.dbus != null) "dbus=${cfg.dbus}"}
|
||||
|
||||
@@ -58,6 +60,12 @@ in
|
||||
"murmur"
|
||||
"logFile"
|
||||
] "This option has been superseded by services.murmur.logToFile")
|
||||
(lib.mkRenamedOptionModule [ "services" "murmur" "sslCa" ] [ "services" "murmur" "tls" "caPath" ])
|
||||
(lib.mkRenamedOptionModule [ "services" "murmur" "sslKey" ] [ "services" "murmur" "tls" "keyPath" ])
|
||||
(lib.mkRenamedOptionModule
|
||||
[ "services" "murmur" "sslCert" ]
|
||||
[ "services" "murmur" "tls" "certPath" ]
|
||||
)
|
||||
];
|
||||
|
||||
options = {
|
||||
@@ -237,22 +245,41 @@ in
|
||||
|
||||
clientCertRequired = lib.mkEnableOption "requiring clients to authenticate via certificates";
|
||||
|
||||
sslCert = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = "Path to your SSL certificate.";
|
||||
};
|
||||
tls = {
|
||||
certPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = if (cfg.tls.useACMEHost != null) then "${acmeHostDir}/cert.pem" else null;
|
||||
defaultText = lib.literalMD "If {option}`services.murmur.tls.useACMEHost` is set, defaults to what's provided by the ACME module.";
|
||||
description = "Path to your TLS certificate.";
|
||||
};
|
||||
|
||||
sslKey = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = "Path to your SSL key.";
|
||||
};
|
||||
keyPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = if (cfg.tls.useACMEHost != null) then "${acmeHostDir}/key.pem" else null;
|
||||
defaultText = lib.literalMD "If {option}`services.murmur.tls.useACMEHost` is set, defaults to what's provided by the ACME module.";
|
||||
description = "Path to your TLS key.";
|
||||
};
|
||||
|
||||
sslCa = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = null;
|
||||
description = "Path to your SSL CA certificate.";
|
||||
caPath = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.path;
|
||||
default = if (cfg.tls.useACMEHost != null) then "${acmeHostDir}/chain.pem" else null;
|
||||
defaultText = lib.literalMD "If {option}`services.murmur.tls.useACMEHost` is set, defaults to what's provided by the ACME module.";
|
||||
description = "Path to your TLS CA certificate.";
|
||||
};
|
||||
|
||||
useACMEHost = lib.mkOption {
|
||||
type = lib.types.nullOr lib.types.str;
|
||||
default = null;
|
||||
example = "mumble.example.com";
|
||||
description = ''
|
||||
Host of an existing Let's Encrypt certificate to use for TLS.
|
||||
Make sure that the certificate directory is readable by the
|
||||
`murmur` user or group. *Note that this option does not
|
||||
create any certificates and it doesn't add subdomains to
|
||||
existing ones – you will need to create them manually using
|
||||
{option}`security.acme.certs`.*
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
extraConfig = lib.mkOption {
|
||||
@@ -316,10 +343,18 @@ in
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
|
||||
security.acme.certs = lib.mkIf (cfg.tls.useACMEHost != null) {
|
||||
"${cfg.tls.useACMEHost}".reloadServices = [ "murmur.service" ];
|
||||
};
|
||||
|
||||
systemd.services.murmur = {
|
||||
description = "Murmur Chat Service";
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
after = [
|
||||
"network.target"
|
||||
]
|
||||
++ lib.optional (cfg.tls.useACMEHost != null) "acme-${cfg.tls.useACMEHost}.service";
|
||||
wants = lib.mkIf (cfg.tls.useACMEHost != null) [ "acme-${cfg.tls.useACMEHost}.service" ];
|
||||
preStart = ''
|
||||
${pkgs.envsubst}/bin/envsubst \
|
||||
-o /run/murmur/murmurd.ini \
|
||||
@@ -422,14 +457,14 @@ in
|
||||
${lib.optionalString cfg.logToFile ''
|
||||
/var/log/murmur/murmurd.log rw,
|
||||
''}
|
||||
${lib.optionalString (cfg.sslCert != null) ''
|
||||
${cfg.sslCert} r,
|
||||
${lib.optionalString (cfg.tls.certPath != null) ''
|
||||
${cfg.tls.certPath} r,
|
||||
''}
|
||||
${lib.optionalString (cfg.sslKey != null) ''
|
||||
${cfg.sslKey} r,
|
||||
${lib.optionalString (cfg.tls.keyPath != null) ''
|
||||
${cfg.tls.keyPath} r,
|
||||
''}
|
||||
${lib.optionalString (cfg.sslCa != null) ''
|
||||
${cfg.sslCa} r,
|
||||
${lib.optionalString (cfg.tls.caPath != null) ''
|
||||
${cfg.tls.caPath} r,
|
||||
''}
|
||||
${lib.optionalString (cfg.dbus != null) ''
|
||||
dbus bus=${cfg.dbus},
|
||||
|
||||
@@ -14,7 +14,9 @@ let
|
||||
children = lib.mapAttrs (
|
||||
childName: childConfig: childConfig.configuration.system.build.toplevel
|
||||
) config.specialisation;
|
||||
hasAtLeastOneInitrdSecret = lib.length (lib.attrNames config.boot.initrd.secrets) > 0;
|
||||
hasInitrdSecrets =
|
||||
(lib.length (lib.attrNames config.boot.initrd.secretPaths) > 0)
|
||||
|| (config.boot.initrd.extraSecretsHook != "");
|
||||
schemas = {
|
||||
v1 = rec {
|
||||
filename = "boot.json";
|
||||
@@ -33,7 +35,7 @@ let
|
||||
// lib.optionalAttrs config.boot.initrd.enable {
|
||||
initrd = "${config.system.build.initialRamdisk}/${config.system.boot.loader.initrdFile}";
|
||||
}
|
||||
// lib.optionalAttrs hasAtLeastOneInitrdSecret {
|
||||
// lib.optionalAttrs hasInitrdSecrets {
|
||||
initrdSecrets = "${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets";
|
||||
};
|
||||
}
|
||||
|
||||
@@ -99,8 +99,8 @@ in
|
||||
sed -i $out/bin/clevis-decrypt-tpm2 -e 's,tpm2_,tpm2 ,'
|
||||
'';
|
||||
|
||||
secrets = lib.mapAttrs' (
|
||||
name: value: lib.nameValuePair "/etc/clevis/${name}.jwe" value.secretFile
|
||||
secretPaths = lib.mapAttrs' (
|
||||
name: value: lib.nameValuePair "/etc/clevis/${name}.jwe" { source = value.secretFile; }
|
||||
) cfg.devices;
|
||||
|
||||
systemd = {
|
||||
|
||||
@@ -29,7 +29,7 @@ in
|
||||
};
|
||||
|
||||
boot.initrd.network.openvpn.configuration = mkOption {
|
||||
type = types.path; # Same type as boot.initrd.secrets
|
||||
type = types.path; # Same type as boot.initrd.secretPaths.*.source
|
||||
description = ''
|
||||
The configuration file for OpenVPN.
|
||||
|
||||
@@ -74,8 +74,8 @@ in
|
||||
"${pkgs.glibc}/lib/libnss_dns.so.2"
|
||||
];
|
||||
|
||||
boot.initrd.secrets = {
|
||||
"/etc/initrd.ovpn" = cfg.configuration;
|
||||
boot.initrd.secretPaths = {
|
||||
"/etc/initrd.ovpn".source = cfg.configuration;
|
||||
};
|
||||
|
||||
# openvpn --version would exit with 1 instead of 0
|
||||
|
||||
@@ -302,8 +302,8 @@ in
|
||||
fi
|
||||
'';
|
||||
|
||||
boot.initrd.secrets = listToAttrs (
|
||||
map (path: nameValuePair (initrdKeyPath path) path) cfg.hostKeys
|
||||
boot.initrd.secretPaths = listToAttrs (
|
||||
map (path: nameValuePair (initrdKeyPath path) { source = path; }) cfg.hostKeys
|
||||
);
|
||||
|
||||
# Systemd initrd stuff
|
||||
|
||||
@@ -414,7 +414,7 @@ in
|
||||
|
||||
ln -s ${initrdPath} $out/initrd
|
||||
|
||||
${optionalString (config.boot.initrd.secrets != { }) ''
|
||||
${optionalString (config.boot.initrd.secretPaths != { }) ''
|
||||
ln -s ${config.system.build.initialRamdiskSecretAppender}/bin/append-initrd-secrets $out
|
||||
''}
|
||||
|
||||
|
||||
@@ -935,21 +935,21 @@ in
|
||||
'')
|
||||
(mkRemovedOptionModule [ "boot" "loader" "grub" "extraInitrd" ] ''
|
||||
This option has been replaced with the bootloader agnostic
|
||||
boot.initrd.secrets option. To migrate to the initrd secrets system,
|
||||
boot.initrd.secretPaths option. To migrate to the initrd secrets system,
|
||||
extract the extraInitrd archive into your main filesystem:
|
||||
|
||||
# zcat /boot/extra_initramfs.gz | cpio -idvmD /etc/secrets/initrd
|
||||
/path/to/secret1
|
||||
/path/to/secret2
|
||||
|
||||
then replace boot.loader.grub.extraInitrd with boot.initrd.secrets:
|
||||
then replace boot.loader.grub.extraInitrd with boot.initrd.secretPaths:
|
||||
|
||||
boot.initrd.secrets = {
|
||||
"/path/to/secret1" = "/etc/secrets/initrd/path/to/secret1";
|
||||
"/path/to/secret2" = "/etc/secrets/initrd/path/to/secret2";
|
||||
boot.initrd.secretPaths = {
|
||||
"/path/to/secret1".source = "/etc/secrets/initrd/path/to/secret1";
|
||||
"/path/to/secret2".source = "/etc/secrets/initrd/path/to/secret2";
|
||||
};
|
||||
|
||||
See the boot.initrd.secrets option documentation for more information.
|
||||
See the boot.initrd.secretPaths option documentation for more information.
|
||||
'')
|
||||
];
|
||||
|
||||
|
||||
@@ -482,7 +482,7 @@ sub addEntry {
|
||||
die "failed to create initrd secrets $!\n";
|
||||
} else {
|
||||
say STDERR "warning: failed to create initrd secrets for \"$name\", an older generation";
|
||||
say STDERR "note: this is normal after having removed or renamed a file in `boot.initrd.secrets`";
|
||||
say STDERR "note: this is normal after having modified or removed an entry in `boot.initrd.secretPaths`";
|
||||
}
|
||||
}
|
||||
# Check whether any secrets were actually added
|
||||
|
||||
@@ -202,7 +202,7 @@ def write_entry(profile: str | None, generation: int, specialisation: str | None
|
||||
print("warning: failed to create initrd secrets "
|
||||
f'for "{title} - Configuration {generation}", an older generation', file=sys.stderr)
|
||||
print("note: this is normal after having removed "
|
||||
"or renamed a file in `boot.initrd.secrets`", file=sys.stderr)
|
||||
"or modified an entry in `boot.initrd.secretPaths`", file=sys.stderr)
|
||||
entry_file = BOOT_MOUNT_POINT / "loader/entries" / generation_conf_filename(profile, generation, specialisation)
|
||||
tmp_path = entry_file.with_suffix(".tmp")
|
||||
kernel_params = "init=%s " % bootspec.init
|
||||
|
||||
@@ -148,23 +148,22 @@ let
|
||||
# Copy secrets if needed.
|
||||
#
|
||||
# TODO: move out to a separate script; see #85000.
|
||||
${optionalString (!config.boot.loader.supportsInitrdSecrets) (
|
||||
concatStringsSep "\n" (
|
||||
mapAttrsToList (
|
||||
dest: source:
|
||||
let
|
||||
source' = if source == null then dest else source;
|
||||
in
|
||||
''
|
||||
mkdir -p $(dirname "$out/secrets/${dest}")
|
||||
# Some programs (e.g. ssh) doesn't like secrets to be
|
||||
# symlinks, so we use `cp -L` here to match the
|
||||
# behaviour when secrets are natively supported.
|
||||
cp -Lr ${source'} "$out/secrets/${dest}"
|
||||
''
|
||||
) config.boot.initrd.secrets
|
||||
)
|
||||
)}
|
||||
${optionalString (!config.boot.loader.supportsInitrdSecrets) ''
|
||||
${concatStringsSep "\n" (
|
||||
mapAttrsToList (_: scfg: ''
|
||||
mkdir -p $(dirname "$out/secrets${scfg.path}")
|
||||
# Some programs (e.g. ssh) doesn't like secrets to be
|
||||
# symlinks, so we use `cp -L` here to match the
|
||||
# behaviour when secrets are natively supported.
|
||||
# The assertion further up in this file (stage-1.nix)
|
||||
# checks that all secretPaths are Nix store paths set via
|
||||
# boot.initrd.secretPaths.*.source if the bootloader doesn't
|
||||
# support initrd secrets.
|
||||
cp -Lr ${scfg.source} "$out/secrets${scfg.path}"
|
||||
'') config.boot.initrd.secretPaths
|
||||
)}
|
||||
${config.boot.initrd.extraSecretsHook}
|
||||
''}
|
||||
|
||||
${config.boot.initrd.extraUtilsCommands}
|
||||
|
||||
@@ -436,7 +435,9 @@ let
|
||||
exit 0
|
||||
fi
|
||||
|
||||
${lib.optionalString (config.boot.initrd.secrets == { }) "exit 0"}
|
||||
${lib.optionalString (
|
||||
config.boot.initrd.secretPaths == { } && config.boot.initrd.extraSecretsHook == ""
|
||||
) "exit 0"}
|
||||
|
||||
export PATH=${pkgs.coreutils}/bin:${pkgs.cpio}/bin:${pkgs.gzip}/bin:${pkgs.findutils}/bin
|
||||
|
||||
@@ -451,17 +452,25 @@ let
|
||||
|
||||
${lib.concatStringsSep "\n" (
|
||||
mapAttrsToList (
|
||||
dest: source:
|
||||
_: scfg:
|
||||
let
|
||||
source' = if source == null then dest else toString source;
|
||||
prefix = lib.optionalString scfg.intermediateSecretsDir "/.initrd-secrets";
|
||||
in
|
||||
''
|
||||
mkdir -p $(dirname "$tmp/.initrd-secrets/${dest}")
|
||||
cp -a ${source'} "$tmp/.initrd-secrets/${dest}"
|
||||
mkdir -p $(dirname "$tmp${prefix}${scfg.path}")
|
||||
(
|
||||
export out="$tmp${prefix}${scfg.path}"
|
||||
${scfg.generateSecretCommand}
|
||||
)
|
||||
''
|
||||
) config.boot.initrd.secrets
|
||||
) config.boot.initrd.secretPaths
|
||||
)}
|
||||
|
||||
(
|
||||
cd "$tmp"
|
||||
${config.boot.initrd.extraSecretsHook}
|
||||
)
|
||||
|
||||
# mindepth 1 so that we don't change the mode of /
|
||||
(cd "$tmp" && find . -mindepth 1 | xargs touch -amt 197001010000 && find . -mindepth 1 -print0 | sort -z | cpio --quiet -o -H newc -R +0:+0 --reproducible --null) | \
|
||||
${compressorExe} ${lib.escapeShellArgs initialRamdisk.compressorArgs} >> "$1"
|
||||
@@ -650,21 +659,113 @@ in
|
||||
boot.initrd.secrets = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (types.nullOr types.path);
|
||||
visible = false;
|
||||
description = ''
|
||||
Secrets to append to the initrd. The attribute name is the
|
||||
path the secret should have inside the initrd, the value
|
||||
is the path it should be copied from (or null for the same
|
||||
path inside and out).
|
||||
Secrets to append to the initrd. This option has been deprecated in
|
||||
favour of `boot.initrd.secretPaths`.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{ "/etc/dropbear/dropbear_rsa_host_key" =
|
||||
./secret-dropbear-key;
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
boot.initrd.secretPaths = mkOption {
|
||||
default = { };
|
||||
type = types.attrsOf (
|
||||
types.submodule (
|
||||
{ config, name, ... }:
|
||||
{
|
||||
options = {
|
||||
path = mkOption {
|
||||
type = types.path;
|
||||
default = name;
|
||||
description = ''
|
||||
The path the secret should be placed at in the initrd. Defaults
|
||||
to the attribute name.
|
||||
'';
|
||||
};
|
||||
|
||||
intermediateSecretsDir = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = ''
|
||||
By default, the secrets will be copied over to the
|
||||
`/.initrd-secrets` dir at initrd generation time, and then copied
|
||||
over to their final location at boot time. This is because initrd secrets
|
||||
that are supposed to be placed in `/run` would be overridden by
|
||||
the tmpfs mount over `/run` otherwise.
|
||||
|
||||
Set this option to `false` to skip this intermediate step and
|
||||
place the secret at its final location straightaway.
|
||||
'';
|
||||
};
|
||||
|
||||
source = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = ''
|
||||
The absolute path on the filesystem to copy the secret from.
|
||||
'';
|
||||
example = "/var/lib/secrets/initrd/ssh_host_ed25519_key";
|
||||
};
|
||||
|
||||
generateSecretCommand = mkOption {
|
||||
type = types.path;
|
||||
description = ''
|
||||
The command to run to generate the secret. It should write
|
||||
the secret to `$out`.
|
||||
|
||||
This is useful if you have a more advanced secrets provisioning
|
||||
mechanism.
|
||||
'';
|
||||
example = ''
|
||||
pkgs.writeShellScript "generate-secret" '''
|
||||
''${lib.getExe pkgs.age} -d -i /etc/ssh/ssh_host_ed25519_key -o "$out" ''${./secret.age}
|
||||
'''
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
generateSecretCommand = lib.mkIf (config.source != null) (
|
||||
pkgs.writeShellScript "copy-secret" ''
|
||||
cp -Lr ${config.source} "$out"
|
||||
''
|
||||
);
|
||||
};
|
||||
}
|
||||
)
|
||||
);
|
||||
description = ''
|
||||
Secret paths to append to the initrd. The attribute name is the
|
||||
path the secret should have inside the initrd.
|
||||
|
||||
Note that `nixos-rebuild switch` will generate the initrd
|
||||
also for past generations, so if secrets are moved or deleted
|
||||
you will also have to garbage collect the generations that
|
||||
use those secrets.
|
||||
'';
|
||||
example = literalExpression ''
|
||||
{ "/etc/dropbear/dropbear_rsa_host_key" =
|
||||
./secret-dropbear-key;
|
||||
}
|
||||
example = {
|
||||
"/etc/ssh/ssh_host_ed25519_key".source = "/var/lib/secrets/initrd/ssh_host_ed25519_key";
|
||||
};
|
||||
};
|
||||
|
||||
boot.initrd.extraSecretsHook = mkOption {
|
||||
default = "";
|
||||
type = types.lines;
|
||||
description = ''
|
||||
Extra commands to be executed after the initrd secrets generation phase.
|
||||
|
||||
This script should place files into the current workdir. These files
|
||||
will then be copied over to the initrd to the corresponding absolute
|
||||
paths, e.g. `etc/ssh/ssh_host_ed25519_key` will be copied over to
|
||||
`/etc/ssh/ssh_host_ed25519_key`.
|
||||
'';
|
||||
example = ''
|
||||
# Generate a new SSH host key for every generation.
|
||||
ssh-keygen -f etc/ssh/ssh_host_ed25519_key
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -746,15 +847,18 @@ in
|
||||
assertion =
|
||||
!config.boot.loader.supportsInitrdSecrets
|
||||
-> all (
|
||||
source: builtins.isPath source || (builtins.isString source && hasPrefix builtins.storeDir source)
|
||||
) (attrValues config.boot.initrd.secrets);
|
||||
scfg:
|
||||
builtins.isPath scfg.source
|
||||
|| (builtins.isString scfg.source && hasPrefix builtins.storeDir scfg.source)
|
||||
) (attrValues config.boot.initrd.secretPaths);
|
||||
message = ''
|
||||
boot.initrd.secrets values must be unquoted paths when
|
||||
using a bootloader that doesn't natively support initrd
|
||||
secrets, e.g.:
|
||||
When using a bootloader that doesn't natively support initrd secrets,
|
||||
all `boot.initrd.secretPaths` values must be defined via
|
||||
`boot.initrd.secretsPaths.*.source`, and the `source` values must be
|
||||
unquoted paths, e.g.
|
||||
|
||||
boot.initrd.secrets = {
|
||||
"/etc/secret" = /path/to/secret;
|
||||
boot.initrd.secretPaths = {
|
||||
"/etc/secret".source = /path/to/secret;
|
||||
};
|
||||
|
||||
Note that this will result in all secrets being stored
|
||||
@@ -763,6 +867,18 @@ in
|
||||
}
|
||||
];
|
||||
|
||||
warnings = lib.optional (config.boot.initrd.secrets != { }) ''
|
||||
The option `boot.initrd.secrets` has been deprecated in favour of `boot.initrd.secretPaths`.
|
||||
'';
|
||||
|
||||
# Backwards compatibility to the legacy `boot.initrd.secrets` option.
|
||||
boot.initrd.secretPaths = lib.mapAttrs' (dest: source: {
|
||||
# The legacy boot.initrd.secrets option didn't type-check the attr
|
||||
# names, so we need to optionally prepend a slash.
|
||||
name = "${lib.optionalString (!lib.hasPrefix "/" dest) "/"}${dest}";
|
||||
value.source = if dest != null then source else dest;
|
||||
}) config.boot.initrd.secrets;
|
||||
|
||||
system.build = mkMerge [
|
||||
{
|
||||
inherit
|
||||
|
||||
@@ -10,14 +10,21 @@
|
||||
# Copy secrets into the initrd if they cannot be appended
|
||||
boot.initrd.systemd.contents = lib.mkIf (!config.boot.loader.supportsInitrdSecrets) (
|
||||
lib.mapAttrs' (
|
||||
dest: source:
|
||||
lib.nameValuePair "/.initrd-secrets/${dest}" { source = if source == null then dest else source; }
|
||||
) config.boot.initrd.secrets
|
||||
_: scfg:
|
||||
let
|
||||
prefix = lib.optionalString scfg.intermediateSecretsDir "/.initrd-secrets";
|
||||
in
|
||||
lib.nameValuePair "${prefix}${scfg.path}" { inherit (scfg) source; }
|
||||
) config.boot.initrd.secretPaths
|
||||
);
|
||||
|
||||
# Copy secrets to their respective locations
|
||||
boot.initrd.systemd.services.initrd-nixos-copy-secrets =
|
||||
lib.mkIf (config.boot.initrd.secrets != { })
|
||||
lib.mkIf
|
||||
(
|
||||
(builtins.any (x: x.intermediateSecretsDir) (builtins.attrValues config.boot.initrd.secretPaths))
|
||||
|| config.boot.initrd.extraSecretsHook != ""
|
||||
)
|
||||
{
|
||||
description = "Copy secrets into place";
|
||||
# Run as early as possible
|
||||
@@ -34,10 +41,12 @@
|
||||
# drop this service, we'd mount the /run tmpfs over the secret, making it
|
||||
# invisible in stage 2.
|
||||
script = ''
|
||||
for secret in $(cd /.initrd-secrets; find . -type f -o -type l); do
|
||||
mkdir -p "$(dirname "/$secret")"
|
||||
cp "/.initrd-secrets/$secret" "/$secret"
|
||||
done
|
||||
if [ -d /.initrd-secrets ]; then
|
||||
for secret in $(cd /.initrd-secrets; find . -type f -o -type l); do
|
||||
mkdir -p "$(dirname "/$secret")"
|
||||
cp "/.initrd-secrets/$secret" "/$secret"
|
||||
done
|
||||
fi
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
|
||||
@@ -51,7 +51,7 @@ in
|
||||
config = mkMerge [
|
||||
{
|
||||
# minimal configuration file to make lvmconfig/lvm2-activation-generator happy
|
||||
environment.etc."lvm/lvm.conf".text = "config {}";
|
||||
environment.etc."lvm/lvm.conf".text = lib.mkBefore "config {}";
|
||||
}
|
||||
(mkIf cfg.enable {
|
||||
systemd.tmpfiles.packages = [ cfg.package.out ];
|
||||
@@ -59,6 +59,8 @@ in
|
||||
systemd.packages = [ cfg.package ];
|
||||
|
||||
services.udev.packages = [ cfg.package.out ];
|
||||
environment.etc."lvm/lvm.conf".text =
|
||||
"global/lvresize_fs_helper_executable = ${pkgs.lvm2.scripts}/libexec/lvresize_fs_helper";
|
||||
})
|
||||
(mkIf config.boot.initrd.services.lvm.enable {
|
||||
# We need lvm2 for the device-mapper rules
|
||||
@@ -71,9 +73,7 @@ in
|
||||
systemd.sockets."dm-event".wantedBy = [ "sockets.target" ];
|
||||
systemd.services."lvm2-monitor".wantedBy = [ "sysinit.target" ];
|
||||
|
||||
environment.etc."lvm/lvm.conf".text = ''
|
||||
dmeventd/executable = "${cfg.package}/bin/dmeventd"
|
||||
'';
|
||||
environment.etc."lvm/lvm.conf".text = "dmeventd/executable = ${cfg.package}/bin/dmeventd";
|
||||
services.lvm.package = mkDefault pkgs.lvm2_dmeventd;
|
||||
})
|
||||
(mkIf cfg.boot.thin.enable {
|
||||
|
||||
@@ -128,7 +128,7 @@ in
|
||||
environment.systemPackages = [ pkgs.jq ];
|
||||
# It's probably the case, but we want to make it explicit here.
|
||||
boot.initrd.enable = true;
|
||||
boot.initrd.secrets."/some/example" = pkgs.writeText "example-secret" "test";
|
||||
boot.initrd.secretPaths."/some/example".source = pkgs.writeText "example-secret" "test";
|
||||
};
|
||||
|
||||
testScript = ''
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
|
||||
|
||||
@contextmanager
|
||||
def record_audio(machine: Machine):
|
||||
def record_audio(machine: BaseMachine):
|
||||
"""
|
||||
Perform actions while recording the
|
||||
machine audio output.
|
||||
@@ -56,7 +56,7 @@
|
||||
machine.systemctl("stop audio-recorder")
|
||||
|
||||
|
||||
def wait_for_sound(machine: Machine):
|
||||
def wait_for_sound(machine: BaseMachine):
|
||||
"""
|
||||
Wait until any sound has been emitted.
|
||||
"""
|
||||
|
||||
@@ -47,7 +47,7 @@ in
|
||||
};
|
||||
};
|
||||
virtualisation.rootDevice = "/dev/mapper/cryptroot";
|
||||
boot.initrd.secrets."/etc/cryptroot.key" = keyfile;
|
||||
boot.initrd.secretPaths."/etc/cryptroot.key".source = keyfile;
|
||||
};
|
||||
|
||||
specialisation.boot-luks-missing-keyfile.configuration = {
|
||||
|
||||
@@ -21,16 +21,16 @@ testing.makeTest {
|
||||
|
||||
boot.loader.grub.device = "/dev/vda";
|
||||
|
||||
boot.initrd.secrets = {
|
||||
"/test" = secret1InStore;
|
||||
"/run/keys/test" = secret1InStore;
|
||||
boot.initrd.secretPaths = {
|
||||
"/test".source = secret1InStore;
|
||||
"/run/keys/test".source = secret1InStore;
|
||||
};
|
||||
boot.initrd.postMountCommands = "cp /test /mnt-root/secret-from-initramfs";
|
||||
|
||||
specialisation.secrets2System.configuration = {
|
||||
boot.initrd.secrets = lib.mkForce {
|
||||
"/test" = secret2InStore;
|
||||
"/run/keys/test" = secret2InStore;
|
||||
boot.initrd.secretPaths = lib.mkForce {
|
||||
"/test".source = secret2InStore;
|
||||
"/run/keys/test".source = secret2InStore;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -21,14 +21,26 @@ let
|
||||
{ ... }:
|
||||
{
|
||||
virtualisation.useBootLoader = true;
|
||||
boot.initrd.secrets = {
|
||||
"/test" = secretInStore;
|
||||
boot.initrd.secretPaths = {
|
||||
"/test" = {
|
||||
source = secretInStore;
|
||||
intermediateSecretsDir = false;
|
||||
};
|
||||
|
||||
# This should *not* need to be copied in postMountCommands
|
||||
"/run/keys/test" = secretInStore;
|
||||
"/run/keys/test1".source = secretInStore;
|
||||
|
||||
"/run/keys/test2".generateSecretCommand = pkgs.writeShellScript "copy-secret" ''
|
||||
cp ${secretInStore} "$out"
|
||||
'';
|
||||
};
|
||||
boot.initrd.extraSecretsHook = ''
|
||||
mkdir -p etc/secrets
|
||||
cp ${secretInStore} etc/secrets/test2
|
||||
'';
|
||||
boot.initrd.postMountCommands = ''
|
||||
cp /test /mnt-root/secret-from-initramfs
|
||||
cp /test /mnt-root/secret-from-initramfs-1
|
||||
cp /etc/secrets/test2 /mnt-root/secret-from-initramfs-2
|
||||
'';
|
||||
boot.initrd.compressor = compressor;
|
||||
# zstd compression is only supported from 5.9 onwards. Remove when 5.10 becomes default.
|
||||
@@ -39,8 +51,10 @@ let
|
||||
start_all()
|
||||
machine.wait_for_unit("multi-user.target")
|
||||
machine.succeed(
|
||||
"cmp ${secretInStore} /secret-from-initramfs",
|
||||
"cmp ${secretInStore} /run/keys/test",
|
||||
"cmp ${secretInStore} /secret-from-initramfs-1",
|
||||
"cmp ${secretInStore} /secret-from-initramfs-2",
|
||||
"cmp ${secretInStore} /run/keys/test1",
|
||||
"cmp ${secretInStore} /run/keys/test2",
|
||||
)
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -67,7 +67,7 @@ let
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
''}
|
||||
|
||||
boot.initrd.secrets."/etc/secret" = "/etc/nixos/secret";
|
||||
boot.initrd.secretPaths."/etc/secret".source = "/etc/nixos/secret";
|
||||
|
||||
${optionalString clevisTest ''
|
||||
boot.kernelParams = [ "console=tty0" "ip=192.168.1.1:::255.255.255.0::eth1:none" ];
|
||||
@@ -1385,7 +1385,7 @@ in
|
||||
};
|
||||
|
||||
# Full disk encryption (root, kernel and initrd encrypted) using GRUB, GPT/UEFI,
|
||||
# LVM-on-LUKS and a keyfile in initrd.secrets to enter the passphrase once
|
||||
# LVM-on-LUKS and a keyfile in initrd.secretPaths to enter the passphrase once
|
||||
fullDiskEncryption = makeInstallerTest "fullDiskEncryption" {
|
||||
createPartitions = ''
|
||||
installer.succeed(
|
||||
@@ -1419,7 +1419,7 @@ in
|
||||
boot.loader.grub.enableCryptodisk = true;
|
||||
boot.loader.efi.efiSysMountPoint = "/boot/efi";
|
||||
|
||||
boot.initrd.secrets."/luks.key" = "/etc/nixos/luks.key";
|
||||
boot.initrd.secretPaths."/luks.key" = "/etc/nixos/luks.key";
|
||||
boot.initrd.luks.devices.crypt =
|
||||
{ device = "/dev/vda2";
|
||||
keyFile = "/luks.key";
|
||||
|
||||
@@ -19,9 +19,12 @@ in
|
||||
meta.maintainers = with lib.maintainers; [ defelo ];
|
||||
|
||||
nodes.seed = {
|
||||
virtualisation.credentials = {
|
||||
"xyz.radicle.node.secret".source = "${seed-ssh-keys.snakeOilEd25519PrivateKey}";
|
||||
};
|
||||
|
||||
services.radicle = {
|
||||
enable = true;
|
||||
privateKeyFile = seed-ssh-keys.snakeOilEd25519PrivateKey;
|
||||
publicKey = seed-ssh-keys.snakeOilEd25519PublicKey;
|
||||
node.openFirewall = true;
|
||||
settings = {
|
||||
|
||||
@@ -76,9 +76,12 @@ in
|
||||
{
|
||||
imports = [ commonHostConfig ];
|
||||
|
||||
virtualisation.credentials = {
|
||||
"xyz.radicle.node.secret".source = "${seed-ssh-keys.snakeOilEd25519PrivateKey}";
|
||||
};
|
||||
|
||||
services.radicle = {
|
||||
enable = true;
|
||||
privateKeyFile = seed-ssh-keys.snakeOilEd25519PrivateKey;
|
||||
publicKey = seed-ssh-keys.snakeOilEd25519PublicKey;
|
||||
node = {
|
||||
openFirewall = true;
|
||||
|
||||
@@ -38,7 +38,7 @@ in
|
||||
};
|
||||
};
|
||||
virtualisation.rootDevice = "/dev/mapper/cryptroot";
|
||||
boot.initrd.secrets."/etc/cryptroot.key" = keyfile;
|
||||
boot.initrd.secretPaths."/etc/cryptroot.key".source = keyfile;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
autoreconfHook,
|
||||
automake,
|
||||
fftw,
|
||||
ladspaH,
|
||||
ladspa-header,
|
||||
libxml2,
|
||||
pkg-config,
|
||||
perlPackages,
|
||||
@@ -41,7 +41,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
];
|
||||
buildInputs = [
|
||||
fftw
|
||||
ladspaH
|
||||
ladspa-header
|
||||
libxml2
|
||||
];
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
ntk,
|
||||
libjack2,
|
||||
libsndfile,
|
||||
ladspaH,
|
||||
ladspa-header,
|
||||
liblo,
|
||||
libsigcxx,
|
||||
lrdf,
|
||||
@@ -37,7 +37,7 @@ stdenv.mkDerivation {
|
||||
ntk
|
||||
libjack2
|
||||
libsndfile
|
||||
ladspaH
|
||||
ladspa-header
|
||||
liblo
|
||||
libsigcxx
|
||||
lrdf
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
alsa-lib,
|
||||
dssiSupport ? false,
|
||||
dssi,
|
||||
ladspaH,
|
||||
ladspa-header,
|
||||
jackSupport ? true,
|
||||
libjack2,
|
||||
ossSupport ? true,
|
||||
@@ -108,7 +108,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
++ lib.optionals alsaSupport [ alsa-lib ]
|
||||
++ lib.optionals dssiSupport [
|
||||
dssi
|
||||
ladspaH
|
||||
ladspa-header
|
||||
]
|
||||
++ lib.optionals jackSupport [ libjack2 ]
|
||||
++ lib.optionals portaudioSupport [ portaudio ]
|
||||
|
||||
@@ -8,8 +8,8 @@ vscode-utils.buildVscodeMarketplaceExtension {
|
||||
mktplcRef = {
|
||||
name = "claude-code";
|
||||
publisher = "anthropic";
|
||||
version = "2.1.78";
|
||||
hash = "sha256-A8i7yU4W8Fjp1h7EFZKAEdyoqoKBVzJDvEZ+Y06dBXg=";
|
||||
version = "2.1.79";
|
||||
hash = "sha256-vQuSSpBcvd7XRTeprk8sMZmdRU6JiwPSmIQyBs94I5M=";
|
||||
};
|
||||
|
||||
postInstall = ''
|
||||
|
||||
@@ -7,8 +7,8 @@ vscode-utils.buildVscodeMarketplaceExtension {
|
||||
mktplcRef = {
|
||||
name = "jjk";
|
||||
publisher = "jjk";
|
||||
version = "0.9.1";
|
||||
hash = "sha256-7CK2fmYVAd12kLTnq3vwDmgL22Tmi9Ljt9+tpXqRWuo=";
|
||||
version = "0.9.3";
|
||||
hash = "sha256-wkHMZTLi3dDV6JQdfJ4hI5uwGAlCmKwg+v8Z9RMU1wU=";
|
||||
};
|
||||
meta = {
|
||||
changelog = "https://github.com/keanemind/jjk/releases";
|
||||
|
||||
@@ -1,80 +1,25 @@
|
||||
{
|
||||
lib,
|
||||
stdenvNoCC,
|
||||
fetchFromGitHub,
|
||||
pnpm,
|
||||
fetchPnpmDeps,
|
||||
pnpmConfigHook,
|
||||
nodejs,
|
||||
vscode-utils,
|
||||
nix-update-script,
|
||||
vscode-extension-update-script,
|
||||
}:
|
||||
|
||||
let
|
||||
vsix = stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
name = "kilo-code-${finalAttrs.version}.vsix";
|
||||
pname = "kilo-code-vsix";
|
||||
version = "4.124.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "Kilo-Org";
|
||||
repo = "kilocode";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-Dy0dd07pWsSbrO6BX7GEYf7CunXD0itaeIFRv9mQJks=";
|
||||
};
|
||||
|
||||
pnpmDeps = fetchPnpmDeps {
|
||||
inherit (finalAttrs) pname version src;
|
||||
fetcherVersion = 2;
|
||||
hash = "sha256-hxgzmJD+Sl7E+ape1M1/Xl8XLtAhtht3AE45zHFctsQ=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
nodejs
|
||||
pnpmConfigHook
|
||||
pnpm
|
||||
];
|
||||
|
||||
buildPhase = ''
|
||||
runHook preBuild
|
||||
|
||||
node --run build
|
||||
|
||||
runHook postBuild
|
||||
'';
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
cp ./bin/kilo-code-$version.vsix $out
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
});
|
||||
in
|
||||
vscode-utils.buildVscodeExtension (finalAttrs: {
|
||||
pname = "kilo-code";
|
||||
inherit (finalAttrs.src) version;
|
||||
|
||||
vscodeExtPublisher = "kilocode";
|
||||
vscodeExtName = "Kilo-Code";
|
||||
vscodeExtUniqueId = "${finalAttrs.vscodeExtPublisher}.${finalAttrs.vscodeExtName}";
|
||||
|
||||
src = vsix;
|
||||
|
||||
passthru = {
|
||||
vsix = finalAttrs.src;
|
||||
updateScript = nix-update-script {
|
||||
attrPath = "vscode-extensions.kilocode.kilo-kode.vsix";
|
||||
};
|
||||
vscode-utils.buildVscodeMarketplaceExtension {
|
||||
mktplcRef = {
|
||||
publisher = "kilocode";
|
||||
name = "Kilo-Code";
|
||||
version = "7.0.51";
|
||||
hash = "sha256-1NzwFTFM1gkTcrAVbP6wNctePMAGdy2T9UDn24xhixM=";
|
||||
};
|
||||
|
||||
passthru.updateScript = vscode-extension-update-script { };
|
||||
|
||||
meta = {
|
||||
description = "Open Source AI coding assistant for planning, building, and fixing code";
|
||||
homepage = "https://kilocode.ai";
|
||||
homepage = "https://kilo.ai";
|
||||
downloadPage = "https://marketplace.visualstudio.com/items?itemName=kilocode.Kilo-Code";
|
||||
license = lib.licenses.asl20;
|
||||
license = lib.licenses.mit;
|
||||
sourceProvenance = with lib.sourceTypes; [ fromSource ];
|
||||
maintainers = with lib.maintainers; [ xiaoxiangmoe ];
|
||||
};
|
||||
})
|
||||
}
|
||||
|
||||
@@ -10,8 +10,8 @@ vscode-utils.buildVscodeMarketplaceExtension {
|
||||
mktplcRef = {
|
||||
publisher = "ms-azuretools";
|
||||
name = "vscode-bicep";
|
||||
version = "0.38.33";
|
||||
hash = "sha256-gmSUPHdbxXu5jUASsbu+yVO2ZdVBo5+uQNeLdTsvQVU=";
|
||||
version = "0.41.2";
|
||||
hash = "sha256-8k2de208t/ZAVJzxkjd0qcqgVx523hEWWe5d1uvthFU=";
|
||||
};
|
||||
|
||||
buildInputs = [
|
||||
|
||||
@@ -14,8 +14,8 @@ vscode-utils.buildVscodeMarketplaceExtension {
|
||||
mktplcRef = {
|
||||
name = "r";
|
||||
publisher = "reditorsupport";
|
||||
version = "2.8.6";
|
||||
hash = "sha256-T/Qh0WfTfXMzPonbg9NMII5qFptfNoApFFiZCT5rR3Y=";
|
||||
version = "2.8.7";
|
||||
hash = "sha256-pA3/81UYrieDfGYn1fVI6KY9B7A5KAhGIzftZtzXQVc=";
|
||||
};
|
||||
nativeBuildInputs = [
|
||||
jq
|
||||
|
||||
@@ -10,8 +10,8 @@ vscode-utils.buildVscodeMarketplaceExtension {
|
||||
mktplcRef = {
|
||||
name = "wgsl-analyzer";
|
||||
publisher = "wgsl-analyzer";
|
||||
version = "0.11.141";
|
||||
hash = "sha256-egd9B5mS5pqzDWVry3dEQKfnxT4zI0RdLMJ/x5n6Nek=";
|
||||
version = "0.11.262";
|
||||
hash = "sha256-a2TVwTmxP9wBt0tMkQcVCyzM0RoihGag56ITd+xjtl8=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -5,13 +5,13 @@
|
||||
}:
|
||||
mkLibretroCore {
|
||||
core = "fbneo";
|
||||
version = "0-unstable-2026-03-08";
|
||||
version = "0-unstable-2026-03-17";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "libretro";
|
||||
repo = "fbneo";
|
||||
rev = "14ff80a2e0611d039321a3ac0dd76bf6b4e3210f";
|
||||
hash = "sha256-L6KYyEb95L9rDnaMVh49afaWxsshTy3eujsTQWbPfl0=";
|
||||
rev = "baafb100b487f2ac06f9e78ac322e3ecf36b8924";
|
||||
hash = "sha256-46hVbQN8QO1FNm56wJ7Q323blUWV9sn529tMwdAOhW8=";
|
||||
};
|
||||
|
||||
makefile = "Makefile";
|
||||
|
||||
@@ -174,7 +174,7 @@ stdenv.mkDerivation (
|
||||
++ lib.optional cupsSupport pkgs.cups
|
||||
++ lib.optional dbusSupport pkgs.dbus
|
||||
++ lib.optional cairoSupport pkgs.cairo
|
||||
++ lib.optional odbcSupport pkgs.unixODBC
|
||||
++ lib.optional odbcSupport pkgs.unixodbc
|
||||
++ lib.optional netapiSupport pkgs.samba4
|
||||
++ lib.optional cursesSupport pkgs.ncurses
|
||||
++ lib.optional vaSupport pkgs.libva
|
||||
|
||||
@@ -758,6 +758,10 @@ let
|
||||
${ungoogler}/utils/domain_substitution.py apply -r ${ungoogler}/domain_regex.list -f ${ungoogler}/domain_substitution.list -c ./ungoogled-domsubcache.tar.gz .
|
||||
'';
|
||||
|
||||
# Sadly, Chromium is not even -fstrict-flex-array=1 clean
|
||||
# See https://github.com/NixOS/nixpkgs/issues/499982#issuecomment-4062355720
|
||||
hardeningDisable = [ "strictflexarrays1" ];
|
||||
|
||||
llvmCcAndBintools = symlinkJoin {
|
||||
name = "llvmCcAndBintools";
|
||||
paths = [
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
{
|
||||
lib,
|
||||
buildGoModule,
|
||||
buildGo124Module,
|
||||
buildGo125Module,
|
||||
fetchFromGitHub,
|
||||
nixosTests,
|
||||
@@ -96,7 +95,7 @@ rec {
|
||||
};
|
||||
|
||||
nomad_1_10 = generic {
|
||||
buildGoModule = buildGo124Module;
|
||||
buildGoModule = buildGo125Module;
|
||||
version = "1.10.5";
|
||||
hash = "sha256-NFH++oYWb6vQN6cOPByscI/ZBWDNy4YbcLiBMO3/jVU=";
|
||||
vendorHash = "sha256-QcTw9kKwoHIvXZoxfDohFG+sBs8OLvYPeygygDClsn8=";
|
||||
@@ -108,7 +107,7 @@ rec {
|
||||
};
|
||||
|
||||
nomad_1_9 = generic {
|
||||
buildGoModule = buildGo124Module;
|
||||
buildGoModule = buildGo125Module;
|
||||
version = "1.9.7";
|
||||
hash = "sha256-U02H6DPr1friQ9EwqD/wQnE2Fm20OE5xNccPDJfnsqI=";
|
||||
vendorHash = "sha256-9GnwqkexJAxrhW9yJFaDTdSaZ+p+/dcMuhlusp4cmyw=";
|
||||
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
diff --git a/src/api/video/nv12_buffer.cc b/src/api/video/nv12_buffer.cc
|
||||
index ca9dcd867..89d28f23c 100644
|
||||
--- a/src/api/video/nv12_buffer.cc
|
||||
+++ b/src/api/video/nv12_buffer.cc
|
||||
@@ -16,6 +16,8 @@
|
||||
#include "third_party/libyuv/include/libyuv/convert.h"
|
||||
#include "third_party/libyuv/include/libyuv/scale.h"
|
||||
|
||||
+#include <cstring>
|
||||
+
|
||||
namespace webrtc {
|
||||
|
||||
namespace {
|
||||
diff --git a/src/audio/utility/channel_mixer.cc b/src/audio/utility/channel_mixer.cc
|
||||
index 0f1e66387..33b771b0c 100644
|
||||
--- a/src/audio/utility/channel_mixer.cc
|
||||
+++ b/src/audio/utility/channel_mixer.cc
|
||||
@@ -15,6 +15,8 @@
|
||||
#include "rtc_base/logging.h"
|
||||
#include "rtc_base/numerics/safe_conversions.h"
|
||||
|
||||
+#include <cstring>
|
||||
+
|
||||
namespace webrtc {
|
||||
|
||||
ChannelMixer::ChannelMixer(ChannelLayout input_layout,
|
||||
diff --git a/src/modules/audio_processing/aec3/alignment_mixer.cc b/src/modules/audio_processing/aec3/alignment_mixer.cc
|
||||
index 7f076dea8..ffd7242b5 100644
|
||||
--- a/src/modules/audio_processing/aec3/alignment_mixer.cc
|
||||
+++ b/src/modules/audio_processing/aec3/alignment_mixer.cc
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "modules/audio_processing/aec3/alignment_mixer.h"
|
||||
|
||||
#include <algorithm>
|
||||
+#include <cstring>
|
||||
|
||||
#include "rtc_base/checks.h"
|
||||
|
||||
diff --git a/src/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc b/src/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
|
||||
index 7ef1a030e..5b9ab7137 100644
|
||||
--- a/src/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
|
||||
+++ b/src/modules/desktop_capture/linux/wayland/shared_screencast_stream.cc
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <spa/param/video/format-utils.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
+#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include "absl/memory/memory.h"
|
||||
diff --git a/src/modules/video_coding/utility/ivf_file_reader.cc b/src/modules/video_coding/utility/ivf_file_reader.cc
|
||||
index 4c08ca613..f82f2bfcb 100644
|
||||
--- a/src/modules/video_coding/utility/ivf_file_reader.cc
|
||||
+++ b/src/modules/video_coding/utility/ivf_file_reader.cc
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include "modules/video_coding/utility/ivf_file_reader.h"
|
||||
|
||||
+#include <cstring>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
diff --git a/src/net/dcsctp/packet/bounded_byte_writer.h b/src/net/dcsctp/packet/bounded_byte_writer.h
|
||||
index d754549e4..bf5e3ed42 100644
|
||||
--- a/src/net/dcsctp/packet/bounded_byte_writer.h
|
||||
+++ b/src/net/dcsctp/packet/bounded_byte_writer.h
|
||||
@@ -12,6 +12,7 @@
|
||||
#define NET_DCSCTP_PACKET_BOUNDED_BYTE_WRITER_H_
|
||||
|
||||
#include <algorithm>
|
||||
+#include <cstring>
|
||||
|
||||
#include "api/array_view.h"
|
||||
|
||||
@@ -47,6 +47,9 @@ stdenv.mkDerivation {
|
||||
# fix build with abseil 202508
|
||||
# upstream PR: https://github.com/desktop-app/tg_owt/pull/164
|
||||
./abseil-202508.patch
|
||||
# fix build with latest glibc
|
||||
# upstream PR: https://github.com/desktop-app/tg_owt/pull/172
|
||||
./cstring-includes.patch
|
||||
];
|
||||
|
||||
postPatch = lib.optionalString stdenv.hostPlatform.isLinux ''
|
||||
|
||||
+2
-2
@@ -19,7 +19,7 @@
|
||||
ffmpeg_6,
|
||||
protobuf,
|
||||
openal-soft,
|
||||
minizip,
|
||||
minizip-ng,
|
||||
range-v3,
|
||||
tl-expected,
|
||||
hunspell,
|
||||
@@ -74,7 +74,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
xxHash
|
||||
ffmpeg_6
|
||||
openal-soft
|
||||
minizip
|
||||
minizip-ng
|
||||
range-v3
|
||||
tl-expected
|
||||
rnnoise
|
||||
|
||||
@@ -77,7 +77,7 @@
|
||||
clucene-core_2,
|
||||
libcdr,
|
||||
lcms2,
|
||||
unixODBC,
|
||||
unixodbc,
|
||||
sane-backends,
|
||||
mythes,
|
||||
libexttextcat,
|
||||
@@ -481,7 +481,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
libpq
|
||||
python3
|
||||
sane-backends
|
||||
unixODBC
|
||||
unixodbc
|
||||
util-linux
|
||||
which
|
||||
xmlsec
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
libsecret,
|
||||
openjdk,
|
||||
sqlite,
|
||||
unixODBC,
|
||||
unixodbc,
|
||||
gtk2,
|
||||
libxtst,
|
||||
glibcLocales,
|
||||
@@ -57,7 +57,7 @@ stdenv.mkDerivation rec {
|
||||
gsettings-desktop-schemas
|
||||
gtk2
|
||||
sqlite
|
||||
unixODBC
|
||||
unixodbc
|
||||
libxtst
|
||||
glibcLocales
|
||||
];
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
ncurses,
|
||||
opencv4,
|
||||
openssl,
|
||||
unixODBC,
|
||||
unixodbc,
|
||||
xkeyboard_config,
|
||||
libxtst,
|
||||
libxrender,
|
||||
@@ -69,7 +69,7 @@ stdenv.mkDerivation rec {
|
||||
opencv4
|
||||
openssl
|
||||
(lib.getLib stdenv.cc.cc)
|
||||
unixODBC
|
||||
unixodbc
|
||||
xkeyboard_config
|
||||
libxml2
|
||||
libuuid
|
||||
|
||||
@@ -49,12 +49,12 @@
|
||||
"format"
|
||||
"fortify"
|
||||
"fortify3"
|
||||
"libcxxhardeningextensive"
|
||||
"libcxxhardeningfast"
|
||||
"pic"
|
||||
"relro"
|
||||
"stackclashprotection"
|
||||
"stackprotector"
|
||||
"strictflexarrays1"
|
||||
"strictoverflow"
|
||||
"zerocallusedregs"
|
||||
],
|
||||
|
||||
Executable → Regular
@@ -11,6 +11,36 @@ use std::{
|
||||
};
|
||||
use url::Url;
|
||||
|
||||
fn warn_unresolved_packages(
|
||||
packages_without_resolved: &[(String, Package)],
|
||||
total_count: usize,
|
||||
) {
|
||||
let missing_count = packages_without_resolved.len();
|
||||
if missing_count == 0 {
|
||||
return;
|
||||
}
|
||||
|
||||
let percentage = (missing_count as f64 / total_count as f64) * 100.0;
|
||||
eprintln!(
|
||||
"warning: {} out of {} packages ({:.1}%) are missing 'resolved' URLs and will not be cached.",
|
||||
missing_count, total_count, percentage
|
||||
);
|
||||
eprintln!("warning: Packages without 'resolved' URLs:");
|
||||
for (name, _) in packages_without_resolved.iter().take(10) {
|
||||
eprintln!("warning: - {}", name.trim_start_matches("node_modules/"));
|
||||
}
|
||||
if missing_count > 10 {
|
||||
eprintln!("warning: ... and {} more", missing_count - 10);
|
||||
}
|
||||
if percentage > 50.0 {
|
||||
eprintln!(
|
||||
"warning: More than 50% of packages are missing 'resolved' URLs. This may indicate an issue with the lockfile.\n\
|
||||
warning: This is a known issue with some npm versions. See: https://github.com/npm/cli/issues/6301\n\
|
||||
warning: Consider regenerating upstream's lockfile with: npm install --package-lock-only (sending an upstream PR is best)"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn packages(content: &str) -> anyhow::Result<Vec<Package>> {
|
||||
let lockfile: Lockfile = serde_json::from_str(content)?;
|
||||
|
||||
@@ -20,18 +50,27 @@ pub(super) fn packages(content: &str) -> anyhow::Result<Vec<Package>> {
|
||||
|
||||
to_new_packages(lockfile.dependencies.unwrap_or_default(), &initial_url)?
|
||||
}
|
||||
2 | 3 => lockfile
|
||||
.packages
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter(|(n, p)| !n.is_empty() && matches!(p.resolved, Some(UrlOrString::Url(_))))
|
||||
.map(|(n, p)| Package {
|
||||
// Use the package's own name if present (for aliases like string-width-cjs -> string-width),
|
||||
// otherwise extract from the lockfile key
|
||||
name: Some(p.name.unwrap_or(n)),
|
||||
..p
|
||||
})
|
||||
.collect(),
|
||||
2 | 3 => {
|
||||
let (packages_with_resolved, packages_without_resolved): (Vec<_>, Vec<_>) = lockfile
|
||||
.packages
|
||||
.unwrap_or_default()
|
||||
.into_iter()
|
||||
.filter(|(n, _)| !n.is_empty())
|
||||
.partition(|(_, p)| matches!(p.resolved, Some(UrlOrString::Url(_))));
|
||||
|
||||
let total_count = packages_with_resolved.len() + packages_without_resolved.len();
|
||||
warn_unresolved_packages(&packages_without_resolved, total_count);
|
||||
|
||||
packages_with_resolved
|
||||
.into_iter()
|
||||
.map(|(n, p)| Package {
|
||||
// Use the package's own name if present (for aliases like string-width-cjs -> string-width),
|
||||
// otherwise extract from the lockfile key
|
||||
name: Some(p.name.unwrap_or(n)),
|
||||
..p
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
_ => bail!(
|
||||
"We don't support lockfile version {}, please file an issue.",
|
||||
lockfile.version
|
||||
|
||||
@@ -13,6 +13,7 @@ from typing import Any, TypedDict, cast
|
||||
from urllib.parse import unquote
|
||||
|
||||
import requests
|
||||
import tomli_w
|
||||
from requests.adapters import HTTPAdapter, Retry
|
||||
|
||||
eprint = functools.partial(print, file=sys.stderr)
|
||||
@@ -172,8 +173,12 @@ def get_manifest_metadata(manifest_path: Path) -> dict[str, Any]:
|
||||
return json.loads(output)
|
||||
|
||||
|
||||
def try_get_crate_manifest_path_from_mainfest_path(manifest_path: Path, crate_name: str) -> Path | None:
|
||||
metadata = get_manifest_metadata(manifest_path)
|
||||
def try_get_crate_manifest_path_from_manifest_path(manifest_path: Path, crate_name: str) -> Path | None:
|
||||
try:
|
||||
metadata = get_manifest_metadata(manifest_path)
|
||||
except subprocess.CalledProcessError:
|
||||
eprint(f"Warning: cargo metadata failed for {manifest_path}, skipping")
|
||||
return None
|
||||
|
||||
for pkg in metadata["packages"]:
|
||||
if pkg["name"] == crate_name:
|
||||
@@ -183,11 +188,15 @@ def try_get_crate_manifest_path_from_mainfest_path(manifest_path: Path, crate_na
|
||||
|
||||
|
||||
def find_crate_manifest_in_tree(tree: Path, crate_name: str) -> Path:
|
||||
# in some cases Cargo.toml is not located at the top level, so we also look at subdirectories
|
||||
manifest_paths = tree.glob("**/Cargo.toml")
|
||||
# Scan all Cargo.toml files; sort by depth/path to make ordering deterministic
|
||||
# and prefer less-nested manifests first.
|
||||
manifest_paths = sorted(
|
||||
tree.glob("**/Cargo.toml"),
|
||||
key=lambda path: (len(path.parts), str(path)),
|
||||
)
|
||||
|
||||
for manifest_path in manifest_paths:
|
||||
res = try_get_crate_manifest_path_from_mainfest_path(manifest_path, crate_name)
|
||||
res = try_get_crate_manifest_path_from_manifest_path(manifest_path, crate_name)
|
||||
if res is not None:
|
||||
return res
|
||||
|
||||
@@ -256,6 +265,21 @@ def extract_crate_tarball_contents(tarball_path: Path, crate_out_dir: Path) -> N
|
||||
subprocess.check_output(cmd)
|
||||
|
||||
|
||||
def make_git_source_selector(source_info: GitSourceInfo) -> dict[str, str]:
|
||||
selector = {}
|
||||
selector["git"] = source_info["url"]
|
||||
if source_info["type"] is not None:
|
||||
selector[source_info["type"]] = source_info["value"]
|
||||
return selector
|
||||
|
||||
|
||||
def make_registry_source_selector(source: str) -> dict[str, str]:
|
||||
registry = source[9:] if source.startswith("registry+") else source
|
||||
selector = {}
|
||||
selector["registry"] = registry
|
||||
return selector
|
||||
|
||||
|
||||
def create_vendor(vendor_staging_dir: Path, out_dir: Path) -> None:
|
||||
lockfile_path = vendor_staging_dir / "Cargo.lock"
|
||||
out_dir.mkdir(exist_ok=True)
|
||||
@@ -264,14 +288,67 @@ def create_vendor(vendor_staging_dir: Path, out_dir: Path) -> None:
|
||||
cargo_lock_toml = load_toml(lockfile_path)
|
||||
lockfile_version = get_lockfile_version(cargo_lock_toml)
|
||||
|
||||
config_lines = [
|
||||
'[source.vendored-sources]',
|
||||
'directory = "@vendor@"',
|
||||
'[source.crates-io]',
|
||||
'replace-with = "vendored-sources"',
|
||||
]
|
||||
source_to_ind: dict[str, str] = {}
|
||||
source_config = {}
|
||||
next_registry_ind = 0
|
||||
next_git_ind = 0
|
||||
|
||||
def add_source_replacement(
|
||||
orig_key: str,
|
||||
orig_selector: dict[str, str],
|
||||
vendored_key: str,
|
||||
vendored_dir: str
|
||||
) -> None:
|
||||
source_config[vendored_key] = {}
|
||||
source_config[vendored_key]["directory"] = vendored_dir
|
||||
source_config[orig_key] = orig_selector
|
||||
source_config[orig_key]["replace-with"] = vendored_key
|
||||
|
||||
# we reserve registry index 0 for crates-io
|
||||
source_to_ind["registry+https://github.com/rust-lang/crates.io-index"] = "registry-0"
|
||||
source_to_ind["sparse+https://index.crates.io/"] = "registry-0"
|
||||
add_source_replacement(
|
||||
orig_key="crates-io",
|
||||
orig_selector={}, # there is an internal selector defined for the `crates-io` source
|
||||
vendored_key="vendored-source-registry-0",
|
||||
vendored_dir="@vendor@/source-registry-0"
|
||||
)
|
||||
next_registry_ind += 1
|
||||
|
||||
for pkg in cargo_lock_toml["package"]:
|
||||
# ignore local dependencies
|
||||
if "source" not in pkg.keys():
|
||||
continue
|
||||
source: str = pkg["source"]
|
||||
if source in source_to_ind:
|
||||
continue
|
||||
|
||||
if source.startswith("git+"):
|
||||
ind = f"git-{next_git_ind}"
|
||||
next_git_ind += 1
|
||||
source_info = parse_git_source(source, lockfile_version)
|
||||
selector = make_git_source_selector(source_info)
|
||||
elif source.startswith("registry+") or source.startswith("sparse+"):
|
||||
ind = f"registry-{next_registry_ind}"
|
||||
next_registry_ind += 1
|
||||
selector = make_registry_source_selector(source)
|
||||
else:
|
||||
raise Exception(f"Can't process source: {source}.")
|
||||
|
||||
source_to_ind[source] = ind
|
||||
add_source_replacement(
|
||||
orig_key=f"original-source-{ind}",
|
||||
orig_selector=selector,
|
||||
vendored_key=f"vendored-source-{ind}",
|
||||
vendored_dir=f"@vendor@/source-{ind}"
|
||||
)
|
||||
|
||||
config_path = out_dir / ".cargo" / "config.toml"
|
||||
config_path.parent.mkdir()
|
||||
|
||||
with open(config_path, "wb") as config_file:
|
||||
tomli_w.dump({"source": source_config}, config_file)
|
||||
|
||||
seen_source_keys = set()
|
||||
for pkg in cargo_lock_toml["package"]:
|
||||
|
||||
# ignore local dependenices
|
||||
@@ -279,13 +356,15 @@ def create_vendor(vendor_staging_dir: Path, out_dir: Path) -> None:
|
||||
continue
|
||||
|
||||
source: str = pkg["source"]
|
||||
|
||||
dir_name = f"{pkg["name"]}-{pkg["version"]}"
|
||||
crate_out_dir = out_dir / dir_name
|
||||
source_ind = source_to_ind[source]
|
||||
crate_dir_name = f"{pkg["name"]}-{pkg["version"]}"
|
||||
source_dir_name = f"source-{source_ind}"
|
||||
crate_out_dir = out_dir / source_dir_name / crate_dir_name
|
||||
crate_out_dir.parent.mkdir(exist_ok=True)
|
||||
|
||||
if source.startswith("git+"):
|
||||
|
||||
source_info = parse_git_source(pkg["source"], lockfile_version)
|
||||
source_info = parse_git_source(source, lockfile_version)
|
||||
|
||||
git_sha_rev = source_info["git_sha_rev"]
|
||||
git_tree = vendor_staging_dir / "git" / git_sha_rev
|
||||
@@ -296,23 +375,13 @@ def create_vendor(vendor_staging_dir: Path, out_dir: Path) -> None:
|
||||
with open(crate_out_dir / ".cargo-checksum.json", "w") as f:
|
||||
json.dump({"files": {}}, f)
|
||||
|
||||
source_key = source[0:source.find("#")]
|
||||
|
||||
if source_key in seen_source_keys:
|
||||
continue
|
||||
|
||||
seen_source_keys.add(source_key)
|
||||
|
||||
config_lines.append(f'[source."{source_key}"]')
|
||||
config_lines.append(f'git = "{source_info["url"]}"')
|
||||
if source_info["type"] is not None:
|
||||
config_lines.append(f'{source_info["type"]} = "{source_info["value"]}"')
|
||||
config_lines.append('replace-with = "vendored-sources"')
|
||||
|
||||
elif source.startswith("registry+"):
|
||||
|
||||
elif source.startswith("registry+") or source.startswith("sparse+"):
|
||||
filename = f"{pkg["name"]}-{pkg["version"]}.tar.gz"
|
||||
tarball_path = vendor_staging_dir / "tarballs" / filename
|
||||
|
||||
# TODO: change this when non-crates-io registries are supported
|
||||
dir_name = "tarballs"
|
||||
|
||||
tarball_path = vendor_staging_dir / dir_name / filename
|
||||
|
||||
extract_crate_tarball_contents(tarball_path, crate_out_dir)
|
||||
|
||||
@@ -323,10 +392,6 @@ def create_vendor(vendor_staging_dir: Path, out_dir: Path) -> None:
|
||||
else:
|
||||
raise Exception(f"Can't process source: {source}.")
|
||||
|
||||
(out_dir / ".cargo").mkdir()
|
||||
with open(out_dir / ".cargo" / "config.toml", "w") as config_file:
|
||||
config_file.writelines(line + "\n" for line in config_lines)
|
||||
|
||||
|
||||
def main() -> None:
|
||||
subcommand = sys.argv[1]
|
||||
|
||||
@@ -27,6 +27,7 @@ let
|
||||
with python3Packages;
|
||||
[
|
||||
requests
|
||||
tomli-w
|
||||
]
|
||||
++ requests.optional-dependencies.socks; # to support socks proxy envs like ALL_PROXY in requests
|
||||
flakeIgnore = [
|
||||
|
||||
Executable → Regular
@@ -5,4 +5,4 @@
|
||||
# library.” Therefore, we keep packages `abseil-cpp_YYYYMM` for each
|
||||
# required LTS branch, leaving `abseil-cpp` as an alias.
|
||||
|
||||
{ abseil-cpp_202508 }: abseil-cpp_202508
|
||||
{ abseil-cpp_202601 }: abseil-cpp_202601
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "abseil-cpp";
|
||||
version = "20250512.1";
|
||||
version = "20250512.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "abseil";
|
||||
repo = "abseil-cpp";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-eB7OqTO9Vwts9nYQ/Mdq0Ds4T1KgmmpYdzU09VPWOhk=";
|
||||
hash = "sha256-NMdCALDFGGNNGyN17nwpRYBh/hoQoU7YMk66YDJndxQ=";
|
||||
};
|
||||
|
||||
cmakeFlags = [
|
||||
|
||||
@@ -10,13 +10,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "abseil-cpp";
|
||||
version = "20250814.1";
|
||||
version = "20250814.2";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "abseil";
|
||||
repo = "abseil-cpp";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-SCQDORhmJmTb0CYm15zjEa7dkwc+lpW2s1d4DsMRovI=";
|
||||
hash = "sha256-PCospVD/hnbT/87tRtvick+RIuwAv7DDPGnLG3ZMb3g=";
|
||||
};
|
||||
|
||||
outputs = [
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
{
|
||||
lib,
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
cmake,
|
||||
gtest,
|
||||
static ? stdenv.hostPlatform.isStatic,
|
||||
cxxStandard ? null,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "abseil-cpp";
|
||||
version = "20260107.1";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "abseil";
|
||||
repo = "abseil-cpp";
|
||||
tag = finalAttrs.version;
|
||||
hash = "sha256-TJT2Kzc64zI42FAbbGWP3Sshh1dU/D/AtEpgZrrhebg=";
|
||||
};
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
"dev"
|
||||
];
|
||||
|
||||
cmakeFlags = [
|
||||
(lib.cmakeBool "ABSL_BUILD_TEST_HELPERS" true)
|
||||
(lib.cmakeBool "ABSL_USE_EXTERNAL_GOOGLETEST" true)
|
||||
(lib.cmakeBool "BUILD_SHARED_LIBS" (!static))
|
||||
]
|
||||
++ lib.optionals (cxxStandard != null) [
|
||||
(lib.cmakeFeature "CMAKE_CXX_STANDARD" cxxStandard)
|
||||
];
|
||||
|
||||
strictDeps = true;
|
||||
|
||||
nativeBuildInputs = [ cmake ];
|
||||
|
||||
buildInputs = [ gtest ];
|
||||
|
||||
meta = {
|
||||
description = "Open-source collection of C++ code designed to augment the C++ standard library";
|
||||
homepage = "https://abseil.io/";
|
||||
changelog = "https://github.com/abseil/abseil-cpp/releases/tag/${finalAttrs.version}";
|
||||
license = lib.licenses.asl20;
|
||||
platforms = lib.platforms.all;
|
||||
maintainers = [ lib.maintainers.GaetanLepage ];
|
||||
};
|
||||
})
|
||||
@@ -14,13 +14,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "ada";
|
||||
version = "3.4.2";
|
||||
version = "3.4.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "ada-url";
|
||||
repo = "ada";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-+aXZY6JFfbw1N+EkenPhfp6ErUJFnbiJsgHpQq36Os4=";
|
||||
hash = "sha256-CSFo5aXxN1jhmD9SUh8XysObEyOvm53XPzbwJyCE0WE=";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
lib,
|
||||
stdenv,
|
||||
fetchurl,
|
||||
fetchpatch,
|
||||
alsa-topology-conf,
|
||||
alsa-ucm-conf,
|
||||
testers,
|
||||
@@ -10,11 +11,11 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "alsa-lib";
|
||||
version = "1.2.15.1";
|
||||
version = "1.2.15.3";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://alsa/lib/alsa-lib-${finalAttrs.version}.tar.bz2";
|
||||
hash = "sha256-f5g8qJykIIcsoW6Kn4+X+2PbbBxuJYW5Fzegi7A/Vmw=";
|
||||
hash = "sha256-ewedYU1YLK3nq42yNk5lJx0Id6N9+HV6xKwMiXC+hh4=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
@@ -23,6 +24,11 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# "libs" field to declare locations for both native and 32bit plugins, in
|
||||
# order to support apps with 32bit sound running on x86_64 architecture.
|
||||
./alsa-plugin-conf-multilib.patch
|
||||
(fetchpatch {
|
||||
name = "CVE-2026-25068.patch";
|
||||
url = "https://github.com/alsa-project/alsa-lib/commit/5f7fe33002d2d98d84f72e381ec2cccc0d5d3d40.patch";
|
||||
hash = "sha256-4memtcg+FDOctX6wgiCdmnlG+IUS+5rL1f3LcsWS5lw=";
|
||||
})
|
||||
];
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
{
|
||||
directoryListingUpdater,
|
||||
fetchurl,
|
||||
fetchpatch,
|
||||
lib,
|
||||
stdenvNoCC,
|
||||
coreutils,
|
||||
@@ -9,13 +10,21 @@
|
||||
|
||||
stdenvNoCC.mkDerivation (finalAttrs: {
|
||||
pname = "alsa-ucm-conf";
|
||||
version = "1.2.15.1";
|
||||
version = "1.2.15.3";
|
||||
|
||||
src = fetchurl {
|
||||
url = "mirror://alsa/lib/alsa-ucm-conf-${finalAttrs.version}.tar.bz2";
|
||||
hash = "sha256-JGxdWdIXtvf0ehH9EPG3ZtJavLDZyZavMHm7nJrFobA=";
|
||||
hash = "sha256-n3noE8CPyGz6Rt11xPzaGkpRtILbJgfh/PqvuS9YijE=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# fix for typo in 1.2.15.3 – remove with subsequent release
|
||||
(fetchpatch {
|
||||
url = "https://github.com/alsa-project/alsa-ucm-conf/commit/95377000e849259764f37295e0ddd58fd8a55a76.patch";
|
||||
hash = "sha256-o2qR69jiGXFWM0mxeIhXd+tCvGikYqnoalce1UOVppw=";
|
||||
})
|
||||
];
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
fetchFromGitHub,
|
||||
alsa-lib,
|
||||
caps,
|
||||
ladspaH,
|
||||
ladspa-header,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
@@ -20,7 +20,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
buildInputs = [
|
||||
alsa-lib
|
||||
ladspaH
|
||||
ladspa-header
|
||||
];
|
||||
|
||||
makeFlags = [ "DESTDIR=$(out)" ];
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
lib,
|
||||
stdenv,
|
||||
fetchurl,
|
||||
ladspaH,
|
||||
ladspa-header,
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
@@ -13,7 +13,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
sha256 = "0x4blm4visjqj0ndqr0cg776v3b7lvplpc8cgi9n51llhavn0jpl";
|
||||
};
|
||||
|
||||
buildInputs = [ ladspaH ];
|
||||
buildInputs = [ ladspa-header ];
|
||||
|
||||
patchPhase = ''
|
||||
sed -i 's@/usr/bin/install@install@g' Makefile
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
stdenv,
|
||||
fetchgit,
|
||||
alsa-lib,
|
||||
ladspaH,
|
||||
ladspa-header,
|
||||
libjack2,
|
||||
fftw,
|
||||
zita-alsa-pcmi,
|
||||
@@ -30,7 +30,7 @@ stdenv.mkDerivation {
|
||||
|
||||
buildInputs = [
|
||||
alsa-lib
|
||||
ladspaH
|
||||
ladspa-header
|
||||
libjack2
|
||||
fftw
|
||||
zita-alsa-pcmi
|
||||
|
||||
@@ -88,13 +88,13 @@
|
||||
enabledProviders,
|
||||
}:
|
||||
let
|
||||
version = "3.1.6";
|
||||
version = "3.1.7";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "apache";
|
||||
repo = "airflow";
|
||||
tag = version;
|
||||
hash = "sha256-wC6C0jhCA76/+KhBQbe3WeSGqR6FwaudCT5xPV39Z6c=";
|
||||
hash = "sha256-qFgI65wAttERPCHn7ezSdNGB0sclEV7zYIBqaC0Gs4A=";
|
||||
};
|
||||
|
||||
airflowUi = stdenv.mkDerivation rec {
|
||||
@@ -112,7 +112,7 @@ let
|
||||
pname = "airflow-ui";
|
||||
inherit sourceRoot src version;
|
||||
fetcherVersion = 3;
|
||||
hash = "sha256-jpv47+DAAoMB4pJBcv5G6zTGQ+/qdg86iQ/H22gwpro=";
|
||||
hash = "sha256-zPIql9rP4EkE0Y3ihP4MkWTTYCIDr8d1LpE6vePiNdU=";
|
||||
};
|
||||
|
||||
buildPhase = ''
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
#!/usr/bin/env nix-shell
|
||||
#!nix-shell -i bash -p common-updater-scripts curl jq nixfmt-tree
|
||||
#!nix-shell -i bash -p common-updater-scripts curl jq nixfmt-tree nix-update
|
||||
|
||||
set -euo pipefail
|
||||
|
||||
@@ -40,7 +40,8 @@ echo "Latest tag found: $LATEST_TAG"
|
||||
# Update the version and hash in the package definition
|
||||
# This uses the standard nixpkgs script `update-source-version`.
|
||||
echo "Updating source version for $PACKAGE_NAME to $LATEST_TAG..."
|
||||
update-source-version "$PACKAGE_NAME" "$LATEST_TAG"
|
||||
nix-update --subpackage airflowUi --subpackage airflowSimpleAuthUi "$PACKAGE_NAME" \
|
||||
--version "$LATEST_TAG"
|
||||
|
||||
# After updating the main package, run the providers update script.
|
||||
# It will automatically pick up the new version from the nix file.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
diff --git a/tools/src/CMakeLists.txt b/tools/src/CMakeLists.txt
|
||||
index 81e2da6f19..cdb809aed9 100644
|
||||
--- a/tools/src/CMakeLists.txt
|
||||
+++ b/tools/src/CMakeLists.txt
|
||||
@@ -64,6 +64,7 @@
|
||||
target_link_libraries (orc-metadata
|
||||
orc-tools-common
|
||||
orc::protobuf
|
||||
+ absl::raw_hash_set
|
||||
)
|
||||
|
||||
add_executable (orc-statistics
|
||||
@@ -27,15 +27,29 @@ let
|
||||
in
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "apache-orc";
|
||||
version = "2.2.1";
|
||||
version = "2.3.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "apache";
|
||||
repo = "orc";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-H7nowl2pq31RIAmTUz15x48Wc99MljFJboc4F7Ln/zk=";
|
||||
hash = "sha256-QQdRzwmUF1Qwxg53kJv1Q6yFuHqSrLYwUxKt+6wK9Hs=";
|
||||
};
|
||||
|
||||
patches = [
|
||||
# Orc's CMake declarations do not correctly attempt to link in abseil,
|
||||
# so we add the relevant library they need. Without these, we get errors
|
||||
# like:
|
||||
# <store path>/bin/ld: <store path>/lib/libabsl_raw_hash-set.so.2601.0.0:
|
||||
# error adding symbols: DSO missing from command line
|
||||
./cmake-link-abseil.patch
|
||||
|
||||
# Protobuf 34 adds `[[nodiscard]]` to several serialization functions. In
|
||||
# order to avoid these warnings causing build failures, we add handling for
|
||||
# this failure case.
|
||||
./protobuf34-nodiscard.patch
|
||||
];
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
];
|
||||
@@ -52,7 +66,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
cmakeFlags = [
|
||||
(lib.cmakeFeature "CMAKE_BUILD_TYPE" "Release")
|
||||
(lib.cmakeBool "BUILD_JAVA" false)
|
||||
(lib.cmakeBool "STOP_BUILD_ON_WARNING" true)
|
||||
(lib.cmakeBool "STOP_BUILD_ON_WARNING" stdenv.isLinux)
|
||||
(lib.cmakeBool "INSTALL_VENDORED_LIBS" false)
|
||||
]
|
||||
++ lib.optional (stdenv.hostPlatform != stdenv.buildPlatform) [
|
||||
@@ -65,12 +79,12 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
env = {
|
||||
GTEST_HOME = gtest.dev;
|
||||
LZ4_ROOT = lz4;
|
||||
LZ4_HOME = lz4;
|
||||
ORC_FORMAT_URL = orc-format;
|
||||
PROTOBUF_HOME = protobuf;
|
||||
SNAPPY_ROOT = snappy.dev;
|
||||
ZLIB_ROOT = zlib.dev;
|
||||
ZSTD_ROOT = zstd.dev;
|
||||
SNAPPY_HOME = snappy.dev;
|
||||
ZLIB_HOME = zlib.dev;
|
||||
ZSTD_HOME = zstd.dev;
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
diff --git a/c++/src/ColumnWriter.cc b/c++/src/ColumnWriter.cc
|
||||
index 9cdbae0709..d049e91bb1 100644
|
||||
--- a/c++/src/ColumnWriter.cc
|
||||
+++ b/c++/src/ColumnWriter.cc
|
||||
@@ -212,7 +212,9 @@
|
||||
}
|
||||
}
|
||||
// write row index to output stream
|
||||
- rowIndex->SerializeToZeroCopyStream(indexStream.get());
|
||||
+ if (!rowIndex->SerializeToZeroCopyStream(indexStream.get())) {
|
||||
+ throw std::logic_error("Failed to write index stream.");
|
||||
+ }
|
||||
|
||||
// construct row index stream
|
||||
proto::Stream stream;
|
||||
@@ -33,7 +33,6 @@
|
||||
gtest,
|
||||
libbacktrace,
|
||||
lz4,
|
||||
minio,
|
||||
ninja,
|
||||
nlohmann_json,
|
||||
openssl,
|
||||
@@ -132,8 +131,10 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
};
|
||||
|
||||
# apache-orc looks for things in caps
|
||||
LZ4_ROOT = lz4;
|
||||
ZSTD_ROOT = zstd.dev;
|
||||
LZ4_HOME = lz4;
|
||||
PROTOBUF_HOME = protobuf;
|
||||
SNAPPY_HOME = snappy.dev;
|
||||
ZSTD_HOME = zstd.dev;
|
||||
ARROW_TEST_DATA = "${arrow-testing}/data";
|
||||
PARQUET_TEST_DATA = "${parquet-testing}/data";
|
||||
GTEST_FILTER =
|
||||
@@ -153,6 +154,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
"TestMinioServer.Connect"
|
||||
"TestS3FS.*"
|
||||
"TestS3FSGeneric.*"
|
||||
"TestS3FSHTTPS.*" # Needs Minio
|
||||
]
|
||||
++ lib.optionals (stdenv.hostPlatform.isDarwin && stdenv.hostPlatform.isx86_64) [
|
||||
# https://github.com/apache/arrow/issues/41505
|
||||
@@ -290,7 +292,6 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
which
|
||||
sqlite
|
||||
]
|
||||
++ lib.optionals enableS3 [ minio ]
|
||||
++ lib.optionals enableFlight [ python3 ]
|
||||
++ lib.optionals enableAzure [ azurite ];
|
||||
|
||||
@@ -320,6 +321,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
runHook postInstallCheck
|
||||
'';
|
||||
|
||||
__structuredAttrs = true;
|
||||
|
||||
meta = {
|
||||
description = "Cross-language development platform for in-memory data";
|
||||
homepage = "https://arrow.apache.org/docs/cpp/";
|
||||
|
||||
@@ -53,7 +53,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
|
||||
substituteInPlace Makefile \
|
||||
--replace-fail /usr/bin/grep ${lib.getExe gnugrep}
|
||||
|
||||
substituteInPlace /build/asusctl-${finalAttrs.version}-vendor/sg-0.4.0/build.rs \
|
||||
substituteInPlace /build/asusctl-${finalAttrs.version}-vendor/source-*/sg-*/build.rs \
|
||||
--replace-fail /usr/include ${lib.getDev glibc}/include
|
||||
'';
|
||||
|
||||
|
||||
@@ -10,16 +10,16 @@
|
||||
|
||||
rustPlatform.buildRustPackage (finalAttrs: {
|
||||
pname = "atuin";
|
||||
version = "18.12.1";
|
||||
version = "18.13.3";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "atuinsh";
|
||||
repo = "atuin";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-ojIL8Iy74UgFE4Mp75oHWbZDsFRKRhOBdkPP/TtZpz4=";
|
||||
hash = "sha256-hLt6CDHEPV8BVpOADVn4bLNcBz89eC2jKtIexHG0yAY=";
|
||||
};
|
||||
|
||||
cargoHash = "sha256-KamAFi6OHE38ss8rIncNecNMVjd8gAeSWMh8G7Yb/rQ=";
|
||||
cargoHash = "sha256-VYwzMnfc/a4Sghmr5oMfhvoMkaWlY4w4e4Flu8MWQg0=";
|
||||
|
||||
# atuin's default features include 'check-updates', which do not make sense
|
||||
# for distribution builds. List all other default features.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
pnpmConfigHook,
|
||||
pnpm,
|
||||
fetchFromGitHub,
|
||||
buildGo124Module,
|
||||
buildGo125Module,
|
||||
installShellFiles,
|
||||
callPackage,
|
||||
nixosTests,
|
||||
@@ -22,7 +22,7 @@
|
||||
}:
|
||||
|
||||
let
|
||||
buildGoModule = buildGo124Module;
|
||||
buildGoModule = buildGo125Module;
|
||||
|
||||
inherit (import ./sources.nix { inherit fetchFromGitHub; })
|
||||
pname
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
stdenv,
|
||||
fetchFromGitHub,
|
||||
autoreconfHook,
|
||||
# doc: https://github.com/bdwgc/bdwgc/blob/v8.2.8/doc/README.macros (LARGE_CONFIG)
|
||||
# doc: https://github.com/bdwgc/bdwgc/blob/v8.2.12/doc/README.macros (LARGE_CONFIG)
|
||||
enableLargeConfig ? false,
|
||||
enableMmap ? true,
|
||||
enableStatic ? false,
|
||||
@@ -21,13 +21,13 @@
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "boehm-gc";
|
||||
version = "8.2.8";
|
||||
version = "8.2.12";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "bdwgc";
|
||||
repo = "bdwgc";
|
||||
rev = "v${finalAttrs.version}";
|
||||
hash = "sha256-UQSLK/05uPal6/m+HMz0QwXVII1leonlmtSZsXjJ+/c=";
|
||||
hash = "sha256-5yeAB5Y92YjOutwRXBJkMxoOLkmzmqIJs4PirKX89fE=";
|
||||
};
|
||||
|
||||
outputs = [
|
||||
@@ -55,24 +55,11 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
let
|
||||
defineFlag = flag: "-D${flag}";
|
||||
|
||||
# This stanza can be dropped when a release fixes this issue:
|
||||
# https://github.com/bdwgc/bdwgc/issues/376
|
||||
# The version is checked with == instead of versionAtLeast so we
|
||||
# don't forget to disable the fix (and if the next release does
|
||||
# not fix the problem the test failure will be a reminder to
|
||||
# extend the set of versions requiring the workaround).
|
||||
noSoftVDB =
|
||||
lib.optional (stdenv.hostPlatform.isPower64 && finalAttrs.version == "8.2.8")
|
||||
# do not use /proc primitives to track dirty bits; see:
|
||||
# https://github.com/bdwgc/bdwgc/issues/479#issuecomment-1279687537
|
||||
# https://github.com/bdwgc/bdwgc/blob/54522af853de28f45195044dadfd795c4e5942aa/include/private/gcconfig.h#L741
|
||||
"NO_SOFT_VDB";
|
||||
|
||||
initialMarkStackSizeFlag = lib.optionals (initialMarkStackSize != null) [
|
||||
"INITIAL_MARK_STACK_SIZE=${toString initialMarkStackSize}"
|
||||
];
|
||||
|
||||
cflagsExtra = noSoftVDB ++ initialMarkStackSizeFlag;
|
||||
cflagsExtra = initialMarkStackSizeFlag;
|
||||
in
|
||||
lib.optionals (cflagsExtra != [ ]) [
|
||||
"CFLAGS_EXTRA=${lib.concatMapStringsSep " " defineFlag cflagsExtra}"
|
||||
@@ -95,7 +82,9 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
|
||||
enableParallelBuilding = true;
|
||||
|
||||
passthru.tests = nixVersions;
|
||||
passthru.tests = {
|
||||
inherit (nixVersions) latest stable;
|
||||
};
|
||||
|
||||
meta = {
|
||||
homepage = "https://hboehm.info/gc/";
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
fetchurl,
|
||||
asar,
|
||||
dpkg,
|
||||
electron_38,
|
||||
electron_41,
|
||||
makeWrapper,
|
||||
nixosTests,
|
||||
undmg,
|
||||
@@ -13,7 +13,7 @@
|
||||
let
|
||||
inherit (stdenv.hostPlatform) system;
|
||||
|
||||
electron = electron_38;
|
||||
electron = electron_41;
|
||||
|
||||
sources = import ./sources.nix;
|
||||
|
||||
|
||||
@@ -8,16 +8,16 @@
|
||||
}:
|
||||
buildGoModule (finalAttrs: {
|
||||
pname = "bsky-cli";
|
||||
version = "0.0.76";
|
||||
version = "0.0.77";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "mattn";
|
||||
repo = "bsky";
|
||||
tag = "v${finalAttrs.version}";
|
||||
hash = "sha256-R8cKWVNk5gXj+wd0d1ZYSkxuXToXB2UZJsF7sCYGMqw=";
|
||||
hash = "sha256-cO2Ub9DVkDcz9+x+EskJsfgJ3xnTba5rWYsxmXfQ2a0=";
|
||||
};
|
||||
|
||||
vendorHash = "sha256-f9LZHJ5yXWUUh6HdF2JPEBucWuVud3YX5l2MkHs6UXc=";
|
||||
vendorHash = "sha256-WFGViuC+8Ba6NCU//Z+MTcwNPJbYzpXeCbf4M9mBFPM=";
|
||||
|
||||
buildInputs = [
|
||||
libpcap
|
||||
|
||||
@@ -9,20 +9,20 @@
|
||||
}:
|
||||
|
||||
let
|
||||
version = "2026.1.2";
|
||||
version = "2026.3";
|
||||
|
||||
product =
|
||||
if proEdition then
|
||||
{
|
||||
productName = "pro";
|
||||
productDesktop = "Burp Suite Professional Edition";
|
||||
hash = "sha256-KF6VOXO3IKsysA3SBJJzL+G2yQEVpCQKL6IMYQhYFMc=";
|
||||
hash = "sha256-iGSXyF6Jh3eSuokzu8DNK6wIUw7a0px/Hg5QwzgMQY4=";
|
||||
}
|
||||
else
|
||||
{
|
||||
productName = "community";
|
||||
productDesktop = "Burp Suite Community Edition";
|
||||
hash = "sha256-5LNzF68VhGdWttzZCkw/Ign4x6V4EhU/EHMddeSVirk=";
|
||||
hash = "sha256-kr4Fa6NjaCiN6ulwr+HR6KN/DpYWFlzwnyO4E34x4yY=";
|
||||
};
|
||||
|
||||
src = fetchurl {
|
||||
|
||||
@@ -9,7 +9,7 @@ curl -s 'https://portswigger.net/burp/releases/data' | jq -r '
|
||||
[ .ResultSet.Results[]
|
||||
| select((.categories|sort) == (["Professional","Community"]|sort))
|
||||
| .builds[]
|
||||
| select(.ProductPlatform == "Jar")
|
||||
| select(.BuildCategoryPlatform == "Jar")
|
||||
] as $all
|
||||
| ($all | max_by( (.Version // "") | split(".") | map(tonumber? // 0) ) | .Version) as $v
|
||||
| $all | map(select(.Version == $v))
|
||||
@@ -17,8 +17,8 @@ curl -s 'https://portswigger.net/burp/releases/data' | jq -r '
|
||||
|
||||
version=$(jq -r '.[0].Version' latest.json)
|
||||
|
||||
comm_hex=$(jq -r '.[] | select(.ProductId=="community") .Sha256Checksum' latest.json)
|
||||
pro_hex=$(jq -r '.[] | select(.ProductId=="pro") .Sha256Checksum' latest.json)
|
||||
comm_hex=$(jq -r '.[] | select(.BuildCategoryId=="community") .Sha256Checksum' latest.json)
|
||||
pro_hex=$(jq -r '.[] | select(.BuildCategoryId=="pro") .Sha256Checksum' latest.json)
|
||||
|
||||
comm_sri="sha256-$(printf %s "$comm_hex" | xxd -r -p | base64 -w0)"
|
||||
pro_sri="sha256-$(printf %s "$pro_hex" | xxd -r -p | base64 -w0)"
|
||||
|
||||
@@ -2,15 +2,12 @@
|
||||
lib,
|
||||
stdenv,
|
||||
writeText,
|
||||
fetchFromGitHub,
|
||||
fetchurl,
|
||||
buildcatrust,
|
||||
blacklist ? [ ],
|
||||
extraCertificateFiles ? [ ],
|
||||
extraCertificateStrings ? [ ],
|
||||
|
||||
# Used by update.sh
|
||||
nssOverride ? null,
|
||||
|
||||
# Used for tests only
|
||||
runCommand,
|
||||
cacert,
|
||||
@@ -23,10 +20,9 @@ let
|
||||
lib.concatStringsSep "\n\n" extraCertificateStrings
|
||||
);
|
||||
|
||||
srcVersion = "3.119.1";
|
||||
version = if nssOverride != null then nssOverride.version else srcVersion;
|
||||
version = "3.121";
|
||||
meta = {
|
||||
homepage = "https://curl.haxx.se/docs/caextract.html";
|
||||
homepage = "https://firefox-source-docs.mozilla.org/security/nss/runbooks/rootstore.html#root-store-consumers";
|
||||
description = "Bundle of X.509 certificates of public Certificate Authorities (CA)";
|
||||
platforms = lib.platforms.all;
|
||||
maintainers = with lib.maintainers; [
|
||||
@@ -39,40 +35,31 @@ let
|
||||
product = "nss";
|
||||
};
|
||||
};
|
||||
certdata = stdenv.mkDerivation {
|
||||
pname = "nss-cacert-certdata";
|
||||
inherit version;
|
||||
|
||||
src =
|
||||
if nssOverride != null then
|
||||
nssOverride.src
|
||||
else
|
||||
fetchFromGitHub {
|
||||
owner = "nss-dev";
|
||||
repo = "nss";
|
||||
rev = "NSS_${lib.replaceStrings [ "." ] [ "_" ] version}_RTM";
|
||||
hash = "sha256-GxLTqHcVWGiFezcwdctXJ8k9wqizVJPHyLBPZzphLro=";
|
||||
};
|
||||
|
||||
dontBuild = true;
|
||||
|
||||
installPhase = ''
|
||||
runHook preInstall
|
||||
|
||||
mkdir $out
|
||||
cp lib/ckfw/builtins/certdata.txt $out
|
||||
|
||||
runHook postInstall
|
||||
'';
|
||||
|
||||
inherit meta;
|
||||
};
|
||||
in
|
||||
stdenv.mkDerivation {
|
||||
pname = "nss-cacert";
|
||||
inherit version;
|
||||
|
||||
src = certdata;
|
||||
src = fetchurl {
|
||||
urls =
|
||||
let
|
||||
# This file is effectively a public interface, see the homepage link
|
||||
file = "lib/ckfw/builtins/certdata.txt";
|
||||
tag = "NSS_${lib.replaceStrings [ "." ] [ "_" ] version}_RTM";
|
||||
in
|
||||
[
|
||||
# Prefer mercurial as the canonical source, while github is just a mirror
|
||||
"https://hg-edge.mozilla.org/projects/nss/raw-file/${tag}/${file}"
|
||||
"https://raw.githubusercontent.com/nss-dev/nss/refs/tags/${tag}/${file}"
|
||||
];
|
||||
hash = "sha256-O5jU4/9XoybZWHwzYzA5yMOpzwtV98pYHXWY/zKesfM=";
|
||||
};
|
||||
|
||||
unpackPhase = ''
|
||||
runHook preUnpack
|
||||
cp "$src" "$(stripHash "$src")"
|
||||
runHook postUnpack
|
||||
'';
|
||||
|
||||
outputs = [
|
||||
"out"
|
||||
|
||||
@@ -25,7 +25,7 @@ BASEDIR="$(dirname "$0")/../../../.."
|
||||
|
||||
|
||||
CURRENT_PATH=$(nix-build --no-out-link -A cacert.out)
|
||||
PATCHED_PATH=$(nix-build --no-out-link -E "with import $BASEDIR {}; (cacert.override { nssOverride = nss_latest; }).out")
|
||||
PATCHED_PATH=$(nix-build --no-out-link -E "with import $BASEDIR {}; (cacert.overrideAttrs { src = nss_latest.src + \"/lib/ckfw/builtins/certdata.txt\"; }).out")
|
||||
|
||||
# Check the hash of the etc subfolder
|
||||
# We can't check the entire output as that contains the nix-support folder
|
||||
@@ -35,5 +35,5 @@ PATCHED_HASH=$(nix-hash "$PATCHED_PATH/etc")
|
||||
|
||||
if [[ "$CURRENT_HASH" != "$PATCHED_HASH" ]]; then
|
||||
NSS_VERSION=$(nix-instantiate --json --eval -E "with import $BASEDIR {}; nss_latest.version" | jq -r .)
|
||||
update-source-version --version-key=srcVersion cacert.src "$NSS_VERSION"
|
||||
update-source-version cacert "$NSS_VERSION"
|
||||
fi
|
||||
|
||||
@@ -60,8 +60,8 @@ cfgbootnone = """ # Disable bootloader.
|
||||
"""
|
||||
|
||||
cfgbootgrubcrypt = """ # Setup keyfile
|
||||
boot.initrd.secrets = {
|
||||
"/boot/crypto_keyfile.bin" = null;
|
||||
boot.initrd.secretPaths = {
|
||||
"/boot/crypto_keyfile.bin".source = null;
|
||||
};
|
||||
|
||||
boot.loader.grub.enableCryptodisk = true;
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
glib,
|
||||
gtk2,
|
||||
libjack2,
|
||||
ladspaH,
|
||||
ladspa-header,
|
||||
gnome2,
|
||||
lv2,
|
||||
pkg-config,
|
||||
@@ -46,7 +46,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
glib
|
||||
gtk2
|
||||
libjack2
|
||||
ladspaH
|
||||
ladspa-header
|
||||
gnome2.libglade
|
||||
lv2
|
||||
];
|
||||
|
||||
@@ -19,7 +19,7 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
inherit (cargo-tauri) version src;
|
||||
|
||||
postPatch = lib.optionalString stdenv.hostPlatform.isLinux ''
|
||||
substituteInPlace $cargoDepsCopy/libappindicator-sys-*/src/lib.rs \
|
||||
substituteInPlace $cargoDepsCopy/*/libappindicator-sys-*/src/lib.rs \
|
||||
--replace "libayatana-appindicator3.so.1" "${libayatana-appindicator}/lib/libayatana-appindicator3.so.1"
|
||||
'';
|
||||
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
|
||||
stdenv.mkDerivation rec {
|
||||
pname = "catch2";
|
||||
version = "3.12.0";
|
||||
version = "3.13.0";
|
||||
|
||||
src = fetchFromGitHub {
|
||||
owner = "catchorg";
|
||||
repo = "Catch2";
|
||||
tag = "v${version}";
|
||||
hash = "sha256-M1n2jWiA0hNCNqO3zSXRANiaMVCebn7/VU/4FfcjoA8=";
|
||||
hash = "sha256-WKp6/NX1SQJFLijW/fKwbR1FRoboAklDiHT6WqPRBjw=";
|
||||
};
|
||||
|
||||
patches = lib.optionals stdenv.cc.isClang [
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@
|
||||
}:
|
||||
|
||||
stdenv.mkDerivation (finalAttrs: {
|
||||
pname = "cdparanoia-III";
|
||||
pname = "cdparanoia-iii";
|
||||
version = "10.2";
|
||||
|
||||
src = fetchurl {
|
||||
@@ -35,7 +35,7 @@ rustPlatform.buildRustPackage (finalAttrs: {
|
||||
patches = [ ./missing-unsafe-block.patch ];
|
||||
|
||||
postPatch = ''
|
||||
pushd $cargoDepsCopy/librclone-sys-*
|
||||
pushd $cargoDepsCopy/*/librclone-sys-*
|
||||
oldHash=$(sha256sum build.rs | cut -d " " -f 1)
|
||||
patch -p2 < ${./librclone-path.patch}
|
||||
substituteInPlace build.rs \
|
||||
|
||||
@@ -117,34 +117,69 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
# versions are all taken from
|
||||
# https://github.com/apache/arrow/blob/apache-arrow-${version}/cpp/thirdparty/versions.txt
|
||||
|
||||
# jemalloc: arrow uses a custom prefix to prevent default allocator symbol
|
||||
# collisions as well as custom build flags
|
||||
${if enableJemalloc then "ARROW_JEMALLOC_URL" else null} = fetchurl {
|
||||
url = "https://github.com/jemalloc/jemalloc/releases/download/5.3.0/jemalloc-5.3.0.tar.bz2";
|
||||
hash = "sha256-LbgtHnEZ3z5xt2QCGbbf6EeJvAU3mDw7esT3GJrs/qo=";
|
||||
};
|
||||
env =
|
||||
lib.optionalAttrs enableJemalloc {
|
||||
# jemalloc: arrow uses a custom prefix to prevent default allocator symbol
|
||||
# collisions as well as custom build flags
|
||||
ARROW_JEMALLOC_URL = fetchurl {
|
||||
url = "https://github.com/jemalloc/jemalloc/releases/download/5.3.0/jemalloc-5.3.0.tar.bz2";
|
||||
hash = "sha256-LbgtHnEZ3z5xt2QCGbbf6EeJvAU3mDw7esT3GJrs/qo=";
|
||||
};
|
||||
}
|
||||
// {
|
||||
# mimalloc: arrow uses custom build flags for mimalloc
|
||||
ARROW_MIMALLOC_URL = fetchFromGitHub {
|
||||
owner = "microsoft";
|
||||
repo = "mimalloc";
|
||||
rev = "v2.0.6";
|
||||
hash = "sha256-u2ITXABBN/dwU+mCIbL3tN1f4c17aBuSdNTV+Adtohc=";
|
||||
};
|
||||
|
||||
# mimalloc: arrow uses custom build flags for mimalloc
|
||||
ARROW_MIMALLOC_URL = fetchFromGitHub {
|
||||
owner = "microsoft";
|
||||
repo = "mimalloc";
|
||||
rev = "v2.0.6";
|
||||
hash = "sha256-u2ITXABBN/dwU+mCIbL3tN1f4c17aBuSdNTV+Adtohc=";
|
||||
};
|
||||
ARROW_XSIMD_URL = fetchFromGitHub {
|
||||
owner = "xtensor-stack";
|
||||
repo = "xsimd";
|
||||
rev = "13.0.0";
|
||||
hash = "sha256-qElJYW5QDj3s59L3NgZj5zkhnUMzIP2mBa1sPks3/CE=";
|
||||
};
|
||||
|
||||
ARROW_XSIMD_URL = fetchFromGitHub {
|
||||
owner = "xtensor-stack";
|
||||
repo = "xsimd";
|
||||
rev = "13.0.0";
|
||||
hash = "sha256-qElJYW5QDj3s59L3NgZj5zkhnUMzIP2mBa1sPks3/CE=";
|
||||
};
|
||||
|
||||
ARROW_SUBSTRAIT_URL = fetchFromGitHub {
|
||||
owner = "substrait-io";
|
||||
repo = "substrait";
|
||||
rev = "v0.44.0";
|
||||
hash = "sha256-V739IFTGPtbGPlxcOi8sAaYSDhNUEpITvN9IqdPReug=";
|
||||
};
|
||||
ARROW_SUBSTRAIT_URL = fetchFromGitHub {
|
||||
owner = "substrait-io";
|
||||
repo = "substrait";
|
||||
rev = "v0.44.0";
|
||||
hash = "sha256-V739IFTGPtbGPlxcOi8sAaYSDhNUEpITvN9IqdPReug=";
|
||||
};
|
||||
}
|
||||
// lib.optionalAttrs finalAttrs.doInstallCheck {
|
||||
ARROW_TEST_DATA = "${arrow-testing}/data";
|
||||
PARQUET_TEST_DATA = "${parquet-testing}/data";
|
||||
GTEST_FILTER =
|
||||
let
|
||||
# Upstream Issue: https://issues.apache.org/jira/browse/ARROW-11398
|
||||
filteredTests =
|
||||
lib.optionals stdenv.hostPlatform.isAarch64 [
|
||||
"TestFilterKernelWithNumeric/3.CompareArrayAndFilterRandomNumeric"
|
||||
"TestFilterKernelWithNumeric/7.CompareArrayAndFilterRandomNumeric"
|
||||
"TestCompareKernel.PrimitiveRandomTests"
|
||||
]
|
||||
++ lib.optionals enableS3 [
|
||||
"S3OptionsTest.FromUri"
|
||||
"S3RegionResolutionTest.NonExistentBucket"
|
||||
"S3RegionResolutionTest.PublicBucket"
|
||||
"S3RegionResolutionTest.RestrictedBucket"
|
||||
"TestMinioServer.Connect"
|
||||
"TestS3FS.*"
|
||||
"TestS3FSGeneric.*"
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isDarwin [
|
||||
# TODO: revisit at 12.0.0 or when
|
||||
# https://github.com/apache/arrow/commit/295c6644ca6b67c95a662410b2c7faea0920c989
|
||||
# is available, see
|
||||
# https://github.com/apache/arrow/pull/15288#discussion_r1071244661
|
||||
"ExecPlanExecution.StressSourceSinkStopped"
|
||||
];
|
||||
in
|
||||
"-${lib.concatStringsSep ":" filteredTests}";
|
||||
};
|
||||
|
||||
nativeBuildInputs = [
|
||||
cmake
|
||||
@@ -249,35 +284,6 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
];
|
||||
|
||||
doInstallCheck = true;
|
||||
ARROW_TEST_DATA = lib.optionalString finalAttrs.doInstallCheck "${arrow-testing}/data";
|
||||
PARQUET_TEST_DATA = lib.optionalString finalAttrs.doInstallCheck "${parquet-testing}/data";
|
||||
GTEST_FILTER =
|
||||
let
|
||||
# Upstream Issue: https://issues.apache.org/jira/browse/ARROW-11398
|
||||
filteredTests =
|
||||
lib.optionals stdenv.hostPlatform.isAarch64 [
|
||||
"TestFilterKernelWithNumeric/3.CompareArrayAndFilterRandomNumeric"
|
||||
"TestFilterKernelWithNumeric/7.CompareArrayAndFilterRandomNumeric"
|
||||
"TestCompareKernel.PrimitiveRandomTests"
|
||||
]
|
||||
++ lib.optionals enableS3 [
|
||||
"S3OptionsTest.FromUri"
|
||||
"S3RegionResolutionTest.NonExistentBucket"
|
||||
"S3RegionResolutionTest.PublicBucket"
|
||||
"S3RegionResolutionTest.RestrictedBucket"
|
||||
"TestMinioServer.Connect"
|
||||
"TestS3FS.*"
|
||||
"TestS3FSGeneric.*"
|
||||
]
|
||||
++ lib.optionals stdenv.hostPlatform.isDarwin [
|
||||
# TODO: revisit at 12.0.0 or when
|
||||
# https://github.com/apache/arrow/commit/295c6644ca6b67c95a662410b2c7faea0920c989
|
||||
# is available, see
|
||||
# https://github.com/apache/arrow/pull/15288#discussion_r1071244661
|
||||
"ExecPlanExecution.StressSourceSinkStopped"
|
||||
];
|
||||
in
|
||||
lib.optionalString finalAttrs.doInstallCheck "-${lib.concatStringsSep ":" filteredTests}";
|
||||
|
||||
__darwinAllowLocalNetworking = true;
|
||||
|
||||
@@ -307,6 +313,8 @@ stdenv.mkDerivation (finalAttrs: {
|
||||
runHook postInstallCheck
|
||||
'';
|
||||
|
||||
__structuredAttrs = true;
|
||||
|
||||
meta = {
|
||||
description = "Cross-language development platform for in-memory data";
|
||||
homepage = "https://arrow.apache.org/docs/cpp/";
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user