作者 | Cory Wilkerson
译者 | 平川
策划 | 钰莹
8 月 11 日,GitHub 向自己的团队和企业云用户开放了 Codespaces 特性。该特性在云上为软件团队提供了一个速度更快、协作性更好的开发环境。要了解更多信息,请移步 Codespaces 页面。
本文最初发布于GitHub官方博客,由InfoQ中文站翻译并分享。
GitHub.com 的代码库有 14 年的历史了。在 GitHub.com 的第一次提交被推送时,Rails 还只有两岁,AWS 只有 1 岁,而 Azure 和 GCP 还不存在。如果用 COBOL 时间来看这可能不算长,但用互联网时间来看,时间真是不短了。
在这 14 年中,支撑 GitHub.com(github/github)的核心存储库已经有超过 100 万次提交。绝大多数提交都是来自开发人员在 macOS 上的构建和测试工作。
一次典型的消息提交
但是,我们的开发平台在发展。在过去的几个月里,我们已经将 macOS 模型抛在一边,GitHub.com 的大部分开发都转到了 Codespaces。这是日常开发流程的一个根本性转变。Codespaces 产品的功能更强大,我们已经为 GitHub.com 未来的发展做好了准备。
现  状
近年来,为使本地开发工作可以快速开始,我们已经投入了大量的时间和精力。一段时间以来,我们所采用的 “脚本管理一切“的方法 为工程师提供了熟悉的界面——新员工可以克隆github/github ,运行 setup 和 bootstrap 脚本,用半天的时间让一个 GitHub.com 本地实例运行起来。在大多数情况下,这都没什么问题,如果有问题,我们的 bootstrap 脚本会打开一个 GitHub 问题,在新员工和内部支持人员之间建立联系。我们的 Slack 频道#friction——上面有许多乐于助人的友善的工程师——几乎可以调试天底下所有的系统配置。
用一条命令在本地运行 GitHub.com
尽管我们做了许多工作,但本地开发环境依然很脆弱。任何看似无害的修改都可能会导致本地环境不可用,更糟糕的是,需要花费数小时宝贵的开发时间来恢复。开发环境经常被莫名其妙的破坏,而是还是灾难性的,我们不得不在 bootstrap 脚本中增加了一个选项:--nuke-from-orbit 。触发该选项时,脚本会尽可能地删除它负责的东西,将本地开发环境恢复到一个已知的良好状态。
当然,任何从事软件工程专业的人一看就知道,这是一种很典型的情况。本地开发环境很脆弱。即使现在很完美,但一个针对特定上下文定制的本地开发环境与我们所处的即时在线、随处访问的世界越来越不相称。
在多个项目的多个分支上协同开发是很痛苦的。我们经常会发现,当一个分支引入了新的依赖,做了模式修改,或者从不同的 SHA 创建了分支,在启动时就得眼睁睁地等 45 分钟。鉴于我们的代码变化很快(我们每天部署数以百计的变更),这经常会导致工程摩擦。
并非只有我们注意到了这一点,在构建 Codespaces 的过程中,我们接触了多家一流的工程组织,他们已经构建了类似 Codespaces 这样的平台来解决同类问题。当规模比较大时,消除这类生产力损失可以快速提高生产力。
这条消息会使 GitHub 的任何工程师都出一身冷汗
软件开发基础设施
在基础设施领域,行业最佳实践一直将服务器作为一种商品。其思想是,没有哪一台服务器是独一无二、不可或缺或不可替换的。任何一个部件都可以被悄无声息的取下并替换。如果一台服务器宕了,那没什么问题,另换一台就是了。
然而,每个人的本地开发环境都是独特的,都有自己的习惯性设置。因此,需要时刻保持警惕才能维持。下一次git pullbootstrap就可能会导致你的环境快速退化,需要进行昂贵的上下文切换才能恢复工作,而你宁可把这些时间用来构建软件。通常,我们并没有一台即取即用的备用笔记本。
但是,有必要强调一下,把开发环境看作是自己的——我们每天大部分时间都花在那里。我们会调整、优化我们的工作台,一方面是为了提高效率,另一方面也是一种个性的展示。
有了 Codespaces,我们就可以像对待基础设施那样对待我们的开发环境——一种我们可以不断更换的商品——但仍然保有个性化定制工作台的能力。我们借助 Visual Studio Code 扩展、设置同步以及 dotfiles 存储库将开发环境带到了我们个人的计算机上。这样,即使工作台出现了问题,也是小事一桩,我们可以用一个已知的良好状态配置一个新的编码空间,然后继续工作。
采用 Codespaces
迁移到 Codespaces 可以克服现有开发环境的缺点,激励我们进一步推动产品的发展,提升整体的开发体验。
虽然我们的迁移故事有一个圆满的结局,但最初迁移的时候还是充满了挑战。GitHub.com 存储库占了将近 13GB 的磁盘空间;光是克隆存储库就需要 20 分钟。在加上依赖项设置,启动一个 GitHub.com 编码空间需要 45 分钟以上。而当我们成功将代码库加载到代码空间后,却发现应用程序不能运行。
我们不得不推翻 14 年来启动过程以 macOS 为中心的假设。
解决这些挑战成就了最好的 GitHub。全公司的贡献者都帮助我们重新审视以往的决策,质疑长期存在的假设,在代码层面将 GitHub 开发从 macOS 解耦。最终,我们可以(尽管很慢)在 Linux 主机上配置基本的 GitHub.com 代码空间了,从 Visual Studio Code 连接上去,然后交付一些工作。现在,我们得想办法让它活跃起来。
从 45 分钟到 5 分钟
对于 Codespaces,我们的目标是可以根据手头的任务按需配置开发环境(分支和代码空间差不多 1:1)。为了支持基于任务的工作流,我们近乎实时地获得开发环境。45 分钟不能满足我们基于任务的需求,但是我们有很多地方可以优化,让我们先从简单的入手。
首先:改变 Codespaces 克隆 github/github 的方式。在准备开发环境的时候,Codespaces 现在不再全部克隆,而是执行一个浅层克隆,然后在包含最新提交的代码空间创建完成后,在后台对存储库历史做深层克隆。这样一来,克隆时间从 20 分钟缩短为 90 秒。
接下来:缓存支撑 GitHub.com 的软件和服务网络,包括传统的基于 Gemfile 的依赖、使用 C、Go 编写的服务以及一个自定义的 Ruby 构建。在该解决方案中,有一个 GitHub Action 会每晚运行,克隆存储库、引导依赖项,构建并推送克隆结果的 Docker 镜像。然后,发布的镜像会作为 github/github devcontainer(Codespaces 的 config-as-code)的基础镜像。现在,我们的代码空间创建 95% 以上都是自举式的。
这两个变化,以及若干应用和服务层面的优化,将 GitHub.com 代码空间的创建时间从 45 分钟缩短到 5 分钟。但是,5 分钟距离“即时”还有相当一段距离。众所周知,有研究表明,人们等待大约 10 秒 之后思维就会中断。因此,虽然我们已经取得了很大的进步,但仍然还有一段路要走。
从 5 分钟到 10 秒
虽然 5 分钟意味着巨大的改进,但我们在修改时也做了一些折衷,这意味着还有更一般化的产品需求。
我们的浅层克隆方法——对于快速启动 Codespaces 很有用——有时候仍然需要我们做完整的克隆。生成代码空间后的深层克隆又存在干扰。任何大型的复杂项目都面临类似的问题,在克隆和启动时会产生资源竞争。
如果我们提前克隆并引导存储库会怎么样?那样,当工程师申请代码空间的时候,我们已经完成了大部分工作。
预构建:代码空间池,已完全克隆并引导,只等想要开始工作的开发人员连接。我们在预构建方面的投资已经获得了无数次的回报:我们现在只需 10 秒钟就可以创建一个可靠的、预先配置好的代码空间,准备好 GitHub.com 的开发环境。
现在,新员工从零开始获得一个功能完备的开发环境比安装 Slack 的时间还短。工程师剥离出新的代码空间以实现并行工作,也没什么开销。当环境崩溃时——也许它太落后了,也许是测试数据造成了破坏——工程师可以快速创建一个新环境并继续一天的工作。
杠杆作用日益增加
迁移到 Codespaces 解决了我们的一些实际问题:它消除了本地开发环境的脆弱性和单轨模式,同时也为我们提供了一个新的强大的杠杆作用点,让我们可以改进 GitHub 的开发体验。
现在,我们有了一个契子来执行额外的设置和优化工作,一些我们在本地环境中从未想过的工作,因为这些优化的成本(时间和耐心)太高。例如,借助预构建,我们现在可以事先准备好语言服务器缓存和 gem 文档,运行待处理的数据库迁移,并启用 GitHub.com 和 GitHub Enterprise 开发模式——这项任务通常需要在另一次引导、设置循环中完成。
借助 Codespaces,我们可以通过一条配置更改升级所有工程师的机器规格。在 Codespaces 迁移的早期阶段,我们使用 8 核 16GB 内存的 VM。那些机器足够了,但 GitHub.com 运行着一个包含不同服务的网络,它会很乐意消耗我们提供的每一颗内核和每一点内存。因此,我们转到了 32 核 64GB 内存的 VM。只需修改一行配置,我们就可以升级所有工程师的机器。
即时升级
此外,Codespaces 还开始偷走我们的内部平台“评审实验室”的业务,这是一个类生产环境,我们和内部协作者在这里预览更改。在 Codespaces 推出之前,GitHub 工程师需要提交并部署一个评审实验室实例(经常需要同行评审),以便和同事共享他们的工作。现在,我们按住 ctrl 并单击就可以获取一个预览 URL 并发送给同事。不需要提交,不需要推送,不需要审核,也不需要部署。
命令行
Visual Studio Code 很棒。这是 GitHub.com 工程师连接代码空间的主要工具。但是,要求 Vim 和 Emacs 用户向图形编辑器提交就不那么好了。如果 Codespaces 是我们的未来,那么我们不能抛下任何人。
令人高兴的是,我们通过一个简单的预构建镜像升级为使用 shell 的同事提供了支持。该升级使用 GitHub公钥 初始化sshd,打开 22 端口,并将该端口转发到代码空间之外。
自此,GitHub 工程就可以运行 Vim、Emacs 了,如果他们愿意,甚至可以运行 ed。这一措施很有效。而且,就像 Docker 镜像缓存带来了预构建一样,很明显,下一步是让我们为 GitHub.com 代码空间所做的工作成为每个代码空间的头等体验。
总  结
改变是很困难的,涉及到开发环境更是如此。值得庆幸的是,GitHub 的工程师有很强的求知欲,同时也很友善——他们很快就变成了 Codespaces 的超级粉。
现在,Codespaces 成了 GitHub.com 的默认开发环境。至于前面提到的用于帮助调试本地开发环境问题的 Slack 频道#friction,我们计划将其归档了。
GitHub 每天都会上线更多的服务,每天都会有工程师加入,关于 Codespaces 的价值创造,我们会发现新的故事。但是,每个故事的核心都是一个每名工程师都会产生共鸣的主题:我找到了一个更好的工具,我现在效率更高了,我不要再回到从前那样了。
查看英文原文:GitHub’s Engineering Team has moved to Codespaces

你也「在看」吗?👇
继续阅读
阅读原文