Merge pull request #976 from cli/auth-from-env

Respect GITHUB_TOKEN environment variable
This commit is contained in:
Mislav Marohnić 2020-05-27 12:06:16 +02:00 committed by GitHub
commit 968e17625e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 60 additions and 46 deletions

18
api/queries_user.go Normal file
View file

@ -0,0 +1,18 @@
package api
import (
"context"
"github.com/shurcooL/githubv4"
)
func CurrentLoginName(client *Client) (string, error) {
var query struct {
Viewer struct {
Login string
}
}
v4 := githubv4.NewClient(client.http)
err := v4.Query(context.Background(), &query, nil)
return query.Viewer.Login, err
}

View file

@ -172,7 +172,7 @@ func issueStatus(cmd *cobra.Command, args []string) error {
return err
}
currentUser, err := ctx.AuthLogin()
currentUser, err := api.CurrentLoginName(apiClient)
if err != nil {
return err
}

View file

@ -20,6 +20,9 @@ func TestIssueStatus(t *testing.T) {
initBlankContext("", "OWNER/REPO", "master")
http := initFakeHTTP()
http.StubRepoResponse("OWNER", "REPO")
http.Register(
httpmock.GraphQL(`\bviewer\b`),
httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`))
jsonFile, _ := os.Open("../test/fixtures/issueStatus.json")
defer jsonFile.Close()
@ -49,6 +52,9 @@ func TestIssueStatus_blankSlate(t *testing.T) {
initBlankContext("", "OWNER/REPO", "master")
http := initFakeHTTP()
http.StubRepoResponse("OWNER", "REPO")
http.Register(
httpmock.GraphQL(`\bviewer\b`),
httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`))
http.StubResponse(200, bytes.NewBufferString(`
{ "data": { "repository": {
@ -86,6 +92,9 @@ func TestIssueStatus_disabledIssues(t *testing.T) {
initBlankContext("", "OWNER/REPO", "master")
http := initFakeHTTP()
http.StubRepoResponse("OWNER", "REPO")
http.Register(
httpmock.GraphQL(`\bviewer\b`),
httpmock.StringResponse(`{"data":{"viewer":{"login":"octocat"}}}`))
http.StubResponse(200, bytes.NewBufferString(`
{ "data": { "repository": {

View file

@ -108,11 +108,6 @@ func prStatus(cmd *cobra.Command, args []string) error {
return err
}
currentUser, err := ctx.AuthLogin()
if err != nil {
return err
}
baseRepo, err := determineBaseRepo(apiClient, cmd, ctx)
if err != nil {
return err
@ -125,6 +120,8 @@ func prStatus(cmd *cobra.Command, args []string) error {
return fmt.Errorf("could not query for pull request for current branch: %w", err)
}
// the `@me` macro is available because the API lookup is ElasticSearch-based
currentUser := "@me"
prPayload, err := api.PullRequests(apiClient, baseRepo, currentPRNumber, currentPRHeadRef, currentUser)
if err != nil {
return err

View file

@ -101,6 +101,9 @@ var initContext = func() context.Context {
if repo := os.Getenv("GH_REPO"); repo != "" {
ctx.SetBaseRepo(repo)
}
if token := os.Getenv("GITHUB_TOKEN"); token != "" {
ctx.SetAuthToken(token)
}
return ctx
}
@ -113,11 +116,15 @@ func BasicClient() (*api.Client, error) {
}
opts = append(opts, api.AddHeader("User-Agent", fmt.Sprintf("GitHub CLI %s", Version)))
if c, err := config.ParseDefaultConfig(); err == nil {
if token, _ := c.Get(defaultHostname, "oauth_token"); token != "" {
opts = append(opts, api.AddHeader("Authorization", fmt.Sprintf("token %s", token)))
token := os.Getenv("GITHUB_TOKEN")
if token == "" {
if c, err := config.ParseDefaultConfig(); err == nil {
token, _ = c.Get(defaultHostname, "oauth_token")
}
}
if token != "" {
opts = append(opts, api.AddHeader("Authorization", fmt.Sprintf("token %s", token)))
}
return api.NewClient(opts...), nil
}
@ -145,8 +152,12 @@ var apiClientForContext = func(ctx context.Context) (*api.Client, error) {
return fmt.Sprintf("token %s", token)
}
tokenFromEnv := func() bool {
return os.Getenv("GITHUB_TOKEN") == token
}
checkScopesFunc := func(appID string) error {
if config.IsGitHubApp(appID) && utils.IsTerminal(os.Stdin) && utils.IsTerminal(os.Stderr) {
if config.IsGitHubApp(appID) && !tokenFromEnv() && utils.IsTerminal(os.Stdin) && utils.IsTerminal(os.Stderr) {
newToken, loginHandle, err := config.AuthFlow("Notice: additional authorization required")
if err != nil {
return err
@ -168,7 +179,11 @@ var apiClientForContext = func(ctx context.Context) (*api.Client, error) {
} else {
fmt.Fprintln(os.Stderr, "Warning: gh now requires the `read:org` OAuth scope.")
fmt.Fprintln(os.Stderr, "Visit https://github.com/settings/tokens and edit your token to enable `read:org`")
fmt.Fprintln(os.Stderr, "or generate a new token and paste it via `gh config set -h github.com oauth_token MYTOKEN`")
if tokenFromEnv() {
fmt.Fprintln(os.Stderr, "or generate a new token for the GITHUB_TOKEN environment variable")
} else {
fmt.Fprintln(os.Stderr, "or generate a new token and paste it via `gh config set -h github.com oauth_token MYTOKEN`")
}
}
return nil
}
@ -194,7 +209,9 @@ var ensureScopes = func(ctx context.Context, client *api.Client, wantedScopes ..
return client, nil
}
if config.IsGitHubApp(appID) && utils.IsTerminal(os.Stdin) && utils.IsTerminal(os.Stderr) {
tokenFromEnv := len(os.Getenv("GITHUB_TOKEN")) > 0
if config.IsGitHubApp(appID) && !tokenFromEnv && utils.IsTerminal(os.Stdin) && utils.IsTerminal(os.Stderr) {
newToken, loginHandle, err := config.AuthFlow("Notice: additional authorization required")
if err != nil {
return client, err
@ -219,9 +236,13 @@ var ensureScopes = func(ctx context.Context, client *api.Client, wantedScopes ..
return reloadedClient, nil
} else {
fmt.Fprintln(os.Stderr, fmt.Sprintf("Warning: gh now requires the `%s` OAuth scope(s).", wantedScopes))
fmt.Fprintln(os.Stderr, fmt.Sprintf("Warning: gh now requires %s OAuth scopes.", wantedScopes))
fmt.Fprintln(os.Stderr, fmt.Sprintf("Visit https://github.com/settings/tokens and edit your token to enable %s", wantedScopes))
fmt.Fprintln(os.Stderr, "or generate a new token and paste it via `gh config set -h github.com oauth_token MYTOKEN`")
if tokenFromEnv {
fmt.Fprintln(os.Stderr, "or generate a new token for the GITHUB_TOKEN environment variable")
} else {
fmt.Fprintln(os.Stderr, "or generate a new token and paste it via `gh config set -h github.com oauth_token MYTOKEN`")
}
return client, errors.New("Unable to reauthenticate")
}

View file

@ -17,7 +17,6 @@ func NewBlank() *blankContext {
// A Context implementation that queries the filesystem
type blankContext struct {
authToken string
authLogin string
branch string
baseRepo ghrepo.Interface
remotes Remotes
@ -39,14 +38,6 @@ func (c *blankContext) SetAuthToken(t string) {
c.authToken = t
}
func (c *blankContext) SetAuthLogin(login string) {
c.authLogin = login
}
func (c *blankContext) AuthLogin() (string, error) {
return c.authLogin, nil
}
func (c *blankContext) Branch() (string, error) {
if c.branch == "" {
return "", fmt.Errorf("branch was not initialized")

View file

@ -18,7 +18,6 @@ const defaultHostname = "github.com"
type Context interface {
AuthToken() (string, error)
SetAuthToken(string)
AuthLogin() (string, error)
Branch() (string, error)
SetBranch(string)
Remotes() (Remotes, error)
@ -195,20 +194,6 @@ func (c *fsContext) SetAuthToken(t string) {
c.authToken = t
}
func (c *fsContext) AuthLogin() (string, error) {
config, err := c.Config()
if err != nil {
return "", err
}
login, err := config.Get(defaultHostname, "user")
if login == "" || err != nil {
return "", err
}
return login, nil
}
func (c *fsContext) Branch() (string, error) {
if c.branch != "" {
return c.branch, nil

View file

@ -116,14 +116,7 @@ func setupConfigFile(filename string) (Config, error) {
func getViewer(token string) (string, error) {
http := api.NewClient(api.AddHeader("Authorization", fmt.Sprintf("token %s", token)))
response := struct {
Viewer struct {
Login string
}
}{}
err := http.GraphQL("{ viewer { login } }", nil, &response)
return response.Viewer.Login, err
return api.CurrentLoginName(http)
}
func waitForEnter(r io.Reader) error {