Search code examples
gitgithubgithub-actionseslintprettier

Trying to create a Github action that auto lints and formats the changed code in a PR


I have two Github actions one for auto formating and another for linting:

Auto lint

name: Lint changed files

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  auto_lint:
    runs-on: ubuntu-latest
    env:
      BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
    steps:
      - name: Start checkout action
        uses: 'actions/checkout@v4'
      
      - name: Setup Node.js
        uses: 'actions/setup-node@v4'
        with:
          node-version: 20

      - name: Setup pnpm
        uses: 'pnpm/action-setup@v4'
        with:
          version: 8

      - name: Get changed files
        id: changed-files
        uses: 'tj-actions/changed-files@v44'

      - name: Install dependencies
        run: pnpm install
        
      - name: Lint all changed files
        if: steps.changed-files.outputs.any_changed == 'true'
        env:
          ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
        run: |
          for file in ${ALL_CHANGED_FILES}; do
            pnpm lint:check $file
          done
          
      - name: No changes to lint
        if: steps.changed-files.outputs.any_changed != 'true'
        run: echo "No changes files to lint"

Auto format

name: Format changed files

on:
  pull_request:
    types: [opened, synchronize, reopened]

jobs:
  auto_format:
    runs-on: ubuntu-latest
    env:
      BRANCH_NAME: ${{ github.head_ref || github.ref_name }}
    steps:
      - name: Start checkout action
        uses: 'actions/checkout@v4'
      
      - name: Setup Node.js
        uses: 'actions/setup-node@v4'
        with:
          node-version: 20

      - name: Setup pnpm
        uses: 'pnpm/action-setup@v4'
        with:
          version: 8

      - name: Get changed files
        id: changed-files
        uses: 'tj-actions/changed-files@v44'
        
      - name: Install dependencies
        run: pnpm install
        
      - name: format all changed files
        if: steps.changed-files.outputs.any_changed == 'true'
        env:
          ALL_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
        run: |
          for file in ${ALL_CHANGED_FILES}; do
            pnpm format:fix $file
          done

          git config user.name "github-actions[bot]"
          git config user.email "github-actions[bot]@users.noreply.github.com"
          git add .
          git commit -m "style: auto format"
          git push     
      - name: No changes to format
        if: steps.changed-files.outputs.any_changed != 'true'
        run: echo "No changes files to format"

When running these two with Act and github actions they fail with the error:

[Lint Changed Files/Lint Changed Files            ]   ✅  Success - Main Install dependencies
[Lint Changed Files/Lint Changed Files            ] ⭐ Run Main Get changed files
[Lint Changed Files/Lint Changed Files            ]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/changed-files] user= workdir=
[Lint Changed Files/Lint Changed Files            ]   ✅  Success - Main Get changed files
[Lint Changed Files/Lint Changed Files            ] ⭐ Run Main Create lint script for changed files
[Lint Changed Files/Lint Changed Files            ]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/5] user= workdir=
[Lint Changed Files/Lint Changed Files            ]   ✅  Success - Main Create lint script for changed files
[Lint Changed Files/Lint Changed Files            ] ⭐ Run Main Run linter on changed files
[Lint Changed Files/Lint Changed Files            ]   🐳  docker exec cmd=[bash --noprofile --norc -e -o pipefail /var/run/act/workflow/6] user= workdir=
| ./lint.sh: line 1: No: command not found
[Lint Changed Files/Lint Changed Files            ]   ❌  Failure - Main Run linter on changed files
[Lint Changed Files/Lint Changed Files            ] exitcode '127': command not found, please refer to https://github.com/nektos/act/issues/107 for more information
[Lint Changed Files/Lint Changed Files            ] 🏁  Job failed

[run-tests/format changed files                   ]   ❓  ::endgroup::
[run-tests/format changed files                   ]   ❓ add-matcher /run/act/actions/actions-setup-node@v4/.github/tsc.json
[run-tests/format changed files                   ]   ❓ add-matcher /run/act/actions/actions-setup-node@v4/.github/eslint-stylish.json
[run-tests/format changed files                   ]   ❓ add-matcher /run/act/actions/actions-setup-node@v4/.github/eslint-compact.json
[run-tests/format changed files                   ]   ✅  Success - Main actions/setup-node@v4
[run-tests/format changed files                   ]   ⚙  ::set-output:: node-version=v20.14.0
[run-tests/format changed files                   ]   ⚙  ::add-path:: /opt/hostedtoolcache/node/20.14.0/arm64/bin
[run-tests/format changed files                   ] ⭐ Run Main actions/checkout@v4
[run-tests/format changed files                   ]   🐳  docker cp src=/Users/ekrich/git/eTech-UI/. dst=/Users/ekrich/git/eTech-UI
| npm error code ENOTEMPTY
| npm error syscall rename
| npm error path /opt/hostedtoolcache/node/20.14.0/arm64/lib/node_modules/pnpm
| npm error dest /opt/hostedtoolcache/node/20.14.0/arm64/lib/node_modules/.pnpm-i4BzBorb
| npm error errno -39
| npm error ENOTEMPTY: directory not empty, rename '/opt/hostedtoolcache/node/20.14.0/arm64/lib/node_modules/pnpm' -> '/opt/hostedtoolcache/node/20.14.0/arm64/lib/node_modules/.pnpm-i4BzBorb'
| 
| npm error A complete log of this run can be found in: /root/.npm/_logs/2024-06-08T03_31_06_800Z-debug-0.log
[Autoformat Changed Files/Autoformat Changed Files]   ❌  Failure - Main Install pnpm
[Autoformat Changed Files/Autoformat Changed Files] exitcode '217': failure
[Autoformat Changed Files/Autoformat Changed Files] 🏁  Job failed
[run-tests/format changed files                   ]   ✅  Success - Main actions/checkout@v4
[run-tests/format changed files                   ] ⭐ Run Main pnpm install

Any idea what is wrong here? Is there a pre-made action I can use instead? I've tried using actions/changed-files but that doesn't work either.

Refrences I've looked at but still had no luck in:


Solution

  • Diagnostic

    For the lint, the problem is that what you created is not a proper script.

    The line

    echo "No JavaScript or TypeScript files were changed." > lint.sh
    

    is what ends up having been run, based on the error message ./lint.sh: line 1: No: command not found, and indeed, you've created script lint.sh with the contents

    No JavaScript or TypeScript files were changed.
    

    which is definitely not a valid script.

    General recommendation

    The way you're trying to create a script inside the action is really not ideal. The solution I would recommend is to write your lint.sh and format.sh scripts locally, where you can test them easily until they work on your own machine. Put the loop over changed files right in there. Then add those scripts to your repo and just call them in the action workflow, passing in the changed_files.txt file as an argument.

    A more precise solution

    This should work for you, instead of the Create format script for changes files and Run formatter on changed files steps:

          - name: Run formatter on changed files of interest
            run: cat changed_files.txt | grep -E '\.(js|ts|tsx|cjs|mjs|astro|spec.ts|mdx)$' | xargs --no-run-if-empty pnpm run format --
    

    And for the linter, replace format by lint:check.

    Explanation:

    • grep the list of changed files for the extensions you care about
    • pass the results as argument to your pnpm command
    • use xargs's --no-run-if-empty option to avoid calling pnpm with an empty list of files