push.go

  1package webhook
  2
  3import (
  4	"context"
  5	"fmt"
  6
  7	"github.com/charmbracelet/soft-serve/git"
  8	"github.com/charmbracelet/soft-serve/pkg/config"
  9	"github.com/charmbracelet/soft-serve/pkg/db"
 10	"github.com/charmbracelet/soft-serve/pkg/proto"
 11	"github.com/charmbracelet/soft-serve/pkg/store"
 12	gitm "github.com/aymanbagabas/git-module"
 13)
 14
 15// PushEvent is a push event.
 16type PushEvent struct {
 17	Common
 18
 19	// Ref is the branch or tag name.
 20	Ref string `json:"ref" url:"ref"`
 21	// Before is the previous commit SHA.
 22	Before string `json:"before" url:"before"`
 23	// After is the current commit SHA.
 24	After string `json:"after" url:"after"`
 25	// Commits is the list of commits.
 26	Commits []Commit `json:"commits" url:"commits"`
 27}
 28
 29// NewPushEvent sends a push event.
 30func NewPushEvent(ctx context.Context, user proto.User, repo proto.Repository, ref, before, after string) (PushEvent, error) {
 31	event := EventPush
 32
 33	payload := PushEvent{
 34		Ref:    ref,
 35		Before: before,
 36		After:  after,
 37		Common: Common{
 38			EventType: event,
 39			Repository: Repository{
 40				ID:          repo.ID(),
 41				Name:        repo.Name(),
 42				Description: repo.Description(),
 43				ProjectName: repo.ProjectName(),
 44				Private:     repo.IsPrivate(),
 45				CreatedAt:   repo.CreatedAt(),
 46				UpdatedAt:   repo.UpdatedAt(),
 47			},
 48			Sender: User{
 49				ID:       user.ID(),
 50				Username: user.Username(),
 51			},
 52		},
 53	}
 54
 55	cfg := config.FromContext(ctx)
 56	payload.Repository.HTTPURL = repoURL(cfg.HTTP.PublicURL, repo.Name())
 57	payload.Repository.SSHURL = repoURL(cfg.SSH.PublicURL, repo.Name())
 58	payload.Repository.GitURL = repoURL(cfg.Git.PublicURL, repo.Name())
 59
 60	// Find repo owner.
 61	dbx := db.FromContext(ctx)
 62	datastore := store.FromContext(ctx)
 63	owner, err := datastore.GetUserByID(ctx, dbx, repo.UserID())
 64	if err != nil {
 65		return PushEvent{}, db.WrapError(err)
 66	}
 67
 68	payload.Repository.Owner.ID = owner.ID
 69	payload.Repository.Owner.Username = owner.Username
 70
 71	// Find commits.
 72	r, err := repo.Open()
 73	if err != nil {
 74		return PushEvent{}, err
 75	}
 76
 77	payload.Repository.DefaultBranch, err = proto.RepositoryDefaultBranch(repo)
 78	if err != nil {
 79		return PushEvent{}, err
 80	}
 81
 82	rev := after
 83	if !git.IsZeroHash(before) {
 84		rev = fmt.Sprintf("%s..%s", before, after)
 85	}
 86
 87	commits, err := r.Log(rev, gitm.LogOptions{
 88		// XXX: limit to 20 commits for now
 89		// TODO: implement a commits api
 90		MaxCount: 20,
 91	})
 92	if err != nil {
 93		return PushEvent{}, err
 94	}
 95
 96	payload.Commits = make([]Commit, len(commits))
 97	for i, c := range commits {
 98		payload.Commits[i] = Commit{
 99			ID:      c.ID.String(),
100			Message: c.Message,
101			Title:   c.Summary(),
102			Author: Author{
103				Name:  c.Author.Name,
104				Email: c.Author.Email,
105				Date:  c.Author.When,
106			},
107			Committer: Author{
108				Name:  c.Committer.Name,
109				Email: c.Committer.Email,
110				Date:  c.Committer.When,
111			},
112			Timestamp: c.Committer.When,
113		}
114	}
115
116	return payload, nil
117}