背景
目前公司测试环境前端项目部署,是由测试人员负责手动操作。当需要更新测试环境版本时,测试同事需要手动操作以下过程。
- 连接打包服务器
- 打开svn管理工具,找到目标svn版本号并拉取项目
- 拉取项目后,打开命令行,下载依赖。
- 等待依赖下载结束后。敲下打包命令
- 等待构建结束,并将资源文件压缩成压缩包复制到桌面
- 链接部署服务器
- 找到需要部署的站点文件夹
- 粘贴至目标文件夹并解压
在项目多的时候,重复操作极大的浪费时间。如果遇到同一时间不同项目组打包项目,打包和部署服务器就要排队使用,测试人员只能在等待中浪费时间。为了解决这些问题,选择寻找合适的持续集成方案。来自动化完成重复的步骤。
我尝试过轻量的自动部署方案(walle,spug)。但由于两者对于Windows系统和svn支持太低。最后还是选择了老牌稳健的Jenkins。
我们利用Jenkins来自动化处理上述问题。(拉取代码,打包构建,将资源送往目标服务器)。让测试同事不再需要关心打包环节,并从这一繁琐的过程中解放出来,回到本应专注的测试程序工作环节上。
下载docker与Jenkins镜像
借助docker这个搭环境的神器来搭建Jenkins,首先安装docker
# 安装docker
yum install docker
# 启动docker
systemctl start docker
# 设置镜像源,加速下载镜像
vim etc/docker/daemon.json
{"registry-mirrors": ["http://hub-mirror.c.163.com"]}
# 服务重启
systemctl restart docker.service
# 安装docker Jenkins
docker pull jenkins/jenkins
# 建立Jenkins数据存储文件夹
mkdir /usr/jenkins
# 设置权限
chown -R 1000:1000 /usr/jenkins
# 启动Jenkins,映射到 9527 端口
docker run -itd --name jenkins -p 50000:50000 -p 9527:8080 --privileged=true -v /usr/jenkins:/var/jenkins jenkins/jenkins
Jenkins初始化
成功启动容器后,访问Jenkins服务器IP地址加端口号,进行Jenkins初始化,初始化的管理员密码从日志中可以获取。
#查看容器ID
docker ps -a
#查看容器日志
docker logs 容器ID
选择推荐安装,等待安装后即可。
安装Jenkins插件
初始化完后。使用刚刚创建的账号登录Jenkins进入界面,需要安装几个插件来支持我们的业务。
在系统管理——插件管理中,安装以下三个插件。
- Subversion Plug-in(svn支持)
- Publish Over SSH(远程连接)
- NodeJS Plugin(前端资源构建)
插件配置
插件安装完后,需要对插件进行配置。
ssh插件配置
在系统管理——系统设置中,找到 publish over SSH
。点击新增按钮,添加需要发布的远程机配置。
比如需要发布到开发环境的远程机,添加以下信息。
部署机器操作系统为windows,需要给部署机器安装ssh并开启服务,以支持ssh链接。
部分机器可能设置了防火墙,需要在防火墙给22端口添加出站入站规则。允许ssh连接。
node.js插件配置
在系统管理-全局工具配置中,找到 NodeJS
。
需要注意的是Node.js版本避免过高,选择开发稳定版本,能避免不少版本过高导致部署过程出现一些奇怪的问题。
插件配置完毕后,就能够新建构建任务了。
新建构建任务
任务类型选择自由风格软件项目。
任务信息
添加参数化构建过程,用于处理不同情况处理的构建。这边需要关注两个参数 env
, svnUrl
,对应着:构建及发布环境、构建的svn版本号。
env
在前端项目构建时,会当作变量传入。用于动态修改构建的项目环境类型。
svnUrl
为每次项目构建时,拉取代码的SVN地址。
svn仓库配置
由于是代码版本控制工具是SVN,需要选择 Subversion
选项,在 Repository URL
中填入变量 $svnUrl
。代表构建时使用传入的地址参数。
同时还需要提供一个svn账号凭证,用于拉取SVN代码。
配置node.js打包前端项目
选择node.js进行构建。
在构建中,能够借助命令行给node.js环境来安装某些源工具,比如yarn、cnpm、nrm。后续可将安装源工具的命令去掉,直接执行安装依赖命令。
此处的命令负责打印常见信息,并执行构建命令。在构建结束后将 dist
文件夹的内容压缩成压缩包:"dist.tar.gz"
配置构建后操作
在前端资源打包完成后,我们需要将文件送到目标服务器。此处添加送往的目标服务器。
点击Add Server
添加构建后需要将文件传送的目标服务器,并指定传送的文件名称dist.tar.gz
,并编写传送后需要执行的命令。
Exec command
中的命令在不同的操作系统中是不一样的,当系统为unix系统时,执行的为unix命令。当为windows系统时,执行的为批处理命令。
Exec command
中的 superDeploy.bat
为目标服务器预留的批处理文件,负责将文件解压缩,送往部署目录的处理。
完成以上配置后,保存此任务。
在远程机器添加批处理文件
当配置的目标机器为windows系统时,文件会被送到配置远程链接的账户所属用户文件夹下。在传输完毕后,预留的 superDeploy.bat
文件会被执行。
superDeploy.bat
接收两个参数,当前构建的环境,和构建后文件传送的路径。
批处理文件负责复制压缩包到目标文件夹,在目标文件夹解压缩等操作。
这里通过命令行来调用 7z
的解压缩功能,需要给部署机安装 7z
解压软件。也能更换为其他解压缩软件。
开始第一次构建
完成配置后,点击 Build with Parameters
开始构建,构建前需要填写构建参数。
此时会按照SVN项目地址拉取代码,构建前端资源时,会执行npm run build:${传入的环境参数}
命令。对应的为前端项目 package.json
中各环境的打包命令。
{
"scripts": {
"build:dev": "vue-cli-service build --mode=dev",
"build:test": "vue-cli-service build --mode=test",
"build:prod": "vue-cli-service build --mode=prod"
}
}
此处利用了 vue-cli3.0
提供的构建命令和环境变量文件,来提供各环境的打包命令。前端项目需要配置多种打包命令,来支持Jenkins的动态环境构建。
一切就绪,点击开始构建。Jenkins就会按照SVN地址拉取代码,并且执行构建命令,在构建完成后将dist文件夹压缩成压缩包,送到目标服务器并且执行预留在目标服务器的批处理文件。批处理文件将压缩包移动到执行的目标目录,处理解压缩的动作。一个自动构建和部署的过程就完成了。
实际构建时间需要40秒~70秒,但对于手工操作来说要强太多了。
踩过的坑
- 文件传送的用户目录名称不一样
在某些电脑上出现,登录的用户名为 user
,但实际传输到目标的文件夹为 user.iZjenfhextasd
这样的文件夹。需要注意脚本的正确存放位置。
- cnpm安装依赖偶尔超时
需要修改Jenkins镜像中安装的cnpm源码文件的超时时间配置。
docker cp jenkins:/var/jenkins_home/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/Node_JS_12.18.4/lib/node_modules/cnpm/node_modules/urllib/lib/urllib.js /usr/jenkins/
#修改文件中的内容
docker cp /usr/jenkins/urllib.js jenkins:/tmp/
docker exec -u root -it jenkins /bin/bash
mv /tmp/urllib.js /var/jenkins_home/tools/jenkins.plugins.nodejs.tools.NodeJSInstallation/Node_JS_12.18.4/lib/node_modules/cnpm/node_modules/urllib/lib/urllib.js
或者能更换为其他依赖下载命令,比如yarn。
- 部署机网络或性能问题,偶尔无法连接
保证部署机能够正常运行,不爆满内存与CPU使用。
- ssh连接失败
检查openSSH服务是否启用,或者防火墙是否禁用了22端口的出入。
- 依赖更新问题
Jenkins首次安装依赖会根据项目中锁定版本号的文件进行依赖版本安装(package-lock.json,yarn-lock),安装过后 node_modules
文件夹会存留。如需要更新特定依赖版本,需要手动修改 package.json
中的版本号并重新提交构建,或者选择任务中的 “清空工作区选项”。
写在最后的碎碎念
在公司没有运维的情况下。一开始只是抱着尝试的心理来探索持续集成的方案,在尝试了 walle/spug 这样的轻量部署方案均失败后曾打算放弃。但听到测试同事的一句吐槽:“自动部署说了三年了,都没有做出来”。于是下定决心一定要将这个目标完成。
我始终坚信着,如果某件事情迟迟完成不了,那它应该是在等待某个人来完成。我就要尝试来成为这个人。
于是开始不断收集资料,查阅文档,从零开始搭建。windows与svn总有大量奇奇怪怪的问题,在搭建的过程频频受阻。好不容易搭建好了,依赖却安装不了了,障碍一个接一个。
在连续失败了95次之后,第96次终于成功将所有的流程走通。成功的喜悦无以言表,差点就激动得在座位上跳了起来。
就这样,测试同事的生产力得到了解放。不再需要为打包的事情苦恼,一切都变得这么简单。
感谢TL一直的信任和支持,在我提出有这样的想法时,不断的帮我争取借用到各个生产服务器环境的权限。也让我领悟到,只有不断跳出固定领域。不断挑战自己不熟悉的内容,自身的能力才有更大的提升。
希望这篇文章能够帮到你,have a nice day :)