summaryrefslogtreecommitdiff
path: root/internal/api
diff options
context:
space:
mode:
Diffstat (limited to 'internal/api')
-rw-r--r--internal/api/stories.go59
-rw-r--r--internal/api/stories_test.go52
2 files changed, 86 insertions, 25 deletions
diff --git a/internal/api/stories.go b/internal/api/stories.go
index fcf8c48..3d9d25a 100644
--- a/internal/api/stories.go
+++ b/internal/api/stories.go
@@ -247,22 +247,30 @@ func (s *Server) handleApproveStory(w http.ResponseWriter, r *http.Request) {
return
}
+ var repoURL string
+ if input.ProjectID != "" {
+ if proj, err := s.store.GetProject(input.ProjectID); err == nil {
+ repoURL = proj.RemoteURL
+ }
+ }
+
taskIDs := make([]string, 0, len(input.Tasks))
var prevTaskID string
for _, tp := range input.Tasks {
t := &task.Task{
- ID: uuid.New().String(),
- Name: tp.Name,
- Project: input.ProjectID,
- StoryID: story.ID,
- Agent: task.AgentConfig{Type: "claude", Instructions: tp.Instructions},
- Priority: task.PriorityNormal,
- Tags: []string{},
- DependsOn: []string{},
- Retry: task.RetryConfig{MaxAttempts: 1, Backoff: "exponential"},
- State: task.StatePending,
- CreatedAt: time.Now().UTC(),
- UpdatedAt: time.Now().UTC(),
+ ID: uuid.New().String(),
+ Name: tp.Name,
+ Project: input.ProjectID,
+ RepositoryURL: repoURL,
+ StoryID: story.ID,
+ Agent: task.AgentConfig{Type: "claude", Instructions: tp.Instructions},
+ Priority: task.PriorityNormal,
+ Tags: []string{},
+ DependsOn: []string{},
+ Retry: task.RetryConfig{MaxAttempts: 1, Backoff: "exponential"},
+ State: task.StatePending,
+ CreatedAt: time.Now().UTC(),
+ UpdatedAt: time.Now().UTC(),
}
if prevTaskID != "" {
t.DependsOn = []string{prevTaskID}
@@ -276,19 +284,20 @@ func (s *Server) handleApproveStory(w http.ResponseWriter, r *http.Request) {
var prevSubtaskID string
for _, sub := range tp.Subtasks {
st := &task.Task{
- ID: uuid.New().String(),
- Name: sub.Name,
- Project: input.ProjectID,
- StoryID: story.ID,
- ParentTaskID: t.ID,
- Agent: task.AgentConfig{Type: "claude", Instructions: sub.Instructions},
- Priority: task.PriorityNormal,
- Tags: []string{},
- DependsOn: []string{},
- Retry: task.RetryConfig{MaxAttempts: 1, Backoff: "exponential"},
- State: task.StatePending,
- CreatedAt: time.Now().UTC(),
- UpdatedAt: time.Now().UTC(),
+ ID: uuid.New().String(),
+ Name: sub.Name,
+ Project: input.ProjectID,
+ RepositoryURL: repoURL,
+ StoryID: story.ID,
+ ParentTaskID: t.ID,
+ Agent: task.AgentConfig{Type: "claude", Instructions: sub.Instructions},
+ Priority: task.PriorityNormal,
+ Tags: []string{},
+ DependsOn: []string{},
+ Retry: task.RetryConfig{MaxAttempts: 1, Backoff: "exponential"},
+ State: task.StatePending,
+ CreatedAt: time.Now().UTC(),
+ UpdatedAt: time.Now().UTC(),
}
if prevSubtaskID != "" {
st.DependsOn = []string{prevSubtaskID}
diff --git a/internal/api/stories_test.go b/internal/api/stories_test.go
index 17bea07..53d15eb 100644
--- a/internal/api/stories_test.go
+++ b/internal/api/stories_test.go
@@ -205,6 +205,58 @@ func TestHandleStoryApprove_WiresDepends(t *testing.T) {
}
}
+func TestHandleStoryApprove_SetsRepositoryURL(t *testing.T) {
+ srv, store := testServer(t)
+
+ proj := &task.Project{
+ ID: "proj-repo",
+ Name: "claudomator",
+ RemoteURL: "/site/git.terst.org/repos/claudomator.git",
+ LocalPath: "/workspace/claudomator",
+ }
+ if err := store.CreateProject(proj); err != nil {
+ t.Fatalf("CreateProject: %v", err)
+ }
+
+ body := `{
+ "name": "Repo URL Story",
+ "branch_name": "story/repo-url",
+ "project_id": "proj-repo",
+ "tasks": [
+ {"name": "Task A", "instructions": "do A", "subtasks": []},
+ {"name": "Task B", "instructions": "do B", "subtasks": [
+ {"name": "Sub B1", "instructions": "do B1"}
+ ]}
+ ],
+ "validation": {"type": "build", "steps": ["go build ./..."], "success_criteria": "ok"}
+ }`
+ req := httptest.NewRequest("POST", "/api/stories/approve", bytes.NewBufferString(body))
+ req.Header.Set("Content-Type", "application/json")
+ w := httptest.NewRecorder()
+ srv.mux.ServeHTTP(w, req)
+
+ if w.Code != http.StatusCreated {
+ t.Fatalf("expected 201, got %d: %s", w.Code, w.Body.String())
+ }
+
+ var resp struct {
+ TaskIDs []string `json:"task_ids"`
+ }
+ if err := json.NewDecoder(w.Body).Decode(&resp); err != nil {
+ t.Fatalf("decode: %v", err)
+ }
+
+ for _, id := range resp.TaskIDs {
+ tk, err := store.GetTask(id)
+ if err != nil {
+ t.Fatalf("GetTask %s: %v", id, err)
+ }
+ if tk.RepositoryURL != proj.RemoteURL {
+ t.Errorf("task %s RepositoryURL: want %q, got %q", tk.ID, proj.RemoteURL, tk.RepositoryURL)
+ }
+ }
+}
+
func TestHandleStoryDeploymentStatus(t *testing.T) {
srv, store := testServer(t)