From 453c283e3adaf4555e3df9a2b1a71296658f3a3c Mon Sep 17 00:00:00 2001 From: Weiwei Zheng Date: Tue, 11 Aug 2026 23:22:19 -0700 Subject: [PATCH] Parallelize CI validation Signed-off-by: Weiwei Zheng --- .github/workflows/ci.yml | 78 ++++++++++++++++++--------------- .github/workflows/docs-sync.yml | 48 ++++++++++++++++++++ .github/workflows/static.yml | 47 -------------------- CONTRIBUTING.md | 2 +- 4 files changed, 92 insertions(+), 83 deletions(-) create mode 100644 .github/workflows/docs-sync.yml delete mode 100644 .github/workflows/static.yml diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 251d7118..8474da85 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -8,16 +8,10 @@ on: pull_request: branches: - main - # Include label events so the docs-sync 'no-docs-needed' escape hatch takes - # effect immediately — the default pull_request activity types omit - # 'labeled'/'unlabeled', so a label added after a failing run would otherwise - # never re-trigger CI. types: - opened - synchronize - reopened - - labeled - - unlabeled push: branches: - main @@ -146,17 +140,6 @@ jobs: PR_BASE_REF: ${{ github.base_ref }} run: buf breaking --against ".git#ref=origin/${PR_BASE_REF}" - # Documentation stays in sync with the public surface: a change to the CRD - # API types (api/v1alpha1/*_types.go) or the gRPC contract (proto/) must - # also update the docs (site/ or docs/) in the same PR. Reuses the base ref - # fetched above. Waived when the PR carries the 'no-docs-needed' label. - # See CONTRIBUTING.md "Documentation stays in sync". - - name: Verify docs updated for public-surface changes - if: github.event_name == 'pull_request' && !contains(github.event.pull_request.labels.*.name, 'no-docs-needed') - env: - PR_BASE_REF: ${{ github.base_ref }} - run: make verify-docs-sync DOCS_SYNC_BASE="origin/${PR_BASE_REF}" - - name: Lint run: | make lint @@ -198,12 +181,11 @@ jobs: python3 -m pip install --quiet -r pkg/fingerprint/testdata/requirements.txt make verify-golden-vectors - test: - name: Test + race-test: + name: Race Tests runs-on: ubuntu-latest permissions: contents: read - id-token: write steps: - name: Checkout uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 @@ -215,10 +197,8 @@ jobs: cache: true # Fetch envtest binaries (apiserver + etcd + kubectl) so the controller - # integration tests (internal/controller/integration_test.go) run against - # a real apiserver instead of skipping AND so the "Verify samples" step - # below has the envtest apiserver + the kubectl that `make verify-samples` - # shells out to. The test skip guard checks $KUBEBUILDER_ASSETS, so + # integration tests run against a real apiserver instead of skipping. The + # test skip guard checks $KUBEBUILDER_ASSETS, so # exporting it via $GITHUB_ENV is enough to flip them on. # The script fails fast if the path is empty or missing, so a `make test-env` # failure can't silently skip the integration suite and let CI go green. @@ -235,6 +215,34 @@ jobs: - name: Test (race detector) run: make test-race + coverage: + name: Coverage + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Setup Go + uses: actions/setup-go@4a3601121dd01d1626a1e23e37211e3254c1c06c # v6 + with: + go-version-file: go.mod + cache: true + + # Coverage includes the envtest integration suites, and sample admission + # below reuses the same apiserver binaries. + - name: Install envtest binaries + run: | + set -euo pipefail + path="$(make test-env | tail -1)" + if [ -z "$path" ] || [ ! -d "$path" ]; then + echo "make test-env did not produce a valid envtest path: '$path'" >&2 + exit 1 + fi + echo "KUBEBUILDER_ASSETS=$path" >> "$GITHUB_ENV" + - name: Coverage gate run: make cover-check @@ -389,17 +397,19 @@ jobs: run: make tokenize-cgo-test lint-test-proto: - name: Lint, Test, Proto + name: CI Gate runs-on: ubuntu-latest needs: - dco - lint-generated-proto - - test + - race-test + - coverage - fingerprint-e2e - vulnerability-scan - build - sbom-smoke - tokenize-cgo + - image-build if: always() permissions: contents: read @@ -408,23 +418,27 @@ jobs: env: LINT_GENERATED_PROTO_RESULT: ${{ needs.lint-generated-proto.result }} DCO_RESULT: ${{ needs.dco.result }} - TEST_RESULT: ${{ needs.test.result }} + RACE_TEST_RESULT: ${{ needs.race-test.result }} + COVERAGE_RESULT: ${{ needs.coverage.result }} FINGERPRINT_E2E_RESULT: ${{ needs.fingerprint-e2e.result }} VULNERABILITY_SCAN_RESULT: ${{ needs.vulnerability-scan.result }} BUILD_RESULT: ${{ needs.build.result }} SBOM_SMOKE_RESULT: ${{ needs.sbom-smoke.result }} TOKENIZE_CGO_RESULT: ${{ needs.tokenize-cgo.result }} + IMAGE_BUILD_RESULT: ${{ needs.image-build.result }} run: | failed=0 for item in \ "dco:$DCO_RESULT" \ "lint-generated-proto:$LINT_GENERATED_PROTO_RESULT" \ - "test:$TEST_RESULT" \ + "race-test:$RACE_TEST_RESULT" \ + "coverage:$COVERAGE_RESULT" \ "fingerprint-e2e:$FINGERPRINT_E2E_RESULT" \ "vulnerability-scan:$VULNERABILITY_SCAN_RESULT" \ "build:$BUILD_RESULT" \ "sbom-smoke:$SBOM_SMOKE_RESULT" \ - "tokenize-cgo:$TOKENIZE_CGO_RESULT"; do + "tokenize-cgo:$TOKENIZE_CGO_RESULT" \ + "image-build:$IMAGE_BUILD_RESULT"; do name="${item%%:*}" result="${item#*:}" if [ "$result" != "success" ]; then @@ -439,12 +453,6 @@ jobs: image-build: name: Image Build runs-on: ubuntu-latest - needs: - - lint-generated-proto - - test - - fingerprint-e2e - - vulnerability-scan - - build permissions: contents: read # Required for Trivy SARIF upload to the Security tab. diff --git a/.github/workflows/docs-sync.yml b/.github/workflows/docs-sync.yml new file mode 100644 index 00000000..4b62072d --- /dev/null +++ b/.github/workflows/docs-sync.yml @@ -0,0 +1,48 @@ +# SPDX-FileCopyrightText: 2026 The inference-cache Authors +# +# SPDX-License-Identifier: Apache-2.0 + +name: Docs Sync + +# Keep the public API documentation gate responsive to the no-docs-needed +# waiver without restarting the full CI suite for every label change. +on: + pull_request: + branches: + - main + types: + - opened + - synchronize + - reopened + - labeled + - unlabeled + +permissions: + contents: read + +concurrency: + group: docs-sync-${{ github.ref }} + cancel-in-progress: true + +jobs: + docs-sync: + name: Docs Sync + runs-on: ubuntu-latest + steps: + - name: Checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6 + + - name: Fetch pull request base + env: + PR_BASE_REF: ${{ github.base_ref }} + run: git fetch --no-tags origin "+refs/heads/${PR_BASE_REF}:refs/remotes/origin/${PR_BASE_REF}" + + - name: Verify docs updated for public-surface changes + if: ${{ !contains(github.event.pull_request.labels.*.name, 'no-docs-needed') }} + env: + PR_BASE_REF: ${{ github.base_ref }} + run: make verify-docs-sync DOCS_SYNC_BASE="origin/${PR_BASE_REF}" + + - name: Record docs-sync waiver + if: ${{ contains(github.event.pull_request.labels.*.name, 'no-docs-needed') }} + run: echo "Docs-sync waived by the no-docs-needed label." diff --git a/.github/workflows/static.yml b/.github/workflows/static.yml deleted file mode 100644 index 7eda8552..00000000 --- a/.github/workflows/static.yml +++ /dev/null @@ -1,47 +0,0 @@ -# SPDX-FileCopyrightText: 2026 The inference-cache Authors -# -# SPDX-License-Identifier: Apache-2.0 - -# Simple workflow for deploying static content to GitHub Pages -name: Deploy static content to Pages - -on: - # Runs on pushes targeting the default branch - push: - branches: ["main"] - - # Allows you to run this workflow manually from the Actions tab - workflow_dispatch: - -# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages -permissions: - contents: read - pages: write - id-token: write - -# Allow only one concurrent deployment, skipping runs queued between the run in-progress and latest queued. -# However, do NOT cancel in-progress runs as we want to allow these production deployments to complete. -concurrency: - group: "pages" - cancel-in-progress: false - -jobs: - # Single deploy job since we're just deploying - deploy: - environment: - name: github-pages - url: ${{ steps.deployment.outputs.page_url }} - runs-on: ubuntu-latest - steps: - - name: Checkout - uses: actions/checkout@v4 - - name: Setup Pages - uses: actions/configure-pages@v5 - - name: Upload artifact - uses: actions/upload-pages-artifact@v3 - with: - # Upload entire repository - path: '.' - - name: Deploy to GitHub Pages - id: deployment - uses: actions/deploy-pages@v5 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 17cfcd1a..5ff9b90f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -251,4 +251,4 @@ The public surfaces have user-facing documentation, and it must not drift behind make verify-docs-sync # checks the current branch's diff vs origin/main; also runs in CI on every PR ``` -CI runs this check on each pull request (as part of the **Lint, Generated Code, Proto** job). If a public-surface change genuinely needs no doc update, add the **`no-docs-needed`** label to the PR to waive it. +CI runs this check on each pull request as the lightweight **Docs Sync** job. Label changes rerun only that job, so adding or removing the **`no-docs-needed`** waiver does not restart the full CI suite.