Refactor error handling for missing "workflow" scope in createRelease

This commit is contained in:
bagtoad 2024-11-23 16:59:49 -07:00
parent 11dc6df88b
commit deb34d6456
3 changed files with 31 additions and 11 deletions

View file

@ -477,6 +477,21 @@ func createRun(opts *CreateOptions) error {
}
newRelease, err := createRelease(httpClient, baseRepo, params)
var errMissingRequiredWorkflowScope *errMissingRequiredWorkflowScope
if errors.As(err, &errMissingRequiredWorkflowScope) {
host := errMissingRequiredWorkflowScope.Hostname
refreshInstructions := fmt.Sprintf("gh auth refresh -h %[1]s -s workflow", host)
cs := opts.IO.ColorScheme()
var sb strings.Builder
sb.WriteString(fmt.Sprintf("%s Failed to create release, \"workflow\" scope may be required.\n", cs.WarningIcon()))
sb.WriteString(fmt.Sprintf("To request it, run:\n%s\n", cs.Bold(refreshInstructions)))
fmt.Fprint(opts.IO.ErrOut, sb.String())
return cmdutil.SilentError
}
if err != nil {
return err
}

View file

@ -1102,10 +1102,12 @@ func Test_createRun(t *testing.T) {
httpmock.REST("POST", "repos/OWNER/REPO/releases"),
httpmock.StatusScopesResponder(404, `repo,read:org`))
},
wantErr: heredoc.Doc(`
HTTP 404: Failed to create release, "workflow" scope may be required
To request it, run gh auth refresh -h github.com -s workflow
wantStderr: heredoc.Doc(`
! Failed to create release, "workflow" scope may be required.
To request it, run:
gh auth refresh -h github.com -s workflow
`),
wantErr: cmdutil.SilentError.Error(),
},
{
name: "API returns 404, OAuth token has workflow scope",
@ -1182,7 +1184,6 @@ func Test_createRun(t *testing.T) {
err := createRun(&tt.opts)
if tt.wantErr != "" {
require.EqualError(t, err, tt.wantErr)
return
} else {
require.NoError(t, err)
}

View file

@ -11,7 +11,6 @@ import (
"slices"
"strings"
"github.com/MakeNowJust/heredoc"
"github.com/cli/cli/v2/api"
"github.com/cli/cli/v2/internal/ghinstance"
"github.com/cli/cli/v2/internal/ghrepo"
@ -32,6 +31,14 @@ type releaseNotes struct {
var notImplementedError = errors.New("not implemented")
type errMissingRequiredWorkflowScope struct {
Hostname string
}
func (e errMissingRequiredWorkflowScope) Error() string {
return "workflow scope may be required"
}
func remoteTagExists(httpClient *http.Client, repo ghrepo.Interface, tagName string) (bool, error) {
gql := api.NewClientFromHTTP(httpClient)
qualifiedTagName := fmt.Sprintf("refs/tags/%s", tagName)
@ -192,12 +199,9 @@ func createRelease(httpClient *http.Client, repo ghrepo.Interface, params map[st
// https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/scopes-for-oauth-apps#available-scopes
if resp.StatusCode == http.StatusNotFound && !tokenHasWorkflowScope(resp) {
normalizedHostname := ghauth.NormalizeHostname(resp.Request.URL.Hostname())
errMissingRequiredWorkflowScope := errors.New(heredoc.Docf(`
HTTP 404: Failed to create release, "workflow" scope may be required
To request it, run gh auth refresh -h %[1]s -s workflow
`, normalizedHostname))
return nil, errMissingRequiredWorkflowScope
return nil, &errMissingRequiredWorkflowScope{
Hostname: normalizedHostname,
}
}
success := resp.StatusCode >= 200 && resp.StatusCode < 300