From b4828820894f40cf6550b2b0fe982f238253f312 Mon Sep 17 00:00:00 2001 From: aleksana Date: Fri, 26 Jul 2024 12:47:50 +0800 Subject: [PATCH] workflow/check-nixf-tidy.yml: init --- .github/workflows/check-nixf-tidy.yml | 98 +++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) create mode 100644 .github/workflows/check-nixf-tidy.yml diff --git a/.github/workflows/check-nixf-tidy.yml b/.github/workflows/check-nixf-tidy.yml new file mode 100644 index 000000000000000..820e030d3ecc60d --- /dev/null +++ b/.github/workflows/check-nixf-tidy.yml @@ -0,0 +1,98 @@ +name: Check changed Nix files with nixf-tidy (experimental) + +on: + pull_request_target: + types: [opened, synchronize, reopened, edited] +permissions: + contents: read + +jobs: + nixos: + runs-on: ubuntu-latest + if: "!contains(github.event.pull_request.title, '[skip treewide]')" + steps: + - uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 + with: + # pull_request_target checks out the base branch by default + ref: refs/pull/${{ github.event.pull_request.number }}/merge + # Fetches the merge commit and its parents + fetch-depth: 2 + - name: Checking out base branch + run: | + base=$(mktemp -d) + baseRev=$(git rev-parse HEAD^1) + git worktree add "$base" "$baseRev" + echo "baseRev=$baseRev" >> "$GITHUB_ENV" + echo "base=$base" >> "$GITHUB_ENV" + - name: Get Nixpkgs revision for nixf + run: | + # pin to a commit from nixpkgs-unstable to avoid e.g. building nixf + # from staging + # This should not be a URL, because it would allow PRs to run arbitrary code in CI! + rev=$(jq -r .rev ci/pinned-nixpkgs.json) + echo "url=https://github.com/NixOS/nixpkgs/archive/$rev.tar.gz" >> "$GITHUB_ENV" + - uses: cachix/install-nix-action@ba0dd844c9180cbf77aa72a116d6fbc515d0e87b # v27 + with: + # explicitly enable sandbox + extra_nix_config: sandbox = true + nix_path: nixpkgs=${{ env.url }} + - name: Install nixf and jq + # provided jq is incompatible with our expression + run: "nix-env -f '' -iAP nixf jq" + - name: Check that Nix files pass nixf-tidy + run: | + failedFiles=() + + # TODO: Make this more parallel + + # Loop through all Nix files touched by the PR + while readarray -d '' -n 2 entry && (( ${#entry[@]} != 0 )); do + type=${entry[0]} + file=${entry[1]} + case $type in + A*) + source="" + dest=$file + ;; + M*) + source=$file + dest=$file + ;; + C*|R*) + source=$file + read -r -d '' dest + ;; + *) + echo "Ignoring file $file with type $type" + continue + esac + + if [[ -n "$source" ]] && [[ "$(nixf-tidy --variable-lookup < ${{ env.base }}/"$source")" != '[]' ]] 2>/dev/null; then + echo "Ignoring file $file because it doesn't pass nixf-tidy in the base commit" + echo # insert blank line + else + nixf_report="$(nixf-tidy --variable-lookup < "$dest")" + if [[ "$nixf_report" != '[]' ]]; then + echo "$dest doesn't pass nixf-tidy. Reported by nixf-tidy:" + echo # insert blank line + echo "$nixf_report" | jq -r ' + def getLCur: "line=" + (.line+1|tostring) + ",col=" + (.column|tostring); + def getRCur: "endLine=" + (.line+1|tostring) + ",endColumn=" + (.column|tostring); + def getRange: "file={{}}," + (.lCur|getLCur) + "," + (.rCur|getRCur); + def getBody: . as $top|(.range|getRange) + ",title="+ .sname + "::" + + (.message|sub("{}" ; ($top.args.[]|tostring))); + def getNote: "\n::notice " + (.|getBody); + def getMessage: "::error " + (.|getBody) + (if (.notes|length)>0 then + (.notes.[]|getNote) else "" end); + .[]|getMessage + ' | sed "s/{{}}/$dest/" + failedFiles+=("$dest") + fi + fi + done < <(git diff -z --name-status ${{ env.baseRev }} -- '*.nix') + + if (( "${#failedFiles[@]}" > 0 )); then + echo "Some new/changed Nix files don't pass nixf-tidy" + echo "If you believe this is a false positive, ping @Aleksanaa in this PR." + exit 1 + fi