Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Bundling Bundler 2.0

Bundling Bundler 2.0

Given at RubyConf BR 2017

Samuel E. Giddins

November 17, 2017
Tweet

More Decks by Samuel E. Giddins

Other Decks in Technology

Transcript

  1. Bundling Bundler 2.0
    Samuel Giddins
    Samuel Giddins, RubyConf BR 2017 1

    View Slide

  2. @segiddins
    Samuel Giddins, RubyConf BR 2017 2

    View Slide

  3. @segiddins
    • Bundler's primary committer
    • RubyGem's primary committer
    • RubyGems.org occasional contributor
    • RubyGems security
    • Mostly finished writing Bundler 2
    • Released CocoaPods 1.0
    Samuel Giddins, RubyConf BR 2017 3

    View Slide

  4. Why Bundler 2?
    Samuel Giddins, RubyConf BR 2017 4

    View Slide

  5. The Forever Plan
    Samuel Giddins, RubyConf BR 2017 5

    View Slide

  6. The Forever Plan
    • Fix every known bug
    • Deprecate everything we wanted to get rid of by
    1.0.0.0.0.0.0.1
    • Don't make promises we can't deliver
    • Ship in ~2012
    Samuel Giddins, RubyConf BR 2017 6

    View Slide

  7. The Tools We Built
    Samuel Giddins, RubyConf BR 2017 7

    View Slide

  8. The Tools We Built
    • bundler-changelog
    • FeatureFlag
    • documentation tests
    • changing Bundler versions on CI
    Samuel Giddins, RubyConf BR 2017 8

    View Slide

  9. bundler-changelog
    https://github.com/bundler/bundler-changelog
    Samuel Giddins, RubyConf BR 2017 9

    View Slide

  10. bundler-changelog
    bundler-changelog
    !"" CHANGELOG.md
    !"" changes
    !"" changes.csv
    !"" from_changelog
    !"" lib
    # $"" changelog.rb
    !"" open_prs_since
    $"" releases.csv
    Samuel Giddins, RubyConf BR 2017 10

    View Slide

  11. Bundler::FeatureFlag
    Samuel Giddins, RubyConf BR 2017 11

    View Slide

  12. Bundler::FeatureFlag
    module Bundler
    class FeatureFlag
    def self.settings_flag(flag, &default)
    settings_method("#{flag}?", flag, &default)
    end
    def self.settings_option(key, &default); end
    def self.settings_method(name, key, &default); end
    (1..10).each {|v| define_method("bundler_#{v}_mode?") { major_version >= v } }
    def initialize(bundler_version); end
    def major_version; end
    settings_flag(:allow_bundler_dependency_conflicts) { bundler_2_mode? }
    settings_option(:default_cli_command) { bundler_2_mode? ? :cli_help : :install }
    end
    end
    Samuel Giddins, RubyConf BR 2017 12

    View Slide

  13. Bundler::FeatureFlag
    - if Bundler::Version.split(".").first.to_i >= 2
    - if Gem::Version.new(Bundler::VERSION) >= Gem::Version.new("2.0")
    + if Bundler.feature_flag.enable_cool_new_feature?
    new_behavior
    end
    Samuel Giddins, RubyConf BR 2017 13

    View Slide

  14. Documentation Tests
    • Every setting documented
    • Bundler can't use arbitrary config settings any
    more
    • Keep language friendly & welcoming
    • All commands have a custom man page
    Samuel Giddins, RubyConf BR 2017 14

    View Slide

  15. Changing Bundler versions on CI
    language: ruby
    script: rake spec:travis
    before_script:
    - travis_retry rake spec:travis:deps
    - travis_retry rake override_version
    - travis_retry rake man:build
    - travis_retry rake spec:rubygems:clone_rubygems_$RGV
    branches:
    only:
    - master
    - auto
    - /.+-dev$/
    - /.+-stable$/
    notifications:
    slack:
    on_success: change
    on_failure: always
    rooms:
    - secure: JxBi7DDJGkIF/7f/FSN/HUHpvV4EKfQccZHTPd1b2pNJn3GXo6u+tNVbAw2WjxYzPyPQI3ZcYBCU9SEXp/i7VmG8uMzh8Kyildw+miSKYKVb90uYqcsXWzbxwyNBgJLvyDkzST45H5lgnyAicee3WkFes/WDZikIajbH7ztdb04=
    addons:
    code_climate:
    repo_token:
    secure: "TrzIv116JLGUxm6PAUskCYrv8KTDguncKROVwbnjVPKTGDAgoDderd8JUdDEXrKoZ9qGLD2TPYKExt9/QDl71E+qHdWnVqWv4HKCUk2P9z/VLKzHuggOUBkCXiJUhjywUieCJhI3N92bfq2EjSBbu2/OFHqWOjLQ+QCooTEBjv8="
    rvm:
    - 2.4.1
    - 2.3.4
    - 2.2.7
    - 2.1.10
    - 2.0.0
    - 1.9.3
    - 1.8.7
    # Rubygems versions MUST be available as rake tasks
    # see Rakefile:125 for the list of possible RGV values
    env:
    # We need to know if changes to rubygems will break bundler on release
    - RGV=master
    # Test the latest rubygems release with all of our supported rubies
    - RGV=v2.6.8
    matrix:
    include:
    - rvm: 2.4.1
    env: RGV=v2.6.8 BUNDLER_SPEC_SUB_VERSION=2.0.0
    # Ruby 2.4, Rubygems 2.6.8 and up
    # Ruby 2.3, Rubygems 2.5.1 and up
    - rvm: 2.2.6
    env: RGV=v2.5.2
    # Ruby 2.2, Rubygems 2.4.5 and up
    - rvm: 2.2.6
    env: RGV=v2.4.8
    # Ruby 2.1, Rubygems 2.2.2 and up
    - rvm: 2.1.10
    env: RGV=v2.2.5
    # Ruby 2.0.0, Rubygems 2.0.0 and up
    - rvm: 2.0.0
    env: RGV=v2.2.5
    - rvm: 2.0.0
    env: RGV=v2.1.11
    - rvm: 2.0.0
    env: RGV=v2.0.14
    # Ruby 1.9.3, Rubygems 1.5.3 and up
    - rvm: 1.9.3
    env: RGV=v2.2.5
    - rvm: 1.9.3
    env: RGV=v2.1.11
    - rvm: 1.9.3
    env: RGV=v2.0.14
    - rvm: 1.9.3
    env: RGV=v1.8.29
    - rvm: 1.9.3
    env: RGV=v1.7.2
    - rvm: 1.9.3
    env: RGV=v1.6.2
    - rvm: 1.9.3
    env: RGV=v1.5.3
    # Ruby 1.8.7, Rubygems 1.3.6 and up
    - rvm: 1.8.7
    env: RGV=v2.2.5
    # ALLOWED FAILURES
    # since the great Travis image outage, frequent random segfaults :'(
    - rvm: 1.8.7
    env: RGV=v2.0.14
    - rvm: 1.8.7
    env: RGV=v1.8.29
    - rvm: 1.8.7
    env: RGV=v1.7.2
    - rvm: 1.8.7
    env: RGV=v1.6.2
    - rvm: 1.8.7
    env: RGV=v1.5.3
    - rvm: 1.8.7
    env: RGV=v1.4.2
    - rvm: 1.8.7
    env: RGV=v1.3.7
    - rvm: 1.8.7
    env: RGV=v1.3.6
    # Ruby-head (we want to know how we're doing, but not fail the build)
    - rvm: ruby-head
    env: RGV=master
    allow_failures:
    - rvm: 1.8.7
    env: RGV=v2.0.14
    - rvm: 1.8.7
    env: RGV=v1.8.29
    - rvm: 1.8.7
    env: RGV=v1.7.2
    - rvm: 1.8.7
    env: RGV=v1.6.2
    - rvm: 1.8.7
    env: RGV=v1.5.3
    - rvm: 1.8.7
    env: RGV=v1.4.2
    - rvm: 1.8.7
    env: RGV=v1.3.7
    - rvm: 1.8.7
    env: RGV=v1.3.6
    - rvm: ruby-head
    env: RGV=master
    Samuel Giddins, RubyConf BR 2017 15

    View Slide

  16. Changing Bundler versions on CI
    Rspec.describe "the lockfile format", bundler: "< 1" do
    end
    Rspec.describe "the lockfile format", bundler: 2 do
    end
    Samuel Giddins, RubyConf BR 2017 16

    View Slide

  17. Intermission
    The Other Forever Plan
    Samuel Giddins, RubyConf BR 2017 17

    View Slide

  18. The Other Forever Plan
    The rumors of Bundler's death have been greatly exaggerated
    http://bundler.io/blog/2013/12/07/the-rumors-of-
    bundlers-death-have-been-greatly-exaggerated.html
    Samuel Giddins, RubyConf BR 2017 18

    View Slide

  19. The Other Forever Plan
    • Shipping Bundler in Ruby ✔
    • Merging RubyGems and Bundler ✔✘
    • Making everything forward and backward
    compatible ✘
    Samuel Giddins, RubyConf BR 2017 19

    View Slide

  20. Top 10 Changes
    Samuel Giddins, RubyConf BR 2017 20

    View Slide

  21. Dropping old Ruby / RubyGems Support
    Samuel Giddins, RubyConf BR 2017 21

    View Slide

  22. Dropping old Ruby / RubyGems Support
    spec.required_ruby_version = ">= 2.3"
    spec.required_rubygems_version = ">= 2.5"
    Samuel Giddins, RubyConf BR 2017 22

    View Slide

  23. Command-Line Flags Aren't Remembered
    Samuel Giddins, RubyConf BR 2017 23

    View Slide

  24. New bundle config Interface
    Samuel Giddins, RubyConf BR 2017 24

    View Slide

  25. New bundle config Interface
    Old:
    $ bundle config # list all settings
    $ bundle config "path" # print the current `path` setting
    $ bundle config "path" "vendor" # set the path to "vendor"
    $ bundle config --delete "path" # delete the current setting for `path`
    Samuel Giddins, RubyConf BR 2017 25

    View Slide

  26. New bundle config Interface
    New:
    $ bundle config list # list all settings
    $ bundle config get "path" # print the current `path` setting
    $ bundle config set "path" "vendor" # set the path to "vendor"
    $ bundle config unset "path" # delete the current setting for `path`
    Samuel Giddins, RubyConf BR 2017 26

    View Slide

  27. Isolated Installs
    Samuel Giddins, RubyConf BR 2017 27

    View Slide

  28. Isolated Installs
    The new default:
    $ bundle install --path ".bundle"
    Samuel Giddins, RubyConf BR 2017 28

    View Slide

  29. Isolated Installs
    The old default:
    $ bundle config set path.system true
    Samuel Giddins, RubyConf BR 2017 29

    View Slide

  30. Aggressive Caching
    Samuel Giddins, RubyConf BR 2017 30

    View Slide

  31. Aggressive Caching
    • Caching built extensions
    • Global gem download cache
    • Global git cache
    Samuel Giddins, RubyConf BR 2017 31

    View Slide

  32. Aggressive Caching
    /Users/segiddins/.bundle/cache
    !"" compact_index
    # !"" rubygems.org.443.29b0360b937aa4d161703e6160654e47
    !"" extensions
    # $"" x86_64-darwin-16
    !"" gems
    # $"" rubygems.org.443.29b0360b937aa4d161703e6160654e47
    $"" git
    !"" CLAide-1f7c26f0e18404ea56d6204dab591f5ec71ac1b9
    !"" Molinillo-9d794a0756ad56a3e90d93c578f55158b9102520
    Samuel Giddins, RubyConf BR 2017 32

    View Slide

  33. Multi-Source Safety
    Samuel Giddins, RubyConf BR 2017 33

    View Slide

  34. Multi-Source Safety
    Addressing Bundler's First CVE
    Samuel Giddins, RubyConf BR 2017 34

    View Slide

  35. Multi-Source Safety
    source "https://rubygems.org"
    source "https://not-rubygems.org"
    gem "rails"
    Samuel Giddins, RubyConf BR 2017 35

    View Slide

  36. Errors Are Now Called Errors
    Samuel Giddins, RubyConf BR 2017 36

    View Slide

  37. Local Platforms are Respected
    Samuel Giddins, RubyConf BR 2017 37

    View Slide

  38. Local Platforms are Respected
    gem "ffi"
    ffi-1.9.1
    ffi-java-1.9.1
    ffi-universal-darwin-1.9.1
    ffi-x86_64-darwin-16-1.9.1
    Samuel Giddins, RubyConf BR 2017 38

    View Slide

  39. Bundler Is More Fun To Develop
    Samuel Giddins, RubyConf BR 2017 39

    View Slide

  40. Counting is Hard,
    Maybe Fewer Than 10 Exciting Things
    Samuel Giddins, RubyConf BR 2017 40

    View Slide

  41. Back To The Top
    Why Bundler 2?
    Samuel Giddins, RubyConf BR 2017 41

    View Slide

  42. Why Bundler 2?
    • Why do we need a new major release?
    • Why talk about it?
    • Why pour so much effort into it?
    Samuel Giddins, RubyConf BR 2017 42

    View Slide

  43. Why Bundler 2?
    A brief history of Bundler usage1
    Version Release Date Downloads
    0.3.0 July 29, 2009 3,308
    1.0.0 August 29, 2010 297,889
    1.15.4 August 19, 2017 12,493,974
    All Time 205,973,132
    1 Current as of November 10, 2017
    Samuel Giddins, RubyConf BR 2017 43

    View Slide

  44. Why Bundler 2?
    A brief history of Bundler:
    http://andre.arko.net/2015/04/28/how-does-bundler-
    work-anyway/
    • André Arko, Bundler Project Lead
    Samuel Giddins, RubyConf BR 2017 44

    View Slide

  45. Why Bundler 2?
    Bundler 1 is Old
    Samuel Giddins, RubyConf BR 2017 45

    View Slide

  46. Why Bundler 2?
    The Ruby Community Has Grown Up
    Samuel Giddins, RubyConf BR 2017 46

    View Slide

  47. Why Bundler 2?
    We've Gotten 7 Years of Experience
    Samuel Giddins, RubyConf BR 2017 47

    View Slide

  48. Why Bundler 2?
    We Want Bundler To Last
    Samuel Giddins, RubyConf BR 2017 48

    View Slide

  49. Why Bundler 2?
    Our Users Deserve the Best Bundler We Can Build Them
    Samuel Giddins, RubyConf BR 2017 49

    View Slide

  50. When Bundler 2?
    Soon
    Samuel Giddins, RubyConf BR 2017 50

    View Slide

  51. gem install bundler --version ">= 2.0.0.pre.1"
    Samuel Giddins, RubyConf BR 2017 51

    View Slide

  52. @segiddins
    Samuel Giddins, RubyConf BR 2017 52

    View Slide