feat: add Vite host and Gitea CI for project57 embed
This commit is contained in:
commit
076e603c93
12 files changed
+901
No files matched your search
@@ -0,0 +1,255 @@
|
||||
# 对齐 project0(projectBase)CI:Gitea + Docker + K8s
|
||||
# 本仓为 Vite 静态宿主,构建产物为 dist/,镜像用 nginx 监听 3000
|
||||
name: CI Pipeline
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [master]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
check-commit:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
should_build: ${{ steps.check.outputs.should_build }}
|
||||
should_deploy: ${{ steps.check.outputs.should_deploy }}
|
||||
should_deploy_only: ${{ steps.check.outputs.should_deploy_only }}
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: false
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Check commit message
|
||||
id: check
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
|
||||
echo "should_build=true" >> $GITHUB_OUTPUT
|
||||
echo "should_deploy=true" >> $GITHUB_OUTPUT
|
||||
echo "should_deploy_only=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ 手动触发"
|
||||
else
|
||||
head_msg="${{ github.event.head_commit.message }}"
|
||||
echo "检查提交消息: $head_msg"
|
||||
|
||||
if echo "$head_msg" | grep -qE '\[deploy-only\]'; then
|
||||
echo "should_build=false" >> $GITHUB_OUTPUT
|
||||
echo "should_deploy=true" >> $GITHUB_OUTPUT
|
||||
echo "should_deploy_only=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ 找到 [deploy-only] 标记,只执行部署(跳过构建)"
|
||||
elif echo "$head_msg" | grep -qE '\[build\]|\[deploy\]'; then
|
||||
echo "should_build=true" >> $GITHUB_OUTPUT
|
||||
echo "should_deploy_only=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ 找到 [build] 或 [deploy] 标记"
|
||||
|
||||
if echo "$head_msg" | grep -qE '\[deploy\]'; then
|
||||
echo "should_deploy=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ 找到 [deploy] 标记,将执行构建和部署"
|
||||
else
|
||||
echo "should_deploy=false" >> $GITHUB_OUTPUT
|
||||
echo "✅ 只找到 [build] 标记,只执行构建"
|
||||
fi
|
||||
else
|
||||
echo "should_build=false" >> $GITHUB_OUTPUT
|
||||
echo "should_deploy=false" >> $GITHUB_OUTPUT
|
||||
echo "should_deploy_only=false" >> $GITHUB_OUTPUT
|
||||
echo "ℹ️ 提交消息不包含 [build]、[deploy] 或 [deploy-only] 标记,跳过工作流"
|
||||
fi
|
||||
fi
|
||||
|
||||
build:
|
||||
needs: check-commit
|
||||
if: needs.check-commit.outputs.should_build == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
image_ref: ${{ steps.push.outputs.image_ref }}
|
||||
|
||||
steps:
|
||||
- name: Checkout Code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
lfs: false
|
||||
persist-credentials: true
|
||||
token: ${{ secrets.LFS_PAT || secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Force LFS Pull with Custom Auth
|
||||
run: |
|
||||
HOST="git.bigmonk.org"
|
||||
REPO_PATH="${{ github.repository }}"
|
||||
|
||||
if [ -z "${{ secrets.LFS_PAT }}" ]; then
|
||||
echo "❌ 错误: 未配置 LFS_PAT Secret"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
GIT_TOKEN="${{ secrets.LFS_PAT }}"
|
||||
git config --local --unset credential.helper || true
|
||||
git config --global --unset credential.helper || true
|
||||
|
||||
AUTH_REMOTE="https://x-access-token:${GIT_TOKEN}@${HOST}/${REPO_PATH}.git"
|
||||
AUTH_LFS_URL="https://x-access-token:${GIT_TOKEN}@${HOST}/${REPO_PATH}.git/info/lfs"
|
||||
|
||||
git remote set-url origin "${AUTH_REMOTE}"
|
||||
git config --local lfs.url "${AUTH_LFS_URL}"
|
||||
|
||||
git lfs install
|
||||
git lfs pull
|
||||
echo "✅ LFS files pulled successfully"
|
||||
|
||||
- name: Setup Node.js and pnpm
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '24'
|
||||
|
||||
- name: Install pnpm
|
||||
run: |
|
||||
corepack enable
|
||||
corepack prepare [email protected] --activate
|
||||
|
||||
- name: Configure npm cache proxy and retries
|
||||
run: |
|
||||
echo "NPM_CONFIG_REGISTRY=http://172.17.0.1:4873" >> $GITHUB_ENV
|
||||
echo "npm_config_registry=http://172.17.0.1:4873" >> $GITHUB_ENV
|
||||
echo "PNPM_CONFIG_REGISTRY=http://172.17.0.1:4873" >> $GITHUB_ENV
|
||||
pnpm config set registry http://172.17.0.1:4873
|
||||
pnpm config set fetch-retries 6
|
||||
pnpm config set fetch-retry-factor 2
|
||||
pnpm config set fetch-retry-mintimeout 20000
|
||||
pnpm config set fetch-retry-maxtimeout 120000
|
||||
pnpm config set network-concurrency 8
|
||||
pnpm config set child-concurrency 4
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
pnpm install --frozen-lockfile --prefer-offline \
|
||||
|| pnpm install --frozen-lockfile --prefer-offline --registry=https://registry.npmjs.org
|
||||
|
||||
- name: Build Vite application
|
||||
env:
|
||||
VITE_A_ORIGIN: ${{ secrets.VITE_A_ORIGIN }}
|
||||
run: |
|
||||
if [ -z "${VITE_A_ORIGIN}" ]; then
|
||||
echo "❌ 未配置 Secret VITE_A_ORIGIN(A 站源站,如 https://swissicapital.net)"
|
||||
exit 1
|
||||
fi
|
||||
echo "VITE_A_ORIGIN=${VITE_A_ORIGIN}"
|
||||
pnpm build
|
||||
echo "✅ Build completed"
|
||||
if [ -d "dist" ] && [ -f "dist/index.html" ]; then
|
||||
echo "✅ dist/index.html 存在"
|
||||
else
|
||||
echo "❌ dist 构建产物不存在"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Verify Docker access
|
||||
run: docker info
|
||||
|
||||
- name: Build Docker image
|
||||
run: |
|
||||
export REGISTRY="104.225.236.253:30500"
|
||||
export REPO_NAME="${{ github.event.repository.name }}"
|
||||
export IMAGE_LATEST="${REGISTRY}/${REPO_NAME}:latest"
|
||||
export IMAGE_SHA="${REGISTRY}/${REPO_NAME}:${GITHUB_SHA}"
|
||||
docker build -t "${IMAGE_LATEST}" -t "${IMAGE_SHA}" .
|
||||
echo "Image built: ${IMAGE_LATEST}"
|
||||
echo "Image built: ${IMAGE_SHA}"
|
||||
|
||||
- name: Push to registry (SHA + latest, deploy by digest)
|
||||
id: push
|
||||
run: |
|
||||
set -euo pipefail
|
||||
export REGISTRY="104.225.236.253:30500"
|
||||
export REPO_NAME="${{ github.event.repository.name }}"
|
||||
export IMAGE_LATEST="${REGISTRY}/${REPO_NAME}:latest"
|
||||
export IMAGE_SHA="${REGISTRY}/${REPO_NAME}:${GITHUB_SHA}"
|
||||
|
||||
docker push "${IMAGE_SHA}"
|
||||
docker push "${IMAGE_LATEST}"
|
||||
|
||||
IMAGE_REF="${IMAGE_SHA}"
|
||||
DIGEST=$(docker inspect --format='{{index .RepoDigests 0}}' "${IMAGE_SHA}" 2>/dev/null || true)
|
||||
if [ -n "${DIGEST}" ]; then
|
||||
IMAGE_REF="${DIGEST}"
|
||||
fi
|
||||
echo "image_ref=${IMAGE_REF}" >> "${GITHUB_OUTPUT}"
|
||||
echo "✅ Pushed ${IMAGE_SHA} and ${IMAGE_LATEST}"
|
||||
echo "✅ Rollout ref (digest preferred): ${IMAGE_REF}"
|
||||
|
||||
deploy:
|
||||
needs: [check-commit, build]
|
||||
if: needs.check-commit.outputs.should_deploy == 'true' && needs.check-commit.outputs.should_deploy_only != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Deploy to K8s
|
||||
run: |
|
||||
if [ -z "${{ secrets.KUBECONFIG_BASE64 }}" ]; then
|
||||
echo "INFO: KUBECONFIG_BASE64 not configured. Deployment skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p ~/.kube
|
||||
echo "${{ secrets.KUBECONFIG_BASE64 }}" | base64 -d > ~/.kube/config
|
||||
chmod 600 ~/.kube/config
|
||||
|
||||
kubectl cluster-info || { echo "ERROR: Failed to connect to K8s cluster"; exit 1; }
|
||||
|
||||
export REPO_NAME="${{ github.event.repository.name }}"
|
||||
export IMAGE_REF="${{ needs.build.outputs.image_ref }}"
|
||||
export NAMESPACE="ns-${REPO_NAME}"
|
||||
export DEPLOYMENT="${REPO_NAME}-deploy"
|
||||
|
||||
echo "Deploying ${IMAGE_REF} to ${NAMESPACE}/${DEPLOYMENT}"
|
||||
kubectl patch "deployment/${DEPLOYMENT}" -n "${NAMESPACE}" --type='json' -p='[
|
||||
{"op":"replace","path":"/spec/strategy/rollingUpdate/maxSurge","value":"100%"},
|
||||
{"op":"replace","path":"/spec/strategy/rollingUpdate/maxUnavailable","value":0},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/image","value":"'"${IMAGE_REF}"'"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/imagePullPolicy","value":"IfNotPresent"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/api/health"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/timeoutSeconds","value":5},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/httpGet/path","value":"/api/health"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/timeoutSeconds","value":5}
|
||||
]'
|
||||
kubectl rollout status "deployment/${DEPLOYMENT}" -n "${NAMESPACE}" --timeout=180s
|
||||
echo "✅ Deployment completed successfully"
|
||||
|
||||
deploy-only:
|
||||
needs: check-commit
|
||||
if: needs.check-commit.outputs.should_deploy_only == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Deploy to K8s (without build)
|
||||
run: |
|
||||
if [ -z "${{ secrets.KUBECONFIG_BASE64 }}" ]; then
|
||||
echo "INFO: KUBECONFIG_BASE64 not configured. Deployment skipped."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
mkdir -p ~/.kube
|
||||
echo "${{ secrets.KUBECONFIG_BASE64 }}" | base64 -d > ~/.kube/config
|
||||
chmod 600 ~/.kube/config
|
||||
|
||||
kubectl cluster-info || { echo "ERROR: Failed to connect to K8s cluster"; exit 1; }
|
||||
|
||||
export REGISTRY="104.225.236.253:30500"
|
||||
export REPO_NAME="${{ github.event.repository.name }}"
|
||||
export IMAGE_LATEST="${REGISTRY}/${REPO_NAME}:latest"
|
||||
export NAMESPACE="ns-${REPO_NAME}"
|
||||
export DEPLOYMENT="${REPO_NAME}-deploy"
|
||||
|
||||
echo "Deploying existing image ${IMAGE_LATEST} to ${NAMESPACE}/${DEPLOYMENT}"
|
||||
kubectl patch "deployment/${DEPLOYMENT}" -n "${NAMESPACE}" --type='json' -p='[
|
||||
{"op":"replace","path":"/spec/strategy/rollingUpdate/maxSurge","value":"100%"},
|
||||
{"op":"replace","path":"/spec/strategy/rollingUpdate/maxUnavailable","value":0},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/image","value":"'"${IMAGE_LATEST}"'"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/imagePullPolicy","value":"Always"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/httpGet/path","value":"/api/health"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/readinessProbe/timeoutSeconds","value":5},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/httpGet/path","value":"/api/health"},
|
||||
{"op":"replace","path":"/spec/template/spec/containers/0/livenessProbe/timeoutSeconds","value":5}
|
||||
]'
|
||||
kubectl rollout status "deployment/${DEPLOYMENT}" -n "${NAMESPACE}" --timeout=180s
|
||||
echo "✅ Deployment completed (using existing image)"
|
||||
Reference in new issue
Block a user