Tagged: bundler Toggle Comment Threads | Keyboard Shortcuts

  • kmitov 7:10 am on January 20, 2021 Permalink |
    Tags: bundler,   

    ‘bundle update’ – why we run it regularly and automatically to update our dependencies? 

    (Everyday Code – instead of keeping our knowledge in an README.md let’s share it with the internet)

    Today it’s Wednesday and on Wednesday we have an automatic Jenkins job that would run ‘bundle update’. This will be 567-th time this build is run. It has saved us a lot of work and this article I would like to share why and how we automatically do ‘bundle update’

    What is ‘bundle update’?

    In the Ruby and Ruby on Rails world the dependencies are called gems. Gems could be installed with the ‘gem’ command. ‘bundle’ is a command provider by the Bundler tool. It automates this process. To quote from the Bundler web site

    Bundler provides a consistent environment for Ruby projects by tracking and installing the exact gems and versions that are needed.

    Bundler is an exit from dependency hell, and ensures that the gems you need are present in development, staging, and production. Starting work on a project is as simple as bundle install.

    https://bundler.io/

    With Bundler you can have two different projects working with two different sets of dependencies and Bundler will make sure the right dependencies are available for each project.

    What is ‘$ bundle install’?

    Both FLLCasts and BuildIn3D are Rails platforms. Before starting the platforms we should install all the dependencies. We use Bundler and the command is

    $ cd platform/
    $ bundle install

    ‘$ bundle install’ will make sure that all the gems that we are dependent on are available on our machine.

    FLLCasts and BuildIn3D for example are dependent on:

    # FLLCasts Gemfile contains
    gem "rails", '~> 6.0.3'
    gem "webpacker", "~> 5.0"
    gem 'turbolinks', '~> 5.2.0'

    This means that we are happy to work with any version of turbolinks that is 5.2.X. It could be 5.2.0, 5.2.1, 5.2.2 and so on. The last digit could change.

    ‘bundle install’ makes sure that you have a compatible version. But what if there is a new version of turbolinks – 5.2.5?

    What is ‘$ bundle update’?

    ‘$ bundle update’ for me is the real deal. It will check what new compatible versions are released for the gems we depend on. If we are currently using turbolinks 5.2.0 and there is 5.2.1 ‘bundle update’ will check this and will fetch the new version of turbolinks for us to use. It will write the specific versions that are used in the Gemfile.lock.

    For the turbolinks example the Gemfile.lock contains:

    # Gemfile.lock for FLLCasts and BuildIn3D
        turbolinks (5.2.1)
          turbolinks-source (~> 5.2)

    When should one run ‘$ bundle update’?

    That’s a thought question and a hard sale. Every team member on our team has at a certain point asked this question or made a statement like ‘But this is not automatic. I want to update dependencies when I want to update dependencies!” or has in some way struggle with ‘$ bundle update’. Myself included.

    The answer is:

    As the rails and ruby communities are live and vibrant things are improved quite often. One should run ‘$ bundle update’ regularly and one should do it automatically to make sure the dependencies are up to date.

    But updating the dependencies could break the platform!

    Automatic ‘bundle update’ could break any platform?

    Yes. It could. That’s why the are doing

    # Run bundle update
    $ bundle update
    
    # Commit the new result to a new branch
    $ git push elvis pr_fllcasts_update --force
    
    # Try to merge the new branch like any other branch. Run merge and then the specs
    $ git merge ...
    $ rake spec (on the merge)
    # If rake is successful continue with the merge. If it is not, then abort the merge. 

    We update and commit the changes to a new Branch (or create a Pull Request, depending on the project), and we then run the normal build.

    It will pull from this Branch (or PR) and will run the specs. If the specs pass successfully we continue with the merge.

    In this way we are constantly up to date

    What is the benefit of automatic ‘$ bundle update’?

    As I’ve written before the main benefit is the allocation of resources and keeping the developers context – https://kmitov.com/posts/the-benefits-of-running-specs-against-nightly-releases-of-dependencies/

    If a change in a gem breaks something that we are dependent on we can identify this in a week. We are not waiting months and we can report it now. The gem owners are probably still in the context of the change they’ve introduced and could faster understand and resolve the issue.

    Additionally we no longer have ‘migrates’ on our team. We are not dedicating any resource to ‘migrating to new dependencies’ as it happens automatically.

    #  Here are just the gems from Jan 13, 2021 7:00:00 AM
    Installing aws-partitions 1.416.0 (was 1.413.0)
    Installing chef-utils 16.9.20 (was 16.8.14)
    Installing autoprefixer-rails 10.2.0.0 (was 10.1.0.0)
    Installing omniauth 2.0.0 (was 1.9.1)
    Installing http-parser 1.2.3 (was 1.2.2) with native extensions
    Installing dragonfly 1.3.0 (was 1.2.1) Installing aws-sdk-core 3.111.0 (was 3.110.0)
    Installing omniauth-oauth2 1.7.1 (was 1.7.0)
    Installing aws-sdk-kms 1.41.0 (was 1.40.0)
    Installing globalize 5.3.1 (was 5.3.0) Installing money-rails 1.13.4 (was 1.13.3)
    

    Every Wednesday we update the gems and if there are problems we know at the middle of the week to be able to address them at the moment or to schedule them appropriately for the next weeks.

     
  • kmitov 9:56 am on April 4, 2020 Permalink |
    Tags: bundler, , geminabox, rake,   

    bundle exec vs non bundle exec. 

    This article is part of the series [Everyday code].

    We use bundler to pack parts of the Instruction Steps Framework, especially the parts that should be easy to port to the rails world. We learned something about Bundler so I decide to share it with everybody.

    TL; DR;

    Question is – which of these two should you use:

    # Call bundle exec before rake
    $ bundle exec rake 
    
    # Call just rake
    $ rake

    ‘bundle exec rake’ will look at what is written in your .gemspec/Gemfile while rake will use whatever is in your env.

    Gem.. but in a box
    gem inabox with bundler

    Bundle exec

    For example we use geminabox, a great tool to keep an internal repo of plugins. In this way rails projects could include the Instruction Steps framework directly as a gem. This makes it very easy for rails projects to use the Instruction Steps.

    To put a gem in the repo one must execute:

    $ gem inabox

    You could make this call in three different ways. The difference is subtle, but important.

    Most of the time the env in which your shell is working will be almost the same as the env in which the gem is bundled. Except with the cases when it is not.

    From the shell

    # This will use the env of the shell. Whatever you have in the shell.
    $ gem inabox

    From a rake file

    If you have this rake file

    require 'rails/all'
    
    task :inabox do 
      system("gem inabox")
    end

    then you could call rake in the following ways:

    rake inabox

    # This will call rake in the env defined by the shell in which you are executing
    $ rake inabox

    bundle exec rake inabox

    # This will call rake in the env of the gem
    $ bundle exec rake inabox

    When using the second call bundle will look at the ‘.gemspec’/’Gemfile’ and what is in the gemspec. If non of the gems in the .gemspec adds the ‘inabox’ command to the env then the command is not found and an error occurs like:

    ERROR:  While executing gem ... (Gem::CommandLineError)
        Unknown command inabox

    If ‘gem inabox’ is called directly from the shell it works, but to call gem inabox from a rake job you must have ‘geminabox’ as development dependency of the gem. When calling ‘gem inabox’ from a shell we are not using the development env of the gem, we are using the env of the shell. But once we call ‘bundle exec rake inabox’ and it calls ‘gem inabox’, this second call is in the environment of the gem. So we should have a development_dependency to the ‘geminabox’ gem:

     spec.add_development_dependency 'geminabox'

    Nice. Simple, nice, logical. One just has to know it.

     
c
compose new post
j
next post/next comment
k
previous post/previous comment
r
reply
e
edit
o
show/hide comments
t
go to top
l
go to login
h
show/hide help
shift + esc
cancel