Pass a check's changed paths in a file so a change of thousands of files can start (issue 1247)
One environment string over 128 KiB made the container fail to start with no words; the gate reads --changed-file, and a command that cannot start now says its error.
This commit is contained in:
@@ -260,9 +260,12 @@ const (
|
||||
EnvTestBus = "MESH_TEST_NATS"
|
||||
EnvRepository = "MESH_CHECK_REPOSITORY"
|
||||
EnvChanged = "MESH_CHECK_CHANGED"
|
||||
EnvVerdict = "MESH_CHECK_VERDICT"
|
||||
EnvBeside = "MESH_CHECK_BESIDE"
|
||||
EnvModules = "MESH_CHECK_MODULES"
|
||||
// EnvChangedFile names a file holding every changed path, one per line, in the order given: the whole
|
||||
// list however long, which one environment string cannot carry (novox/hq issue 1247).
|
||||
EnvChangedFile = "MESH_CHECK_CHANGED_FILE"
|
||||
EnvVerdict = "MESH_CHECK_VERDICT"
|
||||
EnvBeside = "MESH_CHECK_BESIDE"
|
||||
EnvModules = "MESH_CHECK_MODULES"
|
||||
// EnvGroup is a delivery group's other heads, as JSON, for the gate (novox/hq ADR 0239); empty for a
|
||||
// pull request checked alone.
|
||||
EnvGroup = "MESH_CHECK_GROUP"
|
||||
@@ -719,12 +722,17 @@ func Check(ctx context.Context, run Runner, spec CheckSpec, workspace, registry
|
||||
judged.JudgeFrom = siblingJudge.From
|
||||
judged.Validator = siblingJudge.Validator
|
||||
verdictFile := filepath.Join(root, "verdict.json")
|
||||
changedEnv, err := changedEnvironment(root, paths, func(line string) { fmt.Fprintln(&out, line) })
|
||||
if err != nil {
|
||||
return CheckVerdict{}, err
|
||||
}
|
||||
env := []string{EnvFacts + "=" + factsFile, EnvGate + "=" + gate, EnvGateStore + "=" + storeURL,
|
||||
EnvTestStore + "=" + storeURL, EnvTestBus + "=nats://" + bus, EnvRepository + "=" + spec.Owner + "/" + spec.Repo,
|
||||
EnvChanged + "=" + strings.Join(paths, ","), EnvBeside + "=" + root,
|
||||
EnvBeside + "=" + root,
|
||||
EnvModules + "=" + strings.Join(append(append([]string{}, spec.Modules...), spec.New...), ","),
|
||||
EnvGroup + "=" + groupFile,
|
||||
"GOCACHE=" + filepath.Join(workspace, "go-cache"), "GOMODCACHE=" + filepath.Join(workspace, "go-modules")}
|
||||
env = append(env, changedEnv...)
|
||||
env = append(env, selection(spec)...)
|
||||
|
||||
v := CheckVerdict{}
|
||||
@@ -919,6 +927,10 @@ func ownCheck(ctx context.Context, spec CheckSpec, parts []ScriptPart, tree stri
|
||||
if said == "" {
|
||||
said = whatFailed(own.String())
|
||||
}
|
||||
if said == "" {
|
||||
// A command that could not start says nothing itself (novox/hq issue 1247): its error does.
|
||||
said = err.Error()
|
||||
}
|
||||
return &Layer{Verdict: "fail", Summary: passedSoFar(ran) + "its " + part.Script + " failed: " + said,
|
||||
Failed: picked.String()}
|
||||
}
|
||||
@@ -1084,7 +1096,7 @@ func gateLayer(ctx context.Context, spec CheckSpec, tree, root, gate, verdictFil
|
||||
// 2. Every machine composed with the change.
|
||||
if err := running(inToolchain(tree, append(env, EnvVerdict+"="+verdictFile), "sh", "-c",
|
||||
`"$MESH_GATE" merge-gate --facts "$MESH_FACTS" --store "$MESH_GATE_POSTGRES" `+
|
||||
`--repository "$MESH_CHECK_REPOSITORY" --tree . --changed "$MESH_CHECK_CHANGED" `+
|
||||
`--repository "$MESH_CHECK_REPOSITORY" --tree . --changed-file "$MESH_CHECK_CHANGED_FILE" `+
|
||||
`${MESH_CHECK_GROUP:+--group "$MESH_CHECK_GROUP"} --json > "$MESH_CHECK_VERDICT"`)); err != nil {
|
||||
if ctx.Err() != nil {
|
||||
return "error", "the check was ended during the merge gate"
|
||||
@@ -1895,3 +1907,42 @@ func treeAt(ctx context.Context, run Runner, dir string) string {
|
||||
}
|
||||
return strings.TrimSpace(out)
|
||||
}
|
||||
|
||||
// changedEnvLimit is how long MESH_CHECK_CHANGED may be: well under the kernel's 128 KiB for one environment
|
||||
// string, over which the container cannot start (novox/hq issue 1247).
|
||||
const changedEnvLimit = 64 << 10
|
||||
|
||||
// changedEnvironment is the changed paths as a check reads them: every path, one per line, in a file beside the
|
||||
// check's checkouts that MESH_CHECK_CHANGED_FILE names; and MESH_CHECK_CHANGED, the same comma-joined while
|
||||
// that is under changedEnvLimit, otherwise each path's first two directories (a top-level file as itself) once
|
||||
// each, said in the check's output.
|
||||
func changedEnvironment(root string, paths []string, say func(string)) ([]string, error) {
|
||||
file := filepath.Join(root, "changed.txt")
|
||||
body := ""
|
||||
if len(paths) > 0 {
|
||||
body = strings.Join(paths, "\n") + "\n"
|
||||
}
|
||||
if err := os.WriteFile(file, []byte(body), 0o644); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
joined := strings.Join(paths, ",")
|
||||
if len(joined) >= changedEnvLimit {
|
||||
var short []string
|
||||
seen := map[string]bool{}
|
||||
for _, p := range paths {
|
||||
parts := strings.SplitN(p, "/", 3)
|
||||
d := p
|
||||
if len(parts) == 3 {
|
||||
d = parts[0] + "/" + parts[1] + "/"
|
||||
}
|
||||
if !seen[d] {
|
||||
seen[d] = true
|
||||
short = append(short, d)
|
||||
}
|
||||
}
|
||||
joined = strings.Join(short, ",")
|
||||
say(fmt.Sprintf("--- %d changed paths are too long for one environment string: %s holds all of them, one per "+
|
||||
"line, and %s only each path's first two directories", len(paths), EnvChangedFile, EnvChanged))
|
||||
}
|
||||
return []string{EnvChanged + "=" + joined, EnvChangedFile + "=" + file}, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user