Help us learn about your current experience with the documentation. Take the survey.

Gemfile 开发指南

在向 Gemfile 添加新条目或升级现有依赖时,请遵循以下规则。

Bundler 校验和验证

GitLab 15.5 及更高版本中,gem 的校验和会在安装前进行检查。此验证仍处于实验阶段,因此仅在 CI 中激活。

如果下载的 gem 的校验和与 Gemfile.checksum 中的记录不匹配,您将看到一个错误,提示 Bundler 无法继续安装 gem,因为存在潜在的安全问题。

如果您更新或添加了新的 gem 但未更新 Gemfile.checksum,也会看到此错误。要修复此错误,请更新 Gemfile.checksum

您可以通过设置 BUNDLER_CHECKSUM_VERIFICATION_OPT_IN 环境变量来选择性地在本地启用此验证:

export BUNDLER_CHECKSUM_VERIFICATION_OPT_IN=1
bundle install

将其设置为 false 也可以禁用它:

export BUNDLER_CHECKSUM_VERIFICATION_OPT_IN=false
bundle install

更新校验和文件

对于任何新的或更新的 gem,都需要执行此操作。

  1. 更新 Gemfile.lock 时,请确保使用以下命令同时更新 Gemfile.checksum

    bundle exec bundler-checksum init
  2. 检查并提交 Gemfile.checksum 的更改。

更新 Gemfile.next.lock 文件

每当更新 gem 时,确保 Gemfile.next.lock 文件保持一致。

  1. 同步 gem 文件 如果您更新了 Gemfile.checksum,必须通过运行以下命令同步 gem 文件:

    bundle exec rake bundler:gemfile:sync
  2. 审查并提交更改 同步后,验证更新并提交对 Gemfile.next.checksumGemfile.next.lock 的任何更改。

禁止从 Git 仓库获取 gem

我们不允许从 Git 仓库获取的 gem。所有 gem 都必须在 RubyGems 索引中可用。我们希望最小化外部构建依赖和构建时间。这是由 RuboCop 规则 Cop/GemFetcher 强制执行的。

禁止在导入器或集成中使用进行 HTTP 调用的 gem

不要在导入器或集成中添加进行 HTTP 调用的 gem。通常,也强烈建议其他 gem 避免在这些领域使用。更多信息请参见:

审查新依赖的质量

我们不应该向 GitLab 添加无法通过我们自己质量标准的第三方依赖。这意味着新依赖至少应满足以下标准:

  • 它们有活跃的开发者社区。至少维护者应保持活跃,以便在紧急情况下合并变更请求。
  • 没有已知的可能影响 GitLab 可用性或性能的开放问题。
  • 项目使用某种形式的测试自动化进行测试。测试套件必须使用 GitLab 当前使用的 Ruby 版本通过测试。
  • 使用新依赖时,所有支持平台的 CI 构建必须成功。更多信息,请参阅如何构建用于测试的包
  • 如果项目使用 C 扩展,考虑请求 C 或 MRI 领域专家进行额外审查。C 扩展可能会严重影响 GitLab 的稳定性和性能。

需要领域专家批准的 gem

对以下 gem 的更改需要领域专家审查,并由该组的后端团队成员批准。

对于表中未列出的 gem,仍然建议但不是必须要求您找到领域专家来审查更改。

Gem 需要由谁批准
doorkeeper Manage:Authentication and Authorization
doorkeeper-openid_connect Manage:Authentication and Authorization

请求 Appsec 审查

当向我们的 Gemfile 添加新 gem 甚至更改 Gemfile.lock 中的版本时,我们强烈建议您请求安全审查。新的 gem 会给 GitLab 带来额外的安全风险,在将其发布到生产环境之前评估此风险非常重要。从技术上讲,仅添加新 gem 并推送到我们主 gitlab 项目的分支就是一个安全风险,因为它将使用您的 GitLab.com 凭证在 CI 中运行。因此,您应该在安装之前就尽早评估这个 gem 是否看起来合法。

审查人员还应了解我们相关的社区贡献审查建议,并在运行包含对 GemfileGemfile.lock 更改的社区贡献管道时保持谨慎。

许可证合规性

请参阅许可证指南以确保许可证合规性。

GitLab 创建的 gem

有时我们会在代码库中创建想要提取的库,要么是因为我们想在其他应用程序中使用它们,要么是因为我们认为这将使更广泛的社区受益。将代码提取为 gem 也意味着我们可以确保 gem 不包含对我们应用程序代码的任何隐藏依赖。

了解更多关于 Gem 开发指南

升级 Rails

升级 Rails gem 及其依赖时,您还应更新以下内容:

您还应更新遵循当前 Rails 版本的 npm 包:

  • @rails/ujs
    • 更新后运行 yarn patch-package @rails/ujs 以确保我们的本地补丁文件版本匹配。
  • @rails/actioncable

因漏洞而升级依赖

因漏洞而升级依赖时,我们应该在 Gemfile 中锁定 gem 的最低修复版本,以避免意外降级。

例如,假设 gem license_finderthor 作为其依赖。thor 在其版本 1.1.1 之前被发现存在漏洞,该版本包含漏洞修复。

在 Gemfile 中,确保将 thor 锁定到 1.1.1。直接依赖 license_finder 应该已经指定了版本。

gem 'license_finder', '~> 6.0'
# license_finder 的依赖,包含漏洞修复
# _链接到将公开的初始安全问题_
gem 'thor', '>= 1.1.1'

这里我们使用的是 >=(大于或等于)运算符,而不是 ~>悲观运算符),这使得可以升级 license_finder 或任何其他 gem 到依赖于 thor 1.2 的版本。

同样,如果 license_finder 在 6.0.1 版本中修复了漏洞,我们应该添加:

gem 'license_finder', '~> 6.0', '>= 6.0.1'

这样,除了 license_finder 之外的其他依赖仍然可以依赖于 thor 的新版本,如 6.0.2,但将无法依赖于有漏洞的版本 6.0.0

如果我们引入了一个新的依赖,它也依赖于 thor 但将其版本锁定在有漏洞的版本上,就可能发生这样的降级。这些更改在 Gemfile.lock 中很容易被忽略。锁定版本将导致需要解决的冲突。

为了避免升级间接依赖,我们可以使用 bundle update --conservative

在提交包含依赖更新的合并请求时,请在合并请求描述中包含两个版本之间的 Gem diff 链接。您可以在 rubygems.org 上找到此链接,选择 Review Changesdiffend.io 上生成版本比较。例如,这是 thor 1.0.0 vs 1.0.1 的 gem diff。请使用直接从 RubyGems 生成的链接,因为来自 GitLab 或其他代码托管平台的链接可能无法反映实际发布的代码。