Ragnarok rodecomp deployment on memento

Changes to upstream:
- git.js: coordinator commit identity from TD_GIT_AUTHOR_NAME/EMAIL.
- build.js: docker runner can share job dirs through a named volume
  (jobVolume/jobVolumeRoot) for containerized workers.
- install.js: staged installer output with logs, start prompt for regions.
- web: feed layout, cache-busting asset versions, multi-agent help section.
- build-td: fetch checksummed Windows runtime when building on non-Windows.

Additions:
- deploy/rodecomp: compose stack, Dockerfiles, Caddyfile, server.json,
  bulk import/verify scripts, and README.md with the deployment notes
  (the root README stays identical to upstream).
- toolchain/msvc-v142: MSVC v142 under Wine (Docker), SDK 10.0.19041.0.
- tools/rodecomp: project preparation, Forgejo provisioning, history and
  identity tools.
This commit is contained in:
clank-bot 2026-10-25 14:38:52 +01:00
commit 022e0a2c78
39 changed files with 1232 additions and 33 deletions

View file

@ -0,0 +1,13 @@
FROM debian:13-slim AS download
RUN apt-get update && apt-get install -y --no-install-recommends python3 ca-certificates msitools && rm -rf /var/lib/apt/lists/*
WORKDIR /build
COPY download.py /build/download.py
RUN python3 download.py
FROM debian:13-slim
RUN dpkg --add-architecture i386 && apt-get update && apt-get install -y --no-install-recommends wine wine64 wine32:i386 ca-certificates coreutils && rm -rf /var/lib/apt/lists/*
COPY --from=download /build/toolchain /opt/toolchain
COPY env.sh /opt/td/env.sh
ENV WINEPREFIX=/opt/td/wineprefix WINEDEBUG=-all WINEARCH=win64 HOME=/tmp
RUN mkdir -p /opt/td/wineprefix && wineboot --init && wineserver -w && wine reg add 'HKCU\Environment' /v TEMP /t REG_SZ /d 'Z:\tmp' /f && wine reg add 'HKCU\Environment' /v TMP /t REG_SZ /d 'Z:\tmp' /f && wineserver -w && chmod -R a+rX /opt/toolchain && chmod -R a+rwX /opt/td/wineprefix
WORKDIR /job

View file

@ -0,0 +1,7 @@
FROM rodecomp/compiler:v142
RUN apt-get update && apt-get install -y --no-install-recommends cmake ninja-build python3 && rm -rf /var/lib/apt/lists/*
COPY cmake-toolchain.cmake /opt/td/cmake-toolchain.cmake
COPY cl-wine.sh /opt/td/cl-wine.sh
RUN chmod +x /opt/td/cl-wine.sh
COPY lib-wine.sh /opt/td/lib-wine.sh
RUN chmod +x /opt/td/lib-wine.sh

View file

@ -0,0 +1,16 @@
#!/usr/bin/python3
"""Invoke MSVC under Wine, translating POSIX inputs and isolating service pipes."""
import os
import subprocess
import sys
import tempfile
args = []
for arg in sys.argv[1:]:
if arg.startswith('/') and os.path.isfile(arg):
arg = 'Z:' + arg.replace('/', '\\')
args.append(arg)
with tempfile.TemporaryFile() as output:
result = subprocess.run(['wine', '/opt/toolchain/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x86/cl.exe', *args], stdout=output, stderr=subprocess.STDOUT)
output.seek(0)
sys.stdout.buffer.write(output.read())
sys.exit(result.returncode)

View file

@ -0,0 +1,8 @@
set(CMAKE_SYSTEM_NAME Windows)
set(CMAKE_SYSTEM_PROCESSOR x86)
set(CMAKE_C_COMPILER /opt/td/cl-wine.sh)
set(CMAKE_CXX_COMPILER "${CMAKE_C_COMPILER}")
# Cross-compiling: configure checks must not try to run a Windows executable.
set(CMAKE_TRY_COMPILE_TARGET_TYPE STATIC_LIBRARY)
set(CMAKE_AR /opt/td/lib-wine.sh)
set(CMAKE_TRY_COMPILE_CONFIGURATION Release)

View file

@ -0,0 +1,61 @@
"""Acquire pinned v142 x64-host/x86-target packages from Microsoft's VS manifest."""
import hashlib
import io
import json
import pathlib
import re
import shutil
import subprocess
import urllib.request
import zipfile
MANIFEST = 'https://download.visualstudio.microsoft.com/download/pr/e2324e87-3765-4b14-85e5-1234d99f6254/fb642c3f891b70947e0152275e1722ffb3cca7e8700eea0f0fa0f3a7645584cc/VisualStudio.vsman'
root = pathlib.Path('toolchain')
root.mkdir(exist_ok=True)
packages = json.load(urllib.request.urlopen(MANIFEST))['packages']
def package(name):
return next(p for p in packages if p['id'].lower() == name.lower() and p.get('language') in (None, 'en-US'))
def download(payload):
data = urllib.request.urlopen(payload['url'].replace(' ', '%20')).read()
if hashlib.sha256(data).hexdigest().lower() != payload['sha256'].lower():
raise RuntimeError('Checksum mismatch: ' + payload['fileName'])
print(payload['fileName'], len(data), flush=True)
return data
suffixes = ['Tools.HostX64.TargetX86.base', 'Tools.HostX64.TargetX86.Res.base',
'CRT.Headers.base', 'CRT.x86.Desktop.base', 'ATL.Headers.base', 'ATL.X86.base']
for suffix in suffixes:
for payload in package('Microsoft.VC.14.29.16.11.' + suffix)['payloads']:
with zipfile.ZipFile(io.BytesIO(download(payload))) as archive:
for entry in archive.infolist():
name = pathlib.PurePosixPath(entry.filename)
if not entry.is_dir() and name.parts[0] == 'Contents':
if '..' in name.parts:
raise RuntimeError('Unsafe package path')
out = root.joinpath(*name.parts[1:])
out.parent.mkdir(parents=True, exist_ok=True)
out.write_bytes(archive.read(entry))
sdk = package('Win10SDK_10.0.19041')
payloads = {p['fileName'].replace('\\', '/').split('/')[-1]: p for p in sdk['payloads']}
msis = ['Windows SDK for Windows Store Apps Headers-x86_en-us.msi',
'Windows SDK Desktop Headers x86-x86_en-us.msi',
'Windows SDK Desktop Headers x64-x86_en-us.msi',
'Windows SDK Desktop Libs x86-x86_en-us.msi',
'Universal CRT Headers Libraries and Sources-x86_en-us.msi']
cache = pathlib.Path('sdk-downloads')
cache.mkdir(exist_ok=True)
for name in msis:
data = download(payloads[name])
msi = cache / name
msi.write_bytes(data)
for cab in set(re.findall(rb'[A-Za-z0-9]{32}\.cab', data)):
cabname = cab.decode('ascii')
dest = cache / cabname
if not dest.exists():
dest.write_bytes(download(payloads[cabname]))
subprocess.run(['msiextract', '-C', str(root.resolve()), str(msi)], check=True, stdout=subprocess.DEVNULL)
(root / 'provenance.json').write_text(json.dumps({'manifest': MANIFEST, 'toolset': 'v142', 'compilerPackage': '14.29.30159', 'target': 'x86', 'sdk': '10.0.19041.0'}, indent=2))
print('Toolchain extraction complete', flush=True)

View file

@ -0,0 +1,13 @@
export WINEPREFIX=/tmp/wineprefix
export WINEDEBUG=-all
export WINEARCH=win64
export HOME=/tmp
export TMP='Z:\tmp' TEMP='Z:\tmp'
if [ ! -d "$WINEPREFIX" ]; then
cp -rs /opt/td/wineprefix "$WINEPREFIX"
wineserver -p >/dev/null 2>&1 || true
fi
TD_CL='/opt/toolchain/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x86/cl.exe'
td_cl() {
wine "$TD_CL" "$@"
}

View file

@ -0,0 +1,7 @@
#!/bin/sh
log=$(mktemp)
wine /opt/toolchain/VC/Tools/MSVC/14.29.30133/bin/Hostx64/x86/lib.exe "$@" >"$log" 2>&1
status=$?
cat "$log"
rm -f "$log"
exit "$status"