From 2e1e12231da92ea7cbf9cd532b948974e8e092e9 Mon Sep 17 00:00:00 2001 From: Martin Gencur Date: Thu, 18 Jun 2026 15:08:07 +0200 Subject: [PATCH] ci: add top-level directory drift detection Add a verification script and tracked directory list that ensures the CI skip pattern (pipeline_skip_if_only_changed) stays in sync when new top-level directories are added to the repo. The check runs as part of `make verify-parallel`. - hack/ci/toplevel-dirs.txt: canonical list of top-level dirs - hack/ci/verify-toplevel-dirs.sh: diffs actual vs tracked dirs - Makefile: wire verify-toplevel-dirs into verify-parallel Co-Authored-By: Claude Opus 4.6 --- Makefile | 6 +++++- hack/ci/toplevel-dirs.txt | 34 +++++++++++++++++++++++++++++++++ hack/ci/verify-toplevel-dirs.sh | 34 +++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 hack/ci/toplevel-dirs.txt create mode 100755 hack/ci/verify-toplevel-dirs.sh diff --git a/Makefile b/Makefile index 939ffcd68220..2e6f79c35c46 100644 --- a/Makefile +++ b/Makefile @@ -144,7 +144,7 @@ verify-codecov: ## Validate codecov.yml against Codecov's API. | tee /dev/stderr | grep -q "^Valid!" .PHONY: verify-parallel -verify-parallel: verify-codespell verify-codecov verify-api-deps lint cpo-container-sync run-gitlint verify-docs-nav +verify-parallel: verify-codespell verify-codecov verify-api-deps lint cpo-container-sync run-gitlint verify-docs-nav verify-toplevel-dirs .PHONY: verify verify: generate update staticcheck fmt vet @@ -607,6 +607,10 @@ verify-codespell: codespell ## Verify codespell. verify-api-deps: $(VERIFY_API_DEPS) ## Verify API dependencies against allowlist. @$(VERIFY_API_DEPS) +.PHONY: verify-toplevel-dirs +verify-toplevel-dirs: ## Verify top-level directory list is in sync with hack/ci/toplevel-dirs.txt. + @bash hack/ci/verify-toplevel-dirs.sh + .PHONY: run-gitlint run-gitlint: $(GITLINT) ifdef PULL_BASE_SHA diff --git a/hack/ci/toplevel-dirs.txt b/hack/ci/toplevel-dirs.txt new file mode 100644 index 000000000000..90a2f242fd72 --- /dev/null +++ b/hack/ci/toplevel-dirs.txt @@ -0,0 +1,34 @@ +api +availability-prober +client +cmd +contrib +control-plane-operator +control-plane-pki-operator +dnsresolver +docs +etcd-backup +etcd-defrag +etcd-recovery +etcd-upload +examples +hack +hypershift-ci-python +hypershift-operator +ignition-server +karpenter-operator +kas-bootstrap +konnectivity-https-proxy +konnectivity-socks5-proxy +kubernetes-default-proxy +kubevirtexternalinfra +pkg +product-cli +shared-ingress +sharedingress-config-generator +support +sync-fg-configmap +sync-global-pullsecret +test +token-minter +vendor diff --git a/hack/ci/verify-toplevel-dirs.sh b/hack/ci/verify-toplevel-dirs.sh new file mode 100755 index 000000000000..e4bd97479a39 --- /dev/null +++ b/hack/ci/verify-toplevel-dirs.sh @@ -0,0 +1,34 @@ +#!/usr/bin/env bash +# Verifies that the tracked top-level directory list stays in sync with +# the actual git-tracked directories. This prevents the CI skip pattern +# (pipeline_skip_if_only_changed) from silently going stale when new +# top-level directories are added to the repo. +# Directories containing E2E tests directly or indirectly (e.g. test/) +# must be excluded from the regex. +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +TRACKED="${SCRIPT_DIR}/toplevel-dirs.txt" + +# Collect top-level directories from both committed (HEAD) and staged +# (index) state, excluding hidden dirs. In CI the PR is already merged +# into HEAD; the ls-files fallback catches locally staged-but-uncommitted +# directories during local `make verify`. +ACTUAL=$( (git ls-tree -d --name-only HEAD 2>/dev/null; \ + git ls-files --cached | grep '/' | cut -d/ -f1) \ + | grep -v '^\.' | sort -u) +EXPECTED=$(sort "${TRACKED}") + +DIFF=$(diff <(echo "${EXPECTED}") <(echo "${ACTUAL}") || true) + +if [[ -n "${DIFF}" ]]; then + echo "ERROR: Top-level directory list is out of sync." + echo "" + echo "Diff (expected vs actual):" + echo "${DIFF}" + echo "" + echo "If you added or removed a top-level directory, update hack/ci/toplevel-dirs.txt." + echo "Also update the pipeline_skip_if_only_changed regex in the ci-operator config." + echo "Top-level directories containing E2E tests directly or indirectly (e.g. test/) must be excluded from the regex." + exit 1 +fi