Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 4 additions & 30 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ jobs:
run: nix build .#checks.x86_64-linux.fmt --no-link

# Integration tests (actual SDK downloads)
integration-basic:
integration-tests:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
Expand All @@ -62,38 +62,12 @@ jobs:
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf

- name: Run basic integration test
- name: Run integration tests
run: |
system=$(nix eval --impure --raw --expr builtins.currentSystem)
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
nix build .#checks.${system}.integration-test --no-link --option sandbox false
nix build .#checks.${system}.integration-tests --no-link --option sandbox false
else
nix build .#checks.${system}.integration-test --no-link
fi
timeout-minutes: 15

integration-workloads:
strategy:
matrix:
os: [ubuntu-latest, macos-latest]
runs-on: ${{ matrix.os }}
steps:
- uses: actions/checkout@v4

- name: Install Nix
uses: DeterminateSystems/nix-installer-action@main

- name: Enable Flakes
run: |
mkdir -p ~/.config/nix
echo "experimental-features = nix-command flakes" >> ~/.config/nix/nix.conf

- name: Run workload integration test
run: |
system=$(nix eval --impure --raw --expr builtins.currentSystem)
if [ "${{ matrix.os }}" = "ubuntu-latest" ]; then
nix build .#checks.${system}.integration-workload-test --no-link --option sandbox false
else
nix build .#checks.${system}.integration-workload-test --no-link
nix build .#checks.${system}.integration-tests --no-link
fi
timeout-minutes: 20
10 changes: 5 additions & 5 deletions AGENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,9 @@
- Run all checks: `nix flake check`
- Unit tests: `nix run github:nix-community/nix-unit -- --flake '.#tests'`
- Run single unit test: `nix run github:nix-community/nix-unit -- --flake '.#tests' --filter 'testValidateSdkVersionBasic'`
- Integration test: `nix build .#checks.<system>.integration-test --no-link`
- Integration tests: `nix build .#checks.<system>.integration-tests --no-link`
- Reproduce Linux integration checks in container: `./scripts/run-linux-build.sh`
- Run a specific Linux check in container: `./scripts/run-linux-build.sh .#checks.x86_64-linux.integration-test`
- Run a specific Linux check in container: `./scripts/run-linux-build.sh .#checks.x86_64-linux.integration-tests`
- Build basic example: `nix build .#basic-example --no-link`
- Build workload example: `nix build .#workload-example --no-link`
- Enter dev shell: `nix develop`
Expand Down Expand Up @@ -73,10 +73,10 @@ buildWorkloadNames = workloads:
```

- **Integration tests** (slow, requires .NET SDK build):
- Run: `nix build .#checks.<system>.integration-test --no-link`
- Run: `nix build .#checks.<system>.integration-tests --no-link`
- Linux CI parity (from macOS): `./scripts/run-linux-build.sh`
- The script uses a `nixos/nix` linux/amd64 container and defaults to both Linux integration checks.
- Optional attrs can be passed (for example: `./scripts/run-linux-build.sh .#checks.x86_64-linux.integration-workload-test`).
- The script uses a `nixos/nix` linux/amd64 container and defaults to the combined Linux integration check.
- Optional attrs can be passed (for example: `./scripts/run-linux-build.sh .#checks.x86_64-linux.integration-tests`).
- Location: `tests/integration/` (full .NET project with xUnit tests)
- Tests: End-to-end SDK build and test execution
- Validates that mkDotnet produces a working .NET SDK
Expand Down
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ nix develop
nix run github:nix-community/nix-unit -- --flake '.#tests'

# Integration tests
nix build .#checks.<system>.integration-test --no-link
nix build .#checks.<system>.integration-tests --no-link

# All checks
nix flake check
Expand Down
30 changes: 24 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# nix-dotnet

A Nix module that reads your `global.json` and builds a reproducible .NET SDK derivation.
A Nix module that builds reproducible .NET SDK derivations from `global.json` or explicit SDK versions.

## Quick Start

Expand Down Expand Up @@ -49,18 +49,35 @@ A Nix module that reads your `global.json` and builds a reproducible .NET SDK de

```nix
nix-dotnet.lib.${system}.mkDotnet {
globalJsonPath = ./global.json; # Required
workloads = [ "android" "ios" ]; # Optional
globalJsonPath = ./global.json; # Use this for global.json-driven versioning
# sdkVersion = "10.0.103"; # Alternative to globalJsonPath
# workloadVersion = "10.0.100.1"; # Optional with sdkVersion
additionalSdks = [
{
sdkVersion = "9.0.304";
}
];
outputHash = "sha256-..."; # Required for fixed-output
}
```

**Parameters:**

- `globalJsonPath` - Path to global.json (required)
- `workloads` - List of workload names (optional, versions from global.json)
- `globalJsonPath` - Path to global.json (optional; mutually exclusive with `sdkVersion`)
- `sdkVersion` - SDK version string like `10.0.103` (optional; mutually exclusive with `globalJsonPath`)
- `workloadVersion` - Workload manifest version when using explicit `sdkVersion` (optional)
- `workloads` - List of workload names (optional, versions from `global.json` or `workloadVersion`)
- `additionalSdks` - Extra SDK configs to merge into the same `dotnet` installation (optional, no per-SDK hash)
- `outputHash` - Fixed-output derivation hash (required)

`additionalSdks` lets one `dotnet` command expose multiple SDK versions, so `dotnet --list-sdks` can show entries like .NET 10 and .NET 9 together.

Use one top-level `outputHash` for the whole combined installation.

Use `checks.<system>.integration-tests` to run all integration checks that are configured for that system.

_Note_: `additionalSdks` entries do not support installing workloads.

### Getting the outputHash

1. Use a placeholder hash
Expand All @@ -74,6 +91,7 @@ nix-dotnet.lib.${system}.mkDotnet {

- [`examples/basic/`](./examples/basic/) - SDK without workloads
- [`examples/with-workloads/`](./examples/with-workloads/) - SDK with MAUI workloads
- [`examples/multi-sdk/`](./examples/multi-sdk/) - single `dotnet` with both .NET 10 and .NET 9 SDKs

## Supported Platforms

Expand All @@ -89,7 +107,7 @@ nix-dotnet.lib.${system}.mkDotnet {
nix run github:nix-community/nix-unit -- --flake '.#tests'

# Integration tests (slow, builds SDK)
nix build .#checks.<system>.integration-test --no-link
nix build .#checks.<system>.integration-tests --no-link

# All checks
nix flake check
Expand Down
1 change: 0 additions & 1 deletion examples/basic/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
};

outputs = {
self,
nixpkgs,
nix-dotnet,
}: let
Expand Down
34 changes: 34 additions & 0 deletions examples/multi-sdk/flake.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
{
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nix-dotnet.url = "github:adampoit/nix-dotnet";
};

outputs = {
nixpkgs,
nix-dotnet,
}: let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
in {
devShells.${system}.default = pkgs.mkShell {
buildInputs = [
(nix-dotnet.lib.${system}.mkDotnet {
sdkVersion = "10.0.103";
outputHash = "sha256-AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=";
additionalSdks = [
{
sdkVersion = "9.0.304";
}
];
})
];

shellHook = ''
echo "Active SDK: $(dotnet --version)"
echo "Installed SDKs:"
dotnet --list-sdks
'';
};
};
}
1 change: 0 additions & 1 deletion examples/with-workloads/flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
};

outputs = {
self,
nixpkgs,
nix-dotnet,
}: let
Expand Down
67 changes: 49 additions & 18 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
description = "Nix module for installing .NET SDKs with specific versions and workloads from global.json";
description = "Nix module for reproducible .NET SDKs from global.json or explicit versions";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
Expand All @@ -8,10 +8,10 @@
};

outputs = {
self,
nixpkgs,
flake-utils,
nix-unit,
...
}:
flake-utils.lib.eachDefaultSystem
(
Expand All @@ -30,17 +30,48 @@
x86_64-darwin = "sha256-gJPf567EoBmF22ANZX9qFEA/wtZHU/+GBd6rbaj9VUQ=";
x86_64-linux = "sha256-R6+gCgcfrTv1NYQyI0/3YXmjDRvvooPEOjCR59WSpfk=";
};
multiSdkOutputHashes = {
aarch64-darwin = "sha256-McAAMwZCOfvdOKOCjNRKYmpWbdtUQfz03WdoAJImv5c=";
aarch64-linux = "sha256-olZbB/1rbLs587K9NQXBQ9o2pQH0WSTUjaBORlJVD+4=";
x86_64-darwin = "sha256-5DNjlU1VCJs3Soqemq4gU3YdEFXvIol30qad0udUiuU=";
x86_64-linux = "sha256-3LAIxMUQYqrnEaOAoYA/seSFZuE1pyVL97TjC891VCs=";
};
outputHashFor = hashes:
if builtins.hasAttr system hashes
then hashes.${system}
else throw "No outputHash configured for system ${system}";
integrationSingleSdkTest = import ./tests/integration-test.nix {
inherit pkgs dotnet;
outputHash = outputHashFor sdkOutputHashes;
};
integrationWorkloadTest = import ./tests/integration-workload-test.nix {
inherit pkgs dotnet;
outputHash = outputHashFor workloadOutputHashes;
};
integrationMultiSdkTest = import ./tests/integration-multi-sdk-test.nix {
inherit pkgs dotnet;
outputHash = outputHashFor multiSdkOutputHashes;
};
integrationTests =
pkgs.runCommand
"integration-tests"
{
buildInputs = [
integrationSingleSdkTest
integrationWorkloadTest
integrationMultiSdkTest
];
}
''
touch $out
'';
unitTests = import ./tests/unit.nix {
lib = dotnet.internal;
inherit dotnet;
};

unitTestAssertions =
builtins.map
map
(
name: let
test = unitTests.${name};
Expand All @@ -52,18 +83,22 @@
(builtins.attrNames unitTests);
in {
lib = dotnet;
packages = {
basic-example = dotnet.mkDotnet {
packages = let
basicExample = dotnet.mkDotnet {
globalJsonPath = ./global.json;
workloads = [];
outputHash = outputHashFor sdkOutputHashes;
};

workload-example = dotnet.mkDotnet {
workloadExample = dotnet.mkDotnet {
globalJsonPath = ./global.json;
workloads = ["android"];
outputHash = outputHashFor workloadOutputHashes;
};
in {
default = basicExample;
basic-example = basicExample;
workload-example = workloadExample;
};

devShells.default = pkgs.mkShell {
Expand All @@ -80,23 +115,15 @@
{
buildInputs = [pkgs.alejandra];
} "
alejandra --check ${./.}
touch $out
";
alejandra --check ${./.}
touch $out
";

unit-tests = builtins.deepSeq unitTestAssertions (pkgs.runCommand "unit-tests" {} ''
echo "${toString (builtins.length (builtins.attrNames unitTests))} unit tests passed" > $out
'');

integration-test = import ./tests/integration-test.nix {
inherit pkgs dotnet;
outputHash = outputHashFor sdkOutputHashes;
};

integration-workload-test = import ./tests/integration-workload-test.nix {
inherit pkgs dotnet;
outputHash = outputHashFor workloadOutputHashes;
};
integration-tests = integrationTests;
};
}
)
Expand All @@ -110,6 +137,10 @@
path = ./examples/with-workloads;
description = "Example with .NET workloads";
};
multi-sdk = {
path = ./examples/multi-sdk;
description = "Example with one dotnet exposing multiple SDK versions";
};
};

tests = let
Expand Down
3 changes: 1 addition & 2 deletions scripts/run-linux-build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,7 @@ if [[ "$#" -gt 0 ]]; then
attrs=("$@")
else
attrs=(
".#checks.x86_64-linux.integration-test"
".#checks.x86_64-linux.integration-workload-test"
".#checks.x86_64-linux.integration-tests"
)
fi

Expand Down
1 change: 0 additions & 1 deletion src/lib.nix
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
inherit
(pkgs.lib)
concatStringsSep
map
match
hasAttr
replaceStrings
Expand Down
Loading