Run a grouped, bisectable Go dependency security sweep on the Fission repo. Use when the user asks to upgrade outdated/vulnerable Go dependencies, run a dep security pass, or process CVE findings from govulncheck. Produces one commit per logical dependency group on a dedicated branch so failures are attributable and revertable.
Playbook for upgrading outdated Go dependencies as a security sweep. Optimized for isolating failures: each logical group of related dependencies lands as a separate commit so git bisect can attribute any regression to one group, then one dep within it.
Trigger phrases: "upgrade outdated Go deps", "security sweep on go.mod", "run govulncheck and fix what's found", "bump dependencies for security".
Skip if the user asks for a single, named dep bump — that's just go get <pkg>@<ver> + tidy + lint + commit, no grouping needed.
git checkout -b deps/security-sweep-<YYYY-MM> off main.go install golang.org/x/vuln/cmd/govulncheck@latest.govulncheck ./... | tee /tmp/govulncheck-before.txt. Extract the "Your code is affected by N vulnerabilities" line and the per-vuln "Fixed in:" versions — those dictate minimum target versions.go list -m -u -json all filtered to entries with both "Update" and no "Indirect": true. Use this Python one-liner:
go list -m -u -json all 2>/dev/null | python3 -c "
import json, sys
buf=''; mods=[]
for line in sys.stdin:
buf += line
if line.rstrip()=='}':
try: mods.append(json.loads(buf)); buf=''
except: pass
for m in mods:
if not m.get('Indirect') and m.get('Update'):
print(f\"{m['Path']:<70} {m['Version']:<20} -> {m['Update']['Version']}\")
"
Bucket the outdated deps into these groups (in order — lowest risk first):
k8s.io/api, k8s.io/apimachinery, k8s.io/client-go, k8s.io/apiextensions-apiserver, k8s.io/metrics. All must move to the same patch/minor. Typically lowest risk when it's a patch bump.sigs.k8s.io/controller-runtime, sigs.k8s.io/structured-merge-diff/v*, sigs.k8s.io/yaml. controller-runtime minors may break admission-webhook consumers (see pitfall below).go.opentelemetry.io/otel/* and go.opentelemetry.io/contrib/*. Must bump together — otel core and contrib use linked version lines (v1.X / v0.Y where Y = X+39-ish). otel/sdk carries CVEs historically.google.golang.org/grpc, golang.org/x/net. Commonly paired in CVE fixes. Often pulled up transitively by the otel bump — check before bumping explicitly.github.com/IBM/sarama, github.com/kedacore/keda/v2. KEDA has repeatedly shipped broken go.mod declarations for consumers — see pitfall.minio-go, go-git, influxdb, go-snaps, fatih/color, etc. Leave for last; low blast radius.If a dep in a group carries a CVE that the baseline scan flagged, keep that group's order but note it in the commit message.
For each group, on the branch:
go get <pkg1>@<version1> <pkg2>@<version2> ... # all deps in the group in one command
go mod tidy
go build ./pkg/... ./cmd/... # NOT ./... — see pitfall about test fixtures
make code-checks # golangci-lint via Makefile
If build + lint both pass, commit:
Bump <group name> (<pkg@ver>, <pkg@ver>)
<One-line rationale. If this group closes a GO-YYYY-NNNN vuln from the baseline scan, name it.>
If the group fails, bisect within the group: drop one dep at a time from the go get command, re-run tidy+build+lint. Pin back the offender and commit the rest. Do NOT skip the commit for the group entirely — a partial group is still progress.
git diff main -- go.mod | head -80 — sanity-check the direct-deps diff matches the groups.make check — full local gate (lint + envtest + CLI build). See pitfall about Docker-required tests.govulncheck ./... | tee /tmp/govulncheck-after.txt and compare against the baseline. Include "CVEs closed" in the PR description.require pinsgithub.com/kedacore/keda/v2 ships go.mod files that declare require k8s.io/client-go v1.5.2 and require sigs.k8s.io/controller-runtime v0.23.x but internally replaces them to sane versions (v0.3x.x and v0.22.x). Replace directives are not transitive. Consumers inherit the bogus require and MVS picks the ancient (v1.5.2) or wrong-minor version, breaking the build.
Fix: add exclude directives to the Fission go.mod:
// KEDA phantom requires — not propagated through their internal `replace`.
exclude k8s.io/client-go v1.5.2
exclude sigs.k8s.io/controller-runtime v0.23.1
Verify with go mod graph | grep '<bad-version>' to confirm which consumer declares the phantom require.
KEDA's webhook files (apis/keda/v1alpha1/*_webhook.go) are compiled whenever Fission imports KEDA CRD types. If controller-runtime's NewWebhookManagedBy signature changed (happened at v0.23), KEDA webhook files written against the old signature won't compile. Symptoms:
not enough arguments in call to ctrl.NewWebhookManagedBy
have (controllerruntime.Manager)
want (manager.Manager, T)
Fix: pin controller-runtime to the KEDA-compatible version (currently v0.22.4) and defer the bump until KEDA ships a cleanly-compatible release. Document in the deferred-group commit message.
prometheus/common v1.20.99)Some transitive deps push accidental high-version tags (v1.20.99 on a project that's actually on the v0.x line). go get then picks the retracted tag as "latest". Symptom: tidy warns retracted by module author.
Fix: add exclude github.com/prometheus/common v1.20.99 and explicit go get <pkg>@<correct-latest>.
go build ./... vs test fixturesThe Fission repo contains test fixture Go files (e.g. test/tests/test_huge_response/hello.go) that declare package main without a main function — they're not meant to be compiled standalone. go build ./... fails on them on main too. Always scope the compile check to ./pkg/... ./cmd/... to avoid false-positive noise.
pkg/storagesvc/client uses ory/dockertest to spin up a MinIO container. Without Docker running, make check fails there. This is environmental, not a dep regression. Verify by checking out go.mod + go.sum from main and re-running the single package — if it still fails, it's environmental.
git stash pop hazardThe user's stash list may contain pre-existing WIP from other sessions. git stash with a clean working tree reports "No local changes to save" and returns silently; a later git stash pop then unstashes the pre-existing entry unexpectedly and can conflict with the current branch. Before any git stash pop, run git stash list first to verify you're popping what you think you are. If you accidentally contaminate the working tree, git checkout HEAD -- <files> restores them without touching the stash list.
make code-checks (runs golangci-lint run against .golangci.yaml)make test-run (envtest via hack/runtests.sh; needs KUBEBUILDER_ASSETS which the script sets)make check (test-run + build-fission-cli + clean)go build ./pkg/... ./cmd/... (never ./... — see pitfall).github/dependabot.yml). For a security sweep we bypass that grouping on purpose — merging a single 20-dep PR defeats bisect.replace directive in go.mod: k8s.io/code-generator => github.com/fission/code-generator <sha>. Leave it alone.go mod tidy carry them forward).v1 → v2) — those need dedicated review, not a batch sweep.1. TaskCreate: baseline + one task per group + final verification
2. git checkout -b deps/security-sweep-<YYYY-MM>
3. govulncheck ./... | tee /tmp/govulncheck-before.txt
4. For each group in order (k8s → ctrl-runtime → otel → grpc/x-net → messaging → misc):
a. go get <deps> ; go mod tidy
b. go build ./pkg/... ./cmd/... ; make code-checks
c. On failure, bisect within the group; on success, commit
5. make check
6. govulncheck ./... | tee /tmp/govulncheck-after.txt ; diff against baseline
7. Summarize: commits on branch, CVEs closed, deferred groups (with upstream blocker noted)