From cf3eedf5f209f2c2514f548915954e1c5bf9f590 Mon Sep 17 00:00:00 2001 From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Date: Wed, 24 Dec 2025 11:58:01 +0000 Subject: [PATCH 1/6] Add a Makefile target and start running the API diff linter as part of CI. --- .github/workflows/api-diff-lint.yaml | 44 +++++++++++++++++++++++++ Makefile | 4 +++ hack/api-lint-diff/run.sh | 49 +++++++++++++++++++++++++++- 3 files changed, 96 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/api-diff-lint.yaml diff --git a/.github/workflows/api-diff-lint.yaml b/.github/workflows/api-diff-lint.yaml new file mode 100644 index 000000000..0636243e1 --- /dev/null +++ b/.github/workflows/api-diff-lint.yaml @@ -0,0 +1,44 @@ +name: api-diff-lint + +on: + workflow_dispatch: + pull_request: + merge_group: + push: + branches: + - main + +jobs: + lint-api-diff: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + with: + fetch-depth: 0 # Fetch all history for all branches (needed for API diff) + + - uses: actions/setup-go@v6 + with: + go-version-file: "go.mod" + + - name: Run API diff linting checks + id: lint-api-diff + continue-on-error: true + run: make lint-api-diff + + - name: Check for override label + if: ${{ steps.lint-api-diff.outcome == 'failure' }} + run: | + if gh api repos/$OWNER/$REPO/pulls/$PR --jq '.labels[].name' | grep -q "${OVERRIDE_LABEL}"; then + echo "Found ${OVERRIDE_LABEL} label, overriding failed results." + exit 0 + else + echo "No ${OVERRIDE_LABEL} label found, failing the job." + exit 1 + fi + env: + GH_TOKEN: ${{ github.token }} + OWNER: ${{ github.repository_owner }} + REPO: ${{ github.event.repository.name }} + PR: ${{ github.event.pull_request.number }} + OVERRIDE_LABEL: "api-diff-lint-override" + diff --git a/Makefile b/Makefile index f84bafb90..9b887d4ff 100644 --- a/Makefile +++ b/Makefile @@ -149,6 +149,10 @@ custom-linter-build: #EXHELP Build custom linter lint-custom: custom-linter-build #EXHELP Call custom linter for the project go vet -tags=$(GO_BUILD_TAGS) -vettool=./bin/custom-linter ./... +.PHONY: lint-api-diff +lint-api-diff: $(GOLANGCI_LINT) #HELP Validate API changes using kube-api-linter with diff-aware analysis + bash hack/api-lint-diff/run.sh + .PHONY: k8s-pin k8s-pin: #EXHELP Pin k8s staging modules based on k8s.io/kubernetes version (in go.mod or from K8S_IO_K8S_VERSION env var) and run go mod tidy. K8S_IO_K8S_VERSION='$(K8S_IO_K8S_VERSION)' go run hack/tools/k8smaintainer/main.go diff --git a/hack/api-lint-diff/run.sh b/hack/api-lint-diff/run.sh index 993ec9052..a5e08eb9b 100755 --- a/hack/api-lint-diff/run.sh +++ b/hack/api-lint-diff/run.sh @@ -196,7 +196,36 @@ check_linter_support() { # Find golangci-lint binary find_golangci_lint() { - # Check for custom build first + # Check if Variables.mk exists and extract golangci-lint path + if [[ -f ".bingo/Variables.mk" ]]; then + # Extract version from GOLANGCI_LINT variable + # Format: GOLANGCI_LINT := $(GOBIN)/golangci-lint-v2.7.2 + local version + version=$(grep '^GOLANGCI_LINT' .bingo/Variables.mk | sed -E 's/.*golangci-lint-(v[0-9]+\.[0-9]+\.[0-9]+).*/\1/') + + if [[ -n "${version}" ]]; then + # Use go env to get the actual GOBIN/GOPATH + local gobin + gobin=$(go env GOBIN) + + # If GOBIN is empty, use GOPATH/bin + if [[ -z "${gobin}" ]]; then + local gopath + gopath=$(go env GOPATH) + # Take first entry if GOPATH has multiple paths (colon-separated) + gobin="${gopath%%:*}/bin" + fi + + # Check if the versioned binary exists + local bingo_path="${gobin}/golangci-lint-${version}" + if [[ -f "${bingo_path}" ]]; then + echo "${bingo_path}" + return 0 + fi + fi + fi + + # Check for custom build if [[ -f ".bingo/golangci-lint" ]]; then echo ".bingo/golangci-lint" return 0 @@ -216,6 +245,7 @@ find_golangci_lint() { echo -e "${RED}Error: golangci-lint not found.${NC}" >&2 echo -e "${RED}Searched for:${NC}" >&2 + echo -e " - .bingo/Variables.mk (bingo-managed versioned binary)" >&2 echo -e " - .bingo/golangci-lint" >&2 echo -e " - bin/golangci-lint" >&2 echo -e " - golangci-lint on your \$PATH" >&2 @@ -482,6 +512,23 @@ main() { # Create temporary config create_temp_config + # Ensure baseline branch is available (important for CI environments like GitHub Actions) + if ! git rev-parse --verify "${BASELINE_BRANCH}" &> /dev/null; then + echo -e "${YELLOW}Baseline branch '${BASELINE_BRANCH}' not found locally. Fetching from origin...${NC}" >&2 + + # Fetch the baseline branch from origin + if ! git fetch origin "${BASELINE_BRANCH}:${BASELINE_BRANCH}" 2>&1; then + # If direct fetch fails, try fetching with remote tracking + if ! git fetch origin "${BASELINE_BRANCH}" 2>&1; then + echo -e "${RED}Error: Failed to fetch baseline branch '${BASELINE_BRANCH}' from origin${NC}" >&2 + echo -e "${RED}Please ensure the branch exists in the remote repository.${NC}" >&2 + exit 1 + fi + # Use the remote tracking branch + BASELINE_BRANCH="origin/${BASELINE_BRANCH}" + fi + fi + # Get changed files get_changed_files > "${TEMP_DIR}/changed_files.txt" From 336ef3b283e8467cf85a24232ac68c7e499bb5e4 Mon Sep 17 00:00:00 2001 From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Date: Thu, 8 Jan 2026 19:38:47 +0000 Subject: [PATCH 2/6] Update hack/api-lint-diff/run.sh Co-authored-by: Todd Short --- hack/api-lint-diff/run.sh | 32 ++++++-------------------------- 1 file changed, 6 insertions(+), 26 deletions(-) diff --git a/hack/api-lint-diff/run.sh b/hack/api-lint-diff/run.sh index a5e08eb9b..dd6193f50 100755 --- a/hack/api-lint-diff/run.sh +++ b/hack/api-lint-diff/run.sh @@ -196,32 +196,12 @@ check_linter_support() { # Find golangci-lint binary find_golangci_lint() { - # Check if Variables.mk exists and extract golangci-lint path - if [[ -f ".bingo/Variables.mk" ]]; then - # Extract version from GOLANGCI_LINT variable - # Format: GOLANGCI_LINT := $(GOBIN)/golangci-lint-v2.7.2 - local version - version=$(grep '^GOLANGCI_LINT' .bingo/Variables.mk | sed -E 's/.*golangci-lint-(v[0-9]+\.[0-9]+\.[0-9]+).*/\1/') - - if [[ -n "${version}" ]]; then - # Use go env to get the actual GOBIN/GOPATH - local gobin - gobin=$(go env GOBIN) - - # If GOBIN is empty, use GOPATH/bin - if [[ -z "${gobin}" ]]; then - local gopath - gopath=$(go env GOPATH) - # Take first entry if GOPATH has multiple paths (colon-separated) - gobin="${gopath%%:*}/bin" - fi - - # Check if the versioned binary exists - local bingo_path="${gobin}/golangci-lint-${version}" - if [[ -f "${bingo_path}" ]]; then - echo "${bingo_path}" - return 0 - fi + # Check if variables.env exists and extract golangci-lint path + if [[ -f ".bingo/variables.env" ]]; then + source .bingo/variables.env + if [[ -n "${GOLANGCI_LINT}" && -f "${GOLANGCI_LINT}" ]]; then + echo "${GOLANGCI_LINT}" + return 0 fi fi From 965cee93b1bc0b6b2507402313fd5a09cd2c44f2 Mon Sep 17 00:00:00 2001 From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:17:17 +0000 Subject: [PATCH 3/6] Run for pull requests only --- .github/workflows/api-diff-lint.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/.github/workflows/api-diff-lint.yaml b/.github/workflows/api-diff-lint.yaml index 0636243e1..07aa901a2 100644 --- a/.github/workflows/api-diff-lint.yaml +++ b/.github/workflows/api-diff-lint.yaml @@ -1,12 +1,7 @@ name: api-diff-lint on: - workflow_dispatch: pull_request: - merge_group: - push: - branches: - - main jobs: lint-api-diff: From 9221fe2a38a574e5b43b24401ade48f41f1450db Mon Sep 17 00:00:00 2001 From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:34:17 +0000 Subject: [PATCH 4/6] Update .github/workflows/api-diff-lint.yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/api-diff-lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/api-diff-lint.yaml b/.github/workflows/api-diff-lint.yaml index 07aa901a2..5d05e8215 100644 --- a/.github/workflows/api-diff-lint.yaml +++ b/.github/workflows/api-diff-lint.yaml @@ -23,7 +23,7 @@ jobs: - name: Check for override label if: ${{ steps.lint-api-diff.outcome == 'failure' }} run: | - if gh api repos/$OWNER/$REPO/pulls/$PR --jq '.labels[].name' | grep -q "${OVERRIDE_LABEL}"; then + if gh api repos/$OWNER/$REPO/pulls/$PR --jq '.labels.[].name' | grep -q "${OVERRIDE_LABEL}"; then echo "Found ${OVERRIDE_LABEL} label, overriding failed results." exit 0 else From 9b3ef7b6c1d365305a3e4b471a2805944d52c755 Mon Sep 17 00:00:00 2001 From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:34:26 +0000 Subject: [PATCH 5/6] Update .github/workflows/api-diff-lint.yaml Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .github/workflows/api-diff-lint.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/api-diff-lint.yaml b/.github/workflows/api-diff-lint.yaml index 5d05e8215..f301df40e 100644 --- a/.github/workflows/api-diff-lint.yaml +++ b/.github/workflows/api-diff-lint.yaml @@ -13,7 +13,7 @@ jobs: - uses: actions/setup-go@v6 with: - go-version-file: "go.mod" + go-version-file: go.mod - name: Run API diff linting checks id: lint-api-diff From 2c6d7691280ea542077a60ff4b4f9546bcf8f762 Mon Sep 17 00:00:00 2001 From: Camila Macedo <7708031+camilamacedo86@users.noreply.github.com> Date: Thu, 8 Jan 2026 23:35:17 +0000 Subject: [PATCH 6/6] Update hack/api-lint-diff/run.sh Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- hack/api-lint-diff/run.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hack/api-lint-diff/run.sh b/hack/api-lint-diff/run.sh index dd6193f50..8932d77e3 100755 --- a/hack/api-lint-diff/run.sh +++ b/hack/api-lint-diff/run.sh @@ -225,7 +225,7 @@ find_golangci_lint() { echo -e "${RED}Error: golangci-lint not found.${NC}" >&2 echo -e "${RED}Searched for:${NC}" >&2 - echo -e " - .bingo/Variables.mk (bingo-managed versioned binary)" >&2 + echo -e " - .bingo/variables.env (bingo-managed variables for GOLANGCI_LINT)" >&2 echo -e " - .bingo/golangci-lint" >&2 echo -e " - bin/golangci-lint" >&2 echo -e " - golangci-lint on your \$PATH" >&2