使用本机扩展为 gem 保持一致的 Gemfile.lock

Maintaining a consistent Gemfile.lock for a gem with native extensions

我在一个开发 gem 本机可执行文件的工程师团队中工作。出于合同原因,重要的是,当我们部署到新环境时,所有依赖项都使用与我们测试过的完全相同的版本。 Gemfile 只能维护一阶依赖版本,不能维护递归版本。出于这个原因,我们一直将我们的锁定文件检查到 github,但这阻止了我们自 1.14 版本以来升级捆绑器。问题是我们的开发机器是 OSX 和 Linux,并且从 1.14 开始,gem 存储库中的锁定文件的开头从:

PATH
  remote: .
  specs:
    engine (21.2.13)
      <gemspec dependencies here>

PATH
  remote: .
  specs:
    engine (21.2.13-x86_64-linux)
      <gemspec dependencies here>

这是一个问题,因为当开发人员在 OSX 上提取 repo 并运行 bundle install 时,它会更改锁定文件的内容。然后,当 linux 开发人员做同样的事情时,它会再次发生变化,在锁定文件的 git 历史记录中产生一堆虚假的变化!

我尝试了 运行 bundle lock --add-platform x86_64-linuxbundle lock --add-platform x86_64-darwin,希望这能说服捆绑器为不同的平台维护两个条目,而不是在它们之间来回切换。它 确实 为锁定文件的 GEM 部分中的某些 gem 生成重复条目,但不为 PATH\n specs: 部分中的条目生成重复条目.

目前,我们的 Gemfile 包含以下行:

gemspec name: "engine"

加载 engine.gemspec。此文件包含:

Gem::Specification.new do |spec|
  ...
  spec.platform = Gem::Platform::CURRENT
  ...
end

我怀疑这是问题所在。我尝试在 Gemfile 中包含 gemspec twice,并使用全局变量指定要使用的平台,但 bundler 仅在第一次加载它,并跳过第二次尝试。

有谁知道可以让我们将两个特定于平台的 gem 版本保存在同一个锁定文件中的解决方案?

否则,是否有办法关闭捆绑程序的新行为,即向 gem 版本附加平台名称?过去,当锁定文件简单地指定“21.2.13”并且我们的 gem 服务器包含每个版本的两个副本(带有为两个平台构建的二进制文件)时,bundler 从来没有任何问题解决当前的正确版本机器,所以这看起来像是存储多余信息的锁文件。我能以某种方式告诉它停止吗?

我听说过建议和不建议将您的锁定文件置于版本控制中,但从未完全理解其中的原因。这似乎是问题的根源!

我最常看到的建议(虽然这可能总是是可能的),是锁文件永远不应该在 gem 的版本控制下,但是始终用于独立应用程序。这个想法是 gem 旨在是可移植的,因此它的依赖性应该具有一定的灵活性。重要的是,这种灵活性不会阻止我们的开发环境保持一致,前提是所有测试都不是在 gem 存储库中而是在使用 gem.[=11= 的独立应用程序的存储库中进行的。 ]

那个独立应用程序的锁定文件已经跟踪了我们认为我们正在使用 gem 的锁定文件跟踪的依赖项,并且当应用程序被部署时,所有 gem 的依赖项都是固定在应用程序内部,而不是 gem.

内部

Gemfile.lock 的 "spec" 部分只应出现在 gem 存储库中,事实上该部分以平台相关的方式命名 gems这不是问题,因为 gem 在使用它的应用程序的锁定文件中由平台无关的名称引用。