如何使用本地gem存储库处理Gemfile.lock?

时间:2017-01-16 09:21:41

标签: ruby-on-rails ruby git bundler rails-engines

简介

我们有一个Rails5应用程序,它在大约10多个引擎中分离,并且是一个核心应用程序,可以安装这些引擎。

我们的案例中的引擎是一个普通的旧轨道引擎,定义为gem并位于专用的git存储库中。核心应用程序中的Gemfile引用所有引擎(见下文)。

必需行为

  • 对于部署,应使用特定版本的gem /引擎(由核心)。
  • 对于本地开发,应使用本地克隆存储库的HEAD(由核心)。

当前设置

我们通过对核心应用中的每个引擎执行以下步骤来实现这一目标:

  • 添加gem 'nice_engine1', '~> 0.0.1', branch: :develop, git: '[...]', tag: 'v0.0.1'
  • 设置捆绑器配置条目:bundle config local.nice_engine1 ../nice_engine1

这似乎有效,但我们还没有尝试使用该设置运行部署。

该安装程序的问题

每次在本地更新其中一个存储库并在核心中运行bundle install时,bundler会将Gemfile.lock更新为本地引擎存储库的新HEAD ref。我们曾经提交过Gemfile.lock

的更改

不幸的是,这会导致一些问题:

  1. 如果有人更新核心应用程序而不更新引擎,则可能会发生核心Gemfile.lock引用引擎的git提交,该引擎在本地不存在。如果尝试使用rails app,则会导致错误。
  2. 在部署时(我认为)Gemfile.lock可能引用了一个提交ID,这比我想要部署的标记/版本的提交更新。我不确定在那种情况下会发生什么,但我担心,这只会让我们陷入困境。
  3. 我们在核心中有很多提交更改Gemfile.lock(可能是其中一个引擎中的每个更改)。
  4. 在本地使用其他引擎分支,然后master强制开发人员更改主要应用Gemfile中的分支名称
  5. 问题

    在给定情况下管理GemfileGemfile.lock以避免这些问题的正确/最佳方法是什么?

    有关最佳实践,改进建议等的一些提示,如何使用bundler和git来满足我们的要求,我将非常感激。

2 个答案:

答案 0 :(得分:2)

  

如果有人更新核心应用程序,而不更新引擎,则可能   发生了,核心Gemfile.lock引用了一个git提交   引擎,在本地不存在。如果有人尝试,那会导致错误   使用rails app。

这里有几个选项:

1)使用类似git-bundle的gem,以便您可以运行gitb pull之类的单个命令来更新主应用程序和引擎。

2)在像RubyMine这样的IDE中打开主应用程序和引擎,因为如果你单击VCS,它会更新所有存储库 - >更新项目。

3)创建一个类似于git-bundle的脚本,它同时更新所有存储库。

  

在部署时(我认为)Gemfile.lock可能指的是a   提交id,比我提交的标签/版本更新   想要部署。我不确定在那种情况下会发生什么,但是我   恐惧,这只会让我们陷入困境。

让我们说主要应用程序的特定修订版标记为1.0。该修订版的Gemfile.lock指定引擎的哪些修订版用于1.0。除了Gemfile.lock中指定的引擎修订版之外,它无法部署主应用程序的标记1.0。

  

我们在核心中有很多提交更改Gemfile.lock   (可能是其中一个引擎的每次更改)。

是的,这是正确的。这个文件有效地将不同的git存储库和修订版本绑定到一个应用程序中。它在版本控制文件中的事实使它很好并且可追溯。

  

管理Gemfile的正确/最佳方式是什么?   Gemfile.lock在给定的情况下可以避免这些问题吗?

1)有一个宝石。它被称为git-bundle。我写了它,我们已经在不同的应用程序中使用它大约5年,现在取得了巨大的成功。欢迎提出请求或反馈。

2)在主应用程序Gemfile中引用引擎时,不要使用标签。如果在引擎中创建新功能,则通过在本地覆盖上分支所有存储库来执行功能分支中的功能:

gitb checkout -b feature/branch_name

如果需要,可以通过在所有git存储库上拥有多个分支(如master,release和stable)来完成发布管理。使用以下命令将代码从一个环境移动到下一个环境:

gitb checkout release
gitb pull origin master
gitb push

3)如果您需要在引擎中扩展(装饰或猴子补丁)类,反之亦然:在查看可用的各种选项后,我们还制作了activesupport-decorators

答案 1 :(得分:1)

在好answer from Pierre Pretorius,一些研究和新经验之后,我设法解决了所有4个问题。我将解释每个问题的设置和解决方案:

  
      
  1. 如果有人更新核心应用程序,而不更新引擎,则可能会发生核心Gemfile.lock引用引擎的git提交,该引擎在本地不存在。如果尝试使用rails app,则会导致错误。
  2.   

要解决该问题(以及与此线程无关的其他一些问题),我们编写了一个脚本,该脚本关注更新引擎并执行一些其他必要的设置任务。对于每个引擎,将执行以下步骤:

  • 设置主应用程序的bundler配置以使用本地存储库
  • git pull -r --autostash或克隆,如果尚未克隆回购
  • bundle install
  • yarn install
  • bower install

之后,脚本会拉出并设置主应用程序。

对于更简单的设置,您可以使用git-bundle gem,它允许您在所有引擎上执行命令。

这最终解决了这个问题,即堆栈中的某些东西不是最新的。

  
      
  1. 在部署时(我认为),Gemfile.lock可能引用了一个提交ID,这比我想要部署的标记/版本的提交更新。我不确定在那种情况下会发生什么,但我担心,这只会让我们陷入麻烦。
  2.   

为了解决这个问题,我们告诉团队不要提交Gemfile.lock。相反,我们在发布主应用程序的新版本时更新并提交Gemfile.lock。这样,主应用程序总是引用每个引擎的具体(最新的)版本。但是,Bundler通过本地覆盖确保本地引擎存储库的HEAD将独立于锁定版本使用。

这种方式部署是一致的,并且与具体版本相关联,降级很容易,开发人员不必乱用版本,commitIds等。

  
      
  1. 我们在核心中有很多提交更改了Gemfile.lock(可能是其中一个引擎中的每个更改)。
  2.   

请参阅问题2的解决方案:我们只是不提交这些更改。这并不完美,但确实有效。

  
      
  1. 在本地使用另一个引擎分支,然后master强制开发人员更改主应用程序Gemfile中的分支名称。
  2.   

为了解决这个问题,我们将bundler config disable_local_branch_check设置为true:

bundle config disable_local_branch_check true

这样,我们可以从引擎的Gemfile中删除分支名称,开发人员可以使用他们可能想要在本地使用的任何分支(例如开发/审阅时的功能分支)。

之后,我们其中一个引擎的Gemfile条目如下所示:

gem 'nice_engine1', '0.0.1', git: '[...]', tag: 'v0.0.1'