Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions containers/barc-stock-headless/Containerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,11 @@ RUN timeout --kill-after=5s 120s /usr/lib/apt/apt-helper -o APT::Sandbox::User=r
timeout --kill-after=5s 1200s apt-get -o APT::Sandbox::User=root -o APT::Update::Error-Mode=any update && \
timeout --kill-after=5s 1200s apt-get -o APT::Sandbox::User=root install -y --no-install-recommends \
ca-certificates git curl python3 cmake=3.28.3-1build7 g++-13 ninja-build \
pkg-config binutils p7zip-full zip unzip tar autoconf automake libtool \
pkg-config binutils p7zip-full zip unzip tar make perl autoconf automake libtool linux-libc-dev \
libgl1-mesa-dev libglu1-mesa-dev libsdl2-dev libdevil-dev libopenal-dev \
libogg-dev libvorbis-dev libxcursor-dev libx11-dev libxrandr-dev \
libfreetype-dev libfontconfig1-dev libcurl4-openssl-dev zlib1g-dev libssl-dev && \
libfreetype-dev libfontconfig1-dev libcurl4-openssl-dev zlib1g-dev libssl-dev \
libunwind-dev=1.6.2-3build1.1 liblzma-dev=5.6.1+really5.4.5-1ubuntu0.3 && \
timeout --kill-after=5s 3600s python3 /recipe/build-image.py --mode toolchain
ENV PATH=/opt/vcpkg/installed/x64-linux/tools/protobuf:/opt/vcpkg/installed/x64-linux/tools/grpc:${PATH}
ENV CMAKE_PREFIX_PATH=/opt/vcpkg/installed/x64-linux PKG_CONFIG_PATH=/opt/vcpkg/installed/x64-linux/lib/pkgconfig
Expand Down
6 changes: 4 additions & 2 deletions containers/barc-stock-headless/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ Before fetching accepted HighBar, the recipe verifies the tracked Recoil BARb sl

## Repository-owned toolchain bootstrap

The `toolchain` stage starts from the official Ubuntu24.04 amd64 manifest f610ab94… and installs through Ubuntu's signed `20261001T000000Z` snapshot. Apt uses the mapped container root as its sandbox user: this host’s rootless UID/GID mapping stops at64510, while Ubuntu’s `_apt`/nobody group65534 is unavailable. This remains root inside the existing user namespace and changes no host mappings or privileges. The minimal base lacks a TLS CA bundle. Before package resolution, apt-helper acquires only Ubuntu ca-certificates20240203 by its SHA256641de77d… pin and extracts the public trust bundle. The package pin was authenticated from the fixed snapshot’s Packages.xz SHA2562a6a199e… and a verified Ubuntu Archive2018 InRelease signature. This bootstrap uses HTTP with mandatory content hash verification; subsequent package indexes and downloads use an explicit fixed HTTPS snapshot URI. The existing Ubuntu archive keyring and Signed-By checks remain active; strict apt update refuses any index failure. The historical signed snapshot deliberately disables expiry freshness, while keeping archive signatures and hashes. No moving mirror, TLS-verification bypass, trusted=yes or pre-existing toolchain image is accepted. CMake is pinned3.28.3-1build7; the produced CMake3.28.3 and GCC13.3.0 are verified before plugin compilation. The signed snapshot fixes the remaining apt package resolution; its actual complete package versions are recorded as build output, rather than invented from unobserved indexes.
The `toolchain` stage starts from the official Ubuntu24.04 amd64 manifest f610ab94… and installs through Ubuntu's signed `20261001T000000Z` snapshot. Apt uses the mapped container root as its sandbox user: this host’s rootless UID/GID mapping stops at64510, while Ubuntu’s `_apt`/nobody group65534 is unavailable. This remains root inside the existing user namespace and changes no host mappings or privileges. The minimal base lacks a TLS CA bundle. Before package resolution, apt-helper acquires only Ubuntu ca-certificates20240203 by its SHA256641de77d… pin and extracts the public trust bundle. The package pin was authenticated from the fixed snapshot’s Packages.xz SHA2562a6a199e… and a verified Ubuntu Archive2018 InRelease signature. This bootstrap uses HTTP with mandatory content hash verification; subsequent package indexes and downloads use an explicit fixed HTTPS snapshot URI. The existing Ubuntu archive keyring and Signed-By checks remain active; strict apt update refuses any index failure. The historical signed snapshot deliberately disables expiry freshness, while keeping archive signatures and hashes. No moving mirror, TLS-verification bypass, trusted=yes or pre-existing toolchain image is accepted. Make, Perl and Linux headers are explicit native prerequisites, checked before dependency compilation; a real initial OpenSSL port failure exposed the missing Make tool. CMake is pinned3.28.3-1build7; the produced CMake3.28.3 and GCC13.3.0 are verified before plugin compilation. The signed snapshot fixes the remaining apt package resolution; its actual complete package versions are recorded as build output, rather than invented from unobserved indexes.

The builder fetches the existing HighBar vcpkg baseline256acc640… and verifies its exact commit/treee382dac5…. Its own bootstrap metadata pins the2026-04-08 glibc executable SHA512c5a43929…; the resulting downloaded executable must match before installation. The manifest retains HighBar's grpc/protobuf/abseil dependencies and adds GTest for the existing compiled stock controls. Baseline-selected gRPC1.76.0#1, Protobuf6.33.4#1, Abseil20260107.1#2 and GTest1.17.0#2 use the source archive hashes/patches owned by that immutable vcpkg tree. Protoc33.4 and gRPC1.76.0 are checked before generation. Vcpkg may acquire its own baseline-pinned supporting tools and dependency ports; their installed status is retained. This is a fresh source build, not reuse of historical GCC16/protobuf36 qualification.
The builder fetches the existing HighBar vcpkg baseline256acc640… and verifies its exact commit/treee382dac5…. Its own bootstrap metadata pins the2026-04-08 glibc executable SHA512c5a43929…; the resulting downloaded executable must match before installation. The manifest retains HighBar's grpc/protobuf/abseil dependencies and adds GTest for the existing compiled stock controls. A native overlay triplet includes the immutable canonical x64-linux triplet and selects VCPKG_BUILD_TYPE=release, matching the existing stock script’s Release build. This removes the unused Debug variant; source versions, linkage, compiler tracking and all full runtime assets remain selected. Both triplet files are recorded in the produced toolchain manifest, and the included canonical file participates in vcpkg’s ABI hash. Baseline-selected gRPC1.76.0#1, Protobuf6.33.4#1, Abseil20260107.1#2 and GTest1.17.0#2 use the source archive hashes/patches owned by that immutable vcpkg tree. Protoc33.4 and gRPC1.76.0 are checked before generation. Vcpkg may acquire its own baseline-pinned supporting tools and dependency ports; their installed status is retained. This is a fresh source build, not reuse of historical GCC16/protobuf36 qualification.

`HighBar/scripts/build-barc-stock-plugin.sh` permits BARC_SYSROOT; `/usr` supplies Ubuntu SDL2/DevIL/OpenAL paths. The vcpkg prefix is supplied through the existing CMake environment search path while preserving every script engine commit/tree, contract and source-control check. No retained old sysroot byte identity is a required source input. Actual loader ABI compatibility against the official engine remains an output requiring qualification. Recoil requests DevIL1.8.0, while its own FindDevIL module has no version support and Noble supplies1.7.8; that honest API/header compatibility gap needs the first real stock build, not a false1.8 claim. The same vcpkg baseline owns DevIL1.8.0#13 if a source-owned sysroot correction proves necessary.

Expand All @@ -44,3 +44,5 @@ Run as UID10001 with read-only root, all capabilities dropped, no-new-privileges
The entrypoint refuses a nonempty/linked runtime, verifies the startscript, confines token cleanup to the new directory and reuses the maintained HighBar `_launch.sh`. Sourcing it preserves a direct engine child that the entrypoint waits for and forwards termination to. Engine logs, PID, replays and settings remain in `/work` for the runner's independent terminal evidence/cleanup collection. Source setup copies small configuration/plugin data; immutable map/game resources are read through SPRING_DATADIR. No old engine packet is replaced, resumed or retried.

The complete source-defined stock observer/passive gameplay fixture and native coordinator/broker journeys have their existing owner/admission joins. This image retains FSBar fixture source but does not invent modinfo, a startscript, actual game/map checksums, actor grants, platform trust or native acceptance. Full runtime acquisition does not close Count1, six useful-play journeys, receiver adoption or publication.

The stock Recoil configuration requires Libunwind >=1.4 and the LZMA library. The signed fixed snapshot supplies explicit libunwind-dev1.6.2-3build1.1 and liblzma-dev5.6.1+really5.4.5-1ubuntu0.3; their pkg-config prerequisites are checked before the vcpkg dependency compile. The existing CMake requirements remain authoritative. A downstream failed build with --layers=false/--force-rm=true does not retain its intermediate toolchain image, even when that stage committed successfully. Only a separately tagged successful target or a successful final image is reusable; log completion alone does not establish retained cache custody.
19 changes: 17 additions & 2 deletions containers/barc-stock-headless/build-image.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def check_inputs(pins):
require(bool(re.fullmatch(r'20[0-9]{6}T[0-9]{6}Z', boot['ubuntuSnapshot'])), 'fixed signed snapshot required')
require(boot['vcpkgCommit'] == tool['vcpkgBaseline'] and bool(COMMIT.fullmatch(boot['vcpkgTree'])), 'exact canonical vcpkg commit/tree required')
require(bool(re.fullmatch(r'[0-9a-f]{128}', boot['vcpkgToolGlibcSha512'])), 'vcpkg tool hash missing')
require(boot.get('buildType') == 'release', 'stock plugin dependencies require release-only build selection')
for row in pins['sources'].values():
require(row['url'].startswith('https://github.com/'), 'source must use the declared HTTPS repository')
require(bool(COMMIT.fullmatch(row['commit'])) and bool(COMMIT.fullmatch(row['tree'])), 'exact source commit/tree required')
Expand Down Expand Up @@ -168,6 +169,13 @@ def sdp_population(path, files_max, bytes_max):

def toolchain(pins):
check_inputs(pins)
# Refuse missing native prerequisites before a costly dependency compile.
for command in ('git','curl','cmake','ninja','make','perl','pkg-config','g++-13','gcc-13','timeout','readelf','7z','tar','zip','unzip','autoconf','automake','libtoolize'):
require(shutil.which(command) is not None, 'missing bootstrap tool before dependency build: ' + command)
# Selected Recoil requires Libunwind >=1.4 and links its static LZMA closure.
# Check the system prerequisites before spending time on vcpkg compilation.
run(['pkg-config', '--atleast-version=1.4.0', 'libunwind'], 30)
run(['pkg-config', '--exists', 'liblzma'], 30)
boot = pins['toolchain']['bootstrap']; target = pathlib.Path('/opt/vcpkg')
source({'url': boot['vcpkgRepository'], 'commit': boot['vcpkgCommit'], 'tree': boot['vcpkgTree']}, target, pins['budgets']['gitFetchSeconds'])
metadata = (target / 'scripts/vcpkg-tool-metadata.txt').read_text()
Expand All @@ -182,9 +190,16 @@ def toolchain(pins):
# The first three are the existing HighBar manifest; GTest is required by
# its stock source controls. Resolve all sources from the same baseline.
(manifest_root / 'vcpkg.json').write_text(json.dumps(manifest, indent=2) + '\n')
triplets = manifest_root / 'triplets'; triplets.mkdir()
triplet = triplets / 'x64-linux.cmake'
canonical_triplet = target / 'triplets/x64-linux.cmake'
require(canonical_triplet.is_file(), 'canonical x64-linux triplet missing')
triplet.write_text('include("/opt/vcpkg/triplets/x64-linux.cmake")\n'
'set(VCPKG_BUILD_TYPE release)\n'
'list(APPEND VCPKG_HASH_ADDITIONAL_FILES "/opt/vcpkg/triplets/x64-linux.cmake")\n')
env = dict(os.environ, VCPKG_MAX_CONCURRENCY='1', VCPKG_DISABLE_METRICS='1')
run([str(target / 'vcpkg'), 'install', '--triplet=x64-linux', '--x-manifest-root=' + str(manifest_root),
'--x-install-root=/opt/vcpkg/installed', '--disable-metrics'], 3600, env=env)
'--x-install-root=/opt/vcpkg/installed', '--overlay-triplets=' + str(triplets), '--disable-metrics'], 3600, env=env)
packages = subprocess.check_output(['dpkg-query','-W','-f=${Package} ${Version} ${Architecture}\n'], text=True)
(manifest_root / 'ubuntu-packages.txt').write_text(packages)
status = target / 'installed/vcpkg/status'
Expand All @@ -193,7 +208,7 @@ def toolchain(pins):
# Record actual package identities and tool bytes as OUTPUTS, not fake
# prequalified inputs. The platform also records the resulting image ID.
files = [manifest_root / name for name in ('vcpkg.json','ubuntu-packages.txt','vcpkg-status.txt')]
files += [target / 'vcpkg', pathlib.Path('/usr/bin/g++-13'), pathlib.Path('/usr/bin/cmake')]
files += [triplet, canonical_triplet, target / 'vcpkg', pathlib.Path('/usr/bin/g++-13'), pathlib.Path('/usr/bin/cmake')]
for relative in ('tools/protobuf/protoc','tools/grpc/grpc_cpp_plugin'):
files.append(target / 'installed/x64-linux' / relative)
lines = []
Expand Down
3 changes: 2 additions & 1 deletion containers/barc-stock-headless/resources.json
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,8 @@
"sha256": "641de77d8f142cfd62a1a6f964ba67b20754d3337c480efb529d086075a06c9a",
"authenticatedIndexSha256": "2a6a199e1031a5c279cb346646d594993f35b1c03dd4a82aaa0323980dd92451",
"authentication": "fixedsnapshot noble/main/amd64 Packages.xz bound by UbuntuArchive2018 good InRelease signature; pin supplies bootstrapCA only"
}
},
"buildType": "release"
}
},
"budgets": {
Expand Down
9 changes: 9 additions & 0 deletions containers/barc-stock-headless/test_source.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,18 @@
import subprocess
import tempfile
import unittest
from unittest import mock

root = pathlib.Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location('bar_image_source', root / 'build-image.py')
module = importlib.util.module_from_spec(spec); spec.loader.exec_module(module)
pins = json.loads((root / 'resources.json').read_text())

class ImageSourceTests(unittest.TestCase):
def test_missing_unwind_is_refused_before_source_acquisition(self):
with mock.patch.object(module.shutil, 'which', return_value='/fixture/tool'), mock.patch.object(module, 'run', side_effect=subprocess.CalledProcessError(1, ['pkg-config'])), mock.patch.object(module, 'source') as acquire:
with self.assertRaises(subprocess.CalledProcessError): module.toolchain(pins)
acquire.assert_not_called()
def test_moving_parent_tag_is_refused(self):
changed = copy.deepcopy(pins); changed['toolchain']['parentOsCandidate'] = 'ubuntu:latest'
with self.assertRaises(ValueError): module.check_inputs(changed)
Expand All @@ -33,6 +38,10 @@ def test_wrong_game_selection_is_refused(self):
def test_nonfinite_deadline_is_refused(self):
changed = copy.deepcopy(pins); changed['budgets']['downloadSeconds'] = 0
with self.assertRaises(ValueError): module.check_inputs(changed)
def test_missing_make_refuses_before_source_or_compiler_launch(self):
with mock.patch.object(module.shutil, 'which', side_effect=lambda command: None if command == 'make' else '/fixture/' + command), mock.patch.object(module, 'source') as acquire:
with self.assertRaisesRegex(ValueError, 'missing bootstrap tool.*make'): module.toolchain(pins)
acquire.assert_not_called()
def test_real_gitlink_placeholder_and_nonempty_refusal(self):
with tempfile.TemporaryDirectory() as directory:
root = pathlib.Path(directory); repo = root / 'parent'; checkout = root / 'checkout'
Expand Down
Loading