github.com/google/go-github/v70@v70.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 = Ptr(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/enterprise-server@3.7/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 // ListRepoOrgSecrets lists all organization secrets available in a repository 142 // without revealing their encrypted values. 143 // 144 // GitHub API docs: https://docs.github.com/rest/actions/secrets#list-repository-organization-secrets 145 // 146 //meta:operation GET /repos/{owner}/{repo}/actions/organization-secrets 147 func (s *ActionsService) ListRepoOrgSecrets(ctx context.Context, owner, repo string, opts *ListOptions) (*Secrets, *Response, error) { 148 url := fmt.Sprintf("repos/%v/%v/actions/organization-secrets", owner, repo) 149 return s.listSecrets(ctx, url, opts) 150 } 151 152 // ListOrgSecrets lists all secrets available in an organization 153 // without revealing their encrypted values. 154 // 155 // GitHub API docs: https://docs.github.com/rest/actions/secrets#list-organization-secrets 156 // 157 //meta:operation GET /orgs/{org}/actions/secrets 158 func (s *ActionsService) ListOrgSecrets(ctx context.Context, org string, opts *ListOptions) (*Secrets, *Response, error) { 159 url := fmt.Sprintf("orgs/%v/actions/secrets", org) 160 return s.listSecrets(ctx, url, opts) 161 } 162 163 // ListEnvSecrets lists all secrets available in an environment. 164 // 165 // GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#list-environment-secrets 166 // 167 //meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets 168 func (s *ActionsService) ListEnvSecrets(ctx context.Context, repoID int, env string, opts *ListOptions) (*Secrets, *Response, error) { 169 url := fmt.Sprintf("repositories/%v/environments/%v/secrets", repoID, env) 170 return s.listSecrets(ctx, url, opts) 171 } 172 173 func (s *ActionsService) getSecret(ctx context.Context, url string) (*Secret, *Response, error) { 174 req, err := s.client.NewRequest("GET", url, nil) 175 if err != nil { 176 return nil, nil, err 177 } 178 179 secret := new(Secret) 180 resp, err := s.client.Do(ctx, req, secret) 181 if err != nil { 182 return nil, resp, err 183 } 184 185 return secret, resp, nil 186 } 187 188 // GetRepoSecret gets a single repository secret without revealing its encrypted value. 189 // 190 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-a-repository-secret 191 // 192 //meta:operation GET /repos/{owner}/{repo}/actions/secrets/{secret_name} 193 func (s *ActionsService) GetRepoSecret(ctx context.Context, owner, repo, name string) (*Secret, *Response, error) { 194 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) 195 return s.getSecret(ctx, url) 196 } 197 198 // GetOrgSecret gets a single organization secret without revealing its encrypted value. 199 // 200 // GitHub API docs: https://docs.github.com/rest/actions/secrets#get-an-organization-secret 201 // 202 //meta:operation GET /orgs/{org}/actions/secrets/{secret_name} 203 func (s *ActionsService) GetOrgSecret(ctx context.Context, org, name string) (*Secret, *Response, error) { 204 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) 205 return s.getSecret(ctx, url) 206 } 207 208 // GetEnvSecret gets a single environment secret without revealing its encrypted value. 209 // 210 // GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#get-an-environment-secret 211 // 212 //meta:operation GET /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} 213 func (s *ActionsService) GetEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Secret, *Response, error) { 214 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) 215 return s.getSecret(ctx, url) 216 } 217 218 // SelectedRepoIDs are the repository IDs that have access to the actions secrets. 219 type SelectedRepoIDs []int64 220 221 // EncryptedSecret represents a secret that is encrypted using a public key. 222 // 223 // The value of EncryptedValue must be your secret, encrypted with 224 // LibSodium (see documentation here: https://libsodium.gitbook.io/doc/bindings_for_other_languages) 225 // using the public key retrieved using the GetPublicKey method. 226 type EncryptedSecret struct { 227 Name string `json:"-"` 228 KeyID string `json:"key_id"` 229 EncryptedValue string `json:"encrypted_value"` 230 Visibility string `json:"visibility,omitempty"` 231 SelectedRepositoryIDs SelectedRepoIDs `json:"selected_repository_ids,omitempty"` 232 } 233 234 func (s *ActionsService) putSecret(ctx context.Context, url string, eSecret *EncryptedSecret) (*Response, error) { 235 req, err := s.client.NewRequest("PUT", url, eSecret) 236 if err != nil { 237 return nil, err 238 } 239 240 return s.client.Do(ctx, req, nil) 241 } 242 243 // CreateOrUpdateRepoSecret creates or updates a repository secret with an encrypted value. 244 // 245 // GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-a-repository-secret 246 // 247 //meta:operation PUT /repos/{owner}/{repo}/actions/secrets/{secret_name} 248 func (s *ActionsService) CreateOrUpdateRepoSecret(ctx context.Context, owner, repo string, eSecret *EncryptedSecret) (*Response, error) { 249 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, eSecret.Name) 250 return s.putSecret(ctx, url, eSecret) 251 } 252 253 // CreateOrUpdateOrgSecret creates or updates an organization secret with an encrypted value. 254 // 255 // GitHub API docs: https://docs.github.com/rest/actions/secrets#create-or-update-an-organization-secret 256 // 257 //meta:operation PUT /orgs/{org}/actions/secrets/{secret_name} 258 func (s *ActionsService) CreateOrUpdateOrgSecret(ctx context.Context, org string, eSecret *EncryptedSecret) (*Response, error) { 259 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, eSecret.Name) 260 return s.putSecret(ctx, url, eSecret) 261 } 262 263 // CreateOrUpdateEnvSecret creates or updates a single environment secret with an encrypted value. 264 // 265 // GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#create-or-update-an-environment-secret 266 // 267 //meta:operation PUT /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} 268 func (s *ActionsService) CreateOrUpdateEnvSecret(ctx context.Context, repoID int, env string, eSecret *EncryptedSecret) (*Response, error) { 269 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, eSecret.Name) 270 return s.putSecret(ctx, url, eSecret) 271 } 272 273 func (s *ActionsService) deleteSecret(ctx context.Context, url string) (*Response, error) { 274 req, err := s.client.NewRequest("DELETE", url, nil) 275 if err != nil { 276 return nil, err 277 } 278 279 return s.client.Do(ctx, req, nil) 280 } 281 282 // DeleteRepoSecret deletes a secret in a repository using the secret name. 283 // 284 // GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-a-repository-secret 285 // 286 //meta:operation DELETE /repos/{owner}/{repo}/actions/secrets/{secret_name} 287 func (s *ActionsService) DeleteRepoSecret(ctx context.Context, owner, repo, name string) (*Response, error) { 288 url := fmt.Sprintf("repos/%v/%v/actions/secrets/%v", owner, repo, name) 289 return s.deleteSecret(ctx, url) 290 } 291 292 // DeleteOrgSecret deletes a secret in an organization using the secret name. 293 // 294 // GitHub API docs: https://docs.github.com/rest/actions/secrets#delete-an-organization-secret 295 // 296 //meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name} 297 func (s *ActionsService) DeleteOrgSecret(ctx context.Context, org, name string) (*Response, error) { 298 url := fmt.Sprintf("orgs/%v/actions/secrets/%v", org, name) 299 return s.deleteSecret(ctx, url) 300 } 301 302 // DeleteEnvSecret deletes a secret in an environment using the secret name. 303 // 304 // GitHub API docs: https://docs.github.com/enterprise-server@3.7/rest/actions/secrets#delete-an-environment-secret 305 // 306 //meta:operation DELETE /repositories/{repository_id}/environments/{environment_name}/secrets/{secret_name} 307 func (s *ActionsService) DeleteEnvSecret(ctx context.Context, repoID int, env, secretName string) (*Response, error) { 308 url := fmt.Sprintf("repositories/%v/environments/%v/secrets/%v", repoID, env, secretName) 309 return s.deleteSecret(ctx, url) 310 } 311 312 // SelectedReposList represents the list of repositories selected for an organization secret. 313 type SelectedReposList struct { 314 TotalCount *int `json:"total_count,omitempty"` 315 Repositories []*Repository `json:"repositories,omitempty"` 316 } 317 318 func (s *ActionsService) listSelectedReposForSecret(ctx context.Context, url string, opts *ListOptions) (*SelectedReposList, *Response, error) { 319 u, err := addOptions(url, opts) 320 if err != nil { 321 return nil, nil, err 322 } 323 324 req, err := s.client.NewRequest("GET", u, nil) 325 if err != nil { 326 return nil, nil, err 327 } 328 329 result := new(SelectedReposList) 330 resp, err := s.client.Do(ctx, req, result) 331 if err != nil { 332 return nil, resp, err 333 } 334 335 return result, resp, nil 336 } 337 338 // ListSelectedReposForOrgSecret lists all repositories that have access to a secret. 339 // 340 // GitHub API docs: https://docs.github.com/rest/actions/secrets#list-selected-repositories-for-an-organization-secret 341 // 342 //meta:operation GET /orgs/{org}/actions/secrets/{secret_name}/repositories 343 func (s *ActionsService) ListSelectedReposForOrgSecret(ctx context.Context, org, name string, opts *ListOptions) (*SelectedReposList, *Response, error) { 344 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) 345 return s.listSelectedReposForSecret(ctx, url, opts) 346 } 347 348 func (s *ActionsService) setSelectedReposForSecret(ctx context.Context, url string, ids SelectedRepoIDs) (*Response, error) { 349 type repoIDs struct { 350 SelectedIDs SelectedRepoIDs `json:"selected_repository_ids"` 351 } 352 353 req, err := s.client.NewRequest("PUT", url, repoIDs{SelectedIDs: ids}) 354 if err != nil { 355 return nil, err 356 } 357 358 return s.client.Do(ctx, req, nil) 359 } 360 361 // SetSelectedReposForOrgSecret sets the repositories that have access to a secret. 362 // 363 // GitHub API docs: https://docs.github.com/rest/actions/secrets#set-selected-repositories-for-an-organization-secret 364 // 365 //meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories 366 func (s *ActionsService) SetSelectedReposForOrgSecret(ctx context.Context, org, name string, ids SelectedRepoIDs) (*Response, error) { 367 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories", org, name) 368 return s.setSelectedReposForSecret(ctx, url, ids) 369 } 370 371 func (s *ActionsService) addSelectedRepoToSecret(ctx context.Context, url string) (*Response, error) { 372 req, err := s.client.NewRequest("PUT", url, nil) 373 if err != nil { 374 return nil, err 375 } 376 377 return s.client.Do(ctx, req, nil) 378 } 379 380 // AddSelectedRepoToOrgSecret adds a repository to an organization secret. 381 // 382 // GitHub API docs: https://docs.github.com/rest/actions/secrets#add-selected-repository-to-an-organization-secret 383 // 384 //meta:operation PUT /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} 385 func (s *ActionsService) AddSelectedRepoToOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { 386 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) 387 return s.addSelectedRepoToSecret(ctx, url) 388 } 389 390 func (s *ActionsService) removeSelectedRepoFromSecret(ctx context.Context, url string) (*Response, error) { 391 req, err := s.client.NewRequest("DELETE", url, nil) 392 if err != nil { 393 return nil, err 394 } 395 396 return s.client.Do(ctx, req, nil) 397 } 398 399 // RemoveSelectedRepoFromOrgSecret removes a repository from an organization secret. 400 // 401 // GitHub API docs: https://docs.github.com/rest/actions/secrets#remove-selected-repository-from-an-organization-secret 402 // 403 //meta:operation DELETE /orgs/{org}/actions/secrets/{secret_name}/repositories/{repository_id} 404 func (s *ActionsService) RemoveSelectedRepoFromOrgSecret(ctx context.Context, org, name string, repo *Repository) (*Response, error) { 405 url := fmt.Sprintf("orgs/%v/actions/secrets/%v/repositories/%v", org, name, *repo.ID) 406 return s.removeSelectedRepoFromSecret(ctx, url) 407 }