dcrug: achieving development-production parity

31
Parity Keeping development and production environments in sync for fun, profit, and sanity

Upload: geoff-harcourt

Post on 15-Jan-2015

217 views

Category:

Software


3 download

DESCRIPTION

Thursday, June 12th 2014 Discussing strategies in Rails development for keeping multiple application environments as consistent as possible for the best development, testing, and deployment experience.

TRANSCRIPT

Page 1: DCRUG: Achieving Development-Production Parity

Parity

Keeping development andproduction environments in sync

for fun, profit, and sanity

Page 2: DCRUG: Achieving Development-Production Parity

Hi, I’m Geoff

I’m the CTO at Cortexhttp://cortexintel.com

Developing in Ruby since 2008

Formerly operator ofFive Tool Development

Page 3: DCRUG: Achieving Development-Production Parity

What is parity?

Parity is consistency in the configuration of your application’s environments (production, staging, development, test, etc.)

Page 4: DCRUG: Achieving Development-Production Parity

Why is this important?

• When your tests pass, you should be confident that your code works.

• When you have parity, you'll find many more bugs and configuration idiosyncrasies in development, before you get to a QA or (gasp) production phase.

Page 5: DCRUG: Achieving Development-Production Parity

Achieving parity• Make the time gap small: a developer may write

code and have it deployed hours or even just minutes later.

• Make the personnel gap small: developers who wrote code are closely involved in deploying it and watching its behavior in production.

• Make the tools gap small: keep development and production as similar as possible.

Source: http://12factor.net/dev-prod-parity

Page 6: DCRUG: Achieving Development-Production Parity

Setup for parity• Use the same backing services and support

software in all environments

• At Cortex our bootstrap script (modified from Thoughtbot’s suspenders-created script) installs PostgreSQL, Redis, node.js, and Bower if those packages are not already installed. It then sets up pow, foreman, tunnelss, so we can serve the app at http://cortex.dev and https://cortex.dev

Page 7: DCRUG: Achieving Development-Production Parity

Backing Services• Database (Postgres, MySQL, Mongo, etc)

• Queues (Sidekiq, Resque, DelayedJob)

• Storage (local disk, AWS, CloudDrive, SkyDrive)

• Search (solr, Elasticsearch)

• Caching (Rails In-memory, Memcached)

Page 8: DCRUG: Achieving Development-Production Parity

The adapter fallacy: ActiveRecord

• ActiveRecord promises portability, but most applications will eventually implement behavior that isn’t consistent across different databases in the form of SQL literals or queries that return different results

• Rails encourages the use of SQLite in development, but there’s no reason not to use the database you’re going to use in production

Page 9: DCRUG: Achieving Development-Production Parity

Tools for parity• Foreman - process manager

• Setup script

• pow - app/DNS/proxy with nice “.dev” domain names

• Tunnelss (fork of tunnels) - route SSL to another port locally

• Parity - easy management of Heroku environments

Page 10: DCRUG: Achieving Development-Production Parity

Foreman

• Process manager that works well locally as a stand-in for Heroku

• Runs web and background processes like Sidekiq, DelayedJob, or Resque

• Easy to configure alongside pow

Page 11: DCRUG: Achieving Development-Production Parity

Parity gem and Heroku

• Name your app folder big-red-machine

• Name your Heroku remotes big-red-machine-staging and big-red-machine-production

• Use parity aliases to execute commands easily on Heroku

• migrate, rake, log, tail, log2viz, console, config, open

Page 12: DCRUG: Achieving Development-Production Parity

Moving data with parity

• production backup - takes a snapshot on production

• staging restore production - copies the latest production backup to staging

• development restore production - copies the latest production backup to local dev

Page 13: DCRUG: Achieving Development-Production Parity

Rails environment setup

• Make differences between your environments explicit

• Move universal configuration to application.rb or initializers

• Have environments inherit from a base environment (staging and demo from production), then override the few items that are different

Page 14: DCRUG: Achieving Development-Production Parity

Differences in development

For your own sanity, some items might be smart candidates to break parity in your development environment:

• Eager loading

• Asset compilation

• SSL

Page 15: DCRUG: Achieving Development-Production Parity

Windows?

• If you deploy to a POSIX system (Linux, BSD, etc.), you should be doing development or at least your testing in a similar environment

• Use Vagrant or other virtualization tools to run a facsimile environment locally

Page 16: DCRUG: Achieving Development-Production Parity

Configure with ENV Never store credentials or secrets in source control

Environment can be used for configuration beyond credentials!

• S3 configuration

• CDN setup

• DB connection pool size

Page 17: DCRUG: Achieving Development-Production Parity

Local ENV• Rails 4.1 introduced secrets.yml, a standard

way to store local credentials

• dotenv/dotenv-rails can load credentials from Heroku configs (downloaded with heroku config:pull)

• Figaro performs similar functionality to Rails 4.1’s secrets.yml (YAML format, one file for all environments)

Page 18: DCRUG: Achieving Development-Production Parity

Careful what you mock

You should not need a network connection to run your tests locally

In integration tests, don’t stub or mock gems that interface with external services. Record a real response with the vcr gem, then replay that on later tests (make sure to strip out credentials after recording!)

Page 19: DCRUG: Achieving Development-Production Parity

Fog and Amazon• Use Fog to abstract Amazon S3 so that local

development and test machines don’t need the network

• Allows common interface for local and external storage

• In our CI environment, we make a real connection to S3 to confirm that our local setup is not hiding a real problem

Page 20: DCRUG: Achieving Development-Production Parity

Strategies for parity

• Use the same backing services everywhere!

• Manage packages with a package manager such as Homebrew or apt-get

• Use the same application server in development as production. If you’re using Unicorn in production, don’t use WEBrick in development

Page 21: DCRUG: Achieving Development-Production Parity

OSX protip: brew services

Can’t remember how to turn on PostgreSQL? How to restart Redis? Use brew services

• brew services list

• brew services start postgresql

• brew services restart redis

Page 22: DCRUG: Achieving Development-Production Parity

Strategies for parity

Avoid Rails.env.production? checks. Use tools like custom_configuration

# config/environments/production.rbBCX::Application.configure do config.x.resque.jobs_inline = trueend

# config/initializers/resque.rbif Rails.configuration.x.resque.jobs_inline Resque.inline = trueend

Page 23: DCRUG: Achieving Development-Production Parity

Make it easy on testers

• My app serves locally at http://cortex.dev

• My laptop is on the IP address 10.0.1.37

• My tester can reach my machine athttp://cortex.10.0.1.37.xip.io

• When you’re not on the same subnet, use ngrok or Finch

Page 24: DCRUG: Achieving Development-Production Parity

Strategies for deployment

• Keep your PRs as small as is reasonable

• Only merge to master code you’re ready to ship

• Deploy early and often (or… continuously!)

• Automate your deployment process

• Reduce the number of things you can forget

Page 25: DCRUG: Achieving Development-Production Parity

Make deployment easy

• You should be able to do most deploys withONE (1) command

• Reduce the number of things you can forget through automation

• Don’t trust that you or your teammates will follow a checklist every time

Page 26: DCRUG: Achieving Development-Production Parity

Protect yourself

Automating deployment means:

• You don’t forget to run migrations

• You don’t forget to update reference data

• You don’t forget to recompile or sync assets

• You don’t forget to restart the server

Page 27: DCRUG: Achieving Development-Production Parity

How we deploy

• Alias or script: push-to-staging, push-to-production, push-to-demo

gp staging $(git symbolic-ref --short -q HEAD):master --force && staging migrate

• Always rebuild assets with bower

• Always run migrations

• Always apply production data updates

Page 28: DCRUG: Achieving Development-Production Parity

Heroku Buildpacks

• Tim Pope’s Ruby buildpack tracks with Heroku’s buildpack, but always runs migrations without requiring a second connection and app restart

• We use qnyp/heroku-buildpack-ruby-bower to automatically build our assets from Bower whenever we deploy, which helps avoid issues where we forget to sync assets

Page 29: DCRUG: Achieving Development-Production Parity

Questions?

Page 30: DCRUG: Achieving Development-Production Parity

Further Reading• Heroku's 12 Factor App site:

http://12factor.net/

• parity gem: http://github.com/croaky/parity

• Foreman as process manager, Pow as DNS server:http://robots.thoughtbot.com/foreman-as-process-manager-pow-as-dns-server-and-http

• Beyond the default Rails environments:http://signalvnoise.com/posts/3535-beyond-the-default-rails-environments

Page 31: DCRUG: Achieving Development-Production Parity

Thanks!

I love talking about Ruby and Rails, so feel free to reach out to me with questions!

email: [email protected]

Github: geoffharcourt

Twitter: @geoffharcourt