Skip to content

Commit

Permalink
feat: improves error messages and handling
Browse files Browse the repository at this point in the history
- error handling and displaying is now a breeze
  • Loading branch information
nxtcoder17 committed Oct 6, 2024
1 parent 06abe13 commit aa0f863
Show file tree
Hide file tree
Showing 11 changed files with 291 additions and 251 deletions.
25 changes: 13 additions & 12 deletions cmd/run/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,23 +9,21 @@ import (
"strings"
"syscall"

"github.com/nxtcoder17/fwatcher/pkg/logging"
"github.com/nxtcoder17/runfile/pkg/logging"
"github.com/nxtcoder17/runfile/pkg/runfile"
"github.com/nxtcoder17/runfile/pkg/runfile/errors"
"github.com/urfave/cli/v3"
)

var (
Version string = "0.0.1"
runfileNames []string = []string{
"Runfile",
"Runfile.yml",
"Runfile.yaml",
}
)
var Version string = "nightly"

func main() {
logger := logging.NewSlogLogger(logging.SlogOptions{})
var runfileNames []string = []string{
"Runfile",
"Runfile.yml",
"Runfile.yaml",
}

func main() {
cmd := cli.Command{
Name: "run",
Version: Version,
Expand Down Expand Up @@ -166,7 +164,10 @@ func main() {
}()

if err := cmd.Run(ctx, os.Args); err != nil {
logger.Error(err.Error())
errm, ok := err.(errors.Message)
if ok {
errm.Log()
}
os.Exit(1)
}
}
Expand Down
81 changes: 81 additions & 0 deletions pkg/logging/logger.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package logging

import (
"io"
"log/slog"
"os"

"github.com/charmbracelet/lipgloss"
"github.com/charmbracelet/log"
)

type SlogOptions struct {
Writer io.Writer
Prefix string

ShowTimestamp bool
ShowCaller bool
ShowDebugLogs bool

SetAsDefaultLogger bool
}

func NewSlogLogger(opts SlogOptions) *slog.Logger {
// INFO: force colored output, otherwise honor the env-var `CLICOLOR_FORCE`
if _, ok := os.LookupEnv("CLICOLOR_FORCE"); !ok {
os.Setenv("CLICOLOR_FORCE", "1")
}

if opts.Writer == nil {
opts.Writer = os.Stderr
}

level := log.InfoLevel
if opts.ShowDebugLogs {
level = log.DebugLevel
}

logger := log.NewWithOptions(opts.Writer, log.Options{
ReportCaller: opts.ShowCaller,
ReportTimestamp: opts.ShowTimestamp,
Prefix: opts.Prefix,
Level: level,
})

styles := log.DefaultStyles()
// styles.Caller = lipgloss.NewStyle().Foreground(lipgloss.AdaptiveColor{Dark: "#5b717f", Light: "#36cbfa"}).Faint(true)
styles.Caller = lipgloss.NewStyle().Foreground(lipgloss.Color("#878a8a"))

styles.Levels[log.ErrorLevel] = lipgloss.NewStyle().
SetString("ERROR").
Padding(0, 1, 0, 1).
// Background(lipgloss.Color("204")).
Foreground(lipgloss.Color("202"))

styles.Levels[log.DebugLevel] = styles.Levels[log.DebugLevel].Foreground(lipgloss.Color("#5b717f"))

styles.Levels[log.InfoLevel] = styles.Levels[log.InfoLevel].Foreground(lipgloss.Color("#36cbfa"))

// BUG: due to a bug in termenv, adaptive colors don't work within tmux
// it always selects the dark variant

// styles.Levels[log.InfoLevel] = styles.Levels[log.InfoLevel].Foreground(lipgloss.AdaptiveColor{
// Light: string(lipgloss.Color("#36cbfa")),
// Dark: string(lipgloss.Color("#608798")),
// })

styles.Key = lipgloss.NewStyle().Foreground(lipgloss.Color("#36cbfa")).Bold(true)

logger.SetStyles(styles)

// output := termenv.NewOutput(os.Stdout, termenv.WithProfile(termenv.TrueColor))
// logger.Info("theme", "fg", output.ForegroundColor(), "bg", output.BackgroundColor(), "has-dark", output.HasDarkBackground())

l := slog.New(logger)

if opts.SetAsDefaultLogger {
slog.SetDefault(l)
}

return l
}
29 changes: 17 additions & 12 deletions pkg/runfile/types.go → pkg/runfile/context.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,15 @@ import (

sprig "github.com/go-task/slim-sprig/v3"
fn "github.com/nxtcoder17/runfile/pkg/functions"
"github.com/nxtcoder17/runfile/pkg/runfile/errors"
)

type Context struct {
context.Context
*slog.Logger

RunfilePath string
Taskname string
}

func NewContext(ctx context.Context, logger *slog.Logger) Context {
Expand Down Expand Up @@ -49,7 +53,7 @@ type EnvKV struct {
GoTmpl *string `json:"gotmpl"`
}

func (ejv EnvKV) Parse(ctx Context, args EvaluationArgs) (*string, error) {
func (ejv EnvKV) Parse(ctx Context, args EvaluationArgs) (*string, errors.Message) {
switch {
case ejv.Value != nil:
{
Expand All @@ -66,7 +70,7 @@ func (ejv EnvKV) Parse(ctx Context, args EvaluationArgs) (*string, error) {
stdout: value,
})
if err := cmd.Run(); err != nil {
return nil, err
return nil, errors.TaskEnvCommandFailed.WithErr(err)
}

return fn.New(strings.TrimSpace(value.String())), nil
Expand All @@ -76,33 +80,34 @@ func (ejv EnvKV) Parse(ctx Context, args EvaluationArgs) (*string, error) {
t := template.New(ejv.Key).Funcs(sprig.FuncMap())
t, err := t.Parse(fmt.Sprintf(`{{ %s }}`, *ejv.GoTmpl))
if err != nil {
return nil, err
return nil, errors.TaskEnvGoTmplFailed.WithErr(err)
}

value := new(bytes.Buffer)
if err := t.ExecuteTemplate(value, ejv.Key, map[string]string{}); err != nil {
return nil, err
return nil, errors.TaskEnvGoTmplFailed.WithErr(err)
}

return fn.New(strings.TrimSpace(value.String())), nil
}
default:
{
return nil, fmt.Errorf("failed to parse, unknown format, one of [value, sh, gotmpl] must be set")
return nil, errors.TaskEnvInvalid.WithErr(fmt.Errorf("failed to parse, unknown format, one of [value, sh, gotmpl] must be set"))
}
}
}

func parseEnvVars(ctx Context, ev EnvVar, args EvaluationArgs) (map[string]string, error) {
func parseEnvVars(ctx Context, ev EnvVar, args EvaluationArgs) (map[string]string, errors.Message) {
env := make(map[string]string, len(ev))
for k, v := range ev {
attr := []any{slog.Group("env", "key", k, "value", v)}
switch v := v.(type) {
case string:
env[k] = v
case map[string]any:
b, err := json.Marshal(v)
if err != nil {
return nil, err
return nil, errors.TaskEnvInvalid.WithErr(err).WithMetadata(attr)
}

var envAsJson struct {
Expand All @@ -112,7 +117,7 @@ func parseEnvVars(ctx Context, ev EnvVar, args EvaluationArgs) (map[string]strin
}

if err := json.Unmarshal(b, &envAsJson); err != nil {
return nil, err
return nil, errors.TaskEnvInvalid.WithErr(err).WithMetadata(attr)
}

switch {
Expand All @@ -130,7 +135,7 @@ func parseEnvVars(ctx Context, ev EnvVar, args EvaluationArgs) (map[string]strin
}

if !isDefined {
return nil, fmt.Errorf("env: %q, not defined", k)
return nil, errors.TaskEnvInvalid.WithErr(fmt.Errorf("env required, but not provided")).WithMetadata(attr)
}
}

Expand All @@ -139,7 +144,7 @@ func parseEnvVars(ctx Context, ev EnvVar, args EvaluationArgs) (map[string]strin
envAsJson.Key = k
s, err := envAsJson.EnvKV.Parse(ctx, args)
if err != nil {
return nil, err
return nil, err.WithMetadata(attr)
}
env[k] = *s
}
Expand All @@ -149,13 +154,13 @@ func parseEnvVars(ctx Context, ev EnvVar, args EvaluationArgs) (map[string]strin
envAsJson.Default.Key = k
s, err := envAsJson.Default.Parse(ctx, args)
if err != nil {
return nil, err
return nil, err.WithMetadata(attr)
}
env[k] = *s
}
default:
{
return nil, fmt.Errorf("either required, value, sh, gotmpl or default, must be defined")
return nil, errors.TaskEnvInvalid.WithErr(fmt.Errorf("either required, value, sh, gotmpl or default, must be defined")).WithMetadata(attr)
}
}

Expand Down
135 changes: 0 additions & 135 deletions pkg/runfile/errors/errors.go

This file was deleted.

Loading

0 comments on commit aa0f863

Please sign in to comment.