X Tutup
Skip to content

Commit 3b1e526

Browse files
author
Nate Smith
authored
Merge pull request cli#2529 from cli/441-secrets
gh secret {set,list,remove}
2 parents 65e5ba9 + 352cde0 commit 3b1e526

File tree

11 files changed

+1347
-2
lines changed

11 files changed

+1347
-2
lines changed

pkg/cmd/gist/create/create.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,8 @@ func createGist(client *http.Client, hostname, description string, public bool,
227227
}
228228
requestBody := bytes.NewReader(requestByte)
229229

230-
apliClient := api.NewClientFromHTTP(client)
231-
err = apliClient.REST(hostname, "POST", path, requestBody, &result)
230+
apiClient := api.NewClientFromHTTP(client)
231+
err = apiClient.REST(hostname, "POST", path, requestBody, &result)
232232
if err != nil {
233233
return nil, err
234234
}

pkg/cmd/root/root.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ import (
1919
releaseCmd "github.com/cli/cli/pkg/cmd/release"
2020
repoCmd "github.com/cli/cli/pkg/cmd/repo"
2121
creditsCmd "github.com/cli/cli/pkg/cmd/repo/credits"
22+
secretCmd "github.com/cli/cli/pkg/cmd/secret"
2223
versionCmd "github.com/cli/cli/pkg/cmd/version"
2324
"github.com/cli/cli/pkg/cmdutil"
2425
"github.com/spf13/cobra"
@@ -74,6 +75,7 @@ func NewCmdRoot(f *cmdutil.Factory, version, buildDate string) *cobra.Command {
7475
cmd.AddCommand(creditsCmd.NewCmdCredits(f, nil))
7576
cmd.AddCommand(gistCmd.NewCmdGist(f))
7677
cmd.AddCommand(completionCmd.NewCmdCompletion(f.IOStreams))
78+
cmd.AddCommand(secretCmd.NewCmdSecret(f))
7779

7880
// the `api` command should not inherit any extra HTTP headers
7981
bareHTTPCmdFactory := *f

pkg/cmd/secret/list/list.go

Lines changed: 183 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,183 @@
1+
package list
2+
3+
import (
4+
"fmt"
5+
"net/http"
6+
"net/url"
7+
"strings"
8+
"time"
9+
10+
"github.com/cli/cli/api"
11+
"github.com/cli/cli/internal/ghinstance"
12+
"github.com/cli/cli/internal/ghrepo"
13+
"github.com/cli/cli/pkg/cmd/secret/shared"
14+
"github.com/cli/cli/pkg/cmdutil"
15+
"github.com/cli/cli/pkg/iostreams"
16+
"github.com/cli/cli/utils"
17+
"github.com/spf13/cobra"
18+
)
19+
20+
type ListOptions struct {
21+
HttpClient func() (*http.Client, error)
22+
IO *iostreams.IOStreams
23+
BaseRepo func() (ghrepo.Interface, error)
24+
25+
OrgName string
26+
}
27+
28+
func NewCmdList(f *cmdutil.Factory, runF func(*ListOptions) error) *cobra.Command {
29+
opts := &ListOptions{
30+
IO: f.IOStreams,
31+
HttpClient: f.HttpClient,
32+
}
33+
34+
cmd := &cobra.Command{
35+
Use: "list",
36+
Short: "List secrets",
37+
Long: "List secrets for a repository or organization",
38+
Args: cobra.NoArgs,
39+
RunE: func(cmd *cobra.Command, args []string) error {
40+
// support `-R, --repo` override
41+
opts.BaseRepo = f.BaseRepo
42+
43+
if runF != nil {
44+
return runF(opts)
45+
}
46+
47+
return listRun(opts)
48+
},
49+
}
50+
51+
cmd.Flags().StringVarP(&opts.OrgName, "org", "o", "", "List secrets for an organization")
52+
53+
return cmd
54+
}
55+
56+
func listRun(opts *ListOptions) error {
57+
c, err := opts.HttpClient()
58+
if err != nil {
59+
return fmt.Errorf("could not create http client: %w", err)
60+
}
61+
client := api.NewClientFromHTTP(c)
62+
63+
orgName := opts.OrgName
64+
65+
var baseRepo ghrepo.Interface
66+
if orgName == "" {
67+
baseRepo, err = opts.BaseRepo()
68+
if err != nil {
69+
return fmt.Errorf("could not determine base repo: %w", err)
70+
}
71+
}
72+
73+
var secrets []*Secret
74+
if orgName == "" {
75+
secrets, err = getRepoSecrets(client, baseRepo)
76+
} else {
77+
secrets, err = getOrgSecrets(client, orgName)
78+
}
79+
80+
if err != nil {
81+
return fmt.Errorf("failed to get secrets: %w", err)
82+
}
83+
84+
tp := utils.NewTablePrinter(opts.IO)
85+
for _, secret := range secrets {
86+
tp.AddField(secret.Name, nil, nil)
87+
updatedAt := secret.UpdatedAt.Format("2006-01-02")
88+
if opts.IO.IsStdoutTTY() {
89+
updatedAt = fmt.Sprintf("Updated %s", updatedAt)
90+
}
91+
tp.AddField(updatedAt, nil, nil)
92+
if secret.Visibility != "" {
93+
if opts.IO.IsStdoutTTY() {
94+
tp.AddField(fmtVisibility(*secret), nil, nil)
95+
} else {
96+
tp.AddField(strings.ToUpper(string(secret.Visibility)), nil, nil)
97+
}
98+
}
99+
tp.EndRow()
100+
}
101+
102+
err = tp.Render()
103+
if err != nil {
104+
return err
105+
}
106+
107+
return nil
108+
}
109+
110+
type Secret struct {
111+
Name string
112+
UpdatedAt time.Time `json:"updated_at"`
113+
Visibility shared.Visibility
114+
SelectedReposURL string `json:"selected_repositories_url"`
115+
NumSelectedRepos int
116+
}
117+
118+
func fmtVisibility(s Secret) string {
119+
switch s.Visibility {
120+
case shared.All:
121+
return "Visible to all repositories"
122+
case shared.Private:
123+
return "Visible to private repositories"
124+
case shared.Selected:
125+
if s.NumSelectedRepos == 1 {
126+
return "Visible to 1 selected repository"
127+
} else {
128+
return fmt.Sprintf("Visible to %d selected repositories", s.NumSelectedRepos)
129+
}
130+
}
131+
return ""
132+
}
133+
134+
func getOrgSecrets(client *api.Client, orgName string) ([]*Secret, error) {
135+
host := ghinstance.OverridableDefault()
136+
secrets, err := getSecrets(client, host, fmt.Sprintf("orgs/%s/actions/secrets", orgName))
137+
if err != nil {
138+
return nil, err
139+
}
140+
141+
type responseData struct {
142+
TotalCount int `json:"total_count"`
143+
}
144+
145+
for _, secret := range secrets {
146+
if secret.SelectedReposURL == "" {
147+
continue
148+
}
149+
u, err := url.Parse(secret.SelectedReposURL)
150+
if err != nil {
151+
return nil, fmt.Errorf("failed determining selected repositories for %s: %w", secret.Name, err)
152+
}
153+
154+
var result responseData
155+
err = client.REST(u.Host, "GET", u.Path[1:], nil, &result)
156+
if err != nil {
157+
return nil, fmt.Errorf("failed determining selected repositories for %s: %w", secret.Name, err)
158+
}
159+
secret.NumSelectedRepos = result.TotalCount
160+
}
161+
162+
return secrets, nil
163+
}
164+
165+
func getRepoSecrets(client *api.Client, repo ghrepo.Interface) ([]*Secret, error) {
166+
return getSecrets(client, repo.RepoHost(), fmt.Sprintf("repos/%s/actions/secrets",
167+
ghrepo.FullName(repo)))
168+
}
169+
170+
type secretsPayload struct {
171+
Secrets []*Secret
172+
}
173+
174+
func getSecrets(client *api.Client, host, path string) ([]*Secret, error) {
175+
result := secretsPayload{}
176+
177+
err := client.REST(host, "GET", path, nil, &result)
178+
if err != nil {
179+
return nil, err
180+
}
181+
182+
return result.Secrets, nil
183+
}

0 commit comments

Comments
 (0)
X Tutup