diff --git a/.github/workflows/publish-to-docker.yml b/.github/workflows/publish-to-docker.yml new file mode 100644 index 000000000..cf1e8b916 --- /dev/null +++ b/.github/workflows/publish-to-docker.yml @@ -0,0 +1,99 @@ +name: Docker Build and Publish + +on: + workflow_dispatch: + inputs: + version: + description: 'TestPyPI or PyPI version to build (e.g., 0.0.63.dev20250114)' + required: true + type: string + +jobs: + build-and-push: + runs-on: ubuntu-latest + permissions: + contents: read + packages: write + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 + + - name: Log in to the Container registry + uses: docker/login-action@v3 + with: + username: ${{ secrets.DOCKERHUB_USERNAME }} + password: ${{ secrets.DOCKERHUB_TOKEN }} + + - name: Set version + id: version + run: | + if [ "${{ github.event_name }}" = "push" ]; then + echo "VERSION=0.0.63.dev20250114" >> $GITHUB_OUTPUT + else + echo "VERSION=${{ inputs.version }}" >> $GITHUB_OUTPUT + fi + + - name: Check package version availability + run: | + # Function to check if version exists in a repository + check_version() { + local repo=$1 + local status_code=$(curl -s -o /dev/null -w "%{http_code}" "https://$repo.org/project/llama-stack/${{ steps.version.outputs.version }}") + return $([ "$status_code" -eq 200 ]) + } + + # Check TestPyPI first, then PyPI + if check_version "test.pypi"; then + echo "Version ${{ steps.version.outputs.version }} found in TestPyPI" + echo "PYPI_SOURCE=testpypi" >> $GITHUB_ENV + elif check_version "pypi"; then + echo "Version ${{ steps.version.outputs.version }} found in PyPI" + echo "PYPI_SOURCE=pypi" >> $GITHUB_ENV + else + echo "Error: Version ${{ steps.version.outputs.version }} not found in either TestPyPI or PyPI" + exit 1 + fi + + - name: Install llama-stack + run: | + if [ "${{ github.event_name }}" = "push" ]; then + pip install -e . + else + if [ "$PYPI_SOURCE" = "testpypi" ]; then + pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple llama-stack==${{ steps.version.outputs.version }} + else + pip install llama-stack==${{ steps.version.outputs.version }} + fi + fi + + - name: Build docker image + run: | + TEMPLATES=("ollama" "bedrock" "remote-vllm" "fireworks" "together" "tgi" "meta-reference-gpu") + for template in "${TEMPLATES[@]}"; do + if [ "$PYPI_SOURCE" = "testpypi" ]; then + TEST_PYPI_VERSION=${{ steps.version.outputs.version }} llama stack build --template $template --image-type docker + else + PYPI_VERSION=${{ steps.version.outputs.version }} llama stack build --template $template --image-type docker + fi + done + + - name: List docker images + run: | + docker images + + - name: Push to dockerhub + run: | + TEMPLATES=("ollama" "bedrock" "remote-vllm" "fireworks" "together" "tgi" "meta-reference-gpu") + for template in "${TEMPLATES[@]}"; do + if [ "$PYPI_SOURCE" = "testpypi" ]; then + docker tag distribution-$template:test-${{ steps.version.outputs.version }} llamastack/distribution-$template:test-${{ steps.version.outputs.version }} + docker push llamastack/distribution-$template:test-${{ steps.version.outputs.version }} + else + docker tag distribution-$template:${{ steps.version.outputs.version }} llamastack/distribution-$template:${{ steps.version.outputs.version }} + docker push llamastack/distribution-$template:${{ steps.version.outputs.version }} + fi + done diff --git a/llama_stack/cli/stack/build.py b/llama_stack/cli/stack/build.py index 85e6cb962..38994bebf 100644 --- a/llama_stack/cli/stack/build.py +++ b/llama_stack/cli/stack/build.py @@ -107,7 +107,8 @@ class StackBuild(Subcommand): f"Please specify a image-type (docker | conda | venv) for {args.template}" ) self._run_stack_build_command_from_build_config( - build_config, template_name=args.template + build_config, + template_name=args.template, ) return @@ -261,7 +262,9 @@ class StackBuild(Subcommand): ) def _run_stack_build_command_from_build_config( - self, build_config: BuildConfig, template_name: Optional[str] = None + self, + build_config: BuildConfig, + template_name: Optional[str] = None, ) -> None: import json import os diff --git a/llama_stack/distribution/build.py b/llama_stack/distribution/build.py index 5a7dfba11..a8b2342af 100644 --- a/llama_stack/distribution/build.py +++ b/llama_stack/distribution/build.py @@ -6,6 +6,7 @@ import importlib.resources import logging +import sys from enum import Enum from pathlib import Path @@ -20,7 +21,7 @@ from llama_stack.distribution.distribution import get_provider_registry from llama_stack.distribution.utils.config_dirs import BUILDS_BASE_DIR -from llama_stack.distribution.utils.exec import run_with_pty +from llama_stack.distribution.utils.exec import run_command, run_with_pty from llama_stack.providers.datatypes import Api log = logging.getLogger(__name__) @@ -102,7 +103,10 @@ def print_pip_install_help(providers: Dict[str, List[Provider]]): print() -def build_image(build_config: BuildConfig, build_file_path: Path): +def build_image( + build_config: BuildConfig, + build_file_path: Path, +): docker_image = build_config.distribution_spec.docker_image or "python:3.10-slim" normal_deps, special_deps = get_provider_dependencies( @@ -144,7 +148,12 @@ def build_image(build_config: BuildConfig, build_file_path: Path): if special_deps: args.append("#".join(special_deps)) - return_code = run_with_pty(args) + is_terminal = sys.stdin.isatty() + if is_terminal: + return_code = run_with_pty(args) + else: + return_code = run_command(args) + if return_code != 0: log.error( f"Failed to build target {build_config.name} with return code {return_code}", diff --git a/llama_stack/distribution/build_container.sh b/llama_stack/distribution/build_container.sh index 06cb19c32..17902de0a 100755 --- a/llama_stack/distribution/build_container.sh +++ b/llama_stack/distribution/build_container.sh @@ -54,7 +54,7 @@ add_to_docker() { # Update and install UBI9 components if UBI9 base image is used if [[ $docker_base == *"registry.access.redhat.com/ubi9"* ]]; then - add_to_docker <