/k8s-profile — detect a repo's build profile
Target: $ARGUMENTS (a repo directory; a sibling of the workspace root)
Workspace state
cd "${CLAUDE_PROJECT_DIR:-$PWD}" && for d in */; do [ -d "$d.git" ] && echo " ${d%/}"; done; echo "(directories above are git clones in the workspace root)"
Already-cached profiles:
ls -1 "${CLAUDE_PLUGIN_DATA}"/profiles/*.json 2>/dev/null | xargs -n1 basename 2>/dev/null || echo "(none yet)"
Run it
${CLAUDE_PLUGIN_ROOT}/scripts/detect-profile.sh <repo-dir> --write --data "${CLAUDE_PLUGIN_DATA}"
--write caches to ${CLAUDE_PLUGIN_DATA}/profiles/<repo>.json — the
cross-run cache, which survives plugin updates.
- Always pass
--data "${CLAUDE_PLUGIN_DATA}". That variable is
substituted into this skill's text, but it is not present in the
environment of a plain Bash tool call, so the script cannot find it itself.
- The cache is keyed on a hash of the inputs it read (Makefile, go.mod,
.go-version, golangci config, .prow.yaml, OWNERS, CONTRIBUTING, and the
hack/ and .github/workflows/ listings). Re-running is a no-op until one
of those changes.
--force regenerates regardless.
What it derives, and from what
Never hard-code a repo's commands. Detection order:
- Makefile — real targets, parsed from rule lines. It handles multi-target
rules (
check test: is how kubernetes defines test), and skips
.PHONY, variables, and pattern rules.
hack/ — verify-*.sh, update-*.sh, install-etcd.sh,
local-up-cluster.sh, ginkgo-e2e.sh, update-codegen.sh.
go.mod / .go-version / golangci config — module path, Go version.
.github/workflows/, .prow.yaml, OWNERS, OWNERS_ALIASES,
SECURITY_CONTACTS — CI system, reviewers, SIG label.
- Test layout —
test/integration, test/e2e, test/e2e_node, pkg,
cmd, staging, and the PR/issue templates.
- Frameworks — envtest, kind, ginkgo, and which assertion library the
repo's own
_test.go files actually use most. The fix must use that one.
Hazards
The profile records hazards[] for targets that are unsafe under this
workspace's rules, and routes the gate commands around them.
Worked example: in gwctl, make build, make test, and make verify all
depend on a deps target that runs go mod tidy && go mod vendor. Running
them rewrites go.mod/go.sum/vendor/, which guard-deps.sh blocks. The
detector notices, flags all three, and emits the plain go build ./... /
go test -race -count=1 ./... equivalents instead.
Check hazards before trusting any make invocation in a repo you have not
profiled.
Low confidence
When the signals are too thin, the profile records
"confidence": "low" (or "medium") with a confidence_reason.
Do not guess past it. Read the reason, then ask the user one targeted
question — the specific command you could not derive — rather than inventing
a command that will fail ten minutes into a gate.
Worked example: kube-openapi has no Makefile at all, so it comes back
medium with "no Makefile: commands fall back to the plain go toolchain".
That fallback is correct there, and the note tells you it was a fallback rather
than a detected target.
Reading the result
jq '{confidence, confidence_reason, commands, requires, hazards, assertion_library}' \
${CLAUDE_PLUGIN_DATA}/profiles/<repo>.json
Fields the rest of the system relies on: commands.* (gate commands),
requires.etcd|kind|envtest, assertion_library, pr_template,
owners_reviewers, sig_label, uses_prow, sensitive_paths,
gate_runtime_estimate_s (so the verifier can warn before a 40-minute run),
and gate_sets_by_change_class.
1---2name: k8s-profile3description: Detect and cache the build/test/verify profile for a Kubernetes-ecosystem repo clone - real Makefile targets, test tiers, etcd and kind requirements, assertion library, OWNERS, SIG, PR template, generated-code refresh command, and per-gate runtime estimates. Use before running any gate against a repo, or when build commands are unknown or look wrong.4---56# /k8s-profile — detect a repo's build profile78Target: **$ARGUMENTS** (a repo directory; a sibling of the workspace root)910## Workspace state1112```!13cd "${CLAUDE_PROJECT_DIR:-$PWD}" && for d in */; do [ -d "$d.git" ] && echo " ${d%/}"; done; echo "(directories above are git clones in the workspace root)"14```1516Already-cached profiles:1718```!19ls -1 "${CLAUDE_PLUGIN_DATA}"/profiles/*.json 2>/dev/null | xargs -n1 basename 2>/dev/null || echo "(none yet)"20```2122## Run it2324```bash25${CLAUDE_PLUGIN_ROOT}/scripts/detect-profile.sh <repo-dir> --write --data "${CLAUDE_PLUGIN_DATA}"26```2728- `--write` caches to `${CLAUDE_PLUGIN_DATA}/profiles/<repo>.json` — the29 cross-run cache, which survives plugin updates.30- **Always pass `--data "${CLAUDE_PLUGIN_DATA}"`.** That variable is31 substituted into this skill's text, but it is *not* present in the32 environment of a plain Bash tool call, so the script cannot find it itself.33- The cache is keyed on a hash of the inputs it read (Makefile, go.mod,34 `.go-version`, golangci config, `.prow.yaml`, OWNERS, CONTRIBUTING, and the35 `hack/` and `.github/workflows/` listings). Re-running is a no-op until one36 of those changes.37- `--force` regenerates regardless.3839## What it derives, and from what4041Never hard-code a repo's commands. Detection order:42431. **Makefile** — real targets, parsed from rule lines. It handles multi-target44 rules (`check test:` is how `kubernetes` defines `test`), and skips45 `.PHONY`, variables, and pattern rules.462. **`hack/`** — `verify-*.sh`, `update-*.sh`, `install-etcd.sh`,47 `local-up-cluster.sh`, `ginkgo-e2e.sh`, `update-codegen.sh`.483. **`go.mod` / `.go-version` / golangci config** — module path, Go version.494. **`.github/workflows/`, `.prow.yaml`, `OWNERS`, `OWNERS_ALIASES`,50 `SECURITY_CONTACTS`** — CI system, reviewers, SIG label.515. **Test layout** — `test/integration`, `test/e2e`, `test/e2e_node`, `pkg`,52 `cmd`, `staging`, and the PR/issue templates.536. **Frameworks** — envtest, kind, ginkgo, and **which assertion library the54 repo's own `_test.go` files actually use most**. The fix must use that one.5556## Hazards5758The profile records `hazards[]` for targets that are unsafe under this59workspace's rules, and routes the gate commands around them.6061Worked example: in `gwctl`, `make build`, `make test`, and `make verify` all62depend on a `deps` target that runs `go mod tidy && go mod vendor`. Running63them rewrites `go.mod`/`go.sum`/`vendor/`, which `guard-deps.sh` blocks. The64detector notices, flags all three, and emits the plain `go build ./...` /65`go test -race -count=1 ./...` equivalents instead.6667Check `hazards` before trusting any `make` invocation in a repo you have not68profiled.6970## Low confidence7172When the signals are too thin, the profile records73`"confidence": "low"` (or `"medium"`) with a `confidence_reason`.7475**Do not guess past it.** Read the reason, then ask the user **one targeted76question** — the specific command you could not derive — rather than inventing77a command that will fail ten minutes into a gate.7879Worked example: `kube-openapi` has no Makefile at all, so it comes back80`medium` with *"no Makefile: commands fall back to the plain go toolchain"*.81That fallback is correct there, and the note tells you it was a fallback rather82than a detected target.8384## Reading the result8586```bash87jq '{confidence, confidence_reason, commands, requires, hazards, assertion_library}' \88 ${CLAUDE_PLUGIN_DATA}/profiles/<repo>.json89```9091Fields the rest of the system relies on: `commands.*` (gate commands),92`requires.etcd|kind|envtest`, `assertion_library`, `pr_template`,93`owners_reviewers`, `sig_label`, `uses_prow`, `sensitive_paths`,94`gate_runtime_estimate_s` (so the verifier can warn before a 40-minute run),95and `gate_sets_by_change_class`.