Commit 8eea89a307

8eea89a307ad38ce5f8d5582906379040cf75983

parent: 0c16f309f5

Verified · cmc ci/build: success ci/test: success ci/vuln: success

cmc <hello@cleberg.net> · 2026-09-03 01:03 UTC

e2e: an instance is ready on every listener before a test starts

startInstanceWith returned once the SSH port answered. The HTTP and
git listeners come up in their own goroutines, so a test whose first
act was an HTTP request could reach the port before it was bound and be
refused: TestWebSignup in build 331 and TestHealthz in build 358, both
a second into the test, both green in the next run.

The harness now waits for the SSH, HTTP and git ports alike, with the
same probe the LFS test already used for a restart.

Closes #91

Layout: unified · split

e2e/ssh_test.go +6 −13
@@ -10,7 +10,6 @@ import (
10 "path/filepath" 10 "path/filepath"
11 "strings" 11 "strings"
12 "testing" 12 "testing"
13 "time"
14) 13)
15 14
16type instance struct { 15type instance struct {
@@ -113,19 +112,13 @@ port = %d
113 inst.proc.Wait() 112 inst.proc.Wait()
114 }) 113 })
115 114
116 // Wait for the listener. 115 // Every listener, not just SSH: the HTTP and git ones come up in their
117 deadline := time.Now().Add(10 * time.Second) 116 // own goroutines, and a test whose first act is an HTTP request used
118 for { 117 // to race them and be refused.
119 conn, err := net.DialTimeout("tcp", fmt.Sprintf("127.0.0.1:%d", inst.port), 200*time.Millisecond) 118 for _, port := range []int{inst.port, inst.httpPort, inst.gitPort} {
120 if err == nil { 119 waitForPort(t, port)
121 conn.Close()
122 return inst
123 }
124 if time.Now().After(deadline) {
125 t.Fatal("gitbayd did not start listening")
126 }
127 time.Sleep(50 * time.Millisecond)
128 } 120 }
121 return inst
129} 122}
130 123
131// admin runs a gitbayd admin command against the instance's database. 124// admin runs a gitbayd admin command against the instance's database.