본문으로 바로가기

github action을 이용하여 PR시 효율적으로 tsc, eslint 검사하기

github action을 이용하여 PR시 merge branch 코드를 검사할 필요가 있습니다.

하고 싶은 것

PR 시 merge branch의 코드가 정상적인지 검사할 필요가 있음.
monorepo 프로젝트이기 때문에 변경된 모든 프로젝트를 검사해야함.

기존 해결 방법 및 문제점 [1]

커밋 메시지 컨벤션으로 커밋 메시지에 변경된 파일의 프로젝트 명을 작성하게 하였습니다.
그럼 해당 커밋에서 어떠한 프로젝트의 파일이 변경되었는지 파악할 수 있습니다.
해당 정보를 이용하여 변경된 파일의 프로젝트를 tsc, eslint를 수행하여 문제를 해결하였습니다.

그러나 위 방법은 너무 오랜 시간이 소요된다는 문제가 있었습니다.
만약 커밋을 3개하는 경우 프로젝트 tsc, eslint를 총 3번 하는 것이기 때문에 오랜 시간이 소요되었습니다.
또한 해당 작업을 수행할 때 동안은 코드 수정이 불가능하다는 단점도 있었습니다.

위 작업을 PR 요청 보낼 때, 1번만 수행하면 되겠다는 생각이 들어 github action으로 해결해보았습니다.

기존 해결 방법 및 문제점 [2]

첫번째는 커밋 메시지마다 검사를 하였다면 이제 PR 요청 시 한번만 tsc, eslint 작업을 하는 것입니다.
동일하게 변경된 프로젝트만 tsc, eslint를 작업해야 하기 때문에 PR 레이블에 모노레포에 있는 프로젝트 이름을 모두 적어주었습니다.
PR 문서가 생성, 수정 등 이벤트가 들어올 때마다 레이블을 확인하여 해당 프로젝트에 대해 tsc, eslint가 수행되었습니다.

위 방식은 나쁘지 않았습니다. 그러나 PR 레이블에 모든 프로젝트를 적어주어야 한다는 점이 불편하였습니다.
또한, 개발자가 변경된 프로젝트의 레이블 이름을 선택하지 않거나 잘못 선택한 경우 제대로 동작하지 않았습니다.
마지막으로 eslint의 경우 경우 변경된 파일만 수행하면 되는데 해당 프로젝트를 모두 수행하여 시간이 오래 걸리는 점이 문제가 되었습니다.

최종 해결 방법 [3]

위 방식과 동일하게 github action으로 문제를 해결하였습니다.
그러나 이번에는 목표를 정하고 접근을 하였습니다.

목표

  • 레이블에 있는 프로젝트 명 삭제 및 변경된 파일의 프로젝트 명 가져오기.
  • 변경된 파일만 eslint 수행

위 2가지 목표를 달성하는 것은 생각보다 간단하였습니다.

레이블에 있는 프로젝트 명 삭제 및 변경된 파일의 프로젝트 명 가져오기

불편하게 매번 변경된 프로젝트를 레이블로 선택해야 하는 점을 개선하고 싶었습니다.
tj-actions/changed-files을 이용하면 매우 쉽게 변경된 파일명을 가져올 수 있습니다.
추출된 파일명을 분석하여 변경된 프로젝트 이름을 확인할 수 있었습니다. 따라서 변경된 프로젝트만 tsc를 수행할 수 있었습니다.

- name: Check for changed ts files
  if: steps.changed-files.outputs.any_changed == 'true'
  env:
    TS_CHANGED_FILES: ${{ steps.changed-files.outputs.all_changed_files }}
  run: |
    for file in ${TS_CHANGED_FILES}; do
      echo "$file was changed"
    done

- name: Identify packages with changed files
  run: |
    PACKAGES=()
    for file in ${{ steps.changed-files.outputs.all_changed_files }}; do
      if [[ ! " ${PACKAGES[@]} " =~ " main " && "$file" == packages/main/* ]]; then
        PACKAGES+=("main")
      elif [[ ! " ${PACKAGES[@]} " =~ " sub1 " && "$file" == packages/sub1/* ]]; then
        PACKAGES+=("sub1")
      elif [[ ! " ${PACKAGES[@]} " =~ " sub2 " && "$file" == packages/sub2/* ]]; then
        PACKAGES+=("sub2")
      fi
      if [[ ${#PACKAGES[@]} -eq 3 ]]; then
        break
      fi
    done
    echo "UNIQUE_PACKAGES=${PACKAGES[@]}" >> $GITHUB_ENV

- name: Run tsc
  id: tsc-check
  run: |
    IFS=' ' read -r -a PACKAGES <<< "${{ env.UNIQUE_PACKAGES }}"
    for package in "${PACKAGES[@]}"; do
      echo "Type-checking package: $package"
      OUTPUT=$(yarn "$package" tsc 2>&1)
    done

Identify packages with changed files를 보시면 모노레포 프로젝트 이름이 if문에 있는 것을 확인할 수 있습니다.
프로젝트 이름을 if문에 작성해주시면 됩니다.
PACKAGES 크기가 프로젝트 개수만큼 되었으면 강제로 for문을 종료하였습니다.

변경된 파일만 eslint 수행

eslint가 생각보다 오랜 시간이 소요됩니다.
따라서 변경된 파일에 대해서만 eslint를 수행하고 싶었습니다.
tj-actions/eslint-changed-files를 이용하면 간단하게 변경된 파일만 eslint 작업을 할 수 있습니다.
그러나 Next14로 테스트 하고 있었는데 eslint 9 버전으로 계속 에러가 발생하였습니다.
따라서 Next 프로젝트를 생성할 때, eslint 버전이 8로 설정되어 있는 것을 확인하고 eslint 8을 사용하는 버전으로 해당 작업을 수행하였습니다.

- name: Run eslint on changed files
  uses: tj-actions/eslint-changed-files@v23.2.0
  with:
    file_extensions: |
      **/*.ts
      **/*.tsx
    extra_args: "--max-warnings=0"
    token: ${{ secrets.ESLINT_TOKEN }}

file_extensions을 이용하여 변경된 .ts, .tsx 파일만 확인하였습니다.
댓글이 달리기 위해서는 token이 필요한 것 같아 추가해주었습니다.

위 2가지 방법으로 불편했던 점을 모두 개선하였습니다.

반응형