Files
lpt-be/.gitea/workflows/deploy.yml
T
cat-shark 4f99f31475 fix(ci): 绑定分支与部署环境并加固 IMAGE_TAG 传递
- dev 仅允许 dev 分支,prod 仅允许 master/main
- IMAGE_TAG 写 env 文件 + image_tag.txt 兜底
- checkout 时确保 maven 容器内安装 git

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-07-20 22:46:17 +08:00

186 lines
6.5 KiB
YAML
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
name: lpt-be Build & Deploy
on:
workflow_dispatch:
inputs:
environment:
description: '部署环境(dev 仅允许 dev 分支;prod 仅允许 master/main'
required: true
type: choice
options:
- dev
- prod
env:
REGISTRY: 192.168.123.199:5000
APP: lpt-be
REPO_URL: http://git.cat-shark.xyz/cat-shark/lpt-be.git
jobs:
build-and-deploy:
runs-on: ubuntu-latest
container:
image: maven:3.9-eclipse-temurin-17
volumes:
- maven-cache:/root/.m2
steps:
- name: Validate branch ↔ environment
run: |
set -euo pipefail
REF="${{ gitea.ref }}"
BRANCH="${REF#refs/heads/}"
if [[ "$REF" == refs/tags/* ]]; then
echo "ERROR: 请从分支触发部署,不要用 tag。当前 ref=$REF"
exit 1
fi
ENV="${{ inputs.environment }}"
echo "branch=$BRANCH environment=$ENV sha=${{ gitea.sha }}"
case "$ENV" in
prod)
case "$BRANCH" in
master|main) echo "OK: prod 允许从 $BRANCH 部署" ;;
*)
echo "ERROR: prod 只能从 master/main 部署,当前分支是 '$BRANCH'"
echo "请切换到 master 后再 Run workflow,并选择 environment=prod"
exit 1
;;
esac
;;
dev)
case "$BRANCH" in
dev) echo "OK: dev 允许从 $BRANCH 部署" ;;
*)
echo "ERROR: dev 只能从 dev 分支部署,当前分支是 '$BRANCH'"
echo "请切换到 dev 后再 Run workflow,并选择 environment=dev"
echo "(禁止用 master 代码部署到 lpt-dev,避免环境错配)"
exit 1
;;
esac
;;
*)
echo "ERROR: 未知 environment=$ENV"
exit 1
;;
esac
- name: Checkout code
run: |
set -euo pipefail
# maven 容器可能无 git
if ! command -v git >/dev/null 2>&1; then
apt-get update -qq
apt-get install -y -qq git
fi
git clone "$REPO_URL" .
git checkout "${{ gitea.sha }}"
- name: Install Docker CLI
run: |
set -euo pipefail
apt-get update -qq
apt-get install -y -qq docker.io
docker --version
- name: Build with Maven
run: |
set -euo pipefail
mvn clean package -DskipTests -B
- name: Login to Docker Registry
run: |
set -euo pipefail
echo "${{ secrets.REGISTRY_PASSWORD }}" | docker login "$REGISTRY" -u "${{ secrets.REGISTRY_USERNAME }}" --password-stdin
- name: Build & Push Docker image
run: |
set -euo pipefail
ENV="${{ inputs.environment }}"
TAG="${{ gitea.sha }}-$(date +%s)"
echo "Building $REGISTRY/$APP:$TAG (env tag=$ENV)"
docker build -t "$REGISTRY/$APP:$TAG" -t "$REGISTRY/$APP:$ENV" .
docker push "$REGISTRY/$APP:$TAG"
docker push "$REGISTRY/$APP:$ENV"
if [ -n "${GITHUB_ENV:-}" ]; then
echo "IMAGE_TAG=$TAG" >> "$GITHUB_ENV"
fi
if [ -n "${GITEA_ENV:-}" ]; then
echo "IMAGE_TAG=$TAG" >> "$GITEA_ENV"
fi
# runner.temp 在 container job 里可能不可用,用工作区文件兜底
echo "$TAG" > image_tag.txt
mkdir -p /tmp/lpt-ci
echo "$TAG" > /tmp/lpt-ci/image_tag.txt
echo "IMAGE_TAG=$TAG"
- name: Setup kubectl
run: |
set -euo pipefail
curl -sLO "https://dl.k8s.io/release/v1.30.0/bin/linux/amd64/kubectl"
chmod +x kubectl
mv kubectl /usr/local/bin/
mkdir -p ~/.kube
echo "${{ secrets.KUBECONFIG_B64 }}" | base64 -d > ~/.kube/config
- name: Create/Update imagePullSecret
run: |
set -euo pipefail
kubectl create secret docker-registry regcred \
--docker-server="$REGISTRY" \
--docker-username="${{ secrets.REGISTRY_USERNAME }}" \
--docker-password="${{ secrets.REGISTRY_PASSWORD }}" \
-n "lpt-${{ inputs.environment }}" \
--dry-run=client -o yaml | kubectl apply -f -
- name: Deploy to K8s
run: |
set -euo pipefail
ENV="${{ inputs.environment }}"
IMAGE_TAG="${IMAGE_TAG:-}"
if [ -z "$IMAGE_TAG" ] && [ -f image_tag.txt ]; then
IMAGE_TAG="$(cat image_tag.txt)"
fi
if [ -z "$IMAGE_TAG" ] && [ -f /tmp/lpt-ci/image_tag.txt ]; then
IMAGE_TAG="$(cat /tmp/lpt-ci/image_tag.txt)"
fi
if [ -z "$IMAGE_TAG" ]; then
echo "ERROR: IMAGE_TAG 为空,无法部署"
exit 1
fi
echo "Deploying $REGISTRY/$APP:$IMAGE_TAG -> namespace lpt-$ENV"
# Spring profile 由 K8s Deployment 的 SPRING_PROFILES_ACTIVE 控制,镜像本身不区分
kubectl set image "deployment/$APP" \
"$APP=$REGISTRY/$APP:$IMAGE_TAG" \
-n "lpt-$ENV" --record
kubectl rollout status "deployment/$APP" \
-n "lpt-$ENV" --timeout=5m
- name: Debug on failure
if: failure()
run: |
ENV="${{ inputs.environment }}"
echo "=== Deployment Status ==="
kubectl get deployment "$APP" -n "lpt-$ENV" || true
echo ""
echo "=== Pod Status ==="
kubectl get pods -n "lpt-$ENV" -l "app=$APP" || true
echo ""
echo "=== Recent Events ==="
kubectl get events -n "lpt-$ENV" --sort-by='.lastTimestamp' | tail -20 || true
echo ""
echo "=== Pod Describe (latest) ==="
POD=$(kubectl get pods -n "lpt-$ENV" -l "app=$APP" --sort-by=.metadata.creationTimestamp -o jsonpath='{.items[-1].metadata.name}' 2>/dev/null || true)
if [ -n "${POD:-}" ]; then
kubectl describe pod "$POD" -n "lpt-$ENV" || true
echo ""
echo "=== Pod Logs (latest) ==="
kubectl logs "$POD" -n "lpt-$ENV" --tail=50 || true
fi
- name: Rollback on failure
if: failure()
run: |
set -euo pipefail
ENV="${{ inputs.environment }}"
kubectl rollout undo "deployment/$APP" -n "lpt-$ENV" || true
kubectl rollout status "deployment/$APP" -n "lpt-$ENV" || true