名词解释
持续集成
持续集成强调开发人员提交了新代码之后,立刻进行构建、(单元)测试。根据测试结果,我们可以确定新代码和原有代码能否正确地集成在一起。
简单来说,就是每次提交代码的时候,都进行构建、测试等。
持续交付
持续交付在持续集成的基础上,将集成后的代码部署到更贴近真实运行环境的「类生产环境」(production-like environments)中。比如,我们完成单元测试后,可以把代码部署到连接数据库的 Staging 环境中更多的测试。如果代码没有问题,可以继续手动部署到生产环境中。
简单来说,就是代码通过测试后,将其部署到测试环境。
持续部署
持续部署则是在持续交付的基础上,把部署到生产环境的过程自动化。
简单来说,就是代码通过测试后,将其部署到生产环境。
总结:严格来说,持续部署依赖于持续交付,持续交付依赖于持续集成。但是这毕竟只是理论,在实际运用中,可以不用纠结于规范,只实现其中一部分。
参考自: www.zhihu.com/question/23…
travis ci 教程
官方文档: docs.travis-ci.com/user/tutori…
1. 开始
- 进入travis-ci.com/,使用 GitHub 登录。(目前支持 GitHub 、 Bitbucket、 GitLab 及 Assembla. 除GitHub 外,其余三个都还是 beta 版本)
- 点击右上角的 头像-> Setttings ,再点击左侧的 sync account 按钮,即可将 GitHub 的仓库同步至 travis。
3. 在你的仓库下新建 .travis.yml
文件,书写为以下内容,提交后即可触发。
language: node_js
node_js:
- 14
install:
- npm install
script: npm run test
- 提交代码后,即可在 travis-ci 上面看到当前的构建状态。
2. yaml1.1语法
yaml.org/spec/1.1/
travis ci 使用的是 Ruby libYAML 库,所以 .travis.yml
必须采用 YAML 1.1。
- 所有的引号和逗号都可以省略,注意:冒号后的空格不可省略
key1: 213
key2: dsas string
- 行首的空格缩进数量代表数据的层级
obj1:
key1: sad
obj2:
key2: 1.23
nestedObject:
key3: 'quoted string'
- 以 连字符 + 空格 开头,表示数组元素
- 42
- "double-quoted string"
- arrayElement3:
key1: punctuations? sure.
- 引用
object1: &o1
key1: value1
object2:
key2: value2
key3: *o1
# 相当于json
{
"object1": {
"key1": "value1"
},
"object2": {
"key2": "value2",
"key3": {
"key1": "value1"
}
}
}
- 继承
object1: &o1
key1: value1
key2: value2
object2:
<<: *o1
key3: value3
# 相当于json
{
"object1": {
"key1": "value1",
"key2": "value2"
},
"object2": {
"key1": "value1",
"key2": "value2",
"key3": "value3"
}
}
3. 自定义travis ci build
1. 定义构建分支
except定义黑名单,only定义白名单。通常只使用其中一个,容易引起误解。因为使用 only 时,即使不符合 except ,如果在 only 中也不存在,也不会进行构建。
# 黑名单
branches:
except:
- dev
- /^no-.*/
# 白名单
branches:
only:
- master
- /^ci-.*/
2. 跳过构建
只要提交信息包含 [<KEYWORD> skip]
或者 [skip <KEYWORD>]
等信息,即可跳过构建。
KEYWORD
包括 ci, travis, travis ci, travis-ci, or travisci
。
只要提交信息包含 [<KEYWORD> skip]
或者 [skip <KEYWORD>]
等信息,即可跳过构建。
3. 构建矩阵
如下就形成了一个 3*2
的矩阵,npm test
默认将会运行 6 次,可通过下文所示的方法进行排除或包含指定环境。
language: node_js
node_js:
- 14
- 12
- 10
env:
- DB=1
- DB=0
script: npm test
4. job 作业
job的生命周期有如下几种:
apt addons
cache components
before_install
install
before_script
script
before_cache
(当且仅当缓存有效)after_success
orafter_failure
before_deploy
(当且仅当部署处于活动状态时)deploy
after_deploy
(当且仅当部署处于活动状态时)after_script
拿 script
举例来说
# 可以字符串
script: npm test
# 可以用数组
script:
- npm run test
- npm run build
# 命令复杂时可用 shell 脚本
script: ./install.sh
# 值为skip 表示 跳过
script: skip
5. stage 阶段
以下配置表示:先进行 test 阶段的 2个作业,然后在 deploy 阶段开始第3个作业。
jobs:
include:
- stage: test
script: ./test 1
- # 阶段名不是必要的,将沿用之前的 test
script: ./test 2
- stage: deploy
script: ./deploy
stage 的顺序也可以定义:
stages:
- compile
- test
- name: deploy
if: branch = master
6. 条件判断
- 有条件的构建
# 只有 master分支会触发 (注意对 PRs 来说这是 base branch 的 name)
if: branch = master
- 有条件的 Stages
下面的 stage 只会在 master 分支触发。
stages:
- name: deploy
if: branch = master
- 有条件的 Jobs
jobs:
include:
if: branch = master
env: FOO=foo
- 有条件的排除 Jobs
下面的例子会创建 2 个 job,但是只有 master 分支,env ONE=one
生效。
env:
- ONE=one
- TWO=two
jobs:
exclude:
- if: branch = master
env: TWO=two
- 此处条件判断可使用的 keyword
- type (the current event type, known event types are: push, pull_request, api, cron)
- repo (the current repository slug owner_name/name)
- branch (the current branch name; for pull requests: the base branch name)
- tag (the current tag name)
- commit_message (the current commit message)
- sender (the event sender’s login name)
- fork (true or false depending if the repository is a fork)
- head_repo (for pull requests: the head repository slug owner_name/name)
- head_branch (for pull requests: the head repository branch name)
- os (the operating system)
- language (the build language)
- sudo (sudo access)
- dist (the distribution)
- group (the image group)
# 等式
if: 1 = 1
# 不等式
if: true != false
# 环境变量与 type 做比较
env(FOO) = type
# 正则表达式
if: branch =~ /^(one|two)-three$/
# 枚举
if: branch IN (one, other)
# 使用变量枚举
if: repo IN (env(ONE), env(OTHER))
# 布尔操作
if: branch = master AND env(FOO) = foo
branch = master OR env(FOO) = foo
branch = master AND env(FOO) = foo OR tag = bar
branch = master AND (env(FOO) = foo OR tag = bar)
NOT branch = master
# 方法调用,仅支持 env 和 concat
if: concat()
7. 脚本中支持的变量
这个大家自己看官方文档吧,不想CV了---
docs.travis-ci.com/user/enviro…
实战
1. 发布到npm
官方已集成该部分 docs.travis-ci.com/user/deploy…
该 yml 实现了:
- 仅在
master
及ci-
开头的分支触发构建 - 定义 stage 的顺序,先test,然后 publish(仅commit中存在release才会触发publish)
- job 排除 dev 分支及 commit 中存在 no-ci
- 名为 test 的 stage,运行
npm run test
- 名为 publish 的stage,运行
npm run bd
,然后执行 deploy - deploy需要设置
provider为npm,api_key为NPM TOKEN,以及 email
NPM TOKEN生成可参考www.axihe.com/edu/npm/wor…
- 如何查看您帐户上的token:
npm token list.
- 创建新token:
npm token create
注意: 为了避免隐私泄露,像NPM TOKEN 和 EMAIL
这些信息,建议大家在 travis ci 网站的面板上进行设置,如下所示。点击 ADD 按钮后,环境变量就添加成功了,并且默认是不可见的。
如果大家觉得 travis ci 网站也不可信的话,可以使用 travis ci提供的客户端进行加密。travis 使用 ruby 制作,并用gem发布。(windows有坑,如果是windows的话,推荐大家用子系统)
- 安装 ruby,然后就有 gem 了
gem install travis
travis login --github-token 你的GITHUB_TOKEN --com
travis encrypt SOMEVAR="secretvalue" --add --com
;需要在当前仓库的目录下执行- 该命令执行后,就会在 yml文件 中添加
secure: ".... encrypted data ...."
至 env
GITHUB TOKEN 生成步骤:
点击右上角的 头像 -> settings -> Developer settings -> Personal access tokens
,然后点击生成 token 即可,权限通常选择 repo 即可。
完整的 .travis.yml
如下所示:
language: node_js
node_js:
- 12
env:
- BUILD_NAME=bd
install:
- npm install
branches:
only:
- main
- /^ci-.*$/
stages:
- test
- name: publish
if: commit_message =~ /release/
jobs:
exclude:
- if: branch = dev OR commit_message =~ /(no-ci)/
include:
- stage: test
script: npm run test
- stage: publish
script: npm run $BUILD_NAME
deploy:
provider: npm
api_key: $NPM_API_KEY
email: $EMAIL
on:
branch: main
2. 集成 github page
与上面大体类似,需要注意的是:运行构建脚本后,生成的文件在位于当前仓库的 dist
文件夹,部署到 github page 的时候,我们可能只想要这个文件夹,那么可以使用 mv dist/ /tmp/demo
命令将 dist 移动到 其他目录,否则可能直接使用 local_dir
设置目录名会报错。
执行 deploy 时,会在其他目录新建一个文件夹,然后拉取指定分支名的代码,之前的构建和当前目录不在同一个目录,所以直接使用 dist
文件夹,那自然是不存在了。
以下实现的配置会在 main 分支,并且提交信息包含 pub page 时,才会触发。
language: node_js
node_js:
- 14
env:
- BUILD_NAME=bd
install:
- npm install
branches:
only:
- main
- "/^ci-.*$/"
notifications:
email:
recipients:
- $EMAIL_SELF
on_success: change # default: change
on_failure: always # default: always
stages:
- test
- name: page
if: commit_message =~ /pub\s+page/
jobs:
exclude:
- if: branch = dev OR commit_message =~ /(no-ci)/
include:
- stage: test
script: npm run test
- stage: page
script: npm run $BUILD_NAME && mv dist/ /tmp/demo
deploy:
provider: pages
cleanup: true
local_dir: /tmp/demo
token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
on:
branch: main
3. 发送文件到远程服务器
这里与上面的不同在于,需要发送文件到远程服务器,那就需要用ssh
协议连接。
travis ci构建过程不能输入或者中断,所以使用 ssh
登录服务器的时候,不能采用 用户名 + 密码,只能用 公钥和私钥 进行免密登录了。
1.实现免密登录
- 需要在本地生成公钥和私钥,使用
ssh-keygen -t rsa
,会在用户主目录下的 .ssh 文件夹内生成 id_rsa.pub(公钥) 和 id_rsa(私钥) 。 - 将 id_rsa.pub 公钥 写入到服务器对应用户主目录的
.ssh/authorized_keys
。远程机器的.ssh目录需要700权限,authorized_keys文件需要600权限 - 将 id_rsa 私钥通过
travis encrypt-file ~/.ssh/id_rsa --add
添加到当前目录的.travis.yml
中。 - 执行 CI 时,解密后的
id_rsa
文件要修改为 600 权限,chmod 600 ~/.ssh/id_rsa
,同时echo -e "Host $HOST_IP\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
,不校验目标IP,否则 ssh 第一次连接时,会出现选择输入,阻碍流程。
2. linux相关知识
ssh 用户名@主机IP -p SSH端口 "rm -rf ~/$DEST_DIR && mkdir ~/$DEST_DIR"
连接服务器执行相应命令scp -P 主机端口 -r dist/. 用户名@主机IP:~/$DEST_DIR
使用scp命令将本地的 dist 目录发送到服务器export DEST_DIR=`echo $TRAVIS_BRANCH | cut -d "-" -f 1`
截取分支名,qa-ci 获得 qa,并设置为DEST_DIR
变量
以下配置文件实现了 在 main 分支推送代码时,如果 commit 包含了 release
,就会将打包文件发送至远程服务器。
language: node_js
node_js:
- 14
env:
- BUILD_NAME=bd
install:
- npm install
branches:
only:
- main
- "/^.*-ci$/"
notifications:
email:
recipients:
- $EMAIL_SELF
on_success: always # default: change
on_failure: always # default: always
stages:
- test
- name: page
if: commit_message =~ /pub\s+page/
- name: publish
if: commit_message =~ /release/
jobs:
exclude:
- if: branch = dev OR commit_message =~ /(no-ci)/
include:
- stage: test
script: npm run test
- stage: page
script: npm run $BUILD_NAME && mv dist/ /tmp/demo
deploy:
provider: pages
cleanup: true
local_dir: /tmp/demo
token: $GITHUB_TOKEN # Set in travis-ci.org dashboard
on:
branch: main
- stage: publish
before_install:
# 解密
- openssl aes-256-cbc -K $encrypted_db599200e721_key -iv $encrypted_db599200e721_iv -in id_rsa.enc -out ~/.ssh/id_rsa -d
# 设置正确的权限
- chmod 600 ~/.ssh/id_rsa
# 目标IP不进行校验,防止阻碍流程
- echo -e "Host $HOST_IP\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
script:
# 构建脚本
- npm run $BUILD_NAME
# 截取分支名,ci-qa 获得 qa,并设置为 DEST_DIR 变量
- export DEST_DIR=`echo $TRAVIS_BRANCH | cut -d "-" -f 1`
# 删除远程目标文件夹,并新建目录(这一步需要自己衡量是否需要,一般个人开发建议删除)
- ssh travis@$HOST_IP -p $HOST_PORT "rm -rf ~/$DEST_DIR && mkdir ~/$DEST_DIR"
# 将本地文件上传到服务器
# dist/ 将会在目标文件夹下 存在一个 dist 文件夹
# dist/. 将直接存储dist目录下的所有文件,而不包括目录名
- scp -P $HOST_PORT -r dist/. travis@$HOST_IP:~/$DEST_DIR
# 上传文件完毕后,可能需要 启动服务 等,自行替换
- ssh travis@$HOST_IP -p $HOST_PORT "echo 'replace your exec';"
疑难总结
1. gem 安装慢
gem sources修改
gem sources --remove https://rubygems.org/
gem sources -a https://gems.ruby-china.com/
gem sources -l
2. ssh连接时 known_hosts 问题
# 目标IP不进行校验,防止阻碍流程
- echo -e "Host $HOST_IP\n\tStrictHostKeyChecking no\n" >> ~/.ssh/config
3. before_deploy脚本只能为 单个值,不支持数组
github: github.com/ma125120/vi…
gitee: gitee.com/ma125120/vi…
travis ci这次差不多就这样了,下一篇讲一讲 docker + jenkins
实现自动化部署。
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!