| 56 | } |
| 57 | |
| 58 | func runAdd(opts *AddOptions) error { |
| 59 | httpClient, err := opts.HTTPClient() |
| 60 | if err != nil { |
| 61 | return err |
| 62 | } |
| 63 | |
| 64 | var keyReader io.Reader |
| 65 | if opts.KeyFile == "-" { |
| 66 | keyReader = opts.IO.In |
| 67 | defer opts.IO.In.Close() |
| 68 | } else { |
| 69 | f, err := os.Open(opts.KeyFile) |
| 70 | if err != nil { |
| 71 | return err |
| 72 | } |
| 73 | defer f.Close() |
| 74 | keyReader = f |
| 75 | } |
| 76 | |
| 77 | cfg, err := opts.Config() |
| 78 | if err != nil { |
| 79 | return err |
| 80 | } |
| 81 | |
| 82 | hostname, _ := cfg.Authentication().DefaultHost() |
| 83 | |
| 84 | err = gpgKeyUpload(httpClient, hostname, keyReader, opts.Title) |
| 85 | if err != nil { |
| 86 | cs := opts.IO.ColorScheme() |
| 87 | if errors.Is(err, errScopesMissing) { |
| 88 | fmt.Fprint(opts.IO.ErrOut, "Error: insufficient OAuth scopes to list GPG keys\n") |
| 89 | fmt.Fprintf(opts.IO.ErrOut, "Run the following to grant scopes: %s\n", cs.Bold("gh auth refresh -s write:gpg_key")) |
| 90 | return cmdutil.SilentError |
| 91 | } |
| 92 | if errors.Is(err, errDuplicateKey) { |
| 93 | fmt.Fprintf(opts.IO.ErrOut, "%s Error: the key already exists in your account\n", cs.FailureIcon()) |
| 94 | return cmdutil.SilentError |
| 95 | } |
| 96 | if errors.Is(err, errWrongFormat) { |
| 97 | fmt.Fprint(opts.IO.ErrOut, heredoc.Docf(` |
| 98 | %s Error: the GPG key you are trying to upload might not be in ASCII-armored format. |
| 99 | Find your GPG key ID with: %s |
| 100 | Then add it to your account: %s |
| 101 | `, cs.FailureIcon(), cs.Bold("gpg --list-keys"), cs.Bold("gpg --armor --export <ID> | gh gpg-key add -"))) |
| 102 | return cmdutil.SilentError |
| 103 | } |
| 104 | return err |
| 105 | } |
| 106 | |
| 107 | if opts.IO.IsStdoutTTY() { |
| 108 | cs := opts.IO.ColorScheme() |
| 109 | fmt.Fprintf(opts.IO.Out, "%s GPG key added to your account\n", cs.SuccessIcon()) |
| 110 | } |
| 111 | return nil |
| 112 | } |