生产环境 Web 发布规范
本文档定义 Web 应用生产环境发布的标准流程和最佳实践
一、 发布概述
针对定制化项目的多环境部署需求(跨云厂商/私有化/集群/跳板机等场景),制定以下通用发布原则:
部署标准化:
优先
采用阿里云云效流水线实现自动化构建部署- 私有化环境配合客户现有CI/CD体系
架构适配性:
- 复杂架构项目需定制部署方案(如Docker/K8S/CDN等)
核心优势:
- 标准化发布流程,降低人为错误风险
- 自动化构建部署,提升发布效率
- 严格的代码审核机制
- 基于Git标签的版本控制体系
二、 Git发布规范
分支说明:
master
: 基准分支,对齐线上生产环境代码feature/*
: 功能开发分支,基于master创建release/{YYYYMMDD}[_suffix]
: 发布分支。基于master创建
功能发布流程图:
流程说明:
- 从master迁出feature分支进行功能开发。不同功能使用不同的feature分支,功能分支在master分支有更新或者定期合并同步master分支。
- 测试上线时:从master拉取release/{YYYYMMDD}[_suffix]分支
- 合并需要发布的feature分支。
- 通过云效流水线发布release/{YYYYMMDD}[_suffix]分支
- 发布成功后合并回master并打标签
信息
这个发布流程可以通过人工进行管理。但是不仅繁琐并且容易出错。所以下面介绍如何使用CI工具进行自动化发布流程
注意事项
- 确保所有代码变更已通过测试
- 发布过程中如遇问题,及时回滚
- 保留完整的发布记录和版本标签
- 定期清理过期的发布分支和标签
三、 云效流水线配置
我们可以使用云效的分支模式流水线进行发布。通过此方式可以 自动管理发布分支和分支合并操作
3.1 流水线步骤
简单来说,云效流水线发布上线可以简单拆分为下面几个步骤阶段。
设置代码源:
- 选择仓库git地址
- 【重要】开启分支模式
【可选】源码扫描阶段:
- 代码质量扫描
- 代码安全扫描
构建阶段:
- 设置环境:安装指定版本Node.js、设置pnpm、设置缓存配置等
- 构建:执行安装依赖和构建脚本命令
- 产物处理:缓存构建产物到云效供下一步使用 或 直接上传至OSS
部署阶段:按照部署方式不同分为
部署至OSS
- 【可选】清理bucket内容
- 上传构建产物至bucket
部署至云服务器
- 【可选】 审批:生产环境发布需要人工
- 下载构建产物到目标主机
- 解压并部署到指定目录
- 【可选】支持多环境部署(通过${stage}变量区分)
部署至K8S集群
- 构建Dokcer镜像
- 推送至K8S集群服务
收尾阶段:
- 打发布标签
- 自动合并代码回master分支
- 【可选】删除流水线自动创建的relase分支和对应的feature分支。建议自动删除release分支。feature分支由相关开发人员自行删除。
四、 流水线配置
根据上面的步骤阶段我们来看下具体的配置方式。
云效目前支持两种配置方式:YMAL方式
与 可视化方式
。我们默认使用 YAML方式
配置流水线- YAML 格式
下面提供默认的 YAML 模板配置 流水线。你可以 在云效 模板里面选择对应的模板
注意事项:
- 变量替换: 搜索并替换所有<< xx >>标记的内容。这些都是不同项目必须要修改的内容
- 根据项目实际情况调整Node版本和构建命令
- 部署目录需要提前在目标主机创建好
- 处理好自己的服务链接和授权
- 根据实际情况选择部署到服务器还是OSS
配置缓存
按下图配置.pnpm-store 以配合流水线缓存 加快pnpm 项目构建速度。 如果你的项目不是pnpm安装依赖的可以忽略
参数: /root/.pnpm-store
部署到OSS
云效提供了流水线模板。你可以直接选择使用
yaml
# 设置代码源
sources:
my_repo:
type: codeup # 默认是公司云效
name: <<项目名称>>
endpoint: <<git@codeup.aliyun.com:your-project-group/your-project-repo.git>> # 替换为项目git地址
certificate:
type: serviceConnection
serviceConnection: <<your-service-connection-id>> # 你的服务链接。如果没有自己创建一个
branch: master
branchMode: # 启用分支模式
baseBranch: master # 默认master基准分支
# 构建阶段
stages:
node_build_stage:
name: "构建"
jobs:
node_build_job:
name: "Node.js 构建"
runsOn:
group: public/cn-beijing
steps:
# 执行构建命令
setup_node_step:
name: "安装Node"
step: NodeBuild
with:
versionType: "custom"
customNodeVersion: "18.19.0" # 可以按照要求进行修改
run: |
# 安装pnpm@8
npm install pnpm@8.9.0 -g
pnpm -v
node -v
# 这里注意 需要在流水线配置页面顶部 【变量和缓存】配置项中添加 /root/.pnpm-store的配置
# 设置缓存仓库 与 【变量与缓存】中设置配合使用
pnpm config set store-dir /root/.pnpm-store
# 安装依赖。这里可以优化 pnpm install --filter "@wmeimob/backend..." --no-frozen-lockfile
# filter的名称查看相关项目包中package.json中的name字段
pnpm install --no-frozen-lockfile
# 执行构建命令
cd <<packages/backend>> && pnpm build
# 部署阶段
# [可选] 清理原型oss仓库下内容。如果不清除则新老版本可并存。坏处是占用会越来越大
oss_delete_step:
name: "清理仓库"
step: OSSDelete
with:
serviceConnection: <<your-service-connection-id>>
region: <<cn-shanghai>>
bucket: <<bucket>>
batchDelete: true
oss_upload_step:
name: "OSS 上传"
step: "OSSUpload"
with:
serviceConnection: <<your-service-connection-id>>
region: <<cn-shanghai>>
bucket: <<bucket>>
sourceFilePath: "<<sourceFilePath>>" # 构建产物目录。例如 "packages/backend/dist/"
targetFilePath: ""
end_stage:
name: '收尾阶段'
jobs:
manul_job:
name: 代码合并审批
component: ManualValidate
with:
validatorType: pipelineRoles #验证者类型为流水线角色
validateMethod: or
timeoutTime: '0' # 0 表示无超时时间
validatorPipelineRoles: member
git_merge_job:
name: 发布分支合并进主分支
condition: |
succeed('manul_job')
steps:
merge_step:
step: MergeBranch
name: Git代码合并
with:
targetBranch: master
deleteSourceBranch: true
# deleteMatchedBranch: true
# branchFilter: ^feature.*
git_tag_job:
name: 打发布Tag
condition: |
succeed('manul_job')
steps:
merge_step:
step: AddGitTag
name: 打发布Tag
with:
gitTag: ${CI_COMMIT_REF_NAME}
部署到服务器
yaml
# 设置代码源
sources:
my_repo:
type: codeup # 默认是公司云效
name: <<项目名称>>
endpoint: <<git@codeup.aliyun.com:your-project-group/your-project-repo.git>> # 替换为项目git地址
certificate:
type: serviceConnection
serviceConnection: <<your-service-connection-id>> # 你的服务链接。如果没有自己创建一个
branch: master
branchMode: # 启用分支模式
baseBranch: master # 默认master基准分支
# 构建阶段
stages:
node_build_stage:
name: "构建"
jobs:
node_build_job:
name: "Node.js 构建"
runsOn:
group: public/cn-beijing
steps:
# 执行构建命令
setup_node_step:
name: "安装Node"
step: NodeBuild
with:
versionType: "custom"
customNodeVersion: "18.19.0" # 可以按照要求进行修改
run: |
# 安装pnpm@8
npm install pnpm@8.9.0 -g
pnpm -v
node -v
# 这里注意 需要在流水线配置页面顶部 【变量和缓存】配置项中添加 /root/.pnpm-store的配置
# 设置缓存仓库 与 【变量与缓存】中设置配合使用
pnpm config set store-dir /root/.pnpm-store
# 安装依赖。这里可以优化 pnpm install --filter "@wmeimob/backend..." --no-frozen-lockfile
# filter的名称查看相关项目包中package.json中的name字段
pnpm install --no-frozen-lockfile
# 执行构建命令
cd <<packages/backend>> && pnpm build
# 将构建产物缓存在流水线中供后续使用
artifact_upload_step:
name: "构建物上传"
step: ArtifactUpload
with:
uploadType: flowPublic
artifact: "Artifacts_${PIPELINE_ID}_${DATETIME}"
filePath: "./dist" # 一般来说都是dist 按需修改
vm_deploy_stage:
name: "部署"
jobs:
# 这是部署到服务器上的代码
vm_deploy_job:
name: "主机部署"
component: "VMDeploy"
with:
downloadArtifact: true
useEncode: false
machineGroup: <<your-machine-group-id>> # 主机ID 需要先新增主机
executeUser: "root"
artifact: $[stages.node_build_stage.node_build_job.artifact_upload_step.artifacts.Artifacts_${PIPELINE_ID}_${DATETIME}] # 使用上面缓存的构建产物 按路径来的
# 部署到服务器上名称
artifactDownloadPath: "/opt/package_${DATETIME}.tgz"
# 部署到主机后执行的命令
run: |
# 核心逻辑为
# 1.创建文件夹 一般静态页面放在 /var/www/下 通过nginx解析
mkdir -p /var/www/backend
echo /var/www/backend
# 2.[可选] 清除旧文件。如果不清除则可保证新老并存
rm -rf /var/www/backend/*
# 3.将上传的包移动到对应文件夹内
mv /opt/package_${DATETIME}.tgz /var/www/backend/package_${DATETIME}.tgz
# 4.进入目录
cd /var/www/backend
# 5.执行解压操作
tar zxvf package_${DATETIME}.tgz
end_stage:
name: '收尾阶段'
jobs:
manul_job:
name: 代码合并审批
component: ManualValidate
with:
validatorType: pipelineRoles #验证者类型为流水线角色
validateMethod: or
timeoutTime: '0' # 0 表示无超时时间
validatorPipelineRoles: member
git_merge_job:
name: 发布分支合并进主分支
condition: |
succeed('manul_job')
steps:
merge_step:
step: MergeBranch
name: Git代码合并
with:
targetBranch: master
deleteSourceBranch: true
# deleteMatchedBranch: true
# branchFilter: ^feature.*
git_tag_job:
name: 打发布Tag
condition: |
succeed('manul_job')
steps:
merge_step:
step: AddGitTag
name: 打发布Tag
with:
gitTag: ${CI_COMMIT_REF_NAME}
部署到K8S集群
略...