Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
infinisil committed Nov 18, 2024
1 parent 3364d66 commit e950e10
Show file tree
Hide file tree
Showing 11 changed files with 317 additions and 186 deletions.
60 changes: 50 additions & 10 deletions .github/workflows/eval.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ permissions:
contents: read

jobs:
tests:
name: eval-check
attrs:
name: Attrs
runs-on: ubuntu-latest
strategy:
matrix:
system: [x86_64-linux, aarch64-linux, aarch64-darwin, x86_64-darwin]
outputs:
systems: ${{ steps.systems.outputs.systems }}
mergedSha: ${{ steps.merged.outputs.mergedSha }}
steps:
# Important: Because of `pull_request_target`, this doesn't check out the PR,
# but rather the base branch of the PR, which is needed so we don't run untrusted code
Expand All @@ -20,26 +20,66 @@ jobs:
path: base
sparse-checkout: ci
- name: Resolving the merge commit
id: merged
env:
GH_TOKEN: ${{ github.token }}
run: |
if mergedSha=$(base/ci/get-merge-commit.sh ${{ github.repository }} ${{ github.event.number }}); then
echo "Checking the merge commit $mergedSha"
echo "mergedSha=$mergedSha" >> "$GITHUB_ENV"
echo "mergedSha=$mergedSha" >> "$GITHUB_OUTPUT"
else
# Skipping so that no notifications are sent
echo "Skipping the rest..."
fi
rm -rf base
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
# Add this to _all_ subsequent steps to skip them
if: env.mergedSha
if: outputs.merged.mergedSha
with:
ref: ${{ env.mergedSha }}
path: nixpkgs

- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
if: outputs.merged.mergedSha

- id: systems
if: outputs.merged.mergedSha
run: |
nix-build nixpkgs/ci -A eval.evalPlan
echo "systems=$(<result/systems.json)" > "GITHUB_OUTPUT"
- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 v4.4.3
if: outputs.merged.mergedSha
with:
name: eval-plan
path: result/systems

eval:
name: Eval
runs-on: ubuntu-latest
needs: attrs
if: needs.attrs.outputs.mergedSha
strategy:
matrix:
system: ${{ fromJSON(needs.attrs.outputs.systems) }}
steps:
- uses: actions/download-artifact@fa0a91b85d4f404e444e00e005971372dc801d16 # v4.1.8
with:
name: eval-plan
path: systems

- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
with:
ref: ${{ needs.attrs.outputs.mergedSha }}
path: nixpkgs

- uses: cachix/install-nix-action@08dcb3a5e62fa31e2da3d490afc4176ef55ecd72 # v30
if: env.mergedSha

- name: Check eval
if: env.mergedSha
run: ./ci/eval-nixpkgs.sh --system "${{ matrix.system }}"
run: nix-build nixpkgs/ci -A eval.singleJob --arg jobDir systems/${{ matrix.system }}

- uses: actions/upload-artifact@b4b15b8c7c6ac21ea08fcf65892d2ee8f75cf882 v4.4.3
if: outputs.merged.mergedSha
with:
name: result-${ matrix.system }}
path: result/paths
1 change: 1 addition & 0 deletions ci/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -26,4 +26,5 @@ in
inherit pkgs;
requestReviews = pkgs.callPackage ./request-reviews { };
codeownersValidator = pkgs.callPackage ./codeowners-validator { };
eval = pkgs.callPackage ./eval { };
}
89 changes: 0 additions & 89 deletions ci/eval-nixpkgs.sh

This file was deleted.

213 changes: 213 additions & 0 deletions ci/eval/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,213 @@
{
lib,
runCommand,
writeShellScript,
time,
procps,
nix,
jq,
}:

# Use the GitHub Actions cache to cache /nix/store
# Although can't really merge..
# Use artifacts and pass files manually, also doesn't have to repeat eval then
let
nixpkgs = with lib.fileset; toSource {
root = ../..;
fileset = unions (map (lib.path.append ../..) [
"default.nix"
"doc"
"lib"
"maintainers"
"nixos"
"ci"
"pkgs"
".version"
]);
};

attrpathsSuperset =
runCommand "attrpaths-superset.json" {
src = nixpkgs;
nativeBuildInputs = [
nix
];
}
''
export NIX_STATE_DIR=$(mktemp -d)
mkdir $out
nix-instantiate --eval --strict --json $src/pkgs/top-level/release-attrpaths-superset.nix -A paths > $out/paths.json
'';

# Takes a path to an attrpathsSuperset result and computes the result of evaluating it entirely
evalPlan =
{
# null means as many cores as your machine has
cores ? null,
# How many attributes to be evaluating at any single time.
# This effectively limits the maximum memory usage.
# Decrease this if too much memory is used
simultaneousAttrsPerSystem ? 100000,
checkMeta ? true,
includeBroken ? true,
# TODO
quickTest ? false,
}:
runCommand "eval-plan" {
nativeBuildInputs = [
jq
];
env.cores = toString cores;
supportedSystems = builtins.toJSON (import ../supportedSystems.nix);
passAsFile = [ "supportedSystems" ];
} ''
if [[ -z "$cores" ]]; then
cores=$(nproc)
fi
echo "Cores: $cores"
num_attrs=$(jq length "${attrpathsSuperset}/paths.json")
echo "Attribute count: $num_attrs"
chunk_size=$(( ${toString simultaneousAttrsPerSystem} / cores ))
echo "Chunk size: $chunk_size"
# Same as `num_attrs / chunk_size` but rounded up
num_chunks=$(( (num_attrs - 1) / chunk_size + 1 ))
echo "Chunk count: $num_chunks"
mkdir -p $out/systems
mv "$supportedSystemsPath" $out/systems.json
echo "Systems: $(<$out/systems.json)"
for system in $(jq -r '.[]' "$out/systems.json"); do
mkdir -p "$out/systems/$system/chunks"
printf "%s" "$cores" > "$out/systems/$system/cores"
for chunk in $(seq -w 0 "$(( num_chunks - 1 ))"); do
jq '{
paths: .[($chunk * $chunk_size):(($chunk + 1) * $chunk_size)],
systems: [ $system ],
checkMeta: $checkMeta,
includeBroken: $includeBroken
}' \
--argjson chunk "$chunk" \
--argjson chunk_size "$chunk_size" \
--arg system "$system" \
--argjson checkMeta "${lib.boolToString checkMeta}" \
--argjson includeBroken "${lib.boolToString includeBroken}" \
${attrpathsSuperset}/paths.json \
> "$out/systems/$system/chunks/$chunk.json"
done
done
'';


singleSystem =
let
singleChunk = writeShellScript "chunk" ''
set -euo pipefail
chunkFile=$1
outputDir=$2
nix-env -f "${nixpkgs}/ci/eval/parallel.nix" \
--query --available \
--no-name --attr-path --out-path \
--show-trace \
--arg chunkFile "$chunkFile" > "$outputDir/$(basename "$chunkFile")"
'';
in
{
systemDir,
}:
runCommand "nixpkgs-eval-system-${baseNameOf systemDir}" {
nativeBuildInputs = [
nix
time
procps
];
} ''
export NIX_STATE_DIR=$(mktemp -d)
nix-store --init
cores=$(<${systemDir}/cores)
chunkOutputDir=$(mktemp -d)
(
while true; do
free -g
sleep 20
done
) &
find ${systemDir}/chunks -name '*.json' -print0 |
command time -v xargs -0 -t -I{} -P"$cores" \
${singleChunk} {} "$chunkOutputDir"
cat "$chunkOutputDir"/* > $out/paths
'';

combine =
{

}: null;

# mkdir $out
# for system in ${lib.escapeShellArgs (import ../supportedSystems.nix)}; do

# done

#'';

# Files of the form
# $out/<matrix-index>/<number>.json
# {
# paths: [ [ ... ], ... ],
# system: ...,
# }

#attrsSuperset = import ../../pkgs/test/release {
# # Important: This is used to get dependencies for the evaluation itself.
# # Because we don't want it to take forever on staging PRs,
# # this uses the pinned CI version instead.
# inherit pkgs;
#};

# How to get the list of supported systems?
# ci/supportedSystems.nix

#chunkResult =
# {
# # null means all default systems
# # Pass a list of strings to select specific ones
# system,
# attrsSupersetFile,
# myChunk,
# }:
# pkgs.runCommand "chunk-result-${system}-${toString myChunk}" ''
# '';

#combinedResult =
# {
# chunkResults,
# }:
# pkgs.runCommand "combined-result" {
# passAsFile = [ "jqScript" ];
# jqScript = /* jq */ ''
# split("\n") |
# map(select(. != "") | split(" ") | map(select(. != ""))) |
# map(
# {
# key: .[0],
# value: .[1] | split(";") | map(split("=") |
# if length == 1 then
# { key: "out", value: .[0] }
# else
# { key: .[0], value: .[1] }
# end) | from_entries}
# ) | from_entries
# '';
# } ''
# cat ${lib.escapeShellArgs chunkResults} |
# jq --raw-input --slurp -f "$jqScriptPath" "$tmpdir/paths" \
# > $out/outpaths.json
# '';
in
{
inherit attrpathsSuperset evalPlan singleSystem;
}
Loading

0 comments on commit e950e10

Please sign in to comment.