chore: checkpoint web Blender migration source, tools and docs
Accumulated uncommitted work: GHOST Web backend, WebGL/GPU web layer, web workflow engine and protocol, tooling, docs and task records. Large generated evidence, user-testing archives, build snapshots and imported test assets remain untracked. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
68
tools/web/build-desktop-workflow-runtime.py
Normal file
68
tools/web/build-desktop-workflow-runtime.py
Normal file
@@ -0,0 +1,68 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Produce the changed WASM and web bundle without running acceptance commands."""
|
||||
import argparse
|
||||
import datetime
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
from pathlib import Path
|
||||
import subprocess
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
|
||||
def publish(destination, data):
|
||||
destination.parent.mkdir(parents=True, exist_ok=True)
|
||||
temporary = destination.with_name(destination.name + f'.tmp-{os.getpid()}')
|
||||
temporary.write_bytes(data)
|
||||
temporary.replace(destination)
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument('--output', default='tests/golden/WBV2-P1424-001/desktop-workflow-build')
|
||||
args = parser.parse_args()
|
||||
output = ROOT / args.output / datetime.datetime.now(datetime.timezone.utc).strftime('%Y%m%dT%H%M%SZ')
|
||||
output.mkdir(parents=True, exist_ok=False)
|
||||
report = {'schemaVersion': 1, 'task': 'WBV2-P1424-001', 'status': 'BUILDING',
|
||||
'validation': 'NOT_RUN', 'acceptance': 'NOT_CLAIMED', 'steps': []}
|
||||
try:
|
||||
commands = [
|
||||
*(([('cpython', ['python3', 'tools/web/build-webengine-python.py'], ROOT)]) if not (ROOT / 'build_web_python313/build/libpython3.13.a').exists() else []),
|
||||
('wasm', ['bash', '-c', 'source tools/web/emscripten-env.sh && cmake --build build_web_blender6 --target web_engine --parallel 4'], ROOT),
|
||||
]
|
||||
for name, command, directory in commands:
|
||||
with (output / (name + '.log')).open('w') as log:
|
||||
completed = subprocess.run(command, cwd=directory, stdout=log, stderr=subprocess.STDOUT)
|
||||
report['steps'].append({'name': name, 'exitCode': completed.returncode})
|
||||
if completed.returncode: raise RuntimeError(name + ' build failed; see ' + str(output))
|
||||
build = ROOT / 'build_web_blender6/bin'
|
||||
manifest_path = ROOT / 'web/app/public/wasm-module-manifest.json'
|
||||
manifest = json.loads(manifest_path.read_text())
|
||||
report['artifacts'] = {}
|
||||
for name in ('web_engine.js', 'web_engine.wasm'):
|
||||
data = (build / name).read_bytes()
|
||||
digest = hashlib.sha256(data).hexdigest()
|
||||
for directory in ('web/app/src/vendor/blender', 'web/app/public/vendor/blender'):
|
||||
publish(ROOT / directory / name, data)
|
||||
for module in manifest['modules']:
|
||||
for resource in module.get('resources', {}).values():
|
||||
if resource.get('url') == '/vendor/blender/' + name: resource['sha256'] = digest
|
||||
report['artifacts'][name] = {'sha256': digest, 'bytes': len(data)}
|
||||
publish(manifest_path, (json.dumps(manifest, indent=2) + '\n').encode())
|
||||
with (output / 'web.log').open('w') as log:
|
||||
completed = subprocess.run(['node', 'tools/web/incremental-web-build.mjs'], cwd=ROOT,
|
||||
env=dict(os.environ, WBV2_SKIP_TYPECHECK='1'), stdout=log, stderr=subprocess.STDOUT)
|
||||
report['steps'].append({'name': 'web', 'exitCode': completed.returncode})
|
||||
if completed.returncode: raise RuntimeError('web build failed; see ' + str(output))
|
||||
report['status'] = 'BUILT_UNVERIFIED'
|
||||
except BaseException as error:
|
||||
report.update(status='BUILD_INCOMPLETE', error=str(error))
|
||||
raise
|
||||
finally:
|
||||
publish(output / 'build.json', (json.dumps(report, indent=2) + '\n').encode())
|
||||
print(json.dumps({'directory': str(output), **report}), flush=True)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
Reference in New Issue
Block a user