Repository navigation
fix(release): accept current Grype database schema #1074
Workflow file for this run
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: RegistryStack CI | |
| on: | |
| pull_request: | |
| branches: | |
| - main | |
| - release/1.0 | |
| merge_group: | |
| types: | |
| - checks_requested | |
| push: | |
| branches: | |
| - main | |
| concurrency: | |
| group: ci-${{ github.event_name == 'pull_request' && format('pr-{0}', github.event.pull_request.number) || format('run-{0}', github.run_id) }} | |
| cancel-in-progress: ${{ github.event_name == 'pull_request' }} | |
| permissions: | |
| contents: read | |
| env: | |
| CARGO_TERM_COLOR: always | |
| CARGO_INCREMENTAL: "0" | |
| CARGO_PROFILE_DEV_DEBUG: "0" | |
| CARGO_PROFILE_TEST_DEBUG: "0" | |
| CARGO_FUZZ_VERSION: "0.13.2" | |
| CARGO_LLVM_COV_VERSION: "0.8.7" | |
| GITLEAKS_VERSION: "8.30.1" | |
| GITLEAKS_LINUX_X64_SHA256: "551f6fc83ea457d62a0d98237cbad105af8d557003051f41f3e7ca7b3f2470eb" | |
| ACTIONLINT_VERSION: "1.7.7" | |
| ACTIONLINT_LINUX_X64_SHA256: "023070a287cd8cccd71515fedc843f1985bf96c436b7effaecce67290e7e0757" | |
| OASDIFF_VERSION: "1.23.0" | |
| OASDIFF_LINUX_X64_SHA256: "972b10535c3db4366b9dc3ebc11ca021279af3095267c3cffdca854a3a3c4f89" | |
| jobs: | |
| changes: | |
| name: Changed paths | |
| runs-on: ubuntu-24.04 | |
| outputs: | |
| rust: ${{ steps.filter.outputs.rust }} | |
| rust_matrix: ${{ steps.filter.outputs.rust_matrix }} | |
| rust_packages: ${{ steps.filter.outputs.rust_packages }} | |
| platform: ${{ steps.filter.outputs.platform }} | |
| platform_hygiene: ${{ steps.filter.outputs.platform_hygiene }} | |
| notary_contracts: ${{ steps.filter.outputs.notary_contracts }} | |
| relay_contracts: ${{ steps.filter.outputs.relay_contracts }} | |
| project_authoring: ${{ steps.filter.outputs.project_authoring }} | |
| release_tool: ${{ steps.filter.outputs.release_tool }} | |
| release_source_proof: ${{ steps.filter.outputs.release_source_proof }} | |
| docs: ${{ steps.filter.outputs.docs }} | |
| docs_archives: ${{ steps.filter.outputs.docs_archives }} | |
| editors: ${{ steps.filter.outputs.editors }} | |
| registryctl_tutorial: ${{ steps.filter.outputs.registryctl_tutorial }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Classify changed paths | |
| id: filter | |
| env: | |
| BASE_SHA: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }} | |
| HEAD_SHA: ${{ github.event.pull_request.head.sha || github.event.merge_group.head_sha || github.sha }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| metadata="${RUNNER_TEMP}/registry-stack-cargo-metadata.json" | |
| changed_files="${RUNNER_TEMP}/registry-stack-changed-files" | |
| cargo metadata --locked --format-version 1 > "${metadata}" | |
| classifier=( | |
| python3 .github/scripts/ci_changes.py | |
| --metadata "${metadata}" | |
| --github-output "${GITHUB_OUTPUT}" | |
| ) | |
| if [[ "${GITHUB_EVENT_NAME}" == "pull_request" ]]; then | |
| if git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null && | |
| git cat-file -e "${HEAD_SHA}^{commit}" 2>/dev/null; then | |
| git diff --name-only "${BASE_SHA}" "${HEAD_SHA}" > "${changed_files}" | |
| classifier+=(--changed-files "${changed_files}") | |
| else | |
| classifier+=(--all) | |
| fi | |
| elif git cat-file -e "${BASE_SHA}^{commit}" 2>/dev/null && | |
| git cat-file -e "${HEAD_SHA}^{commit}" 2>/dev/null; then | |
| # Keep push and merge-queue complete matrices while preserving | |
| # paths for gates that intentionally do not run on every change. | |
| git diff --name-only "${BASE_SHA}" "${HEAD_SHA}" > "${changed_files}" | |
| classifier+=(--all --changed-files "${changed_files}") | |
| else | |
| # Runs without resolvable comparison commits use the complete | |
| # matrix and leave opt-in immutable archive verification skipped. | |
| classifier+=(--all) | |
| fi | |
| "${classifier[@]}" | |
| - name: Test CI classifier | |
| run: python3 .github/scripts/test_ci_changes.py | |
| - name: Install pinned actionlint | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${RUNNER_TEMP}/bin" | |
| curl --proto '=https' --tlsv1.2 --fail --silent --show-error --location \ | |
| --output "${RUNNER_TEMP}/actionlint.tar.gz" \ | |
| "https://github.com/rhysd/actionlint/releases/download/v${ACTIONLINT_VERSION}/actionlint_${ACTIONLINT_VERSION}_linux_amd64.tar.gz" | |
| echo "${ACTIONLINT_LINUX_X64_SHA256} ${RUNNER_TEMP}/actionlint.tar.gz" | \ | |
| sha256sum --check --strict | |
| tar -xzf "${RUNNER_TEMP}/actionlint.tar.gz" -C "${RUNNER_TEMP}/bin" actionlint | |
| - name: Lint GitHub Actions workflows | |
| run: | | |
| set -euo pipefail | |
| "${RUNNER_TEMP}/bin/actionlint" | |
| - name: Check advisory checker copies | |
| run: python3 release/scripts/check_advisory_checker_copies.py | |
| - name: Test advisory baseline checkers | |
| run: | | |
| python3 -m unittest products/notary/tests/advisory_baseline_check_test.py | |
| python3 -m unittest crates/registry-relay/tests/advisory_baseline_check_test.py | |
| - name: Test advisory checker copy guard | |
| run: python3 -m unittest release/scripts/test_check_advisory_checker_copies.py | |
| - name: Check Debian 13 image contract | |
| run: python3 release/scripts/check-debian13-images.py | |
| secrets: | |
| name: Secret scan | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| submodules: false | |
| - name: Install pinned Gitleaks | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${RUNNER_TEMP}/bin" | |
| curl --fail --silent --show-error --location \ | |
| --output "${RUNNER_TEMP}/gitleaks.tar.gz" \ | |
| "https://github.com/gitleaks/gitleaks/releases/download/v${GITLEAKS_VERSION}/gitleaks_${GITLEAKS_VERSION}_linux_x64.tar.gz" | |
| echo "${GITLEAKS_LINUX_X64_SHA256} ${RUNNER_TEMP}/gitleaks.tar.gz" | sha256sum -c - | |
| tar -xzf "${RUNNER_TEMP}/gitleaks.tar.gz" -C "${RUNNER_TEMP}/bin" gitleaks | |
| chmod +x "${RUNNER_TEMP}/bin/gitleaks" | |
| - name: Scan tracked source for secrets | |
| run: >- | |
| "${RUNNER_TEMP}/bin/gitleaks" dir | |
| --config .gitleaks.toml | |
| --no-banner | |
| --redact | |
| --timeout 120 | |
| . | |
| platform-quality: | |
| name: Platform all-features | |
| needs: changes | |
| if: needs.changes.outputs.platform == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Cache Cargo registry and build artifacts | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| key: platform-all-features | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Lint platform crates with all features | |
| run: cargo clippy --locked -p registry-config-report -p 'registry-platform-*' --all-targets --all-features -- -D warnings | |
| platform-coverage: | |
| name: Platform line coverage | |
| needs: changes | |
| if: needs.changes.outputs.platform == 'true' | |
| runs-on: ubuntu-24.04 | |
| permissions: | |
| contents: read | |
| id-token: write | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| submodules: false | |
| - name: Cache Cargo registry and build artifacts | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| key: platform-coverage | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install pinned coverage tool | |
| uses: taiki-e/install-action@25435dc8dd3baed7417e0c96d3fe89013a5b2e09 # v2.81.3 | |
| with: | |
| tool: cargo-llvm-cov@${{ env.CARGO_LLVM_COV_VERSION }} | |
| - name: Enforce platform line coverage | |
| run: >- | |
| cargo llvm-cov --locked | |
| -p registry-config-report | |
| -p 'registry-platform-*' | |
| --all-features | |
| --fail-under-lines 80 | |
| - name: Export platform coverage | |
| run: | | |
| set -euo pipefail | |
| coverage_dir="target/platform-coverage" | |
| mkdir -p "${coverage_dir}" | |
| cargo llvm-cov report --locked \ | |
| -p registry-config-report \ | |
| -p 'registry-platform-*' \ | |
| --lcov \ | |
| --output-path "${coverage_dir}/platform.lcov" | |
| - name: Upload platform coverage to Codecov | |
| uses: codecov/codecov-action@fb8b3582c8e4def4969c97caa2f19720cb33a72f # v7.0.0 | |
| with: | |
| disable_search: true | |
| fail_ci_if_error: false | |
| files: target/platform-coverage/platform.lcov | |
| flags: platform | |
| name: platform | |
| use_oidc: true | |
| version: v11.3.1 | |
| platform-hygiene: | |
| name: Platform hygiene and config inventory | |
| needs: changes | |
| if: needs.changes.outputs.platform_hygiene == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Check shared Rust hygiene files | |
| run: products/platform/scripts/check-hygiene-alignment.sh | |
| - name: Audit monorepo config roots | |
| run: >- | |
| products/platform/scripts/audit-configs.sh | |
| --check | |
| --format paths | |
| > "${RUNNER_TEMP}/registry-config-inventory.txt" | |
| platform-fuzz: | |
| name: Platform fuzz smoke (${{ matrix.target }}) | |
| needs: changes | |
| if: needs.changes.outputs.platform == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| target: | |
| - authcommon_parsers | |
| - oid4vci_request_and_proof | |
| - sdjwt_holder_proof | |
| - sdjwt_issuance | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Install Rust nightly | |
| uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # nightly | |
| with: | |
| toolchain: nightly | |
| - name: Cache Cargo registry and build artifacts | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| key: platform-fuzz-${{ matrix.target }} | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install pinned cargo-fuzz | |
| uses: taiki-e/install-action@25435dc8dd3baed7417e0c96d3fe89013a5b2e09 # v2.81.3 | |
| with: | |
| tool: cargo-fuzz@${{ env.CARGO_FUZZ_VERSION }} | |
| - name: Smoke fuzz target | |
| working-directory: products/platform | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "fuzz/artifacts/${{ matrix.target }}" | |
| cargo +nightly fuzz run --fuzz-dir fuzz --target x86_64-unknown-linux-gnu "${{ matrix.target }}" -- \ | |
| -max_total_time=60 \ | |
| -rss_limit_mb=1024 \ | |
| -artifact_prefix="fuzz/artifacts/${{ matrix.target }}/" \ | |
| -print_final_stats=1 | |
| - name: Upload fuzz failures | |
| if: failure() | |
| uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 | |
| with: | |
| name: platform-fuzz-${{ matrix.target }} | |
| path: products/platform/fuzz/artifacts/${{ matrix.target }}/ | |
| if-no-files-found: ignore | |
| rust-policy: | |
| name: Rust policy | |
| needs: changes | |
| if: needs.changes.outputs.rust == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Cache Cargo registry | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| shared-key: workspace-registry | |
| cache-targets: false | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install cargo-deny | |
| uses: taiki-e/install-action@25435dc8dd3baed7417e0c96d3fe89013a5b2e09 # v2.81.3 | |
| with: | |
| tool: cargo-deny@0.19.8 | |
| - name: Gate inventory | |
| if: needs.changes.outputs.release_tool != 'true' | |
| run: python3 release/scripts/check-gates-inventory.py | |
| - name: Test gate inventory | |
| if: needs.changes.outputs.release_tool != 'true' | |
| run: python3 -m unittest release/scripts/test_check_gates_inventory.py | |
| - name: Test stable surface compatibility checker | |
| if: needs.changes.outputs.release_tool != 'true' | |
| run: python3 -m unittest release/scripts/test_check_stable_surface_compatibility.py | |
| - name: Stable surface compatibility | |
| if: needs.changes.outputs.release_tool != 'true' | |
| env: | |
| STABLE_SURFACE_BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }} | |
| run: python3 release/scripts/check-stable-surface-compatibility.py | |
| - name: Cargo deny | |
| run: cargo deny check | |
| rust-quality: | |
| name: Rust format and clippy | |
| needs: changes | |
| if: needs.changes.outputs.rust == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| env: | |
| CI_RUST_PACKAGES: ${{ needs.changes.outputs.rust_packages }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Cache Cargo registry | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| shared-key: workspace-registry | |
| cache-targets: false | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Format | |
| run: cargo fmt --check | |
| - name: Clippy affected packages | |
| run: python3 .github/scripts/run_cargo_packages.py clippy | |
| - name: Report disk usage | |
| if: always() | |
| run: | | |
| df -h / | |
| du -sh target 2>/dev/null || true | |
| rust-tests: | |
| name: Rust tests (${{ matrix.name }}) | |
| needs: changes | |
| if: needs.changes.outputs.rust == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 15 | |
| strategy: | |
| fail-fast: false | |
| matrix: ${{ fromJSON(needs.changes.outputs.rust_matrix) }} | |
| env: | |
| CI_RUST_ALL_FEATURES: ${{ matrix.all_features }} | |
| CI_RUST_PACKAGES: ${{ toJSON(matrix.packages) }} | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| persist-credentials: false | |
| submodules: false | |
| - name: Cache Cargo registry | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| shared-key: workspace-registry | |
| cache-targets: false | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Test affected packages | |
| run: python3 .github/scripts/run_cargo_packages.py test | |
| - name: Validate Manifest profiles | |
| if: matrix.name == 'manifest' | |
| working-directory: products/manifest | |
| run: cargo run --locked --profile ci -p registry-manifest-cli -- validate-profiles profiles | |
| - name: Report disk usage | |
| if: always() | |
| run: | | |
| df -h / | |
| du -sh target 2>/dev/null || true | |
| notary-contracts: | |
| name: Notary API contracts | |
| needs: changes | |
| if: needs.changes.outputs.notary_contracts == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| submodules: false | |
| - name: Cache Cargo registry | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| shared-key: workspace-registry | |
| cache-targets: false | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install just | |
| uses: taiki-e/install-action@25435dc8dd3baed7417e0c96d3fe89013a5b2e09 # v2.81.3 | |
| with: | |
| tool: just@1.51.0 | |
| - name: Install pinned oasdiff | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${RUNNER_TEMP}/bin" | |
| curl --fail --silent --show-error --location \ | |
| --output "${RUNNER_TEMP}/oasdiff.tar.gz" \ | |
| "https://github.com/oasdiff/oasdiff/releases/download/v${OASDIFF_VERSION}/oasdiff_${OASDIFF_VERSION}_linux_amd64.tar.gz" | |
| echo "${OASDIFF_LINUX_X64_SHA256} ${RUNNER_TEMP}/oasdiff.tar.gz" | sha256sum -c - | |
| tar -xzf "${RUNNER_TEMP}/oasdiff.tar.gz" -C "${RUNNER_TEMP}/bin" oasdiff | |
| chmod +x "${RUNNER_TEMP}/bin/oasdiff" | |
| echo "${RUNNER_TEMP}/bin" >> "${GITHUB_PATH}" | |
| - name: Notary OpenAPI baseline | |
| working-directory: products/notary | |
| run: just openapi-check | |
| - name: Notary OpenAPI contract | |
| working-directory: products/notary | |
| env: | |
| OPENAPI_CONTRACT_BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }} | |
| run: just openapi-contract | |
| - name: Notary exposure check | |
| working-directory: products/notary | |
| run: just exposure-check | |
| relay-contracts: | |
| name: Relay API contracts | |
| needs: changes | |
| if: needs.changes.outputs.relay_contracts == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 10 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| persist-credentials: false | |
| submodules: false | |
| - name: Cache Cargo registry | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| shared-key: workspace-registry | |
| cache-targets: false | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Install just | |
| uses: taiki-e/install-action@25435dc8dd3baed7417e0c96d3fe89013a5b2e09 # v2.81.3 | |
| with: | |
| tool: just@1.51.0 | |
| - name: Install pinned oasdiff | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| mkdir -p "${RUNNER_TEMP}/bin" | |
| curl --fail --silent --show-error --location \ | |
| --output "${RUNNER_TEMP}/oasdiff.tar.gz" \ | |
| "https://github.com/oasdiff/oasdiff/releases/download/v${OASDIFF_VERSION}/oasdiff_${OASDIFF_VERSION}_linux_amd64.tar.gz" | |
| echo "${OASDIFF_LINUX_X64_SHA256} ${RUNNER_TEMP}/oasdiff.tar.gz" | sha256sum -c - | |
| tar -xzf "${RUNNER_TEMP}/oasdiff.tar.gz" -C "${RUNNER_TEMP}/bin" oasdiff | |
| chmod +x "${RUNNER_TEMP}/bin/oasdiff" | |
| echo "${RUNNER_TEMP}/bin" >> "${GITHUB_PATH}" | |
| - name: Relay OpenAPI contract | |
| working-directory: crates/registry-relay | |
| env: | |
| OPENAPI_CONTRACT_BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }} | |
| run: just openapi-contract | |
| - name: Relay exposure check | |
| working-directory: crates/registry-relay | |
| run: just exposure-check | |
| - name: Verify disposable local OpenAPI opt-out | |
| run: >- | |
| cargo test --locked -p registry-relay --test api_docs | |
| openapi_json_can_be_moved_to_public_router_for_local_testing -- --exact | |
| rust-result: | |
| name: Rust workspace | |
| if: always() | |
| needs: | |
| - changes | |
| - rust-policy | |
| - rust-quality | |
| - rust-tests | |
| - notary-contracts | |
| - relay-contracts | |
| runs-on: ubuntu-24.04 | |
| env: | |
| RUST_JOB_RESULTS: ${{ toJSON(needs) }} | |
| steps: | |
| - name: Require every selected Rust job | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| import sys | |
| jobs = json.loads(os.environ["RUST_JOB_RESULTS"]) | |
| failed = { | |
| name: details["result"] | |
| for name, details in jobs.items() | |
| if details["result"] not in {"success", "skipped"} | |
| } | |
| if failed: | |
| print(f"Rust jobs did not pass: {failed}", file=sys.stderr) | |
| raise SystemExit(1) | |
| print("Every selected Rust job passed; unselected jobs were skipped.") | |
| PY | |
| project-authoring-determinism: | |
| name: Project authoring portability and determinism (${{ matrix.arch }}) | |
| needs: changes | |
| if: needs.changes.outputs.project_authoring == 'true' | |
| runs-on: ${{ matrix.runner }} | |
| strategy: | |
| fail-fast: false | |
| matrix: | |
| include: | |
| - runner: ubuntu-24.04 | |
| arch: x86_64-linux | |
| expected_uname: x86_64 | |
| - runner: macos-14 | |
| arch: aarch64-macos | |
| expected_uname: arm64 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Assert native architecture | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| test "$(uname -m)" = "${{ matrix.expected_uname }}" | |
| - name: Cache Cargo registry and build artifacts | |
| uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # v2 | |
| with: | |
| key: project-authoring-${{ matrix.arch }} | |
| save-if: ${{ github.ref == 'refs/heads/main' }} | |
| - name: Build the Registryctl journey binary | |
| run: cargo build --locked -p registryctl --bin registryctl | |
| - name: Verify cross-machine project inputs | |
| run: >- | |
| cargo test --locked -p registryctl --test project_authoring | |
| check_and_build_produce_deterministic_product_inputs -- --exact | |
| - name: Verify offline Script authoring and compilation | |
| env: | |
| CARGO_NET_OFFLINE: "true" | |
| run: >- | |
| cargo test --locked -p registryctl --test project_authoring | |
| project_authoring_rhai_commands_are_portable_offline -- --exact | |
| - name: Verify every cataloged authoring journey | |
| run: >- | |
| cargo test --locked -p registryctl --test project_authoring | |
| every_cataloged_supported_project_authoring_command_is_automated -- --exact | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e | |
| with: | |
| node-version: 22.12.0 | |
| cache: npm | |
| cache-dependency-path: docs/site/package-lock.json | |
| - name: Install docs shell dependency | |
| if: runner.os == 'Linux' | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install --yes zsh | |
| - name: Assert docs shell dependencies | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| command -v sh | |
| command -v bash | |
| command -v zsh | |
| - name: Install docs dependencies | |
| working-directory: docs/site | |
| run: npm ci | |
| - name: Execute required standard journey commands from clean directories | |
| working-directory: docs/site | |
| env: | |
| REGISTRYCTL_BIN: ${{ github.workspace }}/target/debug/registryctl | |
| run: >- | |
| node --test | |
| --test-name-pattern="executes every required noninteractive sequence" | |
| scripts/generate-standard-journeys.test.mjs | |
| release-tool: | |
| name: Release tooling checks | |
| needs: changes | |
| if: needs.changes.outputs.release_tool == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Test release helper | |
| run: python3 -m unittest release/scripts/test_registry_release.py | |
| - name: Test first-country release-form runner | |
| run: python3 -m unittest release/scripts/test_first_country_release_form.py | |
| - name: Test release planning commands | |
| run: python3 -m unittest release/scripts/test_registry_release_plans.py | |
| - name: Test release candidate receipt and promotion verifier | |
| run: python3 -m unittest release/scripts/test_release_candidate.py | |
| - name: Test release proof-level selection | |
| run: python3 -m unittest release/scripts/test_select_release_proof_level.py | |
| - name: Test release storage preflight | |
| run: python3 -m unittest release/scripts/test_check_release_storage.py | |
| - name: Test release candidate cleanup | |
| run: python3 -m unittest release/scripts/test_cleanup_release_candidates.py | |
| - name: Test release repeatability workflow | |
| run: python3 -m unittest release/scripts/test_release_repeatability_workflow.py | |
| - name: Test release image OCI label checker | |
| run: python3 -m unittest release/scripts/test_check_release_image_oci_labels.py | |
| - name: Test release image layout comparator | |
| run: python3 -m unittest release/scripts/test_compare_release_image_layouts.py | |
| - name: Test release Relay feature checker | |
| run: python3 -m unittest release/scripts/test_check_release_relay_features.py | |
| - name: Set up Docker Buildx | |
| uses: docker/setup-buildx-action@d7f5e7f509e45cec5c76c4d5afdd7de93d0b3df5 | |
| with: | |
| version: v0.33.0 | |
| driver-opts: image=moby/buildkit:v0.31.2@sha256:2f5adac4ecd194d9f8c10b7b5d7bceb5186853db1b26e5abd3a657af0b7e26ec | |
| - name: Smoke release image OCI labels | |
| run: release/scripts/smoke-release-image-oci-labels.sh | |
| - name: Test OpenID conformance runner | |
| run: python3 -m unittest release/scripts/test_openid_conformance_runner.py | |
| - name: Test external integration evidence runner | |
| run: python3 -m unittest release/scripts/test_integration_e2_runner.py | |
| - name: Test conformance candidate binding | |
| run: python3 -m unittest release/scripts/test_conformance_candidate.py | |
| - name: Validate external integration evidence packet | |
| run: python3 release/scripts/integration-e2-runner.py validate | |
| - name: Test Relay OIDC smoke | |
| run: python3 -m unittest release/scripts/test_relay_oidc_smoke.py | |
| - name: Validate Relay OIDC smoke assets | |
| run: python3 release/scripts/relay-oidc-smoke.py validate | |
| - name: Gate inventory | |
| run: python3 release/scripts/check-gates-inventory.py | |
| - name: Test gate inventory | |
| run: python3 -m unittest release/scripts/test_check_gates_inventory.py | |
| - name: Test stable surface compatibility checker | |
| run: python3 -m unittest release/scripts/test_check_stable_surface_compatibility.py | |
| - name: Test Relay OpenAPI stability filter | |
| run: python3 -m unittest release/scripts/test_filter_relay_openapi_stability.py | |
| - name: Test upgrade exercise validator | |
| run: python3 -m unittest release/scripts/test_validate_upgrade_exercise.py | |
| - name: Test product-input lifecycle validator | |
| run: python3 -m unittest release/scripts/test_validate_product_input_lifecycle.py | |
| - name: Test first-country acceptance validator | |
| run: python3 -m unittest release/scripts/test_validate_first_country_acceptance.py | |
| - name: Validate first-country acceptance source packet | |
| run: python3 release/scripts/validate-first-country-acceptance.py check-packet | |
| - name: Test upgrade exercise asset preparation | |
| run: python3 -m unittest release/scripts/test_prepare_upgrade_exercise_assets.py | |
| - name: Prepare committed candidate assets | |
| id: candidate-assets | |
| env: | |
| GH_TOKEN: ${{ github.token }} | |
| run: >- | |
| python3 release/scripts/prepare-upgrade-exercise-assets.py | |
| --discover release/exercises | |
| --product-input-records release/exercises/product-input-lifecycle | |
| --asset-root target/candidate-release-assets | |
| --github-output "${GITHUB_OUTPUT}" | |
| - name: Install cosign for committed candidate evidence | |
| if: steps.candidate-assets.outputs.has_candidates == 'true' | |
| uses: sigstore/cosign-installer@398d4b0eeef1380460a10c8013a76f728fb906ac # v3 | |
| - name: Install SLSA verifier for committed candidate evidence | |
| if: steps.candidate-assets.outputs.has_candidates == 'true' | |
| env: | |
| SLSA_VERIFIER_SHA256: 946dbec729094195e88ef78e1734324a27869f03e2c6bd2f61cbc06bd5350339 | |
| SLSA_VERIFIER_VERSION: v2.7.1 | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| tools_dir="${RUNNER_TEMP}/upgrade-evidence-tools" | |
| mkdir -p "${tools_dir}" | |
| curl --proto '=https' --tlsv1.2 --fail --location --retry 3 \ | |
| --output "${tools_dir}/slsa-verifier" \ | |
| "https://github.com/slsa-framework/slsa-verifier/releases/download/${SLSA_VERIFIER_VERSION}/slsa-verifier-linux-amd64" | |
| echo "${SLSA_VERIFIER_SHA256} ${tools_dir}/slsa-verifier" | sha256sum --check | |
| chmod 0755 "${tools_dir}/slsa-verifier" | |
| echo "${tools_dir}" >> "${GITHUB_PATH}" | |
| - name: Validate product-input lifecycle records | |
| run: >- | |
| python3 release/scripts/validate-product-input-lifecycle.py | |
| --discover release/exercises | |
| --candidate-asset-root target/candidate-release-assets | |
| - name: Validate committed upgrade exercise records | |
| run: >- | |
| python3 release/scripts/validate-upgrade-exercise.py | |
| --discover release/exercises | |
| --candidate-asset-root target/candidate-release-assets | |
| - name: Stable surface compatibility | |
| env: | |
| STABLE_SURFACE_BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before }} | |
| run: python3 release/scripts/check-stable-surface-compatibility.py | |
| - name: Validate release manifest | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| for manifest in release/manifests/registry-stack-*.yaml; do | |
| release/scripts/registry-release validate "${manifest}" | |
| done | |
| - name: Validate release docsets | |
| run: release/scripts/registry-release validate-docsets | |
| - name: Audit import map | |
| run: release/scripts/registry-release audit release/manifests/import-map-2026-06-24.yaml | |
| release-tool-required: | |
| # Branch protection requires this exact context. Keep it successful for | |
| # irrelevant changes without running the release-tooling suite. | |
| name: Release tooling | |
| needs: | |
| - changes | |
| - release-tool | |
| if: ${{ always() }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Report path-gated result | |
| env: | |
| CHANGES_RESULT: ${{ needs.changes.result }} | |
| REQUIRED: ${{ needs.changes.outputs.release_tool }} | |
| RESULT: ${{ needs.release-tool.result }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| case "${CHANGES_RESULT}:${REQUIRED}:${RESULT}" in | |
| success:true:success|success:false:skipped) | |
| ;; | |
| *) | |
| echo "Release tooling path gate did not complete safely: changes=${CHANGES_RESULT} required=${REQUIRED} result=${RESULT}" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| release-source-proof: | |
| name: Release source proof checks | |
| needs: changes | |
| if: needs.changes.outputs.release_source_proof == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Check monorepo source model | |
| run: REGISTRY_RELEASE_SOURCE_MODE=monorepo release/scripts/check-release-source-model.sh | |
| - name: Test source model checker | |
| run: python3 -m unittest release/scripts/test_check_release_source_model.py | |
| release-source-proof-required: | |
| # Branch protection requires this exact context. Keep it successful for | |
| # irrelevant changes without running source proof. | |
| name: Release source proof | |
| needs: | |
| - changes | |
| - release-source-proof | |
| if: ${{ always() }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Report path-gated result | |
| env: | |
| CHANGES_RESULT: ${{ needs.changes.result }} | |
| REQUIRED: ${{ needs.changes.outputs.release_source_proof }} | |
| RESULT: ${{ needs.release-source-proof.result }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| case "${CHANGES_RESULT}:${REQUIRED}:${RESULT}" in | |
| success:true:success|success:false:skipped) | |
| ;; | |
| *) | |
| echo "Release source proof path gate did not complete safely: changes=${CHANGES_RESULT} required=${REQUIRED} result=${RESULT}" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| registryctl-tutorials: | |
| name: registryctl tutorials from source | |
| needs: changes | |
| if: needs.changes.outputs.registryctl_tutorial == 'true' | |
| runs-on: ubuntu-24.04 | |
| timeout-minutes: 60 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Assert amd64 runner | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| [[ "$(uname -m)" == "x86_64" ]] | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e | |
| with: | |
| node-version: 22.12.0 | |
| cache: npm | |
| cache-dependency-path: docs/site/package-lock.json | |
| - name: Install docs dependencies | |
| working-directory: docs/site | |
| run: npm ci | |
| - name: Test registryctl tutorial helpers | |
| working-directory: docs/site | |
| run: npm run test:tutorial:registryctl | |
| - name: Check tutorial command counts | |
| working-directory: docs/site | |
| run: npm run check:tutorial:dry-run | |
| - name: Restore source-under-test Cargo build | |
| id: tutorial-cache | |
| uses: actions/cache/restore@2c8a9bd7457de244a408f35966fab2fb45fda9c8 | |
| with: | |
| path: | | |
| target/registryctl-tutorial-source | |
| key: registryctl-tutorial-ci-${{ runner.os }}-${{ hashFiles('docs/site/scripts/check-registryctl-tutorials.sh', 'Cargo.lock', 'Cargo.toml') }} | |
| restore-keys: | | |
| registryctl-tutorial-ci-${{ runner.os }}- | |
| registryctl-tutorial-${{ runner.os }}- | |
| - name: Execute registryctl tutorials from source | |
| working-directory: docs/site | |
| run: npm run check:tutorial:registryctl | |
| - name: Save source-under-test Cargo build | |
| if: github.ref == 'refs/heads/main' && steps.tutorial-cache.outputs.cache-hit != 'true' | |
| uses: actions/cache/save@2c8a9bd7457de244a408f35966fab2fb45fda9c8 | |
| with: | |
| path: | | |
| target/registryctl-tutorial-source | |
| key: ${{ steps.tutorial-cache.outputs.cache-primary-key }} | |
| - name: Report tutorial disk usage | |
| if: always() | |
| run: | | |
| df -h / | |
| du -sh \ | |
| target/registryctl-tutorial-source \ | |
| 2>/dev/null || true | |
| docs: | |
| name: Docs checks | |
| needs: changes | |
| if: needs.changes.outputs.docs == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e | |
| with: | |
| node-version: 22.12.0 | |
| cache: npm | |
| cache-dependency-path: docs/site/package-lock.json | |
| - name: Install docs shell dependency | |
| run: | | |
| sudo apt-get update | |
| sudo apt-get install --yes zsh | |
| - name: Assert docs shell dependencies | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| command -v sh | |
| command -v bash | |
| command -v zsh | |
| - name: Install docs dependencies | |
| working-directory: docs/site | |
| run: npm ci | |
| - name: Fetch pinned OpenAPI inputs | |
| working-directory: docs/site | |
| run: node scripts/fetch-openapi.mjs | |
| - name: Test docs scripts | |
| working-directory: docs/site | |
| run: npm test | |
| - name: Check docs build | |
| working-directory: docs/site | |
| run: npm run check | |
| docs-required: | |
| # Branch protection requires this exact context. Keep it successful for | |
| # irrelevant changes without installing or building the docs site. | |
| name: Docs | |
| needs: | |
| - changes | |
| - docs | |
| - docs-archives | |
| if: ${{ always() }} | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Report path-gated result | |
| env: | |
| CHANGES_RESULT: ${{ needs.changes.result }} | |
| REQUIRED: ${{ needs.changes.outputs.docs }} | |
| RESULT: ${{ needs.docs.result }} | |
| ARCHIVES_REQUIRED: ${{ needs.changes.outputs.docs_archives }} | |
| ARCHIVES_RESULT: ${{ needs.docs-archives.result }} | |
| shell: bash | |
| run: | | |
| set -euo pipefail | |
| case "${CHANGES_RESULT}:${REQUIRED}:${RESULT}" in | |
| success:true:success|success:false:skipped) | |
| ;; | |
| *) | |
| echo "Docs path gate did not complete safely: changes=${CHANGES_RESULT} required=${REQUIRED} result=${RESULT}" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| case "${CHANGES_RESULT}:${ARCHIVES_REQUIRED}:${ARCHIVES_RESULT}" in | |
| success:true:success|success:false:skipped) | |
| ;; | |
| *) | |
| echo "Docs archive path gate did not complete safely: changes=${CHANGES_RESULT} required=${ARCHIVES_REQUIRED} result=${ARCHIVES_RESULT}" >&2 | |
| exit 1 | |
| ;; | |
| esac | |
| docs-archives: | |
| name: Immutable docs archives | |
| needs: changes | |
| if: needs.changes.outputs.docs_archives == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e | |
| with: | |
| node-version: 22.12.0 | |
| cache: npm | |
| cache-dependency-path: docs/site/package-lock.json | |
| - name: Install docs dependencies | |
| working-directory: docs/site | |
| run: npm ci | |
| - name: Reject changes to locked archive digests | |
| working-directory: docs/site | |
| env: | |
| ARCHIVE_LOCK_BASE_REF: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || github.event.before || 'origin/main' }} | |
| run: npm run check:archive-lock -- --base-ref "${ARCHIVE_LOCK_BASE_REF}" | |
| - name: Assemble and verify every archived release | |
| working-directory: docs/site | |
| run: npm run check:archives | |
| editor-extensions: | |
| name: Editor extensions | |
| needs: changes | |
| if: needs.changes.outputs.editors == 'true' | |
| runs-on: ubuntu-24.04 | |
| steps: | |
| - name: Checkout | |
| uses: actions/checkout@9c091bb21b7c1c1d1991bb908d89e4e9dddfe3e0 | |
| with: | |
| fetch-depth: 0 | |
| submodules: false | |
| - name: Setup Node | |
| uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e | |
| with: | |
| node-version: 22.12.0 | |
| cache: npm | |
| cache-dependency-path: editors/vscode/package-lock.json | |
| - name: Test editor installer | |
| run: bash editors/tests/install_test.sh | |
| - name: Package and test VS Code integration | |
| working-directory: editors/vscode | |
| run: | | |
| npm ci | |
| npm run package:dev | |
| cargo build --locked -p registry-language-server | |
| xvfb-run -a npm test | |
| cmp ../../LICENSE LICENSE | |
| - name: Install Zed extension target | |
| run: rustup target add wasm32-wasip2 | |
| - name: Check Zed extension | |
| run: | | |
| cargo check --locked --target wasm32-wasip2 --manifest-path editors/zed/Cargo.toml | |
| cmp LICENSE editors/zed/LICENSE | |
| ci-result: | |
| name: CI result | |
| if: always() | |
| needs: | |
| - changes | |
| - secrets | |
| - platform-quality | |
| - platform-coverage | |
| - platform-hygiene | |
| - platform-fuzz | |
| - rust-result | |
| - project-authoring-determinism | |
| - release-tool | |
| - release-source-proof | |
| - registryctl-tutorials | |
| - docs | |
| - editor-extensions | |
| runs-on: ubuntu-24.04 | |
| env: | |
| CI_JOB_RESULTS: ${{ toJSON(needs) }} | |
| steps: | |
| - name: Require every selected CI job | |
| run: | | |
| python3 - <<'PY' | |
| import json | |
| import os | |
| import sys | |
| jobs = json.loads(os.environ["CI_JOB_RESULTS"]) | |
| failed = { | |
| name: details["result"] | |
| for name, details in jobs.items() | |
| if details["result"] not in {"success", "skipped"} | |
| } | |
| if failed: | |
| print(f"CI jobs did not pass: {failed}", file=sys.stderr) | |
| raise SystemExit(1) | |
| print("Every selected CI job passed; unselected jobs were skipped.") | |
| PY |