add dry_run option to the merge API (#737)

This commit is contained in:
Marko Gacesa 2023-11-01 19:57:28 +00:00 committed by Harness
parent 0dac44031f
commit 3a7617a2e6
4 changed files with 51 additions and 8 deletions

View File

@ -39,11 +39,12 @@ import (
type MergeInput struct {
Method enum.MergeMethod `json:"method"`
SourceSHA string `json:"source_sha"`
DryRun bool `json:"dry_run"`
}
// Merge merges the pull request.
//
//nolint:gocognit
//nolint:gocognit,gocyclo,cyclop
func (c *Controller) Merge(
ctx context.Context,
session *auth.Session,
@ -54,7 +55,7 @@ func (c *Controller) Merge(
method, ok := in.Method.Sanitize()
if !ok {
return nil, nil, usererror.BadRequest(
fmt.Sprintf("wrong merge method type: %s", in.Method))
fmt.Sprintf("unsupported merge method: %s", in.Method))
}
in.Method = method
@ -168,6 +169,39 @@ func (c *Controller) Merge(
return nil, &types.MergeViolations{RuleViolations: violations}, nil
}
if in.DryRun {
conflictFiles := pr.MergeConflicts
// TODO: This is a temporary solution. The changes needed for the proper implementation:
// 1) GitRPC: Change the merge method to return SHAs (source/target/merge base) even in case of conflicts.
// 2) Event handler: Update target and merge base SHA in the event handler even in case of merge conflicts.
// 3) Here: Update the pull request target and merge base SHA in the DB if merge check status is unchecked.
// 4) Remove the recheck API.
if pr.MergeCheckStatus == enum.MergeCheckStatusUnchecked {
_, err = c.gitRPCClient.Merge(ctx, &gitrpc.MergeParams{
WriteParams: targetWriteParams,
BaseBranch: pr.TargetBranch,
HeadRepoUID: sourceRepo.GitUID,
HeadBranch: pr.SourceBranch,
HeadExpectedSHA: in.SourceSHA,
})
if gitrpc.ErrorStatus(err) == gitrpc.StatusNotMergeable {
conflictFiles = gitrpc.AsConflictFilesError(err)
} else if err != nil {
return nil, nil, fmt.Errorf("merge check execution failed: %w", err)
}
}
return &types.MergeResponse{
DryRun: true,
SHA: "",
BranchDeleted: ruleOut.DeleteSourceBranch,
ConflictFiles: conflictFiles,
RuleViolations: violations,
}, nil, nil
}
// TODO: for forking merge title might be different?
var mergeTitle string
if in.Method == enum.MergeMethod(gitrpcenum.MergeMethodSquash) {

View File

@ -238,6 +238,8 @@ func (s *Service) updateMergeDataInner(
pr.SourceBranch, newSHA)
}
conflicts := gitrpc.AsConflictFilesError(err)
isNotMergeableError := gitrpc.ErrorStatus(err) == gitrpc.StatusNotMergeable
if err != nil && !isNotMergeableError {
return fmt.Errorf("merge check failed for %d:%s and %d:%s with err: %w",
@ -255,9 +257,9 @@ func (s *Service) updateMergeDataInner(
if isNotMergeableError {
// TODO: gitrpc should return sha's either way, and also conflicting files!
pr.MergeCheckStatus = enum.MergeCheckStatusConflict
pr.MergeTargetSHA = &output.BaseSHA
// pr.MergeTargetSHA = &output.BaseSHA // TODO: Merge API doesn't return this when there are conflicts
pr.MergeSHA = nil
pr.MergeConflicts = nil
pr.MergeConflicts = conflicts
} else {
pr.MergeCheckStatus = enum.MergeCheckStatusMergeable
pr.MergeTargetSHA = &output.BaseSHA

View File

@ -508,6 +508,11 @@ func (s *PullReqStore) List(ctx context.Context, opts *types.PullReqFilter) ([]*
}
func mapPullReq(pr *pullReq) *types.PullReq {
var mergeConflicts []string
if pr.MergeConflicts.Valid {
mergeConflicts = strings.Split(pr.MergeConflicts.String, "\n")
}
return &types.PullReq{
ID: pr.ID,
Version: pr.Version,
@ -535,7 +540,7 @@ func mapPullReq(pr *pullReq) *types.PullReq {
MergeTargetSHA: pr.MergeTargetSHA.Ptr(),
MergeBaseSHA: pr.MergeBaseSHA,
MergeSHA: pr.MergeSHA.Ptr(),
MergeConflicts: pr.MergeConflicts.Ptr(),
MergeConflicts: mergeConflicts,
Author: types.PrincipalInfo{},
Merger: nil,
Stats: types.PullReqStats{
@ -550,6 +555,7 @@ func mapPullReq(pr *pullReq) *types.PullReq {
}
func mapInternalPullReq(pr *types.PullReq) *pullReq {
mergeConflicts := strings.Join(pr.MergeConflicts, "\n")
m := &pullReq{
ID: pr.ID,
Version: pr.Version,
@ -577,7 +583,7 @@ func mapInternalPullReq(pr *types.PullReq) *pullReq {
MergeTargetSHA: null.StringFromPtr(pr.MergeTargetSHA),
MergeBaseSHA: pr.MergeBaseSHA,
MergeSHA: null.StringFromPtr(pr.MergeSHA),
MergeConflicts: null.StringFromPtr(pr.MergeConflicts),
MergeConflicts: null.NewString(mergeConflicts, mergeConflicts != ""),
}
return m

View File

@ -54,7 +54,7 @@ type PullReq struct {
MergeTargetSHA *string `json:"merge_target_sha"`
MergeBaseSHA string `json:"merge_base_sha"`
MergeSHA *string `json:"merge_sha"`
MergeConflicts *string `json:"merge_conflicts,omitempty"`
MergeConflicts []string `json:"merge_conflicts,omitempty"`
Author PrincipalInfo `json:"author"`
Merger *PrincipalInfo `json:"merger"`
@ -139,8 +139,9 @@ type PullReqFileView struct {
}
type MergeResponse struct {
DryRun bool `json:"dry_run,omitempty"`
SHA string `json:"sha,omitempty"`
BranchDeleted bool `json:"branch_deleted"`
BranchDeleted bool `json:"branch_deleted,omitempty"`
ConflictFiles []string `json:"conflict_files,omitempty"`
RuleViolations []RuleViolations `json:"rule_violations,omitempty"`
}