Close

CI/CD Git:针对 CI 友好型 Git 代码存储库的五个提示

为成功做好准备——一切都始于您的存储库。

Sarah Goff Du-Pont 头像
Sarah Goff-Dupont

首席作家


Git 和持续交付是我们在软件领域偶尔会发现的美味“巧克力和花生酱”组合之一,这两种搭配起来真的超赞。因此,我想分享一些提示,让您在 Bamboo 中的版本在 Bitbucket 存储库中也能很好地发挥作用。他们的大部分互动都发生在持续交付的构建和测试阶段,所以您会注意到我主要是用 "CI" 而不是 "CD"。

1:将大文件存储在您的代码存储库之外


关于 Git,您经常听到的一件事是,您应该避免在存储库中放入大文件:二进制文件、媒体文件、存档构件等。这是因为一旦您添加了一个文件,它将永远存在于代码存储库的历史记录中,这意味着每次克隆存储库时,都会同时克隆那个庞大的文件。

从代码存储库的历史记录中提取文件很棘手——这相当于在代码库上进行正面额叶切除术。而且这种手术文件提取改变了代码存储库协议的整个历史记录,因此您再也无法清楚地了解发生了哪些变更以及何时进行了变更。通常情况下,避免使用大文件具备充分的理由。还有...

将大文件存储在 Git 代码存储库之外对于 CI 尤其重要

每次构建时,您的 CI 服务器都必须将您的代码存储库克隆到有效的构建目录中。而且,如果您的存储库中充斥着大量巨大的构件,它会减慢处理速度,增加开发人员等待构建结果的时间。

好吧,很好。但是,如果您的构建依赖于其他项目的二进制文件或大型构件呢?这种情况很常见,而且可能一直如此。所以问题是:我们如何才能有效地处理它?

查看解决方案

使用 Open DevOps 构建和操作软件

相关资料

了解基于主干的开发

像 Artifactory(为 Bamboo 制作加载项)、Nexus 或 Archiva 这样的外部存储系统可以帮助处理您的团队或您周围的团队生成的构件。您需要的文件可以在构建开始时被拉到构建目录中,就像您通过 Maven 或 Gradle 提取的第三方库一样。

专业提示:如果构件经常变更,请避免每天晚上将大文件同步到构建服务器,这样您只需要在构建时通过光盘传输即可。在夜间同步之间,您最终会使用陈旧版本的构件进行构建。另外,无论如何,开发人员都需要这些文件才能在本地工作站上构建。因此,总的来说,最干净的做法就是让构件下载成为构建的一部分。

如果您的网络上还没有外部存储系统,则最容易利用 Git 大文件支持 (LFS)

Git LSF 是一个指向存储库中大文件的存储指针的扩展,而不是将文件本身存储在存储库中。文件本身存储在远程服务器上。可以想象,这大大减少了克隆时间。

Git LSF

很有可能您已经可以访问 Git LFS 了——Bitbucket 和 GitHub 都支持它。

2:在 CI 中使用浅层克隆


每次运行构建时,您的构建服务器都会将您的代码存储库克隆到当前的工作目录中。正如我之前提到的,当 Git 克隆代码存储库时,它会默认克隆该代码存储库的全部历史记录。因此,随着时间的推移,这项操作自然会花费越来越长的时间。

对于浅层克隆,只会提取代码存储库的当前快照。因此,它对于减少构建时间非常有用,尤其是在使用大型和/或较旧的存储库时。

Git 存储库屏幕截图

但是,假设您的版本需要完整的代码存储库历史记录——例如,如果您版本中的某个步骤更新了您的 POM(或类似版本)中的版本号,或者您要在每个版本中合并两个分支。这两种情况都需要 Bamboo 将变更推送回您的代码存储库。

使用 Git,可以在不显示完整历史记录的情况下推送对文件的简单变更(例如更新版本号)。但是合并仍然需要代码存储库的历史记录,因为 Git 需要回顾并找到这两个分支的共同祖先——如果您的构建使用浅层克隆,那将是一个问题。这时候可以参考提示 #3。

3:在构建代理上缓存代码存储库


这也使克隆操作变得更快,而 Bamboo 实际上是默认这样做的。

请注意,只有在您使用从一个版本到另一个版本持续存在的代理时,代码存储库缓存才会对您有好处。如果您每次运行构建时都在 EC2 或其他云提供商上创建和拆除构建代理,则代码存储库缓存无关紧要,因为您将使用一个空的构建目录,并且无论如何每次都必须提取代码存储库的完整副本。

浅层克隆加上代码存储库缓存,除以持久代理和弹性代理,等于一系列有趣的因素。这里有一个小矩阵可以帮助您制定策略。

持久代理与弹性代理屏幕截图

4:明智地选择触发器


(几乎)不言而喻,在所有活跃分支上运行 CI 是个好主意。但是,在所有分支上针对所有提交运行所有版本是个好主意吗?可能不是。原因如下。

以 Atlassian 为例,我们有 800 多名开发人员,每位开发人员每天多次推送对代码存储库的变更,主要是推送到他们的功能分支,这样就会有很多版本。而且,除非您立即无限地扩展构建代理,否则队列中就会有大量版本在等待。

我们一台内部 Bamboo 服务器可容纳 935 种不同的构建计划。我们在该服务器中插入了 141 个构建代理,并使用了构件传递和测试并行化等最佳实践,尽可能提高每个构建的效率。尽管如此:每一次推送后的构建都阻碍了工作。

我们没有简单地再设置一个 Bamboo 实例,再构建 100 多个代理,而是退后一步,询问这是否真的有必要,答案是否定的。

因此,我们让开发人员选择是否推送分支构建,而不是一直自动触发。这是在严格测试与资源保护之间取得平衡的好方法,分支是大多数变更活动发生的地方,因此可以取消很多推送。

许多开发人员喜欢按键式版本提供的额外控制功能,并自然地发现适合他们的工作流程。其他人则不愿考虑何时运行构建,而是坚持使用自动触发器。两种方法都有效,重要的是首先对您的分支进行测试,并在合并上游之前确保您的分支有一个干净的构建。

连续触发器缩略图

但是,像主分支和稳定版本分支这样的关键分支则是另一回事。那里的构建会自动触发,要么通过轮询代码存储库中的变更,或者从 Bitbucket 向 Bamboo 发送推送通知。由于我们在所有正在进行的工作中都使用开发分支,因此(理论上)唯一进入主分支的提交应该是合并到主分支的开发分支。另外,这些是我们发布和创建开发分支的代码行。因此,及时获得每次合并的测试结果非常重要。

5:停止轮询,开始钩子


对于 Bamboo 来说,每隔几分钟轮询一次您的代码存储库以寻找变更是一项相当便宜的操作。但是,当您扩展到数百个版本,涉及数十个代码存储库的数千个分支时,代价就会相当高昂。您可以在推送变更且需要构建时调用 Bitbucket,而无需花费大代价去轮询 Bamboo。

通常,这是通过在存储库中添加一个钩子来完成的,但碰巧的是,Bitbucket 和 Bamboo 之间的集成会为您完成所有幕后设置。一旦它们在后端链接,代码存储库驱动的构建就会立即触发 Just Work™。无需钩子或特殊配置。

配置 Bitbucket 屏幕截图

无论使用何种工具,代码存储库驱动的触发器都具有在目标分支处于非活动状态时自动淡出的优点。换句话说,您永远不会浪费 CI 系统的 CPU 周期来轮询数百个废弃的分支。或者浪费自己的时间手动关闭分支构建。(但值得注意的是,如果您还喜欢轮询,可以轻松将 Bamboo 配置为在 X 天不活动后忽略分支。)

将 Git 与 CI 结合使用的关键是...


...深思熟虑。当您使用集中式 VCS 实现 CI 时,有哪些东西效果很好?其中一些在使用 Git 时效果会不太好。因此,请检查您的假设——这是第一步。对于 Atlassian 客户来说,第二步是将 Bamboo 与 Bitbucket 集成。请查看我们的文档了解详情,祝您构建愉快!

Sarah Goff-Dupont
Sarah Goff-Dupont

Sarah 是一位作家,之前是质量保证工程师,其作品曾发表在《哈佛商业评论》、《赫芬顿邮报》以及行业出版物上。她在明尼苏达州的家中远程工作,并且享受工作的每一分钟。当她不写作时,她一般会读书、滑雪、做饭和/或与孩子交流双关语。

在 LinkedIn 上与 Sarah 联系


分享这篇文章

推荐阅读

将这些资源加入书签,以了解 DevOps 团队的类型,或获取 Atlassian 关于 DevOps 的持续更新。

Devops 示意图

DevOps 社区

Devops 示意图

阅读博客文章

地图插图

免费试用

注册以获取我们的 DevOps 新闻资讯

Thank you for signing up