diff options
Diffstat (limited to 'internal/api')
| -rw-r--r-- | internal/api/deployment.go | 36 | ||||
| -rw-r--r-- | internal/api/server.go | 1 | ||||
| -rw-r--r-- | internal/api/server_test.go | 77 |
3 files changed, 114 insertions, 0 deletions
diff --git a/internal/api/deployment.go b/internal/api/deployment.go new file mode 100644 index 0000000..d927545 --- /dev/null +++ b/internal/api/deployment.go @@ -0,0 +1,36 @@ +package api + +import ( + "database/sql" + "net/http" + + "github.com/thepeterstone/claudomator/internal/deployment" +) + +// handleGetDeploymentStatus returns whether the currently-deployed server +// includes the commits that were produced by this task's latest execution. +// GET /api/tasks/{id}/deployment-status +func (s *Server) handleGetDeploymentStatus(w http.ResponseWriter, r *http.Request) { + id := r.PathValue("id") + + tk, err := s.store.GetTask(id) + if err != nil { + writeJSON(w, http.StatusNotFound, map[string]string{"error": "task not found"}) + return + } + + exec, err := s.store.GetLatestExecution(tk.ID) + if err != nil { + if err == sql.ErrNoRows { + // No execution yet — return status with no fix commits. + status := deployment.Check(nil, tk.Agent.ProjectDir) + writeJSON(w, http.StatusOK, status) + return + } + writeJSON(w, http.StatusInternalServerError, map[string]string{"error": err.Error()}) + return + } + + status := deployment.Check(exec.Commits, tk.Agent.ProjectDir) + writeJSON(w, http.StatusOK, status) +} diff --git a/internal/api/server.go b/internal/api/server.go index 65b0181..7988c4c 100644 --- a/internal/api/server.go +++ b/internal/api/server.go @@ -116,6 +116,7 @@ func (s *Server) routes() { s.mux.HandleFunc("POST /api/scripts/{name}", s.handleScript) s.mux.HandleFunc("GET /api/ws", s.handleWebSocket) s.mux.HandleFunc("GET /api/workspaces", s.handleListWorkspaces) + s.mux.HandleFunc("GET /api/tasks/{id}/deployment-status", s.handleGetDeploymentStatus) s.mux.HandleFunc("GET /api/health", s.handleHealth) s.mux.Handle("GET /", http.FileServerFS(webui.Files)) } diff --git a/internal/api/server_test.go b/internal/api/server_test.go index 4899a5c..5c0deba 100644 --- a/internal/api/server_test.go +++ b/internal/api/server_test.go @@ -1704,3 +1704,80 @@ func TestListExecutions_IncludesChangestats(t *testing.T) { t.Errorf("lines_removed: want 20, got %v", csMap["lines_removed"]) } } + +// TestDeploymentStatus_ReturnsStatusForReadyTask verifies that +// GET /api/tasks/{id}/deployment-status returns a valid deployment status +// with deployed_commit, fix_commits, and includes_fix fields. +func TestDeploymentStatus_ReturnsStatusForReadyTask(t *testing.T) { + srv, store := testServer(t) + + // Create a READY task using the walk-path helper. + tk := createTaskWithState(t, store, "deploy-status-task-1", task.StateReady) + + // Create an execution with commits. + exec := &storage.Execution{ + ID: "deploy-exec-1", + TaskID: tk.ID, + StartTime: time.Now(), + EndTime: time.Now(), + Status: "COMPLETED", + Commits: []task.GitCommit{ + {Hash: "abc123def456", Message: "fix: resolve the bug"}, + }, + } + if err := store.CreateExecution(exec); err != nil { + t.Fatal(err) + } + + // GET /api/tasks/{id}/deployment-status + req := httptest.NewRequest("GET", "/api/tasks/deploy-status-task-1/deployment-status", nil) + w := httptest.NewRecorder() + srv.Handler().ServeHTTP(w, req) + + if w.Code != http.StatusOK { + t.Fatalf("want 200, got %d; body: %s", w.Code, w.Body.String()) + } + + var resp map[string]interface{} + if err := json.NewDecoder(w.Body).Decode(&resp); err != nil { + t.Fatalf("decode response: %v", err) + } + + // deployed_commit must be present (will be "dev" in test environment). + if _, ok := resp["deployed_commit"]; !ok { + t.Error("response missing deployed_commit field") + } + // fix_commits must be an array. + fixCommits, ok := resp["fix_commits"] + if !ok { + t.Fatal("response missing fix_commits field") + } + commits, ok := fixCommits.([]interface{}) + if !ok { + t.Fatalf("fix_commits is not an array: %T", fixCommits) + } + if len(commits) != 1 { + t.Fatalf("fix_commits length: want 1, got %d", len(commits)) + } + commit := commits[0].(map[string]interface{}) + if commit["hash"] != "abc123def456" { + t.Errorf("fix_commits[0].hash: want abc123def456, got %v", commit["hash"]) + } + // includes_fix must be present (false in test env since version is "dev"). + if _, ok := resp["includes_fix"]; !ok { + t.Error("response missing includes_fix field") + } +} + +// TestDeploymentStatus_NotFound returns 404 for unknown task. +func TestDeploymentStatus_NotFound(t *testing.T) { + srv, _ := testServer(t) + + req := httptest.NewRequest("GET", "/api/tasks/nonexistent-task/deployment-status", nil) + w := httptest.NewRecorder() + srv.Handler().ServeHTTP(w, req) + + if w.Code != http.StatusNotFound { + t.Fatalf("want 404, got %d", w.Code) + } +} |
