动机
很多脚本语言其实没有“编译”的过程,不需要真的输出一个“构建物”。那么在CRP上是否有更加轻量的部署方式呢?答案就是直接使用git更新的方式。本文会详细讲述这一方式。
不必要的“打包”
前面我们发表两篇文章分别描述了Ruby和
Java在CRP上的持续交付实践。两篇文章中都使用了下面的配置来对代码库进行编译打包:
不同之处是Java打的是一个war包,而Ruby打的其实是源码的压缩包,因为Ruby不需要真正的“编译”过程。这就是编译型语言和脚本型语言之间的显著差别。
除了Ruby之外,脚本语言还包括node、python、php等。他们都可以使用统一的一种方式进行部署,那就是直接更新源码,然后执行相应的包更新操作,比如bundle install
、npm install
、go get
等。然后再执行重启操作即可。那么更新代码应该更新到那个版本呢?如果只是简单的更新到master版本,那么在master分支上有更新之后,这个操作就不等价了。而CRP的一条工作流实例应该对应某个特定的提交版本号,无论运行过多少次rerun
甚至回滚,这个版本号应该都是不变的。在部署任务中,可以使用CODE_VERSION
这个环境变量来获取该版本。所以对于脚本语言的部署就可以使用如下的通用模式:
git checkout . #保证本地没有修改
git fetch #更新本地历史
git checkout $CODE_VERSION #更改到本次工作流实例所对应的版本
#更新依赖,并重启应用
package.tgz怎么办?
你可能注意到了,在这种模式package.tgz
其实已经用不到了。但目前CRP还没有去除填写部署路径的选项。你仍然可以填写一个路径,但事实上没有使用这个文件,而是使用git checkout
的方式进行更新和部署。
我失去了什么?
之前使用package.tgz
的目的是为了保证工作流的一次运行产生一个唯一的状态,这样就能保证当我回滚时就真的回到了这个版本。那么使用git checkout
的方式后,这个承载唯一状态的package.tgz
就形同虚设了。但我们并没有失去这个状态的唯一性,因为我们还有CODE_VERSION
。只要我checkout
的是同一个版本,应用就应该展现出同样的行为。所以虽然不再使用package.tgz
,但我并没有失去这个唯一性和历史的可追溯性。