feat: add commit footers for pull merge #109

closed
opened by dvjn.dev targeting master from dvjn.dev/core: push-rwutqnoxqxlr
Changed files
+39 -8
appview
knotclient
state
knotserver
types
+7 -6
types/merge.go
··· 13 13 } 14 14 15 15 type MergeRequest struct { 16 - Patch string `json:"patch"` 17 - AuthorName string `json:"authorName,omitempty"` 18 - AuthorEmail string `json:"authorEmail,omitempty"` 19 - CommitBody string `json:"commitBody,omitempty"` 20 - CommitMessage string `json:"commitMessage,omitempty"` 21 - Branch string `json:"branch"` 16 + Patch string `json:"patch"` 17 + AuthorName string `json:"authorName,omitempty"` 18 + AuthorEmail string `json:"authorEmail,omitempty"` 19 + CommitBody string `json:"commitBody,omitempty"` 20 + CommitMessage string `json:"commitMessage,omitempty"` 21 + CommitFooters map[string]string `json:"commitFooters,omitempty"` 22 + Branch string `json:"branch"` 22 23 }
+2 -1
appview/knotclient/signer.go
··· 201 201 202 202 func (s *SignedClient) Merge( 203 203 patch []byte, 204 - ownerDid, targetRepo, branch, commitMessage, commitBody, authorName, authorEmail string, 204 + ownerDid, targetRepo, branch, commitMessage, commitBody, authorName, authorEmail string, footers map[string]string, 205 205 ) (*http.Response, error) { 206 206 const ( 207 207 Method = "POST" ··· 215 215 AuthorName: authorName, 216 216 AuthorEmail: authorEmail, 217 217 Patch: string(patch), 218 + CommitFooters: footers, 218 219 } 219 220 220 221 body, _ := json.Marshal(mr)
+8 -1
appview/state/pull.go
··· 1534 1534 log.Printf("failed to get primary email: %s", err) 1535 1535 } 1536 1536 1537 + actor := s.oauth.GetUser(r) // no need to check for nil as this is an authenticated request 1538 + 1539 + var footers = map[string]string{ 1540 + "Pull-id": string(pull.PullAt()), 1541 + "Merged-by": actor.Did, 1542 + } 1543 + 1537 1544 ksClient, err := knotclient.NewSignedClient(f.Knot, secret, s.config.Core.Dev) 1538 1545 if err != nil { 1539 1546 log.Printf("failed to create signed client for %s: %s", f.Knot, err) ··· 1542 1549 } 1543 1550 1544 1551 // Merge the pull request 1545 - resp, err := ksClient.Merge([]byte(pull.LatestPatch()), f.OwnerDid(), f.RepoName, pull.TargetBranch, pull.Title, pull.Body, ident.Handle.String(), email.Address) 1552 + resp, err := ksClient.Merge([]byte(pull.LatestPatch()), f.OwnerDid(), f.RepoName, pull.TargetBranch, pull.Title, pull.Body, ident.Handle.String(), email.Address, footers) 1546 1553 if err != nil { 1547 1554 log.Printf("failed to merge pull request: %s", err) 1548 1555 s.pages.Notice(w, "pull-merge-error", "Failed to merge pull request. Try again later.")
+21
knotserver/git/merge.go
··· 32 32 AuthorName string 33 33 AuthorEmail string 34 34 FormatPatch bool 35 + CommitFooters map[string]string 35 36 } 36 37 37 38 func (e ErrMerge) Error() string { ··· 88 89 var stderr bytes.Buffer 89 90 var cmd *exec.Cmd 90 91 92 + footers := "" 93 + for k, v := range opts.CommitFooters { 94 + footers += fmt.Sprintf("\n%s: %s", k, v) 95 + } 96 + 91 97 if checkOnly { 92 98 cmd = exec.Command("git", "-C", tmpDir, "apply", "--check", "-v", patchFile) 93 99 } else { 94 100 // if patch is a format-patch, apply using 'git am' 95 101 if opts.FormatPatch { 102 + patch, err := os.ReadFile(patchFile) 103 + if err != nil { 104 + return fmt.Errorf("failed to read patch file: %w", err) 105 + } 106 + 107 + re := regexp.MustCompile(`\n(Subject: )([\s\S]*?)(---)\n`) 108 + patch = re.ReplaceAll(patch, []byte("\n${1}${2}\n"+footers+"\n${3}\n")) 109 + 110 + err = os.WriteFile(patchFile, patch, 0o644) 111 + if err != nil { 112 + return fmt.Errorf("failed to write patch file: %w", err) 113 + } 114 + 96 115 amCmd := exec.Command("git", "-C", tmpDir, "am", patchFile) 97 116 amCmd.Stderr = &stderr 98 117 if err := amCmd.Run(); err != nil { ··· 139 158 commitArgs = append(commitArgs, "-m", opts.CommitBody) 140 159 } 141 160 161 + commitArgs = append(commitArgs, "-m", footers) 162 + 142 163 cmd = exec.Command("git", commitArgs...) 143 164 } else { 144 165 // If no commit message specified, use git-am which automatically creates a commit
+1
knotserver/routes.go
··· 732 732 AuthorEmail: data.AuthorEmail, 733 733 CommitBody: data.CommitBody, 734 734 CommitMessage: data.CommitMessage, 735 + CommitFooters: data.CommitFooters, 735 736 } 736 737 737 738 patch := data.Patch