diff --git a/pkg/cmd/issue/create/create.go b/pkg/cmd/issue/create/create.go index 640057100..51f828f8d 100644 --- a/pkg/cmd/issue/create/create.go +++ b/pkg/cmd/issue/create/create.go @@ -242,7 +242,7 @@ func createRun(opts *CreateOptions) (err error) { } allowPreview := !tb.HasMetadata() && utils.ValidURL(openURL) - action, err = prShared.ConfirmSubmission(allowPreview, repo.ViewerCanTriage()) + action, err = prShared.ConfirmIssueSubmission(allowPreview, repo.ViewerCanTriage()) if err != nil { err = fmt.Errorf("unable to confirm: %w", err) return @@ -260,7 +260,7 @@ func createRun(opts *CreateOptions) (err error) { return } - action, err = prShared.ConfirmSubmission(!tb.HasMetadata(), false) + action, err = prShared.ConfirmIssueSubmission(!tb.HasMetadata(), false) if err != nil { return } diff --git a/pkg/cmd/issue/create/create_test.go b/pkg/cmd/issue/create/create_test.go index 69ec38a37..ae98535c5 100644 --- a/pkg/cmd/issue/create/create_test.go +++ b/pkg/cmd/issue/create/create_test.go @@ -473,7 +473,9 @@ func TestIssueCreate_nonLegacyTemplate(t *testing.T) { as.StubPrompt("Choose a template").AnswerWith("Submit a request") as.StubPrompt("Body").AnswerDefault() - as.StubPrompt("What's next?").AnswerWith("Submit") + as.StubPrompt("What's next?"). + AssertOptions([]string{"Submit", "Continue in browser", "Cancel"}). + AnswerWith("Submit") output, err := runCommandWithRootDirOverridden(http, true, `-t hello`, "./fixtures/repoWithNonLegacyIssueTemplates") if err != nil { diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index a642a1def..f0b4c7f94 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -312,7 +312,7 @@ func createRun(opts *CreateOptions) (err error) { allowPreview := !state.HasMetadata() && utils.ValidURL(openURL) allowMetadata := ctx.BaseRepo.ViewerCanTriage() - action, err := shared.ConfirmSubmission(allowPreview, allowMetadata) + action, err := shared.ConfirmPRSubmission(allowPreview, allowMetadata, state.Draft) if err != nil { return fmt.Errorf("unable to confirm: %w", err) } @@ -329,7 +329,7 @@ func createRun(opts *CreateOptions) (err error) { return } - action, err = shared.ConfirmSubmission(!state.HasMetadata(), false) + action, err = shared.ConfirmPRSubmission(!state.HasMetadata(), false, state.Draft) if err != nil { return } @@ -350,6 +350,11 @@ func createRun(opts *CreateOptions) (err error) { return previewPR(*opts, openURL) } + if action == shared.SubmitDraftAction { + state.Draft = true + return submitPR(*opts, *ctx, *state) + } + if action == shared.SubmitAction { return submitPR(*opts, *ctx, *state) } diff --git a/pkg/cmd/pr/create/create_test.go b/pkg/cmd/pr/create/create_test.go index 9aab1c850..5ba641eed 100644 --- a/pkg/cmd/pr/create/create_test.go +++ b/pkg/cmd/pr/create/create_test.go @@ -371,6 +371,7 @@ func TestPRCreate(t *testing.T) { assert.Equal(t, "my body", input["body"].(string)) assert.Equal(t, "master", input["baseRefName"].(string)) assert.Equal(t, "feature", input["headRefName"].(string)) + assert.Equal(t, false, input["draft"].(bool)) })) cs, cmdTeardown := run.Stub() @@ -633,7 +634,7 @@ func TestPRCreate_nonLegacyTemplate(t *testing.T) { AnswerWith("template1") as.StubPrompt("Body").AnswerDefault() as.StubPrompt("What's next?"). - AssertOptions([]string{"Submit", "Continue in browser", "Add metadata", "Cancel"}). + AssertOptions([]string{"Submit", "Submit as draft", "Continue in browser", "Add metadata", "Cancel"}). AnswerDefault() output, err := runCommandWithRootDirOverridden(http, nil, "feature", true, `-t "my title" -H feature`, "./fixtures/repoWithNonLegacyPRTemplates") @@ -862,6 +863,46 @@ func TestPRCreate_webProject(t *testing.T) { assert.Equal(t, "https://github.com/OWNER/REPO/compare/master...feature?body=&expand=1&projects=ORG%2F1", output.BrowsedURL) } +func TestPRCreate_draft(t *testing.T) { + http := initFakeHTTP() + defer http.Verify(t) + + http.StubRepoInfoResponse("OWNER", "REPO", "master") + shared.RunCommandFinder("feature", nil, nil) + http.Register( + httpmock.GraphQL(`query PullRequestTemplates\b`), + httpmock.StringResponse(` + { "data": { "repository": { "pullRequestTemplates": [ + { "filename": "template1", + "body": "this is a bug" }, + { "filename": "template2", + "body": "this is a enhancement" } + ] } } }`), + ) + http.Register( + httpmock.GraphQL(`mutation PullRequestCreate\b`), + httpmock.GraphQLMutation(` + { "data": { "createPullRequest": { "pullRequest": { + "URL": "https://github.com/OWNER/REPO/pull/12" + } } } } + `, func(input map[string]interface{}) { + assert.Equal(t, true, input["draft"].(bool)) + })) + + as := prompt.NewAskStubber(t) + + as.StubPrompt("Choose a template").AnswerDefault() + as.StubPrompt("Body").AnswerDefault() + as.StubPrompt("What's next?"). + AssertOptions([]string{"Submit", "Submit as draft", "Continue in browser", "Add metadata", "Cancel"}). + AnswerWith("Submit as draft") + + output, err := runCommand(http, nil, "feature", true, `-t "my title" -H feature`) + require.NoError(t, err) + + assert.Equal(t, "https://github.com/OWNER/REPO/pull/12\n", output.String()) +} + func Test_determineTrackingBranch_empty(t *testing.T) { cs, cmdTeardown := run.Stub() defer cmdTeardown(t) diff --git a/pkg/cmd/pr/shared/survey.go b/pkg/cmd/pr/shared/survey.go index 4597f777b..ff22e3722 100644 --- a/pkg/cmd/pr/shared/survey.go +++ b/pkg/cmd/pr/shared/survey.go @@ -23,19 +23,33 @@ const ( MetadataAction EditCommitMessageAction EditCommitSubjectAction + SubmitDraftAction noMilestone = "(none)" + + submitLabel = "Submit" + submitDraftLabel = "Submit as draft" + previewLabel = "Continue in browser" + metadataLabel = "Add metadata" + cancelLabel = "Cancel" ) -func ConfirmSubmission(allowPreview bool, allowMetadata bool) (Action, error) { - const ( - submitLabel = "Submit" - previewLabel = "Continue in browser" - metadataLabel = "Add metadata" - cancelLabel = "Cancel" - ) +func ConfirmIssueSubmission(allowPreview bool, allowMetadata bool) (Action, error) { + return confirmSubmission(allowPreview, allowMetadata, false, false) +} - options := []string{submitLabel} +func ConfirmPRSubmission(allowPreview, allowMetadata, isDraft bool) (Action, error) { + return confirmSubmission(allowPreview, allowMetadata, true, isDraft) +} + +func confirmSubmission(allowPreview, allowMetadata, allowDraft, isDraft bool) (Action, error) { + var options []string + if !isDraft { + options = append(options, submitLabel) + } + if allowDraft { + options = append(options, submitDraftLabel) + } if allowPreview { options = append(options, previewLabel) } @@ -65,6 +79,8 @@ func ConfirmSubmission(allowPreview bool, allowMetadata bool) (Action, error) { switch options[confirmAnswers.Confirmation] { case submitLabel: return SubmitAction, nil + case submitDraftLabel: + return SubmitDraftAction, nil case previewLabel: return PreviewAction, nil case metadataLabel: