持续集成:Continuous Integration,简称CI,意思是,在一个项目中,任何人对代码库的任何改动,都会触发CI服务器自动对项目进行构建,自动运行测试,甚至自动部署到测试环境。这样做的好处就是,随时发现问题,随时修复。因为修复问题的成本随着时间的推移而增长,越早发现,修复成本越低。
Travis CI是在线托管的CI服务,用Travis来进行持续集成,不需要自己搭服务器,在网页上点几下就好,用起来更方便。最重要的是,它对开源项目是免费的。
关联github和TravisCI
github+TravisCI是一对好基友,现在很多开源项目都使用了Travis CI服务,你通常可以在相关项目的readme.md
中的一开头看到文章开头的图片:build pass
。这是个实时显示的图标,表示编译通过。
是不是看起来非常酷?要怎么才能做到呢?请按照以下步骤:
- 用github账号登录并授权Travis CI
- 在右上角你的账户名点击进入 account,在Repositories tab页点击Sync now同步你的github项目
- 选中项目将默认的off改变为on开启项目的持续集成
- 在你项目的根目录建立一个.travis.yml文件,按照规则编写。
- 修改readme.md增加图标,markdown语法这样写:
github_id:就是你的github登录名,repo_name就是你的仓库名字。[![Build Status](https://travis-ci.org/<github_id>/<repo_name>.svg?branch=dev)](https://travis-ci.org/<github_id>/<repo_name>)
- 进行git push操作就可以触发Travis CI的进行集成构建。
.travis.yml规则
首先官方的doc在这里:docs。
简单的说,Travis CI并不帮你规定如何构建如何检查,所有规则与工具应该是你提供的或者能找到的,它只帮你提供了一个满足你项目构建检查的一个环境,包括操作系统类型等麻烦的事情。
一个构建的流程,在.travis.yml中体现下面
- apt addons,简单地说就是通过apt包管理器来安装一些依赖包(可选的安装)
- cache(可选的安装):缓存一些不常改变的东西,加快编译速度
- before_install,在install标签之前的动作
- install,安装依赖或者工具
- before_script:script执行之前,可选
- script:这个标签下的动作是由bash来解析的,这里放构建的主要步骤
- before_cache(可选的安装),用于清除cache
- before_deploy:部署之前,可选
- deploy:部署,可选
- after_deploy:部署,可选
- after_script:script执行之后,可选
- after_success:构建成功之后的动作
- after_failure:构建失败之后的动作
下面是install
标签,而且有两个步骤,多个步骤就用-
开始。
install:
- bundle install --path vendor/bundle
- npm install
如果before_install,install或者before_script返回非0,那么构建将立即停止并提示错误。
而script则会继续执行。
after_success, after_failure, after_script这三个标签对构建的结果没有任何影响。
指定repo分支:
# blocklist
branches:
except:
- legacy
- experimental
# safelist
branches:
only:
- master
- stable
还可以用正则表达式来匹配:
branches:
only:
- master
- /^deploy-.*$/
一般来说,复杂的构建过程,不应该直接写在.travis.yml
中,而是应该在仓库里面写好构建脚本,然后再从.travis.yml
中调用。
这么说,你就知道了,TravisCI只是提供个方便的构建环境而已。
安装依赖
apt包管理器:
before_install:
- sudo apt-get -qq update
- sudo apt-get install -y libxml2-dev
第三方ppa:
before_install:
- sudo add-apt-repository ppa:ubuntu-toolchain-r/test -y
- sudo apt-get update -q
- sudo apt-get install gcc-4.8 -y
没有apt也没有ppa的:
before_install:
- wget http://pngquant.org/pngquant_1.7.1-1_i386.deb
- sudo dpkg -i pngquant_1.7.1-1_i386.deb
Apt Addon
addons:
apt:
sources:
- deadsnakes
- sourceline: 'ppa:ubuntu-toolchain-r/test'
- sourceline: 'deb https://packagecloud.io/chef/stable/ubuntu/precise main'
key_url: 'https://packagecloud.io/gpg.key'
其中sourceline将后面获取的文本添加到/etc/apt/sources.list
key_url后面的是GPG keys.
addons:
apt:
packages:
- cmake
- time
addons:
apt:
sources:
- lucid
packages:
- libcxsparse3.1.2
macOS
before_install:
- brew update
- brew install beanstalk
缓存那些不经常变的东西,加速构建过程:
cache:
directories:
- .autoconf
- $HOME/.m2
构建的环境变量
典型的设置,这样的设置将触发两次构建,分别以这些变量的不同值来构建
env:
- FOO=foo BAR=bar
- FOO=bar BAR=foo
多操作系统
os:
- linux
- osx
before_install:
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew update ; fi
- if [[ "$TRAVIS_OS_NAME" == "osx" ]]; then brew install graphviz; fi
TRAVIS_OS_NAME
表示操作系统的类型
允许某个操作系统上的失败:
matrix:
allow_failures:
- os: osx
matrix:
include:
- os: linux
dist: trusty
sudo: required
- os: osx
osx_image: xcode7.2
矩阵
matrix
是一个这样的标签,用于处理矩阵编译的情况,比如说:
rvm:
- 1.9.3
- 2.0.0
- 2.2
- ruby-head
- jruby
- rbx-2
- ree
gemfile:
- gemfiles/Gemfile.rails-2.3.x
- gemfiles/Gemfile.rails-3.0.x
- gemfiles/Gemfile.rails-3.1.x
- gemfiles/Gemfile.rails-edge
env:
- ISOLATED=true
- ISOLATED=false
上面的定义将形成7 * 4 * 2=56种不同的构建,这就是所谓的矩阵。
matrix:
exclude:
- rvm: 1.9.3
gemfile: gemfiles/Gemfile.rails-2.3.x
env: ISOLATED=true
- rvm: jruby
gemfile: gemfiles/Gemfile.rails-2.3.x
env: ISOLATED=true
上面的就实际上排除了56种情况中的两种,现在剩下54种构建的情况。
除了exclude
还有include
,可以特定加入一种特殊的情况,这样做的好处是再不让矩阵变大的情况下,拥有更大的灵活性。
matrix:
include:
- rvm: ruby-head
gemfile: gemfiles/Gemfile.rails-3.2.x
env: ISOLATED=false
注意ruby-head
是上面矩阵里面没有的。
通知
notifications:
email:
- one@example.com
- other@example.com
全部关闭:
notifications:
email: false
条件控制:
notifications:
email:
recipients:
- one@example.com
- other@example.com
on_success: [always|never|change] # default: change
on_failure: [always|never|change] # default: always
always
和never
表示总是发送或者从不发送,change
表示状态改变的时候发送.
通过irc来通知:
notifications:
irc:
channels:
- "chat.freenode.net#my-channel"
- "chat.freenode.net#some-other-channel"
on_success: [always|never|change] # default: always
on_failure: [always|never|change] # default: always
自定义消息类型:
notifications:
irc:
channels:
- "chat.freenode.net#my-channel"
- "chat.freenode.net#some-other-channel"
template:
- "%{repository} (%{commit}) : %{message} %{foo} "
- "Build details: %{build_url}"
在vim项目中使用travisCI
楼主是个vim爱好者,所以用这个来介绍😝
仓库地址:vimagit
language: python
branches:
only:
- master
- next
- /^dev\/.*$/
os:
- linux
# - osx
env:
- VIM_VERSION=normal
- VIM_VERSION=last
- VIM_VERSION=neovim
- VIM_VERSION=macvim
matrix:
exclude:
- os: osx
env: VIM_VERSION=last
# neovim build fails with homebrew
# Error: undefined method `desc' for Neovim:Class
- os: osx
env: VIM_VERSION=neovim
- os: linux
env: VIM_VERSION=macvim
install:
- if [ "$TRAVIS_OS_NAME" = 'osx' ]; then
if [ "$VIM_VERSION" = 'neovim' ]; then
brew tap neovim/neovim &&
brew tap --repair &&
brew install --HEAD neovim;
elif [ "$VIM_VERSION" = 'macvim' ]; then
brew install macvim;
elif [ "$VIM_VERSION" = 'normal' ]; then
echo "use normal vim";
else
echo "VIM_VERSION is not set";
exit 1;
fi
elif [ "$TRAVIS_OS_NAME" = 'linux' ]; then
if [ "$VIM_VERSION" = 'last' ]; then
sudo add-apt-repository -y ppa:fcwu-tw/ppa &&
sudo apt-get -qq update &&
sudo apt-get -qq -f install &&
sudo apt-get -qq install vim;
elif [ "$VIM_VERSION" = 'neovim' ]; then
sudo add-apt-repository -y ppa:neovim-ppa/unstable &&
sudo apt-get -qq update &&
sudo apt-get -qq -f install &&
sudo apt-get -qq install neovim;
elif [ "$VIM_VERSION" = 'normal' ]; then
echo "use normal vim";
else
echo "VIM_VERSION is not set";
exit 1;
fi
fi
before_script:
- git clone https://github.com/jreybert/djooks
- git clone https://github.com/jreybert/vader.vim
script:
- ./test/run.sh . vader.vim djooks $VIM_VERSION
after_success:
- ./test/merge.sh
一个标签一个标签说:
第一个branches
这里选择了master,next和dev开头的分支来编译
os
选择了linux
env定义了VIM_VSERION
用于下面的install标签,也表示以此将有四种不同的编译。
matrix
:排除了一些构建的情况:osx下不要编译VIM_VERSION=last,neovim,macvim
install
标签,根据VIM_VERSION变量进行依赖的安装
before_script
:clone了两个工具
script
:执行了本仓库下的test/run.sh脚本
after_success
:如果成功,执行本仓库下的./test/merge.sh脚本,查看其内容是将非主分支的合并到主分支中
本人并不使用示例中的vader.vim工具,而是采用更强大的:Kuniwak/vint
和syngan/vim-vimlint
具体使用与按照看连接,并非本文内容。
网友评论