Skip to content

Commit 78f74cc

Browse files
authored
feat: enhance CI pipeline with improved caching and multi-arch support (#360)
* feat: enhance CI pipeline with improved caching and multi-arch support Signed-off-by: liuhy <[email protected]> * feat: refactor Dockerfile to use Makefile for Rust library build Signed-off-by: liuhy <[email protected]> * feat: simplify Dockerfile by removing unnecessary directory creation Signed-off-by: liuhy <[email protected]> * feat: enhance Dockerfiles for cross-compilation and optimize CI pipeline Signed-off-by: liuhy <[email protected]> * feat: enhance cross-compilation support in Dockerfile for ARM64 and AMD64 Signed-off-by: liuhy <[email protected]> * feat: improve ARM64 cross-compilation process in Dockerfile Signed-off-by: liuhy <[email protected]> * feat: enhance Dockerfile to include detailed build output for Rust library Signed-off-by: liuhy <[email protected]> * feat: enhance Dockerfile to include detailed build output for Rust library Signed-off-by: liuhy <[email protected]> * feat: optimize CI pipeline with disk cleanup steps and improved build process Signed-off-by: liuhy <[email protected]> * feat: update CI configuration for ARM64 builds and improve Dockerfile syntax Signed-off-by: liuhy <[email protected]> * feat: simplify CI configuration by standardizing runner for ARM64 builds Signed-off-by: liuhy <[email protected]> * feat: enhance Dockerfile for ARM64 cross-compilation with OpenSSL configuration Signed-off-by: liuhy <[email protected]> * feat: enhance Dockerfile for ARM64 cross-compilation with OpenSSL configuration Signed-off-by: liuhy <[email protected]> * feat: enhance Dockerfile for ARM64 cross-compilation with OpenSSL configuration Signed-off-by: liuhy <[email protected]> * feat: enhance Dockerfile for ARM64 cross-compilation with OpenSSL configuration Signed-off-by: liuhy <[email protected]> * feat: update CI configuration for multi-architecture Docker image builds Signed-off-by: liuhy <[email protected]> * feat: update CI manifest tagging for pull requests with architecture suffix Signed-off-by: liuhy <[email protected]> * feat: remove architecture suffix from pull request tags in CI manifest Signed-off-by: liuhy <[email protected]> * feat: update CI manifest tagging for pull requests with architecture suffix Signed-off-by: liuhy <[email protected]> * feat: update CI manifest tagging for pull requests with architecture suffix Signed-off-by: liuhy <[email protected]> --------- Signed-off-by: liuhy <[email protected]>
1 parent be38a4b commit 78f74cc

File tree

6 files changed

+3849
-70
lines changed

6 files changed

+3849
-70
lines changed

.github/workflows/docker-publish.yml

Lines changed: 154 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -14,25 +14,37 @@ on:
1414
required: false
1515
type: boolean
1616
default: false
17-
skip_multiarch:
18-
description: "Skip multi-architecture build for faster CI"
17+
use_cross_compilation:
18+
description: "Use cross-compilation instead of emulation for ARM64"
1919
required: false
2020
type: boolean
21-
default: false
21+
default: true
2222
push:
2323
branches: [ "main" ]
24+
pull_request:
25+
paths:
26+
- ".github/workflows/docker-publish.yml"
27+
- "Dockerfile*"
28+
- "candle-binding/**"
29+
- "src/**"
30+
- "e2e-tests/llm-katan/**"
2431

2532
jobs:
26-
# Parallel job for building both images
27-
build_and_push:
33+
# Build job for multi-architecture Docker images
34+
build_multiarch:
2835
runs-on: ubuntu-latest
2936
permissions:
3037
contents: read
3138
packages: write
3239
strategy:
3340
matrix:
3441
image: [extproc, llm-katan]
35-
fail-fast: false # Continue building other images if one fails
42+
# Multi-architecture build strategy:
43+
# - AMD64: Native build on ubuntu-latest (fast)
44+
# - ARM64: Cross-compilation on ubuntu-latest (faster than emulation)
45+
# arch: ${{ github.event_name == 'pull_request' && fromJSON('["amd64"]') || fromJSON('["amd64", "arm64"]') }}
46+
arch: ["amd64", "arm64"]
47+
fail-fast: false
3648

3749
steps:
3850
- name: Check out the repo
@@ -41,8 +53,8 @@ jobs:
4153
- name: Set up Docker Buildx
4254
uses: docker/setup-buildx-action@v3
4355

44-
- name: Set up QEMU (only for multi-arch builds)
45-
if: inputs.skip_multiarch != true
56+
- name: Set up QEMU for cross-compilation
57+
if: matrix.arch == 'arm64'
4658
uses: docker/setup-qemu-action@v3
4759
with:
4860
platforms: arm64
@@ -54,91 +66,175 @@ jobs:
5466
username: ${{ github.actor }}
5567
password: ${{ secrets.GITHUB_TOKEN }}
5668

57-
- name: Generate date tag for nightly builds
58-
id: date
59-
if: inputs.is_nightly == true
60-
run: echo "date_tag=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
61-
62-
- name: Set lowercase repository owner
63-
run: echo "REPOSITORY_OWNER_LOWER=$(echo $GITHUB_REPOSITORY_OWNER | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
64-
65-
# Rust build cache for extproc - only use GitHub Actions cache for non-PR builds
66-
- name: Cache Rust dependencies (extproc only)
67-
if: matrix.image == 'extproc' && github.event_name != 'pull_request'
69+
# Enhanced Rust caching for extproc builds with incremental compilation
70+
- name: Cache Rust dependencies (extproc)
71+
if: matrix.image == 'extproc'
6872
uses: actions/cache@v4
6973
with:
7074
path: |
71-
~/.cargo/bin/
7275
~/.cargo/registry/index/
7376
~/.cargo/registry/cache/
7477
~/.cargo/git/db/
7578
candle-binding/target/
76-
key: ${{ runner.os }}-cargo-extproc-${{ hashFiles('**/Cargo.lock', '**/Cargo.toml') }}
79+
~/.rustup/
80+
key: ${{ runner.os }}-cargo-${{ matrix.arch }}-${{ hashFiles('candle-binding/Cargo.toml') }}-${{ hashFiles('candle-binding/Cargo.lock') }}-${{ hashFiles('candle-binding/src/**/*.rs') }}
7781
restore-keys: |
78-
${{ runner.os }}-cargo-extproc-
82+
${{ runner.os }}-cargo-${{ matrix.arch }}-${{ hashFiles('candle-binding/Cargo.toml') }}-${{ hashFiles('candle-binding/Cargo.lock') }}-
83+
${{ runner.os }}-cargo-${{ matrix.arch }}-${{ hashFiles('candle-binding/Cargo.toml') }}-
84+
${{ runner.os }}-cargo-${{ matrix.arch }}-
85+
${{ runner.os }}-cargo-
86+
87+
# Python caching for llm-katan builds
88+
- name: Cache Python dependencies (llm-katan)
89+
if: matrix.image == 'llm-katan'
90+
uses: actions/cache@v4
91+
with:
92+
path: |
93+
~/.cache/pip
94+
e2e-tests/llm-katan/.venv
95+
key: ${{ runner.os }}-pip-${{ matrix.arch }}-${{ hashFiles('e2e-tests/llm-katan/requirements.txt', 'e2e-tests/llm-katan/pyproject.toml') }}
96+
restore-keys: |
97+
${{ runner.os }}-pip-${{ matrix.arch }}-
98+
${{ runner.os }}-pip-
99+
100+
- name: Generate date tag for nightly builds
101+
id: date
102+
if: inputs.is_nightly == true
103+
run: echo "date_tag=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
104+
105+
- name: Set lowercase repository owner
106+
run: echo "REPOSITORY_OWNER_LOWER=$(echo $GITHUB_REPOSITORY_OWNER | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
79107

80-
# Set build context and dockerfile based on matrix
81108
- name: Set build parameters
82109
id: build-params
83110
run: |
111+
# Default to cross-compilation for ARM64 (always enabled for better performance)
112+
USE_CROSS_COMPILATION="${{ inputs.use_cross_compilation || 'true' }}"
113+
84114
if [ "${{ matrix.image }}" = "extproc" ]; then
85115
echo "context=." >> $GITHUB_OUTPUT
86-
echo "dockerfile=./Dockerfile.extproc" >> $GITHUB_OUTPUT
87-
echo "platforms=${{ inputs.skip_multiarch == true && 'linux/amd64' || 'linux/amd64,linux/arm64' }}" >> $GITHUB_OUTPUT
116+
if [ "$USE_CROSS_COMPILATION" = "true" ] && [ "${{ matrix.arch }}" = "arm64" ]; then
117+
echo "dockerfile=./Dockerfile.extproc.cross" >> $GITHUB_OUTPUT
118+
echo "platform=linux/${{ matrix.arch }}" >> $GITHUB_OUTPUT
119+
else
120+
echo "dockerfile=./Dockerfile.extproc" >> $GITHUB_OUTPUT
121+
echo "platform=linux/${{ matrix.arch }}" >> $GITHUB_OUTPUT
122+
fi
88123
elif [ "${{ matrix.image }}" = "llm-katan" ]; then
89124
echo "context=./e2e-tests/llm-katan" >> $GITHUB_OUTPUT
90125
echo "dockerfile=./e2e-tests/llm-katan/Dockerfile" >> $GITHUB_OUTPUT
91-
echo "platforms=${{ inputs.skip_multiarch == true && 'linux/amd64' || 'linux/amd64,linux/arm64' }}" >> $GITHUB_OUTPUT
126+
echo "platform=linux/${{ matrix.arch }}" >> $GITHUB_OUTPUT
92127
fi
93128
94-
# Extract version for llm-katan
95-
- name: Extract version from pyproject.toml
96-
id: version
97-
if: matrix.image == 'llm-katan'
98-
run: |
99-
VERSION=$(grep '^version = ' e2e-tests/llm-katan/pyproject.toml | sed 's/version = "\(.*\)"/\1/')
100-
echo "version=$VERSION" >> $GITHUB_OUTPUT
101-
102-
# Generate tags for extproc
103-
- name: Generate extproc tags
104-
id: extproc-tags
105-
if: matrix.image == 'extproc'
129+
- name: Generate tags
130+
id: tags
106131
run: |
107132
REPO_LOWER=$(echo $GITHUB_REPOSITORY_OWNER | tr '[:upper:]' '[:lower:]')
108-
if [ "${{ inputs.is_nightly }}" = "true" ]; then
109-
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/extproc:nightly-${{ steps.date.outputs.date_tag }}" >> $GITHUB_OUTPUT
110-
else
111-
if [ "${{ github.event_name }}" != "pull_request" ]; then
112-
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/extproc:${{ github.sha }},ghcr.io/${REPO_LOWER}/semantic-router/extproc:latest" >> $GITHUB_OUTPUT
113-
else
114-
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/extproc:${{ github.sha }}" >> $GITHUB_OUTPUT
115-
fi
116-
fi
133+
ARCH_SUFFIX="${{ matrix.arch }}"
117134
118-
# Generate tags for llm-katan
119-
- name: Generate llm-katan tags
120-
id: llm-katan-tags
121-
if: matrix.image == 'llm-katan'
122-
run: |
123-
REPO_LOWER=$(echo $GITHUB_REPOSITORY_OWNER | tr '[:upper:]' '[:lower:]')
124135
if [ "${{ inputs.is_nightly }}" = "true" ]; then
125-
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/llm-katan:nightly-${{ steps.date.outputs.date_tag }}" >> $GITHUB_OUTPUT
136+
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:nightly-${{ steps.date.outputs.date_tag }}-${ARCH_SUFFIX}" >> $GITHUB_OUTPUT
126137
else
127138
if [ "${{ github.event_name }}" != "pull_request" ]; then
128-
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/llm-katan:${{ github.sha }},ghcr.io/${REPO_LOWER}/semantic-router/llm-katan:latest,ghcr.io/${REPO_LOWER}/semantic-router/llm-katan:v${{ steps.version.outputs.version }}" >> $GITHUB_OUTPUT
139+
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:${{ github.sha }}-${ARCH_SUFFIX}" >> $GITHUB_OUTPUT
129140
else
130-
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/llm-katan:${{ github.sha }}" >> $GITHUB_OUTPUT
141+
echo "tags=ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:pr-${{ github.event.number }}-${ARCH_SUFFIX}" >> $GITHUB_OUTPUT
131142
fi
132143
fi
133144
134145
- name: Build and push ${{ matrix.image }} Docker image
146+
id: build
135147
uses: docker/build-push-action@v5
136148
with:
137149
context: ${{ steps.build-params.outputs.context }}
138150
file: ${{ steps.build-params.outputs.dockerfile }}
139-
platforms: ${{ steps.build-params.outputs.platforms }}
151+
platforms: ${{ steps.build-params.outputs.platform }}
140152
push: ${{ github.event_name != 'pull_request' }}
141153
load: ${{ github.event_name == 'pull_request' }}
142-
tags: ${{ matrix.image == 'extproc' && steps.extproc-tags.outputs.tags || steps.llm-katan-tags.outputs.tags }}
154+
tags: ${{ steps.tags.outputs.tags }}
155+
cache-from: |
156+
type=gha
157+
type=local,src=/tmp/.buildx-cache
158+
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
143159
build-args: |
144160
BUILDKIT_INLINE_CACHE=1
161+
CARGO_BUILD_JOBS=${{ github.event_name == 'pull_request' && '8' || '16' }}
162+
CARGO_INCREMENTAL=1
163+
RUSTC_WRAPPER=""
164+
CARGO_NET_GIT_FETCH_WITH_CLI=true
165+
BUILDKIT_PROGRESS=plain
166+
TARGETARCH=${{ matrix.arch }}
167+
# Optimize Rust compilation for ARM64
168+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_LINKER=aarch64-linux-gnu-gcc
169+
# Enable link-time optimization for release builds
170+
CARGO_PROFILE_RELEASE_LTO=thin
171+
CARGO_PROFILE_RELEASE_CODEGEN_UNITS=1
172+
# Use faster linker
173+
CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=-fuse-ld=lld"
174+
CARGO_TARGET_AARCH64_UNKNOWN_LINUX_GNU_RUSTFLAGS="-C link-arg=-fuse-ld=lld"
175+
176+
# Create multi-arch manifest for final images
177+
create_manifest:
178+
needs: build_multiarch
179+
runs-on: ubuntu-latest
180+
permissions:
181+
contents: read
182+
packages: write
183+
if: github.event_name != 'pull_request'
184+
strategy:
185+
matrix:
186+
image: [extproc, llm-katan]
187+
188+
steps:
189+
- name: Log in to GitHub Container Registry
190+
uses: docker/login-action@v3
191+
with:
192+
registry: ghcr.io
193+
username: ${{ github.actor }}
194+
password: ${{ secrets.GITHUB_TOKEN }}
195+
196+
- name: Set lowercase repository owner
197+
run: echo "REPOSITORY_OWNER_LOWER=$(echo $GITHUB_REPOSITORY_OWNER | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
198+
199+
- name: Generate date tag for nightly builds
200+
id: date
201+
if: inputs.is_nightly == true
202+
run: echo "date_tag=$(date +'%Y%m%d')" >> $GITHUB_OUTPUT
203+
204+
- name: Create and push manifest
205+
run: |
206+
REPO_LOWER=$(echo $GITHUB_REPOSITORY_OWNER | tr '[:upper:]' '[:lower:]')
207+
208+
# Create manifest for the specific image
209+
if [ "${{ inputs.is_nightly }}" = "true" ]; then
210+
TAG="nightly-${{ steps.date.outputs.date_tag }}"
211+
else
212+
if [ "${{ github.event_name }}" != "pull_request" ]; then
213+
TAG="${{ github.sha }}"
214+
else
215+
TAG="pr-${{ github.event.number }}"
216+
fi
217+
fi
218+
219+
# Create and push manifest by combining architecture-specific images
220+
docker buildx imagetools create \
221+
--tag ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:${TAG} \
222+
ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:${TAG}-amd64 \
223+
ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:${TAG}-arm64
224+
225+
# Also tag as latest for non-nightly builds
226+
if [ "${{ inputs.is_nightly }}" != "true" ]; then
227+
docker buildx imagetools create \
228+
--tag ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:latest \
229+
ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:${TAG}-amd64 \
230+
ghcr.io/${REPO_LOWER}/semantic-router/${{ matrix.image }}:${TAG}-arm64
231+
fi
232+
233+
- name: Build summary
234+
if: always()
235+
run: |
236+
if [ "${{ job.status }}" = "success" ]; then
237+
echo "::notice title=Build Success::${{ matrix.image }} multi-arch manifest created successfully"
238+
else
239+
echo "::error title=Build Failed::${{ matrix.image }} build failed"
240+
fi

.github/workflows/k8s-integration-test.yml

Lines changed: 57 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,32 @@ jobs:
8888
- name: Checkout code
8989
uses: actions/checkout@v4
9090

91+
- name: Free up disk space before build
92+
run: |
93+
echo "=== Initial disk usage ==="
94+
df -h
95+
echo ""
96+
echo "=== Cleaning up system ==="
97+
# Remove unnecessary packages and caches
98+
sudo apt-get clean
99+
sudo apt-get autoremove -y
100+
sudo rm -rf /var/lib/apt/lists/*
101+
sudo rm -rf /tmp/*
102+
sudo rm -rf /var/tmp/*
103+
104+
# Clean Docker system
105+
docker system prune -af --volumes
106+
107+
# Remove large unnecessary files/directories
108+
sudo rm -rf /usr/share/dotnet
109+
sudo rm -rf /usr/local/lib/android
110+
sudo rm -rf /opt/ghc
111+
sudo rm -rf /opt/hostedtoolcache/CodeQL
112+
113+
echo ""
114+
echo "=== Disk usage after cleanup ==="
115+
df -h
116+
91117
- name: Set up Docker Buildx
92118
uses: docker/setup-buildx-action@v3
93119

@@ -115,6 +141,20 @@ jobs:
115141
kind load docker-image ghcr.io/vllm-project/semantic-router/extproc:test --name semantic-router-test
116142
echo "Image loaded successfully!"
117143
144+
- name: Clean up after image build
145+
run: |
146+
echo "=== Cleaning up Docker build artifacts ==="
147+
# Remove build cache and unused images
148+
docker builder prune -af
149+
docker image prune -af
150+
151+
# Keep only the images we need
152+
docker images
153+
154+
echo ""
155+
echo "=== Disk usage after build cleanup ==="
156+
df -h
157+
118158
- name: Verify cluster
119159
run: |
120160
kubectl cluster-info
@@ -181,7 +221,7 @@ jobs:
181221
182222
# Reduce resource requirements for CI testing and set imagePullPolicy
183223
patches:
184-
# Patch for main container
224+
# Patch for main container - reduced resources for CI
185225
- patch: |-
186226
- op: replace
187227
path: /spec/template/spec/containers/0/resources/requests/memory
@@ -239,6 +279,22 @@ jobs:
239279
240280
echo "✓ Connectivity check completed"
241281
282+
- name: Final disk cleanup before deployment
283+
run: |
284+
echo "=== Final cleanup before deployment ==="
285+
# Clean up any remaining build artifacts
286+
docker system prune -f
287+
288+
# Clear system caches
289+
sudo sync
290+
echo 3 | sudo tee /proc/sys/vm/drop_caches > /dev/null || true
291+
292+
echo "=== Final disk usage ==="
293+
df -h
294+
295+
echo "=== Available memory ==="
296+
free -h
297+
242298
- name: Deploy to kind cluster
243299
run: |
244300
echo "Deploying semantic-router to kind cluster..."

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Rust
22
target/
33
**/*.rs.bk
4-
Cargo.lock
4+
# Note: Cargo.lock should be committed for applications and workspace roots
5+
# Cargo.lock
56

67
# Python
78
*.pyc

0 commit comments

Comments
 (0)