import hashlib
import json
import os
from pathlib import Path
import shutil
import signal
import subprocess
import tarfile
import time

HERE=Path(__file__).parent
REPO=Path('/workspace/contextra-analytics-runtime-lifecycle-refactor')
os.umask(0o077)
def cmd(args):
    return subprocess.run(args,check=True,capture_output=True,text=True,timeout=20).stdout
def save(name,data):
    with (HERE/name).open('x') as f:json.dump(data,f,indent=2)
head=cmd(['git','-C',str(REPO),'rev-parse','HEAD']).strip()
assert head=='1fade25380833fce299ffb56aedf54a38c9cd3be'
assert shutil.disk_usage('/var/lib/docker').free>15*1024**3
paths=cmd(['git','-C',str(REPO),'diff','--name-only']).splitlines()+cmd(['git','-C',str(REPO),'ls-files','--others','--exclude-standard']).splitlines()
hashes={p:hashlib.sha256((REPO/p).read_bytes()).hexdigest() for p in paths if (REPO/p).is_file()}
digest=hashlib.sha256(json.dumps(hashes,sort_keys=True).encode()).hexdigest()[:8]
snapshot=HERE/'snapshot';snapshot.mkdir()
p=subprocess.Popen(['git','-C',str(REPO),'archive',head],stdout=subprocess.PIPE)
with tarfile.open(fileobj=p.stdout,mode='r|') as archive:archive.extractall(snapshot,filter='data')
assert p.wait()==0
for path in paths:
    dst=snapshot/path
    if (REPO/path).exists():dst.parent.mkdir(parents=True,exist_ok=True);shutil.copy2(REPO/path,dst)
    else:dst.unlink(missing_ok=True)
base='sha256:5ef7ddad755fa563512a4fc71aeac5ab15261905bdcf9227fb2b413f67b6f506'
images={}
for service,dockerfile,context,extra in (
    ('analytics','docker/Dockerfile','.', ['--target','app']),
    ('sidecar','control_sidecar/Dockerfile','control_sidecar',['--build-arg','SIDECAR_BASE_IMAGE='+base]),
):
    tag=f'contextra-{service}:secure-wss-1fade25-{digest}'
    save(service+'-build-intent.json',dict(tag=tag,hashes=hashes,head=head,base=base))
    with (HERE/(service+'-build.log')).open('x') as log:
        proc=subprocess.Popen(['docker','build','--pull=false','--network=default','-f',dockerfile,'-t',tag,*extra,context],
                              cwd=snapshot,stdout=log,stderr=log,start_new_session=True)
        start=time.monotonic()
        while proc.poll() is None:
            if time.monotonic()-start>900 or shutil.disk_usage('/var/lib/docker').free<15*1024**3:
                os.killpg(proc.pid,signal.SIGTERM);proc.wait(20);raise RuntimeError('BUILD_RESOURCE_BOUND')
            time.sleep(2)
    assert proc.returncode==0,service+' build failed'
    image=json.loads(cmd(['docker','image','inspect',tag]))[0]['Id']
    images[service]=dict(tag=tag,id=image)
    save(service+'-image.json',images[service])
    print(service,tag,image,flush=True)
save('images.json',images)
