mirror of
https://github.com/ivuorinen/gh-action-readme.git
synced 2026-01-30 21:42:45 +00:00
- 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
112 lines
2.8 KiB
Go
112 lines
2.8 KiB
Go
// 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
|
|
}
|