Skip to content

Instantly share code, notes, and snippets.

@finack
Created March 17, 2012 06:18

Revisions

  1. finack revised this gist Jul 11, 2012. 3 changed files with 42 additions and 5 deletions.
    10 changes: 5 additions & 5 deletions application.rb
    Original file line number Diff line number Diff line change
    @@ -15,13 +15,13 @@
    end
    end

    keys = Chef::EncryptedDataBagItem.load(app[:secrets], app[:name])
    keys = Chef::EncryptedDataBagItem.load('rails', app[:name])

    create_database_config app[:name] do
    app_root node[:rails][:servicing][:app_root]
    deploy_user node[:rails][:servicing][:deploy_user]
    databases node[:rails][:servicing][:db][:databases]
    aliases node[:rails][:servicing][:db][:aliases]
    app_root node[:rails][:app][:app_root]
    deploy_user node[:rails][:app][:deploy_user]
    databases node[:rails][:app][:db][:databases]
    aliases node[:rails][:app][:db][:aliases]
    passwords keys["database_passwords"]
    end

    29 changes: 29 additions & 0 deletions application_environment.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    #Used to configure variables for the app per environment (instead of attributes).
    #I have since refactored how this works so treat this as example code, aka I
    #have not tested this and it is not complete.
    #FWIW using libraries in the cookbook to set these variables
    #for smaller apps I would keep this in the attributes

    app_name = 'yourname'
    default = {
    name: app_name
    gemset: app_name
    ruby_ver: 'ruby-1.8.7-p352',
    deploy_user: 'deployer',
    environment: node[:environment],
    #...
    }

    staging = {
    app_root: '/export/staging/yourname',
    #...
    }

    case node[:environment]
    when "staging"
    rails_attributes = Chef::Mixin::DeepMerge.merge(default, staging)
    end

    # Don't know why I saved this in a seperate hash before the deep merge...
    original_node_attributes = node.default.to_hash
    node.default[:rails] = Chef::Mixin::DeepMerge.merge(rails_attributes, original_node_attributes["rails"])
    8 changes: 8 additions & 0 deletions databags/rails/yourname.json
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,8 @@
    {
    # Handwritten from memory, probably broken
    "id": "yourname",
    "database_passwords": {
    "staging": "foo"
    }
    }

  2. Peter Baker created this gist Mar 17, 2012.
    106 changes: 106 additions & 0 deletions application.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,106 @@
    app = node[:rails][:app]

    rails_base app[:name] do
    ruby_ver app[:ruby_ver]
    gemset app[:gemset]
    end

    %w{config log pids cached-copy bundle system}.each do |dir|
    directory "#{app[:app_root]}/shared/#{dir}" do
    owner app[:deploy_user]
    group app[:deploy_user]
    mode '0755'
    recursive true
    action :create
    end
    end

    keys = Chef::EncryptedDataBagItem.load(app[:secrets], app[:name])

    create_database_config app[:name] do
    app_root node[:rails][:servicing][:app_root]
    deploy_user node[:rails][:servicing][:deploy_user]
    databases node[:rails][:servicing][:db][:databases]
    aliases node[:rails][:servicing][:db][:aliases]
    passwords keys["database_passwords"]
    end

    deploy_revision "#{app[:app_root]}" do
    repo app[:repo]
    revision cluster_settings["revision"]
    user app[:deploy_user]
    group app[:deploy_user]
    enable_submodules true
    environment({
    "RAILS_ENV" => app[:environment],
    })
    shallow_clone false

    if node["rails"][app[:name]].attribute?('one_time_action')
    # rollback, deploy, force_deploy
    action node["rails"][app[:name]]["one_time_action"]
    node["rails"][app[:name]].delete('one_time_action')
    else
    action :deploy
    end

    migrate true
    migration_command "/usr/local/rvm/bin/appname_bundle exec rake db:migrate --trace"

    before_migrate do

    template "#{release_path}/config/environments/#{app[:environment]}.rb" do
    source "#{release_path}/config/environments/chef_development.rb.erb"
    local true
    owner app[:deploy_user]
    group app[:deploy_user]
    mode '0400'
    variables(:environment_settings => app[:environment_settings].to_hash)
    end

    rvm_shell "Bundle install and assets precompile" do
    ruby_string "#{app[:ruby_ver]}@#{app[:gemset]}"
    cwd release_path
    user app[:deploy_user]
    group app[:deploy_user]

    # common_groups = %w{development test cucumber}
    # bundle install --deployment --path #{app[:app_root]}/shared/bundle --without #{common_groups.join(' ')}

    code %{
    bundle install --path #{app[:app_root]}/shared/bundle
    }
    end
    end

    before_restart do
    rvm_shell "assets precompile" do
    ruby_string "#{app[:ruby_ver]}@#{app[:gemset]}"
    cwd release_path
    user app[:deploy_user]
    group app[:deploy_user]

    # TODO I could not set the environment via the builtin command. Does not look like it is getting passed to popen4
    # So instead of `environment "RAILS_ENV" => app[:environment]` I have it in the code block
    code %{
    export RAILS_ENV=#{app[:environment]}
    bundle exec rake assets:precompile
    }
    end
    end

    symlink_before_migrate({
    "config/database.yml" => "config/database.yml",
    "config/environments/#{app[:environment]}.rb" => "config/environments/#{app[:environment]}.rb"
    })

    after_restart do
    notify_airbrake release_path do
    environment app[:environment]
    repository app[:repo]
    end
    notify_newrelic release_path do
    environment app[:environment]
    end
    end
    end
    28 changes: 28 additions & 0 deletions create_database_config.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    define :create_database_config, :passwords=>{} do

    databases = Hash.new

    params[:databases].each do |db_name|
    if node[:rails][params[:name]][:db].has_key?(db_name)
    values = node[:rails][params[:name]][:db][db_name].to_hash
    if params[:passwords].has_key?(db_name.to_s)
    values["password"] = params[:passwords].fetch(db_name.to_s)
    end
    name = values.has_key?(name) ? values[:name] : db_name
    databases.merge!({ name.to_s => values })
    end
    end

    if params.has_key? :aliases
    params[:aliases].each do |target,source|
    databases[target.to_s] = databases[source.to_s]
    end
    end

    file "#{params[:app_root]}/shared/config/database.yml" do
    owner params[:deploy_user]
    group params[:deploy_user]
    mode '400'
    content databases.to_yaml
    end
    end
    29 changes: 29 additions & 0 deletions notify_airbrake.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,29 @@
    define :notify_airbrake, :name=>nil, :environment=>nil, :repository=>nil do

    script "notifying airbrake of deploy" do
    interpreter "ruby"
    user "deployer"
    cwd params[:name]
    code <<-EOS
    require 'rubygems'
    unless File.exist?("#{params[:name]}/config/initializers/airbrake.rb")
    puts "!!! airbrake.rb not found. Not notifying Airbrake of the deploy !!!"
    exit 0
    end
    # Setup the airbrake api_key
    require 'airbrake'
    require 'airbrake_tasks'
    require "#{params[:name]}/config/initializers/airbrake.rb"
    revision = `cd #{params[:name]} && git rev-parse HEAD`.chomp
    print "Airbrake : "
    AirbrakeTasks.deploy(:rails_env => '#{params[:environment]}',
    :scm_revision => revision,
    :scm_repository => '#{params[:repository]}',
    :local_username => 'chef')
    EOS
    end
    end
    31 changes: 31 additions & 0 deletions notify_newrelic.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,31 @@
    define :notify_newrelic, :deploy_path=>nil, :environment=>nil do

    script "notifying new relic of deploy" do
    interpreter "ruby"
    user "deployer"
    cwd params[:name]
    code <<-EOS
    require 'rubygems'
    unless File.exist?("#{params[:name]}/config/newrelic.yml")
    puts "!!! newrelic.yml not found. Not notifying New Relic of the deploy !!!"
    exit 0
    end
    ## When new relic is loaded it automagically loads up its configuration file
    ## And sets the config[:environment]. We are injecting the path to the configuration
    ## file and the environment via ENV variables.
    ENV['APP_ROOT'] = "#{params[:name]}"
    ENV['RAILS_ENV'] = "#{params[:environment]}"
    require 'newrelic_rpm'
    require 'new_relic/command'
    config = NewRelic::Control.instance
    revision = `git rev-parse HEAD`.chomp
    deployment = NewRelic::Command::Deployments.new({:revision => revision, :user => 'chef'})
    print "New Relic : "
    deployment.run
    EOS
    end

    end
    33 changes: 33 additions & 0 deletions rails_base.rb
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,33 @@

    define :rails_base, :ruby_ver=>nil, :gemset=>nil do
    include_recipe "nodejs"
    package "mysql-client"
    package "libmysqlclient-dev"
    gem_package "newrelic_rpm"
    gem_package "airbrake"

    directory '/export' do
    owner 'root'
    group 'root'
    recursive true
    action :create
    only_if "test -e /export"
    end

    create_deploy_user

    rvm_gemset params[:gemset] do
    ruby_string params[:ruby_ver]
    action :create
    end

    rvm_gem 'bundler' do
    ruby_string "#{params[:ruby_ver]}@#{params[:gemset]}"
    end

    # Creates /usr/local/rvm/bin/appname_bundle
    rvm_wrapper params[:name] do
    ruby_string "#{params[:ruby_ver]}@#{params[:gemset]}"
    binary 'bundle'
    end
    end