relevance_rails 0.0.3 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. data/.gitignore +2 -0
  2. data/.rvmrc +1 -0
  3. data/.travis.yml +7 -0
  4. data/CHANGELOG.md +24 -0
  5. data/README.md +101 -4
  6. data/Rakefile +10 -0
  7. data/aws_config.example.yml +15 -0
  8. data/bin/relevance_rails +2 -19
  9. data/lib/generators/deployment/deployment_generator.rb +31 -0
  10. data/lib/generators/fixtures/fixtures_generator.rb +44 -0
  11. data/lib/generators/provision_config/provision_config_generator.rb +56 -0
  12. data/lib/generators/provision_config/templates/authorized_keys.json.erb +6 -0
  13. data/lib/generators/relevance_file/relevance_file_generator.rb +14 -76
  14. data/lib/generators/relevance_file/templates/{Gemfile → Gemfile.erb} +11 -5
  15. data/lib/generators/relevance_file/templates/README.markdown.erb +36 -0
  16. data/lib/generators/relevance_file/templates/application.html.haml.erb +9 -0
  17. data/lib/generators/relevance_file/templates/database.example.yml.mysql.erb +17 -0
  18. data/lib/generators/relevance_file/templates/database.example.yml.postgresql.erb +15 -0
  19. data/lib/generators/relevance_file/templates/deploy.rb.erb +22 -0
  20. data/lib/relevance_rails.rb +26 -1
  21. data/lib/relevance_rails/chef_dna.rb +32 -0
  22. data/lib/relevance_rails/provision.rb +69 -0
  23. data/lib/relevance_rails/railtie.rb +9 -0
  24. data/lib/relevance_rails/relevance_rails_template.rb +18 -26
  25. data/lib/relevance_rails/runner.rb +24 -0
  26. data/lib/relevance_rails/version.rb +1 -1
  27. data/lib/tasks/provision.rake +8 -0
  28. data/relevance_rails.gemspec +7 -2
  29. data/script/ci +57 -0
  30. data/spec/acceptance_spec.rb +25 -0
  31. data/spec/lib/provision_config_generator_spec.rb +27 -0
  32. data/spec/lib/relevance_rails_spec.rb +15 -0
  33. data/spec/lib/runner_spec.rb +22 -0
  34. data/spec/spec_helper.rb +59 -0
  35. data/techdebt.md +15 -0
  36. metadata +115 -12
  37. data/lib/relevance_rails/template_injector.rb +0 -5
@@ -1,19 +1,24 @@
1
1
  source :rubygems
2
2
 
3
- gem 'rails', '3.1.1'
4
- gem 'haml', '3.1.3'
3
+ gem 'rails', '3.2.2'
4
+ gem 'haml', '3.1.4'
5
5
  gem 'configatron', '2.8.3'
6
6
  gem 'airbrake', '~> 3.0.4'
7
7
  gem 'factory_girl_rails', '1.2.0'
8
8
  gem 'jquery-rails', '1.0.14'
9
9
  gem 'therubyracer'
10
+ <%- if database == 'mysql' -%>
10
11
  gem 'mysql2', '~> 0.3.11'
12
+ <%- end -%>
13
+ <%- if database == 'postgresql' -%>
14
+ gem 'pg', '~> 0.13.2'
15
+ <%- end -%>
11
16
 
12
17
  # Gems used only for assets and not required
13
18
  # in production environments by default.
14
19
  group "assets" do
15
- gem 'sass-rails', '~> 3.1.4'
16
- gem 'coffee-rails', '~> 3.1.1'
20
+ gem 'sass-rails', '~> 3.2.2'
21
+ gem 'coffee-rails', '~> 3.2.2'
17
22
  gem 'uglifier', '>= 1.0.3'
18
23
  end
19
24
 
@@ -28,8 +33,9 @@ group "development", "test" do
28
33
  gem 'mocha', '~> 0.9.12'
29
34
  gem 'guard-rspec', '~> 0.5.0', :require => false
30
35
  gem 'growl', '~> 1.0.3', :require => false
31
- gem 'rb-fsevent', '~> 0.4.2', :require => false
36
+ gem 'rb-fsevent', '~> 0.9.0', :require => false
32
37
  gem 'capistrano', '~> 2.11.2'
33
38
  gem 'capistrano-ext', '1.2.1', :require => nil
34
39
  gem 'capistrano_colors'
40
+ gem 'relevance_rails', '<%= RelevanceRails::VERSION %>'
35
41
  end
@@ -0,0 +1,36 @@
1
+ # <%= name %>
2
+
3
+ ## Getting Started
4
+
5
+ gem install bundler
6
+ [TODO other setup commands here]
7
+
8
+ ## Provisioning on EC2 (Optional)
9
+
10
+ First create an aws config in ~/.relevance\_rails/aws\_config.yml.
11
+ An example config looks like this:
12
+
13
+ ```yaml
14
+ aws_credentials:
15
+ :aws_access_key_id: <your aws access key id>
16
+ :aws_secret_access_key: <your aws secret access key>
17
+
18
+ server:
19
+ creation_config:
20
+ :flavor_id: <instance type, e.g. 'm1.large'>
21
+ :image_id: <ami to bootstrap with. Must be some UBUNTU image. e.g. "ami-fd589594">
22
+ :groups: <security group to place the new deployment in, e.g. "default">
23
+ :key_name: <name of the public/private keypair to start instance with>
24
+ private_key: |
25
+ -----BEGIN RSA PRIVATE KEY-----
26
+ Include the RSA private key here. This should correspond to the keypair indicated
27
+ by :key_name above.
28
+ -----END RSA PRIVATE KEY-----
29
+ ```
30
+
31
+ Now just provision your instance:
32
+
33
+ ```sh
34
+ $ rails g deployment qa
35
+ $ cap qa deploy:setup deploy
36
+ ```
@@ -0,0 +1,9 @@
1
+ !!!
2
+ %html
3
+ %head
4
+ %title <%= name %>
5
+ = stylesheet_link_tag :application
6
+ = javascript_include_tag :application
7
+ = csrf_meta_tag
8
+ %body
9
+ = yield
@@ -0,0 +1,17 @@
1
+ development:
2
+ adapter: mysql2
3
+ encoding: utf8
4
+ database: <%= name %>_development
5
+
6
+ # Warning: The database defined as "test" will be erased and
7
+ # re-generated from your development database when you run "rake".
8
+ # Do not set this db to the same as development or production.
9
+ test:
10
+ adapter: mysql2
11
+ encoding: utf8
12
+ database: <%= name %>_test
13
+
14
+ production:
15
+ adapter: mysql2
16
+ encoding: utf8
17
+ database: <%= name %>_production
@@ -0,0 +1,15 @@
1
+ development:
2
+ adapter: postgresql
3
+ database: <%= name %>_development
4
+
5
+ # Warning: The database defined as "test" will be erased and
6
+ # re-generated from your development database when you run "rake".
7
+ # Do not set this db to the same as development or production.
8
+ test:
9
+ adapter: postgresql
10
+ database: <%= name %>_test
11
+
12
+ production:
13
+ adapter: postgresql
14
+ database: <%= name %>_production
15
+ user: deploy
@@ -0,0 +1,22 @@
1
+ require 'bundler/capistrano'
2
+ require 'capistrano_colors'
3
+
4
+ set :application, "<%= name %>"
5
+ set :repository, "."
6
+ set :deploy_via, :copy
7
+
8
+ set :scm, :git
9
+
10
+ set :deploy_to, "/var/www/apps/#{ application }"
11
+ default_run_options[:pty] = true
12
+ set :ssh_options, { :paranoid => false, :forward_agent => true }
13
+
14
+ set :copy_exclude, '.git/*'
15
+
16
+ set :stages, %w(vagrant)
17
+ set :default_stage, 'vagrant'
18
+
19
+ after "deploy:setup", "deploy:copy_shared_db_config"
20
+ after "deploy:create_symlink", "deploy:symlink_shared_db_config"
21
+
22
+ Dir['config/deploy/recipes/*.rb'].sort.each { |f| eval(File.read(f)) }
@@ -1,6 +1,31 @@
1
1
  require "relevance_rails/version"
2
2
  require "relevance_rails/public_key_fetcher"
3
+ require "relevance_rails/chef_dna"
4
+ require 'relevance_rails/railtie' if defined? Rails
3
5
 
4
6
  module RelevanceRails
5
- # Your code goes here...
7
+ def self.rvm_gemset
8
+ @rvm_gemset ||= rvm_current.split('@')[1] || 'global'
9
+ end
10
+
11
+ def self.rvm_version
12
+ @rvm_version ||= rvm_current.split('@')[0] || 'ruby-1.9.3-p0'
13
+ end
14
+
15
+ def self.rvm_current
16
+ @rvm_current ||= rvm_exec('rvm current').chomp
17
+ end
18
+
19
+ # rvm_current SHOULD be in $PATH and execute ruby for the
20
+ # correct version and gemset
21
+ def self.rvm_run(command)
22
+ ret = `#{rvm_current} -S #{command}`
23
+ unless $?.success?
24
+ abort "\n Command '#{command}' failed with:\n#{ret}"
25
+ end
26
+ end
27
+
28
+ def self.rvm_exec(command)
29
+ `bash -c 'source ~/.rvm/scripts/rvm > /dev/null && #{command}'`
30
+ end
6
31
  end
@@ -0,0 +1,32 @@
1
+ module RelevanceRails::ChefDNA
2
+ def self.gene_splice(json, database)
3
+ set_ruby(json)
4
+ set_database(json, database)
5
+ end
6
+
7
+ def self.set_database(json, database)
8
+ if database == 'postgresql'
9
+ db_index = json['run_list'].find_index { |e| e == 'mysql::server' || e == 'role[postgres_database]'}
10
+ json['run_list'][db_index] = 'role[postgres_database]'
11
+ elsif database.nil? || database == 'mysql'
12
+ db_index = json['run_list'].find_index { |e| e == 'mysql::server' || e == 'role[postgres_database]'}
13
+ json['run_list'][db_index] = 'mysql::server'
14
+ end
15
+ end
16
+
17
+ def self.set_ruby(json)
18
+ if RelevanceRails.rvm_version =~ /^ree-(.*)/i
19
+ json['ruby_enterprise']['version'] = $1
20
+ json['ruby_enterprise']['url'] = "http://rubyenterpriseedition.googlecode.com/files/ruby-enterprise-#{$1}"
21
+ appstack_index = json['run_list'].find_index {|e| e[/^role\[.*_appstack\]$/] }
22
+ json['run_list'][appstack_index] = 'role[enterprise_appstack]'
23
+ elsif RelevanceRails.rvm_version =~ /^ruby-(.*)/i
24
+ json['ruby']['version'] = $1
25
+ json['ruby']['url'] = "http://ftp.ruby-lang.org/pub/ruby/1.9/ruby-#{$1}.tar.gz"
26
+ appstack_index = json['run_list'].find_index {|e| e[/^role\[.*_appstack\]$/] }
27
+ json['run_list'][appstack_index] = 'role[ruby_appstack]'
28
+ else
29
+ raise "Your ruby is NOT SUPPORTED. Please use ree or ruby."
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,69 @@
1
+ require 'fog'
2
+
3
+ module RelevanceRails
4
+ module Provision
5
+ def self.create_ec2(name = nil)
6
+ abort "Please provide a $NAME" unless name
7
+ provision_ec2_instances(name)
8
+ end
9
+
10
+ private
11
+ def self.provision_ec2_instances(name)
12
+ config = YAML::load(File.read(File.expand_path("~/.relevance_rails/aws_config.yml")))
13
+ fog = Fog::Compute.new(config['aws_credentials'].merge(:provider => 'AWS'))
14
+ server = fog.servers.create(config['server']['creation_config'])
15
+ fog.tags.create(:key => 'Name',
16
+ :value => "#{Rails.application.class.parent_name} #{name}",
17
+ :resource_id => server.id)
18
+ server.private_key = config['server']['private_key']
19
+ wait_for_ssh server
20
+ jobs = []
21
+ puts "Updating apt cache..."
22
+ jobs += server.ssh('sudo apt-get update')
23
+ puts "Installing ruby..."
24
+ jobs += server.ssh('sudo apt-get -y install ruby')
25
+ puts "Installing rubygems..."
26
+ jobs += server.ssh('sudo apt-get -y install rubygems1.8')
27
+ puts "Installing chef..."
28
+ jobs += server.ssh('sudo gem install chef --no-ri --no-rdoc --version 0.10.8')
29
+ puts "Copying chef resources from provision directory.."
30
+ server.scp("#{Rails.root.join('provision')}/", '/tmp/chef-solo', :recursive => true)
31
+ puts "Converging server, this may take a while (10-20 minutes)"
32
+ jobs += server.ssh('cd /tmp/chef-solo && sudo /var/lib/gems/1.8/bin/chef-solo -c solo.rb -j dna.json')
33
+ print_errors(jobs)
34
+ puts "Server IP: #{server.public_ip_address}"
35
+ end
36
+
37
+ def self.wait_for_ssh(server)
38
+ server.wait_for { ready? }
39
+ succeeded = false
40
+ attempts = 0
41
+ last_error = nil
42
+ until succeeded || attempts > 4
43
+ sleep 10
44
+ begin
45
+ server.ssh('ls')
46
+ succeeded = true
47
+ rescue Errno::ECONNREFUSED => e
48
+ puts "Connection #{attempts} refused, retrying..."
49
+ attempts += 1
50
+ last_error = e
51
+ end
52
+ end
53
+ raise last_error unless succeeded
54
+ puts "Server up and listening for SSH..."
55
+ end
56
+
57
+ def self.print_errors(jobs)
58
+ return if jobs.all? { |job| job.status == 0 }
59
+ jobs.each do |job|
60
+ puts "----------------------"
61
+ puts "Running #{job.command}"
62
+ puts "STDOUT: #{job.stdout}"
63
+ puts "STDERR: #{job.stderr}"
64
+ puts "----------------------"
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,9 @@
1
+ require 'rails'
2
+
3
+ module RelevanceRails
4
+ class Railtie < Rails::Railtie
5
+ rake_tasks do
6
+ load 'tasks/provision.rake'
7
+ end
8
+ end
9
+ end
@@ -1,22 +1,25 @@
1
- RVM_RUBY = "ree-1.8.7-2012.02"
2
- RVM_GEMSET = app_name
1
+ require 'relevance_rails'
2
+ require 'json'
3
3
 
4
- def rvm_run(command, config = {})
5
- run ". ~/.rvm/scripts/rvm && rvm use #{RVM_RUBY}@#{RVM_GEMSET} && #{command}", config
4
+ def rvm_run(command)
5
+ say_status :rvm_run, command
6
+ RelevanceRails.rvm_run(command)
6
7
  end
7
8
 
8
- run 'rm README.rdoc'
9
- run 'rm doc/README_FOR_APP'
10
- run 'rm public/index.html'
11
- run 'rm public/favicon.ico'
12
- run 'rm -rf test'
13
- run 'rm Gemfile'
14
- run 'rm app/assets/images/rails.png'
15
- run 'rm app/views/layouts/application.html.erb'
9
+ db = ['postgresql','mysql'].include?(options[:database]) ? options[:database] : 'mysql'
16
10
 
17
- generate(:relevance_file, app_name)
11
+ remove_file 'README.rdoc'
12
+ remove_file 'doc/README_FOR_APP'
13
+ remove_file 'public/index.html'
14
+ remove_file 'public/favicon.ico'
15
+ remove_file 'test'
16
+ remove_file 'Gemfile'
17
+ remove_file 'app/assets/images/rails.png'
18
+ remove_file 'app/views/layouts/application.html.erb'
18
19
 
19
- rvm_run "rvm use #{RVM_RUBY}@#{RVM_GEMSET} --create"
20
+ generate(:relevance_file, app_name, db)
21
+
22
+ run "rvm gemset create #{app_name}"
20
23
  rvm_run "gem install bundler"
21
24
  rvm_run "bundle install"
22
25
 
@@ -25,15 +28,4 @@ append_file ".gitignore", "config/database.yml\n"
25
28
  run 'cp config/database.example.yml config/database.yml'
26
29
  git :add => "."
27
30
  git :commit => "-a -m 'Initial commit'"
28
-
29
- git :remote => 'add -f elzar git://github.com/relevance/elzar.git'
30
- git :merge => '-s ours --no-commit elzar/master'
31
- git :"read-tree" => '--prefix=provision/ -u elzar/master'
32
- gsub_file 'provision/Vagrantfile', /config\.vm\.host_name(\s+)= .*$/, "config.vm.host_name\\1= '#{app_name.gsub('_','-')}.local'"
33
- gsub_file 'provision/roles/rails.rb', /:rails_app => \{$(\s+):name => .*$(\s+)\}/,":rails_app => {\\1:name => '#{app_name}'\\2}"
34
- run 'mv authorized_keys.json provision/data_bags/deploy/authorized_keys.json'
35
- git :rm => 'authorized_keys.json'
36
- git :add => 'provision/data_bags/deploy/authorized_keys.json'
37
- git :add => 'provision/Vagrantfile'
38
- git :add => 'provision/roles/rails.rb'
39
- git :commit => '-m "Merge Elzar as our provision subdirectory"'
31
+ generate(:provision_config, app_name, db)
@@ -0,0 +1,24 @@
1
+ require 'relevance_rails'
2
+
3
+ module RelevanceRails
4
+ class Runner
5
+ def self.start(argv=ARGV)
6
+ if argv.delete '--version'
7
+ puts "RelevanceRails #{RelevanceRails::VERSION}"
8
+ else
9
+ add_default_options! argv
10
+ exec 'rails', *argv
11
+ end
12
+ end
13
+
14
+ private
15
+
16
+ def self.add_default_options!(argv)
17
+ unless argv.any? =~ /^-d$/
18
+ template = File.join(File.dirname(__FILE__), "relevance_rails_template.rb")
19
+ argv << '-m'
20
+ argv << template
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,3 +1,3 @@
1
1
  module RelevanceRails
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,8 @@
1
+ require 'relevance_rails/provision'
2
+
3
+ namespace :provision do
4
+ desc 'Provision a deployable EC2 instance'
5
+ task :ec2 do
6
+ RelevanceRails::Provision.create_ec2(ENV['NAME'])
7
+ end
8
+ end
@@ -5,6 +5,7 @@ require "relevance_rails/version"
5
5
  Gem::Specification.new do |s|
6
6
  s.name = "relevance_rails"
7
7
  s.version = RelevanceRails::VERSION
8
+ s.homepage = "http://github.com/relevance/relevance_rails"
8
9
  s.authors = ["Alex Redington"]
9
10
  s.email = ["alex.redington@thinkrelevance.com"]
10
11
  s.homepage = ""
@@ -22,6 +23,10 @@ Gem::Specification.new do |s|
22
23
  s.executables = ['relevance_rails']
23
24
 
24
25
  # specify any dependencies here; for example:
25
- # s.add_development_dependency "rspec"
26
- s.add_runtime_dependency "rails", "~> 3.1"
26
+ s.add_runtime_dependency "rails", "~> 3.2"
27
+ s.add_runtime_dependency 'fog', '~> 1.3.0'
28
+ s.add_development_dependency 'pry'
29
+ s.add_development_dependency 'capybara'
30
+ s.add_development_dependency 'rspec'
31
+ s.add_development_dependency 'rake', '~> 0.9.2.2'
27
32
  end
data/script/ci ADDED
@@ -0,0 +1,57 @@
1
+ #!/bin/bash -v
2
+
3
+ RAILS_APP="app_for_ci"
4
+ TARGET_HOST="placeholder.example.com"
5
+
6
+ source "$HOME/.rvm/scripts/rvm"
7
+ rvm use "ruby-1.9.2@relevance_rails"
8
+
9
+ gem install bundler
10
+ bundle install
11
+ bundle exec rake spec
12
+
13
+ # exit if any statement fails; must be set AFTER loading RVM
14
+ set -e
15
+
16
+ echo "Building new relevance_rails gem..."
17
+ rm -Rf relevance_rails-*.gem
18
+ gem build --verbose relevance_rails.gemspec
19
+ echo "Done"
20
+
21
+ # NOTE: Manual install of just-built gem to workaround bundler wanting
22
+ # it to live on rubygems.org.
23
+ # NOTE: RVM 1.x doesn't work with "set -e", so you have to unset/set it.
24
+ set +e
25
+ rvm --force gemset delete $RAILS_APP
26
+ rvm gemset create $RAILS_APP
27
+ rvm gemset use $RAILS_APP
28
+ set -e
29
+
30
+ if [ `gem list relevance_rails --installed` = "true" ]; then
31
+ echo "Removing old relevance_rails gem..."
32
+ gem uninstall --verbose --all --executables relevance_rails
33
+ echo "Done"
34
+ fi
35
+
36
+ echo "Installing relevance_rails gem into $RAILS_APP gemset..."
37
+ gem install relevance_rails-*.gem
38
+ echo "Done."
39
+
40
+ rm -Rf ./$RAILS_APP
41
+ relevance_rails new $RAILS_APP --database=postgresql
42
+
43
+ # NOTE: this does NOT change the RVM gemset; we set it manually above
44
+ builtin cd $RAILS_APP
45
+
46
+ echo "Generating relevance_rails deployment scripts..."
47
+ ./script/rails generate deployment staging $TARGET_HOST
48
+ git add .
49
+ git commit -m "Generated relevance_rails deployment scripts."
50
+ echo "Done."
51
+
52
+ echo "Generating relevance_rails fixtures..."
53
+ ./script/rails generate fixtures
54
+ git add .
55
+ git commit -m "Generated relevance_rails fixtures."
56
+ echo "Done."
57
+