CocoaPods Trunk

经过一年的架构设计和辛勤工作,我们很荣幸地推出“Trunk”网络服务,它将极大地改善 Podspec 发布者的用户体验。

TL;DR 我们有充分的理由说明我们为何以及如何继续,但您可以跳过历史课程,直接进入:我们的解决方案“Trunk”

过去和原因

许多人问过“为什么 CocoaPods 没有一种简单的方法来发布新 Pod,就像 RubyGems 和 NPM 等?”,所以让我们来阐明一下。

可以说,配置 Xcode 等黑匣子,并让原生代码针对各种平台、部署目标和架构进行编译以进行构建,其排列组合比 RubyGems、NPM 等要困难得多。显然,这是脚本语言的一大优势,它(通常)不需要处理这些看似深奥的工作流。

因此,当我开始研究 CocoaPods 时,我不想在中心化网络服务上花费太多时间,因为我们甚至还不知道我们“核心业务”的所有细节。即使你可以在“一个周末”内创建一个网络服务,但这并不意味着它对找出困难的部分特别有帮助,即解决、安装和集成你的依赖项。

事实上,从网络服务开始会让整个过程困难,因为运行网络服务意味着你现在必须突然对其进行维护,因为社区会期望它 100% 的时间都处于正常运行状态。而如果有一件事我学到了,那就是作为一群志愿者(在他们的业余时间免费做很多这样的事情)承担这项责任,那么不可避免地会出现倦怠和/或需要筹集大量资金,因为可能难以维护架构决策。(这种情况的例子是 RubyGems.org 志愿者在宕机等情况下的压力,以及 scalenpm.org 在需要大量资金来维护其基础设施的情况。)

我还想设计架构,以便例如,希望通过 CocoaPods 使用其私有依赖项的公司不必配置和托管网络服务。没有人愿意做超出必要的事情,至少是因为它只会带来令人沮丧的服务器管理员体验。

出于这些原因,得出的简单解决方案是将这些文件托管在简单的目录结构中,并使用已建立的 SCM 系统对这些文件进行版本控制和简单分发。这种保持简单性的策略对我们来说非常有效。然而,在一定规模上,尤其是在像我们的“master”spec-repo 这样的开源环境中,不可避免地会出现需要将其提升到更高水平的时候...

问题

我们的“master”spec-repo 老大,Keith Smiley 先生,是一个审查和合并怪物,并且能够跟上在过去两年中你发送给他的所有拉取请求。但是,正如我们清楚地看到发布的 Pod 数量的上升趋势,在某个时候,即使 Keith 也无法处理你的规模。

我们注意到的另一个问题是,除了 Keith 和 Paul 的手动审查之外,创建拉取请求并自动从 Travis 获取反馈的当前工作流导致许多 podspec 发布者过于“懒惰”,他们没有通过在自己的应用程序中对其进行测试来正确测试 podspec 是否实际上对用户有效,而是最终更新并推送他们的规范,直到它据称有效。这不仅滥用了我们的志愿者的时间,而且还将确保适当工作的 podspec 的责任从发布者那里转移了出去。

社区中的其他人希望围绕 CocoaPods 创建网络服务,为此,他们需要某种形式的 API 和 Ruby 之外的格式,以便能够解释 podspec 并提供围绕它们的任何有意义的服务。

最后,在某个时候,即使最有善意的人也会失误。一个很好的例子是,当一个未经授权的人推送了一个不存在的 AFNetworking 版本的 podspec。显然,唯一应该被允许这样做的人是 Mattt(AFNetworking 的作者),以及可能得到 Mattt 允许的其他(维护者)。

解决方案?一个自动网络服务和一个注册“所有者”的数据库,其中包含一个 ACL 层,该层仅允许指定人员发布新版本。

“Trunk”,我们的解决方案

不同成熟度的可可豆生长在一棵树的树干上。维基百科

今天,我们推出我们的网络服务来解决上述问题。“Trunk”网络服务的推出意味着发布者现在可以直接从命令行发布 Pod,而无需创建拉取请求。

第一个发布 Pod 的人会自动被指定为“所有者”,在“master”规范存储库的范围内拥有该 Pod 名称。然后,“所有者”可以根据需要添加其他“所有者”。只有“所有者”才能发布所述 Pod 的后续版本。有关此内容以及与“Trunk”交互的更多信息,请参阅本指南

请注意,我们仍在GitHub 上的同一 git 存储库中托管可用 Pod 及其规范的规范数据库。这意味着如果某些内容影响此数据库的正常运行时间/稳定性,我们的用户可以依靠 GitHub 的专业且全天候支持。因此,如果“Trunk”由于某种原因而关闭,我们的普通用户不会受到影响,只有“所有者”在该时间段内无法发布新 Pod。总而言之,这意味着为(我们的用户)带来更好的稳定性,并为我们(志愿者)减轻压力。以下图表显示了我们架构的简单概览

关于确保 Podspec 正常工作,(“所有者”)且仅您负责 Podspec 的正常工作。我们仅在您这边验证您的 Podspec,以获取我们注册您的 Podspec 所需的最低元数据。我们不再在 Travis 上为您验证您的 Podspec。如果没有通过“master”规范存储库上的拉取请求执行严格的审查流程,我们将接受已发布 Podspec 的更新。因此,强烈建议您在发布 Podspec 之前在您自己的真实应用程序和/或演示应用程序中测试您的 Podspec。

最后,“Trunk”网络服务将不再以 Ruby 格式存储 Podspec。相反,这些将存储为 JSON,因此希望围绕 CocoaPods 生态系统创建其他网络服务的人员可以直接使用它们。

过渡

在我们过渡到“Trunk”网络服务时,我们将有一个宽限期,在此期间所有当前已知的 Pod 都可以由其各自的“所有者”认领。在此期间,pod trunk push 将被禁用,直到我们满意大多数(重要)Pod 已被认领。请阅读 Keith 关于此主题的博文,以获取有关认领您的 Pod 的更多信息。

常见问题

我收到“[!] 推送访问当前已禁用。”消息,出了什么问题?

在认领期间,pod trunk push 将被禁用。请参阅“过渡”部分。

我是否仍然可以对已发布的 Podspec 进行修改?

一旦发布了某个 Pod 的特定版本的 Podspec,你将无法修改它。至少无法通过自动化方式修改。大多数更新请求都是由于贡献者事先没有充分测试他们的 Podspec 所致。通常,你想要做的是发布一个 Pod 的新版本,而不是直接编辑已发布的版本。

但是,如果你确实遇到了特殊情况,并且确实必须修改给定版本的已发布 Podspec,你仍然可以针对“master”规范存储库创建拉取请求;但是,我们不一定接受它,并且我们不提供任何周转时间保证。

我如何区分 Podspec 的格式。

使用 Ruby DSL 的 Podspec 将使用 .podspec 扩展名,基于 JSON 的 Podspec 将使用 .podspec.json

Ruby 格式的规范是否会被弃用?

不会,它们将继续存在,并且如果你需要能够执行自动生成(例如从磁盘收集所有源文件列表),它们是首选方法。pod trunk push 命令将负责将 Podspec 转换为 JSON。这意味着你不必更改任何现有的 Podspec。

私有存储库是否需要采用 JSON 格式?

不需要。此外,pod push 命令将保留旧行为,只不过我们将此移至 pod repo push 以强调区别。请记住,如果两个文件可用,CocoaPods 将首选 JSON 格式。

我是否可以通过 HTTP 访问规范?

可以,你可以使用 GitHub API 的以下端点。在稍后的时间,我们将在“Trunk”上引入一个公共 API,你可以使用它来标准化此操作,尽管需要注意的是,如果你不需要 GitHub API 已提供的更多内容,最好只使用它,因为 GitHub 将能够提供比我们更好的正常运行时间。

获取可用 Pod 的列表

https://api.github.com/repos/CocoaPods/Specs/contents/Specs

获取 Pod 的可用版本

https://api.github.com/repos/CocoaPods/Specs/contents/Specs/ObjectiveSugar

获取 Pod 版本的 Podspec

https://api.github.com/repos/CocoaPods/Specs/contents/Specs/ObjectiveSugar/0.9/ObjectiveSugar.podspec.json