diff --git a/pkg/cmd/pr/create/create.go b/pkg/cmd/pr/create/create.go index 75d4b58f1..1882488a8 100644 --- a/pkg/cmd/pr/create/create.go +++ b/pkg/cmd/pr/create/create.go @@ -480,9 +480,14 @@ func NewCreateContext(opts *CreateOptions) (*CreateContext, error) { } client := api.NewClientFromHTTP(httpClient) + // TODO: consider obtaining remotes from GitClient instead remotes, err := opts.Remotes() if err != nil { - return nil, err + // When a repo override value is given, ignore errors when fetching git remotes + // to support using this command outside of git repos. + if opts.RepoOverride == "" { + return nil, err + } } repoContext, err := ghContext.ResolveRemotesToRepos(remotes, client, opts.RepoOverride) diff --git a/pkg/cmd/pr/create/create_test.go b/pkg/cmd/pr/create/create_test.go index 0764ffe3b..1a709ee35 100644 --- a/pkg/cmd/pr/create/create_test.go +++ b/pkg/cmd/pr/create/create_test.go @@ -2,6 +2,7 @@ package create import ( "encoding/json" + "errors" "fmt" "net/http" "os" @@ -17,7 +18,6 @@ import ( "github.com/cli/cli/v2/internal/ghrepo" "github.com/cli/cli/v2/internal/run" "github.com/cli/cli/v2/pkg/cmd/pr/shared" - prShared "github.com/cli/cli/v2/pkg/cmd/pr/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" @@ -779,7 +779,7 @@ func Test_createRun(t *testing.T) { setup: func(opts *CreateOptions, t *testing.T) func() { tmpfile, err := os.CreateTemp(t.TempDir(), "testrecover*") assert.NoError(t, err) - state := prShared.IssueMetadataState{ + state := shared.IssueMetadataState{ Title: "recovered title", Body: "recovered body", Reviewers: []string{"jillValentine"}, @@ -811,6 +811,31 @@ func Test_createRun(t *testing.T) { }, wantErr: "cannot open in browser: maximum URL length exceeded", }, + { + name: "no local git repo", + setup: func(opts *CreateOptions, t *testing.T) func() { + opts.Title = "My PR" + opts.TitleProvided = true + opts.Body = "" + opts.BodyProvided = true + opts.HeadBranch = "feature" + opts.RepoOverride = "OWNER/REPO" + opts.Remotes = func() (context.Remotes, error) { + return nil, errors.New("not a git repository") + } + return func() {} + }, + httpStubs: func(reg *httpmock.Registry, t *testing.T) { + reg.Register( + httpmock.GraphQL(`mutation PullRequestCreate\b`), + httpmock.StringResponse(` + { "data": { "createPullRequest": { "pullRequest": { + "URL": "https://github.com/OWNER/REPO/pull/12" + } } } } + `)) + }, + expectedOut: "https://github.com/OWNER/REPO/pull/12\n", + }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { @@ -997,7 +1022,7 @@ func Test_generateCompareURL(t *testing.T) { tests := []struct { name string ctx CreateContext - state prShared.IssueMetadataState + state shared.IssueMetadataState want string wantErr bool }{ @@ -1018,7 +1043,7 @@ func Test_generateCompareURL(t *testing.T) { BaseBranch: "a", HeadBranchLabel: "b", }, - state: prShared.IssueMetadataState{ + state: shared.IssueMetadataState{ Labels: []string{"one", "two three"}, }, want: "https://github.com/OWNER/REPO/compare/a...b?body=&expand=1&labels=one%2Ctwo+three",