Research Digest: Dev Container Release Artifact Compilation and Runner Architecture¶
- Date: 2026-09-04 (Updated 2026-09-05)
- Related ADR: ADR-1178
- Author: Lusoris
1. Context and Problem Statement¶
Under ADR-1102, all canonical build artifacts (release binaries, published images, CI artifacts consumed downstream) must be produced inside the vmaf-dev-mcp container. However, .github/workflows/supply-chain.yml historically built native release artifacts (libvmaf.so SONAME chain, vmaf CLI binary, models.tar.gz) directly on the bare ubuntu-latest runner host using ad-hoc apt-get and PyPI meson.
The container-build detector scripts/ci/check-container-build.sh enforces this policy by asserting containerness via /etc/vmafx-dev-container and stamping staged artifact trees (container-build-provenance.txt).
This research digest evaluates the image dimensions, layer composition, hosted runner disk constraints, and the maintainer decision to execute release artifact compilation on the self-hosted Arc A380 canonical runner.
2. Image Metrics and Layer Breakdown¶
Measured on the workstation on 2026-09-05 with docker history --format '{{.Size}}\t{{.CreatedBy}}' vmaf-dev-mcp:local (a local build of the full dev-mcp target of dev/Containerfile; the libvmaf-build stage is a prefix of the same layer stack). The local image ID is sha256:ff297e6d….
Stage / layer group (dev/Containerfile) | Uncompressed size (sum of layers) | Notes |
|---|---|---|
build-deps (ubuntu:26.04 + apt toolchain) | ~1.6 GB | gcc 15.2, clang 19, meson, ninja, Python 3.14 |
gpu-sdks: CUDA toolkit layer | ~7.7 GB | single RUN layer (cuda-toolkit-13-3) |
gpu-sdks: oneAPI + ROCm layer | ~14.2 GB | single RUN layer (intel-basekit + ROCm 7.2.4) |
gpu-sdks: Intel NEO / Level Zero / VPL | ~0.5 GB | Level Zero GPU ICD + compute runtime |
libvmaf-build: source copies + venv + ORT + ffmpeg deps | ~5.5 GB | 2.59 GB + 2.16 GB + ~0.5 GB of COPY layers |
libvmaf-build cumulative | ~29.5 GB | the stage evaluated for containerised compilation |
dev-mcp additions (ffmpeg, MCP server, Go tools) | ~8 GB | interactive dev tools |
dev-mcp total (docker history sum) | ~37.6 GB | docker images reports 52.3 GB with containerd snapshotter |
3. Runner Disk Footprint — The 29.5 GB Pull Blocker¶
GitHub's runner reference lists the standard ubuntu-latest / ubuntu-24.04 runner for public repositories as 4 vCPU, 16 GB RAM, 14 GB SSD (https://docs.github.com/en/actions/reference/runners/github-hosted-runners).
Two physical facts ruled out pulling the image as a job container on ubuntu-latest:
- A ~29.5 GB uncompressed image cannot fit on a 14 GB disk.
- A job-level
container:image is pulled by GitHub Actions during "Initialize containers", before any workflow step runs. Consequently, a disk-clearing step (such as removing Android SDKs or .NET runtimes) cannot precede the pull.
4. Evaluation of Build Execution Strategies¶
| Strategy | Feasibility | Rationale |
|---|---|---|
GHCR job-container pull on ubuntu-latest | Infeasible | 29.5 GB uncompressed layer size causes immediate disk exhaustion during image pull. |
| Slim release-only container stage | Suboptimal | Violates ADR-1102/ADR-0496 single-container invariant; creates toolchain divergence risk between local development and release outputs. |
| On-the-fly container build in CI | Infeasible | Adds 35-45 minutes to every release; risks network timeouts on multi-gigabyte SDK downloads and runner disk exhaustion during intermediate BuildKit caching. |
| Self-hosted Arc A380 canonical runner (Selected) | Fully feasible | The runner container is already locally present on the maintainer workstation; zero network pull; exact bit-identical toolchain; enforces container provenance end-to-end. |
5. Runner Environment Audit & Gaps Analysis¶
The self-hosted runner is provisioned by ADR-1177 (PR #1304) using dev/Containerfile.runner and dev/docker-compose.runner.yml.
Audit of dev/Containerfile.runner¶
- Base Image:
ARG BASE_IMAGE=vmaf-dev-mcp:local->FROM ${BASE_IMAGE}. - Inherited Layers:
vmaf-dev-mcp:localderives fromdev-mcp->libvmaf-build->gpu-sdks->build-deps. - Toolchains Present:
- GCC 13 / GCC 15, Clang 19, LLVM runtime
- Meson 1.x, Ninja, NASM, pkg-config, CMake
- Python 3.14 + venv + pip
- CUDA 13.3, ROCm 7.2.4, Intel oneAPI (icx, icpx, Level Zero)
/etc/vmafx-dev-container(baked intobuild-depsstage withvmafx_dev_container=1)- Isolation: Ephemeral runner running as unprivileged
runneruser; only the Arc A380 DRI node (/dev/dri/renderD129) is exposed; no Docker socket mounted; no host filesystem bind mounts.
Release Build Requirements vs Runner Environment¶
The native release compilation in supply-chain.yml executes: meson setup build core --buildtype=release -Denable_avx512=true -Denable_cuda=false -Denable_sycl=false && meson compile -C build
- Requirements: C compiler, Meson, Ninja, NASM, AVX-512 assembler support, coreutils, tar, gzip, sha256sum, git,
/etc/vmafx-dev-containermarker. - Runner Environment: Fully satisfies every requirement natively inside the runner container. No gaps identified.
- Docker Socket Need: None. Since the runner container itself IS the build environment, workflow steps execute directly inside the canonical environment without spawning sibling or child containers.
6. Decision and Operational Verification¶
- Execution: Release compilation runs on
runs-on: [self-hosted, linux, x64, sycl-arc]with concurrency grouprelease-artifacts-buildandtimeout-minutes: 90. - Provenance:
scripts/ci/check-container-build.sh --stamp artifactsdropscontainer-build-provenance.txt. The gate script was updated to accept bothvmaf-dev-mcpandvmaf-sycl-arc-runneras canonical images while rejecting bareubuntu-latestand unauthorized images. - Verification:
verify-native-artifactsonubuntu-latestdownloads the artifacts and runscheck-container-build.sh --verify artifactsandverify-native-release-artifacts.sh. - Optional GHCR Image:
dev-container-publish.ymlcontinues to build and publishghcr.io/vmafx/vmafx-dev-mcpon master pushes for external transparency and remote contributors, decoupled from the release path.