#!/usr/bin/env python3
"""L4 CI surface: which membership projects have .gitlab-ci.yml + jobs.
Read-only. Checkpoint L4_ci_ckpt/<id>.json."""
import json, ssl, time, urllib.error, urllib.request
from pathlib import Path
D = Path('/root/ir-assessment/redteam/gitlab_hyva_io')
CK = D/'L4_ci_ckpt'; CK.mkdir(exist_ok=True)
tok = (D/'.token').read_text().strip()
CTX = ssl.create_default_context(); CTX.check_hostname=False; CTX.verify_mode=ssl.CERT_NONE
H = {'Authorization': f'Bearer {tok}', 'User-Agent': 'l4-ci/1.0'}
def get(path):
    r = urllib.request.Request('https://gitlab.hyva.io'+path, headers=H)
    for a in (1,2):
        try:
            with urllib.request.urlopen(r, timeout=20, context=CTX) as resp:
                return json.loads(resp.read()), resp.status
        except urllib.error.HTTPError as e:
            if e.code == 429 and a==1: time.sleep(5); continue
            return None, e.code
        except Exception:
            if a==1: time.sleep(2); continue
            return None, 0
    return None, 0
projs = json.load(open(D/'L2.json'))['projects']
done = 0
for p in projs:
    ck = CK/f"{p['id']}.json"
    if ck.exists(): done += 1; continue
    c, st1 = get(f"/api/v4/projects/{p['id']}/repository/files/.gitlab-ci.yml?ref=HEAD")
    j, st2 = get(f"/api/v4/projects/{p['id']}/jobs?per_page=1")
    rec = {'path': p['path'], 'ci': st1==200, 'jobs': isinstance(j,list) and len(j)>0}
    ck.write_text(json.dumps(rec))
    done += 1
    if done % 50 == 0: print(f'  {done}/{len(projs)}', flush=True)
    time.sleep(0.3)
ci = sorted(r['path'] for r in (json.load(open(f)) for f in CK.glob('*.json')) if r['ci'])
jo = sorted(r['path'] for r in (json.load(open(f)) for f in CK.glob('*.json')) if r['jobs'])
json.dump({'ci_config': ci, 'has_jobs': jo}, open(D/'L4_ci_surface.json','w'), indent=1)
print(f'[+] DONE ci_config={len(ci)} has_jobs={len(jo)} overlap={len(set(ci)&set(jo))}')
