目录
前言
在真正开始接触持续化集成之前,始终有一种可望不可即的感觉,但就在某一天就突然想跟他较较劲,于是就自己搞了一套。为了纪念跟他相爱相杀的那段时间,就做下记录吧
一、搭建Jenkins环境
1. 下载Jenkins镜像
在你本地或者服务器执行docker pull jenkins/jenkins
下载jenkins镜像
Jenkins/jenkins版本的镜像自带长期稳定版本的jenkins,强烈推荐此版本
2. 开启Jenkins服务
执行docker run -it -d -p 80:8080 -v /jenkins_home:/var/jenkins_home jenkins/jenkins
- 在指定镜像中开启jenkins服务,并且穿透到宿主(执行docker命令的地方)
- 80指的是穿透到宿主的端口,8080指的是镜像中实际开启的端口
- /var/jenkins_home指的是镜像中jenkins服务所在的路径, /jenkins_home指的jenkins服务映射到宿主的服务路径,宿主的jenkins_home文件夹必须得手动创建
3. Docker填坑
-
如果要将Docker运行在服务器,CPU至少要2G。 我最初搞1G内存,在打Bundle过程中CPU直接飙到100%,整个服务被卡爆
-
我们可能会进入Docker镜像配置一些环境,配置完成以后要通过
docker commit
做保存,要不然容器重启以后所有的配置都会消失 -
启动镜像时要设置Jenkins在宿主环境的映射目录
镜像每次重启都不会保存此次运行的数据,如果不在宿主环境设置映射目录,每次启动都会将Jenkins给初始化,之前Jenkins的配置都会消失,启动时设置映射目录后,每次对Jenkin的改动都会映射到宿主环境的映射目录,启动时也直接读取宿主环境中的jenkins服务,而不会重启初始化Jenkins服务 -
可能会用到的docker命令
// 查看当前镜像 docker images // 查看当前运行的容器 docker ps // 启动容器并指定穿透到本地的端口和目录 docker run -it -d -p 80:8080 -v /app/jenkins_home:/var/jenkins_home wangliguang/jenkins // 登录Docker指定容器(-u 0代表使用root用户) docker exec -u 0 -it b06fae9dcf21 /bin/bash // 保存对容器的修改,后面跟的是容器id和镜像名 docker commit cb439fb2c714 wangliguang/jenkins // 删除当前镜像 docker rmi <镜像名字> //删除当前运行的容器, 后面加-f为强制删除 docker rm <容器id>
4. Jenkins填坑
- 直接下载自带Jenkins服务的镜像,强烈建议使用jenkins/jenkins镜像,因为这个镜像集成的Jenkins是LTS(长期稳定版)版本,另外这个镜像自带两个用户,分别为root和jenkins,打包操作默认是在jenkins用户下,因此要注意权限问题
- 刚启动Jenkins服务时,会提示让你安装一些插件,此时一定要选择安装他们推荐的插件。千万不要跳过想着以后再安装,因为作为初学者你压根就不知道你需要什么插件,而且跳过以后,在也不会推荐你安装插件。
- 打包完成以后,需要通过scp命令将产物上传到自己的服务器,如果配置过ssh后还是一直失败,建议检查一下ssh配置的是root用户还是jenkins用户,默认打包脚本时在jenkins用户下操作的
二、RN的Jenkins打包脚本
1. Jenkinsfile文件
pipeline {
agent any
environment {
HOME = '.'
}
stages {
stage('build') {
steps {
sh 'yarn install'
sh 'rm -rf .cache/'
sh 'whoami'
sh 'node ./node_modules/react-native/local-cli/cli.js bundle --platform ios --dev false --entry-file index.js --bundle-output ./index.bundle'
sh 'chmod 744 ./diff.sh && ./diff.sh'
}
}
}
}
2. diff.sh文件及实现逻辑
#! /bin/bash
localNewFile='./index.bundle'
# 已时间戳为文件名
newName=`date +"%s".bundle`;
scp $localNewFile root@xx.xx.xx.xx:/app/s_phoenix/public/bundle/$newName
count=`ssh root@xx.xx.xx.xx "cd /app/s_phoenix/public/bundle && ls -l | grep "^-" | wc -l"`
if [ $count -gt 8 ]; then
oldFile=`ssh root@xx.xx.xx.xx "cd /app/s_phoenix/public/bundle && ls -t * | tail -1"`
echo $oldFile
ssh root@xx.xx.xx.xx "rm /app/s_phoenix/public/bundle/${oldFile}"
fi
三、差分更新Bundle流程
1. 差分填坑
- 在Linux系统上可以通过
diff
和patch
命令做差分及合并,但由于这两个命令不能再Native层使用,因此推荐使用谷歌的Google-diff-match-patch
算法,这是一个跨平台框架,基本支持所有的主流语言。 - linux的
diff/patch
算法和Google-diff-match-patch
算法不一致,因此不能混着用,比如:使用linux的diff做差分,使用google算法做合并 - 我把该算法的Framework拖到iOS工程中会各种报错,最后还是直接将相关类直接拖到项目中
2. 如何使用Google-diff-match-patch
-
这个库提供了三个网页,分别来查看diff/match/patch的效果,
建议直接看patch,里面完整的展示了一个差分合并的流程, -
我当时仅仅看了diff,发现生成的差分文件不想我想要的,最后
查看patch的源码才发现少调用了一个api