Files
deploy-felhom-compose/TASK.md
T

5.4 KiB

TASK.md — Debug: App Info Page — YAML Parsing Failure

Read CLAUDE.md first for project context, workspace layout, and build instructions.

Problem

The /apps/romm info page shows NO app info content (no tagline, no use cases, no optional config form). More importantly, even basic metadata is missing:

  • ~ RAM badge shows no value (should be "300M")
  • Category badge is empty (should be "media")
  • Tagline <p> is empty

These fields have been in .felhom.yml since BEFORE the app_info section was added. If they're empty, it means LoadMetadata() is silently failing and returning defaults.

Root cause analysis

LoadMetadata() in internal/stacks/metadata.go swallows YAML parse errors:

if err := yaml.Unmarshal(data, &meta); err != nil {
    // Parse error — still return defaults  <-- NO LOG OUTPUT!
    dirName := filepath.Base(stackDir)
    meta.DisplayName = toTitleCase(strings.ReplaceAll(dirName, "-", " "))
    meta.Slug = dirName
    return meta
}

The YAML parse is failing for some reason, and the error is silently ignored.

Step 1: Diagnose — check what the controller has in memory

Run this from your workstation to see the raw API data for romm:

# Get a session first, then check the stack data
ssh kisfenyo@192.168.0.162 "curl -s http://localhost:8080/api/stacks" 2>/dev/null | head -200

Wait — API needs auth. Easier approach: add a temporary debug log.

Step 2: Add error logging to LoadMetadata

In controller/internal/stacks/metadata.go, the LoadMetadata function currently swallows parse errors silently. Add logging so we can see what's failing:

func LoadMetadata(stackDir string) Metadata {
    meta := Metadata{}

    path := filepath.Join(stackDir, ".felhom.yml")
    data, err := os.ReadFile(path)
    if err != nil {
        dirName := filepath.Base(stackDir)
        meta.DisplayName = toTitleCase(strings.ReplaceAll(dirName, "-", " "))
        meta.Slug = dirName
        meta.Category = "tools"
        return meta
    }

    if err := yaml.Unmarshal(data, &meta); err != nil {
        // ADD THIS LOG LINE — this is critical for debugging
        fmt.Fprintf(os.Stderr, "[ERROR] Failed to parse .felhom.yml in %s: %v\n", stackDir, err)
        dirName := filepath.Base(stackDir)
        meta.DisplayName = toTitleCase(strings.ReplaceAll(dirName, "-", " "))
        meta.Slug = dirName
        return meta
    }

    // ADD THIS DEBUG LINE — confirms successful parse
    fmt.Fprintf(os.Stderr, "[DEBUG] Loaded metadata for %s: tagline=%q, useCases=%d, optConfig=%d\n",
        filepath.Base(stackDir), meta.AppInfo.Tagline, len(meta.AppInfo.UseCases), len(meta.OptionalConfig))

    // ... rest of function unchanged ...

You'll need to add "fmt" to the imports if not already there.

Step 3: Build, deploy, check logs

Follow the CLAUDE.md build workflow. After deploying, immediately check logs:

ssh kisfenyo@192.168.0.162 "docker logs felhom-controller 2>&1 | grep -E 'ERROR.*felhom.yml|DEBUG.*Loaded metadata'"

This will show either:

  • [ERROR] Failed to parse .felhom.yml in /opt/docker/stacks/romm: <SPECIFIC ERROR> — tells us exactly what's wrong
  • [DEBUG] Loaded metadata for romm: tagline="Retró...", useCases=5, optConfig=1 — parsing works, problem is elsewhere

Step 4: Fix based on diagnosis

If YAML parse error:

The error message will tell us exactly what's wrong. Common causes:

  • Special Unicode characters in quoted strings (Hungarian quotes „", em-dash )
  • Encoding issue (BOM character at start of file)
  • Indentation mismatch

Fix the .felhom.yml content accordingly in the app-catalog repo, commit + push, trigger sync.

If parsing succeeds but data still missing:

The problem is in how ScanStacks() stores/retrieves metadata. Check:

  • Does GetStacks() return the full Meta field?
  • Is there any code that creates a new Metadata{} after LoadMetadata()?

Step 5: After fixing, clean up debug logging

Once the issue is resolved:

  1. Keep the [ERROR] log line (it should have been there from the start — silent failures are bad)
  2. Remove or gate the [DEBUG] line behind isDebug() check (or just remove it)
  3. Build + deploy the final version

Build workflow fix for CLAUDE.md

Also update the deploy command in CLAUDE.md. The sed approach for updating the image tag is fragile — it matched the service name line too and broke the YAML last time.

Replace Step 3 in CLAUDE.md with this safer approach:

# Deploy on demo node — use targeted sed that only matches the 'image:' line
ssh kisfenyo@192.168.0.162 "cd /opt/docker/felhom-controller && sudo docker pull gitea.dooplex.hu/admin/felhom-controller:<NEW_VERSION> && sudo sed -i 's|image: gitea.dooplex.hu/admin/felhom-controller:.*|image: gitea.dooplex.hu/admin/felhom-controller:<NEW_VERSION>|' docker-compose.yml && sudo docker compose up -d"

Key differences from previous command:

  • sudo for both sed and docker compose (the directory is root-owned)
  • sed pattern matches image: gitea.dooplex.hu/admin/felhom-controller:.* — only the image line, not the service name
  • Single SSH command to avoid partial failures

Update the CLAUDE.md file with this corrected deploy command.

Summary

The core issue is that LoadMetadata() silently swallows YAML parse errors. Even if the fix turns out to be a simple YAML syntax issue, the error logging should be added permanently — silent failures make debugging impossible.