I can't deploy a working rails 6 app on cloud foundry due to bundle version - bundler

I am experiencing this issue even having a higher version of bundler in my gemfile. What could be the issue causing this?
APP/PROC/WEB 0 from /home/vcap/app/bin/bundle:3:in `<main>'
Feb 18, 2021, 08:40:32 PM
APP/PROC/WEB 0 from /usr/lib/ruby/2.5.0/rubygems.rb:263:in `bin_path'
Feb 18, 2021, 08:40:32 PM
APP/PROC/WEB 0 To install the missing version, run `gem install bundler:2.1.4`
Feb 18, 2021, 08:40:32 PM
APP/PROC/WEB 0 To update to the lastest version installed on your system, run `bundle update --bundler`.
Feb 18, 2021, 08:40:32 PM
APP/PROC/WEB 0 /usr/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': Could not find 'bundler' (2.1.4) required by your /home/vcap/app/Gemfile.lock. (Gem::GemNotFoundException)
Feb 18, 2021, 08:40:32 PM
APP/PROC/WEB 0 /usr/lib/ruby/2.5.0/rubygems.rb:289:in `find_spec_for_exe': Could not find 'bundler' (2.1.4) required by your /home/vcap/app/Gemfile.lock. (Gem::GemNotFoundException)
Feb 18, 2021, 08:57:02 PM
APP/PROC/WEB 0 To update to the lastest version installed on your system, run `bundle update --bundler`.

The Ruby buildpack cannot carry every single version of Ruby & bundler, it would make for an extremely large buildpack. Due to this, all buildpacks will only retain a select set of versions of the software they include in each version of the buildpack. Buildpacks are meant to encourage you to keep up with the latest versions of your software, so buildpacks will drop older versions of software as the buildpacks are updated & new releases are cut.
This means you have three choices:
You can look at the release notes for your buildpack or the build pack dependency viewer to see buildpack versions contain the specific versions of software you require.
For example, if you must have bundler 2.1.4, then you'd need to look and find the latest buildpack version which contains it. Hint, it's v1.8.27. You can confirm the same info using the buildpack release notes also.
Once you find the specific buildpack version, then you need to tell Cloud Foundry that you want that version of the buildpack, which contains the version of the software you require. For example: cf push -b https://github.com/cloudfoundry/ruby-buildpack#v1.8.27.
This has some drawbacks though, a.) Cloud Foundry must be able to talk to the Internet and download that buildpack and b.) you're stuck with the versions of software in that buildpack, so your app may be vulnerable to security issues that have already been resolved in newer versions of software installed by the buildpack.
Most of the time you don't care about the exact specific version of Ruby, Bundler, or other libraries, and what you want is to declare a more flexible version in your project, like "I want Bundler 2". At which point, you'll just get the latest Bundler 2.x.y version supported, so long as the buildpack you're using still includes some version of Bundler 2 (even major versions will roll-off over time).
If you feel like you do need to continue specifying an exact version of Bundler (or other software), you will need to periodically update your application and the versions of software it uses to work with the more recent versions installed by the buildpack.
For example, the latest Ruby buildpack as I write this, 1.8.32, includes Bundler 2.2.11. That would mean you'd need to update your app to expect and work with this version.
In general, the most friction-free & safe option is #2. You'll continue to get updates to your software and it should continue to deploy without issue. The downside is that you may over time get an update that's incompatible with your app. You'd then have to fix that before you can continue deploying your app.
Option #3 is also OK, but it requires a lot of micromanagement. If you don't really need that level of control, I would suggest going with option #2. You'll get similar results and it'll be less effort.
Option #1 should be a last resort and only used if your app absolutely has no other option, or perhaps you need to buy some time as you upgrade the app to be compatible with newer versions. This version, over time, will leave your app susceptible to security vulnerabilities.
You might be thinking that this all sounds like a tremendous pain, but it's not. It's the buildpack forcing you to think about your software dependencies and forcing good upgrade hygiene. That is a very good thing, as it will keep your software up-to-date and keep your application protected from vulnerabilities in the software it consumes.

Related

asdf-vm: Can I use global packages associated with the latest installed version of a runtime when working on a project that uses an older runtime?

I will try to explain my question with an example. The contents of my ~./default-gems are:
gem-ctags
dip
bundler
gem-browse
pry
pry-byebug
pry-doc
pry-theme
rubocop
rubocop-performance
rubocop-rake
rubygems-update
ruby-debug-ide
ruby_parser
seeing_is_believing
solargraph
sqlint
This setup is working fine for me but I was wondering if there is a way to use the gems associated with my latest runtime (currently ruby 3.2.0-dev) when working with older runtimes and/or if it would pose compatibility issues.
If not for all global gems, at least for some of them, would it be safe to uninstall those associated with older runtimes?
Thank you
It seems that it is safe to remove global packages associated with older runtimes as long as I keep those installed with the lastest runtime. Then I can configure a project as usual, remembering to add the latest runtime at the end.
asdf local <plugin> <project version> <latest installed version> creates a .tool-versions file declaring that. For example, for a Ruby project I am testing, the .tool-versions contents are:
ruby 2.6.6 3.2.0-dev

Sharing in development Ruby Gems

We use Rails for the majority of our web projects and in a lot of cases we share code we have as dependancies such as our API as Gems. We also have some projects which are similar in nature enough that we've built Engines and then have host applications that use these.
These are all hosted on our own servers and we share the Gems with the projects using Gem In A Box (this is because we can't upload the Gems to anywhere else due to security restrictions). During development we comment out the lines to reference either a specific version on our server or our local version if we are developing within the Gem itself.
So for example:
# version on the server
gem 'our_gem', '1.1.0', source: 'https://gems.domain.net'
# local version
gem 'our_gem', path: '../our_gem'
What happens is that when we do a build on our CI server we then have a script that reads through the Gemfile and finds any gems that have our server as the source and then vendorize them and reference them as the vendored path.
For example:
# this
gem 'our_gem', '1.1.0', source: 'https://gems.domain.net'
# becomes this
gem 'our_gem', path: 'vendor/gems/our_gem-1.1.0'
However the problem we have encountered is that when we are in development and we may have several features or bugs we want to push to our QA team to start testing it means we have to bump the version each time so we can reference it in our Gemfile's as a dependancy. We can't reference the branch due to the Git repository not accessible to our build setup and some other restrictions.
How do teams usually handle in-development dependancies that don't have a version yet? We've thought about having a development version of Gem In A Box and then not passing a version to it in our Gemfile...
# shared dev version of gem on our dev gem server
gem 'our_gem', source: 'https://dev.gems.domain.net'
But the problem here is that we still need to up the version every time in order to push to the Gem Server. Is there a standard way to push a package to a Package Manager whereby the version is always the same (or better yet is version-less but hosted by the manager)?
We also have the same issue with NPM (we run a local version of Vedaccio).

Set version to latest version including prereleases in Gemfile

How do I specify a version constraint in a Gemfile, such that it always take the latest release including pre-releases of a gem.
Currently the library I work with has the latest stable release 2.0.0, and the latest pre-release 2.1.0.alpha.pre.171.
I could set the version constraint to >=2.1.0.alpha.pre.171 or just >=2.1.0.a, as I understand it. But would that also include future pre releases such as >=2.2.0.alpha.pre.1 or even >=3.0.0.alpha.pre.1 as well as future stable versions such as 3.0.0? And would that always resolve to the latest version?
Disclaimer:
To not be misunderstood, this is not for any productive dependency management. The idea is to have a demo up an running, which should always include the latest features and as well should crash if the latest pre-release is broken.
This is a very bad idea in a nutshell, but it’s very easy to check:
%w|2.1.0.alpha.pre.171
2.1.0
2.2.0.alpha.pre.1
3.0.0.alpha.pre.1|.map(&Gem::Version.method(:new)).sort
#⇒ [
# [0] #<Gem::Version "2.1.0.alpha.pre.171">,
# [1] #<Gem::Version "2.1.0">,
# [2] #<Gem::Version "2.2.0.alpha.pre.1">,
# [3] #<Gem::Version "3.0.0.alpha.pre.1">
# ]
So, yes, >= will work for any new release, including 2.1.0.
You'll want to do two things:
Specify >= 2.1.0.alpha.pre.171 in your Gemfile. The important thing here is that the specified constraint is itself a pre-release, which is the only way to make Bundler will pick up that you want pre-releases1. All future releases, including pre-releases and major releases, will then be included when Bundler looks for updates.
Use an automated tool to regularly update the Gemfile.lock. Any of Dependabot, Depfu or Deppbot would work. (Disclosure: I wrote Dependabot.)
Surprisingly, as of Bundler 1.15.1, there's no option that can be passed to bundle update that replicates the behaviour created by (1).
https://github.com/bundler/bundler/blob/v1.15.1/lib/bundler/index.rb#L194-L200

Can I stop Bundler from adding RUBY VERSION to Gemfile.lock

Every time I run any gem command on the command line, Bundler insists on touching my Gemfile.lock file to add this line:
RUBY VERSION
ruby 2.2.2p95
I don't want to commit this to our repository, because it means every dev using a different patch level of Ruby 2.2.2 is going to be in a commit war with me. (I've already resigned myself to a similar issue with the BUNDLED_WITH line.) But I can't deploy unless I do commit that line, because our deploy runs via a rake task and running the deploy leads Bundler to add this block, whereupon the deploy process says, "WAIT! Your working tree is dirty! You might be deploying incomplete changes!!!!1!" (Well, not literally, but you get the idea.)
Can I tell Bundler to leave the RUBY VERSION (and, ideally, BUNDLED_WITH) out of the Gemfile.lock so we don't have to do this ridiculous dance?
(how to prevent bundler from adding platform info to Gemfile.lock seems to be the same question, but there's no answer, natch.)
I don't think so, but maybe it's okay:
As of 2.1.0, Ruby no longer has multiple patch level releases for a given version. See accepted answer on How do version numbers work for MRI Ruby?
2.2.2p95 is the only patch level of 2.2.2 that will ever be released. 'p95' just means that there have been 95 commits since 2.2.0.
Since your whole team will be on 2.2.2 anyway, it shouldn't cause problems to leave this in your Gemfile.lock. (As long as everyone updates Bundler to the version that does this, anyway. Otherwise there'll still be conflicts as the ruby version is added and removed.)
No, it can't be removed, at least in the version(s) of Bundler current as I write this.
This block is added in the #to_lock method of Bundler::Definition. The only conditional it's wrapped in is if locked_ruby_version, and locked_ruby_version is a method which returns either the version defined in an existing lockfile (Gemfile.lock) or the system Ruby - Bundler tries very hard to avoid letting locked_ruby_version return a falsy value.
If you are using some sort of version control like Git you can add the Gemfile.lock to your .gitignore file.
This way anytime you push up a new change you will not push up your Gemfile.lock. Especially since other developers do not need it - once they run bundle, bundle will create a new Gemfile.lock on completion.

Node.js version and Heroku

So, I got a small site started in node.js (my first one) using Express. Pretty happy with it, until I tried to deploy to Heroku and found that I had 0.4.9 installed and they only support 0.4.7.
Is uninstalling 0.4.9 and installing 0.4.7 my only option, or is there a way to do a side-by-side on the two?
You can override the version of node.js and npm by customizing the Heroku build pack:
http://blog.superpat.com/2011/11/15/running-your-own-node-js-version-on-heroku/
Actually...you do not have to remove anything.
Just ensure you are using features of node compliant with node 0.4.7 and when you make your package.json which specifies your dependencies has the correct version number or range specified.
I had a similar issue where one of our developers made is packacge and set the dependency to node 0.4.8 however it didn't require this it was just what version he was using at the time, we ended up updating his package.json to list node 0.4.7 instead and then my package which depended on his deployed to heroku just fine.
It seems Heroku only supports 0.4.7 at the moment and even suggests to develop strictly on that version.
If you have to use heroku then you have to uninstall 0.4.9, install 0.4.7.
If you don't have to use heroku. You can always setup a VPS yourself, and you will have the freedom to install whatever version that pleases you. :D

Resources