agent-orchestrator/backend/internal/service/pr/manager.go

68 lines
2.2 KiB
Go

// Package pr records SCM observations for pull requests associated with sessions.
package pr
import (
"context"
"time"
"github.com/aoagents/agent-orchestrator/backend/internal/domain"
"github.com/aoagents/agent-orchestrator/backend/internal/ports"
)
type lifecycle interface {
ApplyPRObservation(ctx context.Context, id domain.SessionID, o ports.PRObservation) error
}
// Manager persists PR observations and forwards them to lifecycle for agent
// nudges and direct lifecycle effects.
type Manager struct {
writer ports.PRWriter
lifecycle lifecycle
clock func() time.Time
}
// Deps are the collaborators a PR Manager needs.
type Deps struct {
Writer ports.PRWriter
Lifecycle lifecycle
Clock func() time.Time
}
// New builds a PR Manager from its dependencies, defaulting the clock to time.Now.
func New(d Deps) *Manager {
m := &Manager{writer: d.Writer, lifecycle: d.Lifecycle, clock: d.Clock}
if m.clock == nil {
m.clock = time.Now
}
return m
}
// ApplyObservation records a successfully fetched PR observation. Failed fetches
// are ignored because their fields are not authoritative facts.
func (m *Manager) ApplyObservation(ctx context.Context, id domain.SessionID, o ports.PRObservation) error {
if !o.Fetched {
return nil
}
if err := m.write(ctx, id, o); err != nil {
return err
}
if m.lifecycle == nil {
return nil
}
return m.lifecycle.ApplyPRObservation(ctx, id, o)
}
func (m *Manager) write(ctx context.Context, id domain.SessionID, o ports.PRObservation) error {
now := m.clock()
row := domain.PullRequest{URL: o.URL, SessionID: id, Number: o.Number, Draft: o.Draft, Merged: o.Merged, Closed: o.Closed, CI: o.CI, Review: o.Review, Mergeability: o.Mergeability, UpdatedAt: now}
checks := make([]domain.PullRequestCheck, len(o.Checks))
for i, c := range o.Checks {
checks[i] = domain.PullRequestCheck{Name: c.Name, CommitHash: c.CommitHash, Status: c.Status, URL: c.URL, LogTail: c.LogTail, CreatedAt: now}
}
comments := make([]domain.PullRequestComment, len(o.Comments))
for i, c := range o.Comments {
comments[i] = domain.PullRequestComment{ID: c.ID, Author: c.Author, File: c.File, Line: c.Line, Body: c.Body, Resolved: c.Resolved, CreatedAt: now}
}
return m.writer.WritePR(ctx, row, checks, comments)
}