fix(e2e): wait for panel /healthz before setup (v1.0.0 gate)
test / test (push) Has been cancelled
release / prepare (push) Has been cancelled
release / build (amd64, ubuntu-latest) (push) Has been cancelled
release / build (arm64, ubuntu-24.04-arm) (push) Has been cancelled
release / merge (push) Has been cancelled

Supervisor RUNNING is not enough: the setup-token file is written before
ListenAndServe, and Docker host-port publish can lag. Poll /healthz first,
and stop ordered TestE2E steps after a failure so a nil panel cannot panic
and mask the real error.

Co-Authored-By: Composer <noreply@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
mixeme
2026-08-09 01:08:32 +03:00
parent fa9d2016cc
commit 3f0e7dc131
3 changed files with 49 additions and 12 deletions
+25 -12
View File
@@ -87,13 +87,26 @@ type scenario struct {
func TestE2E(t *testing.T) {
sc := &scenario{}
t.Run("startup_processes_running", func(t *testing.T) {
// Ordered scenario: each step needs state from earlier ones. A failed
// subtest must stop the rest — otherwise sc.panel stays nil and the next
// step panics, masking the real failure (as seen on the v1.0.0 release CI).
run := func(name string, fn func(*testing.T)) {
if t.Failed() {
return
}
t.Run(name, fn)
}
run("startup_processes_running", func(t *testing.T) {
if err := checkSupervisorProcesses(h); err != nil {
t.Fatal(err)
}
if err := waitForPanelReady(); err != nil {
t.Fatal(err)
}
})
t.Run("setup_and_login", func(t *testing.T) {
run("setup_and_login", func(t *testing.T) {
token, err := readSetupToken(h.stageDir)
if err != nil {
t.Fatalf("read setup token: %v", err)
@@ -111,7 +124,7 @@ func TestE2E(t *testing.T) {
sc.panel = p
})
t.Run("add_domain_and_publish_dkim", func(t *testing.T) {
run("add_domain_and_publish_dkim", func(t *testing.T) {
id, err := sc.panel.addDomain(senderDomain)
if err != nil {
t.Fatalf("add domain: %v", err)
@@ -137,7 +150,7 @@ func TestE2E(t *testing.T) {
sc.zoneRecords = records
})
t.Run("add_application", func(t *testing.T) {
run("add_application", func(t *testing.T) {
login, password, err := sc.panel.addApplication(sc.domainID, "app1", "wildcard", "")
if err != nil {
t.Fatalf("add application: %v", err)
@@ -145,7 +158,7 @@ func TestE2E(t *testing.T) {
sc.appLogin, sc.appPassword = login, password
})
t.Run("send_verify_dkim_and_status", func(t *testing.T) {
run("send_verify_dkim_and_status", func(t *testing.T) {
token := uniqueToken("positive")
res := attemptSend(sendAttempt{
authLogin: sc.appLogin, authPassword: sc.appPassword,
@@ -179,25 +192,25 @@ func TestE2E(t *testing.T) {
}
})
t.Run("negative_level2_ratelimit_via_panel", func(t *testing.T) {
run("negative_level2_ratelimit_via_panel", func(t *testing.T) {
testLevel2RateLimit(t, sc)
})
t.Run("negative_sender_login_mismatch", func(t *testing.T) {
run("negative_sender_login_mismatch", func(t *testing.T) {
testSenderLoginMismatch(t, sc)
})
t.Run("negative_no_auth_rejected", func(t *testing.T) {
run("negative_no_auth_rejected", func(t *testing.T) {
testNoAuthRejected(t, sc)
})
t.Run("negative_foreign_relay_rejected", func(t *testing.T) {
run("negative_foreign_relay_rejected", func(t *testing.T) {
testForeignRelayRejected(t, sc)
})
t.Run("negative_journal_milter_fail_open", func(t *testing.T) {
run("negative_journal_milter_fail_open", func(t *testing.T) {
testJournalMilterFailOpen(t, sc)
})
t.Run("session_survives_restart", func(t *testing.T) {
run("session_survives_restart", func(t *testing.T) {
testSessionSurvivesRestart(t, sc)
})
t.Run("negative_level1_ratelimit", func(t *testing.T) {
run("negative_level1_ratelimit", func(t *testing.T) {
testLevel1RateLimit(t, sc)
})
}