cairn/internal/forgejo/sync.go

86 lines
2.1 KiB
Go

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")
}