From eb01c1c842d16619d063d7182d382a171e34da27 Mon Sep 17 00:00:00 2001 From: Manuel Ganter Date: Fri, 6 Feb 2026 15:22:27 +0100 Subject: [PATCH] fix(receiver): return Payload as JSON object instead of string Changed the API response to embed Payload as a JSON object using json.RawMessage instead of returning it as a JSON-encoded string inside the JSON response. Added MetricResponse type with ToResponse converter method. Co-Authored-By: Claude Opus 4.5 --- internal/receiver/handler.go | 8 +++++++- internal/receiver/handler_test.go | 4 ++-- internal/receiver/store.go | 26 ++++++++++++++++++++++++++ 3 files changed, 35 insertions(+), 3 deletions(-) diff --git a/internal/receiver/handler.go b/internal/receiver/handler.go index a00e414..66905f9 100644 --- a/internal/receiver/handler.go +++ b/internal/receiver/handler.go @@ -74,8 +74,14 @@ func (h *Handler) handleGetByWorkflowJob(w http.ResponseWriter, r *http.Request) return } + // Convert to response type with Payload as JSON object + response := make([]MetricResponse, len(metrics)) + for i, m := range metrics { + response[i] = m.ToResponse() + } + w.Header().Set("Content-Type", "application/json") - _ = json.NewEncoder(w).Encode(metrics) + _ = json.NewEncoder(w).Encode(response) } func (h *Handler) handleHealth(w http.ResponseWriter, r *http.Request) { diff --git a/internal/receiver/handler_test.go b/internal/receiver/handler_test.go index fdd3894..df589df 100644 --- a/internal/receiver/handler_test.go +++ b/internal/receiver/handler_test.go @@ -125,7 +125,7 @@ func TestHandler_GetByWorkflowJob(t *testing.T) { t.Errorf("status = %d, want %d", rec.Code, http.StatusOK) } - var metrics []Metric + var metrics []MetricResponse if err := json.NewDecoder(rec.Body).Decode(&metrics); err != nil { t.Fatalf("failed to decode response: %v", err) } @@ -149,7 +149,7 @@ func TestHandler_GetByWorkflowJob_NotFound(t *testing.T) { t.Errorf("status = %d, want %d", rec.Code, http.StatusOK) } - var metrics []Metric + var metrics []MetricResponse if err := json.NewDecoder(rec.Body).Decode(&metrics); err != nil { t.Fatalf("failed to decode response: %v", err) } diff --git a/internal/receiver/store.go b/internal/receiver/store.go index 4ae970a..1b934de 100644 --- a/internal/receiver/store.go +++ b/internal/receiver/store.go @@ -24,6 +24,32 @@ type Metric struct { Payload string `gorm:"type:text;not null"` // JSON-encoded RunSummary } +// MetricResponse is the API response type with Payload as embedded JSON object +type MetricResponse struct { + ID uint `json:"id"` + Organization string `json:"organization"` + Repository string `json:"repository"` + Workflow string `json:"workflow"` + Job string `json:"job"` + RunID string `json:"run_id"` + ReceivedAt time.Time `json:"received_at"` + Payload json.RawMessage `json:"payload"` +} + +// ToResponse converts a Metric to a MetricResponse with Payload as JSON object +func (m *Metric) ToResponse() MetricResponse { + return MetricResponse{ + ID: m.ID, + Organization: m.Organization, + Repository: m.Repository, + Workflow: m.Workflow, + Job: m.Job, + RunID: m.RunID, + ReceivedAt: m.ReceivedAt, + Payload: json.RawMessage(m.Payload), + } +} + // Store handles SQLite storage for metrics using GORM type Store struct { db *gorm.DB