GitHub工程团队已经转移到Codespaces:实现开发环境的秒级启用

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