Avoid nested publish OOM in Linux export
All checks were successful
Core validation / Linux core gate (push) Successful in 1m30s
Linux release build / Linux x64 artifact (push) Successful in 1m35s

This commit is contained in:
gamer147
2026-08-03 18:59:46 -04:00
parent 8eb8a45e60
commit 400f431652
10 changed files with 313 additions and 10 deletions

View File

@@ -47,12 +47,13 @@ S:\Game Hacking\Eushully\Himegari\ ← workspace root (three siblings)
│ ├── validate.py layered core/workspace/runtime/full validation driver
│ ├── test_validate.py pure resolver + validation-plan regressions
│ ├── build-linux-x64.sh one-command pinned Linux export/package/smoke pipeline
│ ├── dotnet_publish_proxy.py guarded low-memory Godot export-time publish staging
│ ├── bootstrap-godot-linux-x64.sh repo-local Godot 4.7 Linux editor/template bootstrap
│ ├── godot-linux-x64.json immutable Godot editor/template source + SHA-256 manifest
│ ├── install_godot_templates.py selective HTTP-range installer for pinned template members
│ ├── package_linux_x64.py export verifier + notice/checksum/archive packager
│ ├── test_install_godot_templates.py, test_package_linux_x64.py
│ │ source-only bootstrap/package regressions
│ ├── test_install_godot_templates.py, test_package_linux_x64.py,
│ │ test_dotnet_publish_proxy.py source-only bootstrap/package/publish regressions
│ ├── sys4load.py loader + disassembler (opcode-decoding)
│ ├── age_opcodes.py GENERATED complete Python ABI view (do not hand-edit)
│ ├── opcodes_build.py generator/linter: vm-map/opcodes.toml -> the 5 artifacts below

View File

@@ -58,8 +58,15 @@ fast integration gate. The cache key is derived from both immutable dependency m
prefix; cached archives/templates are still size/hash checked by their owning bootstrap before use. A successful
job retains the archive, external build/checksum manifests, and smoke log for 30 days. It has only read access to
repository contents and does not use private data, secrets, registry credentials, or release-write permission.
The first hosted execution remains the acceptance gate for runner image dependencies and cache/artifact action
behavior; release publication is intentionally deferred until that artifact run succeeds.
The first hosted execution reached Godot's managed publish but was killed with status 137. Local stage-level
measurement reproduced the pressure: the resident Godot export peaks at 772,476 KiB and an isolated managed
publish peaks at 223,764 KiB, so nesting the latter under the former can cross a roughly 1 GiB runner cgroup.
The build now serializes those peaks: it creates the exact self-contained publish first with compiler/build
servers disabled, lets the real Godot export consume a strictly validated one-assembly proxy publish, and stages
the complete external managed payload only after Godot exits. The complete revised path passes locally, including
payload verification and the packaged opcode/FFmpeg smoke gate. The hosted retry remains the acceptance gate for
the mitigation plus cache/artifact action behavior; release publication is intentionally deferred until it
succeeds. The workflow reports both host memory and cgroup limits to make any further runner constraint explicit.
## Dependency inventory

View File

@@ -1005,9 +1005,14 @@ do not mix mechanical moves with semantic changes.
template, calls the same locally accepted build command, and uploads the archive with its external build info,
checksum ledger, and smoke log. Cache entries have no broad fallback and remain subject to the bootstrap's
size/SHA checks. The workflow has no game corpus, secrets, registry login, or release-write authority; tags
still produce ordinary retained workflow artifacts. The immediate gate is the first hosted build on this
server. If it passes, the next bounded slice can promote an already-verified tag artifact to a Gitea release
without rebuilding it; if it fails, fix only the observed runner/action dependency before adding publication.
still produce ordinary retained workflow artifacts. The first hosted build reached Godot's managed publish
and was killed with status 137. Stage-level measurement found a 772,476 KiB Godot peak and a 223,764 KiB
isolated publish peak, explaining why the nested processes can exceed a roughly 1 GiB cgroup. The build now
runs the exact self-contained publish first, substitutes a tightly validated one-assembly publish while Godot
creates the real PCK/executable, and stages the full external managed payload after the editor exits. The
revised complete build, payload verification, and packaged smoke gate pass locally; a hosted retry is the
immediate acceptance gate. Once that succeeds, the next bounded slice can promote an already-verified tag
artifact to a Gitea release without rebuilding it.
**Not cleanup targets:** generated `build/` output, the two intentional solution files, historical
`docs/superpowers/` plans/specifications, and fidelity-specific complexity that is directly covered by the

View File

@@ -380,7 +380,15 @@ member from Godot's all-platform archive; it does not download the complete 1.2
The build regenerates embedded opcode metadata, bootstraps/builds the pinned Linux FFmpeg bundle, performs
the Godot release export, and delegates the shared required/forbidden payload checks to
`package_linux_x64.py`. The packager adds `LICENSE`, `README.md`, `THIRD_PARTY_NOTICES.md`, a source/dependency
`package_linux_x64.py`. To remain inside constrained CI memory cgroups, it first runs the exact self-contained
`ExportRelease` publish with build/compiler servers and debug symbols disabled. Godot then performs its real
PCK/executable export against a one-assembly staging payload supplied by `dotnet_publish_proxy.py`; the proxy
refuses any project, configuration, runtime, self-contained flag, or output root other than the invocation
reserved by the build driver. Because managed outputs are external to the PCK, the complete prepublished
payload replaces that temporary staging directory only after Godot exits. The final payload verifier and
packaged smoke test therefore validate the same complete runtime that is archived.
The packager adds `LICENSE`, `README.md`, `THIRD_PARTY_NOTICES.md`, a source/dependency
`BUILD-INFO.json`, and per-file `SHA256SUMS` to a stable top-level directory. It normalizes archive ownership,
modes, ordering, and timestamps using `SOURCE_DATE_EPOCH` or the source commit time. Outputs are the loose
export under `build/export/linux-x64/`, the staged installation and `package-smoke.log` under
@@ -402,8 +410,8 @@ python3 -X utf8 tools/package_linux_x64.py package build/export/linux-x64
```
The bootstrap prints the pinned editor path. The verifier prints the accepted export directory; the packager
prints the staged root and archive path. Both Python components have source-only synthetic regressions in the
core validation level.
prints the staged root and archive path. Those Python components and the guarded publish proxy have source-only
synthetic regressions in the core validation level.
The older Windows-hosted cross-export remains available for local development: