name: Deploy Noval to K3s on: push: branches: - main - master jobs: deploy: runs-on: self-hosted steps: - name: Deploy to K3s run: | set -e APP_NAME="noval" NAMESPACE="noval-roog-code" IMAGE_NAME="noval-app" echo "🚀 开始部署 ${APP_NAME}..." cd /root/k8syaml/NovalRedot echo "📥 拉取最新代码..." BRANCH="${GITHUB_REF_NAME:-master}" git pull origin "${BRANCH}" NEW_COMMIT_SHA=$(git rev-parse --short HEAD) NEW_COMMIT_MSG=$(git log -1 --oneline) FULL_IMAGE="${IMAGE_NAME}:${NEW_COMMIT_SHA}" echo "🌐 预拉取基础镜像(带重试,避免网络抖动)..." pull_with_retry() { local image="$1" local max=5 local n=1 until [ $n -gt $max ]; do echo "尝试拉取 ${image} (${n}/${max})" if docker pull "${image}"; then echo "✅ 拉取成功: ${image}" return 0 fi sleep $((n * 5)) n=$((n + 1)) done echo "❌ 拉取失败: ${image}" return 1 } pull_with_retry node:20-alpine pull_with_retry python:3.12-slim echo "📦 构建镜像 ${FULL_IMAGE}" docker build --pull=false -t "${FULL_IMAGE}" . docker tag "${FULL_IMAGE}" "${IMAGE_NAME}:latest" if command -v k3s >/dev/null 2>&1; then echo "📤 导入镜像到 k3s containerd..." docker save "${FULL_IMAGE}" | k3s ctr images import - docker save "${IMAGE_NAME}:latest" | k3s ctr images import - fi echo "🧱 应用 K8s 基础资源..." kubectl apply -f k8s/namespace.yaml kubectl apply -f k8s/cluster-issuer.yaml kubectl apply -f k8s/pvc.yaml kubectl apply -f k8s/service.yaml kubectl apply -f k8s/ingress.yaml if kubectl get deployment "${APP_NAME}" -n "${NAMESPACE}" >/dev/null 2>&1; then echo "🔄 检测到现有 deployment,执行滚动更新..." kubectl set image deployment/${APP_NAME} ${APP_NAME}=${FULL_IMAGE} -n "${NAMESPACE}" else echo "🆕 首次部署,创建 deployment..." kubectl apply -f k8s/deployment.yaml kubectl set image deployment/${APP_NAME} ${APP_NAME}=${FULL_IMAGE} -n "${NAMESPACE}" fi echo "⏳ 等待 rollout 完成..." kubectl rollout status deployment/${APP_NAME} -n "${NAMESPACE}" --timeout=300s echo "✅ 部署完成" echo "📌 版本: ${NEW_COMMIT_SHA} - ${NEW_COMMIT_MSG}" kubectl get pods -n "${NAMESPACE}" -l app=${APP_NAME} -o wide