diff --git a/integrations/api_pull_test.go b/integrations/api_pull_test.go index 9e22be5755b..61daf917ff2 100644 --- a/integrations/api_pull_test.go +++ b/integrations/api_pull_test.go @@ -58,7 +58,7 @@ func TestAPIMergePullWIP(t *testing.T) { session.MakeRequest(t, req, http.StatusMethodNotAllowed) } -func TestAPICreatePullSuccess1(t *testing.T) { +func TestAPICreatePullSuccess(t *testing.T) { defer prepareTestEnv(t)() repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository) // repo10 have code, pulls units. @@ -78,7 +78,7 @@ func TestAPICreatePullSuccess1(t *testing.T) { session.MakeRequest(t, req, 201) } -func TestAPICreatePullSuccess2(t *testing.T) { +func TestAPIEditPull(t *testing.T) { defer prepareTestEnv(t)() repo10 := models.AssertExistsAndLoadBean(t, &models.Repository{ID: 10}).(*models.Repository) owner10 := models.AssertExistsAndLoadBean(t, &models.User{ID: repo10.OwnerID}).(*models.User) @@ -90,6 +90,21 @@ func TestAPICreatePullSuccess2(t *testing.T) { Base: "master", Title: "create a success pr", }) + pull := new(api.PullRequest) + resp := session.MakeRequest(t, req, 201) + DecodeJSON(t, resp, pull) + assert.EqualValues(t, "master", pull.Base.Name) + + req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{ + Base: "feature/1", + Title: "edit a this pr", + }) + resp = session.MakeRequest(t, req, 201) + DecodeJSON(t, resp, pull) + assert.EqualValues(t, "feature/1", pull.Base.Name) - session.MakeRequest(t, req, 201) + req = NewRequestWithJSON(t, http.MethodPatch, fmt.Sprintf("/api/v1/repos/%s/%s/pulls/%d?token=%s", owner10.Name, repo10.Name, pull.Index, token), &api.EditPullRequestOption{ + Base: "not-exist", + }) + session.MakeRequest(t, req, 404) } diff --git a/modules/structs/pull.go b/modules/structs/pull.go index c4ec7d416a9..90b3807ddb8 100644 --- a/modules/structs/pull.go +++ b/modules/structs/pull.go @@ -82,6 +82,7 @@ type CreatePullRequestOption struct { type EditPullRequestOption struct { Title string `json:"title"` Body string `json:"body"` + Base string `json:"base"` Assignee string `json:"assignee"` Assignees []string `json:"assignees"` Milestone int64 `json:"milestone"` diff --git a/routers/api/v1/repo/pull.go b/routers/api/v1/repo/pull.go index bddf4e48f70..8425aa6129a 100644 --- a/routers/api/v1/repo/pull.go +++ b/routers/api/v1/repo/pull.go @@ -382,6 +382,8 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { // "$ref": "#/responses/PullRequest" // "403": // "$ref": "#/responses/forbidden" + // "409": + // "$ref": "#/responses/error" // "412": // "$ref": "#/responses/error" // "422": @@ -508,6 +510,30 @@ func EditPullRequest(ctx *context.APIContext, form api.EditPullRequestOption) { notification.NotifyIssueChangeStatus(ctx.User, issue, statusChangeComment, issue.IsClosed) } + // change pull target branch + if len(form.Base) != 0 && form.Base != pr.BaseBranch { + if !ctx.Repo.GitRepo.IsBranchExist(form.Base) { + ctx.Error(http.StatusNotFound, "NewBaseBranchNotExist", fmt.Errorf("new base '%s' not exist", form.Base)) + return + } + if err := pull_service.ChangeTargetBranch(pr, ctx.User, form.Base); err != nil { + if models.IsErrPullRequestAlreadyExists(err) { + ctx.Error(http.StatusConflict, "IsErrPullRequestAlreadyExists", err) + return + } else if models.IsErrIssueIsClosed(err) { + ctx.Error(http.StatusUnprocessableEntity, "IsErrIssueIsClosed", err) + return + } else if models.IsErrPullRequestHasMerged(err) { + ctx.Error(http.StatusConflict, "IsErrPullRequestHasMerged", err) + return + } else { + ctx.InternalServerError(err) + } + return + } + notification.NotifyPullRequestChangeTargetBranch(ctx.User, pr, form.Base) + } + // Refetch from database pr, err = models.GetPullRequestByIndex(ctx.Repo.Repository.ID, pr.Index) if err != nil { diff --git a/templates/swagger/v1_json.tmpl b/templates/swagger/v1_json.tmpl index 2a8f0457b2f..5058166ab7d 100644 --- a/templates/swagger/v1_json.tmpl +++ b/templates/swagger/v1_json.tmpl @@ -6593,6 +6593,9 @@ "403": { "$ref": "#/responses/forbidden" }, + "409": { + "$ref": "#/responses/error" + }, "412": { "$ref": "#/responses/error" }, @@ -11977,6 +11980,10 @@ }, "x-go-name": "Assignees" }, + "base": { + "type": "string", + "x-go-name": "Base" + }, "body": { "type": "string", "x-go-name": "Body"