Files
kandev/apps/backend/internal/github/service_task_pr_detach.go
T
2026-08-02 17:00:32 +01:00

68 lines
2.1 KiB
Go

package github
import (
"context"
"errors"
"strings"
"github.com/kandev/kandev/internal/events"
"github.com/kandev/kandev/internal/events/bus"
"go.uber.org/zap"
)
var ErrTaskPRNotFound = errors.New("github task PR not found")
// TaskPRDeletedEvent identifies one task-PR association removed from active
// task surfaces. The remote GitHub pull request is intentionally untouched.
type TaskPRDeletedEvent struct {
WorkspaceID string `json:"workspace_id"`
TaskID string `json:"task_id"`
AssociationID string `json:"association_id"`
}
// GetWorkspaceID lets the websocket broadcaster route the typed event to the
// owning workspace instead of treating it as an instance-wide notification.
func (e TaskPRDeletedEvent) GetWorkspaceID() string { return e.WorkspaceID }
// DetachTaskPR removes one association from active task views while retaining
// a durable tombstone that prevents background discovery from resurrecting it.
func (s *Service) DetachTaskPR(ctx context.Context, workspaceID, associationID string) (*TaskPR, error) {
if strings.TrimSpace(workspaceID) == "" || strings.TrimSpace(associationID) == "" {
return nil, ErrTaskPRNotFound
}
tp, err := s.store.GetTaskPRByID(ctx, associationID)
if err != nil {
return nil, err
}
if tp == nil || (tp.WorkspaceID != "" && tp.WorkspaceID != workspaceID) {
return nil, ErrTaskPRNotFound
}
if err := s.authorizeWorkspaceAccess(ctx, workspaceID); err != nil {
return nil, err
}
if tp.DetachedAt != nil {
return tp, nil
}
detached, transitioned, err := s.store.DetachTaskPR(ctx, associationID)
if err != nil {
return nil, err
}
if detached == nil {
return nil, ErrTaskPRNotFound
}
if !transitioned {
return detached, nil
}
if s.eventBus != nil {
event := bus.NewEvent(events.GitHubTaskPRDeleted, "github", &TaskPRDeletedEvent{
WorkspaceID: workspaceID,
TaskID: detached.TaskID,
AssociationID: detached.ID,
})
if err := s.eventBus.Publish(ctx, events.GitHubTaskPRDeleted, event); err != nil {
s.logger.Debug("failed to publish task PR deleted event", zap.Error(err))
}
}
return detached, nil
}