diff options
Diffstat (limited to 'Omni')
| -rw-r--r-- | Omni/Agent/Git.hs | 16 | ||||
| -rw-r--r-- | Omni/Agent/Worker.hs | 32 |
2 files changed, 47 insertions, 1 deletions
diff --git a/Omni/Agent/Git.hs b/Omni/Agent/Git.hs index cf9a122..7717cee 100644 --- a/Omni/Agent/Git.hs +++ b/Omni/Agent/Git.hs @@ -11,6 +11,8 @@ module Omni.Agent.Git commit, createBranch, getCurrentBranch, + branchExists, + isMerged, main, test, ) @@ -175,3 +177,17 @@ getCurrentBranch repo = do case code of Exit.ExitSuccess -> pure <| Text.strip (Text.pack out) _ -> panic "git branch failed" + +branchExists :: FilePath -> Text -> IO Bool +branchExists repo branch = do + let cmd = (Process.proc "git" ["show-ref", "--verify", "refs/heads/" <> Text.unpack branch]) {Process.cwd = Just repo} + (code, _, _) <- Process.readCreateProcessWithExitCode cmd "" + pure (code == Exit.ExitSuccess) + +isMerged :: FilePath -> Text -> Text -> IO Bool +isMerged repo branch target = do + -- Check if 'branch' is merged into 'target' + -- git merge-base --is-ancestor <branch> <target> + let cmd = (Process.proc "git" ["merge-base", "--is-ancestor", Text.unpack branch, Text.unpack target]) {Process.cwd = Just repo} + (code, _, _) <- Process.readCreateProcessWithExitCode cmd "" + pure (code == Exit.ExitSuccess) diff --git a/Omni/Agent/Worker.hs b/Omni/Agent/Worker.hs index 511f309..23dd759 100644 --- a/Omni/Agent/Worker.hs +++ b/Omni/Agent/Worker.hs @@ -66,7 +66,16 @@ processTask worker task = do currentBranch <- Git.getCurrentBranch repo if currentBranch == taskBranch then Log.info ["worker", "resuming branch", taskBranch] - else Git.createBranch repo taskBranch + else do + -- Determine base branch from dependencies + baseBranch <- findBaseBranch repo task + if baseBranch /= "live" + then do + Log.info ["worker", "basing", taskBranch, "on", baseBranch] + Git.checkout repo baseBranch + else Log.info ["worker", "basing", taskBranch, "on live"] + + Git.createBranch repo taskBranch -- Run Amp exitCode <- runAmp repo task @@ -154,6 +163,27 @@ formatTask t = <> "Updated: " <> Text.pack (show (TaskCore.taskUpdatedAt t)) <> "\n" + <> maybe "" (\d -> "Description:\n" <> d <> "\n\n") (TaskCore.taskDescription t) <> (if null (TaskCore.taskDependencies t) then "" else "\nDependencies:\n" <> Text.unlines (map formatDep (TaskCore.taskDependencies t))) where formatDep dep = " - " <> TaskCore.depId dep <> " [" <> Text.pack (show (TaskCore.depType dep)) <> "]" + +findBaseBranch :: FilePath -> TaskCore.Task -> IO Text +findBaseBranch repo task = do + let deps = TaskCore.taskDependencies task + -- Filter for blocking dependencies + let blockingDeps = filter (\d -> TaskCore.depType d == TaskCore.Blocks || TaskCore.depType d == TaskCore.ParentChild) deps + + -- Check if any have unmerged branches + candidates <- flip filterM blockingDeps <| \dep -> do + let branch = "task/" <> TaskCore.depId dep + exists <- Git.branchExists repo branch + if exists + then do + merged <- Git.isMerged repo branch "live" + pure (not merged) + else pure False + + case candidates of + (candidate : _) -> pure ("task/" <> TaskCore.depId candidate) + [] -> pure "live" |
