name: Validate observability stack

# The observability DOMAIN deploys by hand (`docker compose up -d` on beta +
# the Alloy agent on each node) with no build step, so nothing caught a
# malformed compose file, a broken dashboard JSON, or an unparseable config
# until it failed live on the host. This is that missing guard: it parses
# every YAML/JSON artifact that ships to a node. It does NOT deploy, and
# deliberately needs no docker CLI (the node:20-bookworm job image doesn't
# ship one) -- a YAML parse catches the real breakage without it.
#
# Monorepo port: paths are prefixed observability/, the push trigger is
# path-filtered to the domain, and workflow_call lets pr-build.yml reuse this
# as the domain's PR check under its single `gate` required status.
#
# Not validated here: the Alloy config (observability/alloy/config.alloy, an
# HCL-like format, needs the `alloy` binary) and docker-compose *schema*
# (unknown-key checks, which would need the docker CLI). Add either if the
# churn warrants the extra tooling.

on:
  workflow_call: {}
  push:
    branches: [main, dev]
    paths: ['observability/**']

jobs:
  validate:
    runs-on: docker
    steps:
      - uses: actions/checkout@v4

      - name: Dashboards are valid JSON
        run: |
          set -euo pipefail
          python3 - <<'PY'
          import json, pathlib, sys
          bad = False
          files = sorted(pathlib.Path("observability/grafana/dashboards").glob("*.json"))
          if not files:
              print("no dashboards found"); sys.exit(1)
          for f in files:
              try:
                  json.loads(f.read_text()); print("OK", f)
              except Exception as e:  # noqa: BLE001
                  print("INVALID JSON", f, "-", e); bad = True
          sys.exit(1 if bad else 0)
          PY

      - name: YAML artifacts parse (compose + loki + grafana provisioning)
        run: |
          set -euo pipefail
          apt-get update -qq && apt-get install -y -qq python3-yaml >/dev/null
          python3 - <<'PY'
          import pathlib, sys
          import yaml
          bad = False
          root = pathlib.Path("observability")
          targets = [
              root / "docker-compose.yml",
              root / "alloy/docker-compose.agent.yml",
              root / "loki/config.yml",
              *sorted((root / "grafana/provisioning").rglob("*.yml")),
          ]
          for f in targets:
              if not f.exists():
                  print("MISSING", f); bad = True; continue
              try:
                  yaml.safe_load(f.read_text()); print("OK", f)
              except Exception as e:  # noqa: BLE001
                  print("INVALID YAML", f, "-", e); bad = True
          sys.exit(1 if bad else 0)
          PY
