relevance_rails 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
data/.gitignore
CHANGED
data/.rvmrc
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
rvm gemset use relevance_rails
|
data/.travis.yml
ADDED
data/CHANGELOG.md
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
*v0.1.0*
|
2
|
+
|
3
|
+
* Provisioning can be done on existing apps
|
4
|
+
* Support multiple rubies - 1.9 and ree
|
5
|
+
* Add unit tests
|
6
|
+
* Can run acceptance tests on generated apps - rails g fixtures
|
7
|
+
* From provision to deploy is a 2 step process - rake provision:ec2 and rails g deployment
|
8
|
+
* Add more error handling
|
9
|
+
* Tentative support for multiple databases - postgresql and mysql
|
10
|
+
|
11
|
+
*v0.0.4*
|
12
|
+
|
13
|
+
* Add support for generating EC2 deployment environments
|
14
|
+
* 'rails g deployment <environment>' to generate a new environment
|
15
|
+
* REQUIRES the presence of ~/.relevance_rails/aws_config.yml
|
16
|
+
* Template aws_config.yml included with this gem.
|
17
|
+
* Newly generates EC2 deployment environments will be wired up as new cap stages.
|
18
|
+
|
19
|
+
*v0.0.3*
|
20
|
+
|
21
|
+
* Add support for multiple public keys pushed to converged hosts.
|
22
|
+
* Public keys are fetched from a git repo.
|
23
|
+
* Git repo url is stored in ~/.relevance_rails/keys_git_url
|
24
|
+
* Only the top level keys from the repo will be pushed to new hosts.
|
data/README.md
CHANGED
@@ -3,7 +3,7 @@ Relevance Rails
|
|
3
3
|
|
4
4
|
Yo dawg, I heard you like automation, so I automated your automation so you can autopilot while you autopilot!
|
5
5
|
|
6
|
-
Rails 3 projects with every fiddly bit convened rather than configured. Includes
|
6
|
+
Rails 3 projects with every fiddly bit convened rather than configured. Includes:
|
7
7
|
|
8
8
|
* HAML and SCSS
|
9
9
|
* RSpec 2 with Relevance config niceties
|
@@ -12,18 +12,115 @@ Rails 3 projects with every fiddly bit convened rather than configured. Includes
|
|
12
12
|
* Capistrano deploy recipes
|
13
13
|
* A VM deployment target under provision
|
14
14
|
|
15
|
+
[![Build Status](https://secure.travis-ci.org/relevance/relevance_rails.png?branch=master)](http://travis-ci.org/relevance/relevance_rails)
|
16
|
+
|
15
17
|
Getting Started
|
16
18
|
---------------
|
17
19
|
|
20
|
+
For new projects:
|
21
|
+
|
18
22
|
````sh
|
19
|
-
|
20
|
-
|
23
|
+
$ gem install relevance_rails
|
24
|
+
$ relevance_rails new <your new project>
|
21
25
|
````
|
22
26
|
|
27
|
+
For existing projects, first add to your Gemfile:
|
28
|
+
|
29
|
+
group :development, :test do
|
30
|
+
gem 'relevance_rails'
|
31
|
+
end
|
32
|
+
|
33
|
+
After a `bundle install`, pull in our chef recipes into provision/:
|
34
|
+
|
35
|
+
```sh
|
36
|
+
# defaults to mysql
|
37
|
+
$ rails g provision_config app_name
|
38
|
+
# if using postgresql
|
39
|
+
$ rails g provision_config app_name postgresql
|
40
|
+
```
|
41
|
+
|
42
|
+
Provisioning on EC2
|
43
|
+
-------------------
|
44
|
+
|
45
|
+
First create an aws config in ~/.relevance\_rails/aws\_config.yml.
|
46
|
+
An example config looks like this:
|
47
|
+
|
48
|
+
```yaml
|
49
|
+
aws_credentials:
|
50
|
+
:aws_access_key_id: <your aws access key id>
|
51
|
+
:aws_secret_access_key: <your aws secret access key>
|
52
|
+
|
53
|
+
server:
|
54
|
+
creation_config:
|
55
|
+
:flavor_id: <instance type, e.g. 'm1.large'>
|
56
|
+
:image_id: <ami to bootstrap with. Must be some UBUNTU image. e.g. "ami-fd589594">
|
57
|
+
:groups: <security group to place the new deployment in, e.g. "default">
|
58
|
+
:key_name: <name of the public/private keypair to start instance with>
|
59
|
+
private_key: |
|
60
|
+
-----BEGIN RSA PRIVATE KEY-----
|
61
|
+
Include the RSA private key here. This should correspond to the keypair indicated
|
62
|
+
by :key_name above.
|
63
|
+
-----END RSA PRIVATE KEY-----
|
64
|
+
```
|
65
|
+
|
66
|
+
Now just provision your instance:
|
67
|
+
|
68
|
+
```sh
|
69
|
+
$ rake provision:ec2 NAME=qa
|
70
|
+
...
|
71
|
+
Server IP: 1.1.1.1
|
72
|
+
# Pass IP from previous command as second argument
|
73
|
+
$ rails g deployment qa 1.1.1.1
|
74
|
+
$ cap qa deploy:setup deploy
|
75
|
+
```
|
76
|
+
|
77
|
+
Provisioning with Vagrant
|
78
|
+
-------------------------
|
79
|
+
|
80
|
+
From your app's root directory:
|
81
|
+
|
82
|
+
```sh
|
83
|
+
$ cd provision
|
84
|
+
# pull in vagrant and chef
|
85
|
+
$ bundle install
|
86
|
+
$ vagrant up
|
87
|
+
```
|
88
|
+
|
89
|
+
Vagrant instance should be up at 172.25.5.5.
|
90
|
+
|
91
|
+
Supported Ruby Versions
|
92
|
+
-----------------------
|
93
|
+
|
94
|
+
Currently both Ruby 1.9.x and REE 1.8.7 are supported via RVM. relevance_rails
|
95
|
+
configures your Rails app (and Chef provisioning scripts) to require the version
|
96
|
+
of Ruby you used to invoke the relevance_rails executable.
|
97
|
+
|
98
|
+
Supported Databases
|
99
|
+
-------------------
|
100
|
+
|
101
|
+
Currently both MySQL and PostgreSQL are supported. By default relevance_rails configures
|
102
|
+
your Rails app (and Chef provisioning scripts) to use MySQL. However, if you use the
|
103
|
+
standard `--database=postgresql` Rails option, relevance_rails will use PostgreSQL.
|
104
|
+
|
105
|
+
Maintainer Notes
|
106
|
+
----------------
|
107
|
+
|
108
|
+
When QAing or doing local development of this gem, the gem must be built and installed locally.
|
109
|
+
|
110
|
+
In order to test deployment, use the example below to package the relevance_rails gem:
|
111
|
+
|
112
|
+
# Given a relevance_rails app "app" lives in "~/src/app"
|
113
|
+
# And the relevance_rails source lives in "~/src/relevance_rails"
|
114
|
+
~/src/relevance_rails $ gem build relevance_rails.gemspec
|
115
|
+
~/src/relevance_rails $ cd ~/src/app
|
116
|
+
~/src/app $ gem install ../relevance_rails/relevance_rails-0.0.7.gem
|
117
|
+
~/src/app $ bundle package
|
118
|
+
~/src/app $ git commit -m "Package gems" vendor/cache
|
119
|
+
|
23
120
|
Caveats
|
24
121
|
-------
|
25
122
|
|
26
|
-
|
123
|
+
Currently we only support Ruby 1.9.x, REE 1.8.7, Rails 3.2, MySQL, and PostgreSQL installed on Ubuntu.
|
27
124
|
|
28
125
|
Improvements
|
29
126
|
------------
|
data/Rakefile
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
aws_credentials:
|
2
|
+
:aws_access_key_id: <your aws access key id>
|
3
|
+
:aws_secret_access_key: <your aws secret access key>
|
4
|
+
|
5
|
+
server:
|
6
|
+
creation_config:
|
7
|
+
:flavor_id: <instance type, e.g. 'm1.large'>
|
8
|
+
:image_id: <ami to bootstrap with. Must be some UBUNTU image. e.g. "ami-fd589594">
|
9
|
+
:groups: <security group to place the new deployment in, e.g. "default">
|
10
|
+
:key_name: <name of the public/private keypair to start instance with>
|
11
|
+
private_key: |
|
12
|
+
-----BEGIN RSA PRIVATE KEY-----
|
13
|
+
Include the RSA private key here. This should correspond to the keypair indicated
|
14
|
+
by :key_name above.
|
15
|
+
-----END RSA PRIVATE KEY-----
|
data/bin/relevance_rails
CHANGED
@@ -1,21 +1,4 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
|
-
#
|
3
|
-
# This file was generated by RubyGems.
|
4
|
-
#
|
5
|
-
# The application 'railties' is installed as part of a gem, and
|
6
|
-
# this file is here to facilitate running it.
|
7
|
-
#
|
8
2
|
|
9
|
-
require '
|
10
|
-
|
11
|
-
version = ">= 0"
|
12
|
-
|
13
|
-
if ARGV.first =~ /^_(.*)_$/ and Gem::Version.correct? $1 then
|
14
|
-
version = $1
|
15
|
-
ARGV.shift
|
16
|
-
end
|
17
|
-
|
18
|
-
require 'relevance_rails/template_injector'
|
19
|
-
|
20
|
-
gem 'railties', version
|
21
|
-
load Gem.bin_path('railties', 'rails', version)
|
3
|
+
require 'relevance_rails/runner'
|
4
|
+
RelevanceRails::Runner.start
|
@@ -0,0 +1,31 @@
|
|
1
|
+
class DeploymentGenerator < Rails::Generators::NamedBase
|
2
|
+
desc "Generates and updates capistrano config for a new deployment target"
|
3
|
+
argument :hostname, :type => :string
|
4
|
+
|
5
|
+
def write_stage_file
|
6
|
+
create_file "config/deploy/#{name}.rb", <<-DEPLOY_STAGE
|
7
|
+
set :user, 'deploy'
|
8
|
+
|
9
|
+
role :web, "#{hostname}"
|
10
|
+
role :app, "#{hostname}"
|
11
|
+
role :db, "#{hostname}", :primary => true
|
12
|
+
DEPLOY_STAGE
|
13
|
+
end
|
14
|
+
|
15
|
+
def inject_new_deployment_to_stages
|
16
|
+
new_contents = ""
|
17
|
+
File.new(Rails.root.join('config','deploy.rb')).readlines.each do |line|
|
18
|
+
unless line =~ /^set :stages, (.*)$/
|
19
|
+
new_contents << line
|
20
|
+
else
|
21
|
+
stages = eval($1)
|
22
|
+
stages << name
|
23
|
+
stage_array_contents = stages.map{|stage| "\"#{stage}\""}.join(', ')
|
24
|
+
new_contents << "set :stages, [#{stage_array_contents}]\n"
|
25
|
+
end
|
26
|
+
end
|
27
|
+
File.open(Rails.root.join('config','deploy.rb'),'w') do |file|
|
28
|
+
file.write new_contents
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class FixturesGenerator < Rails::Generators::Base
|
2
|
+
def create_controller
|
3
|
+
create_file "app/controllers/relevance_rails_controller.rb", <<-STR
|
4
|
+
class RelevanceRailsController < ApplicationController
|
5
|
+
end
|
6
|
+
STR
|
7
|
+
end
|
8
|
+
|
9
|
+
def create_views
|
10
|
+
create_file "app/views/relevance_rails/index.html.haml", <<-STR
|
11
|
+
%h1 WELCOME HOME
|
12
|
+
STR
|
13
|
+
create_file "app/views/relevance_rails/db.html.haml", <<-STR
|
14
|
+
%h1.database= ActiveRecord::Base.connection.current_database
|
15
|
+
STR
|
16
|
+
end
|
17
|
+
|
18
|
+
def create_coffee
|
19
|
+
create_file "app/assets/javascripts/relevance_rails.js.coffee", <<-STR
|
20
|
+
console.log 'Hello from Relevance, Inc!'
|
21
|
+
STR
|
22
|
+
end
|
23
|
+
|
24
|
+
def create_sass
|
25
|
+
create_file "app/assets/stylesheets/relevance_rails.css.scss", <<-STR
|
26
|
+
$background: blue;
|
27
|
+
|
28
|
+
h1.relevance {
|
29
|
+
background-color: $background;
|
30
|
+
}
|
31
|
+
STR
|
32
|
+
end
|
33
|
+
|
34
|
+
def modify_routes
|
35
|
+
insert_into_file "config/routes.rb", :after => "::Application.routes.draw do" do
|
36
|
+
<<-STR
|
37
|
+
|
38
|
+
# Required to test relevance_rails gem.
|
39
|
+
match '/relevance_rails' => 'relevance_rails#index'
|
40
|
+
match '/relevance_rails/db' => 'relevance_rails#db'
|
41
|
+
STR
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,56 @@
|
|
1
|
+
require 'relevance_rails'
|
2
|
+
require 'rails/generators'
|
3
|
+
|
4
|
+
class ProvisionConfigGenerator < Rails::Generators::NamedBase
|
5
|
+
|
6
|
+
desc "This generator configures the provision sub-directory with appropriate files."
|
7
|
+
|
8
|
+
source_root File.expand_path("../templates", __FILE__)
|
9
|
+
|
10
|
+
argument :database, :type => :string, :default => 'mysql'
|
11
|
+
|
12
|
+
attr_reader :authorized_keys
|
13
|
+
|
14
|
+
def fetch_elzar
|
15
|
+
git :remote => 'add -f elzar git://github.com/relevance/elzar.git'
|
16
|
+
git :merge => '-s ours --no-commit elzar/master'
|
17
|
+
git :"read-tree" => '--prefix=provision/ -u elzar/master'
|
18
|
+
gsub_file 'provision/Vagrantfile', /config\.vm\.host_name(\s+)= .*$/,
|
19
|
+
"config.vm.host_name\\1= '#{name.gsub('_','-')}.local'"
|
20
|
+
end
|
21
|
+
|
22
|
+
def create_authorized_key_data_bag
|
23
|
+
if (@authorized_keys = fetch_keys).empty?
|
24
|
+
abort "No ssh keys were found! Check ssh-add -L and your keys_git_url config."
|
25
|
+
end
|
26
|
+
@authorized_keys.map! {|key| "\"#{key}\""}
|
27
|
+
template('authorized_keys.json.erb', 'provision/data_bags/deploy/authorized_keys.json', {:force => true})
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_dna_json
|
31
|
+
path = File.expand_path('provision/dna.json', destination_root)
|
32
|
+
json = JSON.parse File.binread(path)
|
33
|
+
json['rails_app']['name'] = name
|
34
|
+
# This generator may not receive a working directory;
|
35
|
+
# and we pull data by shelling out to RVM about the ruby
|
36
|
+
# version. This sets the directory explicitly beforehand.
|
37
|
+
Dir.chdir(destination_root)
|
38
|
+
RelevanceRails::ChefDNA.gene_splice(json,database)
|
39
|
+
create_file('provision/dna.json', JSON.generate(json), {:force => true})
|
40
|
+
end
|
41
|
+
|
42
|
+
def commit_changes
|
43
|
+
git :add => 'provision/data_bags/deploy/authorized_keys.json'
|
44
|
+
git :add => 'provision/Vagrantfile'
|
45
|
+
git :add => 'provision/dna.json'
|
46
|
+
git :commit => '-m "Merge Elzar as our provision subdirectory"'
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def fetch_keys
|
52
|
+
local_keys = `ssh-add -L`.split("\n")
|
53
|
+
local_keys = [] unless $?.success?
|
54
|
+
(local_keys + RelevanceRails::PublicKeyFetcher.public_keys).uniq
|
55
|
+
end
|
56
|
+
end
|
@@ -6,37 +6,22 @@ class RelevanceFileGenerator < Rails::Generators::NamedBase
|
|
6
6
|
|
7
7
|
source_root File.expand_path("../templates", __FILE__)
|
8
8
|
|
9
|
+
argument :database, :type => :string, :default => 'mysql'
|
10
|
+
|
9
11
|
def copy_gemfile
|
10
|
-
|
12
|
+
template "Gemfile.erb", "Gemfile"
|
11
13
|
end
|
12
14
|
|
13
15
|
def create_readme_markdown
|
14
|
-
|
15
|
-
# #{name}
|
16
|
-
|
17
|
-
## Getting Started
|
18
|
-
|
19
|
-
gem install bundler
|
20
|
-
# TODO other setup commands here
|
21
|
-
README
|
16
|
+
template "README.markdown.erb", "README.markdown"
|
22
17
|
end
|
23
18
|
|
24
19
|
def create_application_layout
|
25
|
-
|
26
|
-
!!!
|
27
|
-
%html
|
28
|
-
%head
|
29
|
-
%title #{name}
|
30
|
-
= stylesheet_link_tag :application
|
31
|
-
= javascript_include_tag :application
|
32
|
-
= csrf_meta_tag
|
33
|
-
%body
|
34
|
-
= yield
|
35
|
-
LAYOUT
|
20
|
+
template 'application.html.haml.erb', 'app/views/layouts/application.html.haml'
|
36
21
|
end
|
37
22
|
|
38
23
|
def create_rvmrc
|
39
|
-
create_file ".rvmrc", "rvm use
|
24
|
+
create_file ".rvmrc", "rvm use #{RelevanceRails.rvm_version}@#{name}"
|
40
25
|
end
|
41
26
|
|
42
27
|
def create_rspec
|
@@ -52,64 +37,17 @@ gem install bundler
|
|
52
37
|
end
|
53
38
|
|
54
39
|
def create_deploy
|
55
|
-
|
56
|
-
require 'bundler/capistrano'
|
57
|
-
|
58
|
-
set :application, "#{name}"
|
59
|
-
set :repository, "."
|
60
|
-
set :deploy_via, :copy
|
61
|
-
|
62
|
-
set :scm, :git
|
63
|
-
|
64
|
-
set :deploy_to, "/var/www/apps/\#{application}"
|
65
|
-
default_run_options[:pty] = true
|
66
|
-
set :ssh_options, { :paranoid => false, :forward_agent => true }
|
67
|
-
|
68
|
-
set :copy_exclude, '.git/*'
|
69
|
-
|
70
|
-
set :stages, %w(vagrant)
|
71
|
-
set :default_stage, 'vagrant'
|
72
|
-
|
73
|
-
after "deploy:setup", "deploy:copy_shared_db_config"
|
74
|
-
after "deploy:create_symlink", "deploy:symlink_shared_db_config"
|
75
|
-
|
76
|
-
Dir['config/deploy/recipes/*.rb'].sort.each { |f| eval(File.read(f)) }
|
77
|
-
CAP_CONFIG
|
40
|
+
template 'deploy.rb.erb', 'config/deploy.rb'
|
78
41
|
end
|
79
42
|
|
80
43
|
def create_database_example_yml
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
# re-generated from your development database when you run "rake".
|
89
|
-
# Do not set this db to the same as development or production.
|
90
|
-
test:
|
91
|
-
adapter: mysql2
|
92
|
-
encoding: utf8
|
93
|
-
database: #{name}_test
|
94
|
-
|
95
|
-
production:
|
96
|
-
adapter: mysql2
|
97
|
-
encoding: utf8
|
98
|
-
database: #{name}_production
|
99
|
-
DATABASE_CONFIG
|
100
|
-
end
|
101
|
-
|
102
|
-
def create_authorized_key_data_bag
|
103
|
-
authorized_keys = (`ssh-add -L`.split("\n") + RelevanceRails::PublicKeyFetcher.public_keys).uniq
|
104
|
-
authorized_keys.map! {|key| "\"#{key}\""}
|
105
|
-
create_file 'authorized_keys.json', <<-AUTHORIZED_KEYS
|
106
|
-
{
|
107
|
-
"id":"authorized_keys",
|
108
|
-
"keys": [
|
109
|
-
#{authorized_keys.join(",\n")}
|
110
|
-
]
|
111
|
-
}
|
112
|
-
AUTHORIZED_KEYS
|
44
|
+
if database == 'mysql'
|
45
|
+
template 'database.example.yml.mysql.erb', 'config/database.example.yml'
|
46
|
+
elsif database == 'postgresql'
|
47
|
+
template 'database.example.yml.postgresql.erb', 'config/database.example.yml'
|
48
|
+
else
|
49
|
+
create_file 'database.example.yml', "Don't know how to make a template for database: #{database}"
|
50
|
+
end
|
113
51
|
end
|
114
52
|
|
115
53
|
def copy_deploy_recipes
|