Developing at Scale

Developing at Scale

Talk given at ConFoo 2016 on February 26th, 2016.

85b03650a2ec5235376b0b983a49511a?s=128

Christian Joudrey

February 26, 2016
Tweet

Transcript

  1. 3.
  2. 4.
  3. 5.
  4. 6.
  5. 7.
  6. 8.
  7. 12.

    pre 2012 — README.md with lots of Bash snippets circa

    2013 — Vagrant with shared Chef cookbooks circa 2012 — GitHub's Boxen (Puppet recipes on local) future — ? Dev environments
  8. 13.

    ~ $ git clone git@github.com:Shopify/vagrant.git
 ~ $ cd vagrant &&

    vagrant up
 ~/vagrant $ vagrant ssh (vagrant) ~ $ git clone git@github.com:Shopify/shopify.git
 (vagrant) ~ $ cd shopify && script/setup (vagrant) ~/shopify $ script/server
  9. 14.

    ~ $ git clone git@github.com:Shopify/vagrant.git
 ~ $ cd vagrant &&

    vagrant up
 ~/vagrant $ vagrant ssh (vagrant) ~ $ git clone git@github.com:Shopify/shopify.git
 (vagrant) ~ $ cd shopify && script/setup (vagrant) ~/shopify $ script/server ✓ quick & easy setup
 ✓ reproducible
 ✓ production-like
  10. 18.

    https://shop1.myshopify.com https://shop1.myshopify.io ~ $ whois myshopify.io Domain : myshopify.io Status

    : Live Expiry : 2016-12-16 ~ $ openssl s_client -connect myshopify.io:443 CONNECTED(00000003) depth=1 /C=US/O=DigiCert Inc/...
  11. 19.
  12. 20.

    Feature flags class Shop < ActiveRecord::Base include HasFeatureFlags end shop.flags.enabled?('free_ssl')

    # false shop.flags.enable('free_ssl')
 shop.flags.enabled?('free_ssl') # true FeatureRollout.enable('test_feature', 50) shop.features.enabled?('test_feature') # true shop2.features.enabled?('test_feature') # false
  13. 21.

    A/B Tests Verdict::Experiment.define :my_experiment do # Block returns true if

    the subject # is qualified to participate. qualify { |subject, context| ... } groups do group :blue_button, 50 group :control, 50 end storage Verdict::Storage::MemoryStorage.new end github.com/shopify/verdict
  14. 22.

    A/B Tests case Verdict[:my_experiment].switch(checkout) when :blue_button # ... when :control

    # ... else # unqualified subjects end github.com/shopify/verdict
  15. 24.

    Secrets circa 2014 — Secrets stored in encrypted data bags

    in Chef. Devs pinged Ops to get secrets added/changed. Hard to trace changes to secrets. Hard to make changes.
  16. 25.

    Secrets circa 2014 — Secrets stored in encrypted data bags

    in Chef. Devs pinged Ops to get secrets added/changed. Hard to trace changes to secrets. tl;dr — It was pretty painful!
  17. 26.

    Secrets — EJSON github.com/shopify/ejson now — Secrets can be safely

    stored in app source. Anyone has access to change/add secrets. Only production servers can decrypt secrets. Secrets change synchronously with app source.
  18. 27.

    Secrets — EJSON github.com/shopify/ejson now — Secrets can be safely

    stored in app source. Anyone has access to change/add secrets. Only production servers can decrypt secrets. Secrets change synchronously with app source. tl;dr — A lot better!
  19. 28.

    Secrets — EJSON github.com/shopify/ejson $ ejson keygen Public Key: 6623423a9492e68e12eeb1c705888aebdcc0080af7e594fc402b

    eb24cce9d14f Private Key: 75b80b4a693156eb435f4ed2fe397e583f461f09fd99ec2bd1bd ef0a56cf6e64
  20. 30.

    Secrets — EJSON github.com/shopify/ejson $ ejson encrypt secrets.production.ejson $ cat

    secrets.production.ejson { "_public_key": "6623423...", "database_password": "EJ[1:WGj...]" }
  21. 31.

    Secrets — EJSON github.com/shopify/ejson $ cat secrets.production.ejson { "_public_key": "6623423...",

    "database_password": "EJ[1:WGj...]", "some_new_password": "something secret" } $ ejson encrypt secrets.production.ejson
  22. 32.
  23. 34.
  24. 35.
  25. 36.
  26. 38.
  27. 40.

    Style Guides Can every language just have a "go fmt"

    so we can stop arguing and get shit done. Please, I'm begging you.
  28. 42.

    RuboCop github.com/bbatsov/rubocop $ rubocop test.rb Inspecting 1 file W Offenses:

    test.rb:1:5: C: Use snake_case for method names. def badName ^^^^^^^ 1 file inspected, 1 offense detected
  29. 45.

    RuboCop github.com/bbatsov/rubocop $ rubocop --auto-correct test.rb Inspecting 1 file C

    Offenses: 
 test.rb:2:1: C: [Corrected] Use 2 (not 0) spaces for indentation. def badName
 test.rb:2:7: C: Use snake_case for method names. def badName ^^^^^^^ 1 file inspected, 2 offenses detected, 1 offense corrected
  30. 46.
  31. 47.
  32. 48.
  33. 49.
  34. 50.
  35. 51.

    Policial octokit = Octokit::Client.new(access_token: 'secret') detective = Policial::Detective.new(octokit) event =

    Policial::PullRequestEvent.new(webhook_payload) detective.brief(event) detective.investigate detective.violations github.com/volmer/policial
  36. 54.

    pre 2013 — Ping #operations for a deploy (Capistrano) circa

    2014 — Shipit circa 2013 — Rackspace's dreadnot Shipping code at Shopify
  37. 56.
  38. 57.
  39. 58.
  40. 59.
  41. 64.
  42. 65.
  43. 67.
  44. 69.
  45. 70.
  46. 72.
  47. 73.
  48. 76.
  49. 77.
  50. 78.