From 3f2b9a18cc06c73cb55556661cf0d523e18efb2a Mon Sep 17 00:00:00 2001 From: timflannagan Date: Fri, 9 Oct 2026 16:42:09 -0400 Subject: [PATCH 1/3] ci: Separate verification from unit tests Run repository verification and unit tests as independent parallel jobs so cheap formatting, code generation, and license failures report promptly. Keep run-tests as an aggregate job over both results to preserve the existing required status check without a ruleset migration. Signed-off-by: timflannagan --- .github/workflows/pr-workflow.yaml | 48 ++++++++++++++++++++++-------- 1 file changed, 35 insertions(+), 13 deletions(-) diff --git a/.github/workflows/pr-workflow.yaml b/.github/workflows/pr-workflow.yaml index 199c874c60..f1e8c47a12 100644 --- a/.github/workflows/pr-workflow.yaml +++ b/.github/workflows/pr-workflow.yaml @@ -33,7 +33,7 @@ concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: - run-tests: + unit-tests: runs-on: ubuntu-latest # A bound well clear of the observed runtime. Without one the platform # default applies, and a wedged step burns a free-tier slot for six hours. @@ -51,10 +51,6 @@ jobs: uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 with: go-version-file: 'go.mod' - # Unconditional: a released migration becoming permanent is exactly what - # this guards, and that happens on the push to main, not on the PR. - - name: Verify immutable PostgreSQL migrations - run: hack/verify/postgresql-migrations.sh # we only test on amd64, make sure everything still builds for arm64 - name: build for arm64 run: GOOS=linux GOARCH=arm64 CGO_ENABLED=0 go build ./... @@ -76,13 +72,6 @@ jobs: run: ../../../hack/run-tool.sh gotestsum --junitfile "${ARTIFACTS}/gcp-secret-manager.xml" --jsonfile "${ARTIFACTS}/gcp-secret-manager.json" --format standard-verbose -- -race -v ./... - # The root verifiers stop at the module's go.mod, so it gets its own run: - # gofmt, go vet and the tidy check, then golangci-lint with the root config. - - name: gcp-secret-manager credential provider verify - working-directory: internal/plugins/gcp-secret-manager - run: | - make verify - ../../../hack/run-tool.sh golangci-lint run --config ../../../.golangci.yaml ./... - name: Cache cargo uses: actions/cache@0057852bfaa89a56745cba8c7296529d2fc39830 # v4.3.0 with: @@ -119,8 +108,41 @@ jobs: name: test-results-unit path: ${{ env.ARTIFACTS }} if-no-files-found: error - - name: verify + verify: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + with: + fetch-depth: 0 + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version-file: 'go.mod' + - name: Verify run: hack/verify-all.sh + # The root verifiers stop at the module's go.mod, so it gets its own run: + # gofmt, go vet and the tidy check, then golangci-lint with the root config. + - name: gcp-secret-manager credential provider verify + working-directory: internal/plugins/gcp-secret-manager + run: | + make verify + ../../../hack/run-tool.sh golangci-lint run --config ../../../.golangci.yaml ./... + # Preserve the required-check name while unit tests and verification run in + # parallel as separate jobs. + run-tests: + needs: [unit-tests, verify] + if: always() + runs-on: ubuntu-latest + steps: + - name: Require unit tests and verification + env: + UNIT_TESTS_RESULT: ${{ needs.unit-tests.result }} + VERIFY_RESULT: ${{ needs.verify.result }} + run: | + test "${UNIT_TESTS_RESULT}" = success + test "${VERIFY_RESULT}" = success # One kind cluster exercises BOTH runtimes. Free x86-64 ubuntu-latest runners # expose /dev/kvm (with a udev rule), so create-kind-cluster.sh mounts it and the # micro-VM (kata + cloud-hypervisor) sandbox class works alongside gVisor. From 7f09a596a9def2e9ff7762e9fe3cbd9e56ba22a5 Mon Sep 17 00:00:00 2001 From: timflannagan Date: Fri, 9 Oct 2026 16:48:12 -0400 Subject: [PATCH 2/3] ci: Separate lint from verification Give linting its own Make-backed CI job so it runs in parallel with unit tests and non-lint verification. Keep the comprehensive make verify command by composing the focused lint and verification targets. Include all root and plugin linters behind make lint, and keep the required run-tests aggregate responsible for every validation result. Signed-off-by: timflannagan --- .github/workflows/pr-workflow.yaml | 29 ++++++++++++-------- Makefile | 15 +++++++--- hack/verify-all.sh | 13 +++++++++ internal/plugins/gcp-secret-manager/Makefile | 4 +++ 4 files changed, 46 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pr-workflow.yaml b/.github/workflows/pr-workflow.yaml index f1e8c47a12..d7d4d661ab 100644 --- a/.github/workflows/pr-workflow.yaml +++ b/.github/workflows/pr-workflow.yaml @@ -121,18 +121,23 @@ jobs: with: go-version-file: 'go.mod' - name: Verify - run: hack/verify-all.sh - # The root verifiers stop at the module's go.mod, so it gets its own run: - # gofmt, go vet and the tidy check, then golangci-lint with the root config. - - name: gcp-secret-manager credential provider verify - working-directory: internal/plugins/gcp-secret-manager - run: | - make verify - ../../../hack/run-tool.sh golangci-lint run --config ../../../.golangci.yaml ./... - # Preserve the required-check name while unit tests and verification run in - # parallel as separate jobs. + run: make verify-checks + lint: + runs-on: ubuntu-latest + timeout-minutes: 30 + steps: + - name: Checkout + uses: actions/checkout@fbc6f3992d24b796d5a048ff273f7fcc4a7b6c09 # v5.1.0 + - name: Setup Go + uses: actions/setup-go@40f1582b2485089dde7abd97c1529aa768e1baff # v5.6.0 + with: + go-version-file: 'go.mod' + - name: Lint + run: make lint + # Preserve the required-check name while unit tests, verification and linting + # run in parallel as separate jobs. run-tests: - needs: [unit-tests, verify] + needs: [unit-tests, verify, lint] if: always() runs-on: ubuntu-latest steps: @@ -140,9 +145,11 @@ jobs: env: UNIT_TESTS_RESULT: ${{ needs.unit-tests.result }} VERIFY_RESULT: ${{ needs.verify.result }} + LINT_RESULT: ${{ needs.lint.result }} run: | test "${UNIT_TESTS_RESULT}" = success test "${VERIFY_RESULT}" = success + test "${LINT_RESULT}" = success # One kind cluster exercises BOTH runtimes. Free x86-64 ubuntu-latest runners # expose /dev/kvm (with a udev rule), so create-kind-cluster.sh mounts it and the # micro-VM (kata + cloud-hypervisor) sandbox class works alongside gVisor. diff --git a/Makefile b/Makefile index f01760e765..217d6d30e6 100644 --- a/Makefile +++ b/Makefile @@ -172,13 +172,20 @@ verify-fmt: .PHONY: lint -# Runs golangci-lint and fails on any reported issues. +# Runs all linters and fails on any reported issues. lint: @./hack/verify/golangci-lint.sh + @./hack/verify/kube-api-linter.sh + @$(MAKE) -C internal/plugins/gcp-secret-manager lint -.PHONY: verify -verify: test - bash hack/verify-all.sh +.PHONY: verify verify-checks + +# Runs non-lint repository checks. +verify-checks: + bash hack/verify-all.sh --skip-lint + @$(MAKE) -C internal/plugins/gcp-secret-manager verify + +verify: test lint verify-checks .PHONY: clean clean: diff --git a/hack/verify-all.sh b/hack/verify-all.sh index 247000462b..0805953903 100755 --- a/hack/verify-all.sh +++ b/hack/verify-all.sh @@ -21,8 +21,21 @@ cd "${ROOT}" export LC_ALL=C # for sorting to be consistent across locales +SKIP_LINT=false +if [[ "${1:-}" == "--skip-lint" ]]; then + SKIP_LINT=true + shift +fi + # shellcheck disable=2044 # for-loop over find output is intentional for F in $(find ./hack/verify -name '*.sh' | sort); do + if [[ "${SKIP_LINT}" == true ]]; then + case "${F}" in + ./hack/verify/golangci-lint.sh | ./hack/verify/kube-api-linter.sh) + continue + ;; + esac + fi echo "Running ${F}" "${F}" "$@" done diff --git a/internal/plugins/gcp-secret-manager/Makefile b/internal/plugins/gcp-secret-manager/Makefile index b769489cc9..69235b25ea 100644 --- a/internal/plugins/gcp-secret-manager/Makefile +++ b/internal/plugins/gcp-secret-manager/Makefile @@ -35,6 +35,10 @@ test: fmt: $(GOFMT) -w . +.PHONY: lint +lint: + ../../../hack/run-tool.sh golangci-lint run --config ../../../.golangci.yaml ./... + .PHONY: verify verify: @out="$$($(GOFMT) -l .)"; if [ -n "$$out" ]; then echo "gofmt needed on:"; echo "$$out"; exit 1; fi From 3022ad48381f1b15ef73843643c6410a0139a636 Mon Sep 17 00:00:00 2001 From: timflannagan Date: Fri, 9 Oct 2026 16:50:56 -0400 Subject: [PATCH 3/3] ci: Clarify lint and verification scopes Classify formatting and static analysis as linting instead of repository verification. This puts gofmt, proto formatting, ShellCheck, go vet, and the Go linters behind the standalone lint target. Keep verification focused on generated artifacts, module state, licenses, migrations, metrics, and other repository invariants. Signed-off-by: timflannagan --- Makefile | 3 +++ hack/verify-all.sh | 6 +++++- internal/plugins/gcp-secret-manager/Makefile | 4 ++-- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/Makefile b/Makefile index 217d6d30e6..576ea70e47 100644 --- a/Makefile +++ b/Makefile @@ -174,8 +174,11 @@ verify-fmt: # Runs all linters and fails on any reported issues. lint: + @./hack/verify/gofmt.sh @./hack/verify/golangci-lint.sh @./hack/verify/kube-api-linter.sh + @./hack/verify/proto-fmt.sh + @./hack/verify/shellcheck.sh @$(MAKE) -C internal/plugins/gcp-secret-manager lint .PHONY: verify verify-checks diff --git a/hack/verify-all.sh b/hack/verify-all.sh index 0805953903..27823985ac 100755 --- a/hack/verify-all.sh +++ b/hack/verify-all.sh @@ -31,7 +31,11 @@ fi for F in $(find ./hack/verify -name '*.sh' | sort); do if [[ "${SKIP_LINT}" == true ]]; then case "${F}" in - ./hack/verify/golangci-lint.sh | ./hack/verify/kube-api-linter.sh) + ./hack/verify/gofmt.sh | \ + ./hack/verify/golangci-lint.sh | \ + ./hack/verify/kube-api-linter.sh | \ + ./hack/verify/proto-fmt.sh | \ + ./hack/verify/shellcheck.sh) continue ;; esac diff --git a/internal/plugins/gcp-secret-manager/Makefile b/internal/plugins/gcp-secret-manager/Makefile index 69235b25ea..75cf06ff74 100644 --- a/internal/plugins/gcp-secret-manager/Makefile +++ b/internal/plugins/gcp-secret-manager/Makefile @@ -37,12 +37,12 @@ fmt: .PHONY: lint lint: + @out="$$($(GOFMT) -l .)"; if [ -n "$$out" ]; then echo "gofmt needed on:"; echo "$$out"; exit 1; fi + go vet ./... ../../../hack/run-tool.sh golangci-lint run --config ../../../.golangci.yaml ./... .PHONY: verify verify: - @out="$$($(GOFMT) -l .)"; if [ -n "$$out" ]; then echo "gofmt needed on:"; echo "$$out"; exit 1; fi - go vet ./... go mod tidy -diff # Builds the image and applies the manifests to the current kubectl context.