Согласованность линтинга

Клянусь, я скопировал все настройки линтера из discourse-plugin-skeleton в свой плагин, но когда я запускаю

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

в директории своего плагина, результат отличается от того, что получается при запуске

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

в корневой директории Discourse.

Как и следовало ожидать, именно второй вариант соответствует тому, что происходит при запуске GitHub Actions.

Моя главная цель — чтобы всё работало правильно при сохранении файла в VSCode, но, полагаю, это уже отдельная проблема.

Да, @cvx / @david

Я тоже это заметил… линтинг в плагинах — это всё «снежинки»: у нас есть отдельные ветки для старого и нового стилей линтинга в CI, и требуется много настроек в репозитории.

Я считаю, что отличной целью будет исправить это так, чтобы bin/lint работал и для плагинов, и для тем. Пока этого ещё не реализовано: сейчас он работает только для ядра и плагинов ядра.

Действительно, линтинг для тем и плагинов намеренно отделён от ядра. Они могут использовать разные версии и конфигурации инструментов линтинга. Это необходимо, чтобы мы могли внедрять изменения, не ломая линтинг во всех репозиториях.

Мы, вероятно, могли бы заставить bin/lint работать — ему потребуется перейти (cd) в директорию плагина или темы, выполнить pnpm i, а затем запустить любые команды линтинга в контексте этой директории. Но он ни в коем случае не должен пытаться использовать конфигурацию линтинга ядра для тем или плагинов.

Так и должно быть. Большинство нашей команды использует VSCode (или его производные), поэтому мы оптимизируем работу именно под него. Плагины Eslint и Prettier для VSCode будут искать «ближайшую» установку и конфигурацию для конкретного файла.

Вы запускали pnpm i в директории темы или плагина? Это необходимо для установки зависимостей линтинга, чтобы VSCode мог найти нужную версию prettier/eslint для использования.

Интересные повороты:

  • Дать возможность опционально запускать правила ядра
  • Дать возможность переконфигурировать существующую конфигурацию для запуска правил ядра

В чём тогда будет польза? :sweat_smile:

Линтинг тем/плагинов принципиально отличается от линтинга ядра. У нас есть специфические правила для тем и плагинов. У тем есть свои собственные глобальные переменные, о которых ESLint должен знать (themePrefix/settings).

Мы очень внимательно относимся к этому, документируем процесс в репозиториях шаблонов тем/плагинов и методично внедряем изменения через массовые pull-запросы.

Как инструмент для самовосхождения, но я полностью понимаю, что у нас есть другие системы.

Ага, понятно. У нас есть скрипты для автоматического обновления (из шаблона) здесь. Сделать их более удобными для запуска на отдельных темах/плагинах могло бы стать отличным проектом. :+1:

Кстати, когда я говорю, что у них разная конфигурация, я имею в виду не то, что мы дублируем конфигурацию повсюду. У нас есть пакет с версионированными конфигами линтинга, который включает общие конфигурации для prettier, eslint, stylelint и ember-template-lint. Это используется ядром и всеми темами/плагинами. Обновление темы или плагина до последних правил обычно сводится к увеличению версии lint-configs в package.json.

Но я почти уверен, что когда я следую правилам линтинга, принятым в плагине, тесты линтинга падают в GitHub Actions.

АГА!!! pnpm i — это то самое волшебство, которого мне не хватало. Я добавил pnpm i в свой скрипт обновления ядра Discourse и в скрипт линтинга…

Итак, вот что делает мой скрипт сейчас:

if [[ "$ARG" == "eslint" ]]
then
  # См. https://github.com/discourse/.github/blob/main/.github/workflows/discourse-plugin.yml
  if [ -f plugin.rb ]
  then
    echo "Линтинг текущей директории."
  else
    echo "Не плагин. Используем $DEFAULT_PLUGIN"
    cd $DEFAULT_PLUGIN
  fi
  echo "ЛИНТИНГ $(pwd)"
  #cd /home/pfaffman/src/literatecomputing/discourse-display-email
  # pnpm install
  echo "Выполняем `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 недоволен -- $exit_code -- пытаемся исправить"
    pnpm eslint --fix --no-error-on-unmatched-pattern {test,assets,admin/assets}/javascripts
    exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "eslint всё ещё недоволен -- $exit_code -- игра окончена"
      exit
    fi
  fi

  echo ESLINT завершён.

  ## stylelint

  echo -n STYLELINT ...
  pnpm stylelint --allow-empty-input "assets/**/*.scss"
  exit_code="$?"
    if [[ $exit_code -ne 0  ]]
    then
      echo "stylelint недоволен. Пытаемся исправить..."
    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 всё ещё недоволен. Это грустно. Игра окончена."
      exit
    fi
  echo "ГОТОВО!"

  ## конец 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 "выполняем 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 что-то сделал!!! -- $?"
      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 "выполняем 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 что-то сделал!!! -- $?"
      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 "выполняем 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 что-то сделал!!! -- $?"
      pnpm prettier --check --loglevel log "test/**/*.{js,gjs}"
    fi
  fi
  echo "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 "ember-template-lint --fix --no-error-on-unmatched-pattern assets/javascripts завершён -- с кодом $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 недоволен. Пытаемся исправить через 2 секунды..."
      sleep 2
      echo "поехали!!!"
      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 всё ещё недоволен. Это грустно. Ждём, чтобы сделать вам ещё грустнее"
      sleep 15
    fi
  echo stree завершён

  echo "rubocop!"
  bundle exec rubocop -A $(find . -name "*.rb"|grep -v gems)
  exit_code="$?"
  if [[ $exit_code -ne 0  ]]
  then
    echo "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

Единственное различие теперь, кажется, в том, что линтинг ядра недоволен этим (и я думаю, что понимаю, почему ядро это находит, а плагин — нет, и нет никаких недостатков в том, чтобы исправить эти устаревания раньше, чем позже):


/home/pfaffman/src/discourse-repos/discourse/plugins/discourse-pfaffmanager/assets/javascripts/discourse/components/modal/really-delete.gjs
  2:8  error  Используйте компоненты Glimmer (@glimmer/component) вместо классических компонентов (@ember/component)  ember/no-classic-components

✖ 1 проблема (1 ошибка, 0 предупреждений)

И если я использую bin/lint, то мне не нужно беспокоиться, что что-то изменится в линтинге и потребует обновления моего 54-строчного скрипта. Верно?

Подождите. Где именно в репозиториях skeleton это документируется?

Мне бы очень хотелось получить рекомендации о том, как методично внедрять изменения, хотя я понимаю, что мой небольшой набор вещей на самом деле не является вашей проблемой… Это не совсем подходит сюда, но я несколько раз пытался разобраться с mass-pr, но пока не добился успеха. Обычно я просто периодически копирую какие-то файлы .whatever из свежего клонирования skeleton и надеюсь на лучшее.

И таких скриптов 16. Должен ли я следить за репозиторием и запускать его всякий раз, когда один из них обновляется? И кажется, что ряд тем не клонируют skeleton, поэтому они не могут скопировать необходимые файлы?

И несколько из них завершаются ошибкой вроде sed: can't read s/default.yml/stree-compat.yml/: No such file or directory? потому что они не клонируют репозитории skeleton? (Я начну тему в подходящем месте, когда у меня будет возможность).

bin/lint использует конфигурацию линтинга ядра и поэтому не поддерживает темы или плагины. Если вы будете его использовать, скорее всего, вы столкнётесь с ошибками в CI вашей темы/плагина. Например, даже незначительные обновления версии prettier могут привести к тонким изменениям в обработке пробелов.

Да, это именно то, что делают скрипты массового PR :+1:

Вам нужен update-linting.sh. Остальные скрипты предназначены для более специализированных обновлений.

Можно и так. Или вы можете просто запускать его время от времени, когда захотите обновить конфигурацию линтинга для вашей темы/плагина. Поскольку конфигурация полностью автономна, изменения в ядре никогда не повлияют на линтинг в ваших темах/плагинах — они полностью развязаны.

Круто! Значит, мне просто нужно запускать его время от времени, и он будет обновлять все линтинги. Остальные нужны для всякой магии вроде помощи при миграции на новую версию Ember и так далее? Возможно, я начинаю понимать, и могу составить список репозиториев, как в примере.

Понял. Я был сбит с толку, так как не запускал pnpm i, поэтому линтинг темы/плагина работал неправильно, а линтинг ядра соответствовал GitHub.

Да, но я люблю тратить 5 часов на автоматизацию задачи, которую могу сделать вручную за 3 минуты, и это кажется отличным способом это сделать. :rofl: