U2a: the builder plans a Go package on the Go build seat instead of refusing it

A module whose only artifact is a Go package (mesh-wireguard's go-overlay) never had a
done build: PlanOf refused every package of language go. The Go build module already packs
and publishes a Go package; the builder now asks it.

Builds: design 47 G §370; design 51 *Publishing*

Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
This commit is contained in:
2026-11-12 16:13:13 +01:00
parent 1550131792
commit 4332246f79
2 changed files with 7 additions and 4 deletions
@@ -67,7 +67,7 @@ func (p Plan) NeedsToolchain(module string) bool {
type Refused struct{ Artifact, What string }
func (r *Refused) Error() string {
return fmt.Sprintf("%s%s (artifact %s): no build module builds it; the builder builds Go and TypeScript bundles, archives, images, upstream copies and TypeScript packages", builds.RefusedKind, r.What, r.Artifact)
return fmt.Sprintf("%s%s (artifact %s): no build module builds it; the builder builds Go and TypeScript bundles and packages, archives, images and upstream copies", builds.RefusedKind, r.What, r.Artifact)
}
// NotPinned is the error of a plan with an upstream artifact whose reference names no digest (ADR 0498 clause 4): it opens
@@ -90,7 +90,7 @@ func (n *NoBuildModule) Unwrap() error { return n.Err }
// PlanOf is the plan of a manifest (ADR 0478 clauses 1 and 2, ADR 0498 clauses 4 and 5): a Go bundle and an archive are
// built by the Go build module, an image by the image build module (ADR 0487), which also copies an upstream image pinned
// by its digest, and a TypeScript bundle or package by the Node one, each in the order of the artifacts' names. A manifest
// by its digest, a Go package by the Go one (design 47 G §370) and a TypeScript bundle or package by the Node one, each in the order of the artifacts' names. A manifest
// with an upstream artifact pinned by no digest, or a bundle or a package of another language, or a kind no build module
// builds, is refused as a whole, naming the first such artifact by name. A manifest with no artifact has an empty plan.
func PlanOf(m catalogue.Manifest, seats *buildrun.BuildSeats) (Plan, error) {
@@ -125,7 +125,8 @@ func PlanOf(m catalogue.Manifest, seats *buildrun.BuildSeats) (Plan, error) {
return Plan{}, &NotPinned{Artifact: a.Name, From: a.From}
case a.Kind == catalogue.ArtifactUpstream:
err = task(a, "", "image")
case a.Kind == catalogue.ArtifactPackage && a.Language == "typescript":
case a.Kind == catalogue.ArtifactPackage && (a.Language == "go" || a.Language == "typescript"):
// A Go package is packed by the Go build module, tagged with the version its build reserved (design 47 G §370).
err = task(a, a.Language, a.Kind)
case a.Kind == catalogue.ArtifactBundle:
return Plan{}, &Refused{Artifact: a.Name, What: fmt.Sprintf("bundle of language %q", a.Language)}
@@ -22,13 +22,15 @@ func TestPlanRoutesEachKindToItsBuildModule(t *testing.T) { // 1607/AC2
m := manifestOf(
catalogue.Artifact{Name: "tool", Kind: "bundle", Language: "go"},
catalogue.Artifact{Name: "web", Kind: "bundle", Language: "typescript"},
catalogue.Artifact{Name: "files", Kind: "archive"})
catalogue.Artifact{Name: "files", Kind: "archive"},
catalogue.Artifact{Name: "go-overlay", Kind: "package", Language: "go"}) // design 47 G §370: a Go package is built
p, err := PlanOf(m, testSeats())
if err != nil {
t.Fatal(err)
}
want := []Task{
{Artifact: "files", Kind: "archive", Module: testGo, Language: "go"},
{Artifact: "go-overlay", Kind: "package", Module: testGo, Language: "go"},
{Artifact: "tool", Kind: "bundle", Module: testGo, Language: "go"},
{Artifact: "web", Kind: "bundle", Module: testNode, Language: "typescript"},
}