- 新增 CI/CD 工作流文件,实现前端项目的自动构建和部署 - 支持 main、master 和 develop 分支的自动构建- 包含代码检出、环境安装、依赖管理、项目构建等步骤 - 实现构建产物的自动部署和 Docker 容器重启
291 lines
9.9 KiB
YAML
291 lines
9.9 KiB
YAML
name: Epic UI Build & Deploy
|
||
run-name: ${{ gitea.actor }} 正在构建 Epic UI 前端项目 🚀
|
||
on:
|
||
push:
|
||
branches: [ main, master, develop ]
|
||
pull_request:
|
||
branches: [ main, master ]
|
||
|
||
jobs:
|
||
build:
|
||
runs-on: gitea_labels
|
||
container:
|
||
image: gitea-ci-bash:latest
|
||
steps:
|
||
- name: 检出代码
|
||
shell: bash
|
||
run: |
|
||
echo "📥 检出代码到工作目录..."
|
||
echo "当前目录: $(pwd)"
|
||
echo "仓库: ${{ gitea.repository }}"
|
||
echo "分支: ${{ gitea.ref }}"
|
||
echo "提交: ${{ gitea.sha }}"
|
||
|
||
# 解析分支名
|
||
BRANCH_NAME=$(echo "${{ gitea.ref }}" | sed 's#refs/heads/##')
|
||
|
||
# 拉取代码(使用token鉴权)
|
||
git clone --depth=1 -b "$BRANCH_NAME" "http://1c18ee1ab9a9cb291506d0c5c016a33be7d59e8c:x-oauth-basic@gitea.htoop.cn/${{ gitea.repository }}.git" .
|
||
if [ $? -ne 0 ]; then
|
||
echo "❌ 代码检出失败"
|
||
exit 1
|
||
fi
|
||
|
||
# 校验分支
|
||
CURRENT_BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||
if [ "$CURRENT_BRANCH" != "$BRANCH_NAME" ]; then
|
||
echo "❌ 检出分支与预期不符: $CURRENT_BRANCH != $BRANCH_NAME"
|
||
exit 1
|
||
fi
|
||
|
||
# 校验提交
|
||
CURRENT_COMMIT=$(git rev-parse HEAD)
|
||
if [ -n "${{ gitea.sha }}" ] && [ "$CURRENT_COMMIT" != "${{ gitea.sha }}" ]; then
|
||
echo "❌ 检出提交与预期不符: $CURRENT_COMMIT != ${{ gitea.sha }}"
|
||
exit 1
|
||
fi
|
||
|
||
echo "✅ 代码检出成功,分支和提交校验通过"
|
||
ls -la
|
||
|
||
- name: 安装Node.js环境
|
||
shell: bash
|
||
run: |
|
||
echo "🔧 安装Node.js环境..."
|
||
if command -v node &> /dev/null; then
|
||
echo "✅ Node.js已安装: $(node --version)"
|
||
echo "✅ npm已安装: $(npm --version)"
|
||
else
|
||
echo "📥 下载并安装Node.js..."
|
||
NODE_VERSION="18.19.0"
|
||
NODE_ARCH="linux-x64"
|
||
MIRRORS=(
|
||
"https://mirrors.aliyun.com/nodejs-release/v${NODE_VERSION}/node-v${NODE_VERSION}-${NODE_ARCH}.tar.xz"
|
||
"https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-${NODE_ARCH}.tar.xz"
|
||
)
|
||
DOWNLOAD_SUCCESS=false
|
||
for mirror in "${MIRRORS[@]}"; do
|
||
echo "尝试从镜像下载: $mirror"
|
||
if wget -q --timeout=30 --tries=3 "$mirror" -O node.tar.xz; then
|
||
echo "✅ 下载成功: $mirror"
|
||
DOWNLOAD_SUCCESS=true
|
||
break
|
||
else
|
||
echo "❌ 下载失败: $mirror"
|
||
continue
|
||
fi
|
||
done
|
||
if [ "$DOWNLOAD_SUCCESS" = false ]; then
|
||
echo "❌ 所有镜像源下载失败"
|
||
exit 1
|
||
fi
|
||
echo "解压Node.js到/usr/local..."
|
||
tar -C /usr/local -xJf node.tar.xz --strip-components=1
|
||
export PATH=$PATH:/usr/local/bin
|
||
echo "验证Node.js安装..."
|
||
node --version
|
||
npm --version
|
||
rm node.tar.xz
|
||
echo "✅ Node.js安装完成"
|
||
fi
|
||
|
||
- name: 检查Node.js环境
|
||
shell: bash
|
||
run: |
|
||
echo "🔍 检查Node.js环境..."
|
||
export PATH=$PATH:/usr/local/bin
|
||
node --version
|
||
npm --version
|
||
echo "Node.js路径: $(which node)"
|
||
echo "npm路径: $(which npm)"
|
||
|
||
- name: 安装pnpm
|
||
shell: bash
|
||
run: |
|
||
echo "📦 安装pnpm包管理器..."
|
||
export PATH=$PATH:/usr/local/bin
|
||
if command -v pnpm &> /dev/null; then
|
||
echo "✅ pnpm已安装: $(pnpm --version)"
|
||
else
|
||
echo "📥 安装pnpm..."
|
||
npm install -g pnpm
|
||
echo "✅ pnpm安装完成: $(pnpm --version)"
|
||
fi
|
||
|
||
- name: 设置 pnpm 缓存目录
|
||
shell: bash
|
||
run: |
|
||
echo "📦 设置 pnpm 缓存目录..."
|
||
export PATH=$PATH:/usr/local/bin
|
||
|
||
# 检查挂载点
|
||
echo "🔍 检查挂载点状态..."
|
||
CACHE_DIR="/shared/pnpm-cache"
|
||
echo "检查目录: $CACHE_DIR"
|
||
|
||
# 强制创建目录(如果挂载存在但目录为空)
|
||
mkdir -p "$CACHE_DIR"
|
||
|
||
if [ -d "$CACHE_DIR" ]; then
|
||
echo " ✅ 目录存在"
|
||
ls -la "$CACHE_DIR" | head -5
|
||
if [ -w "$CACHE_DIR" ]; then
|
||
echo " ✅ 目录可写"
|
||
else
|
||
echo " ❌ 目录不可写,尝试修复权限"
|
||
chmod 777 "$CACHE_DIR" 2>/dev/null || echo " 无法修复权限"
|
||
if [ -w "$CACHE_DIR" ]; then
|
||
echo " ✅ 权限修复成功"
|
||
else
|
||
echo " ❌ 权限修复失败"
|
||
CACHE_DIR=""
|
||
fi
|
||
fi
|
||
else
|
||
echo " ❌ 目录不存在"
|
||
CACHE_DIR=""
|
||
fi
|
||
|
||
if [ -z "$CACHE_DIR" ]; then
|
||
echo "⚠️ 未找到外部缓存目录,使用临时目录"
|
||
CACHE_DIR="/tmp/pnpm-cache"
|
||
mkdir -p "$CACHE_DIR"
|
||
else
|
||
echo "✅ 使用外部缓存目录: $CACHE_DIR"
|
||
fi
|
||
|
||
# 强制设置缓存目录,覆盖 .npmrc 中的配置
|
||
pnpm config set store-dir "$CACHE_DIR" --global
|
||
pnpm config set cache-dir "$CACHE_DIR" --global
|
||
echo "配置的缓存目录: $CACHE_DIR"
|
||
echo "pnpm 实际缓存目录: $(pnpm store path)"
|
||
|
||
# 验证配置是否生效
|
||
echo "验证 pnpm 配置:"
|
||
echo "store-dir: $(pnpm config get store-dir)"
|
||
echo "cache-dir: $(pnpm config get cache-dir)"
|
||
|
||
# 检查缓存状态
|
||
if [ -d "$CACHE_DIR/v10" ]; then
|
||
echo "✅ 找到外部缓存"
|
||
du -sh "$CACHE_DIR"
|
||
echo "缓存文件数量: $(find "$CACHE_DIR" -type f | wc -l)"
|
||
else
|
||
echo "📥 首次运行,无缓存"
|
||
fi
|
||
|
||
- name: 缓存依赖
|
||
shell: bash
|
||
run: |
|
||
echo "📦 检查并恢复依赖缓存..."
|
||
export PATH=$PATH:/usr/local/bin
|
||
|
||
# 记录开始时间
|
||
START_TIME=$(date +%s)
|
||
|
||
# 使用外部缓存时的优化
|
||
echo "📦 使用外部缓存优化..."
|
||
pnpm config set prefer-offline true
|
||
|
||
# 检查 lockfile 是否存在
|
||
if [ -f "pnpm-lock.yaml" ]; then
|
||
echo "✅ 找到 pnpm-lock.yaml,使用离线模式安装..."
|
||
echo "开始时间: $(date)"
|
||
pnpm install --frozen-lockfile
|
||
else
|
||
echo "📥 未找到 lockfile,重新安装依赖..."
|
||
echo "开始时间: $(date)"
|
||
pnpm install
|
||
fi
|
||
|
||
# 记录结束时间
|
||
END_TIME=$(date +%s)
|
||
DURATION=$((END_TIME - START_TIME))
|
||
|
||
# 保存缓存信息
|
||
echo "📊 安装统计:"
|
||
echo "总耗时: ${DURATION}秒"
|
||
echo "缓存目录: $(pnpm store path)"
|
||
echo "缓存大小: $(du -sh $(pnpm store path) 2>/dev/null || echo 'N/A')"
|
||
echo "✅ 依赖安装完成"
|
||
|
||
- name: 验证依赖
|
||
shell: bash
|
||
run: |
|
||
echo "🔍 验证项目依赖..."
|
||
export PATH=$PATH:/usr/local/bin
|
||
pnpm list --depth=0
|
||
echo "✅ 依赖验证完成"
|
||
|
||
- name: 构建项目
|
||
shell: bash
|
||
run: |
|
||
echo "🔨 开始构建 Epic UI 前端项目..."
|
||
export PATH=$PATH:/usr/local/bin
|
||
pnpm build
|
||
echo "✅ 构建完成"
|
||
|
||
- name: 检查构建产物
|
||
shell: bash
|
||
run: |
|
||
echo "📦 构建产物信息:"
|
||
if [ -d "dist" ]; then
|
||
echo "✅ 找到dist目录"
|
||
ls -la dist/
|
||
echo "dist目录大小: $(du -sh dist | cut -f1)"
|
||
else
|
||
echo "❌ 未找到dist目录"
|
||
exit 1
|
||
fi
|
||
|
||
- name: 显示项目信息
|
||
shell: bash
|
||
run: |
|
||
echo "📋 项目信息:"
|
||
export PATH=$PATH:/usr/local/bin
|
||
echo "Node.js 版本: $(node --version)"
|
||
echo "npm 版本: $(npm --version)"
|
||
echo "pnpm 版本: $(pnpm --version)"
|
||
echo "构建时间: $(date)"
|
||
echo "分支: ${{ gitea.ref }}"
|
||
echo "提交: ${{ gitea.sha }}"
|
||
|
||
- name: 准备部署
|
||
shell: bash
|
||
run: |
|
||
echo "🚀 准备部署..."
|
||
echo "运行器操作系统: ${{ runner.os }}"
|
||
echo "工作目录: ${{ gitea.workspace }}"
|
||
echo "任务状态: ${{ job.status }}"
|
||
mkdir -p deploy
|
||
cp -r dist/* deploy/
|
||
echo "📦 部署包已准备完成"
|
||
|
||
- name: 复制构建产物到目标目录
|
||
shell: bash
|
||
run: |
|
||
echo "📤 复制构建产物到 /opt/dockeropt/epic-ui ..."
|
||
mkdir -p /opt/dockeropt/epic-ui
|
||
cp -r dist/* /opt/dockeropt/epic-ui/
|
||
echo "✅ 构建产物已复制到 /opt/dockeropt/epic-ui"
|
||
ls -la /opt/dockeropt/epic-ui/
|
||
|
||
- name: 重启 Docker 容器
|
||
shell: bash
|
||
run: |
|
||
echo "♻️ 重启 epic-ui 容器..."
|
||
if ! command -v docker &> /dev/null; then
|
||
if command -v apt-get &> /dev/null; then
|
||
apt-get update && apt-get install -y docker.io
|
||
elif command -v apk &> /dev/null; then
|
||
echo "http://mirrors.aliyun.com/alpine/v3.20/main" > /etc/apk/repositories
|
||
echo "http://mirrors.aliyun.com/alpine/v3.20/community" >> /etc/apk/repositories
|
||
apk update
|
||
apk add --no-cache docker-cli
|
||
elif command -v yum &> /dev/null; then
|
||
yum install -y docker
|
||
fi
|
||
fi
|
||
docker ps -a
|
||
docker restart epic-ui
|
||
echo "✅ epic-ui 容器已重启" |