-
-
Notifications
You must be signed in to change notification settings - Fork 14.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
buildDotnetModule: allow fetching nuget dependencies at compile time
This allows user to specify a hash for the dependencies using the "nugetSha256" attribute, instead of having to manually generate a lockfile. This is done by generating a lockfile with `dotnet restore`, and then parsing the requested version ranges to see if anything is floating. Afterwards we generate a nix-based lockfile containing hashes and stable downloads for each dependency, which we can IFD. The checksum of this lockfile is specified with "nugetSha256". We want to use the checksum of the nix-based lockfile instead of hashing the entire nuget source so that we can independantly fetch all dependencies, and re-use them across derivations. Co-authored-by: Valentin Gagarin <[email protected]>
- Loading branch information
1 parent
9ca3f64
commit e2c84cf
Showing
6 changed files
with
214 additions
and
24 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
73 changes: 73 additions & 0 deletions
73
pkgs/build-support/dotnet/build-dotnet-module/fetch-deps.nix
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,73 @@ | ||
{ lib | ||
, buildDotnetModule | ||
, dotnetValidateLockfileHook | ||
, nuget-to-nix | ||
, nugetSha256 | ||
|
||
, src | ||
, name | ||
, meta | ||
, dotnet-sdk | ||
, projectFile | ||
, testProjectFile | ||
, dotnetFlags | ||
, dotnetRestoreFlags | ||
, enableParallelBuilding | ||
, sdkExclusions | ||
} @ args: | ||
|
||
buildDotnetModule rec { | ||
name = "${args.name}-nuget-lockfile"; | ||
|
||
inherit src dotnet-sdk projectFile testProjectFile dotnetFlags dotnetRestoreFlags enableParallelBuilding; | ||
|
||
nativeBuildInputs = [ dotnetValidateLockfileHook ]; | ||
|
||
generateLockfile = true; | ||
dontSetNugetSource = true; | ||
dontDotnetFixup = true; | ||
|
||
impureEnvVars = lib.fetchers.proxyImpureEnvVars; | ||
outputHashAlgo = "sha256"; | ||
outputHashMode = "flat"; | ||
outputHash = if (nugetSha256 != null) | ||
then nugetSha256 | ||
else ""; # This needs to be set for networking, an empty string prints the "empty hash found" warning | ||
|
||
preConfigure = '' | ||
dotnetRestoreFlags+=( | ||
--packages "$HOME/nuget-pkgs" | ||
) | ||
echo "Evaluating and fetching Nuget dependencies" | ||
''; | ||
|
||
buildPhase = '' | ||
runHook preBuild | ||
NUGET_DEPS="$HOME/deps.nix" | ||
echo "Writing lockfile..." | ||
${nuget-to-nix}/bin/nuget-to-nix "$HOME/nuget-pkgs" "${sdkExclusions}" > "$NUGET_DEPS" | ||
runHook postBuild | ||
''; | ||
|
||
installPhase = '' | ||
runHook preInstall | ||
cp "$NUGET_DEPS" $out | ||
echo "Installed lockfile to: $out" | ||
runHook postInstall | ||
''; | ||
|
||
# This is the last phase that runs before we error out about the hash being wrong | ||
postFixup = lib.optionalString (nugetSha256 == null) '' | ||
echo "Please set nugetSha256 to the hash below!" | ||
''; | ||
|
||
meta = { | ||
description = "A lockfile containing the Nuget dependencies for ${name}"; | ||
inherit (args.meta) maintainers platforms; | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
67 changes: 67 additions & 0 deletions
67
pkgs/build-support/dotnet/build-dotnet-module/hooks/dotnet-validate-lockfile.sh
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
# Validate a lockfile does not depend on any floating Nuget dependencies | ||
# Note that all ranges other than floating resolve to the lowest available version by default | ||
# See https://docs.microsoft.com/en-us/nuget/concepts/package-versioning#version-ranges for more information | ||
dotnetValidateLockfileHook() { | ||
echo "Executing dotnetValidateLockfileHook" | ||
|
||
if [[ ! -f "${lockfilePath-}" ]]; then | ||
echo "Could not locate the lockfile! Consider setting \"dontDotnetValidateLockfile\"" | ||
exit 1 | ||
fi | ||
|
||
lockfileVersion="$(jq ".version" < "${lockfilePath}")" | ||
|
||
if (( "${lockfileVersion}" != 1 && "${lockfileVersion}" != 2 )); then | ||
echo "error: unsupported lockfile version: ${lockfileVersion}" | ||
exit 1 | ||
fi | ||
|
||
# An array of most dependencies and their versions. | ||
depsWithVersions="$(jq -rc ' | ||
# Direct dependencies. This only includes entries with requested version ranges | ||
[ .dependencies[] | with_entries(select(.value | has("requested"))) | to_entries[] | { | ||
"name": .key, # Name of dependency | ||
"version": .value.requested # Requested version range | ||
# Dependencies of dependencies. Includes all of them, as requested ranges are not marked | ||
}] + [ .dependencies[] | with_entries(select(.value | has("dependencies"))) | .[].dependencies | to_entries[] | { | ||
"name": .key, # Name of dependency | ||
"version": .value # Version, this can either be a range or an exact match | ||
}] | ||
' < "${lockfilePath}")" | ||
|
||
depsLength="$(jq -rc 'length' <<< "${depsWithVersions}")" | ||
lockfileErrors=() | ||
|
||
i=0 | ||
while (( "$i" < "${depsLength}" )); do | ||
depName="$(jq -rc --arg i "$i" '.[($i | tonumber)] | .name' <<< "${depsWithVersions}")" | ||
depVersion="$(jq -rc --arg i "$i" '.[($i | tonumber)] | .version' <<< "${depsWithVersions}")" | ||
|
||
# Check if the version range is floating | ||
if [[ "${depVersion}" = *"*"* ]]; then | ||
lockfileErrors+=("Package \"${depName}\" requested floating version range \"${depVersion}\"") | ||
fi | ||
|
||
i=$(( i + 1 )) | ||
done | ||
unset i | ||
|
||
if (( "${#lockfileErrors[@]}" > 0 )); then | ||
echo "Attempted to fetch unstable NuGet dependency version(s):" | ||
|
||
for error in "${lockfileErrors[@]}"; do | ||
echo " ${error}" | ||
done | ||
|
||
echo "This project uses unstable version range(s) for its Nuget dependencies, which we cannot deterministically fetch." | ||
echo "Please set the \"nugetDeps\" attribute to a lockfile generated with the \"passthru.fetch-deps\" script to ensure all dependencies are locked." | ||
exit 1 | ||
fi | ||
|
||
echo "succesfully validated lockfile" | ||
echo "Finished dotnetValidateLockfileHook" | ||
} | ||
|
||
if [[ -z "${dontDotnetValidateLockfile-}" && -z "${postConfigure-}" ]]; then | ||
postConfigure=dotnetValidateLockfileHook | ||
fi |