feat: v0.3.0d — add PR checks, iostreams, aliases, and broad enhancements

Add PR checks command, iostreams/text packages for colored table output,
top-level run/workflow aliases matching gh CLI structure. Enhance actions,
issues, PRs, releases, repos, labels, milestones, and wiki commands with
improved flags, JSON output, and error handling.
This commit is contained in:
sid 2026-03-23 11:42:44 -06:00
parent 7c0dcc8696
commit 113505de95
29 changed files with 3131 additions and 542 deletions

View file

@ -3,7 +3,8 @@ package cmd
import (
"encoding/json"
"errors"
"os"
"fmt"
"strings"
"forgejo.zerova.net/sid/fgj-sid/internal/api"
)
@ -40,6 +41,45 @@ func NewAPIError(status int, message string) *CLIError {
return &CLIError{Code: ErrAPIError, Message: message, Status: status}
}
// ContextualError wraps common errors with helpful hints.
func ContextualError(err error) error {
if err == nil {
return nil
}
msg := err.Error()
// Check for API errors with status codes
var apiErr *api.APIError
if errors.As(err, &apiErr) {
switch {
case apiErr.StatusCode == 401 || apiErr.StatusCode == 403:
return fmt.Errorf("%w\nHint: Try authenticating with: fgj auth login", err)
case apiErr.StatusCode == 404:
return fmt.Errorf("%w\nHint: Resource not found. Check the repository and number are correct.", err)
}
return err
}
// Check for network/connection errors
switch {
case strings.Contains(msg, "no such host"):
return fmt.Errorf("%w\nHint: Check your internet connection and that the host is correct.", err)
case strings.Contains(msg, "connection refused"):
return fmt.Errorf("%w\nHint: Check your internet connection and that the host is correct.", err)
}
// Check for string-based status code patterns (from wrapped errors)
switch {
case strings.Contains(msg, "401") || strings.Contains(msg, "403"):
if strings.Contains(msg, "authentication") || strings.Contains(msg, "unauthorized") || strings.Contains(msg, "forbidden") {
return fmt.Errorf("%w\nHint: Try authenticating with: fgj auth login", err)
}
}
return err
}
// writeJSONError writes a structured JSON error to stderr.
// It attempts to extract structured info from known error types.
// WriteJSONError writes a structured JSON error to stderr.
@ -70,7 +110,7 @@ func WriteJSONError(err error) {
}
}
enc := json.NewEncoder(os.Stderr)
enc := json.NewEncoder(ios.ErrOut)
enc.SetIndent("", " ")
_ = enc.Encode(cliErr)
}