Skip to content

Commit 470a506

Browse files
committed
add github workflow
1 parent ec3a270 commit 470a506

File tree

2 files changed

+244
-0
lines changed

2 files changed

+244
-0
lines changed
Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
name: Docker
2+
3+
on:
4+
push:
5+
branches: [ "main" ]
6+
tags: [ 'v*.*.*' ]
7+
8+
env:
9+
REGISTRY: ghcr.io
10+
IMAGE_NAME: ${{ github.repository }}
11+
12+
jobs:
13+
build:
14+
runs-on: ubuntu-latest
15+
permissions:
16+
contents: write
17+
packages: write
18+
id-token: write
19+
20+
timeout-minutes: 600
21+
22+
steps:
23+
- name: Free Disk Space (Ubuntu)
24+
uses: jlumbroso/free-disk-space@main
25+
with:
26+
tool-cache: true
27+
android: true
28+
dotnet: true
29+
haskell: true
30+
large-packages: true
31+
swap-storage: false
32+
docker-images: false
33+
34+
- name: Checkout repository
35+
uses: actions/checkout@v3
36+
with:
37+
submodules: recursive
38+
39+
- name: Add Swap
40+
run: |
41+
SWAP_FILE="/mnt/swapfile"
42+
43+
swapon --show
44+
echo "Trying to disable and remove existing swap if needed..."
45+
if swapon --show=NAME | grep -q "$SWAP_FILE"; then
46+
echo "Disabling existing swap at $SWAP_FILE..."
47+
sudo swapoff "$SWAP_FILE"
48+
fi
49+
50+
if [ -f "$SWAP_FILE" ]; then
51+
echo "Removing existing file at $SWAP_FILE..."
52+
sudo rm -f "$SWAP_FILE"
53+
fi
54+
55+
echo "Creating new 32G swap file..."
56+
sudo dd if=/dev/zero of=$SWAP_FILE bs=1G count=32
57+
sudo chmod 600 "$SWAP_FILE"
58+
sudo mkswap "$SWAP_FILE"
59+
sudo swapon "$SWAP_FILE"
60+
61+
echo "Final swap status:"
62+
swapon --show
63+
free -h
64+
65+
- name: Install cosign
66+
if: github.event_name != 'pull_request'
67+
uses: sigstore/[email protected]
68+
69+
- name: Setup Docker buildx
70+
uses: docker/setup-buildx-action@v3
71+
72+
- name: Docker cache - restore
73+
uses: actions/cache@v4
74+
with:
75+
path: /tmp/.buildx-cache
76+
key: buildx-${{ runner.os }}-${{ github.sha }}
77+
restore-keys: |
78+
buildx-${{ runner.os }}-
79+
80+
- name: Log into registry ${{ env.REGISTRY }}
81+
if: github.event_name != 'pull_request'
82+
uses: docker/login-action@v3
83+
with:
84+
registry: ${{ env.REGISTRY }}
85+
username: ${{ github.actor }}
86+
password: ${{ secrets.GITHUB_TOKEN }}
87+
88+
- name: Extract Docker metadata
89+
id: meta
90+
uses: docker/metadata-action@v5
91+
with:
92+
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
93+
94+
- name: Build and push Docker image
95+
id: build-and-push
96+
uses: docker/build-push-action@v5
97+
with:
98+
context: .
99+
push: ${{ github.event_name != 'pull_request' }}
100+
tags: ${{ steps.meta.outputs.tags }}
101+
labels: ${{ steps.meta.outputs.labels }}
102+
cache-from: type=local,src=/tmp/.buildx-cache
103+
cache-to: type=local,dest=/tmp/.buildx-cache,mode=max
104+
105+
- name: Sign the published Docker image
106+
if: ${{ github.event_name != 'pull_request' }}
107+
env:
108+
TAGS: ${{ steps.meta.outputs.tags }}
109+
DIGEST: ${{ steps.build-and-push.outputs.digest }}
110+
run: echo "${TAGS}" | xargs -I {} cosign sign --yes {}@${DIGEST}
111+
112+
- name: Export wheel from image
113+
run: |
114+
CONTAINER_TAG=$(echo "${{ steps.meta.outputs.tags }}" | head -n1)
115+
CONTAINER_ID=$(docker create $CONTAINER_TAG)
116+
# Copy wheel files from the container to the local machine
117+
docker cp "$CONTAINER_ID:/out" ./out
118+
# Remove the container
119+
docker rm "$CONTAINER_ID"
120+
# Verify wheel file has been copied
121+
echo "Exported wheel files:"
122+
ls -la ./out
123+
WHEEL_COUNT=$(ls -1 ./out/*.whl | wc -l)
124+
echo "Total wheel files: $WHEEL_COUNT"
125+
126+
- name: Upload .whl to GitHub Release
127+
if: startsWith(github.ref, 'refs/tags/')
128+
env:
129+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
130+
run: |
131+
TAG_NAME=${GITHUB_REF##*/}
132+
133+
# Get wheel file information
134+
LIGHTKERNEL_WHEEL=$(ls ./out/lightllm_kernel-*.whl | head -n1 | xargs basename)
135+
FLASH_ATTN_WHEEL=$(ls ./out/flash_attn_3-*.whl | head -n1 | xargs basename)
136+
137+
gh release create "$TAG_NAME" ./out/*.whl \
138+
--title "LightKernel Release $TAG_NAME" \
139+
--notes "🎯 **LightKernel Docker Release $TAG_NAME**
140+
141+
This automated release contains pre-compiled wheel packages:
142+
143+
📦 **Packages:**
144+
- **$LIGHTKERNEL_WHEEL** - Core CUDA kernel library
145+
- **$FLASH_ATTN_WHEEL** - Flash Attention 3.0 (Hopper)
146+
147+
🚀 **Quick Installation:**
148+
\`\`\`bash
149+
# Install both packages
150+
pip install https://github.com/${{ github.repository }}/releases/download/$TAG_NAME/$LIGHTKERNEL_WHEEL
151+
pip install https://github.com/${{ github.repository }}/releases/download/$TAG_NAME/$FLASH_ATTN_WHEEL
152+
\`\`\`
153+
154+
🔧 **Build Environment:**
155+
- CUDA: 12.6.1 with cuDNN
156+
- PyTorch: 2.7.1
157+
- Python: 3.10
158+
- Architecture: CUDA Compute Capabilities 8.0, 8.6, 8.9, 9.0
159+
160+
🐳 **Docker Image:** \`${{ steps.meta.outputs.tags }}\`
161+
162+
Built on $(date -u)" \
163+
|| echo "Release already exists, skipping"

Dockerfile

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
ARG CUDA_VERSION=12.6.1
2+
FROM nvidia/cuda:${CUDA_VERSION}-cudnn-devel-ubuntu22.04
3+
ARG PYTHON_VERSION=3.10
4+
ARG MAMBA_VERSION=24.7.1-0
5+
ARG TARGETPLATFORM
6+
7+
ENV PATH=/opt/conda/bin:$PATH \
8+
CONDA_PREFIX=/opt/conda
9+
10+
# Install system dependencies
11+
RUN chmod 777 -R /tmp && apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
12+
ca-certificates \
13+
libssl-dev \
14+
curl \
15+
g++ \
16+
make \
17+
git \
18+
cmake \
19+
ninja-build \
20+
build-essential && \
21+
rm -rf /var/lib/apt/lists/*
22+
23+
# Install Mambaforge
24+
RUN case ${TARGETPLATFORM} in \
25+
"linux/arm64") MAMBA_ARCH=aarch64 ;; \
26+
*) MAMBA_ARCH=x86_64 ;; \
27+
esac && \
28+
curl -fsSL -o ~/mambaforge.sh -v "https://github.com/conda-forge/miniforge/releases/download/${MAMBA_VERSION}/Mambaforge-${MAMBA_VERSION}-Linux-${MAMBA_ARCH}.sh" && \
29+
bash ~/mambaforge.sh -b -p /opt/conda && \
30+
rm ~/mambaforge.sh
31+
32+
# Install Python
33+
RUN case ${TARGETPLATFORM} in \
34+
"linux/arm64") exit 1 ;; \
35+
*) /opt/conda/bin/conda update -y conda && \
36+
/opt/conda/bin/conda install -y "python=${PYTHON_VERSION}" ;; \
37+
esac && \
38+
/opt/conda/bin/conda clean -ya
39+
40+
# Set working directory
41+
WORKDIR /workspace
42+
43+
# Install PyTorch with CUDA support
44+
RUN pip install torch==2.7.1
45+
46+
# Install build dependencies
47+
RUN pip install --upgrade pip setuptools wheel build scikit-build-core[pyproject] pybind11 ninja
48+
49+
RUN git clone https://github.com/ModelTC/LightKernel.git
50+
51+
# Set environment variables for building
52+
ENV FLASH_ATTENTION_FORCE_BUILD=TRUE \
53+
FLASH_ATTENTION_DISABLE_BACKWARD=TRUE \
54+
CUDA_HOME=/usr/local/cuda \
55+
CUDA_ROOT=/usr/local/cuda
56+
57+
# Create output directory
58+
RUN mkdir -p /out
59+
60+
# Build lightllm-kernel package (main project)
61+
RUN echo "🔧 Building lightllm-kernel package..." && \
62+
python -m build --wheel --outdir /out/ && \
63+
echo "✅ lightllm-kernel build completed"
64+
65+
# Build flash_attn_3 package (hopper)
66+
RUN echo "🔧 Building flash_attn_3 package..." && \
67+
cd flash-attention/hopper && \
68+
MAX_JOBS=1 NVCC_THREADS=1 FLASH_ATTN_CUDA_ARCHS="80;86;89;90" python setup.py bdist_wheel && \
69+
cp dist/*.whl /out/ && \
70+
echo "✅ flash_attn_3 build completed"
71+
72+
# Verify all wheels are built
73+
RUN echo "📦 Final wheel packages:" && \
74+
ls -la /out/ && \
75+
WHEEL_COUNT=$(ls -1 /out/*.whl | wc -l) && \
76+
echo "Total wheels built: $WHEEL_COUNT" && \
77+
if [ "$WHEEL_COUNT" -ne 2 ]; then \
78+
echo "❌ Error: Expected 2 wheels, found $WHEEL_COUNT" && exit 1; \
79+
else \
80+
echo "✅ Successfully built all wheel packages"; \
81+
fi

0 commit comments

Comments
 (0)