GitHub的开发人员体验团队如何改进内环开发

我们针对GitHub的分布式服务生态系统中普遍存在的集成测试工程问题的最新解决方案。

|
| 8分钟

在部署之前建立对新代码的信心是任何良好开发循环的关键部分。当在分布式或微服务系统中工作,多个团队在不同的服务上操作时,这尤其具有挑战性。这种模块化团队结构引发了一个重要问题:当测试和发布需要团队在其他服务的生态系统中进行测试时,我们如何为团队提供快速可靠的开发周期?优化此问题的解决方案可以大大提高工程效率,并有助于整个组织取得更成功的结果。

这个问题是GitHub的开发人员体验(DX)团队一次又一次努力解决的问题,最终交付了一个我们称为“Hubber Codespace”(HCS)的解决方案。HCS是Hubbers(在GitHub工作的人)可以使用的一种工具,通过简单地查询端点或向其开发容器添加几行配置,在任何环境中本地维护整个分布式GitHub生态系统。

在这篇文章中,我们将告诉您我们是如何找到HCS解决方案来解决这个常见问题的,而不是一些可能的替代方案,您将直接了解GitHub的“开发人员第一”理念是如何帮助我们为Hubers提供最佳工具,以便在我们自己的分布式环境中快速、安全地发布代码的。

一个大(不)幸福的环境

为了理解我们试图解决的问题,我们必须回到过去。有一段时间,GitHub只是几个团队和一个简单得多的产品。当时,建立一个每个人都会反复迭代并对自己的变化建立信心的单回购协议是有意义的。跨存储库划分责任将增加早期哈伯斯陷入困境的开销。快进到今天,GitHub已经发展成为一个拥有数百个不同团队的大型组织。现在,在速度与复杂性之间进行评估的平衡行为可能看起来非常不同。

让我们进一步考虑这些复杂性。不同的服务可以有完全不同的依赖关系集,甚至对同一软件的不同版本也有依赖关系(例如,一个服务需要Ruby 2.2,而另一个服务则需要Ruby 2.4)。在较小的协作环境中,工程师可以轻松地协调这些需求。但随着更多团队的引入,这种复杂性呈指数级增长。试图提供一个单一的环境,使这些不同的服务能够在开发中运行和交互,这变得很难做到.ruby版本文件取决于您正在处理的服务的开发循环。当您尝试使用包含一组不同服务的代码基的monorepo时,会遇到这些问题。

因此,我们决定设计一个新的解决方案。如果我们没有把开发者带到生态系统中,而是把生态系统带到开发者那里呢?

输入HCS

这种思路引导我们构建了HCS,这是一个Docker-Compose项目。在帖子中“我们如何使用GitHub在GitHub构建集装箱化服务,“我们详细介绍了如何构建容器化服务,以支持GitHub.com平台上的微服务和许多内部工具。我们现在的任务是将这些容器连接起来,以便合作团队可以根据需要构建完整的GitHub生态系统。这将允许他们在集成环境中测试他们的更改。开发人员可以看到他们的代码在引入GitHub的分布式系统时的行为,而不是在整个系统中部署之前只在开发的应用程序的隔离环境中进行观察。通过这种方式,开发人员可以获得信心,他们正在更改的服务在与上下游依赖项交互时表现正确。

在考虑如何编排所有必需的容器时,想到了几个解决方案:Docker-Compose,一个名为Codespace-Compose的内部工具,它允许我们在多个代码空间之间进行SSH隧道,以及Minikube。这三种解决方案中的任何一种都可以解决生态系统问题,并具有独特的权衡。现在让我们看看其中的一些权衡。

Minikube提供了一个健壮的Kubernetes架构,但我们担心整体用户体验。我们最终决定反对它,因为我们发现的问题,例如网络复杂性和长周期时间,可能会阻碍开发速度。

Codespace-Compose允许我们轻松连接团队的日常开发环境,但我们推断,由于Codespace-Compose是一个没有任何SLA的内部实验,因此采用这种方法会给我们自己的团队带来维护成本。

Docker-Compose似乎最适合我们的需要。由于它是公开可用的,并且是主动管理的,因此没有招致任何额外的维护负担。它提供了与Minikube相同的优点,而无需长周期。最重要的是,在Docker中使用Docker在代码空间中,我们可以在主机上创建docker容器,而主机本身就是docker容器,这是一条有很多现有技术的良好道路。考虑到所有这些因素,我们决定使用docker Compose来编排我们的容器。

在决定Docker-Compose作为我们的编配器之后,接下来的步骤是确定接口。Docker-Compose已经为最终用户提供了命令,但我们希望围绕HCS优化用户体验。为此,我们在Golang中构建了一个用户友好的CLI,并将其并行版本控制到HCS。这就抽象掉了将两者结合使用的所有复杂性。只需下载HCS的特定版本,获得相同版本的CLI二进制文件,就可以了!

CLI和发布自动化

确保HCS有用意味着确保以下几点。一个重要目标是易于使用。Docker-Compose已经为最终用户提供了一个界面,但考虑到一些内置命令很长并且使用可预测的选项,我们决定将其封装在自定义Golang CLI中。这抽象了许多底层细节,如静态文件位置、格式选项、入口点命令等,以改进最终用户体验。下面的代码通过将Docker-Compose命令与其等效的HCS CLI命令并列显示了这一点。

下面的示例比较了启动HCS提供的集成环境的命令。

#开始使用Docker-Composedocker compose--项目名称hcs\--文件/工作区/hubber-codesace-dist/docker-compose-hcs-actions.yml\--文件/工作区/hubber-codesace-dist/docker-compose-hcs-base.yml\--文件/工作区/hubber-codesace-dist/docker-compose-hcs-bg.yml\--文件/工作区/huber-codespace-disst/docker-compose-hcs-core.yml\--文件/工作区/hubber-codesace-dist/docker-compose-hcs-volume.yml\--文件/工作区/hubber-codesace-dist/docker-compose-hcs-test.yml\--文件/工作区/hubber-codesace-dist/docker-compose-hcs-vendor.yml\--profile full up-d—删除对象#开始使用CLIhcs启动

下一个示例比较了如何让shell从GitHub的分布式生态系统中的各种容器内部运行命令。这允许开发人员模块化地与系统交互,并对系统进行短暂更改。

#使用Docker-Compose从系统中的容器内部运行命令docker-compose--项目名称hcs exec bash#使用CLI从容器内部运行hcs外壳

此示例比较了如何检查项目中容器的状态,以便最终用户可以轻松查看整个系统的运行状况。

#使用Docker-Compose的状态docker-compose--项目名称hcs-ps--格式json#使用CLI的状态hcs状态

除了这个易于使用且符合人体工程学的CLI之外,我们还必须确保HCS运行最新版本的GitHub生态系统。GitHub是由许多不同的活动块组成的,因此即使在几天之前的代码上测试新的更改也不足以建立信心。当直接在monorepo上迭代时,这不是一个问题,因为人们只是获取主要的分支。对于HCS,这需要我们构建自动化,以根据频繁的cron时间表减少发布。A类HCS释放是一个软件工件,包含HCS的已编译Golang二进制文件及其CLI,可以使用gh CLI提取。

下图说明了这个过程是如何工作的。

该图显示了HCS的夜间发布周期。HCS的存储库从monorepo和其他服务存储库获取SHA。然后,它发布一个包含所有SHA、Docker-Compose配置和CLI二进制文件的版本。

终端用户体验

在代码空间中直接使用HCS

我们最近努力推动GitHub的所有开发GitHub代码空间。代码空间是一种自定义开发容器或devcontainer,基于存储库中的配置文件。一个存储库可以有多个与其关联的代码空间,只要每个代码空间都有一个唯一的配置文件。除了按需开发和迭代可复制环境的明显好处之外,开发容器还提供特征。此抽象允许开发人员轻松地将软件添加到其环境中。HCS也是这样消耗的。下面的代码块显示了将整个生态系统引入合作伙伴团队首选环境(即他们的代码空间)所需的几行代码。

{“功能”:{“ghcr.io/devcontainers/features/github-cli:1”:{“版本”:“最新”},//hcs需要docker-in-docker“ghcr.io/devcontainers/features/docker-in-docker:2”:{},//包括胡言乱语功能“ghcr.io/github/hubber-codespace/hcs:1”:{},“ghcr.io/devcontainers/features/go:1”:{}}}

现在,团队可以直接在进行本地开发的代码空间中对GitHub生态系统中的许多其他服务执行集成测试。

发布二进制文件

即使推进代码空间,也不是每个需要生态系统的上下文都会成为开发容器。有鉴于此,我们还为最终用户提供了直接从GitHub API下载发行版的选项。这样做的命令如下所示。通过几个简单的命令,哈伯斯现在拥有了将整个GitHub生态系统带到他们想要的任何环境所需的一切。

gh发行版下载--repo github/hubber-codespace-p hcs-D/tmp/chmod+x/tmp/hcssudo mv/tmp/hcs/usr/local/binhcs初始化hcs拉力hcs启动

证词

但不要只是相信我的话。看看我们的合作团队对HCS改进他们的开发循环有何评论:

“HCS通过简化针对GitHub生态系统其他部分的测试,改进了我们[服务]的开发循环。它改变了将我们的存储库克隆到[monorepo环境]的许多手动步骤在我们自己的代码空间中生成两个简单的命令。这使得验证我们的更改变得更加容易,而无需部署到临时环境中。”

“考虑到我们是一个在GitHub之外运营的服务,但严重依赖GitHub内部运行的服务,我们不得不经历很多风风雨雨,以确保我们能够获得平稳的开发经验。在我从事[我们的服务]的四年中,HCS在为我们的服务从一个空白的devbox切换到中断实时运行的代码方面是最无缝的体验。”

结论

解决生态系统问题始终是一种平衡行为。幸运的是,得益于GitHub向容器化的推进,以及通过GitHubCLI实现存储库自动化和发布/使用发布等工具,我们已经为开发HCS解决方案做好了充分的准备。哈伯斯现在可以利用一个开发循环,让他们可以放心地部署,并在GitHub复杂的多服务系统中测试了他们的更改。

相关职位