Как читать авторский курс и нормативные материалы
Это учебные материалы, а не заключение о соответствии конкретного продукта. Организационные модели курса отделяйте от терминов стандарта: ППК в опубликованном проекте — машиночитаемый перечень, а живой реестр его версий является практикой сопровождения. Термин OSA в разных материалах имеет разный охват. Статус и обязательность нормативного документа проверяются отдельно; проект КАПО опубликован как проект первой редакции.
П12. ORT и license policy
Зачем эта практика ScanCode отвечает на вопрос «какая лицензия найдена», но не «можно ли с ней выпускаться». OSS Review Toolkit (ORT) добавляет недостающий слой — исполняемую политику: правила на Kotlin DSL, которые из набора лицензий вычисляют нарушения (violations) с уровнем
ERROR/WARNING/HINT. Это превращает лицензионный анализ из ручного просмотра в воспроизводимый CI-gate: pipeline падает не потому, что «кому-то не понравился GPL», а потому что сработало записанное правило.
Цель
Прогнать проект через конвейер ORT analyze → scan → evaluate → report со своим файлом политики и получить отчёт, где есть хотя бы одно зафиксированное нарушение (например, strong copyleft в продукте, помеченном как проприетарный) с категорией severity. Проверяемый результат — отчёт ORT и ненулевой код возврата ort evaluate, на котором можно строить CI-gate.
Команда или действие
ort --version
# 1. Построить дерево зависимостей и собрать заявленные лицензии
ort analyze -i . -o out/
# 2. (опц.) досканировать исходники детектором лицензий — точные находки
ort scan -i out/analyzer-result.yml -o out/
# 3. Применить политику: правила превращают лицензии в violations
ort evaluate \
-i out/scan-result.yml \
--rules-file curations/rules.kts \
--license-classifications-file curations/license-classifications.yml \
-o out/
# 4. Человекочитаемые и машинные отчёты
ort report -i out/evaluation-result.yml -o out/ \
-f WebApp,CycloneDX,SpdxDocument
Минимальный фрагмент политики (rules.kts) — блокировать strong copyleft в проприетарной поставке:
fun RuleSet.copyleftRule() = packageRule("STRONG_COPYLEFT_IN_DISTRIBUTION") {
require { -isExcluded() }
licenseRule("STRONG_COPYLEFT", LicenseView.CONCLUDED_OR_DECLARED_AND_DETECTED) {
require { isStrongCopyleft() } // класс из license-classifications.yml
error(
"Лицензия ${license} класса strong copyleft в распространяемом компоненте ${pkg.id.toCoordinates()}.",
"Получить юридическое заключение либо заменить компонент."
)
}
}
LicenseViewрешает, какие лицензии считатьCONCLUDED_OR_DECLARED_AND_DETECTEDберёт сначала concluded-вердикт (если человек его внёс через curations), иначе declared + detected. Это и есть мост между П11 (detected) и П27 (concluded): курация в ORT поднимает ручной вердикт выше машинной находки, и правило перестаёт срабатывать на уже разобранном кейсе.
Что вы должны увидеть
ort evaluate пишет в stdout сводку и завершается ненулевым кодом при наличии ошибок:
Resolved 248 license findings.
Found 3 rule violations:
ERROR: STRONG_COPYLEFT_IN_DISTRIBUTION — GPL-3.0-only in 'NPM::somelib:2.4.1'
WARNING: WEAK_COPYLEFT_REVIEW — LGPL-3.0-or-later in 'NPM::otherlib:1.0.0'
HINT: UNHANDLED_LICENSE — LicenseRef-custom-eula in 'PyPI::vendored:0.9'
Скелет evaluation-result.yml (секция нарушений):
evaluator:
violations:
- rule: "STRONG_COPYLEFT_IN_DISTRIBUTION"
pkg: "NPM::somelib:2.4.1"
license: "GPL-3.0-only"
severity: "ERROR"
message: "Лицензия GPL-3.0-only класса strong copyleft..."
Проверка для CI: после ort evaluate команда echo $? должна вернуть 2 (есть violations с severity ERROR) — именно этот код останавливает pipeline. Если правил нет или классы не заданы, violations будет 0 и gate пропустит copyleft — это ложноотрицательный результат, а не «всё чисто».
Если не получилось
Типичные ошибки -
ort: command not found— ORT не установлен. Проще всего запускать официальным образом:docker run --rm -v "$PWD":/project ghcr.io/oss-review-toolkit/ort:latest .... Самостоятельная сборка требует JDK 17+. -analyzeнаходит 0 пакетов — не отработал нужный package manager (нетpackage-lock.json/go.sum). ORT читает реальные lock-файлы; без них дерево зависимостей пустое. Проверьте секциюanalyzerв результате. - violations всегда 0, хотя copyleft в проекте есть — не подключён--license-classifications-fileили в нём не размечены классы (isStrongCopyleft()не на что опереться). Правило компилируется, но никогда не истинно. -ort evaluateпадает с ошибкой компиляции.kts— синтаксис Kotlin DSL чувствителен к версии ORT; сверьте сигнатуры функций с версией изort --version, не копируйте правила из старых примеров вслепую.
Критерий зачёта
Показать преподавателю: (1) evaluation-result.yml с минимум одним severity: ERROR; (2) ваш rules.kts и license-classifications.yml (политика, а не дефолт); (3) вывод echo $? после ort evaluate с ненулевым кодом и формулировку, как этот код встроить в CI-шаг (needs/allow_failure: false). Запуск без собственной политики не засчитывается — суть практики именно в policy-driven подходе.
Нормативная связка
- Модуль: М07 Лицензионная чистота и юридический workflow
- Смежные практики: П11. ScanCode для лицензий · П13. FOSSology как юридический workflow · П26. Лицензионная классификация · П27. Юридическое заключение и реестр лицензий
- Нормативка: SPDX ISO/IEC 5962 · OpenChain ISO/IEC 5230
- Шаблоны: Политика лицензионной чистоты · Требования к CI security gate
- Инструмент: OSS Review Toolkit