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

Developing at Scale

Developing at Scale

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

Christian Joudrey

February 26, 2016
Tweet

More Decks by Christian Joudrey

Other Decks in Programming

Transcript

  1. 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
  2. ~ $ git clone [email protected]:Shopify/vagrant.git
 ~ $ cd vagrant &&

    vagrant up
 ~/vagrant $ vagrant ssh (vagrant) ~ $ git clone [email protected]:Shopify/shopify.git
 (vagrant) ~ $ cd shopify && script/setup (vagrant) ~/shopify $ script/server
  3. ~ $ git clone [email protected]:Shopify/vagrant.git
 ~ $ cd vagrant &&

    vagrant up
 ~/vagrant $ vagrant ssh (vagrant) ~ $ git clone [email protected]:Shopify/shopify.git
 (vagrant) ~ $ cd shopify && script/setup (vagrant) ~/shopify $ script/server ✓ quick & easy setup
 ✓ reproducible
 ✓ production-like
  4. 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/...
  5. 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
  6. 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
  7. A/B Tests case Verdict[:my_experiment].switch(checkout) when :blue_button # ... when :control

    # ... else # unqualified subjects end github.com/shopify/verdict
  8. 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.
  9. 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!
  10. 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.
  11. 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!
  12. Secrets — EJSON github.com/shopify/ejson $ ejson keygen Public Key: 6623423a9492e68e12eeb1c705888aebdcc0080af7e594fc402b

    eb24cce9d14f Private Key: 75b80b4a693156eb435f4ed2fe397e583f461f09fd99ec2bd1bd ef0a56cf6e64
  13. Secrets — EJSON github.com/shopify/ejson $ ejson encrypt secrets.production.ejson $ cat

    secrets.production.ejson { "_public_key": "6623423...", "database_password": "EJ[1:WGj...]" }
  14. 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
  15. Style Guides Can every language just have a "go fmt"

    so we can stop arguing and get shit done. Please, I'm begging you.
  16. 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
  17. 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
  18. 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
  19. pre 2013 — Ping #operations for a deploy (Capistrano) circa

    2014 — Shipit circa 2013 — Rackspace's dreadnot Shipping code at Shopify