From d4e78e6b52b5e6e1c3c0539f278cde67fd39d57c Mon Sep 17 00:00:00 2001 From: Cursor Agent Date: Wed, 16 Sep 2026 22:14:00 +0000 Subject: [PATCH] Stop Dependabot from reopening breaking CI-red updates Group update-types do not block ungrouped majors or Go minors, so ginkgo 2.32, Spring Boot 4, and kubernetes 36 still opened and failed operator/local-regression. Ignore those classes, freeze rebases, and keep the operator builder image on the go.mod Go version. Co-authored-by: jmjava --- .github/dependabot.yml | 47 +++++++++++++++++++-- .github/workflows/operator.yml | 20 +++++++++ scripts/check-ci-policy.py | 76 ++++++++++++++++++++++++++++++++++ scripts/run-regression.sh | 4 ++ 4 files changed, 144 insertions(+), 3 deletions(-) create mode 100755 scripts/check-ci-policy.py diff --git a/.github/dependabot.yml b/.github/dependabot.yml index fa16814..bfffe3f 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -1,126 +1,167 @@ +# Group update-types only control what is batched. Ungrouped majors (and +# gomod minors) still open individual PRs unless ignore: "*" is set. version: 2 updates: - package-ecosystem: github-actions directory: / schedule: interval: weekly + rebase-strategy: disabled groups: github-actions: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: gomod directory: /operator schedule: interval: weekly + rebase-strategy: disabled groups: operator-go: patterns: ["*"] update-types: - patch ignore: - - dependency-name: "k8s.io/*" - update-types: ["version-update:semver-major", "version-update:semver-minor"] - - dependency-name: "sigs.k8s.io/controller-runtime" + - dependency-name: "*" update-types: ["version-update:semver-major", "version-update:semver-minor"] - package-ecosystem: npm directory: /management-gui/frontend schedule: interval: weekly + rebase-strategy: disabled groups: management-frontend: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: npm directory: /libs/baggage-node schedule: interval: weekly + rebase-strategy: disabled groups: baggage-node: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: pip directory: /orchestrator schedule: interval: weekly + rebase-strategy: disabled groups: orchestrator-python: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: pip directory: /management-gui/backend schedule: interval: weekly + rebase-strategy: disabled groups: management-backend-python: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: pip directory: /libs/tekton-dag-common schedule: interval: weekly + rebase-strategy: disabled groups: common-python: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: pip directory: /libs/baggage-python schedule: interval: weekly + rebase-strategy: disabled groups: baggage-python: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: maven directory: /libs/baggage-spring-boot-starter schedule: interval: weekly + rebase-strategy: disabled groups: baggage-spring: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: maven directory: /libs/baggage-servlet-filter schedule: interval: weekly + rebase-strategy: disabled groups: baggage-servlet: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] - package-ecosystem: composer directory: /libs/baggage-php schedule: interval: weekly + rebase-strategy: disabled groups: baggage-php: patterns: ["*"] update-types: - minor - patch + ignore: + - dependency-name: "*" + update-types: ["version-update:semver-major"] diff --git a/.github/workflows/operator.yml b/.github/workflows/operator.yml index 67579e6..8f4a86b 100644 --- a/.github/workflows/operator.yml +++ b/.github/workflows/operator.yml @@ -39,6 +39,26 @@ jobs: go-version-file: operator/go.mod cache-dependency-path: operator/go.sum + - name: Builder Go matches go.mod + working-directory: ${{ github.workspace }} + run: | + set -euo pipefail + python3 - <<'PY' + import re + from pathlib import Path + dockerfile = Path("operator/Dockerfile").read_text() + gomod = Path("operator/go.mod").read_text() + image = re.search(r"FROM docker.io/golang:([0-9]+\.[0-9]+)", dockerfile) + module = re.search(r"^go ([0-9]+\.[0-9]+)", gomod, re.M) + if not image or not module: + raise SystemExit("could not parse operator Dockerfile / go.mod Go versions") + if image.group(1) != module.group(1): + raise SystemExit( + f"operator Dockerfile golang:{image.group(1)} != go.mod {module.group(1)}" + ) + print(f"operator builder Go {image.group(1)} matches go.mod") + PY + - name: Check formatting run: test -z "$(gofmt -l .)" diff --git a/scripts/check-ci-policy.py b/scripts/check-ci-policy.py new file mode 100755 index 0000000..021751c --- /dev/null +++ b/scripts/check-ci-policy.py @@ -0,0 +1,76 @@ +#!/usr/bin/env python3 +"""Fail if Dependabot can still open breaking updates, or operator Go pins drift.""" + +from __future__ import annotations + +import re +import sys +from pathlib import Path + +import yaml + +ROOT = Path(__file__).resolve().parents[1] +MAJOR = "version-update:semver-major" +MINOR = "version-update:semver-minor" + + +def _fail(message: str) -> None: + print(message, file=sys.stderr) + raise SystemExit(1) + + +def check_dependabot() -> None: + config = yaml.safe_load((ROOT / ".github/dependabot.yml").read_text()) + for entry in config["updates"]: + eco = entry["package-ecosystem"] + loc = f"{eco}:{entry.get('directory', '/')}" + if entry.get("rebase-strategy") != "disabled": + _fail(f"{loc} must set rebase-strategy: disabled") + + groups = entry.get("groups") or {} + if not groups: + _fail(f"{loc} must group updates") + for name, group in groups.items(): + types = set(group.get("update-types") or []) + if "major" in types: + _fail(f"{name} must not auto-open majors") + if not types <= {"minor", "patch"}: + _fail(f"{name} has unexpected update-types: {types}") + if eco == "gomod" and types != {"patch"}: + _fail(f"{name} must be patch-only") + + ignore_types: set[str] = set() + for rule in entry.get("ignore") or []: + if rule.get("dependency-name") == "*": + ignore_types.update(rule.get("update-types") or []) + if MAJOR not in ignore_types: + _fail(f"{loc} must ignore * semver-major (groups do not block ungrouped majors)") + if eco == "gomod" and MINOR not in ignore_types: + _fail(f"{loc} must ignore * semver-minor (ginkgo/gomega minors bump Go)") + + +def check_operator_go_pin() -> None: + dockerfile = (ROOT / "operator/Dockerfile").read_text() + gomod = (ROOT / "operator/go.mod").read_text() + workflow = (ROOT / ".github/workflows/operator.yml").read_text() + + image = re.search(r"FROM docker.io/golang:([0-9]+\.[0-9]+)", dockerfile) + module = re.search(r"^go ([0-9]+\.[0-9]+)", gomod, re.M) + if not image or not module: + _fail("could not parse operator Dockerfile / go.mod Go versions") + if image.group(1) != module.group(1): + _fail( + f"operator Dockerfile golang:{image.group(1)} != go.mod {module.group(1)}" + ) + if "Builder Go matches go.mod" not in workflow: + _fail("operator workflow must check Dockerfile Go against go.mod") + + +def main() -> None: + check_dependabot() + check_operator_go_pin() + print("CI policy checks passed") + + +if __name__ == "__main__": + main() diff --git a/scripts/run-regression.sh b/scripts/run-regression.sh index 9673951..d63a307 100755 --- a/scripts/run-regression.sh +++ b/scripts/run-regression.sh @@ -121,6 +121,10 @@ if ! python3 -c "import pytest" 2>/dev/null; then exit 1 fi +echo "" +echo ">>> CI policy: Dependabot ignores + operator Go pin — scripts/check-ci-policy.py" +python3 "$SCRIPT_DIR/check-ci-policy.py" + echo "" echo ">>> Phase 1: DAG verification (no cluster) — scripts/verify-dag-phase1.sh" ensure_mikefarah_yq