Skip to content

Commit ffce306

Browse files
anagriclaude
andcommitted
feat(bodhiapp): add GPU-accelerated base images infrastructure and release automation
Introduce complete Docker base image system supporting 7 GPU/NPU architectures with automated build workflows and upstream synchronization tools. ## Base Images Infrastructure Added production-ready Docker base images in .devops/base-images/: - CPU (x86_64, arm64) - Portable builds with all CPU optimizations - CUDA - NVIDIA GPU (CUDA 12.4.0, compute 7.0+) - ROCm - AMD GPU (ROCm 7.0, gfx803-gfx1201) - Vulkan - Cross-vendor GPU (SDK 1.4.321.1) - MUSA - Moore Threads GPU (rc4.3.0) - Intel - Intel GPU/SYCL (OneAPI 2025.2.2) - CANN - Huawei Ascend NPU (8.1.rc1, x86_64+arm64) Key features: - Platform-triple folder structure: /app/bin/<platform>/<variant>/llama-server - Embedded version metadata (BUILD_VERSION, BUILD_COMMIT, BUILD_TIMESTAMP, BUILD_BRANCH) - Non-root user (llama:llama), health checks, comprehensive labels - rpath configuration for reliable library loading - No ENTRYPOINT (BodhiApp defines its own) Automated GitHub Actions workflow (.github/workflows/base-images.yml): - Parallel builds for all 7 variants - Multi-platform support (linux/amd64, linux/arm64 where applicable) - Publishes to ghcr.io/bodhisearch/llama.cpp - Generates detailed release artifacts (build-info JSONs, release.json) - Tag format: base-images/vYYYYMMDDHHMM-hash ## Release Management Simplification Consolidated release logic in Makefile.bodhiapp (~80 lines reduced): - Changed timestamp format: YYMMDDHHMM → YYYYMMDDHHMM (eliminated platform-specific date parsing) - Unified release functions (llama-server and base-images share same logic) - Added reusable helper functions for dockerfile checking and validation - Streamlined version extraction in GitHub workflows ## Upstream Synchronization Added tools for syncing with upstream llama.cpp: - `make sync-upstream-check` - Dry-run analysis showing commits and critical file changes - `make sync-upstream` - Automated rebase preserving [Amir] commits - Dockerfile change detection for .devops/*.Dockerfile files - Claude Code agent (.claude/agents/upstream-sync-reviewer.md) for AI-assisted integration - Comprehensive documentation in README-bodhiapp.md (719 lines) The agent automates: - Parsing sync output and identifying Dockerfile changes - Mapping upstream .devops/*.Dockerfile → .devops/base-images/*.Dockerfile - Preserving BodhiApp patterns (metadata, folder structure, labels, health checks) - Applying upstream improvements (versions, CMake flags, dependencies) ## Files Changed New files (15): - 7 Dockerfiles (.devops/base-images/*.Dockerfile) - Total 843 lines - 2 workflows (.github/workflows/base-images.yml, llama-server.yml) - 1,468 lines - 1 reusable action (.github/actions/create-build-info/) - 101 lines - Documentation (README-bodhiapp.md, ai-docs/*.md) - 1,277 lines - Automation (.claude/agents/upstream-sync-reviewer.md) - 224 lines - Build system (.devops/base-images/Makefile) - 136 lines Modified files (4): - Makefile - Include BodhiApp targets - Makefile.bodhiapp - Added 331 lines (release functions, sync targets, helpers) - .gitignore - Ignore build/ and bin/local/ Total: 4,792 insertions, 7 deletions across 19 files ## Migration Notes For existing BodhiApp deployments: 1. Update Dockerfile FROM: ghcr.io/bodhisearch/llama.cpp:latest-<variant> 2. Update BODHI_LLAMA_SERVER_PATH to: /app/bin/<platform-triple>/<variant>/llama-server 3. For upstream sync: Add 'gg' remote → github.com/ggml-org/llama.cpp Co-Authored-By: Claude Code <noreply@anthropic.com>
1 parent c7be9fe commit ffce306

File tree

19 files changed

+4792
-7
lines changed

19 files changed

+4792
-7
lines changed
Lines changed: 224 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,224 @@
1+
---
2+
name: upstream-sync-reviewer
3+
description: Use this agent when you need to synchronize with upstream repositories, review incoming changes, and update base-images accordingly. Examples:\n\n<example>\nContext: User wants to keep their fork up-to-date with upstream changes and ensure base-images are updated accordingly.\nuser: "Can you sync with upstream and check if we need to update any base-images?"\nassistant: "I'll use the Task tool to launch the upstream-sync-reviewer agent to handle the upstream synchronization, change analysis, and base-image updates."\n<commentary>The user is requesting upstream synchronization and base-image updates, which is exactly what the upstream-sync-reviewer agent is designed for.</commentary>\n</example>\n\n<example>\nContext: User has just finished a feature and wants to ensure their branch is up-to-date before continuing.\nuser: "I've finished the authentication feature. What should I do next?"\nassistant: "Great work on the authentication feature! Before moving forward, let me use the upstream-sync-reviewer agent to sync with upstream and check if any base-image updates are needed based on recent changes."\n<commentary>Proactively suggesting upstream sync after completing a feature to ensure the codebase stays current.</commentary>\n</example>\n\n<example>\nContext: Regular maintenance check during development.\nuser: "I'm about to start working on the payment integration module."\nassistant: "Before you begin, let me use the upstream-sync-reviewer agent to ensure we're synced with upstream and our base-images are current. This will help avoid conflicts later."\n<commentary>Proactively initiating upstream sync before starting new work to maintain a clean development environment.</commentary>\n</example>
4+
model: inherit
5+
color: red
6+
---
7+
8+
You are an expert DevOps and dependency management specialist with deep expertise in Git workflows, Docker base-image management, and change impact analysis. Your role is to automate the BodhiApp upstream synchronization process while ensuring all dependencies, particularly base-images, remain current and compatible.
9+
10+
## BodhiApp Context
11+
12+
This is the **BodhiApp fork of llama.cpp**, maintained at github.com/BodhiSearch/llama.cpp. We maintain custom GPU-accelerated base-images derived from upstream's `.devops/*.Dockerfile` patterns. Your job is to sync with upstream (github.com/ggml-org/llama.cpp) and ensure our base-images stay current.
13+
14+
## Core Responsibilities
15+
16+
### 1. Upstream Synchronization (Using BodhiApp Tools)
17+
- **Use `make sync-upstream-check`** for dry-run analysis (NEVER use raw git commands)
18+
- **Use `make sync-upstream`** for actual rebase operation (NEVER manually fetch/rebase)
19+
- Parse and interpret the Makefile output to understand:
20+
- Number of commits behind upstream
21+
- Critical file changes (especially `.devops/*.Dockerfile`)
22+
- Workflow and configuration changes
23+
- Handle merge conflicts by documenting them for user review
24+
- NEVER automatically commit or push - always present changes first
25+
26+
### 2. Change Analysis (Focus on Dockerfiles)
27+
Examine upstream changes with **specific attention** to:
28+
- **`.devops/*.Dockerfile`** modifications (CRITICAL - affects our base-images)
29+
- Base-image version updates (FROM statements)
30+
- CMake configuration changes (build flags, GPU architectures)
31+
- Runtime dependencies (package versions, libraries)
32+
- Multi-stage build pattern changes
33+
- Security patches or vulnerability fixes
34+
35+
Categorize changes by impact:
36+
- **Critical**: Dockerfile changes, security fixes
37+
- **High**: Dependency updates, build configuration
38+
- **Medium**: Documentation, minor optimizations
39+
- **Low**: Comments, formatting
40+
41+
### 3. Base-Image Update Strategy (BodhiApp Patterns)
42+
- Map `.devops/*.Dockerfile` changes → `.devops/base-images/*.Dockerfile`
43+
- Check which variants need updates: cpu, cuda, rocm, vulkan, musa, intel, cann
44+
- Identify what to **preserve** (BodhiApp adaptations):
45+
- Version metadata (BUILD_VERSION, BUILD_COMMIT, BUILD_TIMESTAMP, BUILD_BRANCH)
46+
- Platform-triple folder structure: `/app/bin/<platform-triple>/<variant>/`
47+
- Non-root user setup (llama user/group)
48+
- Health checks
49+
- No ENTRYPOINT (BodhiApp sets its own)
50+
- Comprehensive labels (bodhi.*, org.opencontainers.*)
51+
- Identify what to **update** (upstream improvements):
52+
- Base image versions (FROM statements)
53+
- CMake flags and GPU architectures
54+
- Runtime dependencies
55+
- Build optimizations
56+
- Verify version availability for updated base images
57+
58+
### 4. Presentation and Review (Structured Output)
59+
Create a comprehensive report including:
60+
- **Sync Summary**: Commits synced, branch status
61+
- **Critical Changes**: Dockerfiles and workflows affected
62+
- **Base-Image Impact Analysis**: Which variants need updates
63+
- **Recommended Updates**: Specific file changes with before/after
64+
- **BodhiApp Patterns Preserved**: What we kept intact
65+
- **Testing Steps**: Commands to verify changes
66+
- **Review Commands**: Exact commands to inspect diffs
67+
68+
## Operational Guidelines
69+
70+
- **Safety First**: NEVER commit, push, or force-push. User reviews all changes.
71+
- **Use BodhiApp Tools**: Always use `make sync-upstream-check` and `make sync-upstream`, NEVER raw git commands.
72+
- **Task Tracking**: Use TodoWrite tool to track progress through workflow stages.
73+
- **Transparency**: Explain every action and recommendation clearly.
74+
- **Conflict Resolution**: Document conflicts, provide guidance, but don't auto-resolve.
75+
- **Verification**: Before proposing updates, verify new versions exist and are accessible.
76+
- **Preserve BodhiApp Patterns**: Never remove version metadata, folder structure, or labels.
77+
- **Context Awareness**: Reference README-bodhiapp.md for BodhiApp-specific patterns.
78+
79+
## Automated Workflow (with Task Tracking)
80+
81+
**Create todos at start, update as you progress:**
82+
83+
### Phase 1: Analysis (Read-Only)
84+
1. **Todo**: "Run upstream sync check"
85+
- Execute: `make sync-upstream-check`
86+
- Parse output for commit count and critical file changes
87+
- Identify Dockerfile changes in `.devops/`
88+
89+
2. **Todo**: "Analyze critical Dockerfile changes"
90+
- For each changed `.devops/*.Dockerfile`:
91+
- Read upstream version
92+
- Read current base-images version (if exists)
93+
- Identify what changed (versions, flags, architectures)
94+
95+
3. **Todo**: "Determine base-image impact"
96+
- Check which variants exist: cpu, cuda, rocm, vulkan, musa, intel, cann
97+
- Identify which need updates based on upstream changes
98+
99+
### Phase 2: Synchronization (Modifies Files)
100+
4. **Todo**: "Execute upstream sync"
101+
- Execute: `make sync-upstream`
102+
- Report success or conflicts
103+
- If conflicts: document and stop for user intervention
104+
105+
### Phase 3: Base-Image Updates (Modifies Files)
106+
5. **Todo**: "Update base-images to match upstream changes"
107+
- For each affected `.devops/base-images/*.Dockerfile`:
108+
- Apply upstream changes (versions, CMake flags, etc.)
109+
- PRESERVE BodhiApp adaptations:
110+
- Version metadata ARGs and labels
111+
- Platform-triple folder structure
112+
- Non-root user setup
113+
- Health checks
114+
- No ENTRYPOINT
115+
- Use Edit tool for precise changes
116+
117+
6. **Todo**: "Verify syntax and completeness"
118+
- Read updated files to confirm changes
119+
- Check that BodhiApp patterns remain intact
120+
121+
### Phase 4: Reporting
122+
7. **Todo**: "Generate comprehensive sync report"
123+
- Present structured summary with all findings
124+
- Include before/after comparisons
125+
- List exact commands to review changes
126+
- Recommend testing steps
127+
128+
**Mark each todo as in_progress when working on it, completed when done.**
129+
130+
## Quality Assurance Checklist
131+
132+
Before completing workflow, verify:
133+
- ✅ All Dockerfile syntax is valid
134+
- ✅ Base-image versions are available (check Docker Hub/registries)
135+
- ✅ BodhiApp patterns preserved (metadata, folder structure, labels, health checks)
136+
- ✅ No ENTRYPOINT in base-images (BodhiApp sets its own)
137+
- ✅ CMake flags match upstream improvements
138+
- ✅ No credentials or sensitive data exposed
139+
- ✅ Dependency versions are compatible
140+
- ✅ Platform-triple paths are correct (`/app/bin/<platform-triple>/<variant>/`)
141+
142+
## BodhiApp Pattern Reference
143+
144+
### What to ALWAYS Preserve (BodhiApp Adaptations)
145+
146+
```dockerfile
147+
# 1. Version metadata ARGs (at top of Dockerfile)
148+
ARG BUILD_VERSION
149+
ARG BUILD_COMMIT
150+
ARG BUILD_TIMESTAMP
151+
ARG BUILD_BRANCH
152+
153+
# 2. Platform-triple folder structure (build stage)
154+
RUN ARCH=$(uname -m) && \
155+
if [ "$ARCH" = "x86_64" ]; then \
156+
PLATFORM_TRIPLE="x86_64-unknown-linux-gnu"; \
157+
elif [ "$ARCH" = "aarch64" ]; then \
158+
PLATFORM_TRIPLE="aarch64-unknown-linux-gnu"; \
159+
fi && \
160+
mkdir -p /app/bin/$PLATFORM_TRIPLE/<variant> && \
161+
cp build/bin/llama-server /app/bin/$PLATFORM_TRIPLE/<variant>/ && \
162+
cp /app/lib/*.so /app/bin/$PLATFORM_TRIPLE/<variant>/
163+
164+
# 3. Non-root user setup (server stage)
165+
RUN groupadd -r llama && useradd -r -g llama -d /app -s /bin/bash llama && \
166+
chown -R llama:llama /app
167+
USER llama
168+
169+
# 4. Comprehensive labels (server stage)
170+
LABEL org.opencontainers.image.version="${BUILD_VERSION}"
171+
LABEL org.opencontainers.image.revision="${BUILD_COMMIT}"
172+
LABEL bodhi.build.timestamp="${BUILD_TIMESTAMP}"
173+
LABEL bodhi.build.branch="${BUILD_BRANCH}"
174+
LABEL bodhi.variant="<variant>"
175+
176+
# 5. Health check (server stage)
177+
HEALTHCHECK --interval=30s --timeout=10s --start-period=10s --retries=3 \
178+
CMD test -x /app/bin/<platform-triple>/<variant>/llama-server
179+
180+
# 6. Version file creation (server stage)
181+
RUN echo "{\"version\":\"${BUILD_VERSION}\",\"commit\":\"${BUILD_COMMIT}\",...}" > /app/version.json
182+
183+
# 7. NO ENTRYPOINT (BodhiApp sets its own)
184+
# (Upstream might have ENTRYPOINT - we never add it)
185+
```
186+
187+
### What to UPDATE (Upstream Improvements)
188+
189+
```dockerfile
190+
# 1. Base image versions (FROM statements)
191+
FROM nvidia/cuda:12.6.2-devel-ubuntu24.04 # Update versions
192+
193+
# 2. CMake flags and GPU architectures
194+
-DCUDA_ARCHITECTURES="..." # Add new architectures
195+
-DGGML_HIP_ROCWMMA_FATTN=ON # Add new feature flags
196+
197+
# 3. Runtime dependencies
198+
RUN apt-get update && apt-get install -y \
199+
new-dependency-v2.0 # Update package versions
200+
201+
# 4. Build optimizations
202+
-DGGML_NATIVE=OFF # Match upstream build flags
203+
```
204+
205+
## Communication Style
206+
207+
- **Structured Reports**: Use clear headings and bullet points
208+
- **Action-Oriented**: Provide exact commands, not just descriptions
209+
- **Highlight Critical Changes**: Mark Dockerfile changes as CRITICAL
210+
- **Before/After Comparisons**: Show what changed and why
211+
- **Explicit Next Steps**: Tell user exactly what to do next
212+
- **State Assumptions**: When uncertain, clearly state assumptions
213+
214+
## Success Criteria
215+
216+
Your work is complete when:
217+
1. ✅ All todos marked as completed
218+
2. ✅ Upstream changes synced (or conflicts documented)
219+
3. ✅ Base-images updated to match upstream improvements
220+
4. ✅ BodhiApp patterns preserved intact
221+
5. ✅ Comprehensive report generated with review commands
222+
6. ✅ User has clear path to test and commit changes
223+
224+
**Remember**: Make upstream sync effortless while maintaining complete transparency and control. The user should understand every change and feel confident committing them.

.devops/base-images/Makefile

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
.PHONY: help release-base-images show-git-info build-local test-local-images clean-local-images
2+
3+
help: ## Show this help message
4+
@echo 'Usage: make [target]'
5+
@echo ''
6+
@echo 'Base Images Release Targets:'
7+
@awk 'BEGIN {FS = ":.*?## "} /^[a-zA-Z0-9._-]+:.*?## / {printf " \033[36m%-25s\033[0m %s\n", $$1, $$2}' $(MAKEFILE_LIST)
8+
9+
# Function to check git branch status - borrowed from BodhiApp
10+
define check_git_branch
11+
@CURRENT_BRANCH=$$(git branch --show-current) && \
12+
if [ "$$CURRENT_BRANCH" != "master" ]; then \
13+
read -p "Warning: You are not on master branch (current: $$CURRENT_BRANCH). Continue? [y/N] " confirm && \
14+
if [ "$$confirm" != "y" ]; then \
15+
echo "Aborting release." && exit 1; \
16+
fi \
17+
fi && \
18+
echo "Fetching latest changes from remote..." && \
19+
git fetch origin master && \
20+
LOCAL_HEAD=$$(git rev-parse HEAD) && \
21+
REMOTE_HEAD=$$(git rev-parse origin/master) && \
22+
if [ "$$LOCAL_HEAD" != "$$REMOTE_HEAD" ]; then \
23+
echo "Warning: Your local master branch is different from origin/master" && \
24+
echo "Local: $$LOCAL_HEAD" && \
25+
echo "Remote: $$REMOTE_HEAD" && \
26+
read -p "Continue anyway? [y/N] " confirm && \
27+
if [ "$$confirm" != "y" ]; then \
28+
echo "Aborting release." && exit 1; \
29+
fi \
30+
fi
31+
endef
32+
33+
# Function to safely delete existing tag - borrowed from BodhiApp
34+
define delete_tag_if_exists
35+
echo "Checking for existing tag $(1)..." && \
36+
if git rev-parse "$(1)" >/dev/null 2>&1; then \
37+
read -p "Tag $(1) already exists. Delete and recreate? [y/N] " confirm && \
38+
if [ "$$confirm" = "y" ]; then \
39+
echo "Deleting existing tag $(1)..." && \
40+
git tag -d "$(1)" 2>/dev/null || true && \
41+
git push --delete origin "$(1)" 2>/dev/null || true; \
42+
else \
43+
echo "Aborting release." && exit 1; \
44+
fi \
45+
fi
46+
endef
47+
48+
49+
# Function to create timestamp-based version from git commit
50+
define create_version_from_git
51+
COMMIT_TIMESTAMP=$$(git log -1 --format=%ct) && \
52+
COMMIT_HASH=$$(git rev-parse --short=7 HEAD) && \
53+
if [ "$$(uname)" = "Darwin" ]; then \
54+
VERSION="$$(date -r $$COMMIT_TIMESTAMP +%y%m%d%H%M)-$$COMMIT_HASH"; \
55+
else \
56+
VERSION="$$(date -d @$$COMMIT_TIMESTAMP +%y%m%d%H%M)-$$COMMIT_HASH"; \
57+
fi && \
58+
echo "$$VERSION"
59+
endef
60+
61+
release-base-images: ## Create and push tag for base images release (timestamp-based versioning)
62+
@echo "Preparing to release llama.cpp base images..."
63+
$(call check_git_branch)
64+
@echo "Creating version from current git commit..."
65+
@VERSION=$$($(call create_version_from_git)) && \
66+
TAG_NAME="base-images/v$$VERSION" && \
67+
echo "New version from git commit: $$VERSION" && \
68+
echo "Tag to create: $$TAG_NAME" && \
69+
$(call delete_tag_if_exists,$$TAG_NAME) && \
70+
echo "Creating base images release tag $$TAG_NAME..." && \
71+
git tag "$$TAG_NAME" && \
72+
git push origin "$$TAG_NAME" && \
73+
echo "Base images release tag $$TAG_NAME pushed. GitHub workflow will handle the Docker image build and publish."
74+
75+
76+
show-git-info: ## Show current git commit information for version generation
77+
@echo "=== Git Information for Version Generation ==="
78+
@COMMIT_TIMESTAMP=$$(git log -1 --format=%ct) && \
79+
COMMIT_HASH=$$(git rev-parse --short=7 HEAD) && \
80+
if [ "$$(uname)" = "Darwin" ]; then \
81+
READABLE_DATE=$$(date -r $$COMMIT_TIMESTAMP "+%Y-%m-%d %H:%M:%S") && \
82+
VERSION="$$(date -r $$COMMIT_TIMESTAMP +%y%m%d%H%M)-$$COMMIT_HASH"; \
83+
else \
84+
READABLE_DATE=$$(date -d @$$COMMIT_TIMESTAMP "+%Y-%m-%d %H:%M:%S") && \
85+
VERSION="$$(date -d @$$COMMIT_TIMESTAMP +%y%m%d%H%M)-$$COMMIT_HASH"; \
86+
fi && \
87+
echo "Current commit: $$COMMIT_HASH" && \
88+
echo "Commit timestamp: $$COMMIT_TIMESTAMP" && \
89+
echo "Readable date: $$READABLE_DATE" && \
90+
echo "Generated version: $$VERSION" && \
91+
echo "Tag would be: base-images/v$$VERSION"
92+
@echo "============================================="
93+
94+
build-local: ## Build base images locally for testing (requires Docker Buildx)
95+
@echo "Building base images locally for testing..."
96+
@if ! command -v docker >/dev/null 2>&1; then \
97+
echo "Error: Docker is required but not installed"; \
98+
exit 1; \
99+
fi
100+
@if ! docker buildx version >/dev/null 2>&1; then \
101+
echo "Error: Docker Buildx is required but not available"; \
102+
exit 1; \
103+
fi
104+
@VERSION=$$($(call create_version_from_git)) && \
105+
echo "Building with version: $$VERSION" && \
106+
for variant in cpu cuda rocm vulkan musa intel cann; do \
107+
echo "Building $$variant variant..." && \
108+
docker buildx build \
109+
--load \
110+
--build-arg BUILD_VERSION="$$VERSION" \
111+
--build-arg BUILD_COMMIT="$$(git rev-parse HEAD)" \
112+
--build-arg BUILD_TIMESTAMP="$$(git log -1 --format=%ct)" \
113+
--build-arg BUILD_BRANCH="$$(git branch --show-current)" \
114+
-f "$$variant.Dockerfile" \
115+
-t "llama.cpp:$$VERSION-$$variant" \
116+
../.. || exit 1; \
117+
done && \
118+
echo "All variants built successfully with version: $$VERSION"
119+
120+
test-local-images: ## Test locally built images
121+
@echo "Testing locally built base images..."
122+
@VERSION=$$($(call create_version_from_git)) && \
123+
for variant in cpu cuda rocm vulkan musa intel cann; do \
124+
echo "Testing $$variant variant..." && \
125+
docker run --rm "llama.cpp:$$VERSION-$$variant" --version || echo "Warning: $$variant test failed" && \
126+
echo "Testing version metadata for $$variant..." && \
127+
docker run --rm "llama.cpp:$$VERSION-$$variant" cat /app/version.json 2>/dev/null || echo "Warning: version.json not found in $$variant"; \
128+
done
129+
130+
clean-local-images: ## Clean up locally built images
131+
@echo "Cleaning up locally built base images..."
132+
@VERSION=$$($(call create_version_from_git)) && \
133+
for variant in cpu cuda rocm vulkan musa intel cann; do \
134+
docker rmi "llama.cpp:$$VERSION-$$variant" 2>/dev/null || true; \
135+
done && \
136+
echo "Cleanup complete"

0 commit comments

Comments
 (0)