-
-
Notifications
You must be signed in to change notification settings - Fork 1.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Proposal to allow defining different lockfile name not based on Gemfile name #3238
Comments
This seems like a good feature to have. I think the only thing that we need to be aware of is loading the correct Bundler version works given the Gemfile.lock with the env var. |
Yes we do this at GitHub and it's been a huge pain for us. In order to do it correctly for all our systems we had to vendor and hack bundler. I'd love for it to be a supported feature so we don't need to do that anymore. |
I normally use two different gemfiles for this kind of situations (well, three actually), and then set the Gemfilegem 'rails', '~> 5.2'
eval_gemfile "Gemfile.common" Gemfile.nextgem 'rails', github: 'rails/rails', branch: 'master'
eval_gemfile "Gemfile.common" |
I experimented with David's approach for a while. While it is great that bundler already supports this way of having two different set of gems while sharing some other gems it gets very annoying when you have a gem that used to be in the But the proposed solution is also not ideal. Instead of one environment variable you have now to set two. This can cause problem when you forgot to set one of them and you will be booting with a different lock that will conflict with the gems required by the Gemfile. The ideal solution in my opinion would have the approach pointed by David, that only require one option being passed, but with gems being allowed to be redefined without errors or warnings. I understand allowing redefining could introduce problems in applications so I think that is not something we can change easily. |
We initially seen this approach as the best course since it was already supported by Bundler however similar to @rafaelfranca, it becomes an issue when you need to decide if a gem is common or needs a specific override. It also made debugging a little more difficult since you needed to remember which Gemfile and setup is was using. While this seems like a non-issue, the size and age of our application lends itself to quite a bit of complexity and sometimes it's difficult to ascertain direct vs implied dependencies. By maintaining a single Gemfile, it's one less hoop to jump through.
I agree here and while it's not perfect, it will allow us (and a few other big Rails apps) to get back onto the mainline of Bundler without managing our own patched versions which I think is a big win in itself. We mitigate the forgotten environment variable data by populating it across the board automatically in CI and locally a centralised bundle script that defines these based on whether or not you tell it that you want to run the "next" version. Not sure if that works for all though.
I do like this idea but as you suggest, this might not be as straight forward as it seems and could introduce some hidden gotchas. Overall, I don't think this is something that will impact alot of people (could be wrong though!) so I think the risk here is pretty minimal and the people that will be using this are using far jankier approaches to make it work so they will be happy it's less to maintain. |
The other thing is that we're assuming that we only ever have 2 lock files. In many cases we (GitHub) have 3. When we were doing the Rails upgrade we would have the main lock file Gemfile.lock, the one for the version that we'd recently gotten green Gemfile_rails51.lock and the one for the version we were going to Gemfile_rails52.lock. To prevent regressions once a build was green we'd swap it out. So the 4.0 gemfile/build became 4.1 while we worked on 4.2, when 4.2 was green we deleted 4.1 and added 5.0. This was so we could keep working on the next version and keep regressions from being introduced. Now that we're on 5.2.1 we have just the Gemfile.lock and Gemfile_next.lock for Rails upgrades. However we're doing a new project that requires us swapping out a major gem that is not rails so we have a third gemfile for that project. For that reason, I don't think we should limit this feature to just Gemfile.lock and Gemfile.next. There should be a simple way to swap out your gemfile regardless of the reason you're doing it. |
I understand that there are little annoyances with the
The bundler CLI has gotten many improvements lately for automatically editing gemfiles. Probably an some alias combination of |
Until there is better handling of multiple gem definitions which don't result in warnings or errors,
@eileencodes just to confirm on this comment, would my proposal of the two environment variables (existing |
Would not both solutions require tooling? Yours would requiring tooling to support two environment variables and changes to bundler. The common Gemfile requires tooling to support Not saying that the common Gemfile is the ideal solution, but in my opinion is better than two distinct env vars that introduce the risk of one of them not matching the other. |
I fully agree with @rafaelfranca. Regarding how to "silence" warnings or errors, I was thinking of a config setting where the last duplicated gem dependency would overwrite any previous definition, instead of erroring (if the duplicated definitions don't match) or warn (if the definitions match). I'm just not sure if the little annoyances of the |
Our setup is hidden behind a single environment flag, if [[ "${RAILS_NEXT}" = "1" ]]; then
BUNDLE_GEMFILE_LOCKFILE="Gemfile_next.lock" bundle install
else
bundle install
fi Which minimises the risk of mismatching. This applies to setup, running the server, CI, etc. The joy of this is that it's very low friction for developers of all levels and streamlines these processes where people may want to try the new version of a gem but don't quite know the ins and outs of applications and their setups. Using multiple Gemfiles and relying on |
You could do the same using multiple gemfiles with if [[ "${RAILS_NEXT}" = "1" ]]; then
BUNDLE_GEMFILE="Gemfile_next" bundle install
else
bundle install
fi I'm not sure I fully understand the additional complexity of the more complicated scenarios you need to support, but intuitively both approaches seem to have a similar level of complexity to me. For example, Gemfilegem 'rails', '~> 5.2'
gem 'devise', '~> 4.0'
eval_gemfile "Gemfile.common" Gemfile.edgegem 'rails', github: 'rails/rails', branch: 'master'
gem 'devise', github: 'plataformatec/devise', branch: 'master'
eval_gemfile "Gemfile.common" Gemfile.next_railsgem 'rails', github: 'rails/rails', branch: 'master'
gem 'devise', '~> 4.0'
eval_gemfile "Gemfile.common" Gemfile.next_devisegem 'rails', '~> 5.2'
gem 'devise', github: 'plataformatec/devise', branch: 'master'
eval_gemfile "Gemfile.common" That's 4 different gemfiles, but with your single gemfile approach you would need six different environment variables: |
I've been thinking about this the last couple of days and I realised we got so caught up discussing the
For this, I still think adding the ability to output the lock file to a desired location is the path I think we should pursue here. |
I think I'm missing something. The That being said I think it satisfy the first buttle point. For the second point is it not possible to add the |
No, you haven't missed anything. I've still just got a patched version locally which skews this a little 🤦♂️ Thanks for confirming that!
The calculation would need to know which one it was building otherwise one Gemfile change could impact the others and cause extra compilation steps that won't be needed. An option here would be to export the Have we got any further ideas on the declaration of multiple gems and how that would be handled? |
This is interesting but I think it would also be beneficial to have it the other way around too. You define your overrides upfront instead of taking on the latest defined. It would allow you to have stable fallbacks but overrides for newer/unstable builds too. |
I might be also misunderstanding something but I'd say the |
@deivid-rodriguez I'm in the process of trying to update our build/CI infrastructure relying on |
As a FYI, many of our apps at Shopify needs to be dualbooted, we needed a solution to make things easier for our developers so we recently built bootboot Sadly, the dualbooting part currently can't work when bundler is frozen (which is most likely the case in your production environment) because of what I think might™ be an issue on bundler rubygems/bundler#6795 We can hopefully try to fix it soon. In the meantime bootboot can still be usefull if you want to ensure that both your lockfiles are always in sync |
Thanks @Edouard-chin, appreciate it! Will definitely check it out! |
Big hat tip to @Edouard-chin and the folks at Shopify for bootboot, it's been working flawlessly since we jumped onto it and it's taken care of the keeping things in sync issue. 🍻 |
Thanks @jacobbednarz , very happy that it helps you ! Also happy new year :) |
We use Bundler on a quite a large Rails installation and one of the pain points we're looking to eliminate is that of major updates. I won't bore you with the details however we essentially are working to the point where we can run multiple versions of Rails in CI and various parts of our infrastructure using a single Gemfile. The Gemfile looks like this:
During our CI/deployment populate the
RAILS_NEXT
with the respective value and it will run the app or test suite using the expected gem versions. The issue with this is that bundler expects the lock file to be the name of the Gemfile appended with.lock
. This is problematic for us as we would like this to be dynamic based on some level of environment input and to work around this, we have a vendored bundler version that patches this method to allow the lock file name to be appended differently.This patch is quite specific to us and the way we intend to run our systems however I wanted to open a discussion (and perhaps a code proposal) to allow an environment variable (similar to
BUNDLE_GEMFILE
) whereby we could define what the lock file name could be. I'd propose an environment variableBUNDLE_GEMFILE_LOCKFILE
to be made accessible and (my example) usage would end up being:This would achieve using a single Gemfile but dynamically outputting the dependencies to a separate lockfile which could later be referenced for installation/vendoring/etc.
We would default this environment variable to the existing Gemfile.lock (or gems.lock when it's ready for release).
cc @rafaelfranca @eileencodes as from previous conversations both Shopify and GitHub also have custom implementations of this.
The text was updated successfully, but these errors were encountered: