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

Continuous Delivery with Rails, Hudson and Heroku

Continuous Delivery with Rails, Hudson and Heroku

Talk about our experiences implementing Continuous Delivery for zendone.com.

This talk was part of the Madrid.rb session of February 2013

Jorge Manrubia

January 31, 2013
Tweet

Other Decks in Programming

Transcript

  1. Cycle time means how long did it take for feature

    X to move from “Next Ten Features” to “Ready for Acceptance Test” Henrik Kniberg. Lean from the Trenches (2011)
  2. commit bundle install add heroku git repos precompile assets (detect

    error) Recreate testing databases client unit tests (Jasmine) server unit tests (RSpec) changes detected automatic
  3. Release to staging generate version git push to heroku (staging)

    run migrations tag source in github acceptance success automatic
  4. Release to production git push to heroku (production) run migrations

    backup database manual testing success manual
  5. Start Server Unit tests (Rspec) Client Unit tests (Jasmine) Functional

    core Functional Evernote Functional Calendar Release to staging Release to production Automatic Commit stage Automatic acceptance testing Manual testing Release Manual
  6. Release to production Release Start Server Unit tests (Rspec) Client

    Unit tests (Jasmine) Commit stage Functional core Functional Evernote Functional Calendar Automatic acceptance testing Release to staging Manual testing
  7. rake admin:db:add_delete_account_token # Update delete account token rake admin:db:maintenance:delete_old_rows #

    Peforms a clean of unused data rake admin:db:obfuscate_database # Obfuscate database rake admin:db:truncate_comments # Truncate long comments in ever rake admin:heroku:deploy:to_development # Deploy to development environm rake admin:heroku:deploy:to_production # Deploy to production environme rake admin:heroku:deploy:to_staging # Deploy to staging environment rake admin:heroku:prepare:development # Prepares development environme rake admin:heroku:prepare:local # Prepares local git repositorie rake admin:heroku:prepare:production # Prepares production environmen rake admin:heroku:prepare:staging # Prepares staging environment rake admin:heroku:prepare:zendone_android # Prepares android environment rake admin:heroku:prepare:zendone_iphone # Prepares iphone environment rake admin:heroku:restart:production # Restart heroku in production rake admin:heroku:restart:staging # Restart heroku in staging rake admin:maintenance_mode:disable # Disable maintenance mode rake admin:maintenance_mode:enable # Enables maintenance mode rake admin:maintenance_mode:enabled? # Returns maintainance mode rake admin:s3:clean_all # Clean all the S3 objects for a rake admin:s3:clean_users_with_recent_activity # Clean all the S3 objects for a rake admin:users:reload_evernote_notes_for[email] # Reload the evernote notes for rake admin:users:reload_evernote_notes_for_all # Reload the evernote notes for ...
  8. DEFAULT_ADDONS = ["scheduler:standard", "newrelic:standard", "memcache:5mb", "heroku- postgresql:dev", "pgbackups:auto-month", "sendgrid:starter", "memcachier:dev"]

    DEFAULT_VARIABLES = { :EVERNOTE_CONSUMER_SECRET => '?', :S3_ACCESS_KEY_ID => '?', :S3_SECRET_ACCESS_KEY => '?', :FAST_SPRING_PASSWORD => '?', :FAST_SPRING_USER => '?', :HEROKU_API_KEY => '?', :ZENDONE_PROTOCOL => 'https', :BUNDLE_WITHOUT => "development:test:skipheroku", :MAINTENANCE_PAGE_URL => "https://s3.amazonaws.com/zendone-static/503.html" } .... desc "Prepares production environment" task :production => :environment do install_addons :production, ['ssl'] ask_for_database_to_promote :production define_config_variables :production, { :ZENDONE_URL => 'https://www.zendone.com', :ZENDONE_ENVIRONMENT => 'PRODUCTION', } end
  9. class CedarMigration def run run_steps [ :put_production_bamboo_in_maintenance_mode, :copy_database_from_bamboo_to_cedar, :migrate_new_database, :short_long_comments,

    :remove_domain_from_bamboo, :put_cedar_in_maintenance_mode, :add_domain_to_cedar] manual_checks [ "Configure SSL and DNS as described here: https:// devcenter.heroku.com/articles/ssl-endpoint", "Activate hirefireapp for production", "Activate cron", "Check that backups are working"] end ...
  10. Practice/principle Heroku Automate almost everything heroku command (toolbet), api Identical

    environments for testing and production zero downtime releases hot deployments*, preboot (beta) backing out changes built-in releases, PG Backups add on
  11. VCR VCR.configure do |c| c.default_cassette_options = { :re_record_interval => 7.days,

    :preserve_exact_body_bytes => true, :record => :new_episodes, :match_requests_on => [:method, :uri, :host, :path, :body, :headers] } c.cassette_library_dir = 'fixtures/vcr_cassettes' c.hook_into :webmock # or :fakeweb end https://github.com/vcr/vcr
  12. evernote_example "should use a counter if the name collides with

    an existing notebook" do @evernote_bot.rename_default_notebook 'other default notebook' base_name = Conf.evernote.inbox_name create_edam_notebooks_with_names base_name, "#{base_name}_1", "#{base_name}_2" @evernote_change_checker.check_changes @user check_notebooks_are "#{base_name}_3", ['other default notebook', "#{base_name}", "#{base_name}_1", "#{base_name}_2"] end
  13. “I get paid for code that works, not for tests,

    so my philosophy is to test as little as possible to reach a given level of confidence (I suspect this level of confidence is high compared to industry standards, but that could just be hubris). If I don't typically make a kind of mistake (like setting the wrong variables in a constructor), I don't test for it. I do tend to make sense of test errors, so I'm extra careful when I have logic with complicated conditionals.” http://stackoverflow.com/questions/153234/how-deep-are-your-unit-tests