package forgejo import ( "context" "fmt" "strings" "github.com/jackc/pgx/v5/pgxpool" "github.com/rs/zerolog/log" "github.com/mattnite/cairn/internal/models" ) // Sync handles bidirectional state synchronization between Cairn and Forgejo. type Sync struct { Client *Client Pool *pgxpool.Pool } // CreateIssueForCrashGroup creates a Forgejo issue for a new crash group. func (s *Sync) CreateIssueForCrashGroup(ctx context.Context, group *models.CrashGroup, sampleTrace string) error { if s.Client == nil { return nil } repo, err := models.GetRepositoryByID(ctx, s.Pool, group.RepositoryID) if err != nil { return fmt.Errorf("getting repository: %w", err) } body := fmt.Sprintf(`## Crash Group **Fingerprint:** `+"`%s`"+` **First seen:** %s **Type:** %s ### Sample Stack Trace `+"```"+` %s `+"```"+` --- *Auto-created by [Cairn](/) — crash artifact aggregator* `, group.Fingerprint, group.FirstSeenAt.Format("2006-01-02 15:04:05"), group.Title, sampleTrace) issue, err := s.Client.CreateIssue(ctx, repo.Owner, repo.Name, CreateIssueRequest{ Title: "[Cairn] " + group.Title, Body: body, }) if err != nil { return fmt.Errorf("creating issue: %w", err) } return models.UpdateCrashGroupIssue(ctx, s.Pool, group.ID, issue.Number, issue.HTMLURL) } // HandleIssueEvent processes a Forgejo issue webhook event for state sync. func (s *Sync) HandleIssueEvent(ctx context.Context, event *WebhookEvent) error { if event.Issue == nil { return nil } // Only handle issues that start with [Cairn] prefix. if !strings.HasPrefix(event.Issue.Title, "[Cairn] ") { return nil } switch event.Action { case "closed": return models.ResolveCrashGroupByIssue(ctx, s.Pool, event.Issue.Number) case "reopened": return models.ReopenCrashGroupByIssue(ctx, s.Pool, event.Issue.Number) } return nil } // HandlePushEvent processes a push webhook event for commit enrichment. func (s *Sync) HandlePushEvent(ctx context.Context, event *WebhookEvent) { if event.Repo == nil || event.After == "" { return } log.Info().Str("repo", event.Repo.FullName).Str("sha", event.After[:8]).Msg("Push event") }