import importlib.util
import os
from pathlib import Path
import sys
import hashlib
import json
import shutil
import signal
import subprocess
import tarfile
import time

os.umask(0o077)
R=Path(__file__).parent;R.chmod(0o700)
s=importlib.util.spec_from_file_location('previous','/tmp/codex/ltb1021/2026-09-15_contextra-tracking-fix_r01/ops.py')
previous=importlib.util.module_from_spec(s);s.loader.exec_module(previous)
previous.R=R
previous.FILES=['app/byte_tracking.py','app/tracking_kernel.py','tests/test_tracking_kernel.py']
os.chdir(previous.REPO)

def build(label):
    p=previous
    assert p.read(label+'-source.json')['success']
    assert not (R/(label+'-build-start.json')).exists()
    hashes={name:p.sha(p.REPO/name) for name in p.FILES}
    digest=hashlib.sha256(json.dumps(hashes,sort_keys=True).encode()).hexdigest()[:8]
    head=p.read('plan.json')['head']
    tag='contextra-analytics:tracking-'+label+'-'+head[:7]+'-'+digest
    assert subprocess.run(['docker','image','inspect',tag],capture_output=True).returncode!=0
    snap=R/(label+'-snapshot');snap.mkdir()
    proc=subprocess.Popen(['git','-C',str(p.REPO),'archive',head],stdout=subprocess.PIPE)
    with tarfile.open(fileobj=proc.stdout,mode='r|') as archive:archive.extractall(snap,filter='data')
    assert proc.wait()==0
    for name in p.FILES:shutil.copyfile(p.REPO/name,snap/name)
    assert shutil.disk_usage('/var/lib/docker').free>=15*1024**3
    p.save(label+'-build-start.json',dict(head=head,tag=tag,hashes=hashes));p.ledger('build',tag=tag)
    started=time.monotonic()
    with (R/(label+'-build.log')).open('x') as f:
        proc=subprocess.Popen(['docker','build','-f','docker/Dockerfile','--target','app','-t',tag,'.'],cwd=snap,
            env=dict(os.environ,DOCKER_BUILDKIT='1'),stdout=f,stderr=f,start_new_session=True)
        while proc.poll() is None:
            if time.monotonic()-started>1200 or shutil.disk_usage('/var/lib/docker').free<15*1024**3:
                os.killpg(proc.pid,signal.SIGTERM)
                try:proc.wait(15)
                except subprocess.TimeoutExpired:os.killpg(proc.pid,signal.SIGKILL);proc.wait()
                raise RuntimeError('BUILD_LIMIT')
            time.sleep(1)
    assert proc.returncode==0
    image=json.loads(p.cmd(['docker','image','inspect',tag]))[0]['Id']
    p.save(label+'-build.json',dict(head=head,tag=tag,image=image,hashes=hashes,elapsed=time.monotonic()-started))
    print('built',tag,flush=True);p.tests(label+'-image',image)

if __name__=='__main__':
    command=sys.argv[1];label=sys.argv[2] if len(sys.argv)>2 else 'active'
    {'gate':previous.gate,'test':lambda:previous.tests(label),
     'build':lambda:build(label),'apply':lambda:previous.apply(label),
     'observe':lambda:previous.observe(label)}[command]()
