CAT-BN2: mesh-build-node regenerates a contracts module's TypeScript and names each file out of step
The unit level fails on one, a module with no tests of its own too; a build ask answers them in its out-of-step through buildstep's compare (lead's ruling on A2k finding 1). Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
This commit is contained in:
@@ -2,6 +2,7 @@ package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
"git.novox.be/novox/mesh-catalog/modules/mesh-build-go/buildstep"
|
||||
@@ -29,6 +30,7 @@ func (m *Module) askSteps(steps []StepTool) buildstep.AskSteps {
|
||||
}
|
||||
return buildstep.AskSteps{
|
||||
Fetch: byName["build_node_fetch"], Build: byName["build_node_build"], Test: byName["build_node_test"],
|
||||
Compare: buildstep.CompareStep(buildstep.GeneratedRootTS, func(ws string) string { return filepath.Join(m.Work, ws, "tree") }),
|
||||
Toolchain: func(ctx context.Context) (delivery.ToolchainUsed, error) {
|
||||
installed, err := m.Probe(ctx)
|
||||
if err != nil {
|
||||
|
||||
@@ -59,6 +59,9 @@ type TestResult struct {
|
||||
// By is the build module and the SDK it was built with (sdkstep.By): the checker names it when a failure hides
|
||||
// its cause.
|
||||
By string `json:"by,omitempty"`
|
||||
// OutOfStep are the generated TypeScript files of a contracts module out of step with the seat generator (CAT-BN2,
|
||||
// buildstep.OutOfStep): the unit level fails on any, Why naming each. Absent when none is.
|
||||
OutOfStep []string `json:"out-of-step,omitempty"`
|
||||
}
|
||||
|
||||
// Failure is the SDK's failure contract (sdkstep.Failure, issue 1901): a failing test of the test script, read from
|
||||
@@ -89,6 +92,29 @@ func (m *Module) testTool() StepTool {
|
||||
}
|
||||
|
||||
func (m *Module) test(ctx context.Context, args map[string]any) (any, error) {
|
||||
res, err := m.testLevel(ctx, args)
|
||||
if err != nil || res.Level != "unit" {
|
||||
return res, err
|
||||
}
|
||||
// CAT-BN2: a contracts module's generated TypeScript is regenerated and compared; a file out of step fails the level.
|
||||
_, dir, err := m.moduleDirOf(res.Workspace, res.Module)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if res.OutOfStep, err = buildstep.OutOfStep(dir, buildstep.GeneratedRootTS); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if len(res.OutOfStep) > 0 {
|
||||
why := "generated files out of step with the seat generator (regenerate them): " + strings.Join(res.OutOfStep, ", ")
|
||||
if res.Why != "" && !res.NoTests {
|
||||
why = res.Why + "; " + why
|
||||
}
|
||||
res.Passed, res.NoTests, res.Why = false, false, why
|
||||
}
|
||||
return res, nil
|
||||
}
|
||||
|
||||
func (m *Module) testLevel(ctx context.Context, args map[string]any) (*TestResult, error) {
|
||||
workspace, _ := args["workspace"].(string)
|
||||
module, _ := args["module"].(string)
|
||||
level, _ := args["level"].(string)
|
||||
|
||||
@@ -79,6 +79,29 @@ func TestAPackageWithNeitherScriptNorTypeScriptHasNoTests(t *testing.T) {
|
||||
if len(f.calls) != 0 {
|
||||
t.Errorf("%d commands ran for a package with no tests", len(f.calls))
|
||||
}
|
||||
// CAT-BN2: a contracts module (a package artifact naming generated-from) with no tests of its own still fails its
|
||||
// unit level on a generated TypeScript file out of step with the seat generator, each named; its Go files are
|
||||
// mesh-build-go's to compare.
|
||||
m, _, work = newMachine(t)
|
||||
workspaceWith(t, work, map[string]string{
|
||||
"module.json": `{"module":"c","build":{"artifacts":[{"name":"ts","kind":"package","language":"typescript","paths":["ts"],"generated-from":"."}]}}`,
|
||||
"seats/index.json": `{"format":1,"seats":["one-store"]}`,
|
||||
"seats/one-store/seat.json": `{"format":1,"seat":"one-store","scope":"mesh","grain":"seat-list","decision":"ADR 1","verbs":[{"name":"query","input":{"type":"object"}}]}`,
|
||||
"go/go.mod": "module example.org/c/go\n", "go/stray.go": "package stray\n",
|
||||
"ts/package.json": `{"name":"@example/c"}`, "ts/stray.ts.txt": "not written by the generator\n",
|
||||
})
|
||||
out, err := m.test(context.Background(), testArgs("unit"))
|
||||
r := out.(*TestResult)
|
||||
stray := false
|
||||
for _, p := range r.OutOfStep {
|
||||
stray = stray || p == "ts/stray.ts.txt"
|
||||
if !strings.HasPrefix(p, "ts/") {
|
||||
t.Errorf("%s is not under the TypeScript root", p)
|
||||
}
|
||||
}
|
||||
if err != nil || r.Passed || r.NoTests || !stray || !strings.Contains(r.Why, "ts/stray.ts.txt") {
|
||||
t.Errorf("a contracts module out of step = %+v, %v", r, err)
|
||||
}
|
||||
}
|
||||
|
||||
// 1491/AC4: with test:integration present the integration level runs it, and reports the setup (the type-check) and
|
||||
|
||||
Reference in New Issue
Block a user