diff --git a/internal/docs/markdown.go b/internal/docs/markdown.go index 74f505a6b..e33df5f45 100644 --- a/internal/docs/markdown.go +++ b/internal/docs/markdown.go @@ -85,6 +85,7 @@ func GenMarkdown(cmd *cobra.Command, w io.Writer) error { // GenMarkdownCustom creates custom markdown output. func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) string) error { + fmt.Fprint(w, "{% raw %}") fmt.Fprintf(w, "## %s\n\n", cmd.CommandPath()) hasLong := cmd.Long != "" @@ -112,6 +113,7 @@ func GenMarkdownCustom(cmd *cobra.Command, w io.Writer, linkHandler func(string) if err := printOptions(w, cmd); err != nil { return err } + fmt.Fprint(w, "{% endraw %}\n") if len(cmd.Example) > 0 { fmt.Fprint(w, "### Examples\n\n{% highlight bash %}{% raw %}\n") diff --git a/pkg/cmd/auth/login/login.go b/pkg/cmd/auth/login/login.go index b0d0e02cf..48cb73bca 100644 --- a/pkg/cmd/auth/login/login.go +++ b/pkg/cmd/auth/login/login.go @@ -9,7 +9,6 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/internal/ghinstance" - "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmd/auth/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" @@ -20,7 +19,7 @@ type LoginOptions struct { IO *iostreams.IOStreams Config func() (config.Config, error) HttpClient func() (*http.Client, error) - Prompter prompter.Prompter + Prompter shared.Prompt MainExecutable string diff --git a/pkg/cmd/auth/logout/logout.go b/pkg/cmd/auth/logout/logout.go index 029d5971a..98735b2e6 100644 --- a/pkg/cmd/auth/logout/logout.go +++ b/pkg/cmd/auth/logout/logout.go @@ -4,14 +4,12 @@ import ( "fmt" "net/http" - "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/config" "github.com/cli/cli/v2/pkg/cmd/auth/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/spf13/cobra" ) @@ -19,6 +17,7 @@ type LogoutOptions struct { HttpClient func() (*http.Client, error) IO *iostreams.IOStreams Config func() (config.Config, error) + Prompter shared.Prompt Hostname string } @@ -27,6 +26,7 @@ func NewCmdLogout(f *cmdutil.Factory, runF func(*LogoutOptions) error) *cobra.Co HttpClient: f.HttpClient, IO: f.IOStreams, Config: f.Config, + Prompter: f.Prompter, } cmd := &cobra.Command{ @@ -79,15 +79,12 @@ func logoutRun(opts *LogoutOptions) error { if len(candidates) == 1 { hostname = candidates[0] } else { - //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter - err = prompt.SurveyAskOne(&survey.Select{ - Message: "What account do you want to log out of?", - Options: candidates, - }, &hostname) - + selected, err := opts.Prompter.Select( + "What account to you want to log out of?", "", candidates) if err != nil { return fmt.Errorf("could not prompt: %w", err) } + hostname = candidates[selected] } } else { var found bool diff --git a/pkg/cmd/auth/logout/logout_test.go b/pkg/cmd/auth/logout/logout_test.go index 71bca8cd7..0a5e32f7c 100644 --- a/pkg/cmd/auth/logout/logout_test.go +++ b/pkg/cmd/auth/logout/logout_test.go @@ -7,10 +7,10 @@ import ( "testing" "github.com/cli/cli/v2/internal/config" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/google/shlex" "github.com/stretchr/testify/assert" ) @@ -92,21 +92,23 @@ func Test_NewCmdLogout(t *testing.T) { func Test_logoutRun_tty(t *testing.T) { tests := []struct { - name string - opts *LogoutOptions - askStubs func(*prompt.AskStubber) - cfgHosts []string - wantHosts string - wantErrOut *regexp.Regexp - wantErr string + name string + opts *LogoutOptions + prompterStubs func(*prompter.PrompterMock) + cfgHosts []string + wantHosts string + wantErrOut *regexp.Regexp + wantErr string }{ { name: "no arguments, multiple hosts", opts: &LogoutOptions{}, cfgHosts: []string{"cheryl.mason", "github.com"}, wantHosts: "cheryl.mason:\n oauth_token: abc123\n", - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("What account do you want to log out of?").AnswerWith("github.com") + prompterStubs: func(pm *prompter.PrompterMock) { + pm.SelectFunc = func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "github.com") + } }, wantErrOut: regexp.MustCompile(`Logged out of github.com account 'cybilb'`), }, @@ -158,11 +160,11 @@ func Test_logoutRun_tty(t *testing.T) { return &http.Client{Transport: reg}, nil } - //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock - as := prompt.NewAskStubber(t) - if tt.askStubs != nil { - tt.askStubs(as) + pm := &prompter.PrompterMock{} + if tt.prompterStubs != nil { + tt.prompterStubs(pm) } + tt.opts.Prompter = pm err := logoutRun(tt.opts) if tt.wantErr != "" { diff --git a/pkg/cmd/auth/refresh/refresh.go b/pkg/cmd/auth/refresh/refresh.go index 31737e976..7b1142e7e 100644 --- a/pkg/cmd/auth/refresh/refresh.go +++ b/pkg/cmd/auth/refresh/refresh.go @@ -5,15 +5,12 @@ import ( "net/http" "strings" - "github.com/AlecAivazis/survey/v2" "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/internal/authflow" "github.com/cli/cli/v2/internal/config" - "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmd/auth/shared" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/spf13/cobra" ) @@ -21,7 +18,7 @@ type RefreshOptions struct { IO *iostreams.IOStreams Config func() (config.Config, error) httpClient *http.Client - Prompter prompter.Prompter + Prompter shared.Prompt MainExecutable string @@ -97,15 +94,11 @@ func refreshRun(opts *RefreshOptions) error { if len(candidates) == 1 { hostname = candidates[0] } else { - //nolint:staticcheck // SA1019: prompt.SurveyAskOne is deprecated: use Prompter - err := prompt.SurveyAskOne(&survey.Select{ - Message: "What account do you want to refresh auth for?", - Options: candidates, - }, &hostname) - + selected, err := opts.Prompter.Select("What account do you want to refresh auth for?", "", candidates) if err != nil { return fmt.Errorf("could not prompt: %w", err) } + hostname = candidates[selected] } } else { var found bool diff --git a/pkg/cmd/auth/refresh/refresh_test.go b/pkg/cmd/auth/refresh/refresh_test.go index 0cb754117..ffacb22d9 100644 --- a/pkg/cmd/auth/refresh/refresh_test.go +++ b/pkg/cmd/auth/refresh/refresh_test.go @@ -8,10 +8,10 @@ import ( "testing" "github.com/cli/cli/v2/internal/config" + "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/httpmock" "github.com/cli/cli/v2/pkg/iostreams" - "github.com/cli/cli/v2/pkg/prompt" "github.com/google/shlex" "github.com/stretchr/testify/assert" ) @@ -132,14 +132,14 @@ type authArgs struct { func Test_refreshRun(t *testing.T) { tests := []struct { - name string - opts *RefreshOptions - askStubs func(*prompt.AskStubber) - cfgHosts []string - oldScopes string - wantErr string - nontty bool - wantAuthArgs authArgs + name string + opts *RefreshOptions + prompterStubs func(*prompter.PrompterMock) + cfgHosts []string + oldScopes string + wantErr string + nontty bool + wantAuthArgs authArgs }{ { name: "no hosts configured", @@ -193,8 +193,10 @@ func Test_refreshRun(t *testing.T) { opts: &RefreshOptions{ Hostname: "", }, - askStubs: func(as *prompt.AskStubber) { - as.StubPrompt("What account do you want to refresh auth for?").AnswerWith("github.com") + prompterStubs: func(pm *prompter.PrompterMock) { + pm.SelectFunc = func(_, _ string, opts []string) (int, error) { + return prompter.IndexFor(opts, "github.com") + } }, wantAuthArgs: authArgs{ hostname: "github.com", @@ -272,11 +274,11 @@ func Test_refreshRun(t *testing.T) { ) tt.opts.httpClient = &http.Client{Transport: httpReg} - //nolint:staticcheck // SA1019: prompt.NewAskStubber is deprecated: use PrompterMock - as := prompt.NewAskStubber(t) - if tt.askStubs != nil { - tt.askStubs(as) + pm := &prompter.PrompterMock{} + if tt.prompterStubs != nil { + tt.prompterStubs(pm) } + tt.opts.Prompter = pm err := refreshRun(tt.opts) if tt.wantErr != "" { diff --git a/pkg/cmd/auth/shared/git_credential.go b/pkg/cmd/auth/shared/git_credential.go index e6cbe3c29..9c9a1cf6b 100644 --- a/pkg/cmd/auth/shared/git_credential.go +++ b/pkg/cmd/auth/shared/git_credential.go @@ -10,14 +10,13 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/ghinstance" - "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/internal/run" "github.com/google/shlex" ) type GitCredentialFlow struct { Executable string - Prompter prompter.Prompter + Prompter Prompt shouldSetup bool helper string diff --git a/pkg/cmd/auth/shared/login_flow.go b/pkg/cmd/auth/shared/login_flow.go index 16386c20c..9cc9d9865 100644 --- a/pkg/cmd/auth/shared/login_flow.go +++ b/pkg/cmd/auth/shared/login_flow.go @@ -10,7 +10,6 @@ import ( "github.com/cli/cli/v2/api" "github.com/cli/cli/v2/internal/authflow" "github.com/cli/cli/v2/internal/ghinstance" - "github.com/cli/cli/v2/internal/prompter" "github.com/cli/cli/v2/pkg/cmd/ssh-key/add" "github.com/cli/cli/v2/pkg/iostreams" "github.com/cli/cli/v2/pkg/ssh" @@ -34,7 +33,7 @@ type LoginOptions struct { Scopes []string Executable string GitProtocol string - Prompter prompter.Prompter + Prompter Prompt sshContext ssh.Context } diff --git a/pkg/cmd/auth/shared/prompt.go b/pkg/cmd/auth/shared/prompt.go new file mode 100644 index 000000000..c0d47372c --- /dev/null +++ b/pkg/cmd/auth/shared/prompt.go @@ -0,0 +1,10 @@ +package shared + +type Prompt interface { + Select(string, string, []string) (int, error) + Confirm(string, bool) (bool, error) + InputHostname() (string, error) + AuthToken() (string, error) + Input(string, string) (string, error) + Password(string) (string, error) +} diff --git a/pkg/cmd/gist/clone/clone.go b/pkg/cmd/gist/clone/clone.go index c1dfee31b..41fa104fa 100644 --- a/pkg/cmd/gist/clone/clone.go +++ b/pkg/cmd/gist/clone/clone.go @@ -7,6 +7,7 @@ import ( "github.com/MakeNowJust/heredoc" "github.com/cli/cli/v2/git" "github.com/cli/cli/v2/internal/config" + "github.com/cli/cli/v2/internal/ghinstance" "github.com/cli/cli/v2/pkg/cmdutil" "github.com/cli/cli/v2/pkg/iostreams" "github.com/spf13/cobra" @@ -92,9 +93,15 @@ func cloneRun(opts *CloneOptions) error { } func formatRemoteURL(hostname string, gistID string, protocol string) string { + if ghinstance.IsEnterprise(hostname) { + if protocol == "ssh" { + return fmt.Sprintf("git@%s:gist/%s.git", hostname, gistID) + } + return fmt.Sprintf("https://%s/gist/%s.git", hostname, gistID) + } + if protocol == "ssh" { return fmt.Sprintf("git@gist.%s:%s.git", hostname, gistID) } - return fmt.Sprintf("https://gist.%s/%s.git", hostname, gistID) } diff --git a/pkg/cmd/gist/clone/clone_test.go b/pkg/cmd/gist/clone/clone_test.go index ebf9b5c31..ccca76b25 100644 --- a/pkg/cmd/gist/clone/clone_test.go +++ b/pkg/cmd/gist/clone/clone_test.go @@ -116,3 +116,60 @@ func Test_GistClone_flagError(t *testing.T) { t.Errorf("unexpected error %v", err) } } + +func Test_formatRemoteURL(t *testing.T) { + type args struct { + hostname string + gistID string + protocol string + } + tests := []struct { + name string + args args + want string + }{ + { + name: "github.com HTTPS", + args: args{ + hostname: "github.com", + protocol: "https", + gistID: "ID", + }, + want: "https://gist.github.com/ID.git", + }, + { + name: "github.com SSH", + args: args{ + hostname: "github.com", + protocol: "ssh", + gistID: "ID", + }, + want: "git@gist.github.com:ID.git", + }, + { + name: "Enterprise HTTPS", + args: args{ + hostname: "acme.org", + protocol: "https", + gistID: "ID", + }, + want: "https://acme.org/gist/ID.git", + }, + { + name: "Enterprise SSH", + args: args{ + hostname: "acme.org", + protocol: "ssh", + gistID: "ID", + }, + want: "git@acme.org:gist/ID.git", + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if got := formatRemoteURL(tt.args.hostname, tt.args.gistID, tt.args.protocol); got != tt.want { + t.Errorf("formatRemoteURL() = %v, want %v", got, tt.want) + } + }) + } +} diff --git a/pkg/cmd/search/repos/repos.go b/pkg/cmd/search/repos/repos.go index 412b36cbb..23e5bfbef 100644 --- a/pkg/cmd/search/repos/repos.go +++ b/pkg/cmd/search/repos/repos.go @@ -20,6 +20,7 @@ type ReposOptions struct { Browser browser.Browser Exporter cmdutil.Exporter IO *iostreams.IOStreams + Now time.Time Query search.Query Searcher search.Searcher WebMode bool @@ -148,10 +149,14 @@ func reposRun(opts *ReposOptions) error { if len(result.Items) == 0 { return cmdutil.NewNoResultsError("no repositories matched your search") } - return displayResults(io, result) + + return displayResults(io, opts.Now, result) } -func displayResults(io *iostreams.IOStreams, results search.RepositoriesResult) error { +func displayResults(io *iostreams.IOStreams, now time.Time, results search.RepositoriesResult) error { + if now.IsZero() { + now = time.Now() + } cs := io.ColorScheme() tp := utils.NewTablePrinter(io) for _, repo := range results.Items { @@ -172,13 +177,12 @@ func displayResults(io *iostreams.IOStreams, results search.RepositoriesResult) tp.AddField(text.RemoveExcessiveWhitespace(description), nil, nil) tp.AddField(info, nil, infoColor) if tp.IsTTY() { - tp.AddField(text.FuzzyAgoAbbr(time.Now(), repo.UpdatedAt), nil, cs.Gray) + tp.AddField(text.FuzzyAgoAbbr(now, repo.UpdatedAt), nil, cs.Gray) } else { tp.AddField(repo.UpdatedAt.Format(time.RFC3339), nil, nil) } tp.EndRow() } - if io.IsStdoutTTY() { header := fmt.Sprintf("Showing %d of %d repositories\n\n", len(results.Items), results.Total) fmt.Fprintf(io.Out, "\n%s", header) diff --git a/pkg/cmd/search/repos/repos_test.go b/pkg/cmd/search/repos/repos_test.go index 010ee84cc..d0410b196 100644 --- a/pkg/cmd/search/repos/repos_test.go +++ b/pkg/cmd/search/repos/repos_test.go @@ -149,6 +149,8 @@ func TestNewCmdRepos(t *testing.T) { } func TestReposRun(t *testing.T) { + var now = time.Date(2022, 2, 28, 12, 30, 0, 0, time.UTC) + var updatedAt = time.Date(2021, 2, 28, 12, 30, 0, 0, time.UTC) var query = search.Query{ Keywords: []string{"cli"}, Kind: "repositories", @@ -158,7 +160,6 @@ func TestReposRun(t *testing.T) { Topic: []string{"golang"}, }, } - var updatedAt = time.Date(2021, 2, 28, 12, 30, 0, 0, time.UTC) tests := []struct { errMsg string name string @@ -270,6 +271,7 @@ func TestReposRun(t *testing.T) { ios.SetStdoutTTY(tt.tty) ios.SetStderrTTY(tt.tty) tt.opts.IO = ios + tt.opts.Now = now t.Run(tt.name, func(t *testing.T) { err := reposRun(tt.opts) if tt.wantErr { diff --git a/pkg/cmd/search/shared/shared.go b/pkg/cmd/search/shared/shared.go index 7531cfedf..f670548b3 100644 --- a/pkg/cmd/search/shared/shared.go +++ b/pkg/cmd/search/shared/shared.go @@ -31,6 +31,7 @@ type IssuesOptions struct { Entity EntityType Exporter cmdutil.Exporter IO *iostreams.IOStreams + Now time.Time Query search.Query Searcher search.Searcher WebMode bool @@ -88,10 +89,13 @@ func SearchIssues(opts *IssuesOptions) error { return cmdutil.NewNoResultsError(msg) } - return displayIssueResults(io, opts.Entity, result) + return displayIssueResults(io, opts.Now, opts.Entity, result) } -func displayIssueResults(io *iostreams.IOStreams, et EntityType, results search.IssuesResult) error { +func displayIssueResults(io *iostreams.IOStreams, now time.Time, et EntityType, results search.IssuesResult) error { + if now.IsZero() { + now = time.Now() + } cs := io.ColorScheme() tp := utils.NewTablePrinter(io) for _, issue := range results.Items { @@ -120,7 +124,7 @@ func displayIssueResults(io *iostreams.IOStreams, et EntityType, results search. tp.AddField(text.RemoveExcessiveWhitespace(issue.Title), nil, nil) tp.AddField(listIssueLabels(&issue, cs, tp.IsTTY()), nil, nil) if tp.IsTTY() { - tp.AddField(text.FuzzyAgo(time.Now(), issue.UpdatedAt), nil, cs.Gray) + tp.AddField(text.FuzzyAgo(now, issue.UpdatedAt), nil, cs.Gray) } else { tp.AddField(issue.UpdatedAt.String(), nil, nil) } diff --git a/pkg/cmd/search/shared/shared_test.go b/pkg/cmd/search/shared/shared_test.go index 66c9c9cc2..fe6c8c57b 100644 --- a/pkg/cmd/search/shared/shared_test.go +++ b/pkg/cmd/search/shared/shared_test.go @@ -23,7 +23,9 @@ func TestSearcher(t *testing.T) { } func TestSearchIssues(t *testing.T) { - query := search.Query{ + var now = time.Date(2022, 2, 28, 12, 30, 0, 0, time.UTC) + var updatedAt = time.Date(2021, 2, 28, 12, 30, 0, 0, time.UTC) + var query = search.Query{ Keywords: []string{"keyword"}, Kind: "issues", Limit: 30, @@ -33,8 +35,6 @@ func TestSearchIssues(t *testing.T) { Is: []string{"public", "locked"}, }, } - - var updatedAt = time.Date(2021, 2, 28, 12, 30, 0, 0, time.UTC) tests := []struct { errMsg string name string @@ -193,6 +193,7 @@ func TestSearchIssues(t *testing.T) { ios.SetStdoutTTY(tt.tty) ios.SetStderrTTY(tt.tty) tt.opts.IO = ios + tt.opts.Now = now t.Run(tt.name, func(t *testing.T) { err := SearchIssues(tt.opts) if tt.wantErr { diff --git a/pkg/cmd/secret/delete/delete.go b/pkg/cmd/secret/delete/delete.go index bf1eb5c77..4759dd1a2 100644 --- a/pkg/cmd/secret/delete/delete.go +++ b/pkg/cmd/secret/delete/delete.go @@ -41,7 +41,7 @@ func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Co Delete a secret on one of the following levels: - repository (default): available to Actions runs or Dependabot in a repository - environment: available to Actions runs for a deployment environment in a repository - - organization: available to Actions runs or Dependabot within an organization + - organization: available to Actions runs, Dependabot, or Codespaces within an organization - user: available to Codespaces for your user `), Args: cobra.ExactArgs(1), diff --git a/pkg/cmd/secret/delete/delete_test.go b/pkg/cmd/secret/delete/delete_test.go index 30030b104..3e4108703 100644 --- a/pkg/cmd/secret/delete/delete_test.go +++ b/pkg/cmd/secret/delete/delete_test.go @@ -73,6 +73,15 @@ func TestNewCmdDelete(t *testing.T) { Application: "Dependabot", }, }, + { + name: "Codespaces org", + cli: "cool --app codespaces --org UmbrellaCorporation", + wants: DeleteOptions{ + SecretName: "cool", + OrgName: "UmbrellaCorporation", + Application: "Codespaces", + }, + }, } for _, tt := range tests { @@ -219,6 +228,14 @@ func Test_removeRun_org(t *testing.T) { }, wantPath: "orgs/UmbrellaCorporation/dependabot/secrets/tVirus", }, + { + name: "Codespaces org", + opts: &DeleteOptions{ + Application: "codespaces", + OrgName: "UmbrellaCorporation", + }, + wantPath: "orgs/UmbrellaCorporation/codespaces/secrets/tVirus", + }, } for _, tt := range tests { diff --git a/pkg/cmd/secret/list/list.go b/pkg/cmd/secret/list/list.go index 2a3d5a100..a7336570c 100644 --- a/pkg/cmd/secret/list/list.go +++ b/pkg/cmd/secret/list/list.go @@ -46,7 +46,7 @@ func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Comman List secrets on one of the following levels: - repository (default): available to Actions runs or Dependabot in a repository - environment: available to Actions runs for a deployment environment in a repository - - organization: available to Actions runs or Dependabot within an organization + - organization: available to Actions runs, Dependabot, or Codespaces within an organization - user: available to Codespaces for your user `), Aliases: []string{"ls"}, diff --git a/pkg/cmd/secret/secret.go b/pkg/cmd/secret/secret.go index 8e331e813..ea8d6f40d 100644 --- a/pkg/cmd/secret/secret.go +++ b/pkg/cmd/secret/secret.go @@ -15,7 +15,7 @@ func NewCmdSecret(f *cmdutil.Factory) *cobra.Command { Short: "Manage GitHub secrets", Long: heredoc.Doc(` Secrets can be set at the repository, or organization level for use in - GitHub Actions or Dependabot. User and repository secrets can be set for + GitHub Actions or Dependabot. User, organization, and repository secrets can be set for use in GitHub Codespaces. Environment secrets can be set for use in GitHub Actions. Run "gh help secret set" to learn how to get started. `), diff --git a/pkg/cmd/secret/set/set.go b/pkg/cmd/secret/set/set.go index 2ba90b888..d56b3d074 100644 --- a/pkg/cmd/secret/set/set.go +++ b/pkg/cmd/secret/set/set.go @@ -58,7 +58,7 @@ func NewCmdSet(f *cmdutil.Factory, runF func(*SetOptions) error) *cobra.Command Set a value for a secret on one of the following levels: - repository (default): available to Actions runs or Dependabot in a repository - environment: available to Actions runs for a deployment environment in a repository - - organization: available to Actions runs or Dependabot within an organization + - organization: available to Actions runs, Dependabot, or Codespaces within an organization - user: available to Codespaces for your user Organization and user secrets can optionally be restricted to only be available to diff --git a/pkg/cmd/secret/set/set_test.go b/pkg/cmd/secret/set/set_test.go index ee86f1d10..d9313f81f 100644 --- a/pkg/cmd/secret/set/set_test.go +++ b/pkg/cmd/secret/set/set_test.go @@ -165,6 +165,18 @@ func TestNewCmdSet(t *testing.T) { Application: "Dependabot", }, }, + { + name: "Codespaces org", + cli: `random_secret -ocoolOrg -b"random value" -vselected -r"coolRepo,cli/cli" -aCodespaces`, + wants: SetOptions{ + SecretName: "random_secret", + Visibility: shared.Selected, + RepositoryNames: []string{"coolRepo", "cli/cli"}, + Body: "random value", + OrgName: "coolOrg", + Application: "Codespaces", + }, + }, } for _, tt := range tests { diff --git a/pkg/cmd/secret/shared/shared.go b/pkg/cmd/secret/shared/shared.go index 14ecd293a..9fe687416 100644 --- a/pkg/cmd/secret/shared/shared.go +++ b/pkg/cmd/secret/shared/shared.go @@ -85,7 +85,7 @@ func IsSupportedSecretEntity(app App, entity SecretEntity) bool { case Actions: return entity == Repository || entity == Organization || entity == Environment case Codespaces: - return entity == User || entity == Repository + return entity == User || entity == Organization || entity == Repository case Dependabot: return entity == Repository || entity == Organization default: diff --git a/pkg/cmd/secret/shared/shared_test.go b/pkg/cmd/secret/shared/shared_test.go index 4b534522f..eb121f0a8 100644 --- a/pkg/cmd/secret/shared/shared_test.go +++ b/pkg/cmd/secret/shared/shared_test.go @@ -167,9 +167,9 @@ func TestIsSupportedSecretEntity(t *testing.T) { supportedEntities: []SecretEntity{ User, Repository, + Organization, }, unsupportedEntities: []SecretEntity{ - Organization, Environment, Unknown, },