Monorepo for Tangled tangled.org

hooks: add create PR message on git push #612

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 me@thecoded.prof

Labels
enhancement
assignee

None yet.

Participants 2
AT URI
at://did:plc:k2zmz2l3hvfr44tmlhewol2j/sh.tangled.repo.pull/3lzwhi232k322
+46
Diff #4
+46
knotserver/internal.go
··· 13 13 securejoin "github.com/cyphar/filepath-securejoin" 14 14 "github.com/go-chi/chi/v5" 15 15 "github.com/go-chi/chi/v5/middleware" 16 + "github.com/go-git/go-git/v5/plumbing" 16 17 "tangled.org/core/api/tangled" 17 18 "tangled.org/core/hook" 19 + "tangled.org/core/idresolver" 18 20 "tangled.org/core/knotserver/config" 19 21 "tangled.org/core/knotserver/db" 20 22 "tangled.org/core/knotserver/git" ··· 118 120 // non-fatal 119 121 } 120 122 123 + if (line.NewSha.String() != line.OldSha.String()) && line.OldSha.IsZero() { 124 + msg, err := h.replyCompare(line, gitUserDid, gitRelativeDir, repoName, r.Context()) 125 + if err != nil { 126 + l.Error("failed to reply with compare link", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) 127 + // non-fatal 128 + } else { 129 + for msgLine := range msg { 130 + resp.Messages = append(resp.Messages, msg[msgLine]) 131 + } 132 + } 133 + } 134 + 121 135 err = h.triggerPipeline(&resp.Messages, line, gitUserDid, repoDid, repoName, pushOptions) 122 136 if err != nil { 123 137 l.Error("failed to trigger pipeline", "err", err, "line", line, "did", gitUserDid, "repo", gitRelativeDir) ··· 128 142 writeJSON(w, resp) 129 143 } 130 144 145 + func (h *InternalHandle) replyCompare(line git.PostReceiveLine, gitUserDid string, gitRelativeDir string, repoName string, ctx context.Context) ([]string, error) { 146 + l := h.l.With("handler", "replyCompare") 147 + userIdent, err := idresolver.DefaultResolver().ResolveIdent(ctx, gitUserDid) 148 + user := gitUserDid 149 + if err != nil { 150 + l.Error("Failed to fetch user identity", "err", err) 151 + // non-fatal 152 + } else { 153 + user = userIdent.Handle.String() 154 + } 155 + gr, err := git.PlainOpen(gitRelativeDir) 156 + if err != nil { 157 + l.Error("Failed to open git repository", "err", err) 158 + return []string{}, err 159 + } 160 + defaultBranch, err := gr.FindMainBranch() 161 + if err != nil { 162 + l.Error("Failed to fetch default branch", "err", err) 163 + return []string{}, err 164 + } 165 + if line.Ref == plumbing.NewBranchReferenceName(defaultBranch).String() { 166 + return []string{}, nil 167 + } 168 + ZWS := "\u200B" 169 + var msg []string 170 + msg = append(msg, ZWS) 171 + msg = append(msg, fmt.Sprintf("Create a PR pointing to %s", defaultBranch)) 172 + msg = append(msg, fmt.Sprintf("\t%s/%s/%s/compare/%s...%s", h.c.AppViewEndpoint, user, repoName, defaultBranch, strings.TrimPrefix(line.Ref, "refs/heads/"))) 173 + msg = append(msg, ZWS) 174 + return msg, nil 175 + } 176 + 131 177 func (h *InternalHandle) insertRefUpdate(line git.PostReceiveLine, gitUserDid, repoDid, repoName string) error { 132 178 didSlashRepo, err := securejoin.SecureJoin(repoDid, repoName) 133 179 if err != nil {

History

5 rounds 3 comments
sign up or login to add to the discussion
1 commit
expand
knotserver/internal: add create PR message on git push
expand 1 comment

lgtm thanks!

pull request successfully merged
1 commit
expand
knotserver/internal: add create PR message on git push
expand 0 comments
1 commit
expand
knotserver/internal: add create PR message on git push
expand 0 comments
1 commit
expand
knotserver: add create PR message on git push
expand 1 comment

this looks pretty good now! the only thing i'd want from this is for this handler to be separated out, just like how insertRefUpdate and triggerPipeline are split up.

this is because we don't want errors here to end the function, even the userIdent fails to resolve, we want to continue with the rest of the post-receive handler.

1 commit
expand
hooks: add create PR message on git push
expand 1 comment

i would prefer if this addition were made to knotserver/internal.go along side the other post-recieve handlers (insertRefUpdate and triggerPipeline). the way to return strings to the user in this handler are via the HookResponse struct.

there is an example of this in triggerPipeline which conditionally returns pipeline compilation status back to the user, by writing messages into resp.Messages. we could do something similar here.

that being said, the change largely looks good to me! thanks for working on this.