敏捷开发
- 敏捷开发以用户的需求进化为核心,采用迭代、循序渐进的方法进行软件开发。 在敏捷开发中,软件项目在构建初期被切分成多个子项目,各个子项目的成果都经过测试,具备可视、可集成和可运行使用的特征。
持续集成
Travis CI 提供的是持续集成服务(Continuous Integration,简称 CI)。它绑定 Github 上面的项目,只要有新的代码,就会自动抓取。然后,提供一个运行环境,执行测试,完成构建,还能部署到服务器。
持续集成指的是只要代码有变更,就自动运行构建和测试,反馈运行结果。确保符合预期以后,再将新代码"集成"到主干。
持续集成的好处在于,每次代码的小幅变更,就能看到运行结果,从而不断累积小的变更,而不是在开发周期结束时,一下子合并一大块代码。
Travis CI
Travis-CI是一个开源的持续构建项目,能够测试和部署;Travis-CI会同步你在GitHub上托管的项目,每当你Commit Push之后,就会在几分钟内开始按照你的要求测试部署你的项目。
-
注意:Travis CI分为
- Github公开项目:http://travis-ci.org/
- Github私有付费项目(私有库):http://travis-ci.com/
官方文档可查看https://docs.travis-ci.com/
本博客主要针对私有项目
使用 Travis CI
- 登录Travis-CI,使用自己的GIthub账号即可,确认接收访问Github的权限
- 登录之后,Travis-CI就会同步你GitHub账号的仓库。然后打开个人页面并给你想要构建的项目启用Travis-CI。
选择需要进行测试的私有项目,然后在github上开放权限。
然后就可以看到该项目的build界面了:
现在就完成了创建工作,接下来需要编辑.travis.yml文件
.travis.yml文件
Travis 要求项目的根目录下面,必须有一个
.travis.yml
文件。这是配置文件,指定了 Travis 的行为。该文件必须保存在 Github 仓库里面,一旦代码仓库有新的 Commit,Travis 就会去找这个文件,执行里面的命令。这个文件采用 YAML 格式。如果需要系统地学习,官方文档是个好选择,本博客只介绍通常会使用的语法,而且由于本博客是基于django项目,因此yml文件也是提供给python环境的。
运行流程
- Travis 的运行流程很简单,任何项目都会经过两个阶段。
- install 阶段:安装依赖,用来指定安装脚本。
install:
- command1
- command2
注:
如果command1失败了,整个构建就会停下来,不再往下进行;
如果不需要安装,即跳过安装阶段,就直接设为true。
install: true
- script 阶段:运行脚本,用来指定构建或测试脚本。
script:
- command1
- command2
注:script与install不一样,如果command1失败,command2会继续执行。但是,整个构建阶段的状态是失败。
如果command2只有在command1成功后才能执行,就要写成下面这样。
script: command1 && command2
Travis钩子
- Travis 为上面这些阶段提供了7个钩子。
- before_install:install 阶段之前执行
- before_script:script 阶段之前执行
- after_failure:script 阶段失败时执行
- after_success:script 阶段成功时执行
- before_deploy:deploy 步骤之前执行
- after_deploy:deploy 步骤之后执行
- after_script:script 阶段之后执行
- 完整的生命周期,从开始到结束是下面的流程。
- before_install
- install
- before_script
- script
- aftersuccess or afterfailure
- [OPTIONAL] before_deploy
- [OPTIONAL] deploy
- [OPTIONAL] after_deploy
- after_script
运行状态
- Travis 每次运行,可能会返回四种状态
- passed:运行成功,所有步骤的退出码都是0
- canceled:用户取消执行
- errored:before_install、install、before_script有非零退出码,运行会立即停止
- failed :script有非零状态码 ,会继续运行
环境变量
env:
- DJANGO_VERSION=1.9.5 DB=mysql
有些环境变量(比如用户名和密码)不能公开,这时可以通过 Travis 网站,写在每个仓库的设置页里面,Travis 会自动把它们加入环境变量。这样一来,脚本内部依然可以使用这些环境变量,但是只有管理员才能看到变量的值。
一般不推荐在travis上使用项目真实的config配置文件,如果非得使用,需要进行加密操作。
例子
以下是我们项目的例子,使用的python环境是3.5,需要安装django,django的数据库指定为mysql,另外在requirements.txt放置python依赖的包,在test之前进行数据库的初始化操作。
configs.json是我们的本地配置文件,而configs.example.json是测试配置文件(这种方式得感谢一位同学的帮助,我们之前是通过对config.json进行加密从而完成配置的。),因此这样测试环境和运行环境实际上是完全独立的。
language: python
sudo: required
python:
- '3.5'
services:
- mysql
env:
- DJANGO_VERSION=1.9.5 DB=mysql
#branchs:
# only:
# - master
install:
- pip install -r requirements.txt
- mv configs.example.json configs.json
before_script:
- mysql -e "create database IF NOT EXISTS wechat_ticket;"
- python manage.py makemigrations
- python manage.py migrate
script:
- python manage.py test
如果build成功,则会显示这样的图标:
为了将此图标放置于我们的github上,只需要点击该图标,选择markdown
最后将其内容复制到Github上的README下即可,最终结果为:
这样,就基本完成了Travis CI在Github上的部署,接下来是一些进阶操作
Travis使用SSH免密登陆服务器
要想通过Travis在执行服务器得脚本首先得登陆到我们得服务器,但是在Travis不像交互式终端。一般利用用户名和密码登陆是需要输入用户名,密码的,但是Travis里面没有提供与用户交互的界面,当然这也与自动化不符,所以我们只有利用其他方式登陆--SSH免密登陆。
SSH的登陆原理大家可以看这个:SSH公钥登陆原理。大概过程就是,在客户端生成一个公钥/私钥对,将公钥内容保存到服务器 ~/.ssh/authrized_keys 中,然后客户端发起连接请求时,服务器发送一个字符串给客户端,客户端用本地的私钥对字符串进行加密然后发送给服务器,服务器将收到的加密字符串用公钥解密,如果能解密成功就登陆成功。
这里的公钥/私钥对就是登陆的关键,我们不能直接操作Travis服务器,在上面生成公钥/私钥对,所以按照上面正常的流程就走不通,这时候就需要让Travis伪装成一个受信的客户端去连接。也就是我们需要有一对公钥/私钥对,公钥已经保存在我们的Linux服务器中,私钥保存在某个Travis能访问到的地方,在必要的时候用这个私钥去连接服务器,这里我们可以把私钥放在Git代码仓库中,但是直接把私钥放代码中不安全,所以Travis提供了对私钥进行加密的功能,我们可以把私钥加密之后放在代码仓库,在登陆的时候Travis解密该私钥用于连接。
具体操作可以参考上述链接
Travis 加密文件
- 安装linux客户端Travis
安装ruby
> ruby -v
显示ruby 2.0.0p195 (2013-05-14 revision 40734) [x86_64-darwin12.3.0]以上信息
> sudo gem install travis -v 1.8.9 --no-rdoc --no-ri
如果有报错:mkmf.rb can't find header files for ruby at /usr/lib/ruby/include/ruby.h
运行> sudo apt-get install ruby-dev
然后> sudo gem install travis -v 1.8.9 --no-rdoc --no-ri
> travis version
1.8.9
> sudo gem install travis --pre
- 安装完成后只需要生成对应的私钥文件了
travis login
travis encrypt-file config.json --add
- --add自动将配置信息添加到yml文件中
- openssl aes-256-cbc -K ****_key -iv _****_iv -in *************
最终的文件:
language: python
sudo: required
python:
- '3.5'
services:
- mysql
env:
- DJANGO=1.9.5 DB=mysql
branchs:
only:
- master
before_install:
- openssl aes-256-cbc -K ****_key -iv _****_iv -in *************
- chmod 600 configs.json
install:
- pip install -r requirements.txt
before_script:
- mysql -e "create database IF NOT EXISTS wechat_ticket;"
- python manage.py makemigrations
- python manage.py migrate
script:
- python manage.py test
- 尽管最终我们没采用加密方式,但是这种方式仍然有意义。
- 注意权限