Lewis: May this revision serve well! lewis@tangled.org
+212
-108
Diff
round #7
+87
-44
appview/migration/migrate_add_repo_did.go
+87
-44
appview/migration/migrate_add_repo_did.go
···
2
2
3
3
import (
4
4
"context"
5
+
"encoding/json"
5
6
"fmt"
6
7
"strings"
7
8
···
14
15
)
15
16
16
17
func (s *Migration) migrateAddRepoDid(ctx context.Context, client *atclient.APIClient, did syntax.DID, record syntax.ATURI) error {
17
-
// TODO: use agnostic.RepoGetRecord instead
18
+
if record.Collection().String() == tangled.FeedStarNSID {
19
+
return s.migrateAddRepoDidStar(ctx, client, did, record)
20
+
}
21
+
18
22
ex, err := comatproto.RepoGetRecord(ctx, client, "", record.Collection().String(), did.String(), record.RecordKey().String())
19
23
if err != nil {
20
24
return fmt.Errorf("pds: %w", err)
···
22
26
23
27
val := ex.Value.Val
24
28
25
-
switch record.Collection() {
29
+
switch record.Collection().String() {
26
30
case tangled.RepoNSID:
27
31
rec, ok := val.(*tangled.Repo)
28
32
if !ok {
···
39
43
if !ok {
40
44
return fmt.Errorf("unexpected type for issue record")
41
45
}
42
-
if rec.Repo != nil {
43
-
repoAt := *rec.Repo
44
-
repo, err := db.GetRepoByAtUri(s.db, repoAt)
45
-
if err != nil {
46
-
return fmt.Errorf("db: failed to query repo: %w", err)
47
-
}
48
-
rec.RepoDid = &repo.RepoDid
46
+
if strings.HasPrefix(rec.Repo, "did:") {
47
+
return nil
49
48
}
49
+
repo, err := db.GetRepoByAtUri(s.db, rec.Repo)
50
+
if err != nil {
51
+
return fmt.Errorf("db: failed to query repo by at_uri %q: %w", rec.Repo, err)
52
+
}
53
+
rec.Repo = repo.RepoDid
50
54
51
55
case tangled.RepoPullNSID:
52
56
rec, ok := val.(*tangled.RepoPull)
53
57
if !ok {
54
58
return fmt.Errorf("unexpected type for pull record")
55
59
}
56
-
if rec.Target != nil && rec.Target.Repo != nil {
57
-
repoAt := *rec.Target.Repo
58
-
repo, err := db.GetRepoByAtUri(s.db, repoAt)
60
+
if rec.Target == nil {
61
+
return fmt.Errorf("pull record has nil target")
62
+
}
63
+
if !strings.HasPrefix(rec.Target.Repo, "did:") {
64
+
repo, err := db.GetRepoByAtUri(s.db, rec.Target.Repo)
59
65
if err != nil {
60
-
return fmt.Errorf("db: failed to query repo: %w", err)
66
+
return fmt.Errorf("db: failed to query target repo by at_uri %q: %w", rec.Target.Repo, err)
61
67
}
62
-
rec.Target.RepoDid = &repo.RepoDid
68
+
rec.Target.Repo = repo.RepoDid
63
69
}
64
-
if rec.Source != nil && rec.Source.Repo != nil {
65
-
repoAt := *rec.Source.Repo
66
-
repo, err := db.GetRepoByAtUri(s.db, repoAt)
67
-
if err != nil {
68
-
return fmt.Errorf("db: failed to query repo: %w", err)
70
+
if rec.Source != nil && rec.Source.Repo != nil && !strings.HasPrefix(*rec.Source.Repo, "did:") {
71
+
sourceRepo, srcErr := db.GetRepoByAtUri(s.db, *rec.Source.Repo)
72
+
if srcErr == nil && sourceRepo.RepoDid != "" {
73
+
rec.Source.Repo = &sourceRepo.RepoDid
69
74
}
70
-
rec.Source.RepoDid = &repo.RepoDid
71
75
}
72
76
73
77
case tangled.RepoCollaboratorNSID:
···
75
79
if !ok {
76
80
return fmt.Errorf("unexpected type for collaborator record")
77
81
}
78
-
if rec.Repo != nil {
79
-
repoAt := *rec.Repo
80
-
repo, err := db.GetRepoByAtUri(s.db, repoAt)
81
-
if err != nil {
82
-
return fmt.Errorf("db: failed to query repo: %w", err)
83
-
}
84
-
rec.RepoDid = &repo.RepoDid
82
+
if strings.HasPrefix(rec.Repo, "did:") {
83
+
return nil
84
+
}
85
+
repo, err := db.GetRepoByAtUri(s.db, rec.Repo)
86
+
if err != nil {
87
+
return fmt.Errorf("db: failed to query repo by at_uri %q: %w", rec.Repo, err)
85
88
}
89
+
rec.Repo = repo.RepoDid
86
90
87
91
case tangled.RepoArtifactNSID:
88
92
rec, ok := val.(*tangled.RepoArtifact)
···
90
94
return fmt.Errorf("unexpected type for artifact record")
91
95
}
92
96
if rec.Repo != nil {
93
-
repoAt := *rec.Repo
94
-
repo, err := db.GetRepoByAtUri(s.db, repoAt)
97
+
repo, err := db.GetRepoByAtUri(s.db, *rec.Repo)
95
98
if err != nil {
96
-
return fmt.Errorf("db: failed to query repo: %w", err)
99
+
return fmt.Errorf("db: failed to query repo by at_uri %q: %w", *rec.Repo, err)
97
100
}
98
101
rec.RepoDid = &repo.RepoDid
99
102
}
100
103
101
-
case tangled.FeedStarNSID:
102
-
rec, ok := val.(*tangled.FeedStar)
103
-
if !ok {
104
-
return fmt.Errorf("unexpected type for star record")
105
-
}
106
-
if rec.Subject != nil {
107
-
repoAt := *rec.Subject
108
-
repo, err := db.GetRepoByAtUri(s.db, repoAt)
109
-
if err != nil {
110
-
return fmt.Errorf("db: failed to query repo: %w", err)
111
-
}
112
-
rec.SubjectDid = &repo.RepoDid
113
-
}
114
-
115
104
case tangled.ActorProfileNSID:
116
105
rec, ok := val.(*tangled.ActorProfile)
117
106
if !ok {
···
149
138
150
139
return nil
151
140
}
141
+
142
+
func (s *Migration) migrateAddRepoDidStar(ctx context.Context, client *atclient.APIClient, did syntax.DID, record syntax.ATURI) error {
143
+
var raw struct {
144
+
Cid *string `json:"cid,omitempty"`
145
+
Uri string `json:"uri"`
146
+
Value json.RawMessage `json:"value"`
147
+
}
148
+
params := map[string]any{
149
+
"collection": record.Collection().String(),
150
+
"repo": did.String(),
151
+
"rkey": record.RecordKey().String(),
152
+
}
153
+
if err := client.LexDo(ctx, lexutil.Query, "", "com.atproto.repo.getRecord", params, nil, &raw); err != nil {
154
+
return fmt.Errorf("get record: %w", err)
155
+
}
156
+
157
+
var legacy struct {
158
+
CreatedAt string `json:"createdAt"`
159
+
Subject *string `json:"subject,omitempty"`
160
+
}
161
+
if err := json.Unmarshal(raw.Value, &legacy); err != nil {
162
+
return fmt.Errorf("decode old star fields: %w", err)
163
+
}
164
+
if legacy.Subject == nil {
165
+
return fmt.Errorf("star record has no subject field")
166
+
}
167
+
168
+
repo, err := db.GetRepoByAtUri(s.db, *legacy.Subject)
169
+
if err != nil {
170
+
return fmt.Errorf("db: failed to query repo by at_uri %q: %w", *legacy.Subject, err)
171
+
}
172
+
if repo.RepoDid == "" {
173
+
return fmt.Errorf("repo has no repoDid: %s", *legacy.Subject)
174
+
}
175
+
176
+
newRecord := &tangled.FeedStar{
177
+
CreatedAt: legacy.CreatedAt,
178
+
Subject: &tangled.FeedStar_Subject{
179
+
FeedStar_Repo: &tangled.FeedStar_Repo{Did: repo.RepoDid},
180
+
},
181
+
}
182
+
183
+
_, err = comatproto.RepoPutRecord(ctx, client, &comatproto.RepoPutRecord_Input{
184
+
Repo: did.String(),
185
+
Collection: record.Collection().String(),
186
+
Rkey: record.RecordKey().String(),
187
+
SwapRecord: raw.Cid,
188
+
Record: &lexutil.LexiconTypeDecoder{Val: newRecord},
189
+
})
190
+
if err != nil {
191
+
return fmt.Errorf("put record: %w", err)
192
+
}
193
+
return nil
194
+
}
+15
-14
appview/notify/db/db.go
+15
-14
appview/notify/db/db.go
···
5
5
"slices"
6
6
7
7
"github.com/bluesky-social/indigo/atproto/syntax"
8
-
"tangled.org/core/api/tangled"
9
8
"tangled.org/core/appview/db"
10
9
"tangled.org/core/appview/models"
11
10
"tangled.org/core/appview/notify"
···
40
39
// no-op for now
41
40
}
42
41
42
+
func (n *databaseNotifier) RenameRepo(ctx context.Context, actor syntax.DID, oldRepo, newRepo *models.Repo) {
43
+
}
44
+
43
45
func (n *databaseNotifier) NewStar(ctx context.Context, star *models.Star) {
44
46
l := log.FromContext(ctx)
45
47
46
-
if star.RepoAt.Collection().String() != tangled.RepoNSID {
47
-
// skip string stars for now
48
+
if star.SubjectType != models.StarSubjectRepo {
48
49
return
49
50
}
50
-
var err error
51
-
repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", string(star.RepoAt)))
51
+
52
+
repo, err := db.GetRepo(n.db, orm.FilterEq("repo_did", star.Subject))
52
53
if err != nil {
53
54
l.Error("failed to get repos", "err", err)
54
55
return
···
58
59
recipients := sets.Singleton(syntax.DID(repo.Did))
59
60
eventType := models.NotificationTypeRepoStarred
60
61
entityType := "repo"
61
-
entityId := star.RepoAt.String()
62
+
entityId := star.Subject
62
63
repoId := &repo.Id
63
64
var issueId *int64
64
65
var pullId *int64
···
83
84
func (n *databaseNotifier) NewIssue(ctx context.Context, issue *models.Issue, mentions []syntax.DID) {
84
85
l := log.FromContext(ctx)
85
86
86
-
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", issue.Repo.RepoAt()))
87
+
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_did", string(issue.RepoDid)))
87
88
if err != nil {
88
89
l.Error("failed to fetch collaborators", "err", err)
89
90
return
···
240
241
func (n *databaseNotifier) NewPull(ctx context.Context, pull *models.Pull) {
241
242
l := log.FromContext(ctx)
242
243
243
-
repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", string(pull.RepoAt)))
244
+
repo, err := db.GetRepo(n.db, orm.FilterEq("repo_did", string(pull.RepoDid)))
244
245
if err != nil {
245
246
l.Error("failed to get repos", "err", err)
246
247
return
247
248
}
248
-
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", repo.RepoAt()))
249
+
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_did", string(pull.RepoDid)))
249
250
if err != nil {
250
251
l.Error("failed to fetch collaborators", "err", err)
251
252
return
···
285
286
l := log.FromContext(ctx)
286
287
287
288
pull, err := db.GetPull(n.db,
288
-
orm.FilterEq("repo_at", syntax.ATURI(comment.RepoAt)),
289
+
orm.FilterEq("repo_did", comment.RepoDid),
289
290
orm.FilterEq("pull_id", comment.PullId),
290
291
)
291
292
if err != nil {
···
293
294
return
294
295
}
295
296
296
-
repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", comment.RepoAt))
297
+
repo, err := db.GetRepo(n.db, orm.FilterEq("repo_did", comment.RepoDid))
297
298
if err != nil {
298
299
l.Error("failed to get repos", "err", err)
299
300
return
···
371
372
func (n *databaseNotifier) NewIssueState(ctx context.Context, actor syntax.DID, issue *models.Issue) {
372
373
l := log.FromContext(ctx)
373
374
374
-
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", issue.Repo.RepoAt()))
375
+
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_did", string(issue.RepoDid)))
375
376
if err != nil {
376
377
l.Error("failed to fetch collaborators", "err", err)
377
378
return
···
419
420
l := log.FromContext(ctx)
420
421
421
422
// Get repo details
422
-
repo, err := db.GetRepo(n.db, orm.FilterEq("at_uri", string(pull.RepoAt)))
423
+
repo, err := db.GetRepo(n.db, orm.FilterEq("repo_did", string(pull.RepoDid)))
423
424
if err != nil {
424
425
l.Error("failed to get repos", "err", err)
425
426
return
426
427
}
427
428
428
-
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_at", repo.RepoAt()))
429
+
collaborators, err := db.GetCollaborators(n.db, orm.FilterEq("repo_did", string(pull.RepoDid)))
429
430
if err != nil {
430
431
l.Error("failed to fetch collaborators", "err", err)
431
432
return
+5
appview/notify/logging/notifier.go
+5
appview/notify/logging/notifier.go
···
31
31
l.inner.DeleteRepo(ctx, repo)
32
32
}
33
33
34
+
func (l *loggingNotifier) RenameRepo(ctx context.Context, actor syntax.DID, oldRepo, newRepo *models.Repo) {
35
+
ctx = tlog.IntoContext(ctx, tlog.SubLogger(l.logger, "RenameRepo"))
36
+
l.inner.RenameRepo(ctx, actor, oldRepo, newRepo)
37
+
}
38
+
34
39
func (l *loggingNotifier) NewStar(ctx context.Context, star *models.Star) {
35
40
ctx = tlog.IntoContext(ctx, tlog.SubLogger(l.logger, "NewStar"))
36
41
l.inner.NewStar(ctx, star)
+4
appview/notify/merged_notifier.go
+4
appview/notify/merged_notifier.go
···
38
38
m.fanout(func(n Notifier) { n.DeleteRepo(ctx, repo) })
39
39
}
40
40
41
+
func (m *mergedNotifier) RenameRepo(ctx context.Context, actor syntax.DID, oldRepo, newRepo *models.Repo) {
42
+
m.fanout(func(n Notifier) { n.RenameRepo(ctx, actor, oldRepo, newRepo) })
43
+
}
44
+
41
45
func (m *mergedNotifier) NewStar(ctx context.Context, star *models.Star) {
42
46
m.fanout(func(n Notifier) { n.NewStar(ctx, star) })
43
47
}
+3
appview/notify/notifier.go
+3
appview/notify/notifier.go
···
10
10
type Notifier interface {
11
11
NewRepo(ctx context.Context, repo *models.Repo)
12
12
DeleteRepo(ctx context.Context, repo *models.Repo)
13
+
RenameRepo(ctx context.Context, actor syntax.DID, oldRepo, newRepo *models.Repo)
13
14
14
15
NewStar(ctx context.Context, star *models.Star)
15
16
DeleteStar(ctx context.Context, star *models.Star)
···
47
48
48
49
func (m *BaseNotifier) NewRepo(ctx context.Context, repo *models.Repo) {}
49
50
func (m *BaseNotifier) DeleteRepo(ctx context.Context, repo *models.Repo) {}
51
+
func (m *BaseNotifier) RenameRepo(ctx context.Context, actor syntax.DID, oldRepo, newRepo *models.Repo) {
52
+
}
50
53
51
54
func (m *BaseNotifier) NewStar(ctx context.Context, star *models.Star) {}
52
55
func (m *BaseNotifier) DeleteStar(ctx context.Context, star *models.Star) {}
+34
-12
appview/notify/posthog/notifier.go
+34
-12
appview/notify/posthog/notifier.go
···
35
35
}
36
36
}
37
37
38
+
func (n *posthogNotifier) RenameRepo(ctx context.Context, actor syntax.DID, oldRepo, newRepo *models.Repo) {
39
+
err := n.client.Enqueue(posthog.Capture{
40
+
DistinctId: actor.String(),
41
+
Event: "repo_renamed",
42
+
Properties: posthog.Properties{
43
+
"repo_at": newRepo.RepoAt(),
44
+
"owner": newRepo.Did,
45
+
"old_name": oldRepo.Name,
46
+
"new_name": newRepo.Name,
47
+
},
48
+
})
49
+
if err != nil {
50
+
log.Println("failed to enqueue posthog event:", err)
51
+
}
52
+
}
53
+
38
54
func (n *posthogNotifier) NewStar(ctx context.Context, star *models.Star) {
39
55
err := n.client.Enqueue(posthog.Capture{
40
56
DistinctId: star.Did,
41
57
Event: "star",
42
-
Properties: posthog.Properties{"repo_at": star.RepoAt.String()},
58
+
Properties: posthog.Properties{
59
+
"subject_type": string(star.SubjectType),
60
+
"subject": star.Subject,
61
+
},
43
62
})
44
63
if err != nil {
45
64
log.Println("failed to enqueue posthog event:", err)
···
50
69
err := n.client.Enqueue(posthog.Capture{
51
70
DistinctId: star.Did,
52
71
Event: "unstar",
53
-
Properties: posthog.Properties{"repo_at": star.RepoAt.String()},
72
+
Properties: posthog.Properties{
73
+
"subject_type": string(star.SubjectType),
74
+
"subject": star.Subject,
75
+
},
54
76
})
55
77
if err != nil {
56
78
log.Println("failed to enqueue posthog event:", err)
···
62
84
DistinctId: issue.Did,
63
85
Event: "new_issue",
64
86
Properties: posthog.Properties{
65
-
"repo_at": issue.RepoAt.String(),
87
+
"repo_did": string(issue.RepoDid),
66
88
"issue_id": issue.IssueId,
67
89
"mentions": mentions,
68
90
},
···
77
99
DistinctId: pull.OwnerDid,
78
100
Event: "new_pull",
79
101
Properties: posthog.Properties{
80
-
"repo_at": pull.RepoAt,
81
-
"pull_id": pull.PullId,
102
+
"repo_did": string(pull.RepoDid),
103
+
"pull_id": pull.PullId,
82
104
},
83
105
})
84
106
if err != nil {
···
91
113
DistinctId: comment.OwnerDid,
92
114
Event: "new_pull_comment",
93
115
Properties: posthog.Properties{
94
-
"repo_at": comment.RepoAt,
116
+
"repo_did": comment.RepoDid,
95
117
"pull_id": comment.PullId,
96
118
"mentions": mentions,
97
119
},
···
106
128
DistinctId: pull.OwnerDid,
107
129
Event: "pull_closed",
108
130
Properties: posthog.Properties{
109
-
"repo_at": pull.RepoAt,
110
-
"pull_id": pull.PullId,
131
+
"repo_did": string(pull.RepoDid),
132
+
"pull_id": pull.PullId,
111
133
},
112
134
})
113
135
if err != nil {
···
216
238
DistinctId: issue.Did,
217
239
Event: event,
218
240
Properties: posthog.Properties{
219
-
"repo_at": issue.RepoAt.String(),
241
+
"repo_did": string(issue.RepoDid),
220
242
"actor": actor,
221
243
"issue_id": issue.IssueId,
222
244
},
···
243
265
DistinctId: pull.OwnerDid,
244
266
Event: event,
245
267
Properties: posthog.Properties{
246
-
"repo_at": pull.RepoAt,
247
-
"pull_id": pull.PullId,
248
-
"actor": actor,
268
+
"repo_did": string(pull.RepoDid),
269
+
"pull_id": pull.PullId,
270
+
"actor": actor,
249
271
},
250
272
})
251
273
if err != nil {
+64
-38
appview/notify/webhook/notifier.go
+64
-38
appview/notify/webhook/notifier.go
···
14
14
"time"
15
15
16
16
"github.com/avast/retry-go/v4"
17
+
"github.com/bluesky-social/indigo/atproto/syntax"
17
18
"github.com/google/uuid"
18
19
"tangled.org/core/appview/db"
19
20
"tangled.org/core/appview/models"
···
41
42
var _ notify.Notifier = &Notifier{}
42
43
43
44
func (w *Notifier) Push(ctx context.Context, repo *models.Repo, ref, oldSha, newSha, committerDid string) {
44
-
webhooks, err := db.GetActiveWebhooksForRepo(w.db, repo.RepoAt())
45
+
webhooks, err := w.activeWebhooksForEvent(repo.RepoDid, models.WebhookEventPush)
45
46
if err != nil {
46
-
w.logger.Error("failed to get webhooks for repo", "repo", repo.RepoAt(), "err", err)
47
+
w.logger.Error("failed to get webhooks for repo", "repo_did", repo.RepoDid, "err", err)
48
+
return
49
+
}
50
+
if len(webhooks) == 0 {
47
51
return
48
52
}
49
53
50
-
var pushWebhooks []models.Webhook
54
+
payload := w.buildPushPayload(repo, ref, oldSha, newSha, committerDid)
55
+
payloadBytes, err := json.Marshal(payload)
56
+
if err != nil {
57
+
w.logger.Error("failed to marshal push payload", "repo_did", repo.RepoDid, "err", err)
58
+
return
59
+
}
60
+
61
+
userAgent := "Tangled-Hook/" + newSha[:7]
51
62
for _, webhook := range webhooks {
52
-
if webhook.HasEvent(models.WebhookEventPush) {
53
-
pushWebhooks = append(pushWebhooks, webhook)
54
-
}
63
+
go w.sendWebhook(ctx, webhook, string(models.WebhookEventPush), payload.Repository.FullName, userAgent, payloadBytes)
55
64
}
65
+
}
56
66
57
-
if len(pushWebhooks) == 0 {
67
+
func (w *Notifier) RenameRepo(ctx context.Context, actor syntax.DID, oldRepo, newRepo *models.Repo) {
68
+
webhooks, err := w.activeWebhooksForEvent(newRepo.RepoDid, models.WebhookEventRepoRenamed)
69
+
if err != nil {
70
+
w.logger.Error("failed to get webhooks for repo", "repo_did", newRepo.RepoDid, "err", err)
71
+
return
72
+
}
73
+
if len(webhooks) == 0 {
58
74
return
59
75
}
60
76
61
-
payload, err := w.buildPushPayload(repo, ref, oldSha, newSha, committerDid)
77
+
payload := &models.WebhookRenamePayload{
78
+
OldName: oldRepo.Name,
79
+
NewName: newRepo.Name,
80
+
Repository: buildWebhookRepository(newRepo),
81
+
Sender: models.WebhookUser{Did: actor.String()},
82
+
}
83
+
payloadBytes, err := json.Marshal(payload)
62
84
if err != nil {
63
-
w.logger.Error("failed to build push payload", "repo", repo.RepoAt(), "err", err)
85
+
w.logger.Error("failed to marshal rename payload", "repo_did", newRepo.RepoDid, "err", err)
64
86
return
65
87
}
66
88
67
-
for _, webhook := range pushWebhooks {
68
-
go w.sendWebhook(ctx, webhook, string(models.WebhookEventPush), payload)
89
+
userAgent := "Tangled-Hook/rename"
90
+
for _, webhook := range webhooks {
91
+
go w.sendWebhook(ctx, webhook, string(models.WebhookEventRepoRenamed), payload.Repository.FullName, userAgent, payloadBytes)
69
92
}
70
93
}
71
94
72
-
func (w *Notifier) buildPushPayload(repo *models.Repo, ref, oldSha, newSha, committerDid string) (*models.WebhookPayload, error) {
73
-
owner := repo.Did
74
-
75
-
pusher := committerDid
76
-
if committerDid == "" {
77
-
pusher = owner
95
+
func (w *Notifier) activeWebhooksForEvent(repoDid string, event models.WebhookEvent) ([]models.Webhook, error) {
96
+
webhooks, err := db.GetActiveWebhooksForRepo(w.db, repoDid)
97
+
if err != nil {
98
+
return nil, err
78
99
}
100
+
var matching []models.Webhook
101
+
for _, webhook := range webhooks {
102
+
if webhook.HasEvent(event) {
103
+
matching = append(matching, webhook)
104
+
}
105
+
}
106
+
return matching, nil
107
+
}
79
108
109
+
func buildWebhookRepository(repo *models.Repo) models.WebhookRepository {
80
110
repository := models.WebhookRepository{
81
111
Name: repo.Name,
82
-
FullName: fmt.Sprintf("%s/%s", repo.Did, repo.Name),
112
+
FullName: fmt.Sprintf("%s/%s", repo.Did, repo.Rkey),
83
113
Description: repo.Description,
84
114
Fork: repo.Source != "",
85
-
HtmlUrl: fmt.Sprintf("https://%s/%s/%s", repo.Knot, repo.Did, repo.Name),
86
-
CloneUrl: fmt.Sprintf("https://%s/%s/%s", repo.Knot, repo.Did, repo.Name),
87
-
SshUrl: fmt.Sprintf("ssh://git@%s/%s/%s", repo.Knot, repo.Did, repo.Name),
115
+
HtmlUrl: fmt.Sprintf("https://%s/%s/%s", repo.Knot, repo.Did, repo.Rkey),
116
+
CloneUrl: fmt.Sprintf("https://%s/%s/%s", repo.Knot, repo.Did, repo.Rkey),
117
+
SshUrl: fmt.Sprintf("ssh://git@%s/%s/%s", repo.Knot, repo.Did, repo.Rkey),
88
118
CreatedAt: repo.Created.Format(time.RFC3339),
89
119
UpdatedAt: repo.Created.Format(time.RFC3339),
90
120
Owner: models.WebhookUser{
91
-
Did: owner,
121
+
Did: repo.Did,
92
122
},
93
123
}
94
-
95
124
if repo.Website != "" {
96
125
repository.Website = repo.Website
97
126
}
···
99
128
repository.StarsCount = repo.RepoStats.StarCount
100
129
repository.OpenIssues = repo.RepoStats.IssueCount.Open
101
130
}
131
+
return repository
132
+
}
102
133
103
-
payload := &models.WebhookPayload{
134
+
func (w *Notifier) buildPushPayload(repo *models.Repo, ref, oldSha, newSha, committerDid string) *models.WebhookPayload {
135
+
pusher := committerDid
136
+
if committerDid == "" {
137
+
pusher = repo.Did
138
+
}
139
+
return &models.WebhookPayload{
104
140
Ref: ref,
105
141
Before: oldSha,
106
142
After: newSha,
107
-
Repository: repository,
143
+
Repository: buildWebhookRepository(repo),
108
144
Pusher: models.WebhookUser{
109
145
Did: pusher,
110
146
},
111
147
}
112
-
113
-
return payload, nil
114
148
}
115
149
116
-
func (w *Notifier) sendWebhook(ctx context.Context, webhook models.Webhook, event string, payload *models.WebhookPayload) {
150
+
func (w *Notifier) sendWebhook(ctx context.Context, webhook models.Webhook, event, repoFullName, userAgent string, payloadBytes []byte) {
117
151
deliveryId := uuid.New().String()
118
152
119
-
payloadBytes, err := json.Marshal(payload)
120
-
if err != nil {
121
-
w.logger.Error("failed to marshal webhook payload", "webhook_id", webhook.Id, "err", err)
122
-
return
123
-
}
124
-
125
153
req, err := http.NewRequestWithContext(ctx, "POST", webhook.Url, bytes.NewReader(payloadBytes))
126
154
if err != nil {
127
155
w.logger.Error("failed to create webhook request", "webhook_id", webhook.Id, "err", err)
128
156
return
129
157
}
130
158
131
-
shortSha := payload.After[:7]
132
-
133
159
req.Header.Set("Content-Type", "application/json")
134
-
req.Header.Set("User-Agent", "Tangled-Hook/"+shortSha)
160
+
req.Header.Set("User-Agent", userAgent)
135
161
req.Header.Set("X-Tangled-Event", event)
136
162
req.Header.Set("X-Tangled-Hook-ID", fmt.Sprintf("%d", webhook.Id))
137
163
req.Header.Set("X-Tangled-Delivery", deliveryId)
138
-
req.Header.Set("X-Tangled-Repo", payload.Repository.FullName)
164
+
req.Header.Set("X-Tangled-Repo", repoFullName)
139
165
140
166
if webhook.Secret != "" {
141
167
signature := w.computeSignature(payloadBytes, webhook.Secret)
History
9 rounds
0 comments
oyster.cafe
submitted
#8
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
merge conflicts detected
expand
collapse
expand
collapse
- api/tangled/cbor_gen.go:866
- api/tangled/feedstar.go:5
- api/tangled/gitrefUpdate.go:29
- api/tangled/repocollaborator.go:19
- api/tangled/repoissue.go:22
- api/tangled/repopull.go:39
- api/tangled/tangledrepo.go:24
- cmd/cborgen/cborgen.go:17
- knotserver/xrpc/merge.go:118
- lexicons/feed/star.json:10
- lexicons/git/refUpdate.json:11
- lexicons/issue/issue.json:9
- lexicons/pulls/pull.json:65
- lexicons/repo/collaborator.json:11
- lexicons/repo/repo.json:6
expand 0 comments
oyster.cafe
submitted
#7
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
expand 0 comments
oyster.cafe
submitted
#6
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
expand 0 comments
oyster.cafe
submitted
#5
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
expand 0 comments
oyster.cafe
submitted
#4
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
expand 0 comments
oyster.cafe
submitted
#3
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
expand 0 comments
oyster.cafe
submitted
#2
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
expand 0 comments
oyster.cafe
submitted
#1
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>
expand 0 comments
oyster.cafe
submitted
#0
1 commit
expand
collapse
appview/oauth,notify: DID-based PDS record rewriting
Lewis: May this revision serve well! <lewis@tangled.org>