github.com/ungtb10d/cli/v2@v2.0.0-20221110210412-98537dd9d6a1/pkg/cmd/secret/delete/delete.go (about)

     1  package delete
     2  
     3  import (
     4  	"fmt"
     5  	"net/http"
     6  
     7  	"github.com/MakeNowJust/heredoc"
     8  	"github.com/ungtb10d/cli/v2/api"
     9  	"github.com/ungtb10d/cli/v2/internal/config"
    10  	"github.com/ungtb10d/cli/v2/internal/ghrepo"
    11  	"github.com/ungtb10d/cli/v2/pkg/cmd/secret/shared"
    12  	"github.com/ungtb10d/cli/v2/pkg/cmdutil"
    13  	"github.com/ungtb10d/cli/v2/pkg/iostreams"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  type DeleteOptions struct {
    18  	HttpClient func() (*http.Client, error)
    19  	IO         *iostreams.IOStreams
    20  	Config     func() (config.Config, error)
    21  	BaseRepo   func() (ghrepo.Interface, error)
    22  
    23  	SecretName  string
    24  	OrgName     string
    25  	EnvName     string
    26  	UserSecrets bool
    27  	Application string
    28  }
    29  
    30  func NewCmdDelete(f *cmdutil.Factory, runF func(*DeleteOptions) error) *cobra.Command {
    31  	opts := &DeleteOptions{
    32  		IO:         f.IOStreams,
    33  		Config:     f.Config,
    34  		HttpClient: f.HttpClient,
    35  	}
    36  
    37  	cmd := &cobra.Command{
    38  		Use:   "delete <secret-name>",
    39  		Short: "Delete secrets",
    40  		Long: heredoc.Doc(`
    41  			Delete a secret on one of the following levels:
    42  			- repository (default): available to Actions runs or Dependabot in a repository
    43  			- environment: available to Actions runs for a deployment environment in a repository
    44  			- organization: available to Actions runs, Dependabot, or Codespaces within an organization
    45  			- user: available to Codespaces for your user
    46  		`),
    47  		Args: cobra.ExactArgs(1),
    48  		RunE: func(cmd *cobra.Command, args []string) error {
    49  			// support `-R, --repo` override
    50  			opts.BaseRepo = f.BaseRepo
    51  
    52  			if err := cmdutil.MutuallyExclusive("specify only one of `--org`, `--env`, or `--user`", opts.OrgName != "", opts.EnvName != "", opts.UserSecrets); err != nil {
    53  				return err
    54  			}
    55  
    56  			opts.SecretName = args[0]
    57  
    58  			if runF != nil {
    59  				return runF(opts)
    60  			}
    61  
    62  			return removeRun(opts)
    63  		},
    64  		Aliases: []string{
    65  			"remove",
    66  		},
    67  	}
    68  	cmd.Flags().StringVarP(&opts.OrgName, "org", "o", "", "Delete a secret for an organization")
    69  	cmd.Flags().StringVarP(&opts.EnvName, "env", "e", "", "Delete a secret for an environment")
    70  	cmd.Flags().BoolVarP(&opts.UserSecrets, "user", "u", false, "Delete a secret for your user")
    71  	cmdutil.StringEnumFlag(cmd, &opts.Application, "app", "a", "", []string{shared.Actions, shared.Codespaces, shared.Dependabot}, "Delete a secret for a specific application")
    72  
    73  	return cmd
    74  }
    75  
    76  func removeRun(opts *DeleteOptions) error {
    77  	c, err := opts.HttpClient()
    78  	if err != nil {
    79  		return fmt.Errorf("could not create http client: %w", err)
    80  	}
    81  	client := api.NewClientFromHTTP(c)
    82  
    83  	orgName := opts.OrgName
    84  	envName := opts.EnvName
    85  
    86  	secretEntity, err := shared.GetSecretEntity(orgName, envName, opts.UserSecrets)
    87  	if err != nil {
    88  		return err
    89  	}
    90  
    91  	secretApp, err := shared.GetSecretApp(opts.Application, secretEntity)
    92  	if err != nil {
    93  		return err
    94  	}
    95  
    96  	if !shared.IsSupportedSecretEntity(secretApp, secretEntity) {
    97  		return fmt.Errorf("%s secrets are not supported for %s", secretEntity, secretApp)
    98  	}
    99  
   100  	var baseRepo ghrepo.Interface
   101  	if secretEntity == shared.Repository || secretEntity == shared.Environment {
   102  		baseRepo, err = opts.BaseRepo()
   103  		if err != nil {
   104  			return fmt.Errorf("could not determine base repo: %w", err)
   105  		}
   106  	}
   107  
   108  	var path string
   109  	switch secretEntity {
   110  	case shared.Organization:
   111  		path = fmt.Sprintf("orgs/%s/%s/secrets/%s", orgName, secretApp, opts.SecretName)
   112  	case shared.Environment:
   113  		path = fmt.Sprintf("repos/%s/environments/%s/secrets/%s", ghrepo.FullName(baseRepo), envName, opts.SecretName)
   114  	case shared.User:
   115  		path = fmt.Sprintf("user/codespaces/secrets/%s", opts.SecretName)
   116  	case shared.Repository:
   117  		path = fmt.Sprintf("repos/%s/%s/secrets/%s", ghrepo.FullName(baseRepo), secretApp, opts.SecretName)
   118  	}
   119  
   120  	cfg, err := opts.Config()
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	host, _ := cfg.DefaultHost()
   126  
   127  	err = client.REST(host, "DELETE", path, nil, nil)
   128  	if err != nil {
   129  		return fmt.Errorf("failed to delete secret %s: %w", opts.SecretName, err)
   130  	}
   131  
   132  	if opts.IO.IsStdoutTTY() {
   133  		var target string
   134  		switch secretEntity {
   135  		case shared.Organization:
   136  			target = orgName
   137  		case shared.User:
   138  			target = "your user"
   139  		case shared.Repository, shared.Environment:
   140  			target = ghrepo.FullName(baseRepo)
   141  		}
   142  
   143  		cs := opts.IO.ColorScheme()
   144  		if envName != "" {
   145  			fmt.Fprintf(opts.IO.Out, "%s Deleted secret %s from %s environment on %s\n", cs.SuccessIconWithColor(cs.Red), opts.SecretName, envName, target)
   146  		} else {
   147  			fmt.Fprintf(opts.IO.Out, "%s Deleted %s secret %s from %s\n", cs.SuccessIconWithColor(cs.Red), secretApp.Title(), opts.SecretName, target)
   148  		}
   149  	}
   150  
   151  	return nil
   152  }