Submit an issue View all issues Source
MIR-1258

Authoritative cgo auto-detection for the Go buildpack

Open public
phinze phinze Opened Jun 25, 2026 Updated Jul 9, 2026

MIR-1248 moved Go to a glibc/bookworm builder with an adaptive runtime: pure-Go apps ship as a static binary on distroless/static, cgo apps ship on debian-slim. Right now you pick between them by setting the standard CGO_ENABLED env var. This issue makes that choice automatic.

The reason it isn't automatic already: which runtime base an image uses is decided when we construct the build graph, before the build runs. We can't build first and then change our minds about the base from the result. So to choose correctly, we have to know whether the app needs cgo up front.

"Needs cgo" is defined as causation, not failure: an app needs cgo if and only if it fails to build with CGO_ENABLED=0 and succeeds with CGO_ENABLED=1. The probe evaluates that directly, which is unambiguous and requires no error-string parsing or "why did it fail" guessing. A build that fails both ways is a real error and is surfaced as-is, never mislabeled as cgo. The 99% pure-Go case is decided by the first cgo-off build and never pays for a second pass; only genuinely-cgo and genuinely-broken apps compile twice. Whether a cheaper proxy (inspecting go list structural fields) can stand in for the second compile without losing that rigor is an implementation question to validate, not the spec.

When the differential routes an app to cgo automatically, emit a build warning in the spirit of #862's port auto-routing: the build succeeded, but the CGO_ENABLED=0 pass failed first and cost an extra compile, and setting CGO_ENABLED=1 under [env] skips detection and builds faster. So the env var introduced in MIR-1248 isn't deprecated by this work, it becomes the documented fast path the warning points to.

Gating: the extra detection step has to run inside the build server's BuildImage, whose solve path is mid-migration to sagas. Hold this until the saga consolidation lands rather than thread the new step through two implementations. Follow-up to MIR-1248.