CI/CD自动化部署-前端

GitLab CI/CD 配置解析

这个配置文件定义了一个完整的 Node.js 项目部署流程,包含预安装、安装和部署三个阶段。下面是对每一部分的详细解析:

变量定义部分

yaml
variables:
BD: dist # 构建输出目录(build directory)
PD: dev.hanlan.site # 生产目录(production directory)
BUR: dev.hanlan.site_backup # 备份目录(backup directory)
SD: “${ng_sd}” # 源目录(source directory),从变量ng_sd获取
ORTHER_SOURCEDIR: /www/wwwroot # 其他源目录路径
DSI: “${DEFAULT}” # 部署服务器IP(deploy server IP)
TEST_SERVER_IP: “10.10.17.18” # 测试服务器IP
MASTER_SERVER_IP: “暂时无生产IP” # 生产服务器IP(暂未设置)
D_HOST: “10.10.17.16:5000” # Docker镜像仓库地址
NPM_REGISTRY: “https://registry.npmmirror.com” # npm镜像源

阶段定义

yaml
stages:
preinstall # 预安装阶段(仅当package.json/package-lock.json变化时运行)
install # 安装阶段(每次构建都运行)
deploy # 部署阶段

缓存配置

yaml
cache:
key:
files:
package-lock.json # 基于package-lock.json的hash作为缓存键
paths:
node_modules/ # 缓存node_modules目录
package-lock.json # 缓存package-lock.json文件

预安装任务

yaml
preinstall-job:
image: $D_HOST/node:v20 # 使用自定义Node.js 20镜像
stage: preinstall # 属于preinstall阶段
only: # 仅在以下分支触发
refs:
master
test
dev
changes: # 仅当以下文件变化时触发
package.json
package-lock.json
script:
echo “配置 NPM 镜像”
npm config set registry $NPM_REGISTRY # 设置npm镜像源
echo “依赖发生变化,开始 install”
npm install # 安装依赖
echo “install 完成”

安装任务

yaml
install-job:
image: $D_HOST/node:v20 # 使用自定义Node.js 20镜像
stage: install # 属于install阶段
only: # 仅在以下分支触发
refs:
master
test
dev
script:
echo “配置 NPM 镜像”
npm config set registry $NPM_REGISTRY # 设置npm镜像源
echo “start install”
npm install # 安装依赖
echo “build package”
npm run build:${CI_COMMIT_BRANCH} # 根据分支构建项目
echo “完成打包”
artifacts: # 生成物配置
paths:
$BD/ # 保存dist目录内容
expire_in: 1 days # 生成物保存1天

部署任务

yaml
deploy-job:
image: $D_HOST/sshpass:latest # 使用包含sshpass的自定义镜像
stage: deploy # 属于deploy阶段
only: # 仅在以下分支触发
refs:
master
test
dev
script: | # 多行脚本(使用|保持格式)
echo “部署到 Nginx”
echo “当前分支: $CI_COMMIT_BRANCH”
echo “默认路径: SD=${SD}, PD=${PD}, BUR=${BUR}, DSI=${DSI}”
# 根据分支设置变量
if [[ “$CI_COMMIT_BRANCH” == “test” ]]; then # 测试分支配置
PD=”test.emit.team”
BUR=”test.emit.team_backup”
DSI=”${TEST_SERVER_IP:-10.10.17.18}” # 使用测试服务器IP
SD=”${ORTHER_SOURCEDIR:-/www/wwwroot}”
elif [[ “$CI_COMMIT_BRANCH” == “master” ]]; then # 主分支配置
DSI=”${MASTER_SERVER_IP:-10.10.17.18}” # 使用生产服务器IP(暂未设置)
SD=”${ORTHER_SOURCEDIR:-/www/wwwroot}”
fi
echo “更新后路径: SD=${SD}, PD=${PD}, BUR=${BUR}, DSI=${DSI}”
# 一行SSH备份命令(变量在本地先展开)
sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no root@$DSI “\
mkdir -p \”$SD/$BUR\” && \ # 创建备份目录
if [ -d \”$SD/$PD\” ] && [ \”\$(ls -A \”$SD/$PD\”)\” ]; then \ # 检查生产目录是否存在且非空
BACKUP_FILE=\”$SD/$BUR/backup_$(date +%Y%m%d%H%M%S).tar.gz\” && \ # 备份文件名
echo \”开始备份: \$BACKUP_FILE\” && \
tar czf \”\$BACKUP_FILE\” -C \”$SD\” \”$PD\” && \ # 执行备份
echo \”备份成功:\$BACKUP_FILE\”; \
else \
echo \”源目录不存在或为空,跳过备份\”; \ # 目录不存在或为空时的处理
fi”
# 清空旧目录
sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no root@$DSI “rm -rf \”$SD/$PD\”/*”
# 本地打包
if [ -d “$BD” ] && [ “$(ls -A “$BD”)” ]; then # 检查构建目录是否存在且非空
echo “打包构建产物”
tar czf release.tar.gz -C “$BD” . # 打包构建产物
else
echo “错误: 构建目录 $BD 不存在或为空!” # 错误处理
exit 1
fi
# 传输并解压
sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no release.tar.gz root@$DSI:”$SD/$PD/” # 上传打包文件
sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no root@$DSI “\ # 远程解压
cd \”$SD/$PD\” && \
echo \”解压到: $SD/$PD\” && \
tar xzf release.tar.gz && \ # 解压文件
rm -f release.tar.gz && \ # 删除临时打包文件
echo \”解压后文件列表:\” && \
ls -l” # 列出解压后的文件
echo “部署完成”
dependencies: # 依赖的任务
install-job # 依赖install-job的生成物
after_script: # 部署后清理
echo “清理临时文件”
rm -f release.tar.gz # 删除本地临时打包文件
echo “部署流程结束”

流程总结

  1. 预安装阶段:仅在依赖文件变化时运行,安装项目依赖
  2. 安装阶段:每次构建都运行,安装依赖并构建项目,生成构建产物
  3. 部署阶段:将构建产物部署到目标服务器,包括:
    • 根据分支设置不同的部署配置
    • 备份现有生产环境
    • 清空生产目录
    • 上传并解压新版本
    • 清理临时文件

整个流程实现了自动化构建和部署,支持多环境(开发/测试/生产)部署,并包含备份机制确保部署安全。

//////.gitlab-ci.yml////////////////////////////////////////////////////////////////////////////////////////////////

variables:
  BD: dist
  PD: dev.hanlan.site
  BUR: dev.hanlan.site_backup
  SD: “${ng_sd}”
  ORTHER_SOURCEDIR: /www/wwwroot
  DSI: “${DEFAULT}”
  TEST_SERVER_IP: “10.10.17.18”
  MASTER_SERVER_IP: “pro.emit.team”
  D_HOST: “10.10.17.16:5000”
  NPM_REGISTRY: “https://registry.npmmirror.com”
stages:
  – preinstall
  – install
  – deploy
# 缓存配置,基于 package-lock.json 的 hash
cache:
  key:
    files:
      – package-lock.json
  paths:
    – node_modules/
    – package-lock.json
preinstall-job:
  image: $D_HOST/node:v20
  stage: preinstall
  only:
    refs:
      – master
      – test
      – dev
    changes:
      – package.json
      – package-lock.json
  script:
    – echo “配置 NPM 镜像”
    – npm config set registry $NPM_REGISTRY
    – echo “依赖发生变化,开始 install”
    – npm install
    – echo “install 完成”
install-job:
  image: $D_HOST/node:v20
  stage: install
  only:
    refs:
      – master
      – test
      – dev
  script:
    – echo “配置 NPM 镜像”
    – npm config set registry $NPM_REGISTRY
    – echo “start install”
    – npm install
    – echo “Format all the files under the “src” directory”
    – npm run format
    – echo “build package”
    – npm run build:${CI_COMMIT_BRANCH}
    – echo “完成打包”
  artifacts:
    paths:
      – $BD/
    expire_in: 1 days
deploy-job:
  image: $D_HOST/sshpass:latest
  stage: deploy
  only:
    refs:
      – master
      – test
      – dev
  script: |
    echo “部署到 Nginx”
    echo “当前分支: $CI_COMMIT_BRANCH”
    echo “默认路径: SD=${SD}, PD=${PD}, BUR=${BUR}, DSI=${DSI}”
    # 根据分支设置变量
    if [[ “$CI_COMMIT_BRANCH” == “test” ]]; then
      PD=”test.emit.team”
      BUR=”test.emit.team_backup”
      DSI=”${TEST_SERVER_IP:-10.10.17.18}”
      SD=”${ORTHER_SOURCEDIR:-/www/wwwroot}”
    elif [[ “$CI_COMMIT_BRANCH” == “master” ]]; then
      PD=”pro.emit.team”
      BUR=”pro.emit.team_backup”
      DSI=”${MASTER_SERVER_IP:-pro.emit.team}”
      SD=”${ORTHER_SOURCEDIR:-/www/wwwroot}”
      PASSWORD=$PASSWORD_PROD_WEB
    fi
    echo “更新后路径: SD=${SD}, PD=${PD}, BUR=${BUR}, DSI=${DSI}”
    # 一行 SSH 备份(变量在本地先展开)
    sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no root@$DSI “\
      mkdir -p \”$SD/$BUR\” && \
      if [ -d \”$SD/$PD\” ] && [ \”\$(ls -A \”$SD/$PD\”)\” ]; then \
        BACKUP_FILE=\”$SD/$BUR/backup_$(date +%Y%m%d%H%M%S).tar.gz\” && \
        echo \”开始备份: \$BACKUP_FILE\” && \
        tar czf \”\$BACKUP_FILE\” -C \”$SD\” \”$PD\” && \
        echo \”备份成功:\$BACKUP_FILE\”; \
      else \
        echo \”源目录不存在或为空,跳过备份\”; \
      fi”
    # 清空旧目录
    sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no root@$DSI “rm -rf \”$SD/$PD\”/*”
    # 本地打包
    if [ -d “$BD” ] && [ “$(ls -A “$BD”)” ]; then
      echo “打包构建产物”
      tar czf release.tar.gz -C “$BD” .
    else
      echo “错误: 构建目录 $BD 不存在或为空!”
      exit 1
    fi
    # 传输并解压
    sshpass -p $PASSWORD scp -o StrictHostKeyChecking=no release.tar.gz root@$DSI:”$SD/$PD/”
    sshpass -p $PASSWORD ssh -o StrictHostKeyChecking=no root@$DSI “\
      cd \”$SD/$PD\” && \
      echo \”解压到: $SD/$PD\” && \
      tar xzf release.tar.gz && \
      rm -f release.tar.gz && \
      echo \”解压后文件列表:\” && \
      ls -l”
    echo “部署完成”
  dependencies:
    – install-job
  after_script:
    – echo “清理临时文件”
    – rm -f release.tar.gz
    – echo “部署流程结束”

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注