--- name: educates-upgrade-go description: Upgrade the Go version across the entire educates-training-platform project. Invoke when asked to "upgrade go version", "bump golang", "update go", or "use go 1.xx". Updates go.work, all go.mod files, all Dockerfiles, and CI/CD workflow files. argument-hint: " (e.g. 1.24)" allowed-tools: "Read, Edit, Glob, Bash" --- # Educates Go Version Upgrade Protocol Upgrade the Go version to `$ARGUMENTS` (e.g. `1.24`) across all files in the project. ## Step 1: Find the Current Version Check the current Go version before making changes: ```bash grep -rn "^go 1\." go.work client-programs/go.mod installer/operator/go.mod node-ca-injector/go.mod assets-server/go.mod ``` ## Step 2: Update All Files You must update **all** of the following. Do not skip any. ### Go Module Files - **`go.work`** — update the `go 1.xx` directive. The workspace covers `client-programs/`, `installer/operator/`, and `node-ca-injector/`. - **`client-programs/go.mod`** — update the `go 1.xx` line - **`installer/operator/go.mod`** — update the `go 1.xx` line (the kubebuilder operator) - **`node-ca-injector/go.mod`** — update the `go 1.xx` line - **`assets-server/go.mod`** — update the `go 1.xx` line (Docker-only module, not in `go.work`) Discover every module so none is missed (the platform modules are at the repo root; ignore any `go.mod` under `workshop-samples/`, which is sample workshop content with its own lifecycle): ```bash git ls-files 'go.mod' '*/go.mod' | grep -v '^workshop-samples/' ``` Note: `tunnel-manager` is a Python (uv) component and has no `go.mod`. ### Dockerfiles Use the plain `golang:1.xx` image tag — do not switch to Alpine, Buster, Trixie, or other derivative tags. Only the `golang:1.xx` version changes — **do not add or remove the `--platform=$BUILDPLATFORM` prefix** as part of a version bump. - **`client-programs/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` - **`installer/operator/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` - **`node-ca-injector/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` - **`assets-server/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` - **`workshop-images/base-environment/Dockerfile`** — `FROM --platform=$BUILDPLATFORM golang:1.xx as builder-image` Search for any other Dockerfile referencing golang: ```bash grep -rn "FROM .*golang:" --include="Dockerfile*" . ``` #### About `--platform=$BUILDPLATFORM` It is not a standalone flag — it is correct **only** as a three-part cross-compile set in the same stage: 1. `FROM --platform=$BUILDPLATFORM golang:1.xx AS builder` (builder runs on the build host, not emulated), 2. `ARG TARGETOS` / `ARG TARGETARCH`, 3. `... GOOS=${TARGETOS} GOARCH=${TARGETARCH} go build ...` (cross-compile to the target). With all three, a multiarch build cross-compiles natively instead of running the Go toolchain under QEMU for each non-native arch — much faster. **Adding the prefix to a stage that builds with a plain `go build` (no `GOOS`/`GOARCH`) produces a wrong-architecture binary** — so the prefix and the `GOOS/GOARCH` build must always go together. All five Go Dockerfiles above currently cross-compile and carry the prefix. If you ever add a new Go build stage, give it the full three-part set (or no `--platform` at all) — never the prefix alone. ### CI/CD Workflows The Go workflows (`.github/workflows/*.yaml` — note the extension) pin the toolchain with `actions/setup-go` using `go-version-file:` pointing at a module's `go.mod` (e.g. `client-programs-ci.yaml` → `client-programs/go.mod`, `installer-operator-ci.yaml` → `installer/operator/go.mod`). Because the version is read from `go.mod`, bumping the `go.mod` files above is normally enough — no hardcoded version to edit. Still confirm there's no stray hardcoded version left behind: ```bash grep -rnE "go-version:|golang:1\." .github/workflows/ ``` If any `go-version: '1.xx'` literal exists, update it (or, preferably, convert it to `go-version-file:`). ## Step 3: Verify Run in order, fix any failures before proceeding: 1. Sync dependencies in every module (run `go mod tidy` in each): ```bash for m in client-programs installer/operator node-ca-injector assets-server; do (cd "$m" && go mod tidy) done ``` 2. Build the CLI and the operator: ```bash make build-cli # CLI (build-client-programs is an alias) make -C installer/operator build # operator manager binary ``` 3. Run tests (the operator's envtest is the most likely to surface a toolchain issue): ```bash cd client-programs && go test ./... make -C installer/operator test ``` ## Step 4: Post-Verification Checklist - [ ] `go.work` updated - [ ] All four platform `go.mod` files updated (`client-programs`, `installer/operator`, `node-ca-injector`, `assets-server`) - [ ] All five Dockerfiles with `FROM ...golang:` updated, `--platform=$BUILDPLATFORM` prefix preserved where present - [ ] CI: no stray hardcoded `go-version:`/`golang:1.` literal left (versions come from `go-version-file: /go.mod`) - [ ] `go mod tidy` ran cleanly in all modules - [ ] CLI builds (`make build-cli`) and operator builds + tests (`make -C installer/operator build test`) - [ ] No remaining references to the old Go version (`grep -rn "golang:1\." --include="Dockerfile*" .`) If `go mod tidy` changes `go.sum`, commit that change but confirm with the user first.