Harden production SSH execution and CodeQL gate (#110) #147
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| name: release-artifacts | |
| # One release graph owns binaries, the VM candidate test, the draft GitHub | |
| # release, and GHCR promotion. A tag is not made visible as a release until the | |
| # exact candidate binaries pass positive and classified-negative VM tests and | |
| # the candidate container has been built and verified. | |
| on: | |
| push: | |
| branches: [main] | |
| tags: ["v*"] | |
| workflow_dispatch: | |
| permissions: | |
| contents: read | |
| concurrency: | |
| group: ${{ github.workflow }}-${{ github.ref }} | |
| cancel-in-progress: false | |
| env: | |
| GO_VERSION: "1.25.12" | |
| IMAGE: ghcr.io/kernel-guard/bpfcompat | |
| jobs: | |
| build-and-sign: | |
| name: Build candidate, SBOM, sign | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 25 | |
| permissions: | |
| actions: read | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| packages: read | |
| outputs: | |
| version: ${{ steps.meta.outputs.version }} | |
| channel: ${{ steps.meta.outputs.channel }} | |
| commit: ${{ steps.meta.outputs.commit }} | |
| build_date: ${{ steps.meta.outputs.build_date }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| with: | |
| fetch-depth: 0 | |
| - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - name: Validate release metadata | |
| run: make check-release-consistency | |
| - name: Verify protected production environment | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| reviewer="$(awk -F': ' '$1 == "release_reviewer" {print $2; exit}' release.yaml)" | |
| bash scripts/check-production-environment.sh \ | |
| "$GITHUB_REPOSITORY" production-release "$reviewer" | |
| - name: Refuse mutation of an already-published release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: bash scripts/check-release-state.sh "$GITHUB_REPOSITORY" "$GITHUB_REF_NAME" | |
| - name: Release quality gates | |
| run: | | |
| set -euo pipefail | |
| make check-docs-drift | |
| bash scripts/check-release-state_test.sh | |
| bash scripts/check-release-consistency_test.sh | |
| bash scripts/check-production-environment_test.sh | |
| bash scripts/promote-release_test.sh | |
| bash scripts/production-readiness-report_test.sh | |
| bash scripts/verify-release-assets_test.sh | |
| go vet ./... | |
| go test -race -count=1 ./... | |
| go run golang.org/x/vuln/cmd/govulncheck@v1.6.0 ./... | |
| make production-tech-check | |
| - name: Resolve build metadata | |
| id: meta | |
| env: | |
| REF: ${{ github.ref }} | |
| run: | | |
| set -euo pipefail | |
| release_channel="$(awk -F': ' '$1 == "release_channel" {print $2; exit}' release.yaml)" | |
| if [[ "$REF" == refs/tags/* ]]; then | |
| version="${REF#refs/tags/}" | |
| channel="$release_channel" | |
| else | |
| version="$(git describe --tags --always --dirty)" | |
| channel="preview" | |
| fi | |
| { | |
| echo "version=${version}" | |
| echo "channel=${channel}" | |
| echo "commit=$(git rev-parse --short=12 HEAD)" | |
| echo "build_date=$(date -u +%Y-%m-%dT%H:%M:%SZ)" | |
| } >> "$GITHUB_OUTPUT" | |
| - name: Build candidate binaries | |
| env: | |
| VERSION: ${{ steps.meta.outputs.version }} | |
| COMMIT: ${{ steps.meta.outputs.commit }} | |
| BUILD_DATE: ${{ steps.meta.outputs.build_date }} | |
| run: | | |
| set -euo pipefail | |
| mkdir -p dist | |
| LDFLAGS="-X github.com/kernel-guard/bpfcompat/internal/version.Version=${VERSION} \ | |
| -X github.com/kernel-guard/bpfcompat/internal/version.Commit=${COMMIT} \ | |
| -X github.com/kernel-guard/bpfcompat/internal/version.BuildDate=${BUILD_DATE}" | |
| CGO_ENABLED=0 go build -trimpath -ldflags "$LDFLAGS" \ | |
| -o dist/bpfcompat-linux-amd64 ./cmd/bpfcompat | |
| GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build -trimpath -ldflags "$LDFLAGS" \ | |
| -o dist/bpfcompat-linux-arm64 ./cmd/bpfcompat | |
| - name: Build static validator | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| libbpf-dev libelf-dev libzstd-dev zlib1g-dev | |
| make validator-static | |
| cp validator/c-libbpf/bin/bpfcompat-validator \ | |
| dist/bpfcompat-validator-static-linux-amd64 | |
| - name: Stage production readiness evidence | |
| if: startsWith(github.ref, 'refs/tags/v') && steps.meta.outputs.channel == 'stable' | |
| env: | |
| RELEASE_VERSION: ${{ steps.meta.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| version="${RELEASE_VERSION#v}" | |
| source_base="docs/releases/bpfcompat-${version}-readiness" | |
| test -s "${source_base}.json" | |
| test -s "${source_base}.md" | |
| jq -e --arg version "$version" ' | |
| .schema_version == "v0.1" and | |
| .gate_status == "ready" and | |
| .release_version == $version and | |
| .slo.campaign_count == 4 and | |
| .slo.infrastructure_errors == 0 and | |
| .reviewer.approved == true | |
| ' "${source_base}.json" >/dev/null | |
| cp "${source_base}.json" dist/production-readiness.json | |
| cp "${source_base}.md" dist/production-readiness.md | |
| - name: Compute checksums | |
| run: | | |
| set -euo pipefail | |
| cd dist | |
| assets=( | |
| bpfcompat-linux-amd64 | |
| bpfcompat-linux-arm64 | |
| bpfcompat-validator-static-linux-amd64 | |
| ) | |
| if [[ -s production-readiness.json && -s production-readiness.md ]]; then | |
| assets+=(production-readiness.json production-readiness.md) | |
| fi | |
| sha256sum "${assets[@]}" > SHA256SUMS | |
| - name: Generate SBOM | |
| uses: anchore/sbom-action@e22c389904149dbc22b58101806040fa8d37a610 # v0 | |
| with: | |
| path: . | |
| format: cyclonedx-json | |
| output-file: dist/bpfcompat.sbom.cdx.json | |
| - name: Attest candidate provenance | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 | |
| with: | |
| subject-path: | | |
| dist/bpfcompat-linux-amd64 | |
| dist/bpfcompat-linux-arm64 | |
| dist/bpfcompat-validator-static-linux-amd64 | |
| - name: Attest production readiness evidence | |
| if: startsWith(github.ref, 'refs/tags/v') && steps.meta.outputs.channel == 'stable' | |
| uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 | |
| with: | |
| subject-path: | | |
| dist/production-readiness.json | |
| dist/production-readiness.md | |
| - name: Attest candidate SBOM | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: actions/attest-sbom@c604332985a26aa8cf1bdc465b92731239ec6b9e # v4.1.0 | |
| with: | |
| subject-path: dist/bpfcompat-linux-amd64 | |
| sbom-path: dist/bpfcompat.sbom.cdx.json | |
| - name: Install cosign | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| with: | |
| cosign-release: "v2.6.3" | |
| - name: Sign checksums and SBOM | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| run: | | |
| set -euo pipefail | |
| cosign sign-blob --yes dist/SHA256SUMS \ | |
| --output-signature dist/SHA256SUMS.sig \ | |
| --output-certificate dist/SHA256SUMS.crt | |
| cosign sign-blob --yes dist/bpfcompat.sbom.cdx.json \ | |
| --output-signature dist/bpfcompat.sbom.cdx.sig \ | |
| --output-certificate dist/bpfcompat.sbom.cdx.crt | |
| - name: Upload candidate | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: bpfcompat-release-${{ steps.meta.outputs.version }} | |
| path: dist/ | |
| if-no-files-found: error | |
| - name: Upload production technical evidence | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: production-tech-evidence-${{ steps.meta.outputs.version }} | |
| path: evidence/production-tech/ | |
| if-no-files-found: error | |
| candidate-vm-gate: | |
| name: Candidate VM positive + classified negative | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: build-and-sign | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 45 | |
| permissions: | |
| contents: read | |
| attestations: read | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: actions/setup-go@b7ad1dad31e06c5925ef5d2fc7ad053ef454303e # v7.0.0 | |
| with: | |
| go-version: ${{ env.GO_VERSION }} | |
| cache: true | |
| - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: bpfcompat-release-${{ needs.build-and-sign.outputs.version }} | |
| path: dist | |
| - name: Verify candidate attestations | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: > | |
| bash scripts/verify-release-assets.sh | |
| dist Kernel-Guard/bpfcompat | |
| bpfcompat-linux-amd64 | |
| bpfcompat-validator-static-linux-amd64 | |
| - name: Install VM dependencies | |
| run: | | |
| set -euo pipefail | |
| sudo apt-get update | |
| sudo apt-get install -y --no-install-recommends \ | |
| qemu-system-x86 qemu-utils cloud-image-utils clang llvm \ | |
| libbpf-dev libelf-dev zlib1g-dev pkg-config jq | |
| if [[ -e /dev/kvm ]]; then | |
| sudo chmod 0666 /dev/kvm | |
| fi | |
| - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 | |
| with: | |
| path: vm/cache/ubuntu-22.04-release-20260722.qcow2 | |
| key: ubuntu-22.04-release-20260722-757908b2 | |
| - name: Prepare exact candidates and fixtures | |
| env: | |
| EXPECTED_VERSION: ${{ needs.build-and-sign.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| chmod +x dist/bpfcompat-linux-amd64 \ | |
| dist/bpfcompat-validator-static-linux-amd64 | |
| actual="$(dist/bpfcompat-linux-amd64 version --json | jq -r .version)" | |
| test "$actual" = "$EXPECTED_VERSION" | |
| make examples | |
| echo "BPFCOMPAT_VALIDATOR_BIN=${GITHUB_WORKSPACE}/dist/bpfcompat-validator-static-linux-amd64" >> "$GITHUB_ENV" | |
| echo "BPFCOMPAT_VALIDATOR_SHA256=$(sha256sum dist/bpfcompat-validator-static-linux-amd64 | awk '{print $1}')" >> "$GITHUB_ENV" | |
| - name: Positive test through the candidate Action | |
| uses: ./ | |
| with: | |
| artifact: examples/simple-pass/simple_pass.bpf.o | |
| manifest: examples/simple-pass/manifest-dev-one.yaml | |
| matrix: matrices/dev-one.yaml | |
| out: reports/release-positive.json | |
| markdown: reports/release-positive.md | |
| timeout: 8m | |
| concurrency: "1" | |
| binary: dist/bpfcompat-linux-amd64 | |
| build: "false" | |
| prebuilt: "never" | |
| - name: Classified negative test through the candidate binary | |
| run: | | |
| set -euo pipefail | |
| set +e | |
| dist/bpfcompat-linux-amd64 test \ | |
| --artifact examples/unknown-load-fail/invalid_object.bin \ | |
| --manifest examples/unknown-load-fail/manifest-dev-one.yaml \ | |
| --matrix matrices/dev-one.yaml \ | |
| --out reports/release-negative.json \ | |
| --markdown reports/release-negative.md \ | |
| --timeout 8m \ | |
| --concurrency 1 | |
| rc=$? | |
| set -e | |
| test "$rc" -eq 2 | |
| jq -e '.summary.status == "pass"' reports/release-positive.json >/dev/null | |
| jq -e '.summary.status == "fail"' reports/release-negative.json >/dev/null | |
| jq -e '.targets | all(.status != "infra_error")' \ | |
| reports/release-positive.json reports/release-negative.json >/dev/null | |
| jq -e --arg validator "$BPFCOMPAT_VALIDATOR_SHA256" \ | |
| '.validator.sha256 == $validator' \ | |
| reports/release-positive.json reports/release-negative.json >/dev/null | |
| jq -e '.. | objects | select(.classification_code? == "UNKNOWN")' \ | |
| reports/release-negative.json >/dev/null | |
| jq -e --arg digest "757908b2fd6d5b1431bb45070fc1f56cbf017d4025568d292ece37d9cc75e812" \ | |
| 'all(.targets[]; any(.notes[]?; contains($digest)))' \ | |
| reports/release-positive.json reports/release-negative.json >/dev/null | |
| - name: Upload release-gate evidence | |
| if: always() | |
| uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: release-gate-evidence-${{ github.run_id }} | |
| path: | | |
| reports/release-positive.json | |
| reports/release-positive.md | |
| reports/release-negative.json | |
| reports/release-negative.md | |
| .bpfcompat/runs/**/targets/**/serial.log | |
| .bpfcompat/runs/**/targets/**/libbpf.log | |
| .bpfcompat/runs/**/targets/**/validator-result.json | |
| if-no-files-found: warn | |
| candidate-arm64-cli-gate: | |
| name: Candidate ARM64 CLI native smoke | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: build-and-sign | |
| runs-on: ubuntu-24.04-arm | |
| timeout-minutes: 15 | |
| permissions: | |
| contents: read | |
| attestations: read | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: bpfcompat-release-${{ needs.build-and-sign.outputs.version }} | |
| path: dist | |
| - name: Verify ARM64 candidate attestation | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: > | |
| bash scripts/verify-release-assets.sh | |
| dist Kernel-Guard/bpfcompat | |
| bpfcompat-linux-arm64 | |
| - name: Execute ARM64 candidate natively | |
| env: | |
| EXPECTED_VERSION: ${{ needs.build-and-sign.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| test "$(uname -m)" = "aarch64" | |
| chmod +x dist/bpfcompat-linux-arm64 | |
| actual="$(dist/bpfcompat-linux-arm64 version --json | jq -r .version)" | |
| test "$actual" = "$EXPECTED_VERSION" | |
| dist/bpfcompat-linux-arm64 --help >/dev/null | |
| build-candidate-image: | |
| name: Build, verify, sign candidate image | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: [build-and-sign, candidate-vm-gate, candidate-arm64-cli-gate] | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 40 | |
| permissions: | |
| contents: read | |
| packages: write | |
| id-token: write | |
| attestations: write | |
| outputs: | |
| digest: ${{ steps.build.outputs.digest }} | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: docker/setup-qemu-action@49b3bc8e6bdd4a60e6116a5414239cba5943d3cf # v3.2.0 | |
| - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 | |
| - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Build candidate image | |
| id: build | |
| uses: docker/build-push-action@48aba3b46d1b1fec4febb7c5d0c644b249a11355 # v6.10.0 | |
| with: | |
| context: . | |
| platforms: linux/amd64,linux/arm64 | |
| target: final | |
| push: true | |
| provenance: false | |
| sbom: false | |
| tags: ${{ env.IMAGE }}:candidate-${{ github.sha }} | |
| build-args: | | |
| VERSION=${{ needs.build-and-sign.outputs.version }} | |
| COMMIT=${{ needs.build-and-sign.outputs.commit }} | |
| BUILD_DATE=${{ needs.build-and-sign.outputs.build_date }} | |
| - name: Verify candidate image version | |
| env: | |
| DIGEST: ${{ steps.build.outputs.digest }} | |
| EXPECTED_VERSION: ${{ needs.build-and-sign.outputs.version }} | |
| run: | | |
| set -euo pipefail | |
| actual="$(docker run --rm "${IMAGE}@${DIGEST}" version --json | jq -r .version)" | |
| test "$actual" = "$EXPECTED_VERSION" | |
| - uses: sigstore/cosign-installer@6f9f17788090df1f26f669e9d70d6ae9567deba6 # v4.1.2 | |
| with: | |
| cosign-release: "v2.6.3" | |
| - name: Sign candidate image | |
| env: | |
| DIGEST: ${{ steps.build.outputs.digest }} | |
| run: cosign sign --yes "${IMAGE}@${DIGEST}" | |
| - name: Attest candidate image provenance | |
| uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 | |
| with: | |
| subject-name: ${{ env.IMAGE }} | |
| subject-digest: ${{ steps.build.outputs.digest }} | |
| push-to-registry: true | |
| assemble-candidate-evidence: | |
| name: Assemble candidate promotion evidence | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: | |
| - build-and-sign | |
| - candidate-vm-gate | |
| - candidate-arm64-cli-gate | |
| - build-candidate-image | |
| runs-on: ubuntu-latest | |
| timeout-minutes: 10 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| attestations: write | |
| steps: | |
| - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: bpfcompat-release-${{ needs.build-and-sign.outputs.version }} | |
| path: candidate/dist | |
| - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: release-gate-evidence-${{ github.run_id }} | |
| path: candidate/vm | |
| - name: Bind promotion evidence to exact inputs and outputs | |
| env: | |
| RELEASE_VERSION: ${{ needs.build-and-sign.outputs.version }} | |
| RELEASE_CHANNEL: ${{ needs.build-and-sign.outputs.channel }} | |
| IMAGE_DIGEST: ${{ needs.build-candidate-image.outputs.digest }} | |
| run: | | |
| set -euo pipefail | |
| positive="candidate/vm/reports/release-positive.json" | |
| negative="candidate/vm/reports/release-negative.json" | |
| checksums="candidate/dist/SHA256SUMS" | |
| test -s "$positive" | |
| test -s "$negative" | |
| test -s "$checksums" | |
| jq -e '.summary.status == "pass"' "$positive" >/dev/null | |
| jq -e ' | |
| .summary.status == "fail" and | |
| ([.targets[] | select(.status == "infra_error")] | length == 0) | |
| ' "$negative" >/dev/null | |
| mkdir -p candidate/evidence | |
| jq -n \ | |
| --arg schema_version "v0.1" \ | |
| --arg repository "$GITHUB_REPOSITORY" \ | |
| --arg workflow "$GITHUB_WORKFLOW_REF" \ | |
| --argjson run_id "$GITHUB_RUN_ID" \ | |
| --argjson run_attempt "$GITHUB_RUN_ATTEMPT" \ | |
| --arg commit_sha "$GITHUB_SHA" \ | |
| --arg tag "$RELEASE_VERSION" \ | |
| --arg channel "$RELEASE_CHANNEL" \ | |
| --arg image "${IMAGE}@${IMAGE_DIGEST}" \ | |
| --arg checksums_sha256 "$(sha256sum "$checksums" | awk '{print $1}')" \ | |
| --arg positive_report_sha256 "$(sha256sum "$positive" | awk '{print $1}')" \ | |
| --arg negative_report_sha256 "$(sha256sum "$negative" | awk '{print $1}')" \ | |
| --arg generated_at "$(date -u +%Y-%m-%dT%H:%M:%SZ)" \ | |
| '{ | |
| schema_version: $schema_version, | |
| repository: $repository, | |
| workflow: $workflow, | |
| workflow_run_id: $run_id, | |
| workflow_run_attempt: $run_attempt, | |
| commit_sha: $commit_sha, | |
| tag: $tag, | |
| channel: $channel, | |
| image: $image, | |
| checksums_sha256: $checksums_sha256, | |
| positive_report_sha256: $positive_report_sha256, | |
| negative_report_sha256: $negative_report_sha256, | |
| generated_at: $generated_at | |
| }' >candidate/evidence/release-candidate-evidence.json | |
| - name: Attest candidate promotion evidence | |
| uses: actions/attest-build-provenance@0f67c3f4856b2e3261c31976d6725780e5e4c373 # v4.1.1 | |
| with: | |
| subject-path: candidate/evidence/release-candidate-evidence.json | |
| - uses: actions/upload-artifact@043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7 | |
| with: | |
| name: bpfcompat-candidate-evidence-${{ needs.build-and-sign.outputs.version }} | |
| path: candidate/evidence/release-candidate-evidence.json | |
| if-no-files-found: error | |
| stage-draft-release: | |
| name: Stage draft release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: [build-and-sign, assemble-candidate-evidence] | |
| runs-on: ubuntu-latest | |
| permissions: | |
| contents: write | |
| steps: | |
| - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: bpfcompat-release-${{ needs.build-and-sign.outputs.version }} | |
| path: dist | |
| - uses: actions/download-artifact@018cc2cf5baa6db3ef3c5f8a56943fffe632ef53 # v6.0.0 | |
| with: | |
| name: bpfcompat-candidate-evidence-${{ needs.build-and-sign.outputs.version }} | |
| path: dist | |
| - uses: softprops/action-gh-release@3d0d9888cb7fd7b750713d6e236d1fcb99157228 # v3 | |
| with: | |
| draft: true | |
| prerelease: ${{ needs.build-and-sign.outputs.channel == 'prerelease' }} | |
| make_latest: false | |
| fail_on_unmatched_files: ${{ needs.build-and-sign.outputs.channel == 'stable' }} | |
| generate_release_notes: true | |
| files: | | |
| dist/bpfcompat-linux-amd64 | |
| dist/bpfcompat-linux-arm64 | |
| dist/bpfcompat-validator-static-linux-amd64 | |
| dist/SHA256SUMS | |
| dist/SHA256SUMS.sig | |
| dist/SHA256SUMS.crt | |
| dist/bpfcompat.sbom.cdx.json | |
| dist/bpfcompat.sbom.cdx.sig | |
| dist/bpfcompat.sbom.cdx.crt | |
| dist/release-candidate-evidence.json | |
| dist/production-readiness.* | |
| promote: | |
| name: Promote image and publish release | |
| if: startsWith(github.ref, 'refs/tags/v') | |
| needs: | |
| - build-and-sign | |
| - build-candidate-image | |
| - assemble-candidate-evidence | |
| - stage-draft-release | |
| runs-on: ubuntu-latest | |
| environment: | |
| name: production-release | |
| permissions: | |
| contents: write | |
| packages: write | |
| steps: | |
| - uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 # v7.0.0 | |
| - uses: docker/setup-buildx-action@c47758b77c9736f4b2ef4073d4d51994fabfe349 # v3.7.1 | |
| - uses: docker/login-action@9780b0c442fbb1117ed29e0efdff1e18412f7567 # v3.3.0 | |
| with: | |
| registry: ghcr.io | |
| username: ${{ github.actor }} | |
| password: ${{ secrets.GITHUB_TOKEN }} | |
| - name: Promote the verified image digest | |
| env: | |
| DIGEST: ${{ needs.build-candidate-image.outputs.digest }} | |
| RELEASE_VERSION: ${{ needs.build-and-sign.outputs.version }} | |
| RELEASE_CHANNEL: ${{ needs.build-and-sign.outputs.channel }} | |
| GH_TOKEN: ${{ github.token }} | |
| run: | | |
| set -euo pipefail | |
| bash scripts/promote-release.sh \ | |
| "$IMAGE" "$DIGEST" "$RELEASE_VERSION" "$RELEASE_CHANNEL" |