A gate judges its own send and the build it sent, and never puts the controller back behind its store (hq issue 352)
On 2026-10-09 a release's gate on the control node read the machine's
report against a newer send another plan had just made there, failed
three builds the machine had reported healthy, and put them back on
every machine to a controller older than the store's schema; that
controller then passed the newer plan's gate from its own health.
- A gate keeps what its send carried (digest, sequence) and reads the
report against it; a report on the last send is on it too.
- A gate judges only the build the machine was last sent: another build
there supersedes the judging — no verdict, nothing put back.
- A controller is told its build (MESH_CONTROLLER_VERSION, ${version}
in a process's env) and records how far it reads the store's schema;
a put-back to a build that reaches less, or never said, is refused
and the current build kept, said as urgent.
- A release's open gate holds other sends of its modules there, and a
plan's own first send waits on it.
This commit is contained in:
@@ -173,11 +173,7 @@ func (m Manifest) Resolve(built []Built) (Manifest, error) {
|
||||
// had — so re-composing a declaration moves nothing, where a commit would move the
|
||||
// path of an identical binary and recreate everything that reads it.
|
||||
for key, value := range filled {
|
||||
text, isText := value.(string)
|
||||
if !isText || !strings.Contains(text, versionRef) {
|
||||
continue
|
||||
}
|
||||
filled[key] = strings.ReplaceAll(text, versionRef, versionOf(artifact.Digest))
|
||||
filled[key] = withVersion(value, versionOf(artifact.Digest))
|
||||
}
|
||||
default:
|
||||
return Manifest{}, fmt.Errorf("%s: %q is a %q, and an artifact is %q, %q, %q or %q",
|
||||
@@ -189,6 +185,31 @@ func (m Manifest) Resolve(built []Built) (Manifest, error) {
|
||||
return out, nil
|
||||
}
|
||||
|
||||
// withVersion is a resource's value with `${version}` filled: in a string, and in each string of a map —
|
||||
// a process's env, where the controller is told which build it is (novox/hq issue 352). Anything else is
|
||||
// left as it is.
|
||||
func withVersion(value any, version string) any {
|
||||
switch v := value.(type) {
|
||||
case string:
|
||||
if strings.Contains(v, versionRef) {
|
||||
return strings.ReplaceAll(v, versionRef, version)
|
||||
}
|
||||
case map[string]any:
|
||||
out := make(map[string]any, len(v))
|
||||
for k, x := range v {
|
||||
out[k] = withVersion(x, version)
|
||||
}
|
||||
return out
|
||||
case map[string]string:
|
||||
out := make(map[string]string, len(v))
|
||||
for k, x := range v {
|
||||
out[k] = strings.ReplaceAll(x, versionRef, version)
|
||||
}
|
||||
return out
|
||||
}
|
||||
return value
|
||||
}
|
||||
|
||||
// checkBuild is the manifest's own account of what it builds.
|
||||
func (b *Build) problems(module string) []string {
|
||||
if b == nil {
|
||||
|
||||
Reference in New Issue
Block a user