Wait for the agent's turn instead of dropping a held merge
This commit is contained in:
@@ -495,7 +495,7 @@ func (m *Manager) failResume(ctx context.Context, sess api.AgentSession, task ap
|
||||
case end.Discard == store.DiscardHeld:
|
||||
go m.startDiscard(task.Id)
|
||||
case end.MergeBy != "":
|
||||
go m.startClaimedMerge(task.Id, end.MergeBy)
|
||||
go m.advanceMergeClaim(task.Id)
|
||||
case end.MergeWaiting:
|
||||
case sess.Role == api.Implementer && m.leadsTask(ctx, task.Id, sess.Id):
|
||||
m.abandonMerge(task.Id, task.ProjectId)
|
||||
@@ -1031,7 +1031,7 @@ func (m *Manager) pump(l *live) {
|
||||
return
|
||||
}
|
||||
if end.MergeBy != "" {
|
||||
go m.startClaimedMerge(l.taskID, end.MergeBy)
|
||||
go m.advanceMergeClaim(l.taskID)
|
||||
}
|
||||
if l.owner == "" {
|
||||
if end.MergeBy == "" && !end.MergeWaiting && m.leadsTask(ctx, l.taskID, l.id) {
|
||||
@@ -1337,7 +1337,7 @@ func (m *Manager) turnEnded(ctx context.Context, l *live, res endResult) error {
|
||||
m.snapshotSoon(liveTarget(l), api.SnapshotTriggerTurnEnd, 0, review, false)
|
||||
}
|
||||
if end.MergeBy != "" {
|
||||
go m.startClaimedMerge(l.taskID, end.MergeBy)
|
||||
go m.advanceMergeClaim(l.taskID)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+38
-58
@@ -161,20 +161,12 @@ func (m *Manager) beginMergeTurn(ctx context.Context, task api.Task, project api
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
prompt := mergeInPrompt(project.DefaultBranch) + fmt.Sprintf(" When this turn ends, byre squashes this branch onto %s and pushes it; if you stop, call stop_merge first so it doesn't. ", project.DefaultBranch) + summaryRequest
|
||||
go m.launchMerge(sess, task, project, prompt)
|
||||
go m.launchMerge(sess, task, project, mergeTurnPrompt(project))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) advanceMergeClaim(taskID string) {
|
||||
login, err := m.store.TakeIdleMergeClaim(context.Background(), taskID)
|
||||
if err != nil {
|
||||
slog.Error("take idle merge claim", "task", taskID, "err", err)
|
||||
return
|
||||
}
|
||||
if login != "" {
|
||||
m.startClaimedMerge(taskID, login)
|
||||
}
|
||||
func mergeTurnPrompt(project api.Project) string {
|
||||
return mergeInPrompt(project.DefaultBranch) + fmt.Sprintf(" When this turn ends, byre squashes this branch onto %s and pushes it; if you stop, call stop_merge first so it doesn't. ", project.DefaultBranch) + summaryRequest
|
||||
}
|
||||
|
||||
func (m *Manager) advanceMergeClaims(ctx context.Context) {
|
||||
@@ -188,11 +180,10 @@ func (m *Manager) advanceMergeClaims(ctx context.Context) {
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) startClaimedMerge(taskID, login string) {
|
||||
func (m *Manager) advanceMergeClaim(taskID string) {
|
||||
ctx := context.Background()
|
||||
err := m.beginClaimedMerge(ctx, taskID, login)
|
||||
err := m.beginClaimedMerge(ctx, taskID)
|
||||
if err == nil {
|
||||
slog.Info("started claimed merge", "task", taskID, "by", login)
|
||||
return
|
||||
}
|
||||
slog.Error("start claimed merge", "task", taskID, "err", err)
|
||||
@@ -210,7 +201,11 @@ func (m *Manager) startClaimedMerge(taskID, login string) {
|
||||
m.fileTaskError(ctx, task, sessions, "Starting the held merge failed: "+err.Error())
|
||||
}
|
||||
|
||||
func (m *Manager) beginClaimedMerge(ctx context.Context, taskID, login string) error {
|
||||
func (m *Manager) beginClaimedMerge(ctx context.Context, taskID string) error {
|
||||
login, err := m.store.MergeClaim(ctx, taskID)
|
||||
if err != nil || login == "" {
|
||||
return err
|
||||
}
|
||||
task, err := m.store.GetTask(ctx, taskID)
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -223,21 +218,35 @@ func (m *Manager) beginClaimedMerge(ctx context.Context, taskID, login string) e
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return m.beginMergeTurn(ctx, task, project, user)
|
||||
if user.GitName == "" || user.GitEmail == "" {
|
||||
return ErrNoGitIdentity
|
||||
}
|
||||
sess, err := m.leadSession(ctx, task, user)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
reserved, err := m.store.ReserveMergeTurn(ctx, task.Id, sess.Id)
|
||||
if err != nil || !reserved {
|
||||
return err
|
||||
}
|
||||
slog.Info("started claimed merge", "task", taskID, "by", login)
|
||||
go m.launchMerge(sess, task, project, mergeTurnPrompt(project))
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Manager) leadSession(ctx context.Context, task api.Task, user api.User) (api.AgentSession, error) {
|
||||
sess, found, err := m.liveSession(ctx, task.Id)
|
||||
if err != nil || found {
|
||||
return sess, err
|
||||
}
|
||||
return m.newSession(ctx, task, user, sess.Member, "")
|
||||
}
|
||||
|
||||
func (m *Manager) mergeSession(ctx context.Context, task api.Task, user api.User) (api.AgentSession, error) {
|
||||
sess, found, err := m.liveSession(ctx, task.Id)
|
||||
sess, err := m.leadSession(ctx, task, user)
|
||||
if err != nil {
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
if !found {
|
||||
sess, err = m.newSession(ctx, task, user, sess.Member, "")
|
||||
if err != nil {
|
||||
return api.AgentSession{}, err
|
||||
}
|
||||
}
|
||||
|
||||
err = transition(ctx, m.store, sess.Id, api.AgentSessionStateIdle, api.AgentSessionStateRunning, "byre")
|
||||
return sess, err
|
||||
}
|
||||
@@ -427,7 +436,7 @@ func (m *Manager) startNextMerge(pm *projectMerge, projectID string) {
|
||||
}
|
||||
|
||||
for _, task := range held {
|
||||
login, claimed, err := m.store.ClaimQueuedMerge(ctx, task.Id)
|
||||
login, err := m.store.ClaimQueuedMerge(ctx, task.Id)
|
||||
if err != nil {
|
||||
slog.Error("take held merge", "task", task.Id, "err", err)
|
||||
continue
|
||||
@@ -435,42 +444,13 @@ func (m *Manager) startNextMerge(pm *projectMerge, projectID string) {
|
||||
if login == "" {
|
||||
continue
|
||||
}
|
||||
if claimed {
|
||||
pm.holder = task.Id
|
||||
slog.Info("claimed held merge until the agent's turn ends", "task", task.Id, "by", login)
|
||||
return
|
||||
}
|
||||
|
||||
err = m.startHeldMerge(ctx, pm, task, login)
|
||||
if err == nil {
|
||||
slog.Info("started held merge", "task", task.Id, "by", login)
|
||||
return
|
||||
}
|
||||
slog.Error("start held merge", "task", task.Id, "err", err)
|
||||
sessions, serr := m.store.ListSessions(ctx, task.Id)
|
||||
if serr != nil {
|
||||
slog.Error("list sessions for held merge", "task", task.Id, "err", serr)
|
||||
continue
|
||||
}
|
||||
m.fileTaskError(ctx, task, sessions, "Starting the held merge failed: "+err.Error())
|
||||
pm.holder = task.Id
|
||||
slog.Info("claimed held merge", "task", task.Id, "by", login)
|
||||
go m.advanceMergeClaim(task.Id)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (m *Manager) startHeldMerge(ctx context.Context, pm *projectMerge, task api.Task, login string) error {
|
||||
project, err := m.store.GetProject(ctx, task.ProjectId)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
user, err := m.store.GetUser(ctx, login)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if user.GitName == "" || user.GitEmail == "" {
|
||||
return ErrNoGitIdentity
|
||||
}
|
||||
return m.startMerge(ctx, pm, task, project, user)
|
||||
}
|
||||
|
||||
func (m *Manager) fileTaskError(ctx context.Context, task api.Task, sessions []api.AgentSession, msg string) {
|
||||
if len(sessions) == 0 {
|
||||
slog.Error("no session to file task error on", "task", task.Id, "error", msg)
|
||||
|
||||
Reference in New Issue
Block a user