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.
- data/.gitignore +2 -0
- data/.rvmrc +1 -0
- data/.travis.yml +7 -0
- data/CHANGELOG.md +24 -0
- data/README.md +101 -4
- data/Rakefile +10 -0
- data/aws_config.example.yml +15 -0
- data/bin/relevance_rails +2 -19
- data/lib/generators/deployment/deployment_generator.rb +31 -0
- data/lib/generators/fixtures/fixtures_generator.rb +44 -0
- data/lib/generators/provision_config/provision_config_generator.rb +56 -0
- data/lib/generators/provision_config/templates/authorized_keys.json.erb +6 -0
- data/lib/generators/relevance_file/relevance_file_generator.rb +14 -76
- data/lib/generators/relevance_file/templates/{Gemfile → Gemfile.erb} +11 -5
- data/lib/generators/relevance_file/templates/README.markdown.erb +36 -0
- data/lib/generators/relevance_file/templates/application.html.haml.erb +9 -0
- data/lib/generators/relevance_file/templates/database.example.yml.mysql.erb +17 -0
- data/lib/generators/relevance_file/templates/database.example.yml.postgresql.erb +15 -0
- data/lib/generators/relevance_file/templates/deploy.rb.erb +22 -0
- data/lib/relevance_rails.rb +26 -1
- data/lib/relevance_rails/chef_dna.rb +32 -0
- data/lib/relevance_rails/provision.rb +69 -0
- data/lib/relevance_rails/railtie.rb +9 -0
- data/lib/relevance_rails/relevance_rails_template.rb +18 -26
- data/lib/relevance_rails/runner.rb +24 -0
- data/lib/relevance_rails/version.rb +1 -1
- data/lib/tasks/provision.rake +8 -0
- data/relevance_rails.gemspec +7 -2
- data/script/ci +57 -0
- data/spec/acceptance_spec.rb +25 -0
- data/spec/lib/provision_config_generator_spec.rb +27 -0
- data/spec/lib/relevance_rails_spec.rb +15 -0
- data/spec/lib/runner_spec.rb +22 -0
- data/spec/spec_helper.rb +59 -0
- data/techdebt.md +15 -0
- metadata +115 -12
- data/lib/relevance_rails/template_injector.rb +0 -5
@@ -1,19 +1,24 @@
|
|
1
1
|
source :rubygems
|
2
2
|
|
3
|
-
gem 'rails', '3.
|
4
|
-
gem 'haml', '3.1.
|
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.
|
16
|
-
gem 'coffee-rails', '~> 3.
|
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.
|
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,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)) }
|
data/lib/relevance_rails.rb
CHANGED
@@ -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
|
-
|
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
|
@@ -1,22 +1,25 @@
|
|
1
|
-
|
2
|
-
|
1
|
+
require 'relevance_rails'
|
2
|
+
require 'json'
|
3
3
|
|
4
|
-
def rvm_run(command
|
5
|
-
|
4
|
+
def rvm_run(command)
|
5
|
+
say_status :rvm_run, command
|
6
|
+
RelevanceRails.rvm_run(command)
|
6
7
|
end
|
7
8
|
|
8
|
-
|
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
|
-
|
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
|
-
|
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
|
data/relevance_rails.gemspec
CHANGED
@@ -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
|
-
|
26
|
-
s.add_runtime_dependency
|
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
|
+
|