From 88b2cbf207cdedb1dba25d0cf0c26c5281de87c9 Mon Sep 17 00:00:00 2001 From: Anirudh Oppiliappan Date: Thu, 02 Apr 2026 08:32:36 +0000 Subject: [PATCH] appview/notify: add Clone notifier, enqueue posthog event for clones Signed-off-by: Anirudh Oppiliappan --- appview/notify/db/db.go | 4 ++++ appview/notify/logging_notifier.go | 5 +++++ appview/notify/merged_notifier.go | 4 ++++ appview/notify/notifier.go | 4 ++++ appview/notify/posthog/notifier.go | 11 +++++++++++ appview/notify/webhook_notifier.go | 2 ++ appview/state/git_http.go | 2 ++ 7 file(s) changed, 32 insertion(s)(+), 0 deletion(s)(-) diff --git a/appview/notify/db/db.go b/appview/notify/db/db.go --- a/appview/notify/db/db.go +++ b/appview/notify/db/db.go @@ -361,6 +361,10 @@ func (n *databaseNotifier) Push(ctx context.Context, repo *models.Repo, ref, oldSha, newSha, committerDid string) { // no-op for now; webhooks are handled by the webhook notifier } +func (n *databaseNotifier) Clone(ctx context.Context, repo *models.Repo) { + // no-op +} + func (n *databaseNotifier) NewIssueState(ctx context.Context, actor syntax.DID, issue *models.Issue) { l := log.FromContext(ctx) diff --git a/appview/notify/logging_notifier.go b/appview/notify/logging_notifier.go --- a/appview/notify/logging_notifier.go +++ b/appview/notify/logging_notifier.go @@ -118,3 +118,8 @@ func (l *loggingNotifier) Push(ctx context.Context, repo *models.Repo, ref, oldSha, newSha, committerDid string) { ctx = tlog.IntoContext(ctx, tlog.SubLogger(l.logger, "Push")) l.inner.Push(ctx, repo, ref, oldSha, newSha, committerDid) } + +func (l *loggingNotifier) Clone(ctx context.Context, repo *models.Repo) { + ctx = tlog.IntoContext(ctx, tlog.SubLogger(l.logger, "Clone")) + l.inner.Clone(ctx, repo) +} diff --git a/appview/notify/merged_notifier.go b/appview/notify/merged_notifier.go --- a/appview/notify/merged_notifier.go +++ b/appview/notify/merged_notifier.go @@ -105,3 +105,7 @@ func (m *mergedNotifier) Push(ctx context.Context, repo *models.Repo, ref, oldSha, newSha, committerDid string) { m.fanout(func(n Notifier) { n.Push(ctx, repo, ref, oldSha, newSha, committerDid) }) } + +func (m *mergedNotifier) Clone(ctx context.Context, repo *models.Repo) { + m.fanout(func(n Notifier) { n.Clone(ctx, repo) }) +} diff --git a/appview/notify/notifier.go b/appview/notify/notifier.go --- a/appview/notify/notifier.go +++ b/appview/notify/notifier.go @@ -35,6 +35,8 @@ EditString(ctx context.Context, s *models.String) DeleteString(ctx context.Context, did, rkey string) Push(ctx context.Context, repo *models.Repo, ref, oldSha, newSha, committerDid string) + + Clone(ctx context.Context, repo *models.Repo) } // BaseNotifier is a listener that does nothing @@ -72,3 +74,5 @@ func (m *BaseNotifier) DeleteString(ctx context.Context, did, rkey string) {} func (m *BaseNotifier) Push(ctx context.Context, repo *models.Repo, ref, oldSha, newSha, committerDid string) { } + +func (m *BaseNotifier) Clone(ctx context.Context, repo *models.Repo) {} diff --git a/appview/notify/posthog/notifier.go b/appview/notify/posthog/notifier.go --- a/appview/notify/posthog/notifier.go +++ b/appview/notify/posthog/notifier.go @@ -180,6 +180,17 @@ log.Println("failed to enqueue posthog event:", err) } } +func (n *posthogNotifier) Clone(ctx context.Context, repo *models.Repo) { + err := n.client.Enqueue(posthog.Capture{ + DistinctId: repo.Did, + Event: "clone", + Properties: posthog.Properties{"repo": repo.Name, "repo_at": repo.RepoAt()}, + }) + if err != nil { + log.Println("failed to enqueue posthog event:", err) + } +} + func (n *posthogNotifier) NewIssueComment(ctx context.Context, comment *models.IssueComment, mentions []syntax.DID) { err := n.client.Enqueue(posthog.Capture{ DistinctId: comment.Did, diff --git a/appview/notify/webhook_notifier.go b/appview/notify/webhook_notifier.go --- a/appview/notify/webhook_notifier.go +++ b/appview/notify/webhook_notifier.go @@ -69,6 +69,8 @@ go w.sendWebhook(ctx, webhook, string(models.WebhookEventPush), payload) } } +func (w *WebhookNotifier) Clone(ctx context.Context, repo *models.Repo) {} + // buildPushPayload creates the webhook payload func (w *WebhookNotifier) buildPushPayload(repo *models.Repo, ref, oldSha, newSha, committerDid string) (*models.WebhookPayload, error) { owner := repo.Did diff --git a/appview/state/git_http.go b/appview/state/git_http.go --- a/appview/state/git_http.go +++ b/appview/state/git_http.go @@ -1,6 +1,7 @@ package state import ( + "context" "fmt" "io" "net/http" @@ -51,6 +52,7 @@ case "git-receive-pack": contentType = "application/x-git-receive-pack-advertisement" default: contentType = "application/x-git-upload-pack-advertisement" + go s.notifier.Clone(context.Background(), repo) } targetURL := fmt.Sprintf("%s://%s/%s/info/refs?%s", scheme, repo.Knot, repo.RepoIdentifier(), r.URL.RawQuery) -- tangled.sh