将我们的代码分解为可重用的位之后,我们如何测试和部署?


9

我们从一个开发人员开始,然后是一个包含我们所有代码的svn存储库:

^/foo/trunk/module-a
^/foo/trunk/module-b
^/foo/trunk/module-b/submodule-b1
^/foo/trunk/website1

(当时是一个很大的进步)。在这有了长足发展的机会之后,我们开始遇到循环依赖项,缓慢的测试套件以及重用代码的一般困难的问题(因为例如website1的功能集已潜入其他通用模块-a中)。

想要对代码库进行模块化,并希望我们不久就迁移到git(并且已经读过git不喜欢svn mega-repos的地方),我们已经过渡到了更精细的结构:

^/module-a/trunk/
^/module-b/trunk/
^/module-b/trunk/sumbmodule-b1
^/earlier-sub-sub-sub-module-c/trunk
etc. (about 120 such modules)

从概念上讲,这很棒。更多的模块化代码,更快的测试套件,更容易记录的文档,等等。我们开源了一些更通用的组件,并使所有模块都可以pip安装(pip install -e .用于将它们安装在developmentvirtualenv中)。

我们创建了一个^/srv/trunk存储库,其中包含运行时环境的文件夹结构。^/srv/trunk/lib用于模块,/srv/trunk/src用于的其余部分^/foo/trunk^/srv/trunk/www用于网站等。

最后(从我很久以前与perforce合作的[ https://www.perforce.com/perforce/r12.1/manuals/cmdref/client.html]中吸取灵感),我们创建了一个“ vcs-提取”文本文件,其中列出了所有相关的存储库以及应将其检出到开发环境中的位置,并提供了相应的命令来执行此操作。例如vcs-fetc行:

svn srv/lib/module-a ^/module-a/trunk

会导致(第一次)

cd /srv/lib && svn co ^/module-a/trunk module-a

或(之后)

cd /srv/lib/module-a && svn up

同样适用于github repos(我们自己的和更改/未更改的供应商软件包)。

我们使用了相同的vcs-fetch流程来创建生产环境,但是我们很快发现,在进行vcs-fetch之后,我们无法知道哪个版本在prod中运行。

对于大型仓库,我们可以在从主干更新产品之前记下修订号,然后回去就很简单svn -r nnn up .了。使用svn和git中的代码(以及hg中的一个模块)以及〜120个仓库,如何执行此操作并不明显。

我今天读了http://12factor.net/,第一个因素是“一个代码库”,所以我也想知道我是否在正确的道路上走?

我曾经想到的一个想法是创建一个部署脚本,该脚本将创建可pip安装的“部署”轮,并将它们“捆绑”在一个requirements.txt文件中。然后,部署将涉及创建新的virtualenv,点安装列出部署轮的requirements.txt文件,并切换活动的virtualenv。恢复到先前的状态仅涉及将virtualenv切换回去(但是除非我们希望永久保留virtualenv,否则不允许我们回到任何时间点-尽管根据我的经验,这是从未需要的)。

在这一点上,我想知道我是朝错误的方向行走,还是只是在正确的道路上走的不够远。(我正在阅读的所有内容都在谈论“您的应用”,而且我不知道这将如何转化为使用相同的代码库运行14个网站...)


我是否可以假定各个组件现在由具有不同开发周期的不同团队开发?如果是这样,则无论如何都无法避免将存储库拆分。即使使用git,您也可以为主要的稳定配置放置同步的发行标签。看看Google的回购工具。试图通过集成元数据匹配开发版本是徒劳的。通过pip将应用程序链接在一起也是完全合法的。
Ext3h '16

如果您包括估算值KLOC(1000行代码)和代码的字节度量,我们可以轻松了解大小,例如“ 2000行代码。50KB源代码”。或“ 40 KLOC,2 GB XML”。。看来您只需要迁移到git,而git具有导入功能。您可以先阅读git书
尼克拉斯

1
@ Programmer400的代码库是.py 670 kloc,.js:135kloc,.less:25kloc,.html:130kloc。很大,但不很大。从我读过的git来看,我真的不喜欢这种大小的存储库,所以我想我们在切换到git之前必须先拆分成较小的存储库。
thebjorn '16

Answers:


2

听起来您好像缺少分支(或者说是“标签”或“发布”分支)。

不应使用SVN revnum作为参考来确定要安装的版本,而应在该发行版本中创建一个分支。然后,您部署该分支名称。

即使没有更改,它也使分支变得更容易,因此每个模块都保持相同的发行版号,但是OSS软件包可能不希望分支没有更改,因此,下一个最好的事情是保留依赖项脚本-第5版您的产品需要OSS模块X v2,依此类推。

您将更改脚本以停止引用版本,而是使用分支名称(尽管它们可以是任何名称,但最好确定固定的命名约定,例如Release_1_2_3)

另一个提示是维护一个文件,其中每个模块都描述当前版本,如有必要,您可以自动生成这些文件,并且可能还包括完整的变更日志,但这意味着任何人都可以通过查看来查看部署了哪个版本。


1

我认为您已经有了很多好主意,这些年来,我已经在许多不同的项目中使用了其中的大部分主意,并且您主要担心的是,如果您拆分了某个给定的程序包,则无法分辨出所有模块的哪个版本他们起来。

我全都以某种程度的粒度将它们拆分,尤其是如果您有多个团队并且发布周期不同,就像@ Ext3h提到的那样。

由于我不确定模块的隔离程度或版本控制的详细程度,因此建议使用一些选项。


使用git子模块。使用子模块,您可以将每个模块存储在单独的git repo中,类似于svn设置,以及您要考虑的内容。然后,您将这些模块链接到根项目,该根项目将包含对每个子模块各自提交的相关提交的引用。

IMO这是一个理论上不错的设置,并且相当简单。主要缺点是子模块的工作流程有点笨拙,但是您之前似乎已经用脚本很好地解决了这些问题,所以这可能不是一个真正的问题。

另一个警告是,子模块提交引用将只是SHA1,关于您所在的分支从来没有任何人类可读的细节,当您想直接在子模块中工作时,最终可能不得不手动签出正确的分支。

但是,我没有广泛使用这种模式,所以我不知道对于像您这样的大型项目来说,这可能有多少问题。


另一种选择是使用某种依赖管理器。这就要求每个模块或每个模块集都可以分别进行版本控制,打包和发布,并且您需要一个系统,可以根据需要将它们打包在一起。

您已经在建议点子,建议中似乎遗漏的是将生成的requirements.txt与构建一起存储,或存储在根项目存储库中,以便您以后可以重新创建virtualenv而不用保存它在磁盘上。

还有其他系统。我使用一个稍微定制化的版本的Apache Ivy设置了一个相当大的项目,将其作为打包和发布每个模块的工具,并将它们组合在一起以用于最终项目。如果您以后需要重新创建安装程序,Ivy还会存储一个清单,列出您所引用的所有模块的所有版本。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.