diff --git a/internal/server/http/server.go b/internal/server/http/server.go index 5db2438..f9c42c5 100644 --- a/internal/server/http/server.go +++ b/internal/server/http/server.go @@ -123,6 +123,7 @@ func (s *Server) routes(r chi.Router) { r.Post("/api/agents/announce", s.handleAnnounce) r.Get("/agent/binary", s.handleAgentBinary) r.Get("/install/*", s.handleInstallAsset) + r.Get("/api/version", s.handleVersion) if s.deps.Hub != nil { r.Mount("/ws/agent", ws.AgentHandler(ws.HandlerDeps{ Hub: s.deps.Hub, diff --git a/internal/server/http/version.go b/internal/server/http/version.go new file mode 100644 index 0000000..33cc17f --- /dev/null +++ b/internal/server/http/version.go @@ -0,0 +1,20 @@ +package http + +import ( + "encoding/json" + stdhttp "net/http" + + "gitea.dcglab.co.uk/steve/restic-manager/internal/version" +) + +// handleVersion exposes the server's build-time identifying constants +// (set via -ldflags). Public-band — no secrets surface here, the agent +// updater compares its own agent_version byte-for-byte against the +// Version field to drive the "out of date" signal. +func (s *Server) handleVersion(w stdhttp.ResponseWriter, r *stdhttp.Request) { + w.Header().Set("Content-Type", "application/json") + _ = json.NewEncoder(w).Encode(map[string]string{ + "version": version.Version, + "commit": version.Commit, + }) +} diff --git a/internal/server/http/version_test.go b/internal/server/http/version_test.go new file mode 100644 index 0000000..b012818 --- /dev/null +++ b/internal/server/http/version_test.go @@ -0,0 +1,42 @@ +package http + +import ( + "encoding/json" + stdhttp "net/http" + "testing" + + "gitea.dcglab.co.uk/steve/restic-manager/internal/version" +) + +func TestVersionEndpoint(t *testing.T) { + t.Parallel() + + prevV, prevC := version.Version, version.Commit + version.Version = "v9.9.9-test" + version.Commit = "abc1234" + t.Cleanup(func() { + version.Version = prevV + version.Commit = prevC + }) + + _, url, _ := newTestServerWithHub(t) + + res, err := stdhttp.Get(url + "/api/version") + if err != nil { + t.Fatalf("get: %v", err) + } + defer res.Body.Close() + if res.StatusCode != stdhttp.StatusOK { + t.Fatalf("status: got %d want 200", res.StatusCode) + } + var body map[string]string + if err := json.NewDecoder(res.Body).Decode(&body); err != nil { + t.Fatalf("decode: %v", err) + } + if body["version"] != "v9.9.9-test" { + t.Fatalf("version: got %q", body["version"]) + } + if body["commit"] != "abc1234" { + t.Fatalf("commit: got %q", body["commit"]) + } +}