docs: publish Tend Compose continuity evidence
Export the reviewed allowlisted snapshot from private source commit 07c1655921f21ee5e4fc4d85639d199e8867b17d. This records the Docker Compose activation, schema-compatible rollback, and stateful migration resource findings from Observatory Preview 19 dogfooding. AI-Assisted: OpenAI Codex Signed-off-by: Cole Speelman <crspeelman@gmail.com>
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
// SPDX-License-Identifier: AGPL-3.0-only
|
||||
|
||||
package process
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"sort"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const maxOutput = 4 << 20
|
||||
|
||||
type Runner interface {
|
||||
Run(ctx context.Context, dir string, env map[string]string, name string, args ...string) ([]byte, error)
|
||||
}
|
||||
|
||||
type ExecRunner struct{}
|
||||
|
||||
func (ExecRunner) Run(ctx context.Context, dir string, env map[string]string, name string, args ...string) ([]byte, error) {
|
||||
cmd := exec.CommandContext(ctx, name, args...)
|
||||
cmd.Dir = dir
|
||||
cmd.Env = mergeEnv(os.Environ(), env)
|
||||
var output limitedBuffer
|
||||
cmd.Stdout = &output
|
||||
cmd.Stderr = &output
|
||||
err := cmd.Run()
|
||||
if err != nil {
|
||||
return output.Bytes(), fmt.Errorf("%s failed: %w: %s", name, err, strings.TrimSpace(output.String()))
|
||||
}
|
||||
return output.Bytes(), nil
|
||||
}
|
||||
|
||||
type limitedBuffer struct{ bytes.Buffer }
|
||||
|
||||
func (b *limitedBuffer) Write(p []byte) (int, error) {
|
||||
written := len(p)
|
||||
remaining := maxOutput - b.Len()
|
||||
if remaining > 0 {
|
||||
if len(p) > remaining {
|
||||
p = p[:remaining]
|
||||
}
|
||||
_, _ = b.Buffer.Write(p)
|
||||
}
|
||||
return written, nil
|
||||
}
|
||||
|
||||
func mergeEnv(base []string, extra map[string]string) []string {
|
||||
values := make(map[string]string, len(base)+len(extra))
|
||||
for _, pair := range base {
|
||||
key, value, ok := strings.Cut(pair, "=")
|
||||
if ok {
|
||||
values[key] = value
|
||||
}
|
||||
}
|
||||
for key, value := range extra {
|
||||
values[key] = value
|
||||
}
|
||||
keys := make([]string, 0, len(values))
|
||||
for key := range values {
|
||||
keys = append(keys, key)
|
||||
}
|
||||
sort.Strings(keys)
|
||||
out := make([]string, 0, len(keys))
|
||||
for _, key := range keys {
|
||||
out = append(out, key+"="+values[key])
|
||||
}
|
||||
return out
|
||||
}
|
||||
Reference in New Issue
Block a user