From a553ef2950e1e7f35491c19c3b61ba22e73a0d08 Mon Sep 17 00:00:00 2001 From: Wolfgang Walther Date: Sat, 10 May 2025 21:55:05 +0200 Subject: [PATCH] ci/parse: init The nix-parse workflow can now be run locally the same way as in CI. To do this, the CI's workflow was slightly adjusted. Instead of testing only the changed files, we're now testing all files in the repository. This is possible in two ways: 1. By calling nix-instantiate once with all files as arguments. This will be rather fast, but only the first error is shown before it errors out. 2. By calling nix-instantiate once for each file. This will be much slower, but has the advantage that we see all errors at once. To avoid running the long variant every time, we first do a quick check with the fast version. If that fails, we run the slower one to report the errors. This gives us the best of both. --- .github/workflows/nix-parse-v2.yml | 21 ++------------- ci/default.nix | 3 +++ ci/parse.nix | 43 ++++++++++++++++++++++++++++++ 3 files changed, 48 insertions(+), 19 deletions(-) create mode 100644 ci/parse.nix diff --git a/.github/workflows/nix-parse-v2.yml b/.github/workflows/nix-parse-v2.yml index cc988e20bd6e..706cc34619bb 100644 --- a/.github/workflows/nix-parse-v2.yml +++ b/.github/workflows/nix-parse-v2.yml @@ -15,18 +15,6 @@ jobs: needs: get-merge-commit if: "needs.get-merge-commit.outputs.mergedSha && !contains(github.event.pull_request.title, '[skip treewide]')" steps: - - name: Get list of changed files from PR - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - run: | - gh api \ - repos/${{ github.repository }}/pulls/${{github.event.number}}/files --paginate \ - | jq --raw-output '.[] | select(.status != "removed" and (.filename | endswith(".nix"))) | .filename' \ - > "$HOME/changed_files" - if [[ -s "$HOME/changed_files" ]]; then - echo "CHANGED_FILES=$HOME/changed_files" > "$GITHUB_ENV" - fi - - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: ref: ${{ needs.get-merge-commit.outputs.mergedSha }} @@ -37,11 +25,6 @@ jobs: extra_nix_config: sandbox = true nix_path: nixpkgs=channel:nixpkgs-unstable - - name: Parse all changed or added nix files + - name: Parse all nix files run: | - ret=0 - while IFS= read -r file; do - out="$(nix-instantiate --parse "$file")" || { echo "$out" && ret=1; } - done < "$HOME/changed_files" - exit "$ret" - if: ${{ env.CHANGED_FILES && env.CHANGED_FILES != '' }} + nix-build ci -A parse diff --git a/ci/default.nix b/ci/default.nix index 396fb172df23..67b1eddf1000 100644 --- a/ci/default.nix +++ b/ci/default.nix @@ -76,5 +76,8 @@ in manual-nixos = (import ../nixos/release.nix { }).manual.${system} or null; manual-nixpkgs = (import ../pkgs/top-level/release.nix { }).manual; manual-nixpkgs-tests = (import ../pkgs/top-level/release.nix { }).manual.tests; + parse = pkgs.lib.recurseIntoAttrs { + latest = pkgs.callPackage ./parse.nix { nix = pkgs.nixVersions.latest; }; + }; shell = import ../shell.nix { inherit nixpkgs system; }; } diff --git a/ci/parse.nix b/ci/parse.nix new file mode 100644 index 000000000000..26ac0f785fd4 --- /dev/null +++ b/ci/parse.nix @@ -0,0 +1,43 @@ +{ + lib, + nix, + runCommand, +}: +let + nixpkgs = + with lib.fileset; + toSource { + root = ../.; + fileset = (fileFilter (file: file.hasExt "nix") ../.); + }; +in +runCommand "nix-parse-${nix.name}" + { + nativeBuildInputs = [ + nix + ]; + } + '' + export NIX_STORE_DIR=$TMPDIR/store + export NIX_STATE_DIR=$TMPDIR/state + + cd "${nixpkgs}" + + # Passes all files to nix-instantiate at once. + # Much faster, but will only show first error. + parse-all() { + find . -type f -iname '*.nix' | xargs -P $(nproc) nix-instantiate --parse >/dev/null 2>/dev/null + } + + # Passes each file separately to nix-instantiate with -n1. + # Much slower, but will show all errors. + parse-each() { + find . -type f -iname '*.nix' | xargs -n1 -P $(nproc) nix-instantiate --parse >/dev/null + } + + if ! parse-all; then + parse-each + fi + + touch $out + ''