This repository has no description
0

Configure Feed

Select the types of activity you want to include in your feed.

core / appview / pulls / merge.go
3.5 kB 117 lines
1package pulls 2 3import ( 4 "fmt" 5 "net/http" 6 "time" 7 8 "github.com/bluesky-social/indigo/atproto/syntax" 9 "tangled.org/core/api/tangled" 10 "tangled.org/core/appview/db" 11 "tangled.org/core/appview/models" 12 "tangled.org/core/appview/oauth" 13 "tangled.org/core/appview/reporesolver" 14 "tangled.org/core/orm" 15) 16 17func (s *Pulls) MergePull(w http.ResponseWriter, r *http.Request) { 18 l := s.logger.With("handler", "MergePull") 19 20 user := s.oauth.GetMultiAccountUser(r) 21 if user == nil { 22 l.Error("nil user") 23 s.pages.Notice(w, "pull-action-error", "You must be logged in to merge this pull.") 24 return 25 } 26 l = l.With("user", user.Did) 27 28 f, err := s.repoResolver.Resolve(r) 29 if err != nil { 30 l.Error("failed to resolve repo", "err", err) 31 s.pages.Notice(w, "pull-action-error", "Failed to merge pull request. Try again later.") 32 return 33 } 34 l = l.With("repo", f.RepoDid) 35 36 pull, ok := r.Context().Value("pull").(*models.Pull) 37 if !ok { 38 l.Error("failed to get pull") 39 s.pages.Notice(w, "pull-action-error", "Failed to merge patch. Try again later.") 40 return 41 } 42 l = l.With("pull_id", pull.PullId, "target_branch", pull.TargetBranch) 43 44 // merge target branch 45 { 46 client, err := s.oauth.ServiceClient( 47 r, 48 oauth.WithService(f.Knot), 49 oauth.WithLxm(tangled.GitMergeCommitNSID), 50 oauth.WithDev(s.config.Core.Dev), 51 oauth.WithTimeout(time.Second*20), // merge is quite slow on large repos, like witchsky 52 ) 53 if err != nil { 54 l.Error("failed to connect to knot server", "err", err, "knot", f.Knot) 55 s.pages.Notice(w, "pull-action-error", "Failed to merge pull request. Try again later.") 56 return 57 } 58 59 var mergeCommit *tangled.GitMergeCommit_Input_MergeCommit 60 // TODO: pass custom merge commit body 61 62 err = tangled.GitMergeCommit(r.Context(), client, &tangled.GitMergeCommit_Input{ 63 Target: &tangled.GitMergeCommit_Input_Target{ 64 Repo: pull.RepoDid.String(), 65 Branch: pull.TargetBranch, 66 }, 67 Source: &tangled.GitMergeCommit_Input_Source{ 68 Repo: pull.SourceRepo.String(), 69 Commit: pull.LatestVersion().Head, 70 }, 71 MergeCommit: mergeCommit, 72 Style: "rebase", 73 }) 74 if err != nil { 75 s.logger.Error("failed to merge", "err", err) 76 s.pages.Notice(w, "pull-action-error", err.Error()) 77 return 78 } 79 } 80 81 if err := s.writePullStatusRecord(r, user.Did, pull.AtUri(), models.StateMerged); err != nil { 82 l.Error("failed to write issue state record", "err", err) 83 s.pages.Notice(w, "issue-action", "Failed to close issue. Try again later.") 84 return 85 } 86 87 tx, err := s.db.Begin() 88 if err != nil { 89 l.Error("failed to start transaction", "err", err) 90 s.pages.Notice(w, "pull-action-error", "Failed to merge pull request. Try again later.") 91 return 92 } 93 defer tx.Rollback() 94 95 err = db.MergePulls( 96 tx, 97 orm.FilterEq("at_uri", pull.AtUri()), 98 ) 99 if err != nil { 100 l.Error("failed to update pull request status in database", "err", err) 101 s.pages.Notice(w, "pull-action-error", "Failed to merge pull request. Try again later.") 102 return 103 } 104 105 err = tx.Commit() 106 if err != nil { 107 // TODO: this is unsound, we should also revert the merge from the knotserver here 108 l.Error("failed to commit merge transaction", "err", err) 109 s.pages.Notice(w, "pull-action-error", "Failed to merge pull request. Try again later.") 110 return 111 } 112 113 s.notifier.NewPullState(r.Context(), syntax.DID(user.Did), pull) 114 115 ownerSlashRepo := reporesolver.GetBaseRepoPath(r, f) 116 s.pages.HxLocation(w, fmt.Sprintf("/%s/pulls/%d", ownerSlashRepo, pull.PullId)) 117}