diff options
| author | Peter Stone <thepeterstone@gmail.com> | 2026-03-16 04:24:19 +0000 |
|---|---|---|
| committer | Peter Stone <thepeterstone@gmail.com> | 2026-03-16 04:24:19 +0000 |
| commit | d75a231d8865d9b14fbe3d608c9aa1bffb7ed386 (patch) | |
| tree | 1875147811c1cbf5b85260dc5fc5be8986902f68 /internal/api/server_test.go | |
| parent | 16ff7ca46bfb4af44af488fa95bd3f8e981f4db2 (diff) | |
feat: add deployment status endpoint for tasks
Adds GET /api/tasks/{id}/deployment-status which checks whether the
currently-deployed server binary includes the fix commits from the
task's latest execution. Uses git merge-base --is-ancestor to compare
commit hashes against the running version.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Diffstat (limited to 'internal/api/server_test.go')
| -rw-r--r-- | internal/api/server_test.go | 77 |
1 files changed, 77 insertions, 0 deletions
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) + } +} |
