Something went wrong. Try again.
Monorepo for Tangled tangled.org
Something went wrong. Try again.
Go
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161package pulls
import ( "context" "fmt" "net/http" "strconv"
"tangled.org/core/api/tangled" "tangled.org/core/appview/db" "tangled.org/core/appview/models" "tangled.org/core/appview/pages" "tangled.org/core/xrpc/xrpcclient"
"github.com/bluesky-social/indigo/atproto/syntax" "github.com/go-chi/chi/v5")
// htmx fragmentfunc (s *Pulls) PullActions(w http.ResponseWriter, r *http.Request) { l := s.logger.With("handler", "PullActions")
switch r.Method { case http.MethodGet: user := s.oauth.GetMultiAccountUser(r) if user != nil { l = l.With("user", user.Did) }
f, err := s.repoResolver.Resolve(r) if err != nil { l.Error("failed to get repo and knot", "err", err) return }
pull, ok := r.Context().Value("pull").(*models.Pull) if !ok { l.Error("failed to get pull") s.pages.Notice(w, "pull-error", "Failed to edit patch. Try again later.") return } l = l.With("pull_id", pull.PullId, "pull_owner", pull.OwnerDid)
versionNumber, err := strconv.Atoi(chi.URLParam(r, "version")) if err != nil { versionNumber = pull.LatestVersionNumber() } if versionNumber >= len(pull.Versions) { http.Error(w, "bad round id", http.StatusBadRequest) l.Error("failed to parse round id", "err", err, "round_number", versionNumber) return }
isLastVersion := versionNumber == pull.LatestVersionNumber()
var workflowsChanged bool var changedWorkflows []string hasPipeline := false if isLastVersion && f.Spindle != "" { pipelines := fetchPipelines(r.Context(), l, f, []string{pull.LatestSha()}) _, hasPipeline = pipelines[pull.LatestSha()]
if pull.IsForkBased() && !hasPipeline { latest := pull.LatestVersion() changedWorkflows, err = func(ctx context.Context) ([]string, error) { base, err := s.resolveRev(ctx, pull.RepoDid, pull.TargetBranch) if err != nil { return nil, fmt.Errorf("failed to resolve target branch: %w", err) } return s.changedWorkflowFiles(ctx, pull.RepoDid, base, pull.SourceRepo, latest.Head) }(r.Context()) if err != nil { l.Error("failed to inspect latest round's patch for workflow changes", "err", err) } workflowsChanged = len(changedWorkflows) > 0 } }
// only the last round's buttons and banners use merge/resubmit checks var mergeCheckParams pages.MergeCheckParams var resubmitResult = pages.Unknown if isLastVersion { mergeCheckParams = s.composeMergeCheck(r.Context(), f, pull.TargetBranch, pull.SourceRepo, pull.LatestVersion().Head) if user != nil && syntax.DID(user.Did) == pull.OwnerDid { resubmitResult = s.resubmitCheck(r.Context(), pull) } }
s.pages.PullActionsFragment(w, pages.PullActionsParams{ BaseParams: pages.BaseParamsFromContext(r.Context()), RepoInfo: s.repoResolver.GetRepoInfo(r, user), Pull: pull, RoundNumber: versionNumber, MergeCheck: mergeCheckParams, ResubmitCheck: resubmitResult, BranchDeleteStatus: s.branchDeleteStatus(r, f, pull),
WorkflowsChanged: workflowsChanged, ChangedWorkflowFiles: changedWorkflows, HasPipeline: hasPipeline, }) return }}
func (s *Pulls) branchDeleteStatus(r *http.Request, repo *models.Repo, pull *models.Pull) *pages.BranchDeleteStatus { if pull.State != models.PullMerged || pull.SourceBranch == nil { return nil }
user := s.oauth.GetMultiAccountUser(r) if user == nil { return nil }
branch := *pull.SourceBranch
if syntax.DID(repo.RepoDid) != pull.SourceRepo { var err error repo, err = db.GetRepoByDid(s.db, pull.SourceRepo.String()) if err != nil { return nil } }
// user can only delete branch if they are a collaborator in the repo that the branch belongs to if !s.acl.HasRepoPermission(r.Context(), repo, user.Did, "repo:push") { return nil }
xrpcc := s.knotMirrorXRPC resp, err := tangled.GitTempGetBranch(r.Context(), xrpcc, branch, repo.RepoDid) if xrpcerr := xrpcclient.HandleXrpcErr(err); xrpcerr != nil { s.logger.Error("failed to get branch", "xrpcerr", xrpcerr, "err", err) return nil }
return &pages.BranchDeleteStatus{ Repo: repo, Branch: resp.Name, }}
func (s *Pulls) resubmitCheck(ctx context.Context, pull *models.Pull) pages.ResubmitResult { if pull.State == models.PullMerged || pull.State == models.PullAbandoned || pull.SourceBranch == nil { return pages.Unknown }
sourceSha, err := s.resolveRev(ctx, pull.SourceRepo, *pull.SourceBranch) if err != nil { s.logger.Error("failed to resolve source branch", "err", err, "pull_id", pull.PullId, "branch", *pull.SourceBranch) return pages.Unknown }
if pull.LatestVersion().Head != sourceSha { return pages.ShouldResubmit }
return pages.ShouldNotResubmit}