diff options
Diffstat (limited to 'internal/executor')
| -rw-r--r-- | internal/executor/executor.go | 22 |
1 files changed, 22 insertions, 0 deletions
diff --git a/internal/executor/executor.go b/internal/executor/executor.go index a60a771..ad79a84 100644 --- a/internal/executor/executor.go +++ b/internal/executor/executor.go @@ -546,6 +546,14 @@ func (p *Pool) handleRunResult(ctx context.Context, t *task.Task, exec *storage. // Subtasks are intentionally excluded — a parent task reaching READY/COMPLETED // already accounts for its subtasks. func (p *Pool) checkStoryCompletion(ctx context.Context, storyID string) { + story, err := p.store.GetStory(storyID) + if err != nil { + p.logger.Error("checkStoryCompletion: failed to get story", "storyID", storyID, "error", err) + return + } + if story.Status != task.StoryInProgress { + return // already SHIPPABLE or beyond — nothing to do + } tasks, err := p.store.ListTasksByStory(storyID) if err != nil { p.logger.Error("checkStoryCompletion: failed to list tasks", "storyID", storyID, "error", err) @@ -572,7 +580,21 @@ func (p *Pool) checkStoryCompletion(ctx context.Context, storyID string) { return } p.logger.Info("story transitioned to SHIPPABLE", "storyID", storyID) + // Deploy is now triggered explicitly by the human via POST /api/stories/{id}/ship. +} + +// ShipStory merges the story branch and runs the deploy script. +// Returns an error if the story is not in SHIPPABLE state. +func (p *Pool) ShipStory(ctx context.Context, storyID string) error { + story, err := p.store.GetStory(storyID) + if err != nil { + return fmt.Errorf("story not found: %w", err) + } + if story.Status != task.StoryShippable { + return fmt.Errorf("story is not SHIPPABLE (current status: %s)", story.Status) + } go p.triggerStoryDeploy(ctx, storyID) + return nil } // spawnCheckerTask creates and submits a checker task for the given completed task. |
