Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -558,6 +558,12 @@
"mlflow",
"observability"
]
},
{
"name": "k8s-rebase",
"source": "./plugins/k8s-rebase",
"description": "Automate Kubernetes dependency rebases for Go projects that consume k8s.io/* packages. Scans go.mod, derives version bumps, runs codegen, updates version references, and guides agent-driven fixups with antagonistic review.",
"version": "0.3.0"
}
]
}
3 changes: 3 additions & 0 deletions .skillsaw.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ rules:
- "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/notify.sh '✅ Claude Code' 'Claude finished your task'"
- "${CLAUDE_PLUGIN_ROOT}/scripts/ensure-precommit.sh"
- "${CLAUDE_PLUGIN_ROOT}/hooks/stop-hook.sh"
- "${CLAUDE_PLUGIN_ROOT}/hooks/block-module-ops.sh"
- "${CLAUDE_PLUGIN_ROOT}/hooks/block-push.sh"
- "${CLAUDE_PLUGIN_ROOT}/hooks/block-vendor-edit.sh"
- "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/start-collector.sh"
- "bash ${CLAUDE_PLUGIN_ROOT}/hooks/scripts/stop-collector.sh"
settings-dangerous:
Expand Down
35 changes: 35 additions & 0 deletions docs/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -1732,6 +1732,41 @@ <h1>ai-helpers</h1>
"name": "github.com/openshift-eng"
}
},
{
"name": "k8s-rebase",
"description": "Automate Kubernetes dependency rebases for Go projects that consume k8s.io/* packages. Scans go.mod, derives version bumps, runs codegen, updates version references, and guides agent-driven fixups with antagonistic review.",
"version": "0.3.0",
"has_readme": true,
"commands": [],
"skills": [
{
"name": "k8s-rebase",
"description": "Rebase a Go project to a new Kubernetes version by bumping all k8s.io/* dependencies, running codegen, updating version references, fixing build breakage with antagonistic review, and presenting a gh pr create command.",
"description_html": "Rebase a Go project to a new Kubernetes version by bumping all k8s.io/* dependencies, running codegen, updating version references, fixing build breakage with antagonistic review, and presenting a gh pr create command.",
"meta": "Tools: Bash, Read, Agent"
}
],
"agents": [],
"hooks": [
{
"event_type": "PreToolUse",
"matcher": "Bash",
"hooks_json": "[\n {\n \"command\": \"${CLAUDE_PLUGIN_ROOT}/hooks/block-module-ops.sh\",\n \"type\": \"command\"\n },\n {\n \"command\": \"${CLAUDE_PLUGIN_ROOT}/hooks/block-push.sh\",\n \"type\": \"command\"\n }\n]"
},
{
"event_type": "PreToolUse",
"matcher": "Edit|Write",
"hooks_json": "[\n {\n \"command\": \"${CLAUDE_PLUGIN_ROOT}/hooks/block-vendor-edit.sh\",\n \"type\": \"command\"\n }\n]"
},
{
"event_type": "Stop",
"matcher": ".*",
"hooks_json": "[\n {\n \"command\": \"${CLAUDE_PLUGIN_ROOT}/hooks/stop-hook.sh\",\n \"type\": \"command\"\n }\n]"
}
],
"mcp_servers": [],
"rules": []
},
{
"name": "marketplace-ops",
"description": "Maintenance commands for Claude Code plugin marketplaces",
Expand Down
8 changes: 8 additions & 0 deletions plugins/k8s-rebase/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"name": "k8s-rebase",
"description": "Automate Kubernetes dependency rebases for Go projects that consume k8s.io/* packages. Scans go.mod, derives version bumps, runs codegen, updates version references, and guides agent-driven fixups with antagonistic review.",
"version": "0.3.0",
"author": {
"name": "github.com/openshift-eng"
}
}
111 changes: 111 additions & 0 deletions plugins/k8s-rebase/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
.DEFAULT_GOAL := help
.PHONY: help matrix test watch results court set-known-good set-from-commit stop clean

SCRIPT := test/test-skill.sh
SPEC ?= $(if $(spec),$(spec),none)
REPO ?= $(repo)
REF ?= $(ref)
URL ?= $(url)
COMMIT ?= $(commit)
JOBS ?= $(jobs)
VER ?= $(version)
REPOS ?= $(repos_dir)
CONFIG ?= test/config$(if $(VER),-$(shell echo $(VER) | grep -oE '[0-9]+\.[0-9]+'),).yaml

help: ## Show available targets
@echo ""
@echo " k8s-rebase skill testing"
@echo " ────────────────────────"
@echo " Tests the k8s-rebase skill by running it against real repos, then"
@echo " comparing the output to a known-good human-verified rebase."
@echo " Gates = 33 pass/fail checks (build, vet, lint, correctness, ...)."
@echo " Court = AI adversarial review that compares output to known-good, votes pass/fail."
@echo " Requires: claude CLI, yq, jq, git, rsync. ~20 min per repo."
@echo ""
@echo " Quick start:"
@echo " make test repo=ovn-kubernetes/ovn-kubernetes-mcp"
@echo " make watch # monitor progress"
@echo " make court repo=ovn-kubernetes/ovn-kubernetes-mcp"
@echo " make results repo=ovn-kubernetes/ovn-kubernetes-mcp"
@echo ""
@echo " Full pipeline (all versions, all repos, court, retries):"
@echo " make matrix # 4-8 hours unattended"
@echo ""
@echo " Workflow: test → watch → court → results"
@echo ""
@echo " Test (launches skill in background, auto-clones repos on first run)"
@echo " make test Run all repos, wait for completion"
@echo " make test repo=<repo> Run one repo"
@echo " make test spec=all Blind test — no patterns doc or autofix"
@echo " make test version=1.35 Backtest against an older k8s version"
@echo " spec: none (default), all (blind), fn:<tag>, pattern:<key>"
@echo " versions: $(shell ls test/config-*.yaml 2>/dev/null | sed 's|test/config-||;s|\.yaml||' | tr '\n' ' ')"
@echo " repos:"; yq '.repos | keys | .[]' test/config.yaml 2>/dev/null | while read -r r; do echo " $$r"; done
@echo ""
@echo " Monitor (check progress while tests run)"
@echo " make watch Show session state, gate count, diff vs known-good"
@echo " watch -n 10 make watch Auto-refresh every 10s"
@echo ""
@echo " Review (run after gates pass — compares output to known-good rebase)"
@echo " make court Run court for all pending repos (all versions)"
@echo " make court repo=<repo> AI review one repo (add version=X.Y for specific version)"
@echo ""
@echo " Results"
@echo " make results Show all versions (or one with version=X)"
@echo " make results repo=<repo> Show gate reports, diff vs known-good, history"
@echo ""
@echo " Manage"
@echo " make stop Stop all running test sessions"
@echo " make clean Reset worktrees, state, temp branches (keeps clones)"
@echo ""
@echo " Config"
@echo " make set-known-good repo=<repo> ref=<sha> Set known-good to a SHA on main"
@echo " make set-known-good repo=<repo> ref=<branch> url=<u> Set known-good to a branch on a fork"
@echo " make set-from-commit repo=<repo> commit=<sha> Set pre-rebase starting commit"
@echo " repos_dir=/path make test Override repo checkout location (default: test/.repos/)"
@echo ""

matrix: ## Full pipeline: all versions x all repos, court, retries (4-8 hours)
@$(if $(JOBS),MAX_CONCURRENT=$(JOBS)) $(if $(REPOS),REPOS_DIR=$(REPOS)) bash $(SCRIPT) matrix $(if $(spec),$(SPEC),all)

test: ## Run tests
@if [ -n "$(REPO)" ]; then \
$(if $(JOBS),MAX_CONCURRENT=$(JOBS)) $(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) test $(SPEC) $(REPO) $(if $(COMMIT),--from-commit $(COMMIT)); \
else \
$(if $(JOBS),MAX_CONCURRENT=$(JOBS)) $(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) test-all $(SPEC); \
fi

watch: ## Show active test status
@$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) watch

results: ## Show results
@if [ -z "$(VER)" ] && [ -z "$(REPO)" ]; then \
$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) results --all-versions; \
else \
$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) results $(REPO); \
fi

court: ## Adversarial court review
@if [ -n "$(REPO)" ]; then \
$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) results $(REPO) --court; \
elif [ -z "$(VER)" ]; then \
$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) court-all --all-versions; \
else \
$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) court-all; \
fi

set-known-good: ## Set known-good reference
@test -n "$(REPO)" || (echo "ERROR: repo required" && exit 1)
@test -n "$(REF)" || (echo "ERROR: ref required" && exit 1)
@$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) set-known-good $(REPO) $(REF) $(if $(URL),--url $(URL))

set-from-commit: ## Set pre-merge commit
@test -n "$(REPO)" || (echo "ERROR: repo required" && exit 1)
@test -n "$(COMMIT)" || (echo "ERROR: commit required" && exit 1)
@$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) set-from-commit $(REPO) $(COMMIT)

stop: ## Stop all sessions
@$(if $(REPOS),REPOS_DIR=$(REPOS)) CONFIG_FILE=$(CONFIG) bash $(SCRIPT) stop --all || true

clean: ## Reset everything
@$(if $(REPOS),REPOS_DIR=$(REPOS)) bash $(SCRIPT) clean
4 changes: 4 additions & 0 deletions plugins/k8s-rebase/OWNERS
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
approvers:
- dfarrell07
reviewers:
- dfarrell07
86 changes: 86 additions & 0 deletions plugins/k8s-rebase/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
# k8s-rebase

Automate Kubernetes dependency rebases for Go projects that consume
`k8s.io/*` packages.

## Usage

```text
/k8s-rebase:k8s-rebase <version>
/k8s-rebase:k8s-rebase --bump-tools <version>
```

Run from the root of any Go repo with `k8s.io/*` dependencies.
Example: `/k8s-rebase:k8s-rebase 1.36.0`

The skill creates a branch with separate commits for each step:
dependency bumps, codegen, version references, and code fixes.
No files need to be installed in the target repo — everything
runs from the plugin.

### --bump-tools

Adds non-k8s version bumps on top of the core rebase. Mixing
tooling bumps into a k8s rebase PR is not ideal (harder to
review, harder to bisect), but some communities bundle them.
ovn-kubernetes-mcp in particular expects all versions to be
current when a rebase PR lands. The flag exists to match that
workflow without polluting the default path.

Script (deterministic):
- Syncs `GINKGO_VERSION` in Makefile from go.mod
- Bumps `NODE_VERSION`, `NPM_VERSION` to latest Node.js release
- Bumps `NVM_VERSION` to latest release

Agent (Step 4d, judgment-based):
- Bumps outdated non-k8s direct Go deps one at a time, checking
that k8s pins survived each bump (reverts if MVS drifted them)
- Re-syncs `GINKGO_VERSION` in Makefile if ginkgo was bumped

All tool bump changes go in separate commits from the k8s
rebase so the rebase is cleanly bisectable.

## What it does

1. Bumps all `k8s.io/*` dependencies across every Go module
2. Runs codegen and mock regeneration
3. Updates version references in CI, scripts, and docs
4. Detects new feature gates that break fake clientsets
5. Fixes build/lint/vet errors with code-first priority
6. Validates all modules and verifies fixes via antagonistic review

## Prerequisites

- Go (any version — auto-containerizes if local Go is too old)
- `podman` (preferred) or `docker`
- `git`

## Contents

| File | Purpose |
|------|---------|
| `skills/k8s-rebase/SKILL.md` | Skill entry point and boot loader |
| `skills/k8s-rebase/steps/*.md` | Step definitions and shared rules (6 files) |
| `scripts/k8s-rebase-orchestrator.sh` | Step/gate state machine |
| `scripts/k8s-rebase.sh` | Mechanical rebase (deps, codegen, version refs) |
| `scripts/k8s-rebase-autofix.sh` | Applies known fix patterns with PASS/FAIL verification |
| `scripts/k8s-rebase-validate.sh` | Build/lint/vet/test across all modules |
| `scripts/k8s-rebase-review.sh` | Antagonistic review via `claude -p` |
| `scripts/gate-script-lib.sh` | Shared library for gate companion scripts |
| `scripts/write-gate-report.sh` | Structured gate pass/fail report writer |
| `gates/step{1,2,3,4}-*/*.md` | Subagent verification prompts (33 files) |
| `docs/k8s-rebase-patterns.md` | Breakage patterns for k8s rebases |

## Tested against

| Repo | Modules | Features exercised |
|------|---------|--------------------|
| ovn-org/ovn-kubernetes | 3 | Codegen, vendor, conformance tests, feature gates |
| openshift/multus-cni | 1 | Vendor, Eventf vet errors, gate insertion |
| openshift/api | 1 | Vendor, codegen field removal, golangci-lint format |
| metallb/frr-k8s | 2 | No vendor, codegen, 3-version jump, transitive deps |
| kubernetes-sigs/network-policy-api | 2 | No vendor, codegen, multi-module |
| ovn-kubernetes/ovn-kubernetes-mcp | 1 | Vendor, no test-go.sh |
| openshift/ingress-node-firewall | 1 | Vendor, 4-version jump, staging deps, controller-gen, golangci-lint v1/v2 |
| openshift/cloud-network-config-controller | 1 | Vendor, library-go blocker |
| openshift/cluster-network-operator | 1 | Vendor, library-go blocker |
Loading