"""Build production sources in QA, retaining the approved package and active bundle.""" from pathlib import Path from datetime import datetime, timezone import hashlib, json, os, subprocess ROOT=Path(__file__).resolve().parent.parent PRIVATE=ROOT/'storage/app/private/investmoz-v2/portal-audit' read=lambda p:json.loads(Path(p).read_text(encoding='utf-8-sig')) sha=lambda p:hashlib.sha256(Path(p).read_bytes()).hexdigest() plan=read(PRIVATE/'portal-stability-latest.json');source=Path(plan['source']) active={p.relative_to(ROOT/'public/build').as_posix():sha(p) for p in (ROOT/'public/build').rglob('*') if p.is_file()} # Route generation bootstraps the same guarded QA configuration and local class map. (source/'artisan').write_text('''#!/usr/bin/env php handleCommand(new Symfony\\Component\\Console\\Input\\ArgvInput); exit($status); ''',encoding='utf-8') # The shared bootstrap must return the app when invoked through the guarded artisan. runtime=source/'tools/portal-stability-runtime.php' text=runtime.read_text(encoding='utf-8') text=text.replace("if (PHP_SAPI !== 'cli') { return $app; }", "if (PHP_SAPI !== 'cli' || basename($_SERVER['SCRIPT_FILENAME'] ?? '') === 'artisan') { return $app; }") runtime.write_text(text,encoding='utf-8') inputs={p.relative_to(source).as_posix():sha(p) for folder in ['app','config','routes','resources','database/migrations','bootstrap'] for p in (source/folder).rglob('*') if p.is_file() and 'cache' not in p.relative_to(source).parts} for name in ['composer.json','composer.lock','package.json','package-lock.json','tsconfig.json','vite.config.ts']: inputs[name]=sha(source/name) env=dict(os.environ);env.pop('INVESTMOZ_QA_BUILD',None) env['PATH']='C:/laragon/bin/php/php-8.5.11-Win32-vs17-x64'+os.pathsep+env['PATH'] env['VITE_APP_NAME']='InvestMoz' log=PRIVATE/'portal-stability-production-build.log' with log.open('w',encoding='utf-8') as stream: result=subprocess.run(['npm.cmd','run','build'],cwd=source,env=env,stdout=stream,stderr=subprocess.STDOUT,shell=True) assert result.returncode==0,'Build failed; inspect the private build log' assets={p.relative_to(source/'public/build').as_posix():sha(p) for p in (source/'public/build').rglob('*') if p.is_file()} assert 'manifest.json' in assets manifest=read(source/'public/build/manifest.json') for item in manifest.values(): for name in ['file','css','assets']: values=item.get(name,[]);values=[values] if isinstance(values,str) else values assert all((source/'public/build'/p).is_file() for p in values) assert active=={p.relative_to(ROOT/'public/build').as_posix():sha(p) for p in (ROOT/'public/build').rglob('*') if p.is_file()} proof={'result':'passed','at':datetime.now(timezone.utc).isoformat(),'mode':'production','inputs':inputs, 'assets':assets,'build_manifest_sha256':assets['manifest.json'],'active_assets_preserved':True, 'active_writes':0,'source':str(source),'input_hash':hashlib.sha256(json.dumps(inputs,sort_keys=True,separators=(',',':')).encode()).hexdigest()} (PRIVATE/'portal-stability-production.json').write_text(json.dumps(proof,indent=2),encoding='utf-8') print(json.dumps({k:proof[k] for k in ['result','mode','build_manifest_sha256','input_hash','active_assets_preserved','active_writes']}))