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,都需要执行此操作。
-
更新
Gemfile.lock时,请确保使用以下命令同时更新Gemfile.checksum:bundle exec bundler-checksum init -
检查并提交
Gemfile.checksum的更改。
更新 Gemfile.next.lock 文件
每当更新 gem 时,确保 Gemfile.next.lock 文件保持一致。
-
同步 gem 文件 如果您更新了
Gemfile.checksum,必须通过运行以下命令同步 gem 文件:bundle exec rake bundler:gemfile:sync -
审查并提交更改 同步后,验证更新并提交对
Gemfile.next.checksum和Gemfile.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 是否看起来合法。
审查人员还应了解我们相关的社区贡献审查建议,并在运行包含对 Gemfile 或 Gemfile.lock 更改的社区贡献管道时保持谨慎。
许可证合规性
请参阅许可证指南以确保许可证合规性。
GitLab 创建的 gem
有时我们会在代码库中创建想要提取的库,要么是因为我们想在其他应用程序中使用它们,要么是因为我们认为这将使更广泛的社区受益。将代码提取为 gem 也意味着我们可以确保 gem 不包含对我们应用程序代码的任何隐藏依赖。
了解更多关于 Gem 开发指南。
升级 Rails
升级 Rails gem 及其依赖时,您还应更新以下内容:
您还应更新遵循当前 Rails 版本的 npm 包:
@rails/ujs- 更新后运行
yarn patch-package @rails/ujs以确保我们的本地补丁文件版本匹配。
- 更新后运行
@rails/actioncable
因漏洞而升级依赖
因漏洞而升级依赖时,我们应该在 Gemfile 中锁定 gem 的最低修复版本,以避免意外降级。
例如,假设 gem license_finder 有 thor 作为其依赖。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 Changes 在 diffend.io 上生成版本比较。例如,这是 thor 1.0.0 vs 1.0.1 的 gem diff。请使用直接从 RubyGems 生成的链接,因为来自 GitLab 或其他代码托管平台的链接可能无法反映实际发布的代码。