Compare commits

..

1 Commits

Author SHA1 Message Date
30d3dbc796
feat: improved deploy progress reporting
All checks were successful
continuous-integration/drone/push Build is passing
See #478
2025-03-23 10:04:06 +01:00
3 changed files with 56 additions and 50 deletions

View File

@ -115,14 +115,16 @@ Pass "--all-services/-a" to restart all services.`,
log.Fatal(err) log.Fatal(err)
} }
if err := stack.WaitOnServices( waitOpts := stack.WaitOpts{
cmd.Context(), Services: []ui.ServiceMeta{{Name: stackServiceName, ID: service.ID}},
cl, AppName: app.Name,
[]ui.ServiceMeta{{Name: stackServiceName, ID: service.ID}}, ServerName: app.Server,
app.Name, Filters: f,
app.Server, NoLog: true,
f, Quiet: true,
); err != nil { }
if err := stack.WaitOnServices(cmd.Context(), cl, waitOpts); err != nil {
log.Fatal(err) log.Fatal(err)
} }
@ -133,14 +135,7 @@ Pass "--all-services/-a" to restart all services.`,
log.Fatal(err) log.Fatal(err)
} }
if err := stack.WaitOnServices( if err := stack.WaitOnServices(cmd.Context(), cl, waitOpts); err != nil {
cmd.Context(),
cl,
[]ui.ServiceMeta{{Name: stackServiceName, ID: service.ID}},
app.Name,
app.Server,
f,
); err != nil {
log.Fatal(err) log.Fatal(err)
} }

View File

@ -73,7 +73,7 @@ type stream struct {
reader *io.PipeReader reader *io.PipeReader
writer *io.PipeWriter writer *io.PipeWriter
status string status string
attempts int retries int
health string health string
rollback bool rollback bool
} }
@ -158,13 +158,13 @@ func DeployInitialModel(
r, w := io.Pipe() r, w := io.Pipe()
d := json.NewDecoder(r) d := json.NewDecoder(r)
streams = append(streams, stream{ streams = append(streams, stream{
Name: service.Name, Name: service.Name,
id: service.ID, id: service.ID,
reader: r, reader: r,
writer: w, writer: w,
decoder: d, decoder: d,
attempts: 0, retries: -1, // NOTE(d1): skip first attempt
health: "?", health: "?",
}) })
} }
@ -295,7 +295,7 @@ func (m Model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
if !strings.Contains(currentStatus, "starting") && if !strings.Contains(currentStatus, "starting") &&
strings.Contains(newStatus, "starting") { strings.Contains(newStatus, "starting") {
(*m.Streams)[idx].attempts += 1 (*m.Streams)[idx].retries += 1
} }
if (*m.Streams)[idx].rollback { if (*m.Streams)[idx].rollback {
@ -338,10 +338,15 @@ func (m Model) View() string {
status = "rolled back" status = "rolled back"
} }
output := fmt.Sprintf("%s: %s (attempts: %v, healthcheck: %s)", retries := 0
if stream.retries > 0 {
retries = stream.retries
}
output := fmt.Sprintf("%s: %s (retries: %v, healthcheck: %s)",
formatter.BoldStyle.Render(short), formatter.BoldStyle.Render(short),
status, status,
stream.attempts, retries,
stream.health, stream.health,
) )

View File

@ -300,14 +300,14 @@ func deployCompose(
return nil return nil
} }
if err := WaitOnServices( waitOpts := WaitOpts{
ctx, Services: serviceIDs,
cl, AppName: appName,
serviceIDs, ServerName: serverName,
appName, Filters: filters,
serverName, }
filters,
); err != nil { if err := WaitOnServices(ctx, cl, waitOpts); err != nil {
return err return err
} }
@ -535,19 +535,23 @@ func timestamp() string {
return strings.Replace(ts, ":", "", -1) // get rid of offensive colons return strings.Replace(ts, ":", "", -1) // get rid of offensive colons
} }
func WaitOnServices( type WaitOpts struct {
ctx context.Context, AppName string
cl *dockerClient.Client, Filters filters.Args
services []ui.ServiceMeta, NoLog bool
appName string, Quiet bool
serverName string, ServerName string
filters filters.Args, Services []ui.ServiceMeta
) error { }
func WaitOnServices(ctx context.Context, cl *dockerClient.Client, opts WaitOpts) error {
timeout := time.Duration(WaitTimeout) * time.Second timeout := time.Duration(WaitTimeout) * time.Second
model := ui.DeployInitialModel(ctx, cl, services, appName, timeout, filters) model := ui.DeployInitialModel(ctx, cl, opts.Services, opts.AppName, timeout, opts.Filters)
tui := tea.NewProgram(model) tui := tea.NewProgram(model)
log.Info("polling deployment status") if !opts.Quiet {
log.Info("polling deployment status")
}
m, err := log.Without( m, err := log.Without(
func() (tea.Model, error) { func() (tea.Model, error) {
@ -576,14 +580,14 @@ func WaitOnServices(
} }
} }
if len(*deployModel.Logs) > 0 { if len(*deployModel.Logs) > 0 && !opts.NoLog {
logsPath := filepath.Join( logsPath := filepath.Join(
config.LOGS_DIR, config.LOGS_DIR,
serverName, opts.ServerName,
fmt.Sprintf("%s_%s", appName, timestamp()), fmt.Sprintf("%s_%s", opts.AppName, timestamp()),
) )
if err := os.MkdirAll(filepath.Join(config.LOGS_DIR, serverName), 0764); err != nil { if err := os.MkdirAll(filepath.Join(config.LOGS_DIR, opts.ServerName), 0764); err != nil {
return fmt.Errorf("waitOnServices: error creating log dir: %s", err) return fmt.Errorf("waitOnServices: error creating log dir: %s", err)
} }
@ -604,7 +608,9 @@ func WaitOnServices(
return stdlibErr.Join(errs...) return stdlibErr.Join(errs...)
} }
log.Info("deploy succeeded 🟢") if !opts.Quiet {
log.Info("deploy succeeded 🟢")
}
return nil return nil
} }