controller v0.272.0: the backup page says when a whole-box backup does not fit (R-685); R-671, R-670, R-677
gates / gates (push) Successful in 26s

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0159rPz1ZhFKsS53msqPYxtS
This commit is contained in:
2026-09-25 11:19:27 +02:00
parent 71accca427
commit 44ae4dea70
21 changed files with 376 additions and 10 deletions
+16 -2
View File
@@ -316,7 +316,21 @@ func (m Metadata) CatalogSinceAge(now time.Time) (int, bool) {
// LoadMetadata reads .felhom.yml from a stack directory.
// Returns default metadata if the file doesn't exist.
func LoadMetadata(stackDir string) Metadata {
func LoadMetadata(stackDir string) Metadata { return loadMetadata(stackDir, true) }
// LoadProbeMetadata reads a `.felhom.yml` for its health check and resources ONLY (R-670, v0.272.0): the
// backup and data_paths blocks are dropped instead of validated. For the copies that live without their
// compose file — the undo's `pre-update-meta/` and a step's `steps/<key>.felhom.yml` — the validation could
// only fail ("docker-compose.yml unreadable") and logged a false ERROR on every undo. Nothing read through
// this loader may consult Backup or DataPaths; they are always nil here.
// Pinned by TestR670_ProbeLoaderLogsNoFalseError.
func LoadProbeMetadata(stackDir string) Metadata {
m := loadMetadata(stackDir, false)
m.Backup, m.DataPaths = nil, nil
return m
}
func loadMetadata(stackDir string, validateBackup bool) Metadata {
meta := Metadata{}
path := filepath.Join(stackDir, ".felhom.yml")
@@ -401,7 +415,7 @@ func LoadMetadata(stackDir string) Metadata {
// block exists) the WHOLE block is rejected — meta.Backup = nil, one ERROR — so the app degrades
// to legacy (today's behavior) rather than partially classifying. INERT: nothing consumes
// meta.Backup yet (Task 3/4).
if meta.Backup != nil || len(meta.DataPaths) > 0 {
if validateBackup && (meta.Backup != nil || len(meta.DataPaths) > 0) {
composePath := filepath.Join(stackDir, "docker-compose.yml")
binds := ParseComposeClassifiableBinds(composePath)
_, composeErr := os.Stat(composePath)