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}