Skip to content
Open
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
6 changes: 6 additions & 0 deletions .github/workflows/publish-dockers.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,11 @@ on:
description: 'Optional comma-separated distributions to publish'
required: false
type: string
include_ui_image:
description: 'Set to false to skip publishing the UI Docker image'
required: false
default: true
type: boolean

jobs:
publish-cpu-distros:
Expand Down Expand Up @@ -88,5 +93,6 @@ jobs:
with:
version: ${{ inputs.version }}
distros: ${{ inputs.distros }}
include_ui_image: ${{ inputs.include_ui_image }}
dockerhub_username: ${{ secrets.DOCKERHUB_USERNAME }}
dockerhub_token: ${{ secrets.DOCKERHUB_TOKEN }}
14 changes: 14 additions & 0 deletions RELEASE_PROCESS.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,20 @@ release-0.1.x ← v0.1.0rc1, v0.1.0rc2, v0.1.0, v0.1.1rc1, v0.1.1, ...
release-0.2.x ← v0.2.0rc1, v0.2.0, ...
```

## Packages

The release process handles multiple packages across different repositories:

- **Python packages** (published to PyPI/test.pypi):
- `llama-stack-client` (from `llama-stack-client-python` repo)
- `llama-stack` (from `llama-stack` repo)

- **npm packages** (published to npmjs.org):
- `llama-stack-client` (from `llama-stack-client-typescript` repo)
- `llama-stack-ui` (from `llama-stack` repo at `src/llama_stack_ui/`)

All packages are versioned together and released synchronously. Note that the UI package is built and published as part of the `llama-stack` repository release process.

## Workflows

**Cut Release Candidate** (`cut-release-candidate.yaml`)
Expand Down
6 changes: 6 additions & 0 deletions actions/publish-dockers/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,11 @@ inputs:
description: 'Optional comma-separated distributions to publish'
required: false
type: string
include_ui_image:
description: 'Set to false to skip publishing the llamastack/ui image'
required: false
default: 'true'
type: string
dockerhub_username:
description: 'DockerHub username'
required: true
Expand Down Expand Up @@ -39,6 +44,7 @@ runs:
env:
VERSION: ${{ inputs.version }}
DISTROS: ${{ inputs.distros }}
INCLUDE_UI_IMAGE: ${{ inputs.include_ui_image }}
run: |
chmod +x ${{ github.action_path }}/main.sh
${{ github.action_path }}/main.sh
Expand Down
74 changes: 74 additions & 0 deletions actions/publish-dockers/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,18 @@ if [ -z "$VERSION" ]; then
exit 1
fi
DISTROS=${DISTROS:-}
INCLUDE_UI_IMAGE=${INCLUDE_UI_IMAGE:-true}

set -euo pipefail

is_truthy() {
case "$1" in
true | 1 | yes | on) return 0 ;;
false | 0 | no | off) return 1 ;;
*) return 1 ;;
esac
}

release_exists() {
local source=$1
releases=$(curl -s https://${source}.org/pypi/llama-stack/json | jq -r '.releases | keys[]')
Expand Down Expand Up @@ -110,6 +119,65 @@ EOF
fi
}

build_and_push_ui_docker_image() {
local version=$1

if ! command -v docker &>/dev/null; then
echo "docker CLI is required to publish llamastack/ui" >&2
exit 1
fi

local tag_suffix
if [ "$PYPI_SOURCE" = "testpypi" ]; then
tag_suffix="test-${version}"
else
tag_suffix="${version}"
fi

(
set -euo pipefail
local tmp_dir
tmp_dir=$(mktemp -d)
trap 'rm -rf "$tmp_dir"' EXIT

cat > "$tmp_dir/Containerfile" <<'EOF'
ARG UI_VERSION
FROM node:22.5.1-alpine

ENV NODE_ENV=production

# Install dumb-init for proper signal handling
RUN apk add --no-cache dumb-init

# Create non-root user for security
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs

# Install the UI package from npm
RUN npm install -g "llama-stack-ui@${UI_VERSION}"

USER nextjs

ENTRYPOINT ["dumb-init", "--"]
CMD ["llama-stack-ui"]
EOF

docker build \
--build-arg UI_VERSION="$version" \
-t "llamastack/ui:${tag_suffix}" \
-f "$tmp_dir/Containerfile" \
"$tmp_dir"
)

if [ "$PYPI_SOURCE" = "testpypi" ]; then
docker push "llamastack/ui:${tag_suffix}"
else
docker tag "llamastack/ui:${tag_suffix}" "llamastack/ui:latest"
docker push "llamastack/ui:${tag_suffix}"
docker push "llamastack/ui:latest"
fi
}

if [ -z "$DISTROS" ]; then
DISTROS=(starter meta-reference-gpu postgres-demo dell starter-gpu)
else
Expand All @@ -120,4 +188,10 @@ for distro in "${DISTROS[@]}"; do
build_and_push_docker $distro
done

if is_truthy "$INCLUDE_UI_IMAGE"; then
build_and_push_ui_docker_image "$VERSION"
else
echo "Skipping UI docker image publish (INCLUDE_UI_IMAGE=$INCLUDE_UI_IMAGE)"
fi

echo "Done"
35 changes: 31 additions & 4 deletions actions/release-final-package/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -182,13 +182,10 @@ add_bump_version_commit() {
perl -pi -e "s/llama-stack-client>=.*,/llama-stack-client>=$version\",/" pyproject.toml

if [ "$repo" == "stack" ]; then
# Handle both old (llama_stack/ui) and new (src/llama_stack_ui) paths
if [ -f "src/llama_stack_ui/package.json" ]; then
UI_PATH="src/llama_stack_ui"
elif [ -f "llama_stack/ui/package.json" ]; then
UI_PATH="llama_stack/ui"
else
echo "ERROR: Could not find llama_stack_ui/package.json" >&2
echo "ERROR: Could not find src/llama_stack_ui/package.json" >&2
exit 1
fi

Expand All @@ -203,6 +200,21 @@ add_bump_version_commit() {
fi
fi

# Update UI version for stack repo
if [ "$repo" == "stack" ]; then
if [ -f "src/llama_stack_ui/package.json" ]; then
UI_PATH="src/llama_stack_ui"
else
echo "ERROR: Could not find src/llama_stack_ui/package.json" >&2
exit 1
fi

if [ -n "$UI_PATH" ]; then
perl -pi -e "s/\"version\": \".*\"/\"version\": \"$version\"/" "$UI_PATH/package.json"
(cd "$UI_PATH" && npm install && npm run build)
fi
fi

if is_truthy "$should_update_lockfiles"; then
run_precommit_lockfile_update
fi
Expand Down Expand Up @@ -365,6 +377,21 @@ if ! is_truthy "$DRY_RUN"; then
--skip-existing \
--non-interactive \
"dist/*.whl" "dist/*.tar.gz"

if [ "$repo" == "stack" ] && [ -d "src/llama_stack_ui/dist" ]; then
echo "Uploading llama-stack-ui to npm"
cd src/llama_stack_ui/dist

if npm view llama-stack-ui@$RELEASE_VERSION version &>/dev/null; then
echo "Version $RELEASE_VERSION already exists on npm for llama-stack-ui, skipping publish"
else
npx yarn publish --access public --tag $RELEASE_VERSION --registry https://registry.npmjs.org/
fi

npx yarn tag add llama-stack-ui@$RELEASE_VERSION latest || true
cd ../../..
fi

cd ..
done
else
Expand Down
42 changes: 26 additions & 16 deletions actions/test-and-cut/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -175,27 +175,37 @@ build_packages() {
fi
fi

# TODO: this is dangerous use uvx toml-cli toml set project.version $VERSION instead of this
perl -pi -e "s/^version = .*$/version = \"$VERSION\"/" pyproject.toml
if [ "$repo" == "stack-client-typescript" ]; then
# TypeScript client package - update package.json version
perl -pi -e "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" package.json
npx yarn install
npx yarn build
else
# Python packages - update pyproject.toml version
# TODO: this is dangerous use uvx toml-cli toml set project.version $VERSION instead of this
perl -pi -e "s/^version = .*$/version = \"$VERSION\"/" pyproject.toml

if ! is_truthy "$LLAMA_STACK_ONLY"; then
# this one is only applicable for llama-stack-client-python
if [ -f "src/llama_stack_client/_version.py" ]; then
perl -pi -e "s/__version__ = .*$/__version__ = \"$VERSION\"/" src/llama_stack_client/_version.py
fi

if ! is_truthy "$LLAMA_STACK_ONLY"; then
# this one is only applicable for llama-stack-client-python
if [ -f "src/llama_stack_client/_version.py" ]; then
perl -pi -e "s/__version__ = .*$/__version__ = \"$VERSION\"/" src/llama_stack_client/_version.py
# this is applicable for llama-stack repo but we should not do it when
# LLAMA_STACK_ONLY is true
perl -pi -e "s/llama-stack-client>=.*/llama-stack-client>=$VERSION\",/" pyproject.toml
fi
if [ -f "package.json" ]; then

# Build UI package
if [ "$repo" == "stack" ]; then
echo "Building llama-stack-ui npm package..."
cd src/llama_stack_ui
perl -pi -e "s/\"version\": \".*\"/\"version\": \"$VERSION\"/" package.json
npx yarn install
npx yarn build
cd ../..
fi

# this is applicable for llama-stack repo but we should not do it when
# LLAMA_STACK_ONLY is true
perl -pi -e "s/llama-stack-client>=.*/llama-stack-client>=$VERSION\",/" pyproject.toml
fi

if [ "$repo" == "stack-client-typescript" ]; then
npx yarn install
npx yarn build
else
uv build -q
uv pip install dist/*.whl
fi
Expand Down
21 changes: 21 additions & 0 deletions actions/upload-packages-and-tag/main.sh
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,17 @@ for repo in "${REPOS[@]}"; do
PYPROJECT_VERSION=$(cat pyproject.toml | grep version)
echo "version to build: $PYPROJECT_VERSION"

# Build UI package
if [ "$repo" == "stack" ]; then
if [ -d "src/llama_stack_ui" ]; then
echo "Building llama-stack-ui npm package..."
cd src/llama_stack_ui
npx yarn install
npx yarn build
cd ../..
fi
fi

uv build -q
uv pip install dist/*.whl
fi
Expand All @@ -121,6 +132,16 @@ for repo in "${REPOS[@]}"; do
--repository-url https://test.pypi.org/legacy/ \
--skip-existing \
dist/*.whl dist/*.tar.gz

# Publish UI npm package
if [ "$repo" == "stack" ]; then
if [ -d "src/llama_stack_ui/dist" ]; then
echo "Uploading llama-stack-ui to npm"
cd src/llama_stack_ui/dist
npx yarn publish --access public --tag rc-$VERSION --registry https://registry.npmjs.org/
cd ../../..
fi
fi
fi

cd ..
Expand Down