diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 03d2974..42a80fb 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,6 +14,9 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v7 + - name: Проверить режимы container workflow + shell: pwsh + run: ./scripts/check-workflows.ps1 - name: Проверить GitHub Actions run: docker run --rm -v "$GITHUB_WORKSPACE:/repo" -w /repo rhysd/actionlint:1.7.12 -color docs: diff --git a/.github/workflows/reusable-container.yml b/.github/workflows/reusable-container.yml index 9296fce..55f8ae1 100644 --- a/.github/workflows/reusable-container.yml +++ b/.github/workflows/reusable-container.yml @@ -38,8 +38,8 @@ jobs: push: ${{ github.event_name != 'pull_request' }} tags: ghcr.io/${{ github.repository_owner }}/${{ inputs.image-name }}:${{ github.sha }} load: ${{ github.event_name == 'pull_request' }} - provenance: mode=max - sbom: true + provenance: ${{ github.event_name == 'pull_request' && 'false' || 'mode=max' }} + sbom: ${{ github.event_name != 'pull_request' }} - name: Проверить образ if: github.event_name == 'pull_request' uses: aquasecurity/trivy-action@v0.36.0 diff --git a/README.md b/README.md index bd1883d..62aacc0 100644 --- a/README.md +++ b/README.md @@ -28,6 +28,7 @@ ```powershell pwsh ./scripts/check-docs.ps1 +pwsh ./scripts/check-workflows.ps1 ``` ## Полезные ссылки diff --git a/docs/architecture.md b/docs/architecture.md index 5cec8bc..f7c48ca 100644 --- a/docs/architecture.md +++ b/docs/architecture.md @@ -14,3 +14,7 @@ portable-agent/.github Общий workflow не должен знать устройство бизнес-кода. Нужные отличия передаются через простые входные параметры. Специальные правила остаются в репозитории сервиса. + +Container workflow имеет два режима. В pull request образ загружается в локальный Docker для проверки +Trivy, поэтому SBOM и provenance не создаются. После изменения `main` образ публикуется в GHCR вместе с +SBOM, максимальным provenance, attestation и подписью Cosign. diff --git a/docs/development.md b/docs/development.md index 2554f20..e663164 100644 --- a/docs/development.md +++ b/docs/development.md @@ -17,6 +17,7 @@ ```powershell pwsh ./scripts/check-docs.ps1 +pwsh ./scripts/check-workflows.ps1 ``` Новый общий workflow также проверяется в тестовом репозитории до обязательного включения для всех сервисов. diff --git a/docs/service-template.md b/docs/service-template.md index 5c12b35..915dfeb 100644 --- a/docs/service-template.md +++ b/docs/service-template.md @@ -2,7 +2,8 @@ GitHub показывает workflow templates при создании Actions workflow. Для Java, Python и Node есть отдельные короткие файлы, но результат одинаков: тесты, поиск секретов, Trivy, сборка контейнера, -SBOM, provenance и keyless-подпись Cosign. +В pull request образ проверяется локально через Trivy. При публикации из `main` добавляются SBOM, +provenance и keyless-подпись Cosign. Папка `service-template` содержит обязательную документацию. `SERVICE.md` — быстрый индекс границ сервиса. Он не генерируется из кода, потому что ответственность сервиса — архитектурное решение. diff --git a/scripts/check-workflows.ps1 b/scripts/check-workflows.ps1 new file mode 100644 index 0000000..dac0caf --- /dev/null +++ b/scripts/check-workflows.ps1 @@ -0,0 +1,40 @@ +$ErrorActionPreference = "Stop" + +$workflow = Get-Content -LiteralPath ".github/workflows/reusable-container.yml" -Raw +$requiredLines = @( + 'id-token: write', + 'push: ${{ github.event_name != ''pull_request'' }}', + 'load: ${{ github.event_name == ''pull_request'' }}', + 'provenance: ${{ github.event_name == ''pull_request'' && ''false'' || ''mode=max'' }}', + 'sbom: ${{ github.event_name != ''pull_request'' }}', + 'uses: actions/attest-build-provenance@v4', + 'push-to-registry: true', + 'uses: sigstore/cosign-installer@v4.0.0', + 'run: cosign sign --yes "${IMAGE}@${DIGEST}"' +) + +foreach ($line in $requiredLines) { + if (-not $workflow.Contains($line)) { + throw "В reusable-container.yml нет ожидаемого правила: $line" + } +} + +$publishSteps = @( + "Аттестовать образ", + "Установить Cosign", + "Подписать образ через GitHub OIDC" +) + +foreach ($stepName in $publishSteps) { + $escapedName = [regex]::Escape($stepName) + $stepPattern = "(?ms)^\s{6}- name: $escapedName\r?\n(?:(?!^\s{6}- name: ).)*" + $step = [regex]::Match($workflow, $stepPattern) + if (-not $step.Success) { + throw "В reusable-container.yml нет шага: $stepName" + } + if (-not $step.Value.Contains("if: github.event_name != 'pull_request'")) { + throw "Шаг '$stepName' не должен выполняться в pull request." + } +} + +Write-Host "Режимы container workflow настроены корректно."