Compare commits

..
3 Commits
Author SHA1 Message Date
sneak f416e73611 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 21:00:28 +00:00
sneak 8aaf6dc794 Test that pixad writes only its own errors to stderr (closes #359)
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 21:00:24 +00:00
clawbot 0de6972c2d Run make devserver from environment variables, not a config file (closes #360)
check / check (push) Canceled after 0s
The target mounted config.dev.yml, which nothing creates, so Docker made
a directory in its place and pixad exited. It now passes a new random
PIXA_SIGNING_KEY each run, printed so the developer can log in, and
PIXA_DEBUG=true so the login form works over plain HTTP. The unused
.gitignore entry for config.dev.yml is removed.

Model: opus-5-5
2026-11-11 21:55:58 +01:00
3 changed files with 24 additions and 12 deletions

No files matched your search

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