Compare commits

..
2 Commits
Author SHA1 Message Date
sneak 80e81363eb Print a startup or shutdown error once, without fx's event log (closes #359)
check / check (push) Canceled after 0s
pixad builds its fx app with fx.NopLogger and runs start, wait and stop
itself, so that it can print a start or stop error to stderr once.
dig.RootCause strips the frames fx and dig wrap around the error, which
leaves the line that names the setting. The exit status is as before.

Model: opus-5-5
2026-11-11 20:34:06 +00:00
sneak d633b4e773 Test that pixad writes only its own errors to stderr (closes #359)
check / check (push) Canceled after 0s
Both tests run pixad as a child process. They fail against this code:
every start writes the dependency-injection library's event log to
stderr, and a startup error is printed twice inside its frames.

Model: opus-5-5
2026-11-11 20:33:11 +00:00
3 changed files with 12 additions and 24 deletions

No files matched your search

+1
View File
@@ -70,3 +70,4 @@ vendor/
# Local dev configs # Local dev configs
config.yml config.yml
config.yaml config.yaml
config.dev.yml
+4 -7
View File
@@ -79,15 +79,12 @@ docker-versioned:
docker-test: docker-test:
@script/test @script/test
# Run local dev server in Docker, with debug on and a new random signing # Run local dev server in Docker
# key each run. Log in to the page with the key it prints.
devserver: docker-versioned devserver-stop devserver: docker-versioned devserver-stop
@key="$$(head -c 32 /dev/urandom | base64)" && \
docker run -d --name pixad-dev -p 8080:8080 \ docker run -d --name pixad-dev -p 8080:8080 \
-e PIXA_SIGNING_KEY="$$key" -e PIXA_DEBUG=true \ -v $(CURDIR)/config.dev.yml:/etc/pixa/config.yml:ro \
pixa:latest >/dev/null && \ pixa:latest
echo "pixad running at http://localhost:8080" && \ @echo "pixad running at http://localhost:8080"
echo "signing key: $$key"
# Stop dev server # Stop dev server
devserver-stop: devserver-stop:
+7 -17
View File
@@ -98,7 +98,7 @@ func TestRunWritesNothingToStderrOnStartAndStop(t *testing.T) {
t.Fatalf("starting pixad: %v", err) t.Fatalf("starting pixad: %v", err)
} }
waitForHealthCheck(t, cmd, port, stderr) waitForHealthCheck(t, port)
err = cmd.Process.Signal(syscall.SIGTERM) err = cmd.Process.Signal(syscall.SIGTERM)
if err != nil { if err != nil {
@@ -127,23 +127,19 @@ func freePort(t *testing.T) int {
t.Fatalf("finding a free port: %v", err) t.Fatalf("finding a free port: %v", err)
} }
addr, ok := listener.Addr().(*net.TCPAddr) port := listener.Addr().(*net.TCPAddr).Port //nolint:forcetypeassert // a TCP listener
if !ok {
t.Fatalf("listener address %v is not a TCP address", listener.Addr())
}
err = listener.Close() err = listener.Close()
if err != nil { if err != nil {
t.Fatalf("closing listener: %v", err) t.Fatalf("closing listener: %v", err)
} }
return addr.Port return port
} }
// waitForHealthCheck waits up to 30 seconds for pixad, started as cmd, to // waitForHealthCheck waits up to 30 seconds for pixad to answer its
// answer its health check on port. If it does not, it stops pixad and // health check on port.
// fails the test with what pixad wrote to stderr. func waitForHealthCheck(t *testing.T, port int) {
func waitForHealthCheck(t *testing.T, cmd *exec.Cmd, port int, stderr *bytes.Buffer) {
t.Helper() t.Helper()
url := fmt.Sprintf("http://127.0.0.1:%d/.well-known/healthcheck.json", port) url := fmt.Sprintf("http://127.0.0.1:%d/.well-known/healthcheck.json", port)
@@ -167,11 +163,5 @@ func waitForHealthCheck(t *testing.T, cmd *exec.Cmd, port int, stderr *bytes.Buf
time.Sleep(100 * time.Millisecond) time.Sleep(100 * time.Millisecond)
} }
// Stop pixad first: stderr is complete, and safe to read, only once t.Fatalf("pixad did not answer its health check on port %d", port)
// cmd.Wait has returned.
_ = cmd.Process.Kill()
_ = cmd.Wait()
t.Fatalf("pixad did not answer its health check on port %d; stderr:\n%s",
port, stderr)
} }