Uh oh!
There was an error while loading. Please reload this page.
fix: build a CGO-free CLI so companion publish links statically - #456
Merged
Conversation
…cally The companion publisher cross-compiles the CLI with CGO_ENABLED=0 into bin/linux/$TARGETARCH/codefly for the base + language images. That build failed to link because pkg/engine unconditionally installed the tree-sitter semantic analyzer (core/code/semantic), which requires cgo — so `codefly companion publish` (and any static CLI build) errored out with tree-sitter bindings excluded under CGO_ENABLED=0. Split newSource by the cgo build constraint: the cgo build keeps the analyzer (unchanged behavior for the normal CLI); the !cgo build uses core's CGO-free default. The companion CLI only builds and runs services in-container and never serves the semantic gateway, so it loses nothing. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This was referenced Aug 23, 2026
The static companion/self-cross build dropped the tree-sitter semantic
analyzer implicitly, by splitting newSource on the automatic `cgo` build
constraint (`//go:build cgo` / `!cgo`). That made CGO_ENABLED=0 a silent
switch: any build without cgo — including an *accidental* one, e.g. `go
install` on a machine with no C compiler, where Go auto-sets
CGO_ENABLED=0 — quietly produced a semantic-less CLI. Before this PR that
same build failed loudly ("build constraints exclude all Go files"),
which is the correct signal that a normal CLI needs cgo. Trading a loud
build failure for a silent capability downgrade is the exact "safe
default" that ships regressions.
Gate on an explicit intent tag instead:
- source_semantic.go //go:build !codefly_nosemantic (default; keeps
the analyzer; still fails to link under
CGO_ENABLED=0, restoring the loud signal)
- source_nosemantic.go //go:build codefly_nosemantic (CGO-free)
The two builds that legitimately want the analyzer-free variant now opt
in explicitly with `-tags codefly_nosemantic`: `codefly companion
build/publish` (buildLinuxCLI) and `codefly self build --os/--arch`
(buildCLICross). Renamed the files from _cgo/_nocgo to _semantic/
_nosemantic so the names track the real boundary, and named both opt-in
consumers in the CGO-free variant's doc (previously only companion was
mentioned).
Verification: add TestNewSourceExecutesLanguageNeutralOperation, which
asserts newSource returns a live Source whose base behavior runs; it
covers the analyzer variant in the normal suite and the analyzer-free
variant when run with -tags codefly_nosemantic. Wire a coverage-gate CI
step that builds the CGO-free variant statically and runs that test under
the tag, so a regression in the analyzer-free path is caught without the
Docker-dependent companions.yaml job.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>8 tasks
Uh oh!
There was an error while loading. Please reload this page.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
codefly companion publish(base + language images) cross-compiles the CLI withCGO_ENABLED=0intobin/linux/$TARGETARCH/codefly, thenCOPYs it into the alpine-based companion images. That build could not link:pkg/engine/source.gounconditionally installed the tree-sitter semantic analyzer (core/code/semantic), which requires cgo, soCGO_ENABLED=0 go buildfailed with all tree-sitter bindings excluded by build constraints.newSourceby the automaticcgobuild constraint: the cgo build keeps the analyzer (normal CLI behavior is unchanged); the!cgobuild falls back to core's CGO-free defaultDefaultCodeServer. The companion CLI only builds/runs services in-container — it never serves the semantic gateway — so nothing of value is lost in that image.Found while publishing the Go 1.27 companion image for codefly-dev/core#341:
codefly companion publish goaborted before Docker ran, at the CLI cross-compile step.Test plan
CGO_ENABLED=0 GOOS=linux go build -ldflags '-s -w -extldflags "-static"' .— now succeeds (was exit 1:build constraints exclude all Go filesfor the tree-sitter bindings).go build ./...(default, cgo on) — succeeds; the semantic analyzer is still linked into the normal CLI.go vet ./pkg/engine/passes both with cgo and withCGO_ENABLED=0.gofmtclean.🤖 Generated with Claude Code