github.com/google/go-github/v57@v57.0.0/github/actions_secrets.go (about) 1 // Copyright 2020 The go-github AUTHORS. All rights reserved. 2 // 3 // Use of this source code is governed by a BSD-style 4 // license that can be found in the LICENSE file. 5 6 package github 7 8 import ( 9 "context" 10 "encoding/json" 11 "fmt" 12 "strconv" 13 ) 14 15 // PublicKey represents the public key that should be used to encrypt secrets. 16 type PublicKey struct { 17 KeyID *string `json:"key_id"` 18 Key *string `json:"key"` 19 } 20 21 // UnmarshalJSON implements the json.Unmarshaler interface. 22 // This ensures GitHub Enterprise versions which return a numeric key id 23 // do not error out when unmarshaling. 24 func (p *PublicKey) UnmarshalJSON(data []byte) error { 25 var pk struct { 26 KeyID interface{} `json:"key_id"` 27 Key *string `json:"key"` 28 } 29 30 if err := json.Unmarshal(data, &pk); err != nil { 31 return err 32 } 33 34 p.Key = pk.Key 35 36 switch v := pk.KeyID.(type) { 37 case nil: 38 return nil 39 case string: 40 p.KeyID = &v 41 case float64: 42 p.KeyID = String(strconv.FormatFloat(v, 'f', -1, 64)) 43 default: 44 return fmt.Errorf("unable to unmarshal %T as a string", v) 45 } 46 47 return nil 48 } 49 50 func (s *ActionsService) getPublicKey(ctx context.Context, url string) (*PublicKey, *Response, error) { 51 req, err := s.client.NewRequest("GET", url, nil) 52 if err != nil { 53 return nil, nil, err 54 } 55 56 pubKey := new(PublicKey) 57 resp, err := s.client.Do(ctx, req, pubKey) 58 if err != nil { 59 return nil, resp, err 60 } 61 62 return pubKey, resp, nil 63 } 64 65 // GetRepoPublicKey gets a public key that should be used for secret encryption. 66 // 67 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-a-repository-public-key 68 // 69 //meta:operation GET /repos/{owner}/{repo}/actions/secrets/public-key 70 func (s *ActionsService) GetRepoPublicKey(ctx context.Context, owner, repo string) (*PublicKey, *Response, error) { 71 url := fmt.Sprintf("repos/%v/%v/actions/secrets/public-key", owner, repo) 72 return s.getPublicKey(ctx, url) 73 } 74 75 // GetOrgPublicKey gets a public key that should be used for secret encryption. 76 // 77 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-organization-public-key 78 // 79 //meta:operation GET /orgs/{org}/actions/secrets/public-key 80 func (s *ActionsService) GetOrgPublicKey(ctx context.Context, org string) (*PublicKey, *Response, error) { 81 url := fmt.Sprintf("orgs/%v/actions/secrets/public-key", org) 82 return s.getPublicKey(ctx, url) 83 } 84 85 // GetEnvPublicKey gets a public key that should be used for secret encryption. 86 // 87 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-environment-public-key 88 // 89 //meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets/public-key 90 func (s *ActionsService) GetEnvPublicKey(ctx context.Context, repoID int, env string) (*PublicKey, *Response, error) { 91 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/public-key", repoID, env) 92 return s.getPublicKey(ctx, url) 93 } 94 95 // Secret represents a repository action secret. 96 type Secret struct { 97 Name string `json:"name"` 98 CreatedAt Timestamp `json:"created_at"` 99 UpdatedAt Timestamp `json:"updated_at"` 100 Visibility string `json:"visibility,omitempty"` 101 SelectedRepositoriesURL string `json:"selected_repositories_url,omitempty"` 102 } 103 104 // Secrets represents one item from the ListSecrets response. 105 type Secrets struct { 106 TotalCount int `json:"total_count"` 107 Secrets []*Secret `json:"secrets"` 108 } 109 110 func (s *ActionsService) listSecrets(ctx context.Context, url string, opts *ListOptions) (*Secrets, *Response, error) { 111 u, err := addOptions(url, opts) 112 if err != nil { 113 return nil, nil, err 114 } 115 116 req, err := s.client.NewRequest("GET", u, nil) 117 if err != nil { 118 return nil, nil, err 119 } 120 121 secrets := new(Secrets) 122 resp, err := s.client.Do(ctx, req, &secrets) 123 if err != nil { 124 return nil, resp, err 125 } 126 127 return secrets, resp, nil 128 } 129 130 // ListRepoSecrets lists all secrets available in a repository 131 // without revealing their encrypted values. 132 // 133 // GitHub API docs: https://docs.github.com/rest/actions/secrets#list-repository-secrets 134 // 135 //meta:operation GET /repos/{owner}/{repo}/actions/secrets 136 func (s *ActionsService) ListRepoSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { 137 url := fmt.Sprintf("repos/%v/%v/actions/secrets", owner, repo) 138 return s.listSecrets(ctx, url, opts) 139 } 140 141 // ListOrgSecrets lists all secrets available in an organization 142 // without revealing their encrypted values. 143 // 144 // GitHub API docs: https://docs.github.com/rest/actions/secrets#list-organization-secrets 145 // 146 //meta:operation GET /orgs/{org}/actions/secrets 147 func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { 148 url := fmt.Sprintf("orgs/%v/actions/secrets", org) 149 return s.listSecrets(ctx, url, opts) 150 } 151 152 // ListEnvSecrets lists all secrets available in an environment. 153 // 154 // GitHub API docs: https://docs.github.com/rest/actions/secrets#list-environment-secrets 155 // 156 //meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets 157 func (s *ActionsService) ListEnvSecrets(ctx context.Context, repoID int, env string, opts *ListOptions) (*Secrets, *Response, error) { 158 url := fmt.Sprintf("repositories/%v/environments/%v/secrets", repoID, env) 159 return s.listSecrets(ctx, url, opts) 160 } 161 162 func (s *ActionsService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { 163 req, err := s.client.NewRequest("GET", url, nil) 164 if err != nil { 165 return nil, nil, err 166 } 167 168 secret := new(Secret) 169 resp, err := s.client.Do(ctx, req, secret) 170 if err != nil { 171 return nil, resp, err 172 } 173 174 return secret, resp, nil 175 } 176 177 // GetRepoSecret gets a single repository secret without revealing its encrypted value. 178 // 179 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-a-repository-secret 180 // 181 //meta:operation GET /repos/{owner}/{repo}/actions/secrets/{secret_name} 182 func (s *ActionsService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { 183 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) 184 return s.getSecret(ctx, url) 185 } 186 187 // GetOrgSecret gets a single organization secret without revealing its encrypted value. 188 // 189 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-organization-secret 190 // 191 //meta:operation GET /orgs/{org}/actions/secrets/{secret_name} 192 func (s *ActionsService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { 193 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) 194 return s.getSecret(ctx, url) 195 } 196 197 // GetEnvSecret gets a single environment secret without revealing its encrypted value. 198 // 199 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-environment-secret 200 // 201 //meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} 202 func (s *ActionsService) GetEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Secret, *Response, error) { 203 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) 204 return s.getSecret(ctx, url) 205 } 206 207 // SelectedRepoIDs are the repository IDs that have access to the actions secrets. 208 type SelectedRepoIDs []int64 209 210 // EncryptedSecret represents a secret that is encrypted using a public key. 211 // 212 // The value of EncryptedValue must be your secret, encrypted with 213 // LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) 214 // using the public key retrieved using the GetPublicKey method. 215 type EncryptedSecret struct { 216 Name string `json:"-"` 217 KeyID string `json:"key_id"` 218 EncryptedValue string `json:"encrypted_value"` 219 Visibility string `json:"visibility,omitempty"` 220 SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"` 221 } 222 223 func (s *ActionsService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { 224 req, err := s.client.NewRequest("PUT", url, eSecret) 225 if err != nil { 226 return nil, err 227 } 228 229 return s.client.Do(ctx, req, nil) 230 } 231 232 // CreateOrUpdateRepoSecret creates or updates a repository secret with an encrypted value. 233 // 234 // GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-a-repository-secret 235 // 236 //meta:operation PUT /repos/{owner}/{repo}/actions/secrets/{secret_name} 237 func (s *ActionsService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { 238 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name) 239 return s.putSecret(ctx, url, eSecret) 240 } 241 242 // CreateOrUpdateOrgSecret creates or updates an organization secret with an encrypted value. 243 // 244 // GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-an-organization-secret 245 // 246 //meta:operation PUT /orgs/{org}/actions/secrets/{secret_name} 247 func (s *ActionsService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { 248 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, eSecret.Name) 249 return s.putSecret(ctx, url, eSecret) 250 } 251 252 // CreateOrUpdateEnvSecret creates or updates a single environment secret with an encrypted value. 253 // 254 // GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-an-environment-secret 255 // 256 //meta:operation PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} 257 func (s *ActionsService) CreateOrUpdateEnvSecret(ctx context.Context, repoID int, env string, eSecret *EncryptedSecret) (*Response, error) { 258 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, eSecret.Name) 259 return s.putSecret(ctx, url, eSecret) 260 } 261 262 func (s *ActionsService) deleteSecret(ctx context.Context, url string) (*Response, error) { 263 req, err := s.client.NewRequest("DELETE", url, nil) 264 if err != nil { 265 return nil, err 266 } 267 268 return s.client.Do(ctx, req, nil) 269 } 270 271 // DeleteRepoSecret deletes a secret in a repository using the secret name. 272 // 273 // GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-a-repository-secret 274 // 275 //meta:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name} 276 func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { 277 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) 278 return s.deleteSecret(ctx, url) 279 } 280 281 // DeleteOrgSecret deletes a secret in an organization using the secret name. 282 // 283 // GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-an-organization-secret 284 // 285 //meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name} 286 func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { 287 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) 288 return s.deleteSecret(ctx, url) 289 } 290 291 // DeleteEnvSecret deletes a secret in an environment using the secret name. 292 // 293 // GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-an-environment-secret 294 // 295 //meta:operation DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} 296 func (s *ActionsService) DeleteEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Response, error) { 297 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) 298 return s.deleteSecret(ctx, url) 299 } 300 301 // SelectedReposList represents the list of repositories selected for an organization secret. 302 type SelectedReposList struct { 303 TotalCount *int `json:"total_count,omitempty"` 304 Repositories []*Repository `json:"repositories,omitempty"` 305 } 306 307 func (s *ActionsService) listSelectedReposForSecret(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { 308 u, err := addOptions(url, opts) 309 if err != nil { 310 return nil, nil, err 311 } 312 313 req, err := s.client.NewRequest("GET", u, nil) 314 if err != nil { 315 return nil, nil, err 316 } 317 318 result := new(SelectedReposList) 319 resp, err := s.client.Do(ctx, req, result) 320 if err != nil { 321 return nil, resp, err 322 } 323 324 return result, resp, nil 325 } 326 327 // ListSelectedReposForOrgSecret lists all repositories that have access to a secret. 328 // 329 // GitHub API docs: https://docs.github.com/rest/actions/secrets#list-selected-repositories-for-an-organization-secret 330 // 331 //meta:operation GET /orgs/{org}/actions/secrets/{secret_name}/repositories 332 func (s *ActionsService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { 333 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) 334 return s.listSelectedReposForSecret(ctx, url, opts) 335 } 336 337 func (s *ActionsService) setSelectedReposForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { 338 type repoIDs struct { 339 SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` 340 } 341 342 req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) 343 if err != nil { 344 return nil, err 345 } 346 347 return s.client.Do(ctx, req, nil) 348 } 349 350 // SetSelectedReposForOrgSecret sets the repositories that have access to a secret. 351 // 352 // GitHub API docs: https://docs.github.com/rest/actions/secrets#set-selected-repositories-for-an-organization-secret 353 // 354 //meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories 355 func (s *ActionsService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { 356 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) 357 return s.setSelectedReposForSecret(ctx, url, ids) 358 } 359 360 func (s *ActionsService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { 361 req, err := s.client.NewRequest("PUT", url, nil) 362 if err != nil { 363 return nil, err 364 } 365 366 return s.client.Do(ctx, req, nil) 367 } 368 369 // AddSelectedRepoToOrgSecret adds a repository to an organization secret. 370 // 371 // GitHub API docs: https://docs.github.com/rest/actions/secrets#add-selected-repository-to-an-organization-secret 372 // 373 //meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} 374 func (s *ActionsService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { 375 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) 376 return s.addSelectedRepoToSecret(ctx, url) 377 } 378 379 func (s *ActionsService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { 380 req, err := s.client.NewRequest("DELETE", url, nil) 381 if err != nil { 382 return nil, err 383 } 384 385 return s.client.Do(ctx, req, nil) 386 } 387 388 // RemoveSelectedRepoFromOrgSecret removes a repository from an organization secret. 389 // 390 // GitHub API docs: https://docs.github.com/rest/actions/secrets#remove-selected-repository-from-an-organization-secret 391 // 392 //meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} 393 func (s *ActionsService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { 394 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) 395 return s.removeSelectedRepoFromSecret(ctx, url) 396 }