Архитектурная проверка показывает, какие зависимости нарушают принятые границы компонентов, и связывает каждую находку с исходным кодом. Команда может сначала изучить результаты, затем зафиксировать существующий долг и блокировать новые нарушения в CI. Это руководство объясняет, как результат анализа становится решением о выпуске. Оно предназначено для владельцев репозиториев и операторов CI, у которых уже есть проверенная модель и CPG нужной ревизии. Начните с модели и правил, чтобы определить компоненты и контракты. Для изучения выходных данных используйте интерфейсы и результаты.
gocpg architecture validate проверяет только схему правила и применимость языка. Рабочему процессу CI нужны политика проекта, ключ проекта, документ управления выпуском и выходной файл. Также требуется подтверждение, что граф, факты, модель и правила относятся к проверяемому коммиту.
Выберите профиль для этапа внедрения
Начните с discovery, когда ещё определяете компоненты. Используйте advisory, чтобы рассмотреть находки и настроить политику вместе с командой. После фиксации базового долга enforce_new проверяет новые нарушения. Выберите enforce_all, когда выпуск должен учитывать и существующий долг, или strict, когда требуется полная матрица проверок, включая пустые выборки.
Профиль задаёт отношение к находкам, а полнота входных данных определяет, может ли система принять блокирующее решение.
Профили условий выпуска
Проверка оценивает полноту доказательств до подсчёта находок. Требуются актуальный CPG, полный запуск или эквивалентный инкрементальный запуск, результат каждого активного правила, все обязательные возможности, известные знаменатели зависимостей, покрытие классификации и разрешения зависимостей, а также доверенные решения управления.
| Профиль | Обработка находок | Решение |
|---|---|---|
discovery |
Помогает построить модель и классифицировать сущности. | NOT_APPLICABLE |
advisory |
Показывает находки, пока команда проверяет политику. | NOT_APPLICABLE |
enforce_new |
Блокирует новые находки без исключений. | PASS или FAIL_VIOLATIONS при полных доказательствах. |
enforce_all |
Блокирует новые и известные находки без исключений. | PASS или FAIL_VIOLATIONS при полных доказательствах. |
strict |
Применяет полную матрицу проверок, включая пустые выборки. | PASS или FAIL_VIOLATIONS при полных доказательствах. |
Любой блокирующий профиль возвращает BLOCKED_INCOMPLETE, если входные данные устарели, неполны, неизвестны или не заслуживают доверия. Только PASS устанавливает release_allowed=true. NOT_APPLICABLE означает, что блокирующее решение не запрашивалось. Для запуска без разрешённых фактов зависимостей нужен известный знаменатель: пустой результат не позволяет заявить покрытие разрешения 100%.
Ниже приведена форма вызова CI для рабочего репозитория. Запускайте её из корня репозитория в PowerShell. Нужны gocpg в PATH, базовая ссылка Git и четыре пути, настроенные для одного проекта. Замените пути и ключ проекта своими. Политика — это манифест политики репозитория, а не отдельное правило kind: architecture, используемое командой architecture validate.
При первом запуске создайте каталог вывода и постройте CPG из того же корня репозитория. Команда ci-update использует сохранённую привязку CPG к исходникам; для отсутствующей базы архитектурный запуск возвращает git_source_scope_unavailable.
New-Item -ItemType Directory -Force .gocpg | Out-Null
gocpg parse --input . --output .gocpg/cpg.duckdb --lang python
Затем обновите граф и получите архитектурный артефакт:
gocpg ci-update --input . --output .gocpg/cpg.duckdb `
--base-ref origin/main --head-ref HEAD --lang python `
--architecture-policy .gocpg/architecture/policy.yaml `
--architecture-project-key my-repository `
--architecture-release-control .gocpg/architecture/release-control.yaml `
--architecture-artifact .gocpg/architecture/result.json --json
Четыре архитектурных флага передаются вместе. Минимальный документ управления выпуском для рассмотрения находок может выбрать advisory, но всё равно должен соответствовать текущей схеме и требованиям к доказательствам репозитория. Проверьте идентичность запуска, полноту, результаты правил и статус условий выпуска в выходном файле. Успешного кода завершения CLI недостаточно для подтверждения PASS. Руководство по внедрению объясняет общую последовательность перехода.
Учебный запуск с готовыми входами
Используйте PowerShell 7, Git с настроенными именем и адресом автора, gocpg в PATH и исходную рабочую копию CodeGraph. Замените два пути ниже. Создайте новый каталог для примера. Два Python-модуля дают реальную зависимость для проверки покрытия; поставляемый реестр позволяет найти python/module-boundaries@1.0.0.
$CodeGraphSource = "<path-to-codegraph-source>"
$DemoRoot = "<new-empty-directory>"
New-Item -ItemType Directory -Path $DemoRoot | Out-Null
Set-Location $DemoRoot
New-Item -ItemType Directory -Force app, .gocpg/architecture/fixtures, gocpg/configs/architecture/presets | Out-Null
Copy-Item -Recurse "$CodeGraphSource/gocpg/configs/architecture/presets/v1" gocpg/configs/architecture/presets/v1
@'
from app.helpers import format_greeting
def greet(name):
return format_greeting(name)
'@ | Set-Content -Encoding utf8 app/service.py
@'
def format_greeting(name):
return "Hello, " + name
'@ | Set-Content -Encoding utf8 app/helpers.py
@'
.gocpg/cpg.duckdb*
.gocpg/architecture/result.json
'@ | Set-Content -Encoding utf8 .gitignore
Создайте политику одного компонента и документ управления с профилем discovery. Пути fixtures задают пары исходников правила; оценка их соответствия — отдельный этап подготовки промышленной политики.
@'
schema_version: architecture_policy.v1
id: teaching-service/python
version: 1.0.0
preset_ref: python/module-boundaries@1.0.0
source_paths:
- app/*.py
- app/**/*.py
vocabularies:
layer:
- service
dispositions:
- id: include-production
action: include
paths:
- app/*.py
- app/**/*.py
owner: Architecture Team
reason: Teaching source population.
components:
- uid: service
id: service
name: Service
kind: leaf
tags:
layer:
- service
classifiers:
- id: service-files
component: service
priority: 100
paths:
- app/**
entity_kinds:
- file
- function
- method
- type
rules:
- id: TEAM-CLASSIFICATION-01
version: 1.0.0
contract: exhaustive_classification
mode: discovery
owner: Architecture Team
severity: high
applicability: python
rationale: Classify every source entity.
fixtures:
valid: fixtures/valid.py
invalid: fixtures/invalid.py
spec:
contract: exhaustive_classification
languages:
- python
minimum_coverage: 1
'@ | Set-Content -Encoding utf8 .gocpg/architecture/policy.yaml
@'
schema_version: architecture_release_control.v1
profile: discovery
scope: enforce_new
previous_modes: {}
governance_manifest_path: ''
advisory_cycles_path: ''
rollback_requested: false
rollback_policy_disabled: false
rollback_from_policy_id: ''
rollback_from_policy_version: ''
rollback_from_policy_digest: ''
'@ | Set-Content -Encoding utf8 .gocpg/architecture/release-control.yaml
"def valid(): return 1" | Set-Content -Encoding utf8 .gocpg/architecture/fixtures/valid.py
"def invalid(): return 0" | Set-Content -Encoding utf8 .gocpg/architecture/fixtures/invalid.py
Зафиксируйте входы в Git, постройте CPG и выполните архитектурную проверку. Локальная ссылка origin/main здесь обозначает ту же учебную ревизию.
git init -b main
git add .
git commit -m "Teaching architecture input"
git update-ref refs/remotes/origin/main HEAD
gocpg parse --input . --output .gocpg/cpg.duckdb --lang python
gocpg ci-update --input . --output .gocpg/cpg.duckdb `
--base-ref origin/main --head-ref HEAD --lang python `
--architecture-policy .gocpg/architecture/policy.yaml `
--architecture-project-key teaching-service `
--architecture-release-control .gocpg/architecture/release-control.yaml `
--architecture-artifact .gocpg/architecture/result.json --json
$result = Get-Content .gocpg/architecture/result.json -Raw | ConvertFrom-Json
$result | Select-Object status, complete, release_allowed, reason_codes
$result.binding | Select-Object project_key, repository_revision, cpg_repository_revision
Ожидаемый результат: код завершения 0, status=NOT_APPLICABLE, complete=true, release_allowed=false, причина non_enforcing_profile. В binding указан teaching-service, а repository_revision совпадает с cpg_repository_revision и выводом git rev-parse HEAD. В active_rule_ids и rule_outcome_ids присутствует TEAM-CLASSIFICATION-01. Профиль discovery готовит результат анализа для рассмотрения командой.
Получите и объясните находку
Продолжите работу в том же учебном репозитории. Теперь отнесите app/service.py к компоненту service, а app/helpers.py — к storage. Правило TEAM-BOUNDARY-01 запрещает прямой импорт из первого компонента во второй. Существующий импорт в первой строке app/service.py даст одну находку.
Замените политику следующим файлом и добавьте два образца для нового правила. Профиль остаётся discovery: он собирает результаты для изучения зависимостей.
@'
schema_version: architecture_policy.v1
id: teaching-service/python
version: 1.0.0
preset_ref: python/module-boundaries@1.0.0
source_paths:
- app/*.py
- app/**/*.py
vocabularies:
layer:
- service
- storage
dispositions:
- id: include-production
action: include
paths:
- app/*.py
- app/**/*.py
owner: Architecture Team
reason: Teaching source population.
components:
- uid: service
id: service
name: Service
kind: leaf
tags:
layer:
- service
- uid: storage
id: storage
name: Storage
kind: leaf
tags:
layer:
- storage
classifiers:
- id: service-files
component: service
priority: 100
paths:
- app/service.py
entity_kinds:
- file
- function
- method
- type
- id: storage-files
component: storage
priority: 100
paths:
- app/helpers.py
entity_kinds:
- file
- function
- method
- type
rules:
- id: TEAM-CLASSIFICATION-01
version: 1.0.0
contract: exhaustive_classification
mode: discovery
owner: Architecture Team
severity: high
applicability: python
rationale: Classify every source entity.
fixtures:
valid: fixtures/valid.py
invalid: fixtures/invalid.py
spec:
contract: exhaustive_classification
languages:
- python
minimum_coverage: 1
- id: TEAM-BOUNDARY-01
version: 1.0.0
contract: forbidden_dependency
mode: discovery
owner: Architecture Team
severity: high
applicability: python
rationale: Teaching forbidden service-to-storage import.
fixtures:
valid: fixtures/boundary-valid.py
invalid: fixtures/boundary-invalid.py
spec:
contract: forbidden_dependency
from:
components:
- service
to:
components:
- storage
relation:
edge_types:
- import
reachability: direct
'@ | Set-Content -Encoding utf8 .gocpg/architecture/policy.yaml
@'
def greet(name):
return name
'@ | Set-Content -Encoding utf8 .gocpg/architecture/fixtures/boundary-valid.py
@'
from app.helpers import format_greeting
def greet(name):
return format_greeting(name)
'@ | Set-Content -Encoding utf8 .gocpg/architecture/fixtures/boundary-invalid.py
Сохраните новую ревизию, перестройте CPG и повторите анализ. Команды получают ID запуска и отпечаток из артефакта, затем показывают объяснение находки:
git add .gocpg/architecture
git commit -m "Teaching forbidden dependency"
git update-ref refs/remotes/origin/main HEAD
gocpg parse --input . --output .gocpg/cpg.duckdb --lang python
gocpg ci-update --input . --output .gocpg/cpg.duckdb `
--base-ref origin/main --head-ref HEAD --lang python `
--architecture-policy .gocpg/architecture/policy.yaml `
--architecture-project-key teaching-service `
--architecture-release-control .gocpg/architecture/release-control.yaml `
--architecture-artifact .gocpg/architecture/result.json --json
$artifact = Get-Content .gocpg/architecture/result.json -Raw | ConvertFrom-Json
$RunId = $artifact.binding.run_id
$Fingerprint = $artifact.current_advisory_cycle.rule_fingerprints.'TEAM-BOUNDARY-01'[0]
gocpg architecture explain --db .gocpg/cpg.duckdb --run-id $RunId --fingerprint $Fingerprint --json
Ожидайте finding_count: 1, complete: true и статус NOT_APPLICABLE в артефакте. В ответе explain поле rule_id содержит TEAM-BOUNDARY-01, компоненты — service и storage, а поле primary_location указывает на app/service.py, строку 1. Так можно перейти от правила границы к конкретному импорту и связанному файлу.
Для просмотра и экспорта результатов используйте этот $RunId; $Fingerprint выбирает находку для объяснения.
Исправьте исходник и повторите проверку
В том же учебном каталоге перенесите простое форматирование в greet.
Функция по-прежнему возвращает Hello, и имя, а прямой импорт из компонента
service в storage исчезает. Зафиксируйте изменение и пересоберите граф:
@'
def greet(name):
return "Hello, " + name
'@ | Set-Content -Encoding utf8 app/service.py
git add app/service.py
git commit -m "Remove forbidden storage dependency"
git update-ref refs/remotes/origin/main HEAD
gocpg parse --input . --output .gocpg/cpg.duckdb --lang python
gocpg ci-update --input . --output .gocpg/cpg.duckdb `
--base-ref origin/main --head-ref HEAD --lang python `
--architecture-policy .gocpg/architecture/policy.yaml `
--architecture-project-key teaching-service `
--architecture-release-control .gocpg/architecture/release-control.yaml `
--architecture-artifact .gocpg/architecture/result.json --json
$fixed = Get-Content .gocpg/architecture/result.json -Raw | ConvertFrom-Json
$fixed | Select-Object finding_count, complete, status
В новом артефакте ожидаются finding_count: 0, complete: true и
status: BLOCKED_INCOMPLETE. Поле reason_codes содержит
canonical_coverage_incomplete: после удаления единственного импорта
в этом минимальном проекте нет связей для расчёта покрытия. Правило выполнено,
находка устранена, а проверка выпуска отдельно оценивает покрытие графа.
Ревизии в binding.repository_revision и binding.cpg_repository_revision
должны совпадать с git rev-parse HEAD.
Действие по результату
| Результат | Следующее действие |
|---|---|
PASS |
Используйте архитектурный результат в пакете приёмки выпуска. |
FAIL_VIOLATIONS |
Рассмотрите блокирующие находки: исправьте зависимости или получите решение об исключении для текущей области. Затем повторите анализ. |
BLOCKED_INCOMPLETE |
Проверьте ревизию CPG, полноту результатов правил и доверие к документу управления. Обновите недостающие входы и повторите запуск. |
NOT_APPLICABLE |
Рассмотрите результаты discovery/advisory и выберите блокирующий профиль, когда политика готова к применению. |
Базовый набор известных находок
Базовый набор фиксирует уже рассмотренный долг для точного правила, версии отпечатка, отпечатка находки и семантического хеша правила. В enforce_new точная известная находка исключается из числа новых нарушений. enforce_all и strict продолжают учитывать известный долг без исключений. Базовый набор подтверждает рассмотрение находки, но не делает зависимость допустимой и не изменяет граф.
Например, UI импортирует хранилище. Если отпечаток рассмотрен как существующий долг, следующий идентичный запуск может считать находку известной. При смене direct на transitive меняется семантический хеш: прежнее решение переходит в needs_review. Если импорт исчезает и затем возвращается, находка считается повторно появившейся, а не автоматически известной.
Для регистрации известного долга выполните полный анализ и рассмотрите каждую находку. Получите подписанный манифест управления от сервиса, который хранит решения по проекту, затем повторите анализ с привязкой к этому манифесту. Локальная выгрузка базового набора помогает сравнить находки между запусками; подписанный манифест определяет, какие решения учитываются при проверке выпуска.
Исключения и доверие
Исключение относится к одной находке и имеет срок действия. Оно содержит владельца правила, заявителя, согласующего, причину, ссылку на решение, отпечаток, семантический хеш, версию отпечатка и область действия. Заявитель и согласующий должны быть разными участниками. Изменение отпечатка, правила, репозитория или ревизии требует нового решения. Псевдоним символа не переносит исключение.
Подписываемые данные Ed25519 связывают проект, репозиторий, коммит, ветку, хеши модели и правил, период действия и монотонную ревизию. Доверенные публичные ключи и состояние отзыва поступают из плоскости управления или конфигурации CI. Проверяются подпись, ID ключа, отзыв, срок действия и точная область. Истёкшие, отозванные, неиспользованные и устаревшие исключения остаются видимыми находками. Ошибка подписи или области блокирует проверку с BLOCKED_INCOMPLETE.
Например, исключение подписано для коммита A, а политика проверяется на B. Не копируйте отпечаток в локальный YAML для подавления находки. После полного запуска получите решение для текущей области.
Инкрементальные проверки
Планировщик использует изменённые пути и UID затронутых компонентов, чтобы решить, можно ли повторно использовать работу. Изменения модели, публичного API, рёбер зависимостей, сильно связных компонент, базового набора и исключений расширяют область пересчёта. Неизвестные компоненты или неполная область пересчёта вызывают ошибку. По умолчанию полный запуск выбирается, если доля затронутых компонентов превышает 0.20. Изменение модели всегда требует полного запуска.
incremental_complete имеет полномочия для выпуска только при совпадении отпечатков, состояний жизненного цикла, базового набора и исключений, покрытия, семантического хеша и решения с полным запуском на тех же данных. Неполный блокирующий запуск получает одну синхронную полную повторную попытку. Если она неполна, завершилась ошибкой, устарела или не совпадает, результат остаётся BLOCKED_INCOMPLETE.
Например, перенос src/ui/ в новый компонент изменяет классификацию и может затронуть рёбра вне списка изменённых файлов. Поэтому изменение модели запускает полный анализ. Проверка только изменённых файлов пропустила бы связи переклассифицированных сущностей.
Переход с прежних проверок
Для прежних проверок выбирается решение: migrate, retain advisory, retire или defer. Режимы discovery и advisory могут показывать явно помеченные прежние доказательства. Но прежний результат не создаёт канонический PASS, состояние находки, базовый набор, исключение или разрешение выпуска.
- Перечислите прежние обработчики и наборы правил; назначьте каждому решение.
- Выполните прежний и канонический процессы параллельно на одной ревизии. Классифицируйте различия по устойчивому отпечатку и подтверждающим исходникам.
- Квалифицируйте эталонные примеры и устраните необъяснённые блокирующие пропуски нарушений.
- Наблюдайте два реальных цикла выпуска в advisory с устойчивой семантической идентичностью.
- Переведите потребителей на сохранённые канонические результаты и подтвердите отключение прежней блокирующей проверки.
Откат может вернуть блокирующий режим в advisory. Он не даёт прежней проверке полномочий разрешать выпуск. Локальная проверка совпадения подтверждает только свои тестовые данные, а не промышленное внедрение.
Проверки реализации
Из корня модуля gocpg эти тесты проверяют контракты реализации. Они не доказывают, что произвольный репозиторий прошёл условия выпуска.
go test ./pkg/architecture -run '^TestSignedGovernanceRequiresExactScopeAndSeparationOfDuties$' -count=1
go test ./pkg/architecture -run '^TestNormativeGovernanceRequiresCompleteScopeRevisionAndRevocationState$' -count=1
go test ./pkg/architecture -run '^TestNormativeReleaseGateFiveProfilesAndStateMatrix$' -count=1
go test ./pkg/architecture -run '^TestStory1240FullIncrementalEquivalence$' -count=1
go test ./pkg/architecture -run '^TestCodeGraphReleaseGateRejectsLegacyAuthorityInEnforceNew$' -count=1