about summary refs log tree commit diff
path: root/.github/workflows/check-nix-format.yml
blob: eed685946c3bc7c787f84c8f8a1a7e245c9f1aec (plain) (blame)
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
# This file was copied mostly from check-maintainers-sorted.yaml.
# NOTE: Formatting with the RFC-style nixfmt command is not yet stable. See
# https://github.com/NixOS/rfcs/pull/166.
# Because of this, this action is not yet enabled for all files -- only for
# those who have opted in.
name: Check that Nix files are formatted

on:
  pull_request_target:
    # See the comment at the same location in ./check-by-name.yml
    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 nixfmt
        run: |
          # pin to a commit from nixpkgs-unstable to avoid e.g. building nixfmt
          # 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 nixfmt
        run: "nix-env -f '<nixpkgs>' -iAP nixfmt-rfc-style"
      - name: Check that Nix files are formatted according to the RFC style
        run: |
          unformattedFiles=()

          # 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

            # Ignore files that weren't already formatted
            if [[ -n "$source" ]] && ! nixfmt --check ${{ env.base }}/"$source" 2>/dev/null; then
              echo "Ignoring file $file because it's not formatted in the base commit"
            elif ! nixfmt --check "$dest"; then
              unformattedFiles+=("$dest")
            fi
          done < <(git diff -z --name-status ${{ env.baseRev }} -- '*.nix')

          if (( "${#unformattedFiles[@]}" > 0 )); then
            echo "Some new/changed Nix files are not properly formatted"
            echo "Please run the following in \`nix-shell\`:"
            echo "nixfmt ${unformattedFiles[*]@Q}"
            exit 1
          fi