import os import yaml import requests import subprocess REPOS = { "dev-tools": "https://git.dvirlabs.com/dvirlabs/dev-tools.git", "infra": "https://git.dvirlabs.com/dvirlabs/infra.git" } GITHUB_REPO = "git@github.com:dvirh/lab-monitor.git" BASE_DIR = "./repos" WORKFLOW_FILE = "./repos/lab-monitor/.github/workflows/monitor.yml" def clone_repos(): os.makedirs(BASE_DIR, exist_ok=True) for name, url in REPOS.items(): repo_path = os.path.join(BASE_DIR, name) if os.path.exists(repo_path): subprocess.run(["git", "-C", repo_path, "pull"]) else: subprocess.run(["git", "clone", url, repo_path]) def extract_urls(): urls = [] for repo in REPOS: manifests_path = os.path.join(BASE_DIR, repo, "manifests") if not os.path.isdir(manifests_path): continue for app in os.listdir(manifests_path): path = os.path.join(manifests_path, app, "monitoring.yaml") if not os.path.exists(path): continue with open(path) as f: cfg = yaml.safe_load(f) if not cfg.get("enabled"): continue ext = cfg.get("external_check") if not ext or not ext.get("url"): continue app_name = cfg.get("app", app) for code, sev in ext.get("expected_codes", {}).items(): urls.append({ "url": ext["url"], "name": app_name, "code": code, "message": f"⚠️ {app_name} down ({code})", "severity": sev }) return urls def severity_to_priority(sev): return { "critical": 2, "high": 1, "warning": 0, "info": 0 }.get(sev.lower(), 0) def generate_workflow(urls): os.makedirs(os.path.dirname(WORKFLOW_FILE), exist_ok=True) with open(WORKFLOW_FILE, "w") as f: f.write("""name: Monitor Lab URLs on: schedule: - cron: "*/5 * * * *" workflow_dispatch: jobs: monitor: runs-on: ubuntu-latest steps: - name: Check all URLs run: | check_url() { URL=$1 NAME=$2 CODE=$3 MESSAGE=$4 PRIORITY=$5 STATUS=$(curl -s -o /dev/null -w "%{http_code}" "$URL") TIME=$(date "+%Y-%m-%d %H:%M:%S") if [[ "$STATUS" == "$CODE" ]]; then curl -s \\ --form-string "token=${{ secrets.PUSHOVER_TOKEN }}" \\ --form-string "user=${{ secrets.PUSHOVER_USER }}" \\ --form-string "title=🔴 $NAME Alert" \\ --form-string "message=$MESSAGE at $TIME" \\ --form-string "priority=$PRIORITY" \\ --form-string "retry=60" \\ --form-string "expire=600" \\ https://api.pushover.net/1/messages.json else echo "✅ $NAME is up: $STATUS" fi } """) for item in urls: f.write(f' check_url "{item["url"]}" "{item["name"]}" "{item["code"]}" "{item["message"]}" "{severity_to_priority(item["severity"])}"\n') def push_workflow(): repo_path = os.path.join(BASE_DIR, "lab-monitor") if not os.path.exists(repo_path): subprocess.run(["git", "clone", GITHUB_REPO, repo_path]) subprocess.run(["git", "-C", repo_path, "pull", "origin", "main"]) # Set Git identity subprocess.run(["git", "-C", repo_path, "config", "user.name", "lab-monitor-bot"]) subprocess.run(["git", "-C", repo_path, "config", "user.email", "bot@dvirlabs.com"]) # Add + Commit subprocess.run(["git", "-C", repo_path, "add", ".github/workflows/monitor.yml"]) subprocess.run(["git", "-C", repo_path, "commit", "-m", "update monitor.yml from monitoring.yaml"], check=False) # Push with upstream set to main subprocess.run(["git", "-C", repo_path, "push", "--set-upstream", "origin", "main"]) if __name__ == "__main__": clone_repos() urls = extract_urls() generate_workflow(urls) push_workflow()