环境清单:
1,本机环境: Mac OSX
2,服务器环境:Centos7 ,nodejs,git
3,需要基础:一些基本服务器操作指令,git使用及了解gitlab平台基本使用
注:这里演示的都是基础能用的版本,实际生产肯定不能这么来的,根据大佬的建议一般来说这部署应该在docker环境配置,并且权限配置也很重要,而且runner机器和生产代码机器应该独立。
好了,前端自动部署,这个听起来如此高大上的东西是啥叻,我们为什么需要呢,对于众javaer来说jenkins肯定是不陌生的,这个原理颇为相似,但配置起来却简单的多(那不然我就写不了这个文章了),我们目前希望能够实现:
本地代码推到master => 触发钩子服务器自动执行脚本 => 拉代码,自动装依赖,打包,编译,上线
好了,确保你拥有环境清单里面的2,3,当然没有也没关系,慢慢折腾嘛......
1,第一步准备你的服务器公钥
如果你有的话它应该在 ~/.ssh目录下的id_rsa.pub,没有的话你可以创建一个
ssh-keygen -t rsa -C "youremail@example.com"
然后去gitlab setting的ssh key那里添加一下,这里是为了方便服务端去拉取git仓库代码,也是我们搞事情的关键。
2,在服务端安装gitlab runner
移除旧版本仓库(如果你之前搞过这个,如果没有,这步可以忽略):
sudo rm /etc/yum.repos.d/runner_gitlab-ci-multi-runner.repo
添加 GitLab's 官方仓库:
curl -L https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.rpm.sh | sudo bash
下载最新版 GitLab Runner:
sudo yum install gitlab-runner
3,注册runner
我们需要在这里和gitlab建立连接,命令行敲入
sudo gitlab-runner register
// 注册 gitlab-ci-multi-runner
sudo gitlab-ci-multi-runner register
出来一系列对话如下
# 填写gitlab ci地址(见图1)
Please enter the gitlab-ci coordinator URL (e.g. https://gitlab.com )
我这里用的是gitlab的库当然就是https://gitlab.com/啦,参数可看图1
------------------------------------------------------------
输入您获得的注册Runner的令牌:(见图1)
Please enter the gitlab-ci token for this runner
token,图一的位置有
------------------------------------------------------------
# 输入Runner的描述,你可以稍后在GitLab的UI中进行更改:
Please enter the gitlab-ci description for this runner[hostame]
my-runner (如果不是实际生产,随便写,只是标识作用)
------------------------------------------------------------
# 输入与Runner关联的标签,稍后可以在GitLab的UI中进行更改:
Please enter the gitlab-ci tagsforthisrunner (comma separated):
xxx(这里不填也行)
------------------------------------------------------------
选择Runner是否应该选择没有标签的作业,可以稍后在GitLab的UI中进行更改(默认为false):
Whether to run untagged jobs [true/false]:
[false]:true (暂时自己玩的话,可以直接空格调过)
------------------------------------------------------------
选择是否将Runner锁定到当前项目,稍后可以在GitLab的UI中进行更改。
Runner特定时有用(默认为true):
Whether to lock Runner to current project [true/false]:
[true]:true (暂时自己玩的话/不知道干啥用的,可以直接空格调过)
------------------------------------------------------------
# 输入Runner执行者:Please enter the executor: ssh, docker+machine, docker-ssh+machine, kubernetes, docker, parallels, virtualbox, docker-ssh, shell
shell(这里我们用较简单的shell命令来玩先)
步骤1,2信息可在gitalb -setting -ci(见图1)里面找到相关信息
完成注册后我们的gitlab runner应该会被安排在/home/gitlab-runner 目录,至少我的是这样的。随后我们需要给gitlab-runner文件夹赋予权限,否则很有可能在跑runner的时候报permission denied,操作如下
sudo chown -R gitlab-runner:gitlab-runner /home/gitlab-runner
sudo chmod -R 777 /home/gitlab-runner
注意这里有个坑:远端拉下来的代码文件很可能在linxu下没有执行权限,我们可能会遇到permission denied的情况,这时候需要手动加权限 sudo chmod -R 777 /project_name ,然后使项目中的文件都可读写;再进行一个无关的修改,提交到远端分支,这样以后clone或者fetch下来的项目都是可读写的了。
一顿操作之后如果发现gitlab setting runner左边(例图2)这里有一个绿点证明我们刚刚挂载成功了,如果是红点和黑点,可能需要手动启动runner一下
sudo gitlab-ci-multi-runner start
4,编写一个简单shell脚本去操作我们的前端文件
因为我极少接触shell,所以这里也是参考其他大佬的简单写法,因为我的前端文件在/www/wwwroot/下,所以这里执行的操作就是去这个目录自动拉代码并且编译,然后把这个文件放到/usr/local/bin/ ,放这里只是方便全局执行,其实也可能用其它方式去调用,任君选择,注意这玩意没后缀。
注:这里只是简单演示其基本原理,作为实际生产的ci,我们其实应该编译目录和线上目录是分开的,专门有一份文件进行这些拉/装/编/合的操作,最后进行替换才能减少用户被影响的时间,如果真的像如下这样搞,那用户等编译白屏这个过程2,3分钟,岂不日了狗。
deploy
# echo "更新代码...."
cd /root/../www/wwwroot/项目目录/
git pull
# build
echo "正在构建..."
npm install
npm run build
echo "构建成功...."
5,我们还需要一份.gitlab-ci.yml(这是建立连接的关键)
我们的项目一级目录添加一个.gitlab-ci.yml,里面内容大概就是我们runner定义的,意思是在我们master分支有变动时,触发钩子自动执行deploy脚本
https://gitlab.com/szdubinbin1/tryci/blob/master/.gitlab-ci.yml
stages:
- deploy
deploy:
stage: deploy
script:
- deploy
only:
- master
tags:
- my-runner
最后,测试一下
当我们的master代码发生变化(因为我懒,所以我用的是create-react-app脚手架做的测试),gitlab项目的ci/cd这里就可以看到我们执行的runner(图3)
passed就是成功了,当然,光看这里是不行的,如果拉取git代码失败,它还是提示passed,原因猜测可能是它监测到shell脚本跑完就觉得ok的,这里还需要看一下jobs
我们可以发现在jobs(图4)它会反馈我们整个shell脚本、包括拉代码/装依赖/编译打包的过程,如果如下,具体项目可能不同,我这个是react,理论上vue打包成功也差不多这样,这时候我们刷新自己的项目地址就会发现修改生效了。
坑
1,跑脚本的时候,npm install可能会说权限不够,这时候只能去修改项目目录的权限
2,跑脚本的时候,git说没有ssh key,原因是我们刚开始添加的是root的ssh key ,gitlab runner可能用不了,解决方案:切到gitlab runner用户去添加一个ssh key
命令:su gitlab-runner => 添加ssh key
因为公司使用这个方案,不过当然比我这个高级的太多,我们重在实践了解一下前端自动化部署的大概流程,说不定哪天这玩意真的需要我们自己搭呢?折腾了这玩意一天,有一些莫名其妙的坑,不过好在都算解决了,真的感觉这玩意太高效率了,以后自己做项目就不用去服务器拉代码了。