-
Notifications
You must be signed in to change notification settings - Fork 0
/
flake.nix
152 lines (145 loc) · 7.86 KB
/
flake.nix
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
{
description = "Break Lazy Source Trees in Nix with Source Tree Abstraction";
inputs.nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, nixpkgs, flake-utils }:
flake-utils.lib.eachDefaultSystem
(system:
let
evalTarget = import ./default.nix;
pkgs = nixpkgs.legacyPackages.${system};
nix-stable = pkgs.nixVersions.nix_2_16;
nix-lst = nix-stable.overrideAttrs (old: {
version = old.version + "-lst";
src = pkgs.fetchFromGitHub {
owner = "edolstra";
repo = "nix";
rev = "f355c3437c4abeeaadb28726b49453135c6868c0";
hash = "sha256-O/sLP84mscj1+TkIcn9+leA5tiHIglUaY2tjjziXRFQ=";
};
buildInputs = old.buildInputs ++ [ pkgs.libgit2 ];
});
lib = pkgs.lib;
in
{
packages.default = evalTarget { inherit pkgs; };
packages.noRepro = evalTarget { inherit pkgs; useFilteredPath = false; };
# I'm sorry for the following monstrosity.
#
# Nix did not make it easy to generate combinatoric tests for multiple versions of
# itself, and recursive-nix is not yet supported without an experimental flag.
# Besides, recursive-nix would probably not support multiple mismatched versions anyway.
packages.report = (
let
buildCacheBreaker = configurationModeFlags: builtins.substring 0 5 (builtins.hashString "sha256" (builtins.toJSON configurationModeFlags));
writeAttemptOutPath = (nixBuildPath: srcPath: configuration:
let
breaker = buildCacheBreaker (configuration // { inherit nixBuildPath; });
argValue = value: if (builtins.typeOf value) == "bool" then (if value then "true" else "false") else "\"${value}\"";
buildArg = { name, value }: if name == "impure" then (if value then "--impure" else "--pure") else "--arg${if (builtins.typeOf value) == "string" then "str" else ""} ${name} ${argValue value}";
configArgs = builtins.concatStringsSep " " (lib.attrsets.mapAttrsToList (k: v: buildArg { name = k; value = v; }) configuration);
in
''${nixBuildPath} ${srcPath}/default.nix ${configArgs} ${buildArg { name = "cacheBreaker"; value = "$(echo \\\"$nixBuildExe\\\" | sha256sum -t | head -c5)${breaker}"; }}''
);
availableModeFlags = (builtins.filter (lib.strings.hasPrefix "use") (builtins.attrNames (lib.trivial.functionArgs evalTarget))) ++ ["impure"];
configurations = lib.attrsets.cartesianProductOfSets (builtins.listToAttrs (map (modeFlag: { name = modeFlag; value = [false true]; }) availableModeFlags));
sed = "${pkgs.gnused}/bin/sed";
reportCommands = { metaProps }: map (configuration: builtins.traceVerbose "Generating report for ${builtins.toJSON configuration}" ''
echo "Running case: ${writeAttemptOutPath "$nixBuildExe" "$src" configuration}"
OUTPATH=$(${writeAttemptOutPath "$nixBuildExe" "$src" configuration} 2>/dev/null || echo "/failed")
SUCCESS=false
if [[ -d "$OUTPATH" && -f "$OUTPATH/helloworld.txt" || -d "$OUTPATH" && -f "$OUTPATH/hello.txt" ]]; then
echo -e " \033[32mSuccess: $OUTPATH\033[0m"
SUCCESS=true
else
echo -e " \033[0;31mFailed\033[0m"
SUCCESS=false
fi
write_json_if_needed ${lib.strings.escapeShellArg (builtins.toJSON (configuration // metaProps // { success = "SUCCESS_STATE"; }))}
'') configurations;
generator = pkgs.writeShellScript
"gen-report.sh"
''
set -e
echo "Report of various configuration states:"
function write_json_if_needed()
{
if $SUCCESS; then
SUCCESS="true"
else
SUCCESS="false"
fi
if [ -z ''${NIX_VERSION+x} ]; then
NIX_VERSION=""
fi
if [ ! -z ''${REPORTOUT+x} ]; then
echo -n " $1" \
| ${sed} "s/[\"']SUCCESS_STATE[\"']/$SUCCESS/" \
| ${sed} "s/NIX_VERSION/$NIX_VERSION/" \
>> "$REPORTOUT"
fi
}
function write_json_sep_if_needed()
{
if [ ! -z ''${REPORTOUT+x} ]; then
echo "," >> "$REPORTOUT"
fi
}
if [ -z ''${FULL_REPORT_MODE+x} ]; then
echo "[" > "$REPORTOUT"
fi
${builtins.concatStringsSep "\nwrite_json_sep_if_needed\n" (reportCommands { metaProps = { "nixVersion" = "NIX_VERSION"; }; })}
if [ -z ''${FULL_REPORT_MODE+x} ]; then
echo -e "\n]" >> "$REPORTOUT"
fi
'';
runGeneratorFor = nixVersion: versionTitle: srcDirVar: ''
export NIX_VERSION="${versionTitle}"
NIX_HOME="${nixVersion}"
echo -e "\nNix ${versionTitle} ($($NIX_HOME/bin/nix-build --version)) at $NIX_HOME:"
GENERATOR_SCRIPT=$($NIX_HOME/bin/nix build .#report.generator --impure --show-trace --print-out-paths)
src="${srcDirVar}" nixBuildExe="$NIX_HOME/bin/nix-build" $GENERATOR_SCRIPT | ${sed} "s/^/ /"
echo -e "\n"
'';
fullReportGenerator = pkgs.writeShellScript
"gen-full-report.sh"
''
set -eu
export SOURCE_DIR="${./.}"
echo "Source dir is $SOURCE_DIR"
export TEST_DIR=$(mktemp -d -t 'nixltstest' 2>/dev/null || mktemp -d 2>/dev/null)
echo "Copying test materials to $TEST_DIR"
bash -c "cp -R $SOURCE_DIR/* \"$TEST_DIR\""
chmod -R 770 "$TEST_DIR"
ls -al "$TEST_DIR"
cd "$TEST_DIR"
echo "Beginning tests..."
if [ ! -z ''${REPORTOUT+x} ]; then
echo -e "[\n" > "$REPORTOUT"
fi
export FULL_REPORT_MODE=true
${runGeneratorFor nix-stable "Stable" "$TEST_DIR"}
if [ ! -z ''${REPORTOUT+x} ]; then
echo "," >> "$REPORTOUT"
fi
${runGeneratorFor nix-lst "LST" "$TEST_DIR"}
if [ ! -z ''${REPORTOUT+x} ]; then
echo -e "\n]" >> "$REPORTOUT"
# Pretty-format the file to the format guessed by extension
REPORTEXT="''${REPORTOUT${"##"}*.}"
REPORTFORMAT="''${REPORTEXT:-auto}"
echo "Interpreting path format as \"$REPORTFORMAT\""
"${"${pkgs.yq-go}/bin/yq"}" --indent 2 -M -P '.' --input-format=json --output-format="$REPORTFORMAT" -i "$REPORTOUT"
fi
echo "You may wish to delete the content of "$TEST_DIR", if you do not want to rerun any of the above scenarios for logs."
'';
in {
generator = generator; # Report generator
inherit fullReportGenerator; # Report generator for both prior-correct and LST-failing cases
inherit availableModeFlags; # Display with `nix eval .#report.availableModeFlags`
inherit configurations; # Display pretty output with `nix eval .#report.configurations --json | nix-shell -p yq --command yq`
}
);
}
);
}