From 2396b1e13aaeb0484edd398a996034c4e4a10f7f Mon Sep 17 00:00:00 2001 From: reluctantfuturist Date: Wed, 16 Apr 2025 23:34:29 -0700 Subject: [PATCH] =?UTF-8?q?fix(build):=20add=20UBI=C2=A09=20compiler=20too?= =?UTF-8?q?l=E2=80=91chain=20and=20split=20fast/slow=20tests=20(#1970)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * build_container.sh - append `python3.11‑devel gcc make` to UBI 9 dnf line so C‑ext wheels build. * tests/integration - + test_ubi9_toolchain.py (fast; asserts pkgs exist in Containerfile) - + test_ubi9_compiles.py (slow; @integration, compiles hello‑world in built image) - – test_container_build.py (removed heavyweight test) * pytest.ini - register `integration` marker. * CI - tests.yml ⇒ `pytest -m "not integration"` - providers_build.yml ⇒ run integration compiler smoke for container jobs --- .github/workflows/providers-build.yml | 5 ++ .github/workflows/tests.yml | 4 ++ llama_stack/distribution/build_container.sh | 3 +- tests/integration/test_ubi9_compiles.py | 63 +++++++++++++++++++++ tests/integration/test_ubi9_toolchain.py | 53 +++++++++++++++++ tests/pytest.ini | 3 + 6 files changed, 130 insertions(+), 1 deletion(-) create mode 100644 tests/integration/test_ubi9_compiles.py create mode 100644 tests/integration/test_ubi9_toolchain.py create mode 100644 tests/pytest.ini diff --git a/.github/workflows/providers-build.yml b/.github/workflows/providers-build.yml index 915344221..dfac37521 100644 --- a/.github/workflows/providers-build.yml +++ b/.github/workflows/providers-build.yml @@ -76,6 +76,11 @@ jobs: # LLAMA_STACK_DIR is set to the current directory so we are building from the source USE_COPY_NOT_MOUNT=true LLAMA_STACK_DIR=. uv run llama stack build --template ${{ matrix.template }} --image-type ${{ matrix.image-type }} --image-name test + - name: Integration compiler smoke + if: matrix.image-type == 'container' + run: | + pytest -m integration tests/integration/test_ubi9_compiles.py + - name: Print dependencies in the image if: matrix.image-type == 'venv' run: | diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 79c935005..a57a12adb 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -35,6 +35,10 @@ jobs: pip install -r requirements.txt pytest pip install -e . + - name: Run fast unit & smoke tests + run: | + pytest -m "not integration" + - name: Build providers run: | llama stack build --template ${{ matrix.provider }} --image-type venv diff --git a/llama_stack/distribution/build_container.sh b/llama_stack/distribution/build_container.sh index ed83b7bff..3102878b0 100755 --- a/llama_stack/distribution/build_container.sh +++ b/llama_stack/distribution/build_container.sh @@ -74,7 +74,8 @@ WORKDIR /app RUN dnf -y update && dnf install -y iputils net-tools wget \ vim-minimal python3.11 python3.11-pip python3.11-wheel \ - python3.11-setuptools && ln -s /bin/pip3.11 /bin/pip && ln -s /bin/python3.11 /bin/python && dnf clean all + python3.11-setuptools python3.11-devel gcc make && \ + ln -s /bin/pip3.11 /bin/pip && ln -s /bin/python3.11 /bin/python && dnf clean all ENV UV_SYSTEM_PYTHON=1 RUN pip install uv diff --git a/tests/integration/test_ubi9_compiles.py b/tests/integration/test_ubi9_compiles.py new file mode 100644 index 000000000..29f9eb0ba --- /dev/null +++ b/tests/integration/test_ubi9_compiles.py @@ -0,0 +1,63 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +import os +import subprocess +import tempfile +import textwrap +from pathlib import Path + +import pytest +import yaml + +pytestmark = pytest.mark.integration # filtered out of the fast suite + + +def _tmp_yaml() -> Path: + f = tempfile.NamedTemporaryFile(delete=False, suffix=".yaml") + yaml.safe_dump( + { + "version": "2", + "distribution_spec": { + "description": "UBI9 compile smoke", + "providers": { + "inference": ["remote::ollama"], + "vector_io": ["inline::faiss"], + }, + "container_image": "registry.access.redhat.com/ubi9", + }, + "image_type": "container", + "image_name": "ci-test", + }, + f, + ) + f.close() + return Path(f.name) + + +def test_image_compiles_c(): + cfg = _tmp_yaml() + tag = "ci-test:dev" + + # Build image (providers‑build.yml already did `uv venv` etc.) + subprocess.run( + ["llama", "stack", "build", "--config", cfg, "--image-name", "ci-test"], + check=True, + env={**os.environ, "USE_COPY_NOT_MOUNT": "true"}, + ) + + # compile a hello‑world c program inside the container + hello_c = textwrap.dedent(""" + #include + int main(){puts("ok");return 0;} + """) + with tempfile.NamedTemporaryFile(delete=False, suffix=".c") as f: + f.write(hello_c.encode()) + + subprocess.run( + ["docker", "run", "--rm", "-v", f.name + ":/tmp/a.c", tag, "bash", "-c", "gcc /tmp/a.c -o /tmp/a && /tmp/a"], + check=True, + ) diff --git a/tests/integration/test_ubi9_toolchain.py b/tests/integration/test_ubi9_toolchain.py new file mode 100644 index 000000000..20c0589c5 --- /dev/null +++ b/tests/integration/test_ubi9_toolchain.py @@ -0,0 +1,53 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the terms described in the LICENSE file in +# the root directory of this source tree. + +import re +import subprocess +import tempfile +from pathlib import Path + +import yaml + +# exact packages we just added +REQUIRED_PKGS = ("python3.11-devel", "gcc", "make") + + +def _tmp_yaml() -> Path: + f = tempfile.NamedTemporaryFile(delete=False, suffix=".yaml") + yaml.safe_dump( + { + "version": "2", + "distribution_spec": { + "description": "CI smoke test", + "providers": { + "inference": ["remote::ollama"], + "vector_io": ["inline::faiss"], + }, + "container_image": "registry.access.redhat.com/ubi9", + }, + "image_type": "container", + "image_name": "ci-test", + }, + f, + ) + f.close() + return Path(f.name) + + +def test_ubi9_toolchain_present(): + cfg = _tmp_yaml() + + # --dry-run only renders the Containerfile + out = subprocess.run( + ["llama", "stack", "build", "--config", cfg, "--dry-run"], + text=True, + capture_output=True, + check=True, + ).stdout + + cfile = Path(re.search(r"(/tmp/.+?/Containerfile)", out).group(1)).read_text() + missing = [p for p in REQUIRED_PKGS if p not in cfile] + assert not missing, f"dnf line lost packages: {', '.join(missing)}" diff --git a/tests/pytest.ini b/tests/pytest.ini new file mode 100644 index 000000000..64ec09bd2 --- /dev/null +++ b/tests/pytest.ini @@ -0,0 +1,3 @@ +[pytest] +markers = + integration: slow / docker‑dependent tests