v0.12.4 — 15 bug fixes (CRITICAL/HIGH/MEDIUM)
CRITICAL: - C1: SetAppBackupBulk data loss + nil map panic (settings.go) - C2: UpdateStackConfig nil Env map panic (deploy.go) - C3: ValidateDump missing scanner.Err() check (dbdump.go) HIGH: - H1: nextDailyRun DST bug — use time.Date(day+1) not Add(24h) - H2: Cache Europe/Budapest timezone with sync.Once in scheduler - H3: settings.save() leaks .tmp file on WriteFile failure - H4: SetNotificationPrefs nil pointer panic - H5: appDirSize + getDirSizeBytes ignore Sscanf return value - H6: getDirSizeBytes has no timeout — add 30s context - H7: dbdump.go tmpFile not using defer Close - H8: UpdateCrossDriveStatus misleading comment MEDIUM: - M1: Replace custom containsBytes with strings.Contains - M2: scheduler.Every() validates interval > 0 - M3: executeJob panic recovery now sets LastRun - M4: logPostStartStatus copies env slice before goroutine - M5: Cache timezone in web package via getTimezone() sync.Once Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2,6 +2,7 @@ package stacks
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
@@ -278,7 +279,9 @@ func getDirSizeHuman(path string) string {
|
||||
|
||||
// getDirSizeBytes returns the total size in bytes for a directory.
|
||||
func getDirSizeBytes(path string) int64 {
|
||||
cmd := exec.Command("du", "-sb", path)
|
||||
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
|
||||
defer cancel()
|
||||
cmd := exec.CommandContext(ctx, "du", "-sb", path)
|
||||
output, err := cmd.Output()
|
||||
if err != nil {
|
||||
return 0
|
||||
@@ -286,7 +289,9 @@ func getDirSizeBytes(path string) int64 {
|
||||
fields := strings.Fields(string(output))
|
||||
if len(fields) > 0 {
|
||||
var size int64
|
||||
fmt.Sscanf(fields[0], "%d", &size)
|
||||
if n, _ := fmt.Sscanf(fields[0], "%d", &size); n != 1 {
|
||||
return 0
|
||||
}
|
||||
return size
|
||||
}
|
||||
return 0
|
||||
|
||||
@@ -233,6 +233,10 @@ func (m *Manager) UpdateStackConfig(name string, values map[string]string) error
|
||||
return fmt.Errorf("stack %q is not deployed yet", name)
|
||||
}
|
||||
|
||||
if appCfg.Env == nil {
|
||||
appCfg.Env = make(map[string]string)
|
||||
}
|
||||
|
||||
lockedSet := make(map[string]bool)
|
||||
for _, f := range appCfg.LockedFields {
|
||||
lockedSet[f] = true
|
||||
|
||||
@@ -628,10 +628,12 @@ func truncateStr(s string, maxLen int) string {
|
||||
// logPostStartStatus queries container states after a start/deploy operation
|
||||
// and logs them. This runs asynchronously to avoid blocking the HTTP response.
|
||||
func (m *Manager) logPostStartStatus(name, stackDir string, env []string) {
|
||||
envCopy := make([]string, len(env))
|
||||
copy(envCopy, env)
|
||||
go func() {
|
||||
time.Sleep(3 * time.Second)
|
||||
|
||||
output, err := m.composeExecCustomEnv(stackDir, env, "ps", "-a", "--format", "table {{.Name}}\t{{.Image}}\t{{.State}}\t{{.Status}}")
|
||||
output, err := m.composeExecCustomEnv(stackDir, envCopy, "ps", "-a", "--format", "table {{.Name}}\t{{.Image}}\t{{.State}}\t{{.Status}}")
|
||||
if err != nil {
|
||||
m.logger.Printf("[WARN] Post-start status check failed for %s: %v", name, err)
|
||||
return
|
||||
|
||||
Reference in New Issue
Block a user