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  }