feat: 增加cicd
central-platform-frontend / deploy (push) Failing after 2s

This commit is contained in:
2026-10-04 06:55:48 -07:00
parent b9b2c1bb01
commit bc3651da1e
4 changed files with 171 additions and 1 deletions
+14
View File
@@ -0,0 +1,14 @@
.git
.gitea
.idea
.next
.agents
.claude
.hermes
node_modules
.env*
*.tsbuildinfo
next-env.d.ts
AGENTS.md
CLAUDE.md
README.md
+117
View File
@@ -0,0 +1,117 @@
name: central-platform-frontend
run-name: "${{ gitea.event.head_commit.message }}"
on:
push:
branches:
- main
concurrency:
group: deploy-central-platform-frontend
cancel-in-progress: true
env:
IMAGE_NAME: central-platform-frontend
HOST_PORT: 22786
# 浏览器访问的后端公网地址,会内联进前端代码;在仓库 Variables 中配置 API_BASE_URL
NEXT_PUBLIC_API_BASE_URL: ${{ vars.API_BASE_URL }}
# Next.js 服务端访问同机后端,容器使用宿主机网络,127.0.0.1 即宿主机
INTERNAL_API_BASE_URL: http://127.0.0.1:22788
DOCKER_BUILDKIT: "0"
jobs:
deploy:
runs-on:
- vps_jp
timeout-minutes: 20
steps:
- name: Prepare environment
run: |
STEP_START=$(date +%s)
if ! command -v docker > /dev/null 2>&1; then
apk add docker-cli
fi
if ! command -v git > /dev/null 2>&1; then
apk add git
fi
if ! command -v node > /dev/null 2>&1; then
apk add nodejs
fi
docker --version
echo "Environment preparation took $(( $(date +%s) - STEP_START ))s"
- name: Checkout repository
uses: actions/checkout@v4
- name: Check build config
run: |
if [ -z "$NEXT_PUBLIC_API_BASE_URL" ]; then
echo "Repository variable API_BASE_URL is empty, set the public backend URL"
exit 1
fi
echo "API base URL: $NEXT_PUBLIC_API_BASE_URL"
- name: Build application image
run: |
STEP_START=$(date +%s)
SHORT_SHA=$(echo "${{ gitea.sha }}" | cut -c1-8)
docker build \
--build-arg NEXT_PUBLIC_API_BASE_URL="$NEXT_PUBLIC_API_BASE_URL" \
--label "git.sha=${{ gitea.sha }}" \
-t $IMAGE_NAME:latest \
-t $IMAGE_NAME:$SHORT_SHA .
docker images $IMAGE_NAME:latest --format "Image size: {{.Size}}"
echo "Application image step took $(( $(date +%s) - STEP_START ))s"
- name: Deploy container
run: |
STEP_START=$(date +%s)
if docker ps -a --filter "name=^${IMAGE_NAME}$" -q | grep -q .; then
docker stop --timeout 15 $IMAGE_NAME || true
docker rm $IMAGE_NAME || true
fi
docker run -d \
--name $IMAGE_NAME \
--network host \
-e PORT=$HOST_PORT \
-e HOSTNAME=127.0.0.1 \
-e INTERNAL_API_BASE_URL=$INTERNAL_API_BASE_URL \
-e TZ=Asia/Shanghai \
--restart unless-stopped \
$IMAGE_NAME:latest
MAX_WAIT=60
WAITED=0
HEALTH="unknown"
while [ $WAITED -lt $MAX_WAIT ]; do
RUNNING_ID=$(docker ps --filter "name=^${IMAGE_NAME}$" --filter "status=running" -q)
HEALTH=$(docker inspect --format '{{if .State.Health}}{{.State.Health.Status}}{{else}}none{{end}}' $IMAGE_NAME 2>/dev/null || echo "unknown")
if [ -n "$RUNNING_ID" ] && [ "$HEALTH" = "healthy" ]; then
break
fi
sleep 2
WAITED=$((WAITED + 2))
done
if [ "$HEALTH" = "healthy" ]; then
docker ps --filter "name=^${IMAGE_NAME}$" --format "Status: {{.Status}}"
echo "Startup wait: ${WAITED}s"
else
echo "Container not healthy after ${MAX_WAIT}s (health=$HEALTH)"
docker inspect $IMAGE_NAME --format 'ExitCode={{.State.ExitCode}} Error={{.State.Error}} StartedAt={{.State.StartedAt}} FinishedAt={{.State.FinishedAt}}' 2>/dev/null || true
docker logs --tail 30 $IMAGE_NAME || true
exit 1
fi
echo "Deployment step took $(( $(date +%s) - STEP_START ))s"
- name: Clean up old images
run: docker image prune -f
- name: Show startup logs
if: always()
run: docker logs --tail 15 $IMAGE_NAME
+38
View File
@@ -0,0 +1,38 @@
FROM node:22-alpine AS builder
WORKDIR /app
RUN npm install -g pnpm@10
COPY package.json pnpm-lock.yaml pnpm-workspace.yaml ./
RUN pnpm install --frozen-lockfile
# NEXT_PUBLIC_* 会在构建时内联进浏览器代码,必须通过构建参数传入
ARG NEXT_PUBLIC_API_BASE_URL
ENV NEXT_PUBLIC_API_BASE_URL=$NEXT_PUBLIC_API_BASE_URL \
NEXT_TELEMETRY_DISABLED=1
COPY . .
RUN pnpm build
FROM node:22-alpine
ENV NODE_ENV=production \
NEXT_TELEMETRY_DISABLED=1 \
HOSTNAME=127.0.0.1 \
PORT=22786
WORKDIR /app
COPY --from=builder --chown=node:node /app/.next/standalone ./
COPY --from=builder --chown=node:node /app/.next/static ./.next/static
COPY --from=builder --chown=node:node /app/public ./public
USER node
EXPOSE 22786
HEALTHCHECK --interval=10s --timeout=5s --start-period=10s --retries=3 \
CMD wget -q --spider http://127.0.0.1:22786/ || exit 1
CMD ["node", "server.js"]
+2 -1
View File
@@ -1,7 +1,8 @@
import type { NextConfig } from "next";
const nextConfig: NextConfig = {
/* config options here */
// 生成可独立运行的 server.js,供 Docker 镜像使用
output: "standalone"
};
export default nextConfig;