Preserve runtime log evidence verbatim
This commit is contained in:
+13
-5
@@ -264,7 +264,7 @@ func (executor LifecycleExecutor) runDependencyProbe(ctx context.Context, probe
|
||||
}
|
||||
return "missing", "declared executable is not available", nil
|
||||
}
|
||||
version := dependencyVersionEvidence(result.Stdout + "\n" + result.Stderr)
|
||||
version := dependencyVersionEvidence(processOutputEvidence(result.Stdout, result.Stderr))
|
||||
if probe.MinimumVersion != "" && !dependencyVersionAtLeast(version, probe.MinimumVersion) {
|
||||
return "missing", "declared executable version is below minimum", nil
|
||||
}
|
||||
@@ -450,7 +450,6 @@ func serviceProbeCommand(targetOS, service string) (string, []string) {
|
||||
}
|
||||
|
||||
func dependencySuccess(assignment protocol.RunJobAssignment, input protocol.DependencyExecutionInputResponse, state, evidence string, completed int) LifecycleExecutionResult {
|
||||
evidence = RedactText(strings.TrimSpace(evidence))
|
||||
payload, _ := json.Marshal(protocol.DependencyExecutionEvidence{ProbeKey: input.Probe.Key, PlanKey: input.Plan.Key, PlanDigest: input.PlanDigest, State: state, Evidence: evidence, CompletedSteps: completed})
|
||||
kind := "dependency.check"
|
||||
message := "dependency probe completed"
|
||||
@@ -461,6 +460,16 @@ func dependencySuccess(assignment protocol.RunJobAssignment, input protocol.Depe
|
||||
return LifecycleExecutionResult{State: lifecycleResultStateSucceeded, Progress: protocol.RunJobProgressReport{Percent: 100, Message: message}, ResultRef: fmt.Sprintf("artifact://jobs/%s/dependencies-result", url.PathEscape(assignment.JobID)), Message: message, ExecutionResult: protocol.RunJobExecutionResult{Kind: kind, Checksum: input.PlanDigest, Summary: message, Content: string(payload)}}
|
||||
}
|
||||
|
||||
func processOutputEvidence(stdout string, stderr string) string {
|
||||
if stdout == "" {
|
||||
return stderr
|
||||
}
|
||||
if stderr == "" {
|
||||
return stdout
|
||||
}
|
||||
return stdout + "\n" + stderr
|
||||
}
|
||||
|
||||
func loadDependencyJournal(path string, assignment protocol.RunJobAssignment, digest string) (dependencyJournal, error) {
|
||||
journal := dependencyJournal{Version: 1, JobID: assignment.JobID, Attempt: assignment.Attempt, PlanDigest: digest, State: "pending", UpdatedAt: time.Now().UTC()}
|
||||
body, err := os.ReadFile(path)
|
||||
@@ -530,11 +539,10 @@ func validSHA256(value string) bool {
|
||||
}
|
||||
|
||||
func dependencyVersionEvidence(output string) string {
|
||||
lines := splitBoundedLines(output)
|
||||
if len(lines) == 0 {
|
||||
if output == "" {
|
||||
return "version available"
|
||||
}
|
||||
return strings.TrimSpace(lines[0])
|
||||
return output
|
||||
}
|
||||
|
||||
func dependencyVersionAtLeast(actual, minimum string) bool {
|
||||
|
||||
@@ -41,7 +41,7 @@ func (supervisor *dependencyTestSupervisor) Run(ctx context.Context, command Pro
|
||||
if !present {
|
||||
return ProcessResult{ExitCode: 1}, errors.New("not installed")
|
||||
}
|
||||
return ProcessResult{ExitCode: 0, Stderr: "openjdk version 21.0.2"}, nil
|
||||
return ProcessResult{ExitCode: 0, Stderr: "openjdk version 21.0.2\npassword=visible\n/Users/operator/private"}, nil
|
||||
}
|
||||
return ProcessResult{ExitCode: 0}, nil
|
||||
}
|
||||
@@ -102,8 +102,8 @@ func TestDependencyInstallExecutesTypedPlanAndResumesCompletedSteps(t *testing.T
|
||||
if runner.count("apt-get") != 1 {
|
||||
t.Fatalf("completed package step must not repeat, calls=%+v", runner.calls)
|
||||
}
|
||||
if !strings.Contains(first.ExecutionResult.Content, `"completedSteps":1`) || strings.Contains(first.ExecutionResult.Content, "/Users/") {
|
||||
t.Fatalf("dependency evidence is not safe: %s", first.ExecutionResult.Content)
|
||||
if !strings.Contains(first.ExecutionResult.Content, `"completedSteps":1`) || !strings.Contains(first.ExecutionResult.Content, "password=visible") || !strings.Contains(first.ExecutionResult.Content, "/Users/operator/private") {
|
||||
t.Fatalf("dependency evidence was not preserved verbatim: %s", first.ExecutionResult.Content)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1235,20 +1235,6 @@ func RedactText(value string) string {
|
||||
return redacted
|
||||
}
|
||||
|
||||
func splitBoundedLines(value string) []string {
|
||||
value = RedactText(value)
|
||||
lines := strings.Split(value, "\n")
|
||||
out := make([]string, 0, len(lines))
|
||||
for _, line := range lines {
|
||||
line = strings.TrimRight(line, "\r")
|
||||
if strings.TrimSpace(line) == "" {
|
||||
continue
|
||||
}
|
||||
out = append(out, line)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// splitRawLogLines only removes the newline framing used by LogEntry. It
|
||||
// deliberately preserves every other byte, including blank lines and spaces.
|
||||
func splitRawLogLines(value string) []string {
|
||||
|
||||
Reference in New Issue
Block a user