#!/bin/bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)"
IMAGE_NAME="memcache-ci:latest"
CONTAINER_NAME="memcache-ci-check"
info() { echo -e " \e[36m[CI]\e[0m $*"; }
ok() { echo -e " \e[32m[OK]\e[0m $*"; }
err() { echo -e " \e[31m[ERR]\e[0m $*"; }
header(){ echo -e "\n\e[1;34m--- $* ---\e[0m"; }
check_prerequisites() {
if ! command -v docker &>/dev/null; then
err "docker not found. Install Docker or use a CI runner with Docker support."
exit 1
fi
ok "docker: $(docker --version)"
local npu_count
npu_count=$(ls -d /dev/davinci[0-9]* 2>/dev/null | wc -l || true)
if [[ "$npu_count" -eq 0 ]]; then
err "No NPU devices found on host (/dev/davinci*)."
exit 1
fi
ok "NPU: $npu_count device(s) on host"
local mount_paths=(
/usr/local/dcmi
/usr/local/Ascend/driver/tools/hccn_tool
/usr/local/bin/npu-smi
/usr/local/Ascend/driver/lib64/
/usr/local/Ascend/driver/version.info
/etc/ascend_install.info
/etc/hccn.conf
)
for p in "${mount_paths[@]}"; do
if [[ ! -e "$p" ]]; then
err "Bind mount source not found: $p"
err "Ensure CANN driver is installed on the host."
exit 1
fi
done
ok "All bind mount sources exist"
local devc_files=(
"$PROJECT_DIR/.devcontainer/Dockerfile"
"$PROJECT_DIR/.devcontainer/post_create.sh"
"$PROJECT_DIR/.devcontainer/requirements.txt"
"$PROJECT_DIR/script/run_all_examples.sh"
)
for f in "${devc_files[@]}"; do
if [[ ! -f "$f" ]]; then
err "Required file not found: $f"
exit 1
fi
done
ok "All devcontainer files present"
}
build_image() {
info "Building Docker image: $IMAGE_NAME"
info " Dockerfile: $PROJECT_DIR/.devcontainer/Dockerfile"
docker build -t "$IMAGE_NAME" \
-f "$PROJECT_DIR/.devcontainer/Dockerfile" \
"$PROJECT_DIR" --network=host
ok "Image built: $IMAGE_NAME"
}
run_in_container() {
info "Starting container..."
local inner="bash .devcontainer/post_create.sh"
inner+=" && source /usr/local/Ascend/ascend-toolkit/set_env.sh"
inner+=" && bash script/run_all_examples.sh --verbose"
local run_args=(
run --rm
--name "$CONTAINER_NAME"
--network=host
--privileged
--shm-size=2g
-v "$PROJECT_DIR:/workspaces/memcache"
-v /usr/local/dcmi:/usr/local/dcmi
-v /usr/local/Ascend/driver/tools/hccn_tool:/usr/local/Ascend/driver/tools/hccn_tool
-v /usr/local/bin/npu-smi:/usr/local/bin/npu-smi
-v /usr/local/Ascend/driver/lib64/:/usr/local/Ascend/driver/lib64/
-v /usr/local/Ascend/driver/version.info:/usr/local/Ascend/driver/version.info
-v /etc/ascend_install.info:/etc/ascend_install.info
-v /etc/hccn.conf:/etc/hccn.conf
-e PYTHONUNBUFFERED=1
-e PIP_INDEX_URL=https://mirrors.aliyun.com/pypi/simple/
-e PIP_TRUSTED_HOST=mirrors.aliyun.com
-e PRE_COMMIT_HOME=/root/.cache/pre-commit
-e PIP_SYSTEM_SITE_PACKAGES=1
-e CMAKE_BUILD_PARALLEL_LEVEL=$(nproc)
-e MMC_BUILD_JOBS=$(nproc)
-e PYTHON_HOME=/usr/local/python3.11.15
-w /workspaces/memcache
)
local log_file="/tmp/memcache_ci_$(date +%Y%m%d_%H%M%S).log"
info "Logging container output to: $log_file"
: > "$log_file"
docker "${run_args[@]}" "$IMAGE_NAME" bash -c "$inner" >"$log_file" 2>&1 &
local docker_pid=$!
tail -f "$log_file" 2>/dev/null &
local tail_pid=$!
local rc=0
wait "$docker_pid" || rc=$?
kill "$tail_pid" 2>/dev/null || true
wait "$tail_pid" 2>/dev/null || true
if [[ $rc -ne 0 ]]; then
err "Container exited with code $rc"
err "Full log: $log_file"
exit $rc
fi
ok "Container run completed (log: $log_file)"
}
cleanup_stale_meta() {
local pids
pids=$(pgrep -f "mmc_meta_service|from memcache_hybrid import MetaService" 2>/dev/null || true)
if [[ -n "$pids" ]]; then
info "Killing stale MemCache MetaService on host (PID: $(echo $pids | tr '\n' ' '))"
kill $pids 2>/dev/null || true
sleep 2
kill -9 $pids 2>/dev/null || true
sleep 1
fi
}
cleanup_stale_containers() {
local ids
ids=$(docker ps -aq --filter "name=${CONTAINER_NAME}" 2>/dev/null || true)
if [[ -n "$ids" ]]; then
info "Removing stale CI container (ID: $(echo $ids | tr '\n' ' '))"
docker rm -f $ids >/dev/null 2>&1 || true
fi
}
echo ""
echo "============================================"
echo " MemCache CI -- DevContainer Check"
echo " Project: $PROJECT_DIR"
echo " Image: $IMAGE_NAME"
echo "============================================"
header "Step 1: Check prerequisites"
check_prerequisites
header "Step 1.5: Cleanup stale MetaService and containers"
cleanup_stale_meta
cleanup_stale_containers
header "Step 2: Build Docker image (Dockerfile)"
build_image
header "Step 3: Run post_create.sh + run_all_examples.sh (in container)"
run_in_container
echo ""
echo "============================================"
echo " CI DevContainer Check -- PASSED"
echo "============================================"