Skip to content

Commit eb132a1

Browse files
committed
Merge remote-tracking branch 'origin/trunk' into checks
2 parents 2961c65 + 0083607 commit eb132a1

File tree

13 files changed

+274
-47
lines changed

13 files changed

+274
-47
lines changed

.github/CONTRIBUTING.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,16 @@
33
[legal]: https://help.github.com/articles/github-terms-of-service/#6-contributions-under-repository-license
44
[license]: ../LICENSE
55
[code-of-conduct]: CODE-OF-CONDUCT.md
6+
[bug issues]: https://github.com/cli/cli/issues?q=is%3Aopen+is%3Aissue+label%3Abug
7+
[feature request issues]: https://github.com/cli/cli/issues?q=is%3Aopen+is%3Aissue+label%3Aenhancement
68

79
Hi! Thanks for your interest in contributing to the GitHub CLI!
810

911
We accept pull requests for bug fixes and features where we've discussed the approach in an issue and given the go-ahead for a community member to work on it. We'd also love to hear about ideas for new features as issues.
1012

1113
Please do:
1214

15+
* check existing issues to verify that the [bug][bug issues] or [feature request][feature request issues] has not already been submitted
1316
* open an issue if things aren't working as expected
1417
* open an issue to propose a significant change
1518
* open a pull request to fix a bug

README.md

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,9 @@ the terminal next to where you are already working with `git` and your code.
99

1010
While in beta, GitHub CLI is available for repos hosted on GitHub.com only. It currently does not support repositories hosted on GitHub Enterprise Server or other hosting providers. We are planning on adding support for GitHub Enterprise Server after GitHub CLI is out of beta (likely towards the end of 2020), and we want to ensure that the API endpoints we use are more widely available for GHES versions that most GitHub customers are on.
1111

12-
## We need your feedback
12+
## We want your feedback
1313

14-
GitHub CLI is currently in its early development stages, and we're hoping to get feedback from people using it.
15-
16-
If you've installed and used `gh`, we'd love for you to take a short survey here (no more than five minutes): https://forms.gle/umxd3h31c7aMQFKG7
17-
18-
And if you spot bugs or have features that you'd really like to see in `gh`, please check out the [contributing page][]
14+
We'd love to hear your feedback about `gh`. If you spot bugs or have features that you'd really like to see in `gh`, please check out the [contributing page][].
1915

2016
## Usage
2117

@@ -27,14 +23,14 @@ And if you spot bugs or have features that you'd really like to see in `gh`, ple
2723

2824
## Documentation
2925

30-
Read the [official docs](https://cli.github.com/manual/) for more information.
26+
Read the [official docs][] for more information.
3127

3228
## Comparison with hub
3329

3430
For many years, [hub][] was the unofficial GitHub CLI tool. `gh` is a new project that helps us explore
3531
what an official GitHub CLI tool can look like with a fundamentally different design. While both
3632
tools bring GitHub to the terminal, `hub` behaves as a proxy to `git`, and `gh` is a standalone
37-
tool. Check out our [more detailed explanation](/docs/gh-vs-hub.md) to learn more.
33+
tool. Check out our [more detailed explanation][gh-vs-hub] to learn more.
3834

3935

4036
<!-- this anchor is linked to from elsewhere, so avoid renaming it -->
@@ -128,7 +124,7 @@ Install and upgrade:
128124
Install and upgrade:
129125

130126
1. Download the `.rpm` file from the [releases page][];
131-
2. Install the downloaded file: `sudo yum localinstall gh_*_linux_amd64.rpm`
127+
2. Install the downloaded file: `sudo yum localinstall gh_*_linux_amd64.rpm`
132128

133129
### openSUSE/SUSE Linux
134130

@@ -139,7 +135,7 @@ Install and upgrade:
139135

140136
### Arch Linux
141137

142-
Arch Linux users can install from the [community repo](https://www.archlinux.org/packages/community/x86_64/github-cli/):
138+
Arch Linux users can install from the [community repo][arch linux repo]:
143139

144140
```bash
145141
pacman -S github-cli
@@ -159,11 +155,14 @@ Download packaged binaries from the [releases page][].
159155

160156
### Build from source
161157

162-
See here on how to [build GitHub CLI from source](/docs/source.md).
158+
See here on how to [build GitHub CLI from source][build from source].
163159

164-
[docs]: https://cli.github.com/manual
160+
[official docs]: https://cli.github.com/manual
165161
[scoop]: https://scoop.sh
166162
[Chocolatey]: https://chocolatey.org
167163
[releases page]: https://github.com/cli/cli/releases/latest
168164
[hub]: https://github.com/github/hub
169165
[contributing page]: https://github.com/cli/cli/blob/trunk/.github/CONTRIBUTING.md
166+
[gh-vs-hub]: /docs/gh-vs-hub.md
167+
[arch linux repo]: https://www.archlinux.org/packages/community/x86_64/github-cli
168+
[build from source]: /docs/source.md

api/queries_pr.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -739,7 +739,7 @@ func CreatePullRequest(client *Client, repo *Repository, params map[string]inter
739739
}
740740
err := client.GraphQL(repo.RepoHost(), updateQuery, variables, &result)
741741
if err != nil {
742-
return nil, err
742+
return pr, err
743743
}
744744
}
745745

@@ -764,7 +764,7 @@ func CreatePullRequest(client *Client, repo *Repository, params map[string]inter
764764
}
765765
err := client.GraphQL(repo.RepoHost(), reviewQuery, variables, &result)
766766
if err != nil {
767-
return nil, err
767+
return pr, err
768768
}
769769
}
770770

api/queries_user.go

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,14 @@ func CurrentLoginName(client *Client, hostname string) (string, error) {
1414
err := gql.QueryNamed(context.Background(), "UserCurrent", &query, nil)
1515
return query.Viewer.Login, err
1616
}
17+
18+
func CurrentUserID(client *Client, hostname string) (string, error) {
19+
var query struct {
20+
Viewer struct {
21+
ID string
22+
}
23+
}
24+
gql := graphQLClient(client.http, hostname)
25+
err := gql.QueryNamed(context.Background(), "UserCurrent", &query, nil)
26+
return query.Viewer.ID, err
27+
}

auth/oauth.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ func (oa *OAuthFlow) ObtainAccessToken() (accessToken string, err error) {
6969
}
7070
}
7171

72-
if resp.StatusCode == 401 || resp.StatusCode == 403 || resp.StatusCode == 404 ||
72+
if resp.StatusCode == 401 || resp.StatusCode == 403 || resp.StatusCode == 404 || resp.StatusCode == 422 ||
7373
(resp.StatusCode == 400 && values != nil && values.Get("error") == "unauthorized_client") {
7474
// OAuth Device Flow is not available; continue with OAuth browser flow with a
7575
// local server endpoint as callback target

internal/config/config_setup.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import (
1212
"github.com/cli/cli/auth"
1313
"github.com/cli/cli/pkg/browser"
1414
"github.com/cli/cli/utils"
15+
"github.com/mattn/go-colorable"
1516
)
1617

1718
var (
@@ -29,7 +30,9 @@ func IsGitHubApp(id string) bool {
2930
}
3031

3132
func AuthFlowWithConfig(cfg Config, hostname, notice string, additionalScopes []string) (string, error) {
32-
token, userLogin, err := authFlow(hostname, notice, additionalScopes)
33+
stderr := colorable.NewColorableStderr()
34+
35+
token, userLogin, err := authFlow(hostname, stderr, notice, additionalScopes)
3336
if err != nil {
3437
return "", err
3538
}
@@ -48,14 +51,17 @@ func AuthFlowWithConfig(cfg Config, hostname, notice string, additionalScopes []
4851
return "", err
4952
}
5053

51-
AuthFlowComplete()
54+
fmt.Fprintf(stderr, "%s Authentication complete. %s to continue...\n",
55+
utils.GreenCheck(), utils.Bold("Press Enter"))
56+
_ = waitForEnter(os.Stdin)
57+
5258
return token, nil
5359
}
5460

55-
func authFlow(oauthHost, notice string, additionalScopes []string) (string, string, error) {
61+
func authFlow(oauthHost string, w io.Writer, notice string, additionalScopes []string) (string, string, error) {
5662
var verboseStream io.Writer
5763
if strings.Contains(os.Getenv("DEBUG"), "oauth") {
58-
verboseStream = os.Stderr
64+
verboseStream = w
5965
}
6066

6167
minimumScopes := []string{"repo", "read:org", "gist"}
@@ -73,9 +79,9 @@ func authFlow(oauthHost, notice string, additionalScopes []string) (string, stri
7379
HTTPClient: http.DefaultClient,
7480
OpenInBrowser: func(url, code string) error {
7581
if code != "" {
76-
fmt.Fprintf(os.Stderr, "%s First copy your one-time code: %s\n", utils.Yellow("!"), utils.Bold(code))
82+
fmt.Fprintf(w, "%s First copy your one-time code: %s\n", utils.Yellow("!"), utils.Bold(code))
7783
}
78-
fmt.Fprintf(os.Stderr, "- %s to open %s in your browser... ", utils.Bold("Press Enter"), oauthHost)
84+
fmt.Fprintf(w, "- %s to open %s in your browser... ", utils.Bold("Press Enter"), oauthHost)
7985
_ = waitForEnter(os.Stdin)
8086

8187
browseCmd, err := browser.Command(url)
@@ -84,15 +90,15 @@ func authFlow(oauthHost, notice string, additionalScopes []string) (string, stri
8490
}
8591
err = browseCmd.Run()
8692
if err != nil {
87-
fmt.Fprintf(os.Stderr, "%s Failed opening a web browser at %s\n", utils.Red("!"), url)
88-
fmt.Fprintf(os.Stderr, " %s\n", err)
89-
fmt.Fprint(os.Stderr, " Please try entering the URL in your browser manually\n")
93+
fmt.Fprintf(w, "%s Failed opening a web browser at %s\n", utils.Red("!"), url)
94+
fmt.Fprintf(w, " %s\n", err)
95+
fmt.Fprint(w, " Please try entering the URL in your browser manually\n")
9096
}
9197
return nil
9298
},
9399
}
94100

95-
fmt.Fprintln(os.Stderr, notice)
101+
fmt.Fprintln(w, notice)
96102

97103
token, err := flow.ObtainAccessToken()
98104
if err != nil {
@@ -107,12 +113,6 @@ func authFlow(oauthHost, notice string, additionalScopes []string) (string, stri
107113
return token, userLogin, nil
108114
}
109115

110-
func AuthFlowComplete() {
111-
fmt.Fprintf(os.Stderr, "%s Authentication complete. %s to continue...\n",
112-
utils.GreenCheck(), utils.Bold("Press Enter"))
113-
_ = waitForEnter(os.Stdin)
114-
}
115-
116116
func getViewer(hostname, token string) (string, error) {
117117
http := api.NewClient(api.AddHeader("Authorization", fmt.Sprintf("token %s", token)))
118118
return api.CurrentLoginName(http, hostname)

pkg/cmd/auth/login/login.go

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ func NewCmdLogin(f *cmdutil.Factory, runF func(*LoginOptions) error) *cobra.Comm
8787
}
8888
}
8989

90+
if cmd.Flags().Changed("hostname") {
91+
if err := hostnameValidator(opts.Hostname); err != nil {
92+
return &cmdutil.FlagError{Err: fmt.Errorf("error parsing --hostname: %w", err)}
93+
}
94+
}
95+
9096
if runF != nil {
9197
return runF(opts)
9298
}
@@ -156,7 +162,7 @@ func loginRun(opts *LoginOptions) error {
156162
if isEnterprise {
157163
err := prompt.SurveyAskOne(&survey.Input{
158164
Message: "GHE hostname:",
159-
}, &hostname, survey.WithValidator(survey.Required))
165+
}, &hostname, survey.WithValidator(hostnameValidator))
160166
if err != nil {
161167
return fmt.Errorf("could not prompt: %w", err)
162168
}
@@ -256,7 +262,7 @@ func loginRun(opts *LoginOptions) error {
256262

257263
gitProtocol = strings.ToLower(gitProtocol)
258264

259-
fmt.Fprintf(opts.IO.ErrOut, "- gh config set -h%s git_protocol %s\n", hostname, gitProtocol)
265+
fmt.Fprintf(opts.IO.ErrOut, "- gh config set -h %s git_protocol %s\n", hostname, gitProtocol)
260266
err = cfg.Set(hostname, "git_protocol", gitProtocol)
261267
if err != nil {
262268
return err
@@ -288,3 +294,14 @@ func loginRun(opts *LoginOptions) error {
288294

289295
return nil
290296
}
297+
298+
func hostnameValidator(v interface{}) error {
299+
val := v.(string)
300+
if len(strings.TrimSpace(val)) < 1 {
301+
return errors.New("a value is required")
302+
}
303+
if strings.ContainsRune(val, '/') || strings.ContainsRune(val, ':') {
304+
return errors.New("invalid hostname")
305+
}
306+
return nil
307+
}

pkg/cmd/pr/create/create.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -366,11 +366,15 @@ func createRun(opts *CreateOptions) error {
366366
}
367367

368368
pr, err := api.CreatePullRequest(client, baseRepo, params)
369+
if pr != nil {
370+
fmt.Fprintln(opts.IO.Out, pr.URL)
371+
}
369372
if err != nil {
370-
return fmt.Errorf("failed to create pull request: %w", err)
373+
if pr != nil {
374+
return fmt.Errorf("pull request update failed: %w", err)
375+
}
376+
return fmt.Errorf("pull request create failed: %w", err)
371377
}
372-
373-
fmt.Fprintln(opts.IO.Out, pr.URL)
374378
} else if action == shared.PreviewAction {
375379
openURL, err := generateCompareURL(baseRepo, baseBranch, headBranchLabel, title, body, tb.Assignees, tb.Labels, tb.Projects, tb.Milestones)
376380
if err != nil {

pkg/cmd/repo/create/create.go

Lines changed: 41 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,18 @@
11
package create
22

33
import (
4+
"errors"
45
"fmt"
56
"net/http"
67
"path"
78
"strings"
89

910
"github.com/AlecAivazis/survey/v2"
1011
"github.com/MakeNowJust/heredoc"
12+
"github.com/cli/cli/api"
1113
"github.com/cli/cli/git"
1214
"github.com/cli/cli/internal/config"
15+
"github.com/cli/cli/internal/ghinstance"
1316
"github.com/cli/cli/internal/ghrepo"
1417
"github.com/cli/cli/internal/run"
1518
"github.com/cli/cli/pkg/cmdutil"
@@ -28,6 +31,7 @@ type CreateOptions struct {
2831
Description string
2932
Homepage string
3033
Team string
34+
Template string
3135
EnableIssues bool
3236
EnableWiki bool
3337
Public bool
@@ -73,13 +77,18 @@ func NewCmdCreate(f *cmdutil.Factory, runF func(*CreateOptions) error) *cobra.Co
7377
return runF(opts)
7478
}
7579

80+
if opts.Template != "" && (opts.Homepage != "" || opts.Team != "" || !opts.EnableIssues || !opts.EnableWiki) {
81+
return &cmdutil.FlagError{Err: errors.New(`The '--template' option is not supported with '--homepage, --team, --enable-issues or --enable-wiki'`)}
82+
}
83+
7684
return createRun(opts)
7785
},
7886
}
7987

8088
cmd.Flags().StringVarP(&opts.Description, "description", "d", "", "Description of repository")
8189
cmd.Flags().StringVarP(&opts.Homepage, "homepage", "h", "", "Repository home page URL")
8290
cmd.Flags().StringVarP(&opts.Team, "team", "t", "", "The name of the organization team to be granted access")
91+
cmd.Flags().StringVarP(&opts.Template, "template", "p", "", "Make the new repository based on a template repository")
8392
cmd.Flags().BoolVar(&opts.EnableIssues, "enable-issues", true, "Enable issues in the new repository")
8493
cmd.Flags().BoolVar(&opts.EnableWiki, "enable-wiki", true, "Enable wiki in the new repository")
8594
cmd.Flags().BoolVar(&opts.Public, "public", false, "Make the new repository public")
@@ -164,6 +173,37 @@ func createRun(opts *CreateOptions) error {
164173
}
165174
}
166175

176+
// Find template repo ID
177+
if opts.Template != "" {
178+
httpClient, err := opts.HttpClient()
179+
if err != nil {
180+
return err
181+
}
182+
183+
var toClone ghrepo.Interface
184+
apiClient := api.NewClientFromHTTP(httpClient)
185+
186+
cloneURL := opts.Template
187+
if !strings.Contains(cloneURL, "/") {
188+
currentUser, err := api.CurrentLoginName(apiClient, ghinstance.Default())
189+
if err != nil {
190+
return err
191+
}
192+
cloneURL = currentUser + "/" + cloneURL
193+
}
194+
toClone, err = ghrepo.FromFullName(cloneURL)
195+
if err != nil {
196+
return fmt.Errorf("argument error: %w", err)
197+
}
198+
199+
repo, err := api.GitHubRepo(apiClient, toClone)
200+
if err != nil {
201+
return err
202+
}
203+
204+
opts.Template = repo.ID
205+
}
206+
167207
input := repoCreateInput{
168208
Name: repoToCreate.RepoName(),
169209
Visibility: visibility,
@@ -189,7 +229,7 @@ func createRun(opts *CreateOptions) error {
189229
}
190230

191231
if opts.ConfirmSubmit {
192-
repo, err := repoCreate(httpClient, repoToCreate.RepoHost(), input)
232+
repo, err := repoCreate(httpClient, repoToCreate.RepoHost(), input, opts.Template)
193233
if err != nil {
194234
return err
195235
}

0 commit comments

Comments
 (0)