Diff и CI
ranklint diff
| Флаг | Описание |
|---|---|
--base | путь к report.json или git-ref — тогда отчёт достаётся из артефактов CI |
--current | текущий report.json |
--reporter | markdown | json |
--output | в файл |
CI-адаптер по окружению: GITHUB_ACTIONS=true → GitHub (артефакт по имени, zip распаковывается встроенным ридером), иначе GitLab (job-артефакт ветки). Политика ошибок: нет CI-контекста → warn + полный отчёт «first run» (base не найден — не ошибка); ошибка загрузки (401/403/сеть) → падение, чтобы протухший токен не маскировался вечным first run. Exit 1 только при новых error-issues.
Diff и CI
Ключ проблемы: checkId + url без origin + selector — стабилен между окружениями (UAT сравнивается с prod). diffReports → newIssues / fixedIssues / pagesDelta.
Хранилища базовых отчётов (ReportStorage): fs (директория JSON, latest по mtime), GitLab artifacts (read-only, по job-артефакту ветки), GitHub artifacts (read-only: список по имени, фильтр по ветке, скачивание zip — свой минимальный zip-ридер: EOCD → central directory → inflateRawSync; битый вход → null, не исключение), S3 (для монитора; SDK — опциональный peer, любой S3-совместимый endpoint).
Готовые CI-пресеты: presets/gitlab-ci/seo.yml (джобы .ranklint-audit, .ranklint-diff с автокомментом в MR, .ranklint-lighthouse, .ranklint-monitor с кешем Playwright и отчётов) и presets/github-actions/seo.yml, presets/github-actions/monitor.yml (монитор по расписанию с кешем отчётов). Репортер github — аннотации в PR.
SARIF для GitHub Code Scanning
SARIF — формат, который GitHub читает на вкладке Security → Code scanning. ranklint audit --reporter sarif пишет документ SARIF 2.1.0: один run, tool.driver.name: ranklint, по правилу на каждый checkId с helpUri на доку правила, по результату на каждый issue с level (error / warning / note), URL страницы как location и стабильный partialFingerprints.primaryLocationLineHash из diff-ключа checkId + путь + selector, чтобы GitHub сохранял алерт между прогонами, а не заводил новый.
ranklint audit --url "$URL" --reporter sarif --output ranklint.sarif
permissions:
security-events: write
steps:
- run: ranklint audit --url "$URL" --reporter sarif --output ranklint.sarif
- uses: github/codeql-action/upload-sarif@v3
with:
sarif_file: ranklint.sarif
category: ranklint
В переиспользуемом пресете presets/github-actions/seo.yml шаг включается инпутом sarif: true. Находки появляются в Security → Code scanning с фильтром по инструменту ranklint. Локации — абсолютные URL страниц, а не файлы репозитория: SARIF это допускает, алерты группируются по id правила.
Sticky-комментарий в PR и MR
markdownDiff начинает вывод скрытым маркером <!-- ranklint-diff -->. Пресеты используют его, чтобы обновлять прежний комментарий, а не добавлять новый на каждый прогон пайплайна.
GitLab: джоба .ranklint-diff проходит постранично GET /merge_requests/:iid/notes (per_page=100), находит note, тело которой начинается с маркера, и шлёт PUT .../notes/:note_id; если такой нет, остаётся POST. Для поиска нужен jq в образе и RANKLINT_GITLAB_TOKEN со scope api.
GitHub: шаг Comment on PR получает комментарии PR через actions/github-script, ищет тот же маркер и зовёт updateComment или createComment. Шагу нужен pull-requests: write.
GitLab CI
include:
- remote: 'https://raw.githubusercontent.com/aakazancev/ranklint/main/presets/gitlab-ci/seo.yml'
seo:audit:
extends: .ranklint-audit
needs: [deploy:uat]
variables:
RANKLINT_URL: $CI_ENVIRONMENT_URL
ranklint diff --base main достаёт базовый отчёт из артефактов CI: в GitLab — из job-артефакта ветки, в GitHub Actions — из артефакта ranklint-report (распаковка zip встроена). Отсутствующий base — не ошибка: diff деградирует до полного отчёта.