| 146 | } |
| 147 | |
| 148 | func ReportError(ctx context.Context, err error, drv *ui.Driver, cmd *cobra.Command, args []string) { |
| 149 | cfg := ConfigFromContext(ctx) |
| 150 | |
| 151 | var flags []string |
| 152 | cmd.Flags().Visit(func(flag *pflag.Flag) { |
| 153 | flags = append(flags, flag.Name) |
| 154 | }) |
| 155 | |
| 156 | q := url.Values{} |
| 157 | q.Add("title", fmt.Sprintf("Error: %s", err.Error())) |
| 158 | |
| 159 | var body strings.Builder |
| 160 | |
| 161 | fmt.Fprintf(&body, "**Are there any additional details you would like to share?**\n") |
| 162 | fmt.Fprintf(&body, "\n") |
| 163 | fmt.Fprintf(&body, "---\n") |
| 164 | fmt.Fprintf(&body, "\n") |
| 165 | fmt.Fprintf(&body, "**Command:** `%s`\n", cmd.CommandPath()) |
| 166 | var executable string |
| 167 | if Executable != "" { |
| 168 | executable = Executable |
| 169 | } else { |
| 170 | executable, _ = os.Executable() |
| 171 | } |
| 172 | if executable != "" { |
| 173 | fmt.Fprintf(&body, "**Executable:** `%s`\n", executable) |
| 174 | } |
| 175 | fmt.Fprintf(&body, "**Version:** `%s`\n", VersionString()) |
| 176 | fmt.Fprintf(&body, "**Arguments:** `[%s]`\n", strings.Join(args, ", ")) |
| 177 | fmt.Fprintf(&body, "**Flags:** `[%s]`\n", strings.Join(flags, ", ")) |
| 178 | fmt.Fprintf(&body, "**Timestamp:** `%s`\n", cfg.Timestamp().Format(time.RFC3339Nano)) |
| 179 | |
| 180 | var stackerr stacktrace.Error |
| 181 | if errors.As(err, &stackerr) { |
| 182 | fmt.Fprintf(&body, "**Stack:**\n```\n%s\n```\n", stackerr.Stack) |
| 183 | } |
| 184 | |
| 185 | fmt.Fprintf(&body, "**Stdout:**\n```\n%s\n```\n", strings.TrimRight(drv.ErrorView(), "\n")) |
| 186 | q.Add("body", body.String()) |
| 187 | |
| 188 | reportErrorConfirmCh := make(chan struct{}) |
| 189 | drv.Activate(ctx, &models.ReportError{ |
| 190 | ConfirmCh: reportErrorConfirmCh, |
| 191 | Cmd: cmd, |
| 192 | Args: args, |
| 193 | Msg: err.Error(), |
| 194 | }) |
| 195 | |
| 196 | if !cfg.NonInteractive { |
| 197 | <-reportErrorConfirmCh |
| 198 | } |
| 199 | |
| 200 | newIssueURL := fmt.Sprintf("https://github.com/anchordotdev/cli/issues/new?%s", q.Encode()) |
| 201 | // FIXME: ? remove config val, switch to mocking this to always err in tests |
| 202 | if cfg.Test.Browserless { |
| 203 | drv.Activate(ctx, &models.Browserless{Url: newIssueURL}) |
| 204 | } else { |
| 205 | if err := browser.OpenURL(newIssueURL); err != nil { |