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

SpreeConf DC 2013 - Open Source War Stories

SpreeConf DC 2013 - Open Source War Stories

Managing an open source project as large as Spree comes with its own interesting challenges. I go through some of these within this talk.

These are the slides of a talk that I gave at Ruby on Ales 2013, Los Angeles Ruby Users Group in March, and SpreeConf DC in May.

Ryan Bigg

May 20, 2013
Tweet

More Decks by Ryan Bigg

Other Decks in Programming

Transcript

  1. Open Source
    War Stories
    Saturday, 25 May 13

    View Slide

  2. Making People Happy
    Through Open Source
    Saturday, 25 May 13

    View Slide

  3. Saturday, 25 May 13

    View Slide

  4. Saturday, 25 May 13

    View Slide

  5. “WOW! GREAT! Thx!! You’re awesome!”
    @radar awesome, thank you so much!
    Saturday, 25 May 13

    View Slide

  6. 0
    175
    350
    525
    700
    01/01/2010 01/05/2010 01/09/2010 01/01/2011 01/05/2011 01/09/2011 01/01/2012 01/05/2012 01/09/2012 01/01/2013
    Posts to Spree User
    Saturday, 25 May 13

    View Slide

  7. 0
    175
    350
    525
    700
    01/01/2010 01/05/2010 01/09/2010 01/01/2011 01/05/2011 01/09/2011 01/01/2012 01/05/2012 01/09/2012 01/01/2013
    Posts to Spree User
    Saturday, 25 May 13

    View Slide

  8. 0
    175
    350
    525
    700
    01/01/2010 01/05/2010 01/09/2010 01/01/2011 01/05/2011 01/09/2011 01/01/2012 01/05/2012 01/09/2012 01/01/2013
    Posts to Spree User
    Saturday, 25 May 13

    View Slide

  9. 0
    225
    450
    675
    900
    01/01/2010 01/05/2010 01/09/2010 01/01/2011 01/05/2011 01/09/2011 01/01/2012 01/05/2012 01/09/2012 01/01/2013
    Posts to Spree User
    855!
    Saturday, 25 May 13

    View Slide

  10. 855!
    Saturday, 25 May 13

    View Slide

  11. 0
    225
    450
    675
    900
    01/01/2010 01/05/2010 01/09/2010 01/01/2011 01/05/2011 01/09/2011 01/01/2012 01/05/2012 01/09/2012 01/01/2013
    Posts to Spree User
    Saturday, 25 May 13

    View Slide

  12. 690
    Before Ryan:
    September 15th 2010 - November 5th 2011
    Saturday, 25 May 13

    View Slide

  13. 2333
    After Ryan:
    November 5th 2011 - Last Thursday
    Saturday, 25 May 13

    View Slide

  14. 2372
    After Ryan:
    November 5th 2011 - Today
    Saturday, 25 May 13

    View Slide

  15. 0
    50
    100
    150
    200
    01/07/2010 01/01/2011 01/07/2011 01/01/2012 01/07/2012 01/01/2013
    Spree Issues by month
    Saturday, 25 May 13

    View Slide

  16. 0
    200
    400
    600
    800
    01/11/2010 01/06/2011 01/01/2012 01/08/2012 01/03/2013
    Spree issue comments
    Saturday, 25 May 13

    View Slide

  17. 99.9%
    of issues are awesome
    Saturday, 25 May 13

    View Slide

  18. #1247
    Saturday, 25 May 13

    View Slide

  19. “I'm having the same error and restarting
    heroku or resetting the database have not
    fixed the problem.”
    boxfirepress
    Saturday, 25 May 13

    View Slide

  20. #1247
    “@boxfirepress Going to need more
    information.
    Please see the contributing guide.”
    Saturday, 25 May 13

    View Slide

  21. #1247
    “When filing an issue on the Spree project, please
    provide these details:
    • A comprehensive list of steps to reproduce the issue.
    • The version of Spree and the version of Rails.
    • A list of all extensions.
    • Any relevant stack traces (‘Full trace’ preferred)
    Filing an issue

    Saturday, 25 May 13

    View Slide

  22. “What part of same problem
    was difficult to understand?”
    #1247
    boxfirepress
    Saturday, 25 May 13

    View Slide

  23. #1247
    “Please don't expect help if you're
    going to be passive aggressive with
    us.”
    Saturday, 25 May 13

    View Slide

  24. “ I'm being openly agressive and I was only reflecting your
    rudeness. Had there been a material difference in the setup, I
    would've made it a point to tell you since I posted more information
    in the stack trace than the last person did (yet he still managed to
    get a reply that wasn't: you didn't follow the arbitrary rules in some
    guide so no help for you.)”
    #1247
    boxfirepress
    Saturday, 25 May 13

    View Slide

  25. #1247
    “I just quickly generated an app using PostgreSQL as the
    DB with Spree 1.3.2, no products loaded in the products
    table and going to /admin/products works fine.”
    Saturday, 25 May 13

    View Slide

  26. #1247
    However, on Heroku I have now been able to reproduce
    this issue.
    Saturday, 25 May 13

    View Slide

  27. #1247 was then fixed 8
    minutes later.
    Saturday, 25 May 13

    View Slide

  28. @ryanbigg not sure? Is there something
    wrong with it? It's managed by directly by a
    contractor…
    @boxfirepress
    Saturday, 25 May 13

    View Slide

  29. @ryanbigg interesting… really sorry about
    that. We don't actually do our own
    development, a variety of contractors do.
    @boxfirepress
    Saturday, 25 May 13

    View Slide

  30. @ryanbigg thanks for letting us know.
    We've been using a couple guys through
    oDesk for the last year, which has been a
    mixed bag.
    @boxfirepress
    Saturday, 25 May 13

    View Slide

  31. Tyler Menezes
    Saturday, 25 May 13

    View Slide

  32. Tyler Menezes
    “... From presentations full of porn and
    jokes at the expense of women, DongML,
    to refusing to acknowledge [the] design
    flaw [of] semi-colons in URLs [and] mass-
    assignment protection ... ”
    Saturday, 25 May 13

    View Slide

  33. “Mr. Homakov is not representative of
    the Rails community at all.
    He is, to me, an outsider who spends his
    time trying to show that he’s an “uber
    l33t hacker” by breaking GitHub or any
    other Rails site. ”
    Saturday, 25 May 13

    View Slide

  34. By default there is no api key generated. I just
    managed to break into api on test installation
    using ?token[], one of my favourite CVEs.
    @radar, please take a look at Mr. Outsider's
    PR
    #2492
    homakov
    Saturday, 25 May 13

    View Slide

  35. “Mr. Homakov is not representative of
    the Rails community at all.
    He is, to me, an outsider who spends his
    time trying to show that he’s an “uber
    l33t hacker” by breaking GitHub or any
    other Rails site. ”
    Saturday, 25 May 13

    View Slide

  36. commit 3c2015e5b8df36b08188978f78443e3c385548bb
    Author: Egor Homakov
    Date: Sat Jan 26 14:17:39 2013 +0700
    Stringify api_key
    By default there is no api key generated...
    @radar, please take a look at Mr. Outsider's PR
    Fixes #2492
    Saturday, 25 May 13

    View Slide

  37. ’08 ’09 ’10 ’11 ’12 ’13
    Saturday, 25 May 13

    View Slide

  38. ’08 ’09 ’10 ’11 ’12 ’13
    4,382 commits
    Saturday, 25 May 13

    View Slide

  39. ’08 ’09 ’10 ’11 ’12 ’13
    4,382 commits 5,017 commits
    Saturday, 25 May 13

    View Slide

  40. 200
    150
    100
    50
    https://github.com/spree/spree/graphs/contributors
    Saturday, 25 May 13

    View Slide

  41. 200
    150
    100
    50
    API redesign
    Saturday, 25 May 13

    View Slide

  42. def  index
       respond_with(@collection)  do  |format|
           format.json  do
             render  :json  =>  @collection.to_json(collection_serialization_options)
           end
       end
    end
    app/controllers/spree/api/base_controller.rb
    The Old API
    Saturday, 25 May 13

    View Slide

  43. def  create
       if  @object.save
           render  :text  =>  "Resource  created\n",
                         :status  =>  201,
                         :location  =>  object_url
       else
           respond_with(@object.errors,  :status  =>  422)
       end
    end
    app/controllers/spree/api/base_controller.rb
    The Old API
    Saturday, 25 May 13

    View Slide

  44. def  create
       if  @object.save
           render  :text  =>  "Resource  created\n",
                         :status  =>  201,
                         :location  =>  object_url
       else
           respond_with(@object.errors,  :status  =>  422)
       end
    end
    app/controllers/spree/api/base_controller.rb
    The Old API
    Saturday, 25 May 13

    View Slide

  45. Saturday, 25 May 13

    View Slide

  46. Saturday, 25 May 13

    View Slide

  47. def  index
       if  params[:ids]
           @products  =  product_scope.where(:id  =>  params[:ids])
       else
           @products  =  product_scope.ransack(params[:q]).result
       end
     
       @products  =  @products.page(params[:page]).per(params[:per_page])
     
       respond_with(@products)
    end
    app/controllers/spree/api/products_controller.rb
    The New API
    Saturday, 25 May 13

    View Slide

  48. object  false
    node(:count)  {  @products.count  }
    node(:total_count)  {  @products.total_count  }
    node(:current_page)  {  params[:page]  ?  params[:page].to_i  :  1  }
    node(:pages)  {  @products.num_pages  }
    child(@products)  do
       extends  "spree/api/products/show"
    end
    app/views/spree/api/products/index.v1.rabl
    The New API
    https://github.com/nesquena/rabl
    Saturday, 25 May 13

    View Slide

  49. object  @product
    attributes  *product_attributes
    child  :variants_including_master  =>  :variants  do
       attributes  *variant_attributes
    ...
    app/views/spree/api/products/show.v1.rabl
    The New API
    Saturday, 25 May 13

    View Slide

  50. def  product_attributes
       [:id,  :name,  :description,  :price,  :available_on,  :permalink,
         :count_on_hand,  :meta_description,  :meta_keywords,  :taxon_ids]
    end
    app/helpers/spree/api_helpers.rb
    The New API
    Saturday, 25 May 13

    View Slide

  51. app/views/spree/api/products/show.v1.rabl
    The New API
    Saturday, 25 May 13

    View Slide

  52. http://api.spreecommerce.com
    https://github.com/spree/api.spreecommerce.com
    Saturday, 25 May 13

    View Slide

  53. Saturday, 25 May 13

    View Slide

  54. 200
    150
    100
    50
    Auth Refactoring
    #1512
    Saturday, 25 May 13

    View Slide

  55. Spree.user_class = “User”
    rails g spree:custom_user User
    Saturday, 25 May 13

    View Slide

  56. module  Spree
       module  AuthenticationHelpers
           def  self.included(receiver)
               receiver.send  :helper_method,  :spree_login_path
               receiver.send  :helper_method,  :spree_signup_path
               receiver.send  :helper_method,  :spree_logout_path
               receiver.send  :helper_method,  :spree_current_user
           end
     
           def  spree_current_user
               current_person
           end
     
           def  spree_login_path
               main_app.login_path
           end
     
           def  spree_signup_path
               main_app.signup_path
           end
     
           def  spree_logout_path
               main_app.logout_path
           end
       end
    end
     
    Spree::BaseController.send  :include,  Spree::AuthenticationHelpers
    ApplicationController.send  :include,  Spree::AuthenticationHelpers
    Saturday, 25 May 13

    View Slide

  57. Deface::Override.new({
       :name  =>  "auth_shared_login_bar",
       :virtual_path  =>  "spree/shared/_nav_bar",  
       :insert_before  =>  "li#search-­‐bar",
       :partial  =>  "spree/shared/login_bar"
    })
    app/overrides/auth_login_bar.rb
    Saturday, 25 May 13

    View Slide

  58. <%  if  spree_current_user  %>
       <%=  link_to  t(:logout),  spree_logout_path,  :method  =>  :delete  %>
    <%  else  %>
       <%=  link_to  t(:login),  spree_login_path  %>
       <%=  link_to  t(:signup),  spree_signup_path  %>
    <%  end  %>
    app/views/spree/shared/_login_bar.html.erb
    Saturday, 25 May 13

    View Slide

  59. 200
    150
    100
    50
    Spree::Money
    #1822
    Saturday, 25 May 13

    View Slide

  60. Saturday, 25 May 13

    View Slide

  61. product.price = 100
    Saturday, 25 May 13

    View Slide

  62. product.price = 100
    I18n.locale = :en
    Saturday, 25 May 13

    View Slide

  63. product.price = 100
    I18n.locale = :en
    number_to_currency(product.price)
    Saturday, 25 May 13

    View Slide

  64. product.price = 100
    I18n.locale = :en
    number_to_currency(product.price)
    $100
    Saturday, 25 May 13

    View Slide

  65. product.price = 100
    I18n.locale = :en
    number_to_currency(product.price)
    $100
    I18n.locale = :jp
    Saturday, 25 May 13

    View Slide

  66. product.price = 100
    I18n.locale = :en
    number_to_currency(product.price)
    $100
    I18n.locale = :jp
    number_to_currency(product.price)
    Saturday, 25 May 13

    View Slide

  67. product.price = 100
    I18n.locale = :en
    number_to_currency(product.price)
    $100
    I18n.locale = :jp
    number_to_currency(product.price)
    ¥100
    Saturday, 25 May 13

    View Slide

  68. require  'money'
    module  Spree
       class  Money
           def  initialize(amount,  options={})
               @money  =  ::Money.new(amount  *  100,  Spree::Config[:currency])
               @options  =  {}
               @options[:with_currency]  =  true  if  Spree::Config[:display_currency]
               @options.merge!(options)
           end
     
           def  to_s
               @money.format(@options)
           end
       end
    end
    Saturday, 25 May 13

    View Slide

  69. Spree::Config[:currency] = “USD”
    product.price = 100
    I18n.locale = :en
    Spree::Money.new(product.price)
    $100
    I18n.locale = :jp
    Spree::Money.new(product.price)
    $100
    Saturday, 25 May 13

    View Slide

  70. require  'money'
     
    module  Spree
       class  Money
           attr_reader  :money
     
           def  initialize(amount,  options={})
               @money  =  ::Money.parse([amount,  (options[:currency]  ||  Spree::Config[:currency])].join)
               @options  =  {}
               @options[:with_currency]  =  Spree::Config[:display_currency]
               @options[:symbol_position]  =  Spree::Config[:currency_symbol_position].to_sym
               @options[:no_cents]  =  Spree::Config[:hide_cents]
               @options.merge!(options)
               #  Must  be  a  symbol  because  the  Money  gem  doesn't  do  the  conversion
               @options[:symbol_position]  =  @options[:symbol_position].to_sym
           end
     
           def  to_s
               @money.format(@options)
           end
     
           def  to_html
               output  =  @money.format(@options.merge(:html  =>  true))
               #  1)  prevent  blank,  breaking  spaces
               #  2)  prevent  escaping  of  HTML  character  entities
               output.gsub("  ",  " ").html_safe
           end
     
           def  ==(obj)
               @money  ==  obj.money
           end
       end
    end
    Saturday, 25 May 13

    View Slide

  71. 200
    150
    100
    50
    checkout_flow
    #1418, #1733, #1743
    Saturday, 25 May 13

    View Slide

  72. Spree::Order.state_machine[:state]  =  
    StateMachine::Machine.new(Spree::Order,  :initial  =>  "cart")  do
       event  :next  do
           transition  :from  =>  'cart',  :to  =>  'summary'
           transition  :from  =>  'summary',  :to  =>  'complete'
       end
    end
    app/models/spree/order_decorator.rb
    Saturday, 25 May 13

    View Slide

  73. checkout_flow  do
       go_to_state  :summary
       go_to_state  :complete
    end
    app/models/spree/order.rb
    Saturday, 25 May 13

    View Slide

  74. 200
    150
    100
    50
    Admin Redesign
    Saturday, 25 May 13

    View Slide

  75. Saturday, 25 May 13

    View Slide

  76. Saturday, 25 May 13

    View Slide

  77. 200
    150
    100
    50
    Multi-currency
    #2197
    Saturday, 25 May 13

    View Slide

  78. Spree::Config[:currency] = “USD”
    product.price = 100
    Spree::Money.new(product.price)
    $100
    Saturday, 25 May 13

    View Slide

  79. Spree::Config[:currency] = “JPY”
    product.price = 50
    Spree::Money.new(product.price)
    ¥50
    Saturday, 25 May 13

    View Slide

  80. Saturday, 25 May 13

    View Slide

  81. Saturday, 25 May 13

    View Slide

  82. 200
    150
    100
    Split Core
    #2225
    Saturday, 25 May 13

    View Slide

  83. 200
    150
    100
    Split Shipments
    Saturday, 25 May 13

    View Slide

  84. 200
    150
    100
    2.0 Ramp-up
    Saturday, 25 May 13

    View Slide

  85. 2527 Ryan Bigg (29%)
    1816 Sean Schofield (21%)
    501 Brian Quinn (5.7%)
    (spree) git shortlog -sn
    55.7%
    Saturday, 25 May 13

    View Slide

  86. 2527 Ryan Bigg (29%)
    (spree) git shortlog -sn
    55.7%
    1816 Sean Schofield (21%)
    501 Brian Quinn (5.7%)
    ???? ???? ????
    ???? ???? ????
    Saturday, 25 May 13

    View Slide

  87. 2527 Ryan Bigg (29%)
    (spree) git shortlog -sn
    1816 Sean Schofield (21%)
    501 Brian Quinn (5.7%)
    ???? ???? ????
    ???? ???? ????
    Saturday, 25 May 13

    View Slide

  88. 2527 Ryan Bigg (29%)
    (spree) git shortlog -sn
    1816 Sean Schofield (21%)
    501 Brian Quinn (5.7%)
    ???? ???? ????
    ???? ???? ????
    Saturday, 25 May 13

    View Slide

  89. 871 Andre Arko (29%)
    391 José Valim (13%)
    324 Terence Lee (10%)
    (bundler) git shortlog -sn
    52%
    Saturday, 25 May 13

    View Slide

  90. 871 Andre Arko (36.2%)
    324 Terence Lee (13.4%)
    312 Carl Lerche (12.9%)
    180 Carlhuda (7.94%)
    67 wycats (2.7%)
    (bundler) git shortlog --since "Jan 11 2010" -sn
    73.14%
    Saturday, 25 May 13

    View Slide

  91. (jquery) git shortlog -sn
    Saturday, 25 May 13

    View Slide

  92. (jquery) git shortlog -sn
    1714 John Resig (33.3%)
    Saturday, 25 May 13

    View Slide

  93. (jquery) git shortlog -sn
    1714 John Resig (33.3%)
    460 Dave Methvin (9.02%)
    Saturday, 25 May 13

    View Slide

  94. (jquery) git shortlog -sn
    1714 John Resig (33.3%)
    460 Dave Methvin (9.02%)
    ... 14 more people ...
    52 Yehuda Katz (1.02%)
    Saturday, 25 May 13

    View Slide

  95. 3409 DHH (9.47%)
    3356 Jeremy Kemper (9.32%)
    2500 José Valim (6.94%)
    2273 Aaron Patterson (6.31%)
    1637 Xavier Noria (4.55%)
    1099 Joshua Peek (3.05%)
    (rails) git shortlog -sn
    39.64%
    Saturday, 25 May 13

    View Slide

  96. (rails) git shortlog -sn
    63% of commits
    have been done by
    top 20 contributors
    Saturday, 25 May 13

    View Slide

  97. (rails) git shortlog -sn
    37% of commits
    have been done by
    2,155 contributors
    Saturday, 25 May 13

    View Slide

  98. (bundler) git shortlog -sn
    41% of commits
    have been done by
    195 contributors
    Saturday, 25 May 13

    View Slide

  99. (spree) git shortlog -sn
    44% of commits
    have been done by
    350 contributors
    Saturday, 25 May 13

    View Slide

  100. Documentation
    Saturday, 25 May 13

    View Slide

  101. Saturday, 25 May 13

    View Slide

  102. Saturday, 25 May 13

    View Slide

  103. Saturday, 25 May 13

    View Slide

  104. Saturday, 25 May 13

    View Slide

  105. Saturday, 25 May 13

    View Slide

  106. https://github.com/spree/spree-guides
    Saturday, 25 May 13

    View Slide

  107. https://github.com/spree/spree-guides
    Saturday, 25 May 13

    View Slide

  108. Continuous
    Integration
    Saturday, 25 May 13

    View Slide

  109. spree/spree
    Saturday, 25 May 13

    View Slide

  110. spree/spree
    Saturday, 25 May 13

    View Slide

  111. spree/spree
    Saturday, 25 May 13

    View Slide

  112. spree/spree
    1 hour later...
    Saturday, 25 May 13

    View Slide

  113. spree/spree
    1 hour later... Whoops!
    Saturday, 25 May 13

    View Slide

  114. spree/spree
    Saturday, 25 May 13

    View Slide

  115. spree/spree
    1 hour later... Yessss!!!!
    Saturday, 25 May 13

    View Slide

  116. spree/spree
    1 hour later... Yessss!!!!
    Saturday, 25 May 13

    View Slide

  117. spree/spree
    1 hour later... Yessss!!!!
    Saturday, 25 May 13

    View Slide

  118. spree/spree
    1 hour later... Yessss!!!!
    Saturday, 25 May 13

    View Slide

  119. spree/spree
    1 hour later... Yessss!!!!
    Saturday, 25 May 13

    View Slide

  120. Saturday, 25 May 13

    View Slide

  121. radar/spree
    spree/spree
    Saturday, 25 May 13

    View Slide

  122. api (master)˒ bundle exec rspec spec
    1 minute 13.57 seconds
    Saturday, 25 May 13

    View Slide

  123. $ bundle exec rspec spec
    52.06 seconds
    -15.51s
    Saturday, 25 May 13

    View Slide

  124. $ bundle exec rspec spec
    25.75 seconds
    -48.18s
    Saturday, 25 May 13

    View Slide

  125. 12 seconds faster
    Saturday, 25 May 13

    View Slide

  126. 12 seconds faster
    Saturday, 25 May 13

    View Slide

  127. radar/spree
    spree/spree
    minutes...
    Saturday, 25 May 13

    View Slide

  128. radar/spree
    spree/spree
    minutes...
    Saturday, 25 May 13

    View Slide