v0.24.0 — Pre-testing observability: debug logging, diagnostic dump, startup self-test
- Add [DEBUG] logging across all modules (backup, storage, sync, selfupdate, monitor, notify, report, assets, setup) gated behind logging.level: "debug" - Add /api/debug/dump endpoint returning full controller state JSON (debug only) - Add startup self-test validating 9 subsystems (Docker, dirs, storage, hub, restic repos, metrics DB) with pass/warn/fail summary - New packages: internal/selftest, internal/util - Constructor/signature changes: debug bool params, logger params on RunHealthCheck and BuildReport, smart watchdog probe logging Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -40,6 +40,7 @@ type Updater struct {
|
||||
dataDir string
|
||||
composePath string // e.g., "/opt/docker/felhom-controller/docker-compose.yml"
|
||||
logger *log.Logger
|
||||
debug bool
|
||||
|
||||
mu sync.Mutex
|
||||
latestVersion string
|
||||
@@ -49,7 +50,7 @@ type Updater struct {
|
||||
}
|
||||
|
||||
// NewUpdater creates a new Updater instance.
|
||||
func NewUpdater(cfg *config.SelfUpdateConfig, gitCfg *config.GitConfig, currentVersion, dataDir, composePath string, logger *log.Logger) *Updater {
|
||||
func NewUpdater(cfg *config.SelfUpdateConfig, gitCfg *config.GitConfig, currentVersion, dataDir, composePath string, logger *log.Logger, debug bool) *Updater {
|
||||
return &Updater{
|
||||
cfg: cfg,
|
||||
gitCfg: gitCfg,
|
||||
@@ -57,6 +58,7 @@ func NewUpdater(cfg *config.SelfUpdateConfig, gitCfg *config.GitConfig, currentV
|
||||
dataDir: dataDir,
|
||||
composePath: composePath,
|
||||
logger: logger,
|
||||
debug: debug,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,10 +133,16 @@ func (u *Updater) CheckForUpdate() CheckResult {
|
||||
return result
|
||||
}
|
||||
|
||||
if latestVer.Compare(currentVer) > 0 {
|
||||
cmp := latestVer.Compare(currentVer)
|
||||
if cmp > 0 {
|
||||
result.UpdateAvailable = true
|
||||
}
|
||||
|
||||
if u.debug {
|
||||
u.logger.Printf("[DEBUG] [SELFUPDATE] Version comparison: current=%s, latest=%s, cmp=%d, updateAvailable=%v",
|
||||
u.currentVer, latestStr, cmp, result.UpdateAvailable)
|
||||
}
|
||||
|
||||
u.mu.Lock()
|
||||
u.latestVersion = latestStr
|
||||
u.lastCheck = &result
|
||||
@@ -153,6 +161,10 @@ func (u *Updater) queryRegistry() (string, error) {
|
||||
// Gitea registry V2: GET /v2/<owner>/<repo>/tags/list
|
||||
url := fmt.Sprintf("https://gitea.dooplex.hu/v2/%s/tags/list", registryImagePath(u.cfg.Image))
|
||||
|
||||
if u.debug {
|
||||
u.logger.Printf("[DEBUG] [SELFUPDATE] Registry API URL: %s (user: %s)", url, u.gitCfg.Username)
|
||||
}
|
||||
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("creating request: %w", err)
|
||||
@@ -181,6 +193,10 @@ func (u *Updater) queryRegistry() (string, error) {
|
||||
return "", fmt.Errorf("decoding response: %w", err)
|
||||
}
|
||||
|
||||
if u.debug {
|
||||
u.logger.Printf("[DEBUG] [SELFUPDATE] Registry returned %d tags: %v", len(tagsResp.Tags), tagsResp.Tags)
|
||||
}
|
||||
|
||||
// Find highest semver tag
|
||||
var highest *Version
|
||||
for _, tag := range tagsResp.Tags {
|
||||
@@ -342,6 +358,15 @@ func (u *Updater) updateComposeFile(newImage string) error {
|
||||
|
||||
// Replace image line: "image: gitea.dooplex.hu/admin/felhom-controller:..." → new image
|
||||
re := regexp.MustCompile(`(image:\s*)gitea\.dooplex\.hu/admin/felhom-controller:\S+`)
|
||||
|
||||
if u.debug {
|
||||
// Log old image line for debugging
|
||||
oldMatch := re.Find(data)
|
||||
if oldMatch != nil {
|
||||
u.logger.Printf("[DEBUG] [SELFUPDATE] Compose file edit: %q → %q", string(oldMatch), "image: "+newImage)
|
||||
}
|
||||
}
|
||||
|
||||
newData := re.ReplaceAll(data, []byte("${1}"+newImage))
|
||||
|
||||
if bytes.Equal(data, newData) {
|
||||
|
||||
Reference in New Issue
Block a user