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.
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
data/.gitignore CHANGED
@@ -2,3 +2,5 @@
2
2
  .bundle
3
3
  Gemfile.lock
4
4
  pkg/*
5
+ app_for_ci
6
+ *.swp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm gemset use relevance_rails
data/.travis.yml ADDED
@@ -0,0 +1,7 @@
1
+ script: rake spec
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.3
5
+ branches:
6
+ only:
7
+ - master
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
- gem install relevance_rails
20
- relevance_rails new <your new project>
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
- Only supports REE 1.8.7, Rails 3.1 and MySQL right now.
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
@@ -1 +1,11 @@
1
1
  require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new
5
+ task :default => :spec
6
+
7
+ desc 'Run the acceptance specs'
8
+ task :acceptance do
9
+ ENV["ACCEPTANCE"] = "true"
10
+ Rake::Task[:spec].invoke
11
+ end
@@ -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 'rubygems'
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
@@ -0,0 +1,6 @@
1
+ {
2
+ "id":"authorized_keys",
3
+ "keys": [
4
+ <%= authorized_keys.join(",\n") %>
5
+ ]
6
+ }
@@ -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
- copy_file "Gemfile", "Gemfile"
12
+ template "Gemfile.erb", "Gemfile"
11
13
  end
12
14
 
13
15
  def create_readme_markdown
14
- create_file "README.markdown", <<-README
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
- create_file 'app/views/layouts/application.html.haml', <<-LAYOUT
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 ree-1.8.7-2012.02@#{name}"
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
- create_file 'config/deploy.rb', <<-CAP_CONFIG
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
- create_file 'config/database.example.yml', <<-DATABASE_CONFIG
82
- development:
83
- adapter: mysql2
84
- encoding: utf8
85
- database: #{name}_development
86
-
87
- # Warning: The database defined as "test" will be erased and
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