From 70a436c7719ca988e98e9d8a77043f9a148925dc Mon Sep 17 00:00:00 2001 From: Samuel Shuert Date: Fri, 26 Sep 2025 19:49:46 +0000 Subject: [PATCH] knotserver/internal: add create PR message on git push Change-Id: pylzpxmqulmpyyntlyswrsxkqzkxyvwp Respond to a successful push with a URL to create a PR pointing to the default branch. This behavior is made to mimic other Git forges. Signed-off-by: Samuel Shuert --- knotserver/internal.go | 45 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/knotserver/internal.go b/knotserver/internal.go index fb70c318..228a2e14 100644 --- a/knotserver/internal.go +++ b/knotserver/internal.go @@ -15,6 +15,7 @@ import ( "github.com/go-chi/chi/v5/middleware" "tangled.org/core/api/tangled" "tangled.org/core/hook" + "tangled.org/core/idresolver" "tangled.org/core/knotserver/config" "tangled.org/core/knotserver/db" "tangled.org/core/knotserver/git" @@ -118,6 +119,18 @@ func (h *InternalHandle) PostReceiveHook(w http.ResponseWriter, r *http.Request) // non-fatal } + if (line.NewSha.String() != line.OldSha.String()) && line.OldSha.IsZero() { + msg, err := h.replyCompare(line, gitUserDid, gitRelativeDir, repoName, r.Context()) + if err != nil { + l.Error("failed to reply with compare link", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) + // non-fatal + } else { + for msgLine := range msg { + resp.Messages = append(resp.Messages, msg[msgLine]) + } + } + } + err = h.triggerPipeline(&resp.Messages, line, gitUserDid, repoDid, repoName, pushOptions) if err != nil { l.Error("failed to trigger pipeline", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) @@ -128,6 +141,38 @@ func (h *InternalHandle) PostReceiveHook(w http.ResponseWriter, r *http.Request) writeJSON(w, resp) } +func (h *InternalHandle) replyCompare(line git.PostReceiveLine, gitUserDid string, gitRelativeDir string, repoName string, ctx context.Context) ([]string, error) { + l := h.l.With("handler", "replyCompare") + userIdent, err := idresolver.DefaultResolver().ResolveIdent(ctx, gitUserDid) + user := gitUserDid + if err != nil { + l.Error("Failed to fetch user identity", "err", err) + // non-fatal + } else { + user = userIdent.Handle.String() + } + gr, err := git.PlainOpen(gitRelativeDir) + if err != nil { + l.Error("Failed to open git repository", "err", err) + return []string{}, err + } + defaultBranch, err := gr.FindMainBranch() + if err != nil { + l.Error("Failed to fetch default branch", "err", err) + return []string{}, err + } + if line.Ref == fmt.Sprintf("refs/heads/%s", defaultBranch) { + return []string{}, nil + } + ZWS := "​" + var msg []string + msg = append(msg, ZWS) + msg = append(msg, fmt.Sprintf("Create a PR pointing to %s", defaultBranch)) + msg = append(msg, fmt.Sprintf("\t%s/%s/%s/compare/%s...%s", h.c.AppViewEndpoint, user, repoName, defaultBranch, strings.TrimPrefix(line.Ref, "refs/heads/"))) + msg = append(msg, ZWS) + return msg, nil +} + func (h *InternalHandle) insertRefUpdate(line git.PostReceiveLine, gitUserDid, repoDid, repoName string) error { didSlashRepo, err := securejoin.SecureJoin(repoDid, repoName) if err != nil { -- 2.43.0