Skip to content

Commit

Permalink
✨ finally exiting with status 1 and erroring
Browse files Browse the repository at this point in the history
  • Loading branch information
acidjazz committed May 20, 2024
1 parent 6e5736d commit d6a8858
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 33 deletions.
1 change: 1 addition & 0 deletions examples/error/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ func main() {
},
},
}, taskin.Defaults)
// }, taskin.Config{Options: taskin.ConfigOptions{ExitOnFailure: false}})
err := tasks.Run()

if err != nil {
Expand Down
10 changes: 10 additions & 0 deletions models.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ import (
"github.com/charmbracelet/bubbles/spinner"
)

type TerminateWithError struct {
Error error
}

type TaskState int

const (
Expand Down Expand Up @@ -39,3 +43,9 @@ type Runner struct {
}

type Runners []Runner

type Model struct {
Runners Runners
Shutdown bool
ShutdownError error
}
70 changes: 42 additions & 28 deletions mvc.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,70 +6,83 @@ import (
"github.com/charmbracelet/lipgloss"
)

func (r *Runners) Init() tea.Cmd {
func (m *Model) Init() tea.Cmd {
var cmds []tea.Cmd
for i := range *r {
if (*r)[i].Spinner != nil {
cmds = append(cmds, (*r)[i].Spinner.Tick)
for i := range m.Runners {
if (m.Runners)[i].Spinner != nil {
cmds = append(cmds, (m.Runners)[i].Spinner.Tick)
}
for j := range (*r)[i].Children {
if (*r)[i].Children[j].Spinner != nil {
cmds = append(cmds, (*r)[i].Children[j].Spinner.Tick)
for j := range (m.Runners)[i].Children {
if (m.Runners)[i].Children[j].Spinner != nil {
cmds = append(cmds, (m.Runners)[i].Children[j].Spinner.Tick)
}
}
}
return tea.Batch(cmds...)
}

func (r *Runners) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
func (m *Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd

if m.Shutdown && m.ShutdownError != nil {
return m, tea.Quit
}

switch msg := msg.(type) {

case TerminateWithError:
m.SetShutdown(msg.Error)
return m, tea.Quit

case spinner.TickMsg:
allDone := true
for i := range *r {
for i := range m.Runners {

if (*r)[i].State == Running || (*r)[i].State == NotStarted {
if (m.Runners)[i].State == Running || (m.Runners)[i].State == NotStarted {
if !IsCI() {
newSpinner, cmd := (*r)[i].Spinner.Update(msg)
(*r)[i].Spinner = &newSpinner
newSpinner, cmd := (m.Runners)[i].Spinner.Update(msg)
(m.Runners)[i].Spinner = &newSpinner
cmds = append(cmds, cmd)
}
}

for j := range (*r)[i].Children {
if (*r)[i].Children[j].State == Running || (*r)[i].Children[j].State == NotStarted {
for j := range (m.Runners)[i].Children {
if (m.Runners)[i].Children[j].State == Running || (m.Runners)[i].Children[j].State == NotStarted {
if !IsCI() {
newSpinner, cmd := (*r)[i].Children[j].Spinner.Update(msg)
(*r)[i].Children[j].Spinner = &newSpinner
newSpinner, cmd := (m.Runners)[i].Children[j].Spinner.Update(msg)
(m.Runners)[i].Children[j].Spinner = &newSpinner
cmds = append(cmds, cmd)
}
}
}

if (*r)[i].State == Failed {
return r, tea.Quit
if (m.Runners)[i].State == Failed {
return m, tea.Quit
}

if (*r)[i].State != Completed && (*r)[i].State != Failed {
if (m.Runners)[i].State != Completed && (m.Runners)[i].State != Failed {
allDone = false
}
}

if allDone {
return r, tea.Quit
return m, tea.Quit
}

return r, tea.Batch(cmds...)
return m, tea.Batch(cmds...)
}

return r, nil
return m, nil
}

func (r *Runners) checkTasksState() (allDone, anyFailed bool) {
func (m *Model) SetShutdown(err error) {
m.Shutdown = true
m.ShutdownError = err
}

func (m *Model) checkTasksState() (allDone, anyFailed bool) {
allDone = true
for _, runner := range *r {
for _, runner := range m.Runners {
if runner.State != Completed && runner.State != Failed {
allDone = false
}
Expand All @@ -80,17 +93,18 @@ func (r *Runners) checkTasksState() (allDone, anyFailed bool) {
return
}

func (r *Runners) View() string {
func (m *Model) View() string {
var view string

// check if CI is set, if it is then don't return the view until all tasks are completed or one has failed
if IsCI() {
allDone, _ := r.checkTasksState()
if !allDone {
allDone, anyFailed := m.checkTasksState()
if !allDone && !anyFailed {
return ""
}
}
for _, runner := range *r {

for _, runner := range m.Runners {
status := ""
switch runner.State {
case NotStarted:
Expand Down
19 changes: 14 additions & 5 deletions taskin.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,21 @@ func (task *Task) Progress(current, total int) {
}

func (r *Runners) Run() error {
program = tea.NewProgram(r, tea.WithInput(nil))
m := &Model{Runners: *r, Shutdown: false, ShutdownError: nil}
program = tea.NewProgram(m, tea.WithInput(nil))
_, err := program.Run()
if err != nil {
program.Send(TerminateWithError{Error: err})
os.Exit(1)
}
if m.Shutdown && m.ShutdownError != nil {
os.Exit(1)
}
return err
}

func New(tasks Tasks, cfg Config) Runners {

_ = mergo.Merge(&cfg, Defaults)
var runners Runners
for _, task := range tasks {
Expand All @@ -67,18 +76,18 @@ func New(tasks Tasks, cfg Config) Runners {
for i := range runners {

for _, runner := range runners[:i] {
if runner.State == Failed {
if runner.State == Failed && runner.Config.Options.ExitOnFailure {
return
}
}

runners[i].State = Running
err := runners[i].Task.Task(&runners[i].Task)
if err != nil {
runners[i].Task.Title = fmt.Sprintf("%s - Error: %s", runners[i].Task.Title, err.Error())
runners[i].Task.Title = fmt.Sprintf("%s - %s", runners[i].Task.Title, err.Error())
runners[i].State = Failed
if program != nil {
program.Send(spinner.TickMsg{})
program.Send(TerminateWithError{Error: err})
}
continue
}
Expand All @@ -92,7 +101,7 @@ func New(tasks Tasks, cfg Config) Runners {
runners[i].Children[j].State = Failed
runners[i].State = Failed // Mark parent task as Failed
if program != nil {
program.Send(spinner.TickMsg{})
program.Send(TerminateWithError{Error: err})
}
break
}
Expand Down

0 comments on commit d6a8858

Please sign in to comment.