From d5fe1fa88d243d016d76fad528266439819bb163 Mon Sep 17 00:00:00 2001 From: Rogee Date: Fri, 9 Oct 2026 11:58:20 +0800 Subject: [PATCH] Report only the latest deployment probe request outcome --- deploys/production/probe.go | 3 ++ deploys/production/probe_test.go | 47 ++++++++++++++++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/deploys/production/probe.go b/deploys/production/probe.go index d7d965e..58e1959 100644 --- a/deploys/production/probe.go +++ b/deploys/production/probe.go @@ -53,6 +53,9 @@ type report struct { type transport struct{ report *report } func (t transport) RoundTrip(req *http.Request) (*http.Response, error) { + // These fields describe this request, not the last successful endpoint. + t.report.HTTPStatus = 0 + t.report.TransportFailure = "" response, err := http.DefaultTransport.RoundTrip(req) if response != nil { t.report.HTTPStatus = response.StatusCode diff --git a/deploys/production/probe_test.go b/deploys/production/probe_test.go index 545f1e7..4d0dd69 100644 --- a/deploys/production/probe_test.go +++ b/deploys/production/probe_test.go @@ -7,6 +7,7 @@ import ( "errors" "fmt" "net" + "net/http" "strings" "syscall" "testing" @@ -39,6 +40,52 @@ func TestTransportFailureDistinguishesCertificateAndAvailability(t *testing.T) { } } +type probeRoundTripFunc func(*http.Request) (*http.Response, error) + +func (f probeRoundTripFunc) RoundTrip(req *http.Request) (*http.Response, error) { + return f(req) +} + +func TestTransportReportTracksOnlyLatestRequest(t *testing.T) { + original := http.DefaultTransport + t.Cleanup(func() { http.DefaultTransport = original }) + for _, tc := range []struct { + name string + response *http.Response + err error + status int + failure string + }{ + {name: "success clears earlier failure", response: &http.Response{StatusCode: 200}, status: 200}, + {name: "HTTP failure clears earlier transport failure", response: &http.Response{StatusCode: 503}, status: 503}, + {name: "connection refusal clears earlier HTTP success", err: &net.OpError{Op: "dial", Err: syscall.ECONNREFUSED}, failure: "unavailable"}, + {name: "timeout clears earlier HTTP success", err: &net.DNSError{IsTimeout: true}, failure: "unavailable"}, + {name: "certificate failure is not availability", err: x509.UnknownAuthorityError{}, failure: "tls_failed"}, + {name: "unknown failure remains fatal", err: errors.New("synthetic-sensitive-error"), failure: "transport_failed"}, + } { + t.Run(tc.name, func(t *testing.T) { + http.DefaultTransport = probeRoundTripFunc(func(*http.Request) (*http.Response, error) { + return tc.response, tc.err + }) + r := report{Phase: "tasks", HTTPStatus: 200, TransportFailure: "tls_failed", Trunks: 3, Providers: 1} + req, err := http.NewRequest(http.MethodGet, "http://diagnostic.invalid/tasks", nil) + if err != nil { + t.Fatal(err) + } + response, err := (transport{&r}).RoundTrip(req) + if response != tc.response || err != tc.err { + t.Fatal("diagnostic changed the actual transport outcome") + } + if r.HTTPStatus != tc.status || r.TransportFailure != tc.failure { + t.Fatalf("status=%d failure=%q, want status=%d failure=%q", r.HTTPStatus, r.TransportFailure, tc.status, tc.failure) + } + if r.Phase != "tasks" || r.Trunks != 3 || r.Providers != 1 { + t.Fatal("diagnostic discarded earlier independent verification facts") + } + }) + } +} + func TestDiagnosticNeverSerializesErrorContents(t *testing.T) { r := report{Phase: "sip"} rejected(&r, errors.New("synthetic-sensitive-value"))