린팅 일관성

discourse-plugin-skeleton에서 모든 린트 관련 설정을 내 플러그인으로 복사해왔다고 맹세합니다. 그런데 플러그인 디렉터리에서 다음을 실행하면

pnpm prettier  --write "assets/**/*.{scss,js,gjs,hbs}"

결과가 discourse 코어 디렉터리에서 다음을 실행했을 때와 다릅니다.

./bin/lint  --fix plugins/discourse-pfaffmanager/assets/**/*.{scss,js,gjs,hbs}

예상대로, GitHub Actions가 실행될 때의 결과와 일치하는 건 후자입니다.

정말 원하는 건 VSCode에서 파일을 저장할 때 '올바른 것’이 실행되는 건데, 이건 아마도 또 다른 문제일 것 같습니다.

네, @cvx / @david

저도 이 부분을 눈치챘습니다… 플러그인에서의 린팅은 전부 눈덩이처럼 커지는 문제(snowflake material)입니다. CI에서 구식과 신식 린팅 스타일을 위한 분기가 있고, 리포지토리에 상당한 설정이 필요합니다.

훌륭한 목표는 bin/lint가 플러그인과 테마에서도 작동하도록 수정하는 것이라고 생각합니다. 아직 이를 구현하지 않았으며, 현재는 코어와 코어 플러그인에서만 작동합니다.

실제로 테마/플러그인에 대한 린팅은 코어와 의도적으로 분리되어 있습니다. 테마/플러그인은 린팅 도구의 서로 다른 버전과 설정을 사용할 수 있습니다. 이는 모든 저장소에서 린팅이 갑자기 깨지지 않도록 변경 사항을 배포할 수 있게 하므로 필수적입니다.

bin/lint를 작동하도록 만들 수도 있습니다. 플러그인/테마 디렉토리로 cd를 하고, pnpm i를 실행한 후 해당 디렉토리 컨텍스트에서 린팅 명령을 실행해야 합니다. 하지만 절대 코어의 린팅 설정을 테마/플러그인에 적용하려는 시도를 해서는 안 됩니다.

그렇게 되어야 합니다. 우리 팀의 대부분이 VSCode(또는 VSCode 파생 제품)를 사용하므로, 우리는 그것을 위해 최적화하고 있습니다. Eslint와 Prettier VSCode 플러그인은 주어진 파일에 대해 ‘가장 가까운’ 설치와 설정을 검색합니다.

테마/플러그인 디렉토리에서 pnpm i를 실행해 보셨나요? 린팅 의존성을 설치하려면 이 작업이 필요하며, 이렇게 해야 VSCode가 사용할 올바른 prettier/eslint 복사본을 찾을 수 있습니다.

흥미로운 전개입니다.

  • 코어의 규칙을 선택적으로 실행할 수 있도록 허용
  • 코어의 규칙을 실행하도록 기존 설정을 재구성할 수 있도록 허용

그렇게 하면 어떤 이점이 있을까요? :sweat_smile:

테마/플러그인 린팅은 코어와 근본적으로 다릅니다. 테마/플러그인에 특화된 규칙들이 있습니다. 테마에는 ESLint가 알아야 할 자체 마법 전역 변수(themePrefix/settings)가 있습니다.

우리는 이를 매우 신중하게 관리하고, 테마/플러그인 스켈레톤 저장소에 이를 문서화하며, mass-PR을 통해 변경 사항을 체계적으로 배포하고 있습니다.

자기 업그레이드를 위한 도구로 사용할 수 있겠지만, 다른 시스템들도 있다는 점은 충분히 이해합니다.

아, 그렇군요. 자동 업데이트용 스크립트(스켈레톤에서 가져오는 것)는 여기에 있습니다. 이 스크립트를 단일 테마/플러그인에서 실행하기 더 쉽게 만드는 것도 좋은 프로젝트가 될 수 있겠네요. :+1:

참고로, 제가 설정이 다르다고 할 때 모든 곳에 설정을 중복해서 만든다는 의미는 아닙니다. 버전 관리가 되는 lint configs 패키지를 사용하고 있으며, 여기에는 prettier, eslint, stylelint, ember-template-lint의 공유 설정이 포함되어 있습니다. 이 패키지는 코어와 모든 테마/플러그인에서 사용됩니다. 테마/플러그인을 최신 규칙으로 업그레이드하는 것은 보통 package.json에서 lint-configs 버전을 올리는 것만으로 가능합니다.

하지만 플러그인에서 수행되는 린팅을 따를 경우, GitHub Action에서 린팅 테스트가 실패하는 것 같습니다.

아하!!! pnpm i가 제가 놓치고 있던 마법이었던 것 같습니다. discourse 코어를 업데이트하는 스크립트와 린팅을 수행하는 스크립트에 'pnpm i’를 추가했습니다. . .

그래서 이제 제 스크립트는 다음과 같이 동작합니다:

if [[ "$ARG" == "eslint" ]]
then
  # See https://github.com/discourse/.github/blob/main/.github/workflows/discourse-plugin.yml
  if [ -f plugin.rb ]
  then
    echo "Linting current directory."
  else
    echo "Not on a plugin. Using $DEFAULT_PLUGIN"
    cd $DEFAULT_PLUGIN
  fi
  echo "LINTING $(pwd)"
  #cd /home/pfaffman/src/literatecomputing/discourse-display-email
  # pnpm install
  echo "Doing `pnpm i`"
  pnpm -i

  echo -n ESLINT. . .
  pnpm eslint --no-error-on-unmatched-pattern {test,assets,admin/assets}/javascripts
  exit_code="$?"
  if [[ $exit_code -ne 0  ]]
  then
    echo "eslint was unhappy -- $exit_code -- trying to fix"
    pnpm eslint --fix --no-error-on-unmatched-pattern {test,assets,admin/assets}/javascripts
    exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "eslint was still unhappy -- $exit_code -- game over"
      exit
    fi
  fi

  echo ESLINT done.

  ## styllint

  echo -n STYLELINT . . .
  pnpm stylelint --allow-empty-input "assets/**/*.scss"
  exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "stylelint is unhappy. Trying to fix . . . "
    fi
  pnpm stylelint --fix --allow-empty-input "assets/**/*.scss"
  pnpm stylelint --allow-empty-input "assets/**/*.scss"
  exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "stylelint is still unhappy. this is sad. Game over."
      exit
    fi
  echo "DONE!"

  ## end stylelint

  ## PRETTIER

  echo -n "Prettier . . . "
  if [ -n "$(find assets -type f \( -name "*.scss" -or -name "*.js" -or -name "*.gjs" -or -name "*.hbs" \) 2>/dev/null)" ]; then
    #pnpm prettier --write                  'assets/**/*.{scss,js,gjs,es6,hbs}'
    # echo "doing pnpm prettier --write --log-level warn assets/**/*.{scss,js,gjs,es6,hbs}"
    pnpm prettier --write --log-level error "assets/**/*.{scss,js,gjs,hbs}"
    if [[ $? -ne 0  ]]
    then
      echo "prettier assets did something!!! -- $?"
      sleep 5
    fi
  fi
  if [ -n "$(find admin/assets -type f \( -name "*.scss" -or -name "*.js" -or -name "*.gjs" -or -name "*.hbs" \) 2>/dev/null)" ]; then
    #pnpm prettier --write                  'assets/**/*.{scss,js,gjs,es6,hbs}'
    # echo "doing pnpm prettier --write --log-level warn admin/assets/**/*.{scss,js,gjs,hbs}"
    pnpm prettier --write --log-level log "assets/**/*.{scss,js,gjs,es6,hbs}"
    if [[ $? -ne 0  ]]
    then
      echo "prettier admin/assets did something!!! -- $?"
      pnpm prettier --check --log-level log "assets/**/*.{scss,js,gjs,es6,hbs}"
    fi
  fi
  if [ -n "$(find test -type f \( -name "*.js" -or -name "*.gjs" \) 2>/dev/null)" ]; then
    #pnpm prettier --write                  'assets/**/*.{scss,js,gjs,es6,hbs}'
    # echo "doing pnpm prettier --write --log-level warn assets/**/*.{scss,js,gjs,es6,hbs}"
    pnpm prettier --write --log-level warn "test/**/*.{js,gjs}"
    if [[ $? -ne 0  ]]
    then
      echo "prettier test did something!!! -- $?"
      pnpm prettier --check --loglevel log "test/**/*.{js,gjs}"
    fi
  fi
  echo "Done with prettier"

  echo "ember-template-lint"
  pnpm ember-template-lint --fix --no-error-on-unmatched-pattern assets/javascripts admin/assets/javascripts
  exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "done with ember-template-lint --fix --no-error-on-unmatched-pattern assets/javascripts -- with $exit_code"
      echo sleep 5
      sleep 5
    fi
  #bundle exec stree write Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake') $(git ls-files '*.thor')
  bundle exec stree check Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake') $(git ls-files '*.thor')
  exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "stree is unhappy. Trying to fix in 2 seconds . .. "
      sleep 2
      echo "here we go!!!"
      bundle exec stree write Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake') $(git ls-files '*.thor')
    fi
  bundle exec stree check Gemfile $(git ls-files '*.rb') $(git ls-files '*.rake') $(git ls-files '*.thor')
  exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "stree is still unhappy. this is sad. Waiting to make you sadder"
      sleep 15
    fi
  echo done with stree

  echo "rubocop!"
  bundle exec rubocop -A $(find . -name "*.rb"|grep -v gems)
  exit_code="$?"
  if [[ $exit_code -ne 0  ]]
  then
    echo "done with rubocop -- $exit_code"
    sleep 15
  fi
  exit
fi


하지만 거의 동일한 방식으로 작동한다고 생각하는 다음 스크립트도 가지고 있습니다:

if [[ "$ARG" ==  "lint" ]]
then
  cd ~/src/discourse-repos/discourse
  find plugins/discourse-pfaffmanager/assets -type f \( -name "*.scss" -o -name "*.js" -o -name "*.gjs" -o -name "*.hbs" -o -name "*.rb" \) -exec ./bin/lint --fix {} +
  cd -
fi

이제 유일한 차이는 코어 린팅이 이 내용에 대해 불만인 것 같습니다(그리고 코어는 발견하지만 플러그인은 발견하지 못하는 이유를 이해하고 있으며, 이러한 비추천(deprecation)을 빨리 수정하는 데는 단점이 없다고 생각합니다):


/home/pfaffman/src/discourse-repos/discourse/plugins/discourse-pfaffmanager/assets/javascripts/discourse/components/modal/really-delete.gjs
  2:8  error  Use Glimmer components(@glimmer/component) instead of classic components(@ember/component)  ember/no-classic-components

✖ 1 problem (1 error, 0 warnings)

그리고 bin/lint를 사용하면 린팅이 변경되어 제 54줄짜리 스크립트를 업데이트해야 하는 상황을 걱정할 필요가 없습니다. 맞나요?

잠깐. 스켈레톤 저장소에서 어디에 문서화되어 있나요?

제 작은 규모의 작업물은 사실 당신들의 문제가 아니라는 점은 이해하지만, 변경 사항을 체계적으로 배포하는 방법에 대한 안내를 받고 싶습니다. . . 이 주제는 여기에는 적합하지 않지만, mass-pr를 몇 번 시도해 보았지만 아직 성공하지 못했습니다. 저는 보통 스켈레톤의 최근 풀에서 몇 가지 .whatever 파일을 복사하고 최선의 결과를 기대하는 편입니다.

그리고 그런 스크립트가 16개나 있습니다. 저장소를 관찰하고 그중 하나라도 업데이트될 때마다 실행해야 하나요? 그리고 일부 테마는 스켈레톤을 클론하지 않아 필요한 파일을 복사하지 못해서 실패하는 것 같습니다.

그리고 일부는 스켈레톤 저장소를 클론하지 않기 때문에 sed: can’t read s/default.yml/stree-compat.yml/: No such file or directory와 같은 오류로 실패하는 것 같습니다? (기회가 되면 적절한 곳에서 해당 문제를 위한 주제를 시작하겠습니다).

bin/lint는 코어(core)의 린팅 설정을 사용하므로 테마나 플러그인을 지원하지 않습니다. 이 명령을 사용하면 테마/플러그인 CI에서 실패가 발생할 가능성이 높습니다. 예를 들어, prettier의 아주 작은 버전 업그레이드조차도 공백 처리에 미묘한 변화를 가져올 수 있습니다.

네, 대량 PR 스크립트들이 하는 일이 본질적으로 바로 그것입니다. :+1:

update-linting.sh가 바로 필요한 스크립트입니다. 다른 스크립트들은 더 전문적인 롤아웃을 위한 것입니다.

그렇게 하셔도 됩니다. 아니면 테마/플러그인의 린팅 설정을 업데이트하고 싶을 때 가끔 다시 실행하셔도 됩니다. 설정이 완전히 독립적으로 포함되어 있으므로, 코어(core)의 변경 사항은 테마/플러그인의 린팅에 영향을 미치지 않습니다. 두 시스템은 완전히 분리되어 있습니다.

좋아요! 그러면 가끔 이 스크립트만 실행하면 모든 린팅이 업데이트된다는 거죠. 나머지는 새로운 ember로 마이그레이션하는 것을 돕는 마법 같은 작업을 하는 건가요? 이제 조금 이해가 오는 것 같네요. 예시처럼 저장소 목록을 만들어 봐야겠어요.

알겠습니다. pnpm i를 실행하지 않아서 테마/플러그인 린팅이 잘못된 동작을 하고 있었고, 코어 린팅은 github와 일치하고 있어서 혼란스러웠습니다.

네, 하지만 저는 3분 만에 수동으로 할 수 있는 작업을 자동화하는 데 5시간을 쓰는 걸 좋아하거든요. 이 방법이 그렇게 하는 좋은 방법인 것 같습니다. :rofl: