diff --git a/.github/workflows/api-diff-lint.yaml b/.github/workflows/api-diff-lint.yaml new file mode 100644 index 000000000..f301df40e --- /dev/null +++ b/.github/workflows/api-diff-lint.yaml @@ -0,0 +1,39 @@ +name: api-diff-lint + +on: + pull_request: + +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..8932d77e3 100755 --- a/hack/api-lint-diff/run.sh +++ b/hack/api-lint-diff/run.sh @@ -196,7 +196,16 @@ check_linter_support() { # Find golangci-lint binary find_golangci_lint() { - # Check for custom build first + # 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 + + # Check for custom build if [[ -f ".bingo/golangci-lint" ]]; then echo ".bingo/golangci-lint" return 0 @@ -216,6 +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.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 @@ -482,6 +492,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"