Support GH_DEBUG to control verbosity, deprecate DEBUG (#5306)

The GH_DEBUG environment variable is a new gh-specific verbosity control.

For backwards-compatibility, DEBUG will still be respected if it has values
"1", "true", "yes", and "api", but any other values will be ignored.

Finally, support for "oauth" debug value has been dropped in favor of "api".
The "oauth" value only had limited, internal use.

Co-authored-by: Mislav Marohnić <mislav@github.com>
This commit is contained in:
lylecantcode 2022-03-29 17:05:35 +01:00 committed by GitHub
parent c1e5934b21
commit 56fda0f8c6
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 85 additions and 20 deletions

View file

@ -58,7 +58,7 @@ func mainRun() exitCode {
updateMessageChan <- rel
}()
hasDebug := os.Getenv("DEBUG") != ""
hasDebug, _ := utils.IsDebugEnabled()
cmdFactory := factory.New(buildVersion)
stderr := cmdFactory.IOStreams.ErrOut
@ -327,8 +327,10 @@ func checkForUpdate(currentVersion string) (*update.ReleaseInfo, error) {
// does not depend on user configuration
func basicClient(currentVersion string) (*api.Client, error) {
var opts []api.ClientOption
if verbose := os.Getenv("DEBUG"); verbose != "" {
opts = append(opts, apiVerboseLog())
if isVerbose, debugValue := utils.IsDebugEnabled(); isVerbose {
colorize := utils.IsTerminal(os.Stderr)
logTraffic := strings.Contains(debugValue, "api")
opts = append(opts, api.VerboseLog(colorable.NewColorable(os.Stderr), logTraffic, colorize))
}
opts = append(opts, api.AddHeader("User-Agent", fmt.Sprintf("GitHub CLI %s", currentVersion)))
@ -344,12 +346,6 @@ func basicClient(currentVersion string) (*api.Client, error) {
return api.NewClient(opts...), nil
}
func apiVerboseLog() api.ClientOption {
logTraffic := strings.Contains(os.Getenv("DEBUG"), "api")
colorize := utils.IsTerminal(os.Stderr)
return api.VerboseLog(colorable.NewColorable(os.Stderr), logTraffic, colorize)
}
func isRecentRelease(publishedAt time.Time) bool {
return !publishedAt.IsZero() && time.Since(publishedAt) < time.Hour*24
}

View file

@ -12,6 +12,7 @@ import (
"github.com/cli/cli/v2/internal/ghinstance"
"github.com/cli/cli/v2/pkg/cmdutil"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/utils"
"github.com/cli/oauth"
)
@ -53,8 +54,9 @@ func authFlow(oauthHost string, IO *iostreams.IOStreams, notice string, addition
cs := IO.ColorScheme()
httpClient := http.DefaultClient
if envDebug := os.Getenv("DEBUG"); envDebug != "" {
logTraffic := strings.Contains(envDebug, "api") || strings.Contains(envDebug, "oauth")
debugEnabled, debugValue := utils.IsDebugEnabled()
if debugEnabled {
logTraffic := strings.Contains(debugValue, "api")
httpClient.Transport = api.VerboseLog(IO.ErrOut, logTraffic, IO.ColorEnabled())(httpClient.Transport)
}

View file

@ -8,6 +8,8 @@ import (
"os/exec"
"path/filepath"
"strings"
"github.com/cli/cli/v2/utils"
)
// Runnable is typically an exec.Cmd or its stub in tests
@ -28,7 +30,7 @@ type cmdWithStderr struct {
}
func (c cmdWithStderr) Output() ([]byte, error) {
if os.Getenv("DEBUG") != "" {
if isVerbose, _ := utils.IsDebugEnabled(); isVerbose {
_ = printArgs(os.Stderr, c.Cmd.Args)
}
if c.Cmd.Stderr != nil {
@ -44,7 +46,7 @@ func (c cmdWithStderr) Output() ([]byte, error) {
}
func (c cmdWithStderr) Run() error {
if os.Getenv("DEBUG") != "" {
if isVerbose, _ := utils.IsDebugEnabled(); isVerbose {
_ = printArgs(os.Stderr, c.Cmd.Args)
}
if c.Cmd.Stderr != nil {

View file

@ -3,7 +3,6 @@ package factory
import (
"fmt"
"net/http"
"os"
"regexp"
"strings"
"time"
@ -12,6 +11,7 @@ import (
"github.com/cli/cli/v2/internal/ghinstance"
"github.com/cli/cli/v2/internal/httpunix"
"github.com/cli/cli/v2/pkg/iostreams"
"github.com/cli/cli/v2/utils"
)
var timezoneNames = map[int]string{
@ -84,8 +84,8 @@ func NewHTTPClient(io *iostreams.IOStreams, cfg configGetter, appVersion string,
}))
}
if verbose := os.Getenv("DEBUG"); verbose != "" {
logTraffic := strings.Contains(verbose, "api")
if isVerbose, debugValue := utils.IsDebugEnabled(); isVerbose {
logTraffic := strings.Contains(debugValue, "api")
opts = append(opts, api.VerboseLog(io.ErrOut, logTraffic, io.IsStderrTTY()))
}

View file

@ -24,6 +24,8 @@ func TestNewHTTPClient(t *testing.T) {
name string
args args
envDebug string
setGhDebug bool
envGhDebug string
host string
sso string
wantHeader map[string]string
@ -82,8 +84,39 @@ func TestNewHTTPClient(t *testing.T) {
appVersion: "v1.2.3",
setAccept: true,
},
host: "github.com",
envDebug: "api",
host: "github.com",
envDebug: "api",
setGhDebug: false,
wantHeader: map[string]string{
"authorization": "token MYTOKEN",
"user-agent": "GitHub CLI v1.2.3",
"accept": "application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview",
},
wantStderr: heredoc.Doc(`
* Request at <time>
* Request to http://<host>:<port>
> GET / HTTP/1.1
> Host: github.com
> Accept: application/vnd.github.merge-info-preview+json, application/vnd.github.nebula-preview
> Authorization: token
> User-Agent: GitHub CLI v1.2.3
< HTTP/1.1 204 No Content
< Date: <time>
* Request took <duration>
`),
},
{
name: "github.com in verbose mode",
args: args{
config: tinyConfig{"github.com:oauth_token": "MYTOKEN"},
appVersion: "v1.2.3",
setAccept: true,
},
host: "github.com",
envGhDebug: "api",
setGhDebug: true,
wantHeader: map[string]string{
"authorization": "token MYTOKEN",
"user-agent": "GitHub CLI v1.2.3",
@ -145,9 +178,16 @@ func TestNewHTTPClient(t *testing.T) {
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
oldDebug := os.Getenv("DEBUG")
oldGhDebug := os.Getenv("GH_DEBUG")
os.Setenv("DEBUG", tt.envDebug)
if tt.setGhDebug {
os.Setenv("GH_DEBUG", tt.envGhDebug)
} else {
os.Unsetenv("GH_DEBUG")
}
t.Cleanup(func() {
os.Setenv("DEBUG", oldDebug)
os.Setenv("GH_DEBUG", oldGhDebug)
})
io, _, _, stderr := iostreams.Test()

View file

@ -47,8 +47,11 @@ var HelpTopics = map[string]map[string]string{
GH_BROWSER, BROWSER (in order of precedence): the web browser to use for opening links.
DEBUG: set to any value to enable verbose output to standard error. Include values "api"
or "oauth" to print detailed information about HTTP requests or authentication flow.
GH_DEBUG: set to a truthy value to enable verbose output on standard error. Set to "api"
to additionally log details of HTTP traffic.
DEBUG (deprecated): set to "1", "true", or "yes" to enable verbose output on standard
error.
GH_PAGER, PAGER (in order of precedence): a terminal paging program to send standard output
to, e.g. "less".

View file

@ -3,6 +3,7 @@ package utils
import (
"fmt"
"net/url"
"os"
"strings"
"time"
)
@ -83,3 +84,24 @@ func DisplayURL(urlStr string) string {
func ValidURL(urlStr string) bool {
return len(urlStr) < 8192
}
func IsDebugEnabled() (bool, string) {
debugValue, isDebugSet := os.LookupEnv("GH_DEBUG")
legacyDebugValue := os.Getenv("DEBUG")
if !isDebugSet {
switch legacyDebugValue {
case "true", "1", "yes", "api":
return true, legacyDebugValue
default:
return false, legacyDebugValue
}
}
switch debugValue {
case "false", "0", "no", "":
return false, debugValue
default:
return true, debugValue
}
}