mesh-build-go reads a check's toolchain from the job, answers with the Delivery SDK's CheckAnswer and typed FetchAnswer, and takes the toolchains value from the Delivery SDK; askrun_gaps.go and toolchain.go are gone (B5j; ADR 0584 clause 2, ADR 0634 section 6; issue 1966)
Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
@@ -49,7 +49,7 @@ type AskSteps struct {
|
||||
Has func(need string) bool
|
||||
}
|
||||
|
||||
// RunAsk runs ask's job with steps and answers a sdkstep.BuildAnswer or a CheckAnswer.
|
||||
// RunAsk runs ask's job with steps and answers a sdkstep.BuildAnswer or a sdkstep.CheckAnswer.
|
||||
func RunAsk(ctx context.Context, steps AskSteps, ask sdkstep.StepAsk) (any, error) {
|
||||
if ask.Build != nil {
|
||||
job := *ask.Build
|
||||
@@ -274,7 +274,7 @@ func (s AskSteps) build(ctx context.Context, job sdkstep.BuildJob) (any, error)
|
||||
}
|
||||
|
||||
func (s AskSteps) check(ctx context.Context, job sdkstep.CheckJob) (any, error) {
|
||||
if _, err := s.onToolchain(ctx, checkToolchain(ctx)); err != nil {
|
||||
if _, err := s.onToolchain(ctx, job.Toolchain); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
r, f, err := s.fetch(ctx, &job.Fetch)
|
||||
@@ -282,7 +282,10 @@ func (s AskSteps) check(ctx context.Context, job sdkstep.CheckJob) (any, error)
|
||||
return nil, err
|
||||
}
|
||||
defer s.release(f.Workspace)
|
||||
answer := CheckAnswer{Fetch: r}
|
||||
answer := sdkstep.CheckAnswer{}
|
||||
if err := json.Unmarshal(r, &answer.Fetch); err != nil {
|
||||
return nil, fmt.Errorf("the fetch answered what is not a fetch answer: %s: %w", r, err)
|
||||
}
|
||||
if len(f.Conflicts) > 0 {
|
||||
return answer, nil // the asker reads the conflict from the fetch's answer: a verdict, not an error
|
||||
}
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
package buildstep
|
||||
|
||||
// Two layouts the part build-step (mesh-delivery-sdk buildstep, as the three node-build seats generate it) lacks, which a
|
||||
// check ask still carries; both are kept here and nowhere else, so that deleting this file is the whole change once the
|
||||
// part has them (B5i finding 1 and 2, issue 1966):
|
||||
//
|
||||
// - the check job's toolchain (novox/hq ADR 0584 clause 2): the part's CheckJob has no `toolchain`, so a node on
|
||||
// another toolchain than the checker agreed would take the ask and record a pass it did not run. The Puller reads
|
||||
// the field from the ask's own bytes and the run takes it from its context.
|
||||
// - the check answer's fetch: the part types the answer's `fetch` as Fetch (the arguments), but the fetch tool's answer
|
||||
// (workspace, merge, conflicts, changed, modules) is what the checker reads a conflict from.
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
)
|
||||
|
||||
type checkToolchainKey struct{}
|
||||
|
||||
// checkToolchainOf reads the toolchain a check ask names, from the ask's bytes; nil when it names none or is no check.
|
||||
func checkToolchainOf(data []byte) *sdkstep.ToolchainUsed {
|
||||
var a struct {
|
||||
Check *struct {
|
||||
Toolchain *sdkstep.ToolchainUsed `json:"toolchain"`
|
||||
} `json:"check"`
|
||||
}
|
||||
if json.Unmarshal(data, &a) != nil || a.Check == nil {
|
||||
return nil
|
||||
}
|
||||
return a.Check.Toolchain
|
||||
}
|
||||
|
||||
// WithCheckToolchain is ctx carrying the toolchain the ask in data names for its check.
|
||||
func WithCheckToolchain(ctx context.Context, data []byte) context.Context {
|
||||
if tc := checkToolchainOf(data); tc != nil {
|
||||
return context.WithValue(ctx, checkToolchainKey{}, tc)
|
||||
}
|
||||
return ctx
|
||||
}
|
||||
|
||||
func checkToolchain(ctx context.Context) *sdkstep.ToolchainUsed {
|
||||
tc, _ := ctx.Value(checkToolchainKey{}).(*sdkstep.ToolchainUsed)
|
||||
return tc
|
||||
}
|
||||
|
||||
// CheckAnswer is a check ask's answer with the fetch tool's own answer as it is.
|
||||
type CheckAnswer struct {
|
||||
Fetch json.RawMessage `json:"fetch"`
|
||||
Levels []sdkstep.LevelAnswer `json:"levels,omitempty"`
|
||||
}
|
||||
@@ -82,7 +82,7 @@ func TestRunAskBuilds(t *testing.T) {
|
||||
steps.Imports = func(ctx context.Context, args map[string]any) (any, error) {
|
||||
b, _ := json.Marshal(args)
|
||||
r.calls = append(r.calls, "imports "+string(b))
|
||||
return map[string]any{"imports": []string{"git.novox.be/novox/mesh-sdk/go/announce", "git.novox.be/novox/mesh-sdk/go/delivery"}}, nil
|
||||
return map[string]any{"imports": []string{"git.novox.be/novox/mesh-sdk/go/announce", "git.novox.be/novox/mesh-sdk/go/health"}}, nil
|
||||
}
|
||||
// Issue 1585: the ask's package versions reach the fetch, and the ask's own fetch arguments stay as they were.
|
||||
a := ask(sdkstep.BuildJob{Module: "m", Path: "modules/m", Publish: true,
|
||||
@@ -112,7 +112,7 @@ imports {"module":"modules/m","workspace":"/w/1"}`
|
||||
if len(answer.Artifacts) != 3 || answer.Artifacts[1].Reference != "artifact-store://bundle" {
|
||||
t.Fatalf("answer %+v", answer)
|
||||
}
|
||||
if !slices.Equal(answer.Imports, []string{"git.novox.be/novox/mesh-sdk/go/announce", "git.novox.be/novox/mesh-sdk/go/delivery"}) {
|
||||
if !slices.Equal(answer.Imports, []string{"git.novox.be/novox/mesh-sdk/go/announce", "git.novox.be/novox/mesh-sdk/go/health"}) {
|
||||
t.Errorf("the answer's imports are %v", answer.Imports)
|
||||
}
|
||||
}
|
||||
@@ -130,15 +130,10 @@ func TestRunAskRefusesAnotherToolchain(t *testing.T) {
|
||||
if !errors.As(err, &dec) || len(dec.Lacks) != 1 || len(r.calls) != 0 {
|
||||
t.Fatalf("err %v, calls %v", err, r.calls)
|
||||
}
|
||||
// A check ask names the toolchain too (ADR 0584), and a node on another declines it before it fetches. The part's
|
||||
// CheckJob has no field for it, so the ask's own bytes carry it (askrun_gaps.go).
|
||||
check := ask(sdkstep.CheckJob{Fetch: sdkstep.Fetch{Repository: "novox/x", Commit: runCommit}, Levels: []string{sdkstep.LevelUnit}})
|
||||
raw, _ := json.Marshal(check)
|
||||
var doc map[string]any
|
||||
_ = json.Unmarshal(raw, &doc)
|
||||
doc["check"].(map[string]any)["toolchain"] = map[string]any{"version": "go1.26", "recipe": "3"}
|
||||
raw, _ = json.Marshal(doc)
|
||||
_, err = RunAsk(WithCheckToolchain(context.Background(), raw), s, check)
|
||||
// A check ask names the toolchain too (ADR 0584 clause 2), and a node on another declines it before it fetches.
|
||||
check := ask(sdkstep.CheckJob{Fetch: sdkstep.Fetch{Repository: "novox/x", Commit: runCommit}, Levels: []string{sdkstep.LevelUnit},
|
||||
Toolchain: &sdkstep.ToolchainUsed{Version: "go1.26", Recipe: "3"}})
|
||||
_, err = RunAsk(context.Background(), s, check)
|
||||
if !errors.As(err, &dec) || len(r.calls) != 0 {
|
||||
t.Fatalf("a check ask: err %v, calls %v", err, r.calls)
|
||||
}
|
||||
@@ -169,7 +164,10 @@ test {"level":"integration","packages":["x/pkg/a"],"workspace":"/w"}`
|
||||
if got != want {
|
||||
t.Fatalf("calls:\n%s\nwant:\n%s", got, want)
|
||||
}
|
||||
a := out.(CheckAnswer)
|
||||
a := out.(sdkstep.CheckAnswer)
|
||||
if a.Fetch.Workspace != "/w" || !slices.Equal(a.Fetch.Changed, []string{"pkg/b/b_test.go"}) {
|
||||
t.Fatalf("the answer's fetch is the tool's whole answer, typed: %+v", a.Fetch)
|
||||
}
|
||||
if len(a.Levels) != 2 {
|
||||
t.Fatalf("levels %+v, want both levels", a.Levels)
|
||||
}
|
||||
@@ -201,7 +199,7 @@ test {"level":"integration","packages":["x/pkg/a"],"workspace":"/w"}`
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
u := out.(CheckAnswer).Levels[0]
|
||||
u := out.(sdkstep.CheckAnswer).Levels[0]
|
||||
tested := strings.Contains(strings.Join(r.calls, "\n"), `"x/pkg/a"`)
|
||||
if tested != has || (len(u.Unmet) == 0) == !has || (!has && (u.Unmet[0].Package != "x/pkg/a" || sdkstep.UnmetNeeds([]sdkstep.LevelAnswer{u})[0] != sdkstep.NeedNodeBuildNode)) {
|
||||
t.Fatalf("has %v: tested x/pkg/a %v, unmet %+v, calls %v", has, tested, u.Unmet, r.calls)
|
||||
@@ -218,7 +216,7 @@ test {"level":"integration","packages":["x/pkg/a"],"workspace":"/w"}`
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
u := out.(CheckAnswer).Levels[0]
|
||||
u := out.(sdkstep.CheckAnswer).Levels[0]
|
||||
if last := r.calls[len(r.calls)-1]; !strings.HasSuffix(last, `"packages":["x/pkg/a"],"workspace":"/w"}`) || len(u.Kept) != 0 || len(u.Tests) != 1 {
|
||||
t.Fatalf("digests %v: calls %v, kept %+v: want x/pkg/a alone tested, nothing taken kept", digests != nil, r.calls, u.Kept)
|
||||
}
|
||||
@@ -250,7 +248,7 @@ test {"level":"unit","runner":"workspace","workspace":"/w"}`},
|
||||
if got := strings.Join(r.calls[1:], "\n"); got != tc.want {
|
||||
t.Errorf("judged by %s: calls\n%s\nwant\n%s", tc.judged, got, tc.want)
|
||||
}
|
||||
l := out.(CheckAnswer).Levels[0]
|
||||
l := out.(sdkstep.CheckAnswer).Levels[0]
|
||||
if tc.judged == "installed" && (len(l.Kept) != 1 || l.Judged != "") {
|
||||
t.Errorf("an installed module's level %+v, want the kept verdict taken", l)
|
||||
}
|
||||
@@ -264,7 +262,7 @@ test {"level":"unit","runner":"workspace","workspace":"/w"}`},
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if l := out.(CheckAnswer).Levels[0]; len(l.Kept) != 0 || l.Digest != nil {
|
||||
if l := out.(sdkstep.CheckAnswer).Levels[0]; len(l.Kept) != 0 || l.Digest != nil {
|
||||
t.Fatalf("a digest without the siblings kept %+v", l)
|
||||
}
|
||||
}
|
||||
@@ -284,7 +282,7 @@ func TestRunAskChecksNodeModulesAndConflicts(t *testing.T) {
|
||||
}
|
||||
r = &recorder{fetch: map[string]any{"workspace": "/w", "conflicts": []string{"go.mod"}}}
|
||||
out, err := RunAsk(context.Background(), r.steps(), ask(sdkstep.CheckJob{Levels: []string{sdkstep.LevelUnit}, Fetch: sdkstep.Fetch{Repository: "novox/x", Commit: runCommit}}))
|
||||
if err != nil || len(r.calls) != 1 || len(out.(CheckAnswer).Levels) != 0 {
|
||||
if err != nil || len(r.calls) != 1 || len(out.(sdkstep.CheckAnswer).Levels) != 0 {
|
||||
t.Fatalf("a conflict: %v %v", err, r.calls)
|
||||
}
|
||||
}
|
||||
@@ -324,7 +322,7 @@ func TestRunAskRunsEveryPackageAndLevelAfterAFailure(t *testing.T) {
|
||||
if want := append(slices.Clone(row.want), row.want...); fmt.Sprint(got) != fmt.Sprint(want) {
|
||||
t.Errorf("%s: tested %v, want %v", row.name, got, want)
|
||||
}
|
||||
if a := out.(CheckAnswer); len(a.Levels) != 2 || len(a.Levels[0].Tests) != len(row.want) {
|
||||
if a := out.(sdkstep.CheckAnswer); len(a.Levels) != 2 || len(a.Levels[0].Tests) != len(row.want) {
|
||||
t.Errorf("%s: levels %+v, want both, each with every test result", row.name, a.Levels)
|
||||
}
|
||||
}
|
||||
@@ -338,7 +336,7 @@ func TestRunAskRunsEveryPackageAndLevelAfterAFailure(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if a := out.(CheckAnswer); len(r.calls) != 5 || len(a.Levels) != 2 || len(a.Levels[0].Tests) != 2 {
|
||||
if a := out.(sdkstep.CheckAnswer); len(r.calls) != 5 || len(a.Levels) != 2 || len(a.Levels[0].Tests) != 2 {
|
||||
t.Fatalf("calls %v, levels %+v: want b then a at each of the two levels", r.calls, a.Levels)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ func TestADigestOfAPackageNamedTokenIsStoredAsAList(t *testing.T) {
|
||||
if !ok || s.State != sdkstep.StepPassed || st.refused != 0 {
|
||||
t.Fatalf("the end %+v (written %v, refused %d), want it passed and taken at once", s, ok, st.refused)
|
||||
}
|
||||
var a CheckAnswer
|
||||
var a sdkstep.CheckAnswer
|
||||
if err := json.Unmarshal(s.Result, &a); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
@@ -4,6 +4,8 @@ import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
)
|
||||
|
||||
// Guard is a build module's check that the toolchain installed on its node is the one its recipe builds with
|
||||
@@ -31,11 +33,11 @@ func (g Guard) Check(ctx context.Context) error {
|
||||
if err != nil {
|
||||
return &Refusal{Text: fmt.Sprintf("the installed %s version could not be read: %v", g.Language, err), Want: g.Want}
|
||||
}
|
||||
key, err := ToolchainKey(g.Node, g.Language)
|
||||
key, err := sdkstep.ToolchainKey(g.Node, g.Language)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
raw, err := EncodeToolchain(Toolchain{Language: g.Language, Version: installed, Recipe: g.Recipe, At: now().UTC()})
|
||||
raw, err := sdkstep.EncodeToolchain(sdkstep.Toolchain{Language: g.Language, Version: installed, Recipe: g.Recipe, At: now().UTC()})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -6,12 +6,14 @@ import (
|
||||
"errors"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
)
|
||||
|
||||
type toolchainKeys map[string]Toolchain
|
||||
type toolchainKeys map[string]sdkstep.Toolchain
|
||||
|
||||
func (k toolchainKeys) put(key string, value any) (uint64, error) {
|
||||
tc, err := DecodeToolchain(value.(json.RawMessage))
|
||||
tc, err := sdkstep.DecodeToolchain(value.(json.RawMessage))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
@@ -644,7 +644,7 @@ func (p *Puller) run(ctx context.Context, msg *Pulled, ask sdkstep.StepAsk, key
|
||||
}()
|
||||
ph := &phases{put: p.Put, key: key, step: step, logf: p.Logf, prefix: fmt.Sprintf("the %s ask %s on %s", ask.Kind, ask.ID, p.Node)}
|
||||
result, err := protect(ctx, func(ctx context.Context) (any, error) {
|
||||
return p.Run(WithCheckToolchain(context.WithValue(ctx, phaseKey{}, ph), msg.Data), ask)
|
||||
return p.Run(context.WithValue(ctx, phaseKey{}, ph), ask)
|
||||
})
|
||||
step = ph.end() // its end keeps the phase it ended in
|
||||
close(done)
|
||||
|
||||
@@ -1,82 +0,0 @@
|
||||
package buildstep
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// ToolchainVersion is the layout version of a toolchains value.
|
||||
const ToolchainVersion = 1
|
||||
|
||||
// Toolchain is the value of a build module's state toolchains under the key <node>.<language>: the version of the
|
||||
// language's toolchain installed on the node, the build module's recipe version, and when the module saw them. It is
|
||||
// the layout every node-build seat gives that state (the seats' generated Toolchain); the three build modules share
|
||||
// this form because their runner does (design 26 *Where a seat's code goes*, a module's own package). A test holds it
|
||||
// to each seat's decoder.
|
||||
type Toolchain struct {
|
||||
V int `json:"v,omitempty"`
|
||||
Language string `json:"language"`
|
||||
Version string `json:"version"`
|
||||
Recipe string `json:"recipe"`
|
||||
At time.Time `json:"at,omitzero"`
|
||||
}
|
||||
|
||||
func checkToolchainLanguage(language string) error {
|
||||
switch language {
|
||||
case "go", "typescript":
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("buildstep: the toolchain language %q is not go or typescript", language)
|
||||
}
|
||||
|
||||
// ToolchainKey is the key of a node's toolchain of one language: <node>.<language>. It refuses an empty node, a node
|
||||
// with a dot and a language other than go or typescript.
|
||||
func ToolchainKey(node, language string) (string, error) {
|
||||
if node == "" || strings.ContainsAny(node, ". ") {
|
||||
return "", fmt.Errorf("buildstep: %q is not a node name", node)
|
||||
}
|
||||
if err := checkToolchainLanguage(language); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return node + "." + language, nil
|
||||
}
|
||||
|
||||
func (t Toolchain) check() error {
|
||||
if err := checkToolchainLanguage(t.Language); err != nil {
|
||||
return err
|
||||
}
|
||||
if t.Version == "" || t.Recipe == "" {
|
||||
return fmt.Errorf("buildstep: a %s toolchain needs its version and its recipe", t.Language)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// EncodeToolchain is t as JSON; it refuses a language other than go or typescript and an empty version or recipe.
|
||||
func EncodeToolchain(t Toolchain) ([]byte, error) {
|
||||
if err := t.check(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
t.V = ToolchainVersion
|
||||
return json.Marshal(t)
|
||||
}
|
||||
|
||||
// DecodeToolchain reads a toolchains value, refusing an unknown field, another layout version and what
|
||||
// EncodeToolchain refuses.
|
||||
func DecodeToolchain(data []byte) (Toolchain, error) {
|
||||
var t Toolchain
|
||||
dec := json.NewDecoder(bytes.NewReader(data))
|
||||
dec.DisallowUnknownFields()
|
||||
if err := dec.Decode(&t); err != nil {
|
||||
return Toolchain{}, fmt.Errorf("buildstep: a toolchain does not read: %w", err)
|
||||
}
|
||||
if t.V != ToolchainVersion {
|
||||
return Toolchain{}, fmt.Errorf("buildstep: a toolchain of version %d, this reads %d", t.V, ToolchainVersion)
|
||||
}
|
||||
if err := t.check(); err != nil {
|
||||
return Toolchain{}, err
|
||||
}
|
||||
return t, nil
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
package buildstep
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
nodebuildgo "git.novox.be/novox/mesh-delivery/contracts/go/seats/nodebuildgo"
|
||||
nodebuildimage "git.novox.be/novox/mesh-delivery/contracts/go/seats/nodebuildimage"
|
||||
nodebuildnode "git.novox.be/novox/mesh-delivery/contracts/go/seats/nodebuildnode"
|
||||
)
|
||||
|
||||
// The toolchains value and key are the layout all three node-build seats generate: each seat's strict decoder reads
|
||||
// what the shared runner writes, and each seat's key function agrees with ToolchainKey.
|
||||
func TestTheToolchainsValueAndKeyAreTheSeatsLayout(t *testing.T) {
|
||||
raw, err := EncodeToolchain(Toolchain{Language: "go", Version: "go1.27.1", Recipe: "3", At: time.Date(2026, 11, 5, 10, 0, 0, 0, time.UTC)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if _, err := nodebuildgo.DecodeToolchainsByNodeLanguageValue(raw); err != nil {
|
||||
t.Errorf("node-build-go does not read the value: %v", err)
|
||||
}
|
||||
if _, err := nodebuildimage.DecodeToolchainsByNodeLanguageValue(raw); err != nil {
|
||||
t.Errorf("node-build-image does not read the value: %v", err)
|
||||
}
|
||||
if _, err := nodebuildnode.DecodeToolchainsByNodeLanguageValue(raw); err != nil {
|
||||
t.Errorf("node-build-node does not read the value: %v", err)
|
||||
}
|
||||
back, err := DecodeToolchain(raw)
|
||||
if err != nil || back.Version != "go1.27.1" || back.At.IsZero() {
|
||||
t.Errorf("the value reads back as %+v, %v", back, err)
|
||||
}
|
||||
key, err := ToolchainKey("ace", "typescript")
|
||||
if err != nil || key != nodebuildnode.ToolchainsByNodeLanguageKey("ace", "typescript") || key != nodebuildgo.ToolchainsByNodeLanguageKey("ace", "typescript") {
|
||||
t.Errorf("key %q, %v", key, err)
|
||||
}
|
||||
for _, bad := range [][2]string{{"", "go"}, {"a.b", "go"}, {"ace", "rust"}} {
|
||||
if _, err := ToolchainKey(bad[0], bad[1]); err == nil {
|
||||
t.Errorf("the key of %v was made", bad)
|
||||
}
|
||||
}
|
||||
if _, err := EncodeToolchain(Toolchain{Language: "go", Version: "go1.27"}); err == nil {
|
||||
t.Error("a toolchain without its recipe was written")
|
||||
}
|
||||
if _, err := DecodeToolchain([]byte(`{"v":1,"language":"go","version":"x","recipe":"1","extra":1}`)); err == nil || !strings.Contains(err.Error(), "extra") {
|
||||
t.Errorf("a field the layout lacks was read: %v", err)
|
||||
}
|
||||
}
|
||||
@@ -203,7 +203,7 @@ func TestACheckAsksDigestIsTheToolsAnswerInTheCall(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if l := out.(buildstep.CheckAnswer).Levels; len(l) != 1 || l[0].Digest.Map()["x/a"] != "d1" {
|
||||
if l := out.(sdkstep.CheckAnswer).Levels; len(l) != 1 || l[0].Digest.Map()["x/a"] != "d1" {
|
||||
t.Fatalf("levels = %+v, want the digest's packages", l)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
buildstep "git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
)
|
||||
@@ -17,17 +16,17 @@ import (
|
||||
// keptStates stands in for the toolchains and the steps states.
|
||||
type keptStates struct {
|
||||
mu sync.Mutex
|
||||
toolchains map[string]buildstep.Toolchain
|
||||
toolchains map[string]sdkstep.Toolchain
|
||||
steps map[string][]sdkstep.Step
|
||||
ended chan string
|
||||
}
|
||||
|
||||
func newStates() *keptStates {
|
||||
return &keptStates{toolchains: map[string]buildstep.Toolchain{}, steps: map[string][]sdkstep.Step{}, ended: make(chan string, 16)}
|
||||
return &keptStates{toolchains: map[string]sdkstep.Toolchain{}, steps: map[string][]sdkstep.Step{}, ended: make(chan string, 16)}
|
||||
}
|
||||
|
||||
func (s *keptStates) putToolchain(key string, value any) (uint64, error) {
|
||||
tc, err := buildstep.DecodeToolchain(value.(json.RawMessage))
|
||||
tc, err := sdkstep.DecodeToolchain(value.(json.RawMessage))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -51,7 +50,7 @@ func (s *keptStates) putStep(key string, value any) (uint64, error) {
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func (s *keptStates) toolchain(key string) (buildstep.Toolchain, bool) {
|
||||
func (s *keptStates) toolchain(key string) (sdkstep.Toolchain, bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
tc, ok := s.toolchains[key]
|
||||
@@ -86,7 +85,7 @@ func TestStartWritesTheToolchainAndHealthIsHealthy(t *testing.T) {
|
||||
ctx, stop := context.WithCancel(context.Background())
|
||||
defer stop()
|
||||
go m.Start(ctx)
|
||||
var tc buildstep.Toolchain
|
||||
var tc sdkstep.Toolchain
|
||||
for deadline := time.Now().Add(30 * time.Second); time.Now().Before(deadline); time.Sleep(5 * time.Millisecond) {
|
||||
if got, ok := states.toolchain("ace.go"); ok {
|
||||
tc = got
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
buildstep "git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
)
|
||||
@@ -192,7 +191,7 @@ func (m *Module) RecentSteps(limit int) (lines []StepLine, cut bool, err error)
|
||||
}
|
||||
|
||||
// ReadToolchains is every key of the toolchains state (<node>.<language>) with its stored value.
|
||||
func (m *Module) ReadToolchains() (map[string]buildstep.Toolchain, error) {
|
||||
func (m *Module) ReadToolchains() (map[string]sdkstep.Toolchain, error) {
|
||||
if m.ReadToolchainsState.Keys == nil || m.ReadToolchainsState.Get == nil {
|
||||
return nil, fmt.Errorf("the toolchains state cannot be read here")
|
||||
}
|
||||
@@ -210,12 +209,12 @@ func (m *Module) ReadToolchains() (map[string]buildstep.Toolchain, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := map[string]buildstep.Toolchain{}
|
||||
out := map[string]sdkstep.Toolchain{}
|
||||
for i, raw := range raws {
|
||||
if len(raw) == 0 {
|
||||
continue
|
||||
}
|
||||
t, err := buildstep.DecodeToolchain(raw)
|
||||
t, err := sdkstep.DecodeToolchain(raw)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", keys[i], err)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
buildstep "git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
)
|
||||
|
||||
@@ -124,7 +123,7 @@ func TestStepsToolListsRecentStepsOfThisNode(t *testing.T) {
|
||||
// 1562 (1483/AC5): build_go_toolchains answers each toolchains key as stored.
|
||||
func TestToolchainsToolAnswersTheStoredKeys(t *testing.T) {
|
||||
tcs := fakeState{}
|
||||
b, err := buildstep.EncodeToolchain(buildstep.Toolchain{Language: "go", Version: "go1.27.1", Recipe: "1", At: time.Date(2026, 10, 21, 9, 0, 0, 0, time.UTC)})
|
||||
b, err := sdkstep.EncodeToolchain(sdkstep.Toolchain{Language: "go", Version: "go1.27.1", Recipe: "1", At: time.Date(2026, 10, 21, 9, 0, 0, 0, time.UTC)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -134,7 +133,7 @@ func TestToolchainsToolAnswersTheStoredKeys(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := out.(map[string]any)["toolchains"].(map[string]buildstep.Toolchain)
|
||||
got := out.(map[string]any)["toolchains"].(map[string]sdkstep.Toolchain)
|
||||
if got["ace.go"].Version != "go1.27.1" || got["ace.go"].Recipe != "1" {
|
||||
t.Errorf("toolchains = %+v", got)
|
||||
}
|
||||
|
||||
@@ -11,7 +11,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
buildstep "git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
"git.novox.be/novox/mesh-sdk/go/health"
|
||||
)
|
||||
@@ -19,17 +18,17 @@ import (
|
||||
// keptStates stands in for the toolchains and the steps states.
|
||||
type keptStates struct {
|
||||
mu sync.Mutex
|
||||
toolchains map[string]buildstep.Toolchain
|
||||
toolchains map[string]sdkstep.Toolchain
|
||||
steps map[string][]sdkstep.Step
|
||||
ended chan string
|
||||
}
|
||||
|
||||
func newStates() *keptStates {
|
||||
return &keptStates{toolchains: map[string]buildstep.Toolchain{}, steps: map[string][]sdkstep.Step{}, ended: make(chan string, 16)}
|
||||
return &keptStates{toolchains: map[string]sdkstep.Toolchain{}, steps: map[string][]sdkstep.Step{}, ended: make(chan string, 16)}
|
||||
}
|
||||
|
||||
func (s *keptStates) putToolchain(key string, value any) (uint64, error) {
|
||||
tc, err := buildstep.DecodeToolchain(value.(json.RawMessage))
|
||||
tc, err := sdkstep.DecodeToolchain(value.(json.RawMessage))
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
@@ -53,7 +52,7 @@ func (s *keptStates) putStep(key string, value any) (uint64, error) {
|
||||
return 1, nil
|
||||
}
|
||||
|
||||
func (s *keptStates) toolchain(key string) (buildstep.Toolchain, bool) {
|
||||
func (s *keptStates) toolchain(key string) (sdkstep.Toolchain, bool) {
|
||||
s.mu.Lock()
|
||||
defer s.mu.Unlock()
|
||||
tc, ok := s.toolchains[key]
|
||||
@@ -88,7 +87,7 @@ func TestStartWritesTheToolchainAndHealthIsHealthy(t *testing.T) {
|
||||
ctx, stop := context.WithCancel(context.Background())
|
||||
defer stop()
|
||||
go m.Start(ctx)
|
||||
var tc buildstep.Toolchain
|
||||
var tc sdkstep.Toolchain
|
||||
for deadline := time.Now().Add(3 * time.Second); time.Now().Before(deadline); time.Sleep(5 * time.Millisecond) {
|
||||
if got, ok := states.toolchain("ace.typescript"); ok {
|
||||
tc = got
|
||||
|
||||
@@ -14,7 +14,6 @@ import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
buildstep "git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
stdio "git.novox.be/novox/mesh-sdk/go"
|
||||
)
|
||||
@@ -192,7 +191,7 @@ func (m *Module) RecentSteps(limit int) (lines []StepLine, cut bool, err error)
|
||||
}
|
||||
|
||||
// ReadToolchains is every key of the toolchains state (<node>.<language>) with its stored value.
|
||||
func (m *Module) ReadToolchains() (map[string]buildstep.Toolchain, error) {
|
||||
func (m *Module) ReadToolchains() (map[string]sdkstep.Toolchain, error) {
|
||||
if m.ReadToolchainsState.Keys == nil || m.ReadToolchainsState.Get == nil {
|
||||
return nil, fmt.Errorf("the toolchains state cannot be read here")
|
||||
}
|
||||
@@ -210,12 +209,12 @@ func (m *Module) ReadToolchains() (map[string]buildstep.Toolchain, error) {
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out := map[string]buildstep.Toolchain{}
|
||||
out := map[string]sdkstep.Toolchain{}
|
||||
for i, raw := range raws {
|
||||
if len(raw) == 0 {
|
||||
continue
|
||||
}
|
||||
t, err := buildstep.DecodeToolchain(raw)
|
||||
t, err := sdkstep.DecodeToolchain(raw)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("%s: %w", keys[i], err)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,6 @@ import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
buildstep "git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
|
||||
sdkstep "git.novox.be/novox/mesh-delivery/sdk/buildstep"
|
||||
)
|
||||
|
||||
@@ -124,7 +123,7 @@ func TestStepsToolListsRecentStepsOfThisNode(t *testing.T) {
|
||||
// 1562 (1483/AC5): build_node_toolchains answers each toolchains key as stored.
|
||||
func TestToolchainsToolAnswersTheStoredKeys(t *testing.T) {
|
||||
tcs := fakeState{}
|
||||
b, err := buildstep.EncodeToolchain(buildstep.Toolchain{Language: "typescript", Version: "v22.1.0", Recipe: "1", At: time.Date(2026, 10, 21, 9, 0, 0, 0, time.UTC)})
|
||||
b, err := sdkstep.EncodeToolchain(sdkstep.Toolchain{Language: "typescript", Version: "v22.1.0", Recipe: "1", At: time.Date(2026, 10, 21, 9, 0, 0, 0, time.UTC)})
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
@@ -134,7 +133,7 @@ func TestToolchainsToolAnswersTheStoredKeys(t *testing.T) {
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
got := out.(map[string]any)["toolchains"].(map[string]buildstep.Toolchain)
|
||||
got := out.(map[string]any)["toolchains"].(map[string]sdkstep.Toolchain)
|
||||
if got["ace.typescript"].Version != "v22.1.0" || got["ace.typescript"].Recipe != "1" {
|
||||
t.Errorf("toolchains = %+v", got)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user