diff --git a/acceptance/testdata/secret/secret-require-remote-disambiguation.txtar b/acceptance/testdata/secret/secret-require-remote-disambiguation.txtar index f4d1bbb4a53..02dec06a00d 100644 --- a/acceptance/testdata/secret/secret-require-remote-disambiguation.txtar +++ b/acceptance/testdata/secret/secret-require-remote-disambiguation.txtar @@ -34,3 +34,29 @@ stderr 'multiple remotes detected. please specify which repo to use by providing # Secret delete requires disambiguation ! exec gh secret delete 'TEST_SECRET_NAME' stderr 'multiple remotes detected. please specify which repo to use by providing the -R, --repo argument' + +# Move out of the fork repo to test whether secret commands work without local repository context +cd .. + +# Secret set using --repo flag does not require disambiguation +exec gh secret set 'TEST_SECRET_NAME' --body 'TEST_SECRET_VALUE' --repo ${ORG}/${REPO}-fork + +# Secret list using --repo flag does not require disambiguation +exec gh secret list --repo ${ORG}/${REPO}-fork +stdout 'TEST_SECRET_NAME' + +# Secret delete using --repo flag does not require disambiguation +exec gh secret delete 'TEST_SECRET_NAME' --repo ${ORG}/${REPO}-fork + +# Setup GH_REPO for testing environment variable behavior +env GH_REPO=${ORG}/${REPO}-fork + +# Secret set using GH_REPO env var does not require disambiguation +exec gh secret set 'TEST_SECRET_NAME2' --body 'TEST_SECRET_VALUE2' + +# Secret list using GH_REPO env var does not require disambiguation +exec gh secret list +stdout 'TEST_SECRET_NAME2' + +# Secret delete using GH_REPO env var does not require disambiguation +exec gh secret delete 'TEST_SECRET_NAME2' diff --git a/pkg/cmd/secret/delete/delete.go b/pkg/cmd/secret/delete/delete.go index 84a5e7a8304..1cbfbca9da0 100644 --- a/pkg/cmd/secret/delete/delete.go +++ b/pkg/cmd/secret/delete/delete.go @@ -3,6 +3,7 @@ package delete import ( "fmt" "net/http" + "os" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" @@ -48,8 +49,9 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co RunE: func(cmd *cobra.Command, args []string) error { // If the user specified a repo directly, then we're using the OverrideBaseRepoFunc set by EnableRepoOverride // So there's no reason to use the specialised BaseRepoFunc that requires remote disambiguation. - opts.BaseRepo = f.BaseRepo - if !cmd.Flags().Changed("repo") { + if cmd.Flags().Changed("repo") || os.Getenv("GH_REPO") != "" { + opts.BaseRepo = f.BaseRepo + } else { // If they haven't specified a repo directly, then we will wrap the BaseRepoFunc in one that errors if // there might be multiple valid remotes. opts.BaseRepo = shared.RequireNoAmbiguityBaseRepoFunc(opts.BaseRepo, f.Remotes) diff --git a/pkg/cmd/secret/delete/delete_test.go b/pkg/cmd/secret/delete/delete_test.go index 377879cf2ab..2f6cad43139 100644 --- a/pkg/cmd/secret/delete/delete_test.go +++ b/pkg/cmd/secret/delete/delete_test.go @@ -144,6 +144,7 @@ func TestNewCmdDeleteBaseRepoFuncs(t *testing.T) { tests := []struct { name string args string + env map[string]string prompterStubs func(*prompter.MockPrompter) wantRepo ghrepo.Interface wantErr error @@ -154,14 +155,22 @@ func TestNewCmdDeleteBaseRepoFuncs(t *testing.T) { wantRepo: ghrepo.New("owner", "repo"), }, { - name: "when there is no repo flag provided, and no prompting, the base func requiring no ambiguity is used", + name: "when GH_REPO env var is provided, the factory base repo func is used", + args: "SECRET_NAME", + env: map[string]string{ + "GH_REPO": "owner/repo", + }, + wantRepo: ghrepo.New("owner", "repo"), + }, + { + name: "when there is no repo flag or GH_REPO env var provided, and no prompting, the base func requiring no ambiguity is used", args: "SECRET_NAME", wantErr: shared.AmbiguousBaseRepoError{ Remotes: remotes, }, }, { - name: "when there is no repo flag provided, and can prompt, the base func resolving ambiguity is used", + name: "when there is no repo flag or GH_REPO env var provided, and can prompt, the base func resolving ambiguity is used", args: "SECRET_NAME", prompterStubs: func(pm *prompter.MockPrompter) { pm.RegisterSelect( @@ -199,6 +208,10 @@ func TestNewCmdDeleteBaseRepoFuncs(t *testing.T) { }, } + for k, v := range tt.env { + t.Setenv(k, v) + } + argv, err := shlex.Split(tt.args) assert.NoError(t, err) diff --git a/pkg/cmd/secret/list/list.go b/pkg/cmd/secret/list/list.go index af3526386ed..c976bd60edb 100644 --- a/pkg/cmd/secret/list/list.go +++ b/pkg/cmd/secret/list/list.go @@ -3,6 +3,7 @@ package list import ( "fmt" "net/http" + "os" "slices" "strings" "time" @@ -69,8 +70,9 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman RunE: func(cmd *cobra.Command, args []string) error { // If the user specified a repo directly, then we're using the OverrideBaseRepoFunc set by EnableRepoOverride // So there's no reason to use the specialised BaseRepoFunc that requires remote disambiguation. - opts.BaseRepo = f.BaseRepo - if !cmd.Flags().Changed("repo") { + if cmd.Flags().Changed("repo") || os.Getenv("GH_REPO") != "" { + opts.BaseRepo = f.BaseRepo + } else { // If they haven't specified a repo directly, then we will wrap the BaseRepoFunc in one that errors if // there might be multiple valid remotes. opts.BaseRepo = shared.RequireNoAmbiguityBaseRepoFunc(opts.BaseRepo, f.Remotes) diff --git a/pkg/cmd/secret/list/list_test.go b/pkg/cmd/secret/list/list_test.go index 601de2572ff..f4ecde73eaa 100644 --- a/pkg/cmd/secret/list/list_test.go +++ b/pkg/cmd/secret/list/list_test.go @@ -124,6 +124,7 @@ func TestNewCmdListBaseRepoFuncs(t *testing.T) { tests := []struct { name string args string + env map[string]string prompterStubs func(*prompter.MockPrompter) wantRepo ghrepo.Interface wantErr error @@ -134,14 +135,21 @@ func TestNewCmdListBaseRepoFuncs(t *testing.T) { wantRepo: ghrepo.New("owner", "repo"), }, { - name: "when there is no repo flag provided, and no prompting, the base func requiring no ambiguity is used", + name: "when GH_REPO env var is provided, the factory base repo func is used", + env: map[string]string{ + "GH_REPO": "owner/repo", + }, + wantRepo: ghrepo.New("owner", "repo"), + }, + { + name: "when there is no repo flag or GH_REPO env var provided, and no prompting, the base func requiring no ambiguity is used", args: "", wantErr: shared.AmbiguousBaseRepoError{ Remotes: remotes, }, }, { - name: "when there is no repo flag provided, and can prompt, the base func resolving ambiguity is used", + name: "when there is no repo flag or GH_REPO env var provided, and can prompt, the base func resolving ambiguity is used", args: "", prompterStubs: func(pm *prompter.MockPrompter) { pm.RegisterSelect( @@ -179,6 +187,10 @@ func TestNewCmdListBaseRepoFuncs(t *testing.T) { }, } + for k, v := range tt.env { + t.Setenv(k, v) + } + argv, err := shlex.Split(tt.args) assert.NoError(t, err) diff --git a/pkg/cmd/secret/set/set.go b/pkg/cmd/secret/set/set.go index 3c12b41924e..89f11f1cf85 100644 --- a/pkg/cmd/secret/set/set.go +++ b/pkg/cmd/secret/set/set.go @@ -106,8 +106,9 @@ func NewCmdSet(f *cmdutil.Factory, runF func(*SetOptions) error) *cobra.Command RunE: func(cmd *cobra.Command, args []string) error { // If the user specified a repo directly, then we're using the OverrideBaseRepoFunc set by EnableRepoOverride // So there's no reason to use the specialised BaseRepoFunc that requires remote disambiguation. - opts.BaseRepo = f.BaseRepo - if !cmd.Flags().Changed("repo") { + if cmd.Flags().Changed("repo") || os.Getenv("GH_REPO") != "" { + opts.BaseRepo = f.BaseRepo + } else { // If they haven't specified a repo directly, then we will wrap the BaseRepoFunc in one that errors if // there might be multiple valid remotes. opts.BaseRepo = shared.RequireNoAmbiguityBaseRepoFunc(opts.BaseRepo, f.Remotes) diff --git a/pkg/cmd/secret/set/set_test.go b/pkg/cmd/secret/set/set_test.go index 99c8c6cbe3b..22c7aaab865 100644 --- a/pkg/cmd/secret/set/set_test.go +++ b/pkg/cmd/secret/set/set_test.go @@ -243,6 +243,7 @@ func TestNewCmdSetBaseRepoFuncs(t *testing.T) { tests := []struct { name string args string + env map[string]string prompterStubs func(*prompter.MockPrompter) wantRepo ghrepo.Interface wantErr error @@ -253,14 +254,22 @@ func TestNewCmdSetBaseRepoFuncs(t *testing.T) { wantRepo: ghrepo.New("owner", "repo"), }, { - name: "when there is no repo flag provided, and no prompting, the base func requiring no ambiguity is used", + name: "when GH_REPO env var is provided, the factory base repo func is used", + args: "SECRET_NAME", + env: map[string]string{ + "GH_REPO": "owner/repo", + }, + wantRepo: ghrepo.New("owner", "repo"), + }, + { + name: "when there is no repo flag or GH_REPO env var provided, and no prompting, the base func requiring no ambiguity is used", args: "SECRET_NAME", wantErr: shared.AmbiguousBaseRepoError{ Remotes: remotes, }, }, { - name: "when there is no repo flag provided, and can prompt, the base func resolving ambiguity is used", + name: "when there is no repo flag or GH_REPO env var provided, and can prompt, the base func resolving ambiguity is used", args: "SECRET_NAME", prompterStubs: func(pm *prompter.MockPrompter) { pm.RegisterSelect( @@ -298,6 +307,10 @@ func TestNewCmdSetBaseRepoFuncs(t *testing.T) { }, } + for k, v := range tt.env { + t.Setenv(k, v) + } + argv, err := shlex.Split(tt.args) assert.NoError(t, err)