Files
gatewayapi-certificates-ope…/docs/plans-executions/2026-10-08-2028-house-conventions.md
kacerrandClaude Opus 5.5 5c4a148b36
Deploy to K8s / deploy (push) Successful in 14s
docs: close out the conventions and listener-name plans
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-08 20:47:53 +02:00

7.1 KiB

Execution: Bring gateway-helper-operator up to house conventions

Plan: docs/plans/2026-10-08-2028-house-conventions.md

  • Step 0 — Save and commit the plan
  • Step 1 — CLAUDE.md
  • Step 2 — .claude/ and docs scaffolding
  • Step 3 — Makefile, lint, formatting
  • Step 4 — Module path and version identity
  • Step 5 — Baseline tests
  • Step 6 — CI build workflow
  • Step 7 — Close out

Step 1 — CLAUDE.md

Rewrote CLAUDE.md in the five-section shape. The Go, Testing, Changelog and Branching text comes from the go-project-bootstrap skill references; the plan ordering and execution-summary rules come from egress-proxies-operator/CLAUDE.md, condensed from prose into bullets.

Deviations from the plan:

  • The house container rules about Ubuntu dev images and separate dev/prod Dockerfiles were left out: this repo has one production Dockerfile and no dev image, and listing rules nobody follows only adds noise.
  • The listener-port row was removed from the annotation table and moved to Gotchas, so the table lists only what works.
  • Added a short Reviews subsection so the reviewer agents and docs/reviews/ have a documented trigger.
  • README.md also claimed that deleting a certificate removes its listeners "instantly". Reworded and added the known limitation.

Worth noting: Commands and CI/CD describe the repo as it is at this commit; Steps 3, 4 and 6 update them. docs/flows.md cites main.go line numbers that Step 4 shifts.

Step 2 — .claude/ and docs scaffolding

Copied the two reviewer agents and /ship from egress-proxies-operator/.claude/. /release was rewritten for the semver rule instead of copied, because the egress text says "no tagging scheme is documented" and this repo now has one.

Deviations from the plan:

  • /ship names "a Co-Authored-By: trailer for Claude" instead of the fixed Claude <noreply@anthropic.com> string, matching CLAUDE.md.
  • .gitignore already covered /bin/ and *.out, so only .claude/settings.local.json was added.
  • settings.json also allows kubectl kustomize, which the Commands section uses.

Worth noting: .claude/settings.json leaves out git commit, git push and git tag on purpose, but ~/.claude/settings.json allows git commit and git push globally, so on this machine the push confirmation rests on CLAUDE.md, not on the permission system.

Step 3 — Makefile, lint, formatting

Added Makefile (uh-cli's shape plus run, docker-build and -race on test), .golangci.yml (v2 defaults) and .dockerignore (egress's allowlist).

make lint failed on first run, before reaching this repo's code:

$ golangci-lint run ./...
.../go/1.27.1/libexec/src/crypto/internal/randutil/randutil.go:11:2: could not import math/rand/v2
(.../math/rand/v2/rand.go:213:17: method must have no type parameters) (typecheck)

The installed golangci-lint 2.12.2 was built with go1.26.4 and cannot type-check the Go 1.27 standard library. The lint target now runs under the go.mod toolchain, which is also what CI uses:

GO_MOD_VERSION := $(shell awk '$$1 == "go" {print $$2}' go.mod)
lint:
	GOTOOLCHAIN=go$(GO_MOD_VERSION) golangci-lint run ./...

With that, lint reported the two expected dead variables (gatewayGroup, gatewayKind in patch.go), which were removed. make fmt reformatted main.go (import order) and the patch.go var block.

Worth noting: this is likely the same failure the egress changelog records as "make lint is blocked by a Go 1.27 toolchain/staticcheck panic"; the same GOTOOLCHAIN pin should unblock it there. Rebuilding golangci-lint with Go 1.27 is the other fix. .golangci.yml carries no settings yet: uh-cli's errcheck exclusions are CLI-specific and nothing here needed one.

Step 4 — Module path and version identity

Module renamed to gitea.home.hrajfrisbee.cz/kacerr/gatewayapi-certificates-operator. internal/version copied from egress unchanged (code and test). main.go gained --version, a first log line with commit and Go version, the standard --zap-* flags, and passes --metrics-bind-address to the manager.

$ make build && ./bin/manager --version
0eb588e8bd3a-dirty
$ make docker-build && docker run --rm gateway-cert-operator:dev --version
0eb588e8bd3a-dirty
$ docker inspect gateway-cert-operator:dev --format '{{index .Config.Labels "org.opencontainers.image.revision"}} {{.Config.User}}'
0eb588e8bd3a-dirty 65532:65532

Deviations from the plan:

  • The Dockerfile build also got -trimpath, and keeps -s -w (egress has neither).
  • The Dockerfile now does COPY . . and relies on the new .dockerignore allowlist, instead of copying main.go and internal/ by name.
  • The gozap.AddCaller() option was kept so log lines look the same as before.

Worth noting: the manager was not started against a cluster in this step; the flag wiring is verified by --help output and the build only. GOARCH defaults to amd64 when TARGETARCH is empty (legacy builder, as on the CI runner) and follows the host under BuildKit, so a local build on an Apple Silicon machine is arm64. docs/flows.md still cites pre-change main.go line numbers in §2.

Step 5 — Baseline tests

internal/gateway/patch_test.go: five table-driven tests over the pure functions.

$ go test -race -cover ./...
ok  .../internal/gateway   1.870s  coverage: 96.9% of statements
ok  .../internal/version   2.196s  coverage: 94.7% of statements

Worth noting: internal/controller and main are at 0%; reconciler tests with the fake client come with the first reconcile fix. Wildcard names, name collisions and truncation are deliberately not asserted, so the suite does not pin behaviour that the bug-fix phase will change. TestListenersEqual_managedFields only asserts the four fields the comparison covers today; it says nothing about protocol, allowed routes or TLS mode.

Step 6 — CI build workflow

.gitea/workflows/build.yaml is now a verbatim copy of the egress workflow; it has no project-specific strings (the image name comes from github.repository).

Worth noting: not run yet. The first tag push or manual dispatch is the test. Two things could differ from egress on this repo's runner: actions/setup-go@v5 (uh-cli had to install Go with curl instead), and lint is not part of the check job, same as egress. The unused GIT_TAG and BUILD_DATE build args are gone; kubernetes-deploy.yaml is untouched.

Step 7 — Close out (review)

Ran both reviewer agents on main...HEAD; findings and their status are in docs/reviews/2026-10-08-2040-house-conventions.md. Ten items fixed on the branch, four new bugs deferred to the bug-fix phase, one test simplification declined.

Worth noting: the reviewer agents were not registered as agent types when the review started (they were added in this session), so they were run as general-purpose agents told to follow the agent files. The :latest dispatch hole came in with the workflow copied from egress and is still open there. Pushed together with the listener-name fix (docs/plans/2026-10-08-2046-listener-name-sanitize.md) as one MR. The CHANGELOG entry is still owed, after the owner confirms it works.