Ctrl K
ComunidadGuías…

scripts/stack_insights.py

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
"""
stack_insights.py

Deterministic Docker Hub pull analytics for projectdavid-core.

Uses GitHub Releases API for exact tag publication timestamps — no inference,
no proximity matching. Gap = tag_last_pulled - release published_at.
"""

import json
import re
import subprocess
from datetime import datetime, timezone

import requests

REPO = "project-david-ai/projectdavid-core"
IMAGES = [
    "projectdavid-core-api",
    "projectdavid-core-sandbox",
    "projectdavid-core-inference-worker",
    "projectdavid-core-training-worker",
    "projectdavid-core-training-api",
    "projectdavid-core-router",
]
ERA1_END = datetime(2026, 3, 16, tzinfo=timezone.utc)
ERA2_END = datetime(2026, 4, 1, tzinfo=timezone.utc)
PULLS_PER_IMAGE_PER_RUN = 17


def parse_dt(s: str) -> datetime:
    return datetime.fromisoformat(s.replace("Z", "+00:00"))


# ---------------------------------------------------------------------------
# CI noise — all runs across all branches
# ---------------------------------------------------------------------------
result = subprocess.run(
    [
        "gh",
        "run",
        "list",
        "--repo",
        REPO,
        "--limit",
        "300",
        "--json",
        "updatedAt,conclusion",
    ],
    capture_output=True,
    text=True,
)
all_runs = json.loads(result.stdout)
if isinstance(all_runs, dict) and "value" in all_runs:
    all_runs = all_runs["value"]

era1 = sum(
    1 for r in all_runs if r.get("updatedAt") and parse_dt(r["updatedAt"]) < ERA1_END
)
era2 = sum(
    1
    for r in all_runs
    if r.get("updatedAt") and ERA1_END <= parse_dt(r["updatedAt"]) < ERA2_END
)
era3 = sum(
    1 for r in all_runs if r.get("updatedAt") and parse_dt(r["updatedAt"]) >= ERA2_END
)
ci_noise = (era1 * 2 + era2 * 4 + era3 * 6) * PULLS_PER_IMAGE_PER_RUN

# ---------------------------------------------------------------------------
# GitHub Releases — exact publication timestamp per tag
# Deduplicate keeping latest published_at per tag name
# ---------------------------------------------------------------------------
result = subprocess.run(
    [
        "gh",
        "api",
        "repos/project-david-ai/projectdavid-core/releases",
        "--paginate",
        "--jq",
        ".[] | {tag_name, published_at}",
    ],
    capture_output=True,
    text=True,
)

release_map = {}
for line in result.stdout.strip().split("\n"):
    line = line.strip()
    if not line:
        continue
    try:
        entry = json.loads(line)
        tag = entry["tag_name"].lstrip("v")
        pub = parse_dt(entry["published_at"])
        # Keep latest published_at if duplicates exist
        if tag not in release_map or pub > release_map[tag]:
            release_map[tag] = pub
    except Exception:
        continue

# ---------------------------------------------------------------------------
# Docker Hub pull counts
# ---------------------------------------------------------------------------
print(f"\n{'Image':<45} {'Pulls':>8}")
print("-" * 55)
total_pulls = 0
for image in IMAGES:
    r = requests.get(
        f"https://hub.docker.com/v2/repositories/thanosprime/{image}/",
        timeout=10,
    ).json()
    pulls = r["pull_count"]
    total_pulls += pulls
    print(f"{image:<45} {pulls:>8,}")

# ---------------------------------------------------------------------------
# Semver tags from Docker Hub
# ---------------------------------------------------------------------------
url = "https://hub.docker.com/v2/repositories/thanosprime/projectdavid-core-api/tags/?page_size=100"
all_tags = []
while url:
    resp = requests.get(url, timeout=10).json()
    all_tags += resp.get("results", [])
    url = resp.get("next")

semver_tags = [t for t in all_tags if re.match(r"^\d+\.\d+\.\d+$", t["name"])]
semver_tags.sort(key=lambda t: list(map(int, t["name"].split("."))), reverse=True)

# ---------------------------------------------------------------------------
# Output
# ---------------------------------------------------------------------------
print(f"\n{'Tag':<10} {'Released':<14} {'LastPulled':<14} {'GapHours':>10} {'Likely'}")
print("-" * 60)

real_user_tags = 0
active_tags = 0
now = datetime.now(timezone.utc)

for tag in semver_tags:
    pulled = parse_dt(tag["tag_last_pulled"])
    released = release_map.get(tag["name"])
    gap = round((pulled - released).total_seconds() / 3600, 1) if released else None
    likely = "REAL USER" if gap is not None and gap > 2 else "CI/YOU"

    if likely == "REAL USER":
        real_user_tags += 1
    if (now - pulled).days < 7:
        active_tags += 1

    rel_str = released.strftime("%m-%d %H:%M") if released else "n/a"
    print(
        f"{tag['name']:<10} {rel_str:<14} {pulled.strftime('%m-%d %H:%M'):<14} {str(gap):>10} {likely}"
    )

print(f"\n=== SUMMARY ===")
print(f"Total pulls (all images):      {total_pulls:,}")
print(f"CI run breakdown:              Era1={era1} Era2={era2} Era3={era3}")
print(f"Estimated CI noise:            {ci_noise:,}")
print(f"Estimated real user pulls:     {total_pulls - ci_noise:,}")
print(f"Confirmed real user tags:      {real_user_tags}")
print(f"Active tags (pulled <7d):      {active_tags}")
print(f"Snapshot time:                 {now.strftime('%Y-%m-%d %H:%M')} UTC")