Skip to main content

CICD 下前端的多特性分支环境部署

一般可以可以划分为三个环境,我把这三个环境命名如下,并会在下述

local:本地环境,把项目 git clone 到自己的工作笔记本或者开发机中,在 localhost:8080 类似的地址进行调试与开发。此时环境的面向对象主要是开发者。 dev:测试环境,本地业务迭代开发结束并交付给测试进行功能测试的环境,在 dev.shanyue.tech 类似的二级域名进行测试。此时环境的面向对象主要是测试人员。 prod:生产环境,线上供用户使用的环境,在 shanyue.tech 类似的地址。此时环境的面向对象主要是用户。

git flow 流程如图上所示,关于细节这里不作过多的讨论。一般来说

feature 分支对应本地环境 develop 分支对应测试环境 master 分支对应生产环境 由于每次 feature 开发结束后都要合并到 develop 分支进行测试。此时会有几个问题

当 develop 分支测试出现 bug 后,每次修复后都需要合并到 develop 分支。 当多功能同时开发时会造成 develop 分支的拥挤导致,各个功能最后只能统一上线,因为它无法时刻保持一个干净的 develop 分支,这与我们现在所提倡的敏捷开发,小步迭代格格不入。 此时,基于 feature 分支急需一套可单独测试的环境

多分支环境部署

CI,Continous Integration 持续集成使项目变得更加自动化,充分减少程序员的手动操作,并且在产品快速迭代的同时提高代码质量。基于 CICD 的工作流也大大改善了 Git 的工作流。其中就增加了一个基于分支的前端环境:

特性环境 (也不知道叫啥名字,就这么起吧),对应于 feature 分支。每个 feature 分支都会有一个环境,可以视为本地环境与测试环境的结合体。如对功能 feature-A 的开发在 feature-A.dev.shanyue.tech 类似的三级域名进行测试。 此时对于开发,测试,产品交付来讲,整个流程的体验就顺滑了很多。于是终于到了今天的正题:

如何实现多分支环境部署?

基于 docker 进行部署

由于 docker 的轻便易用,隔离性好并且可移植性高的特点,这里选择基于 docker 的部署,镜像配置文件如下所示。

FROM node:10-alpine as builder

ENV PROJECT_ENV development
ENV NODE_ENV production

# http-server 不变动也可以利用缓存
WORKDIR /code

ADD package.json package-lock.json /code
RUN npm install --production

ADD . /code
RUN npm run build

# 选择更小体积的基础镜像
FROM nginx:10-alpine
COPY --from=builder /code/public /usr/share/nginx/html

另外由于此时不在生产环境,完全没有必要把所有静态资源扔到 CDN 去处理,甚至为了方便调试,在打包时也可以避免做过多的混淆及压缩。如果你对 docker 不熟悉,可以查看本系列暨前端工程暨高级前端进阶的系列文章第 N 篇:使用 Docker 部署前端项目

基于容器的前端部署与反向代理

现在流行的 kubernetes,docker-compose 应用编排都是基于容器的,所以我们只需要着力于容器,思考如何利用它做多分支部署。

首先解决的问题是多分支部署环境的多域名问题,因此首先要了解如何利用容器来映射域名,以下是两种常见的方案,但是利用容器的 label 的方式还是多一些

基于 container label,如 traefik 以及 kubernetes ingress。 基于 environment,如 docker-nginx。 但是无论基于那种方式的部署,我们总是可以在给它封装一层来简化操作,一来方便运维管理,一来方便开发者直接接入。如把部署抽象为一个命令,我们这里暂时把这个命令命名为 deploy,deploy 这个命令可能基于 kubectl/heml 也有可能基于 docker-conpose。

该命令最核心 API 如下:

$ deploy service-name --host :host 假设要部署一个应用 shanyue-feature-A,设置它的域名为 feature-A.dev.shanyue.tech,则这个部署前端的命令为:

$ deploy shanyue-feature-A --host feature-A.dev.shanyue.tech 现在只剩下了一个问题:找到当前分支。

基于 CICD 的多分支部署

在 CICD 中很容易获取当前分支的信息,在 CI 环境中可以通过环境变量获取到。

如在 gitlab CI 中可以通过环境变量 CI_COMMIT_REF_SLUG 获取,该环境变量还会做相应的分支名替换,如 feature/A 到 feature-a 的转化。

CI_COMMIT_REF_SLUG: $CI_COMMIT_REF_NAME lowercased, shortened to 63 bytes, and with everything except 0-9 and a-z replaced with -. No leading / trailing -. Use in URLs, host names and domain names. 以下是一个基于 gitlab CI 的一个多分支部署的简单示例

deploy-for-feature: stage: deploy only: refs: - /^feature/.*$/ script: - deploy shanyue-$CI_COMMIT_REF_SLUG --host https://$CI_COMMIT_REF_SLUG.sp.dev.smartstudy.com environment: name: review/$CI_COMMIT_REF_NAME url: http://$CI_COMMIT_REF_SLUG.dev.shanyue.tech

小结

随着 CICD 的发展,对快速迭代以及代码质量提出了更高的要求,基于分支的多测试环境成为了刚需。

对于该环境的搭建,思路也很清晰

  • 借用现有的 CICD 服务,如 jenkins,gitlab CI 或者 drone CI,获取当前分支信息
  • 借用 Docker 快速部署前端或者后端,根据分支信息启动不同的容器,并配置标签
  • 根据容器的标签与当前 Git 分支对前端后端设置不同的域名

另外,这个基于容器的思路不仅仅使用于前端,同样也适用于后端。而现实的业务中复杂多样,如又分为已下几种,这需要在项目的使用场景中灵活处理。

  • feature-A 的前端分支对应 feature-A 的后端分支环境
  • feature-A 的前端分支对应 develop 的后端分支环境
  • feature-A 的前端分支对应 master 的后端分支环境

参考