images: shared task base, code-last layers, no per-push rebuilds [skip ci]

One base (Temurin 21 JDK, node/npm/tsc, php/composer, maven, sqlite, bwrap)
built only when its Dockerfile or dependencies change, plus a browser variant;
engine/search/VM images FROM base@sha256 with the code in the last layer; the
image workflow runs on dispatch, tags, Dockerfile or pin changes, with a build
cache. Executor NPROC bound relative to the current process count.

Co-Authored-By: Claude Fable 5.1 <[email protected]>
This commit is contained in:
Marius Ciepluch
2026-10-05 20:40:13 +02:00
co-authored by Claude Fable 5.1
parent 7fb061fb69
commit 1b9d1ca85c
12 changed files with 671 additions and 127 deletions
+59
View File
@@ -2,7 +2,9 @@
import json
import os
import signal
import sys
import time
from pathlib import Path
import pytest
@@ -222,3 +224,60 @@ def test_scratch_failure_preserves_exit_and_stderr(workspace, monkeypatch):
assert result["exit_code"] is not None
assert result["stderr"] == "pip build detail"
assert result["reason"].startswith("ScratchLimit:")
@pytest.mark.parametrize("project", [".", "subproject"])
def test_preparation_uses_project_gradle_wrapper(workspace, monkeypatch, project):
repo = workspace / "checkout"
repo.mkdir()
root = repo / project
root.mkdir(exist_ok=True)
# A real local child proves wrapper execution without system Gradle or network.
wrapper = root / "gradlew"
wrapper.write_text(
'test "$1" = "--no-daemon" || exit 1\n'
'test "$2" = "--project-dir" || exit 2\n'
'test "$4" = "assemble" || exit 3\n'
'mkdir -p "$3/build"\n'
'printf compiled > "$3/build/product"\n'
)
wrapper.chmod(0o644)
app = executor.InProcessExecutor(repo, task_boundary=True)
app.prepared_put_url = "https://files.example/output"
blobs = []
monkeypatch.setattr(executor.URLTransport, "put", lambda self, url, data, timeout: blobs.append(data))
request = spec()
request["demo"]["build"] = {"recipe": "gradle", "arguments": [project]}
result = app.submit("prepare_verification", request)
assert result["status"] == "ok", result
unpacked = workspace / "unpacked"
verify_task.extract_checkout(blobs[0], unpacked)
assert (unpacked / "checkout" / project / "build/product").read_text() == "compiled"
assert json.loads((unpacked / "spec.json").read_text())["demo"]["build"]["recipe"] == "none"
def test_preparation_with_many_host_processes(workspace, monkeypatch):
repo = workspace / "checkout"
repo.mkdir()
(repo / "gradlew").write_text('mkdir -p "$3/build"\nprintf compiled > "$3/build/product"\n')
app = executor.InProcessExecutor(repo, task_boundary=True)
app.prepared_put_url = "https://files.example/output"
monkeypatch.setattr(executor.URLTransport, "put", lambda self, url, data, timeout: None)
request = spec()
request["demo"]["build"] = {"recipe": "gradle", "arguments": ["."]}
children = []
try:
for _ in range(300):
pid = os.fork()
if pid == 0:
time.sleep(60)
os._exit(0)
children.append(pid)
result = app.submit("prepare_verification", request)
assert result["status"] == "ok", result
assert (repo / "build/product").read_text() == "compiled"
finally:
for pid in children:
os.kill(pid, signal.SIGKILL)
for pid in children:
os.waitpid(pid, 0)