The gate's module check notes a seat another module declares, which it was not given (hq issue 364)
The gate passes only the manifests a change touches, so a module that starts using the operator channel was refused for a declaration it could not see. Over every manifest it stays a refusal.
This commit is contained in:
@@ -32,6 +32,9 @@ import (
|
|||||||
// provision it wants that a manifest given here offers. An overflow is refused in the pull request
|
// provision it wants that a manifest given here offers. An overflow is refused in the pull request
|
||||||
// that introduces it — a new requirement, a lowered bound, a longer slug — instead of on the
|
// that introduces it — a new requirement, a lowered bound, a longer slug — instead of on the
|
||||||
// provider's machine when a real machine's name first meets the module's.
|
// provider's machine when a real machine's name first meets the module's.
|
||||||
|
// SomeManifestsVar, set by the merge gate, says the manifests given are only some of their repository's.
|
||||||
|
const SomeManifestsVar = "MESH_MODULE_CHECK_SOME"
|
||||||
|
|
||||||
func moduleCheck(paths []string, out io.Writer) error {
|
func moduleCheck(paths []string, out io.Writer) error {
|
||||||
return moduleCheckFor(paths, catalogue.DefaultLongestMachine, out)
|
return moduleCheckFor(paths, catalogue.DefaultLongestMachine, out)
|
||||||
}
|
}
|
||||||
@@ -85,12 +88,24 @@ func moduleCheckFor(paths []string, longestMachine int, out io.Writer) error {
|
|||||||
// Between the manifests: a seat declared twice, a use of a seat nothing declares, a claim on
|
// Between the manifests: a seat declared twice, a use of a seat nothing declares, a claim on
|
||||||
// a seat that does not exist. Run only over what parsed, because a problem inside one manifest
|
// a seat that does not exist. Run only over what parsed, because a problem inside one manifest
|
||||||
// has already been said and would be said again here in a worse form.
|
// has already been said and would be said again here in a worse form.
|
||||||
|
//
|
||||||
|
// **Over some of a repository's manifests, a seat none of them declares is a note** (novox/hq issue 364), as
|
||||||
|
// this command's own word says above: the merge gate passes only the manifests a change touches, and says so
|
||||||
|
// with SomeManifestsVar, so a module that uses or claims a seat another module declares (the operator
|
||||||
|
// channel's, a channel bench) was refused there for a manifest it was not given. Given every manifest — the
|
||||||
|
// catalogue's own check, and registration — it stays a refusal.
|
||||||
|
some := os.Getenv(SomeManifestsVar) != ""
|
||||||
problems := catalogue.CatalogueProblems(shelf)
|
problems := catalogue.CatalogueProblems(shelf)
|
||||||
sort.Strings(problems)
|
sort.Strings(problems)
|
||||||
for _, p := range problems {
|
for _, p := range problems {
|
||||||
|
if some && catalogue.IsUndeclaredSeat(p) {
|
||||||
|
fmt.Fprintf(out, "note: %s among the manifests given; registration judges it against the whole catalogue, "+
|
||||||
|
"and passing the declaring module's manifest too judges it here\n", p)
|
||||||
|
continue
|
||||||
|
}
|
||||||
fmt.Fprintln(out, p)
|
fmt.Fprintln(out, p)
|
||||||
|
failed++
|
||||||
}
|
}
|
||||||
failed += len(problems)
|
|
||||||
|
|
||||||
// Between the manifests too: an identity against the bounds of the provisions it wants, which
|
// Between the manifests too: an identity against the bounds of the provisions it wants, which
|
||||||
// only the provider's manifest states.
|
// only the provider's manifest states.
|
||||||
|
|||||||
@@ -103,3 +103,23 @@ func TestTheControllersManifestServesEveryVerbOfItsSeat(t *testing.T) {
|
|||||||
t.Fatalf("the controller's own module.json fails module check: %v\n%s", err, out.String())
|
t.Fatalf("the controller's own module.json fails module check: %v\n%s", err, out.String())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// A module that uses a seat another module declares (novox/hq issue 364): refused over the whole catalogue when the
|
||||||
|
// declarer is missing, a note when the gate says it gives only the manifests a change touches.
|
||||||
|
func TestASeatAnotherModuleDeclaresIsANoteOverSomeManifests(t *testing.T) {
|
||||||
|
dir := t.TempDir()
|
||||||
|
user := filepath.Join(dir, "user.json")
|
||||||
|
os.WriteFile(user, []byte(`{"module":"asker","version":"1","uses":["operator-channel"]}`), 0o600)
|
||||||
|
var out bytes.Buffer
|
||||||
|
if err := moduleCheck([]string{user}, &out); err == nil {
|
||||||
|
t.Fatalf("a use of a seat nothing given declares passed the whole-catalogue check:\n%s", out.String())
|
||||||
|
}
|
||||||
|
t.Setenv(SomeManifestsVar, "1")
|
||||||
|
out.Reset()
|
||||||
|
if err := moduleCheck([]string{user}, &out); err != nil {
|
||||||
|
t.Fatalf("over some manifests the use was refused:\n%s", out.String())
|
||||||
|
}
|
||||||
|
if !strings.Contains(out.String(), "note: asker uses the seat \"operator-channel\"") {
|
||||||
|
t.Fatalf("the note was not said:\n%s", out.String())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -543,6 +543,11 @@ func passedSoFar(ran []string) string {
|
|||||||
return strings.Join(ran, ", ") + " passed; "
|
return strings.Join(ran, ", ") + " passed; "
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SomeManifestsEnv tells the judge's module check that the manifests it is given are only those a change touches,
|
||||||
|
// so a seat another module of the repository declares is a note there, not a refusal (novox/hq issue 364). A judge
|
||||||
|
// that predates it reads nothing of it and refuses as before.
|
||||||
|
const SomeManifestsEnv = "MESH_MODULE_CHECK_SOME=1"
|
||||||
|
|
||||||
// gateLayer runs the gate: the touched manifests through `module check`, every machine composed with the
|
// gateLayer runs the gate: the touched manifests through `module check`, every machine composed with the
|
||||||
// change, and the replays of what the mesh runs. It answers the gate's verdict and summary.
|
// change, and the replays of what the mesh runs. It answers the gate's verdict and summary.
|
||||||
func gateLayer(ctx context.Context, spec CheckSpec, tree, root, gate, verdictFile string, env []string,
|
func gateLayer(ctx context.Context, spec CheckSpec, tree, root, gate, verdictFile string, env []string,
|
||||||
@@ -562,7 +567,7 @@ func gateLayer(ctx context.Context, spec CheckSpec, tree, root, gate, verdictFil
|
|||||||
checked := func(dir string) (string, error) {
|
checked := func(dir string) (string, error) {
|
||||||
var own tail
|
var own tail
|
||||||
cmd := exec.CommandContext(ctx, "docker", LabelledArgs("docker",
|
cmd := exec.CommandContext(ctx, "docker", LabelledArgs("docker",
|
||||||
inToolchain(dir, env, append([]string{gate, "module", "check"}, manifests...)...), spec.ID)...)
|
inToolchain(dir, append(append([]string{}, env...), SomeManifestsEnv), append([]string{gate, "module", "check"}, manifests...)...), spec.ID)...)
|
||||||
inItsOwnGroup(cmd)
|
inItsOwnGroup(cmd)
|
||||||
w := io.MultiWriter(out, &own)
|
w := io.MultiWriter(out, &own)
|
||||||
cmd.Stdout, cmd.Stderr = w, w
|
cmd.Stdout, cmd.Stderr = w, w
|
||||||
|
|||||||
@@ -230,6 +230,14 @@ type Shelf map[string]Manifest
|
|||||||
//
|
//
|
||||||
// Run at registration, which is the last moment the mesh can still refuse: after it, a caller is
|
// Run at registration, which is the last moment the mesh can still refuse: after it, a caller is
|
||||||
// bound to a seat and a refusal is an outage rather than a conversation.
|
// bound to a seat and a refusal is an outage rather than a conversation.
|
||||||
|
// UndeclaredSeat ends the problem of a `uses` or a claim naming a seat no manifest given declares: over the whole
|
||||||
|
// catalogue (registration, the catalogue's own check) a refusal, and over some manifests alone a seat whose
|
||||||
|
// declaring module was not given (novox/hq issue 364).
|
||||||
|
const UndeclaredSeat = "which no module declares and the mesh does not define"
|
||||||
|
|
||||||
|
// IsUndeclaredSeat says whether a problem CatalogueProblems gave is a seat no manifest given declares.
|
||||||
|
func IsUndeclaredSeat(problem string) bool { return strings.HasSuffix(problem, UndeclaredSeat) }
|
||||||
|
|
||||||
func CatalogueProblems(shelf Shelf) []string {
|
func CatalogueProblems(shelf Shelf) []string {
|
||||||
var problems []string
|
var problems []string
|
||||||
|
|
||||||
@@ -282,7 +290,7 @@ func CatalogueProblems(shelf Shelf) []string {
|
|||||||
for _, u := range m.Uses {
|
for _, u := range m.Uses {
|
||||||
if !exists(u) {
|
if !exists(u) {
|
||||||
problems = append(problems, fmt.Sprintf(
|
problems = append(problems, fmt.Sprintf(
|
||||||
"%s uses the seat %q, which no module declares and the mesh does not define",
|
"%s uses the seat %q, "+UndeclaredSeat,
|
||||||
module, u))
|
module, u))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,7 +298,7 @@ func CatalogueProblems(shelf Shelf) []string {
|
|||||||
for _, c := range m.Claims {
|
for _, c := range m.Claims {
|
||||||
if !exists(c.Name) {
|
if !exists(c.Name) {
|
||||||
problems = append(problems, fmt.Sprintf(
|
problems = append(problems, fmt.Sprintf(
|
||||||
"%s claims the seat %q, which no module declares and the mesh does not define",
|
"%s claims the seat %q, "+UndeclaredSeat,
|
||||||
module, c.Name))
|
module, c.Name))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user