ci: check readiness and the release version after deploy
CI / go (push) Canceled after 0s
CI / web (push) Canceled after 0s
CI / images (Dockerfile, server, alisten) (push) Canceled after 0s
CI / images (web/Dockerfile, web, ) (push) Canceled after 0s
CI / images (worker.Dockerfile, worker, alisten-worker) (push) Canceled after 0s
CI / helm-release (push) Canceled after 0s

The ops port serves GET /version, so the smoke test can confirm that the
upgraded build is the one answering.
This commit is contained in:
DiheChen committed 2026-11-07 22:17:16 +08:00
1 parent 0345d948ac
commit 0dbfe26c1f
6 files changed
+38 -10

No files matched your search

+24 -5
View File
@@ -59,14 +59,33 @@ jobs:
shell: bash
env:
KUBECONFIG: ${{ runner.temp }}/k3s-kubeconfig
HEAD_SHA: ${{ github.event.workflow_run.head_sha }}
run: |
set -euo pipefail
kubectl port-forward --namespace alisten service/alisten-serve 18090:9090 &
kubectl port-forward \
--namespace alisten \
--address 127.0.0.1 \
service/alisten-serve 18090:9090 &
pid=$!
trap 'kill "$pid" 2>/dev/null || true' EXIT
base_url="http://127.0.0.1:18090"
curl --silent --show-error --fail \
--retry 10 \
--retry-delay 2 \
--connect-timeout 2 \
--max-time 5 \
--retry 20 \
--retry-delay 1 \
--retry-connrefused \
--max-time 10 \
http://127.0.0.1:18090/healthz
--retry-max-time 60 \
"${base_url}/readyz"
expected="${TAG}+${HEAD_SHA}"
actual="$(curl --silent --show-error --fail \
--connect-timeout 2 \
--max-time 5 \
"${base_url}/version")"
diff -u --label expected --label actual \
<(echo "$expected") <(echo "$actual")
+4 -1
View File
@@ -8,7 +8,7 @@ import (
"github.com/prometheus/client_golang/prometheus/promhttp"
)
func NewHandler(ready func() bool, metrics prometheus.Gatherer) http.Handler {
func NewHandler(ready func() bool, metrics prometheus.Gatherer, version string) http.Handler {
mux := http.NewServeMux()
mux.HandleFunc("GET /healthz", func(w http.ResponseWriter, _ *http.Request) {
_, _ = io.WriteString(w, "ok\n")
@@ -20,6 +20,9 @@ func NewHandler(ready func() bool, metrics prometheus.Gatherer) http.Handler {
}
_, _ = io.WriteString(w, "ok\n")
})
mux.HandleFunc("GET /version", func(w http.ResponseWriter, _ *http.Request) {
_, _ = io.WriteString(w, version+"\n")
})
mux.Handle("GET /metrics", promhttp.HandlerFor(metrics, promhttp.HandlerOpts{}))
return mux
}
+7 -1
View File
@@ -15,7 +15,7 @@ func TestHandler(t *testing.T) {
registry := prometheus.NewRegistry()
registry.MustRegister(prometheus.NewGauge(prometheus.GaugeOpts{Name: "test_gauge", Help: "测试用指标。"}))
var ready atomic.Bool
handler := NewHandler(ready.Load, registry)
handler := NewHandler(ready.Load, registry, "v1.2.3+abc")
get := func(path string) *httptest.ResponseRecorder {
rec := httptest.NewRecorder()
@@ -28,6 +28,12 @@ func TestHandler(t *testing.T) {
t.Errorf("/healthz 状态码 = %d,期望 200", rec.Code)
}
})
t.Run("version 返回构建版本", func(t *testing.T) {
rec := get("/version")
if body := rec.Body.String(); rec.Code != http.StatusOK || body != "v1.2.3+abc\n" {
t.Errorf("/version 状态码 = %d,响应 = %q,期望 200 和 \"v1.2.3+abc\\n\"", rec.Code, body)
}
})
t.Run("metrics 输出注册的指标", func(t *testing.T) {
rec := get("/metrics")
body, _ := io.ReadAll(rec.Body)
+1 -1
View File
@@ -12,7 +12,7 @@ import (
func TestHealthcheckFollowsReadiness(t *testing.T) {
var ready atomic.Bool
server := httptest.NewServer(ops.NewHandler(ready.Load, prometheus.NewRegistry()))
server := httptest.NewServer(ops.NewHandler(ready.Load, prometheus.NewRegistry(), version))
defer server.Close()
t.Setenv("ALISTEN_OPS_LISTEN", server.Listener.Addr().String())
+1 -1
View File
@@ -182,7 +182,7 @@ func runServe(base *slog.Logger) (err error) {
opsLogger := base.With("component", "ops")
publicServer := newHTTPServer(p.handler, base.With("component", "http"))
opsServer := newHTTPServer(recoverPanics(ops.NewHandler(ready, metrics), opsLogger), opsLogger)
opsServer := newHTTPServer(recoverPanics(ops.NewHandler(ready, metrics, version), opsLogger), opsLogger)
go func() { fatal <- fmt.Errorf("HTTP 服务异常退出:%w", publicServer.Serve(publicListener)) }()
go func() { fatal <- fmt.Errorf("HTTP 服务异常退出:%w", opsServer.Serve(opsListener)) }()
logger.Info("服务已启动", "listen", publicListener.Addr().String(), "ops_listen", opsListener.Addr().String(), "instance", instance)
+1 -1
View File
@@ -275,7 +275,7 @@ func (w mediaWorker) run(ctx context.Context, listener net.Listener) error {
}),
)
opsLogger := w.base.With("component", "ops")
opsServer := newHTTPServer(recoverPanics(ops.NewHandler(ready, w.metrics), opsLogger), opsLogger)
opsServer := newHTTPServer(recoverPanics(ops.NewHandler(ready, w.metrics, version), opsLogger), opsLogger)
go func() { fatal <- fmt.Errorf("运维端口异常退出:%w", opsServer.Serve(listener)) }()
w.logger.Info("worker 已启动", "ops_listen", listener.Addr().String(), "instance", w.instance)