mirror of
https://github.com/ivuorinen/gh-action-readme.git
synced 2026-02-05 23:45:38 +00:00
feat: add interactive wizard, contextual errors, and code improvements
- Add interactive configuration wizard with auto-detection and multi-format export - Implement contextual error system with 14 error codes and actionable suggestions - Add centralized progress indicators with consistent theming - Fix all cyclomatic complexity issues (8 functions refactored) - Eliminate code duplication with centralized utilities and error handling - Add comprehensive test coverage for all new components - Update TODO.md with completed tasks and accurate completion dates
This commit is contained in:
111
internal/errorhandler.go
Normal file
111
internal/errorhandler.go
Normal file
@@ -0,0 +1,111 @@
|
||||
// Package internal provides centralized error handling utilities.
|
||||
package internal
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ivuorinen/gh-action-readme/internal/errors"
|
||||
)
|
||||
|
||||
// ErrorHandler provides centralized error handling and exit management.
|
||||
type ErrorHandler struct {
|
||||
output *ColoredOutput
|
||||
}
|
||||
|
||||
// NewErrorHandler creates a new error handler.
|
||||
func NewErrorHandler(output *ColoredOutput) *ErrorHandler {
|
||||
return &ErrorHandler{
|
||||
output: output,
|
||||
}
|
||||
}
|
||||
|
||||
// HandleError handles contextual errors and exits with appropriate code.
|
||||
func (eh *ErrorHandler) HandleError(err *errors.ContextualError) {
|
||||
eh.output.ErrorWithSuggestions(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// HandleFatalError handles fatal errors with contextual information.
|
||||
func (eh *ErrorHandler) HandleFatalError(code errors.ErrorCode, message string, context map[string]string) {
|
||||
suggestions := errors.GetSuggestions(code, context)
|
||||
helpURL := errors.GetHelpURL(code)
|
||||
|
||||
contextualErr := errors.New(code, message).
|
||||
WithSuggestions(suggestions...).
|
||||
WithHelpURL(helpURL)
|
||||
|
||||
if len(context) > 0 {
|
||||
contextualErr = contextualErr.WithDetails(context)
|
||||
}
|
||||
|
||||
eh.HandleError(contextualErr)
|
||||
}
|
||||
|
||||
// HandleSimpleError handles simple errors with automatic context detection.
|
||||
func (eh *ErrorHandler) HandleSimpleError(message string, err error) {
|
||||
code := errors.ErrCodeUnknown
|
||||
context := make(map[string]string)
|
||||
|
||||
// Try to determine appropriate error code based on error content
|
||||
if err != nil {
|
||||
context["error"] = err.Error()
|
||||
code = eh.determineErrorCode(err)
|
||||
}
|
||||
|
||||
eh.HandleFatalError(code, message, context)
|
||||
}
|
||||
|
||||
// determineErrorCode attempts to determine appropriate error code from error content.
|
||||
func (eh *ErrorHandler) determineErrorCode(err error) errors.ErrorCode {
|
||||
errStr := err.Error()
|
||||
|
||||
switch {
|
||||
case contains(errStr, "no such file or directory"):
|
||||
return errors.ErrCodeFileNotFound
|
||||
case contains(errStr, "permission denied"):
|
||||
return errors.ErrCodePermission
|
||||
case contains(errStr, "yaml"):
|
||||
return errors.ErrCodeInvalidYAML
|
||||
case contains(errStr, "github"):
|
||||
return errors.ErrCodeGitHubAPI
|
||||
case contains(errStr, "config"):
|
||||
return errors.ErrCodeConfiguration
|
||||
default:
|
||||
return errors.ErrCodeUnknown
|
||||
}
|
||||
}
|
||||
|
||||
// contains checks if a string contains a substring (case-insensitive).
|
||||
func contains(s, substr string) bool {
|
||||
// Simple implementation - could use strings.Contains with strings.ToLower
|
||||
// but avoiding extra imports for now
|
||||
sLen := len(s)
|
||||
substrLen := len(substr)
|
||||
|
||||
if substrLen > sLen {
|
||||
return false
|
||||
}
|
||||
|
||||
for i := 0; i <= sLen-substrLen; i++ {
|
||||
match := true
|
||||
for j := 0; j < substrLen; j++ {
|
||||
if toLower(s[i+j]) != toLower(substr[j]) {
|
||||
match = false
|
||||
break
|
||||
}
|
||||
}
|
||||
if match {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// toLower converts a byte to lowercase.
|
||||
func toLower(b byte) byte {
|
||||
if b >= 'A' && b <= 'Z' {
|
||||
return b + ('a' - 'A')
|
||||
}
|
||||
return b
|
||||
}
|
||||
Reference in New Issue
Block a user