Skip to content

Repository files navigation

Harness CLI

Standalone CLI с единой рамкой качества для разных репозиториев. Он читает self-reported ответы из tracked .harness.json и измеряет то, что можно одинаково проверить в любом репозитории. Тесты, сборку и линтеры проекта харнес не запускает — за них отвечает CI самого проекта.

Установка

curl -fsSL https://raw.githubusercontent.com/gently-whitesnow/harness-cli/master/install.sh | sh

Скрипт определяет платформу, сверяет sha256 и кладёт бинарь в ~/.local/bin/harness без sudo. Никакого .NET runtime для запуска не нужно. Той же командой харнес обновляется: пинить при установке нечего, потому что поведение задаёт проверяемый репозиторий, а не бинарь. Внутри репозитория с .harness.json скрипт заодно выполняет harness setup, который активирует commit-шаблон и commit-msg hook этого клона.

Для disposable-контейнера или installer-задачи бинарь можно оставить внутри клона:

curl -fsSL https://raw.githubusercontent.com/gently-whitesnow/harness-cli/master/install.sh \
  | sh -s -- --scope clone

--scope clone атомарно устанавливает его в $(git rev-parse --git-common-dir)/harness/bin/harness, под lock-файлом защищает две параллельные установки и обязательно выполняет harness setup. Hook получает стабильный абсолютный путь к этому бинарю, поэтому продолжает работать после завершения контейнера и остаётся общим для всех linked worktree клона. User-каталоги и tracked-файлы этот режим не меняет.

HARNESS_VERSION=2.10.0 ставит конкретный релиз, HARNESS_INSTALL_DIR меняет каталог обычной user-установки, а HARNESS_NO_SETUP=1 отключает подготовку клона.

Запуск

harness init /path/to/repository   # выбрать application/library и создать явную рамку
harness init --kind application    # то же без интерактивного stdin
harness upgrade                    # поднять pin и получить маршрут миграции
harness check                      # проверить репозиторий
harness budget update              # создать или ужать DSM-бюджет
harness setup                      # подготовить этот клон
harness version                    # релиз бинаря и текущий контракт

init задаёт один вопрос — приложение это или standalone-библиотека. Для приложения он фиксирует architecture.standard: sliced-dotnet/1, для библиотеки — явный architecture.applicable: false; карту каталогов он не генерирует. Команда создаёт .harness.json и .harness.budget.json с текущими DSM-метриками и явными settings, applicability и policy. Неотвеченные frame-вопросы — off, кроме обязательного verify. По умолчанию фиксируется текущий релиз; --latest включает rolling-контракт. Существующие файлы команда не перезаписывает и в Git не добавляет. Если в корне нет .editorconfig, init записывает эталонный файл харнеса — тот же baseline, который затем требует editorconfig.dotnet. В скриптах и CI тот же выбор задаётся через --kind application|library. init также активирует шаблон коммита и commit-msg hook; после нового клонирования это делает идемпотентный harness setup. Если frame требует setup, обычный check явно падает в неподготовленном клоне. Для CI сообщения проверяются явным диапазоном: harness commits check <base>..<head>.

answers.verify.paths называет tracked скрипт всех проверок, включая harness check; харнес его не запускает и не инспектирует. Здесь это ./verify.sh; commit range задаёт отдельно CI.

Применимый complexity.csharp требует tracked .harness.budget.json. Он измеряет файлы внутри архитектурных зон sliced-dotnet (тесты вне зоны не входят) и бюджетирует mean reach — сколько файлов достигает изменение в среднем — и core size. Превышение потолка блокирует check, а улучшение предлагает выполнить harness budget update. Команда создаёт baseline, мигрирует бюджет контракта 2.5 или атомарно ужимает оба значения; повышать бюджет она не умеет — такое изменение делается вручную как обычный tracked-дифф для ревью.

Путь можно не указывать для текущего репозитория. harness help перечисляет команды и проверки; check печатает строку со статусом на каждую проверку, --verbose раскрывает причины, --all — полный список измеренных субъектов, --only <check-id> запускает одну. Каждая проверка называет файлы, которые читает по имени, поэтому файл в рабочем дереве без git add отчёт называет строкой not in the index: untracked-файл не является доказательством. harness explain <check-id> описывает смысл и исправление проверки.

Версия

version в .harness.json называет релиз харнеса и фиксирует весь контракт проверки: какие вопросы задаются и какие проверки выполняются. Это единственная версия в конфиге.

Бинарь исполняет ровно один текущий контракт. Пин на другую версию останавливает прогон с кодом 2; единственный путь сменить pin — harness upgrade. Команда меняет только pin и печатает полный маршрут контракта 2.0: удалённые проверки/секции, новый стандарт, явную policy и DSM-бюджет. Ответы владельца она не угадывает. Все правки принимаются одним reviewable-коммитом. ADR-0023

В CI

GitLab:

harness:
  image: ghcr.io/gently-whitesnow/harness:2.10.0
  script:
    - harness check
    - harness commits check "$CI_MERGE_REQUEST_DIFF_BASE_SHA..$CI_COMMIT_SHA"

GitHub Actions или любой контур без доступа к ghcr.io:

- name: Repository harness
  run: |
    curl -fsSL https://raw.githubusercontent.com/gently-whitesnow/harness-cli/master/install.sh | sh
    ~/.local/bin/harness check

Как это работает

Эталон — рабочий .harness.json этого репозитория: в нём представлены все формы ответа и секции конфигурации. paths служит навигацией и не проверяется как доказательство. Каждый shipped check обязан иметь явный policy: required блокирует, advisory оставляет находки видимыми без провала, off отключает. Каждый параметр settings и каждая ось applicability также обязательны: список проверок и их состояние читаются прямо из файла, defaults в ридере нет. Для неприменимой оси используется { "applicable": false, "reason": "..." }; для применимой — { "applicable": true }.

Коды возврата: 0 — всё выбранное прошло, 1 — доказано нарушение, 2 — проверить достоверно не удалось (сюда же относится отсутствующий или невалидный .harness.json).

Собственные проверки

То, что не воспроизводит чужой пайплайн и что в каждом репозитории расходится:

  • связанность: граф зависимостей между модулями и типами; доказанный цикл модулей blocking;
  • форма sliced-dotnet: канонические слои, слайсы, направления Proven-зависимостей и неблокирующие структурные advisories: группировка плоских каталогов, плотность X-контрактов, словарь имён по всему zone;
  • DSM-сложность: mean reach и core size файлового графа продукта, propagation cost как справка;
  • не больше одного верхнеуровневого C# class или record в authored-файле;
  • нормализованные межфайловые повторы C#;
  • документационная политика: один корневой навигационный документ и симлинки на него;
  • .NET-рамка: hardened Directory.Build.props, central packages, .slnx, эталонный .editorconfig и учёт подавленных warnings: адресное подавление блокируется, выключение правила для всего репозитория печатается в каждом отчёте.

Харнес несёт общий стандарт формы, который иначе копировался бы между репозиториями.

Отчёт печатает архитектуру и DSM-бюджет рядом с текущими значениями и областью измерения; модель трёх ярусов, формулы и словарь раскрываются через harness explain и ADR-0032/0033.

Специфичные для продукта контракты и архитектурные правила остаются в самом репозитории.

Сайт

Лендинг — статика в site/: все проверки, формулы циклов, DSM и дупликации, конструктор .harness.json. Реестр и версия зеркалят бинарь и сверяются тестом; что обновлять — site/AGENTS.md, почему — ADR-0047.

About

Standalone repository quality CLI for consistent checks across codebases.

Topics

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages