blue 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/ISSUES.md +6 -0
- data/README.md +11 -5
- data/Rakefile +1 -0
- data/blue.gemspec +7 -2
- data/lib/blue/abstract_manifest.rb +27 -0
- data/lib/blue/box.rb +28 -0
- data/lib/blue/config.rb +29 -0
- data/lib/blue/database_config.rb +17 -0
- data/lib/blue/deep_merge.rb +22 -0
- data/lib/blue/plugins/ntpd.rb +16 -0
- data/lib/blue/plugins.rb +16 -0
- data/lib/blue/railtie.rb +10 -0
- data/lib/blue/template.rb +40 -0
- data/lib/blue/version.rb +1 -1
- data/lib/blue.rb +71 -2
- data/lib/capistrano/deploy.rb +29 -0
- data/lib/capistrano/gems.rb +22 -0
- data/lib/capistrano/integration.rb +39 -0
- data/lib/capistrano/local_config.rb +59 -0
- data/lib/capistrano/os.rb +37 -0
- data/lib/capistrano/rails.rb +25 -0
- data/lib/capistrano/ruby.rb +44 -0
- data/lib/capistrano/setup.rb +28 -0
- data/lib/tasks/blue.rake +28 -0
- data/templates/Capfile +3 -0
- data/templates/blue.yml +10 -0
- data/templates/box.rb +23 -0
- data/templates/deploy.rb +3 -0
- metadata +76 -12
data/.gitignore
CHANGED
data/ISSUES.md
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
Currently hacking in place (in an unsafe way) the github key fingerprint, or else the first git clone fails.
|
2
|
+
|
3
|
+
Postgres notes:
|
4
|
+
sudo apt-get install libpq-dev # required for gem 'pg'
|
5
|
+
will need to use puppet/shaddow_puppet from root install (not bundler) as they'll need to be available to install postgres/dependencies before the gem 'pg' can be installed
|
6
|
+
|
data/README.md
CHANGED
@@ -1,20 +1,25 @@
|
|
1
1
|
# Blue
|
2
2
|
|
3
|
-
|
3
|
+
Blue helps you manage your Ruby on Rails deployment.
|
4
|
+
|
5
|
+
* Deploy new code
|
6
|
+
* Install/Update/Restart services
|
4
7
|
|
5
8
|
## Installation
|
6
9
|
|
7
10
|
Add this line to your application's Gemfile:
|
8
11
|
|
9
|
-
|
12
|
+
group :development, :deployment do
|
13
|
+
gem 'blue', :git => 'git@github.com:crankharder/blue.git'
|
14
|
+
end
|
10
15
|
|
11
|
-
|
16
|
+
Run Bundle:
|
12
17
|
|
13
18
|
$ bundle
|
14
19
|
|
15
|
-
|
20
|
+
Then run the following to move a basic set of configs into place.
|
16
21
|
|
17
|
-
$
|
22
|
+
$ rake blue:setup
|
18
23
|
|
19
24
|
## Usage
|
20
25
|
|
@@ -27,3 +32,4 @@ TODO: Write usage instructions here
|
|
27
32
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
28
33
|
4. Push to the branch (`git push origin my-new-feature`)
|
29
34
|
5. Create new Pull Request
|
35
|
+
|
data/Rakefile
CHANGED
data/blue.gemspec
CHANGED
@@ -8,8 +8,8 @@ Gem::Specification.new do |spec|
|
|
8
8
|
spec.version = Blue::VERSION
|
9
9
|
spec.authors = ["Josh Sharpe"]
|
10
10
|
spec.email = ["josh.m.sharpe@gmail.com"]
|
11
|
-
spec.description = %q{
|
12
|
-
spec.summary = %q{
|
11
|
+
spec.description = %q{A deployment framework for rails apps}
|
12
|
+
spec.summary = %q{Helps manage all aspects of your cloud infrastructure. Install services, deploy code, restart processes, monitor, etc...}
|
13
13
|
spec.homepage = ""
|
14
14
|
spec.license = "MIT"
|
15
15
|
|
@@ -18,6 +18,11 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency 'hashie'
|
22
|
+
spec.add_dependency 'shadow_puppet'
|
23
|
+
spec.add_dependency 'capistrano'
|
24
|
+
|
21
25
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
26
|
spec.add_development_dependency "rake"
|
23
27
|
end
|
28
|
+
|
@@ -0,0 +1,27 @@
|
|
1
|
+
module Blue
|
2
|
+
class AbstractManifest < ShadowPuppet::Manifest
|
3
|
+
|
4
|
+
def self.inherited(klass)
|
5
|
+
unless klass == Blue::Box
|
6
|
+
raise StandardError, "Do not inherit directly from #{self.class.name}. Instead, inherit from #{Blue::Box}"
|
7
|
+
end
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.hostname
|
11
|
+
self.const_defined?(:HOSTNAME) ? self.const_get(:HOSTNAME) : self.name.underscore.gsub("_", '.')
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.roles
|
15
|
+
self.const_get(:ROLES)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.__config__
|
19
|
+
ShadowPuppet::Manifest.__config__
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.recipes
|
23
|
+
ShadowPuppet::Manifest.recipes
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
data/lib/blue/box.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'blue/template'
|
2
|
+
|
3
|
+
module Blue
|
4
|
+
class Box < Blue::AbstractManifest
|
5
|
+
|
6
|
+
include Blue::Template
|
7
|
+
include Blue::Ntpd
|
8
|
+
|
9
|
+
def self.inherited(klass)
|
10
|
+
Blue.register_box(klass)
|
11
|
+
klass.add_role(:ruby)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.add_role(role)
|
15
|
+
roles << role
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.roles
|
20
|
+
@roles ||= Set.new
|
21
|
+
end
|
22
|
+
|
23
|
+
def roles
|
24
|
+
self.class.roles
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
data/lib/blue/config.rb
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
module Blue
|
2
|
+
module Config
|
3
|
+
|
4
|
+
def self.included(klass)
|
5
|
+
klass.class_eval do
|
6
|
+
@@config = Hashie::Mash.new
|
7
|
+
|
8
|
+
def self.configure(new_config = {})
|
9
|
+
@@config.deep_merge!(new_config)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.load_app_config!
|
13
|
+
configure(YAML.load(IO.read(BLUE_CONFIG)))
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.config
|
17
|
+
@@config
|
18
|
+
end
|
19
|
+
|
20
|
+
Blue.configure({
|
21
|
+
:user => 'rails',
|
22
|
+
:group => 'rails',
|
23
|
+
:scm => 'git'
|
24
|
+
})
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Blue
|
2
|
+
module DatabaseConfig
|
3
|
+
|
4
|
+
def self.database_yml
|
5
|
+
File.join(Blue.current_release_dir, 'config', 'database.yml')
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.load
|
9
|
+
if File.exists?(database_yml)
|
10
|
+
Blue.configure(:database => YAML::load(IO.read(database_yml))[Blue.env])
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
Blue::DatabaseConfig.load
|
17
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Hash
|
2
|
+
# Returns a new hash with +self+ and +other_hash+ merged recursively.
|
3
|
+
#
|
4
|
+
# h1 = {:x => {:y => [4,5,6]}, :z => [7,8,9]}
|
5
|
+
# h2 = {:x => {:y => [7,8,9]}, :z => "xyz"}
|
6
|
+
#
|
7
|
+
# h1.deep_merge(h2) #=> { :x => {:y => [7, 8, 9]}, :z => "xyz" }
|
8
|
+
# h2.deep_merge(h1) #=> { :x => {:y => [4, 5, 6]}, :z => [7, 8, 9] }
|
9
|
+
def deep_merge(other_hash)
|
10
|
+
dup.deep_merge!(other_hash)
|
11
|
+
end
|
12
|
+
|
13
|
+
# Same as +deep_merge+, but modifies +self+.
|
14
|
+
def deep_merge!(other_hash)
|
15
|
+
other_hash.each_pair do |k,v|
|
16
|
+
tv = self[k]
|
17
|
+
self[k] = tv.is_a?(Hash) && v.is_a?(Hash) ? tv.deep_merge(v) : v
|
18
|
+
end
|
19
|
+
self
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
module Blue
|
2
|
+
module Ntpd
|
3
|
+
|
4
|
+
def ntpd
|
5
|
+
package :ntp, :ensure => :latest
|
6
|
+
service :ntp, :ensure => :running, :require => package('ntp'), :pattern => 'ntpd'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.included(klass)
|
10
|
+
klass.class_eval do
|
11
|
+
recipe :ntpd
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
data/lib/blue/plugins.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'blue/plugins/ntpd'
|
2
|
+
|
3
|
+
module Blue
|
4
|
+
module Plugins
|
5
|
+
|
6
|
+
# Scour loaded gems for matches and require them.
|
7
|
+
def self.init
|
8
|
+
Gem.loaded_specs.values.map(&:name).select{|n| n.match("blue-")}.each do |plugin|
|
9
|
+
require plugin.gsub('-','/')
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
Blue::Plugins.init
|
16
|
+
|
data/lib/blue/railtie.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
module Blue
|
2
|
+
module Template
|
3
|
+
|
4
|
+
def self.included(klass)
|
5
|
+
klass.class_eval do
|
6
|
+
def local_template_dir
|
7
|
+
@local_template_dir ||= Pathname.new(Blue.rails_current + '/app/manifests/templates')
|
8
|
+
end
|
9
|
+
|
10
|
+
def local_template(pathname)
|
11
|
+
(local_template_dir + pathname.basename).expand_path
|
12
|
+
end
|
13
|
+
|
14
|
+
# Render the ERB template located at <tt>pathname</tt>. If a template exists
|
15
|
+
# with the same basename at <tt>RAILS_ROOT/app/manifests/templates</tt>, it
|
16
|
+
# is used instead. This is useful to override templates provided by plugins
|
17
|
+
# to customize application configuration files.
|
18
|
+
def template(pathname, b = binding)
|
19
|
+
pathname = Pathname.new(pathname) unless pathname.kind_of?(Pathname)
|
20
|
+
|
21
|
+
pathname = if local_template(pathname).exist?
|
22
|
+
local_template(pathname)
|
23
|
+
elsif pathname.exist?
|
24
|
+
pathname
|
25
|
+
else
|
26
|
+
raise LoadError, "Can't find template #{pathname}"
|
27
|
+
end
|
28
|
+
erb = ERB.new(pathname.read)
|
29
|
+
erb.filename = pathname.to_s
|
30
|
+
erb.result(b)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def template(pathname, b = binding)
|
36
|
+
self.class.template(pathname, b)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
data/lib/blue/version.rb
CHANGED
data/lib/blue.rb
CHANGED
@@ -1,5 +1,74 @@
|
|
1
|
-
|
1
|
+
ENV['DEPLOY_ENV'] ||= 'production'
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'capistrano'
|
5
|
+
require 'hashie'
|
6
|
+
require 'shadow_puppet'
|
7
|
+
|
8
|
+
require 'blue/version'
|
9
|
+
require 'blue/deep_merge'
|
10
|
+
require 'blue/config'
|
11
|
+
|
12
|
+
require 'blue/railtie' if defined?(Rails)
|
2
13
|
|
3
14
|
module Blue
|
4
|
-
|
15
|
+
BLUE_CONFIG = 'config/blue.yml'
|
16
|
+
|
17
|
+
include Blue::Config
|
18
|
+
|
19
|
+
def self.env
|
20
|
+
ENV['DEPLOY_ENV']
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.rails_root
|
24
|
+
@@rails_root ||= `pwd`.strip #File.join(current_release_dir.split('/')[0..3] + ['current'])
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.rails_current
|
28
|
+
@@rails_current ||= File.join(current_release_dir.split('/')[0..3] + ['current'])
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.current_release_dir
|
32
|
+
@@current_release_dir ||= `pwd`.strip
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.shared_path
|
36
|
+
@@shared_path ||= "/u/apps/stocks/shared/"
|
37
|
+
end
|
38
|
+
|
39
|
+
@@boxes = []
|
40
|
+
def self.register_box(klass)
|
41
|
+
@@boxes << klass
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.boxes
|
45
|
+
@@boxes
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.load_boxes!
|
49
|
+
Dir.glob("#{rails_root}/config/blue/boxes/#{env}/*.rb").each do |rb|
|
50
|
+
require rb
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
if File.exists?(Blue::BLUE_CONFIG)
|
56
|
+
require 'blue/config'
|
57
|
+
require 'blue/database_config'
|
58
|
+
|
59
|
+
require 'capistrano/setup'
|
60
|
+
require 'capistrano/deploy'
|
61
|
+
require 'capistrano/rails'
|
62
|
+
|
63
|
+
require 'blue/plugins'
|
64
|
+
require 'blue/abstract_manifest'
|
65
|
+
require 'blue/box'
|
66
|
+
|
67
|
+
require 'capistrano/local_config'
|
68
|
+
|
69
|
+
Blue.load_app_config!
|
70
|
+
Blue.load_boxes!
|
5
71
|
end
|
72
|
+
|
73
|
+
require "capistrano/integration"
|
74
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Blue
|
2
|
+
class Deploy
|
3
|
+
def self.load(capistrano_config)
|
4
|
+
capistrano_config.load do
|
5
|
+
|
6
|
+
namespace :blue do
|
7
|
+
desc 'Apply the Blue manifest for this application'
|
8
|
+
task :apply_manifest, :except => { :no_release => true } do
|
9
|
+
current_host = capture("echo $CAPISTRANO:HOST$").strip.gsub('.', '_')
|
10
|
+
run "cd #{latest_release} && RAILS_ROOT=#{latest_release} RAILS_ENV=#{Blue.env} sudo shadow_puppet #{latest_release}/config/blue/boxes/#{Blue.env}/#{current_host}.rb"
|
11
|
+
end
|
12
|
+
|
13
|
+
task :verify_db do
|
14
|
+
run "cd #{latest_release} && RAILS_ENV=#{Blue.env} bundle exec rails runner 'ActiveRecord::Base.connection.execute %q!SELECT 1=1!'"
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
after 'deploy:migrate', 'blue:verify_db'
|
19
|
+
before 'bundle:install', 'blue:apply_manifest'
|
20
|
+
after "deploy:update", "deploy:cleanup"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
if Capistrano::Configuration.instance
|
27
|
+
Blue::Deploy.load(Capistrano::Configuration.instance)
|
28
|
+
end
|
29
|
+
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Blue
|
2
|
+
class Gems
|
3
|
+
def self.load(capistrano_config)
|
4
|
+
capistrano_config.load do
|
5
|
+
|
6
|
+
namespace :blue do
|
7
|
+
namespace :setup do
|
8
|
+
desc "Install required gems"
|
9
|
+
task :gems do
|
10
|
+
sudo "gem install bundler shadow_puppet --no-ri --no-rdoc"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
if Capistrano::Configuration.instance
|
20
|
+
Blue::Gems.load(Capistrano::Configuration.instance)
|
21
|
+
end
|
22
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
module Blue
|
2
|
+
class CapistranoIntegration
|
3
|
+
|
4
|
+
def self.load(capistrano_config)
|
5
|
+
capistrano_config.load do
|
6
|
+
|
7
|
+
set :ruby_version, Blue.config.ruby.major_version
|
8
|
+
set :ruby_patch, Blue.config.ruby.minor_version
|
9
|
+
|
10
|
+
set :application, Blue.config.application
|
11
|
+
set :repository, Blue.config.repository
|
12
|
+
set :scm, Blue.config.scm
|
13
|
+
set :user, Blue.config.user
|
14
|
+
|
15
|
+
set :keep_releases, Blue.config.keep_releases || 5
|
16
|
+
set :normalize_asset_timestamps, false
|
17
|
+
|
18
|
+
set :shared_children, %w(system log pids tmp)
|
19
|
+
|
20
|
+
Blue.boxes.each do |box|
|
21
|
+
server box.hostname, *box.roles, :primary => true # primary is a hack, shouldn't be here
|
22
|
+
end
|
23
|
+
|
24
|
+
namespace :blue do
|
25
|
+
desc "Display Blue Configuration"
|
26
|
+
task :config do
|
27
|
+
require 'pp'
|
28
|
+
pp Blue.config
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
if Capistrano::Configuration.instance
|
37
|
+
Blue::CapistranoIntegration.load(Capistrano::Configuration.instance)
|
38
|
+
end
|
39
|
+
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Blue
|
2
|
+
module LocalConfig
|
3
|
+
module CapistranoIntegration
|
4
|
+
|
5
|
+
def self.included(klass)
|
6
|
+
Blue.load_config!({
|
7
|
+
:local_config => []
|
8
|
+
})
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.load(capistrano_config)
|
12
|
+
capistrano_config.load do
|
13
|
+
|
14
|
+
set :local_config, Blue.config.local_config
|
15
|
+
|
16
|
+
namespace :local_config do
|
17
|
+
|
18
|
+
desc <<-DESC
|
19
|
+
Uploads local configuration files to the application's shared directory for \
|
20
|
+
later symlinking (if necessary). Called if local_config is set.
|
21
|
+
DESC
|
22
|
+
task :upload do
|
23
|
+
Blue.config.local_config.each do |file|
|
24
|
+
filename = File.basename(file)
|
25
|
+
path = File.dirname(file)
|
26
|
+
if File.exist?(file)
|
27
|
+
run "mkdir -p '#{shared_path}/#{path}'" unless path.empty?
|
28
|
+
parent.upload(file, "#{shared_path}/#{path}/#{filename}")
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
desc <<-DESC
|
34
|
+
Symlinks uploaded local configurations into the release directory.
|
35
|
+
DESC
|
36
|
+
task :symlink do
|
37
|
+
Blue.config.local_config.each do |file|
|
38
|
+
filename = File.basename(file)
|
39
|
+
path = File.dirname(file)
|
40
|
+
run "mkdir -p '#{latest_release}/#{path}'" unless path.empty?
|
41
|
+
run "ls #{latest_release}/#{file} 2> /dev/null || ln -nfs #{shared_path}/#{path}/#{filename} #{latest_release}/#{file}"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
after 'deploy:finalize_update' do
|
47
|
+
local_config.upload
|
48
|
+
local_config.symlink
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if Capistrano::Configuration.instance
|
57
|
+
Blue::LocalConfig::CapistranoIntegration.load(Capistrano::Configuration.instance)
|
58
|
+
end
|
59
|
+
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Blue
|
2
|
+
class Os
|
3
|
+
PACKAGES = %w(
|
4
|
+
g++ gcc make libc6-dev patch openssl ca-certificates libreadline6 \
|
5
|
+
libreadline6-dev curl zlib1g zlib1g-dev libssl-dev libyaml-dev \
|
6
|
+
libxml2-dev libxslt1-dev autoconf libc6-dev \
|
7
|
+
libgdbm-dev libncurses5-dev automake libtool bison pkg-config libffi-dev
|
8
|
+
)
|
9
|
+
|
10
|
+
def self.load(capistrano_config)
|
11
|
+
capistrano_config.load do
|
12
|
+
|
13
|
+
namespace :blue do
|
14
|
+
namespace :setup do
|
15
|
+
desc "Install required gems"
|
16
|
+
task :os do
|
17
|
+
sudo "apt-get install -y #{Blue::Os::PACKAGES.join(' ')}"
|
18
|
+
|
19
|
+
# Capistrano isn't smart enough to set this up correctly
|
20
|
+
path = "/u/apps/#{application}"
|
21
|
+
sudo "chown -R #{user} #{path}"
|
22
|
+
|
23
|
+
# Grab github's fingerprint
|
24
|
+
# Oh yea, this is dangerous
|
25
|
+
run "ssh -o StrictHostKeyChecking=no git@github.com || true"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
if Capistrano::Configuration.instance
|
35
|
+
Blue::Os.load(Capistrano::Configuration.instance)
|
36
|
+
end
|
37
|
+
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Blue
|
2
|
+
class Rails
|
3
|
+
def self.load(capistrano_config)
|
4
|
+
capistrano_config.load do
|
5
|
+
|
6
|
+
namespace :blue do
|
7
|
+
namespace :precompile do
|
8
|
+
desc "Precompile assets"
|
9
|
+
task :assets do
|
10
|
+
run "cd #{release_path} && RAILS_ENV=#{Blue.env} RAILS_GROUPS=assets bundle exec rake assets:precompile"
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
after 'blue:apply_manifest', 'deploy:migrate'
|
16
|
+
after 'deploy:migrate', 'blue:precompile:assets'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
if Capistrano::Configuration.instance
|
23
|
+
Blue::Rails.load(Capistrano::Configuration.instance)
|
24
|
+
end
|
25
|
+
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Blue
|
2
|
+
class RubyInstall
|
3
|
+
|
4
|
+
def self.load(capistrano_config)
|
5
|
+
capistrano_config.load do
|
6
|
+
|
7
|
+
namespace :blue do
|
8
|
+
namespace :setup do
|
9
|
+
desc "Install Ruby 1.9.3"
|
10
|
+
task :ruby do
|
11
|
+
version = "ruby-#{Blue.config.ruby.major_version}-p#{Blue.config.ruby.minor_version}"
|
12
|
+
|
13
|
+
cmd = [
|
14
|
+
'sudo apt-get install autoconf libyaml-dev -y || true',
|
15
|
+
'cd /tmp',
|
16
|
+
"sudo rm -rf #{version}* || true",
|
17
|
+
"wget -q http://ftp.ruby-lang.org/pub/ruby/#{version}.tar.gz",
|
18
|
+
"tar zxvf #{version}.tar.gz",
|
19
|
+
"cd /tmp/#{version}",
|
20
|
+
"./configure --prefix=/usr",
|
21
|
+
"make",
|
22
|
+
"sudo make install"
|
23
|
+
].join(' && ')
|
24
|
+
|
25
|
+
run "test -x /usr/bin/ruby && test #{Blue.config.ruby.major_version}p#{Blue.config.ruby.minor_version} = $(ruby --version | awk '{print $2}') || (#{cmd})"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
Blue.configure({
|
35
|
+
:ruby => {
|
36
|
+
:major_version => '1.9.3',
|
37
|
+
:minor_version => '429'
|
38
|
+
}
|
39
|
+
})
|
40
|
+
|
41
|
+
if Capistrano::Configuration.instance
|
42
|
+
Blue::RubyInstall.load(Capistrano::Configuration.instance)
|
43
|
+
end
|
44
|
+
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Blue
|
2
|
+
class Setup
|
3
|
+
def self.load(capistrano_config)
|
4
|
+
capistrano_config.load do
|
5
|
+
|
6
|
+
namespace :blue do
|
7
|
+
# This task should be idempotent
|
8
|
+
desc "Configures generic dependencies Blue depends on"
|
9
|
+
task :install, :roles => [:ruby] do
|
10
|
+
blue.setup.os
|
11
|
+
blue.setup.ruby
|
12
|
+
blue.setup.gems
|
13
|
+
end
|
14
|
+
end
|
15
|
+
after 'deploy:setup', 'blue:install'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
if Capistrano::Configuration.instance
|
22
|
+
Blue::Setup.load(Capistrano::Configuration.instance)
|
23
|
+
end
|
24
|
+
|
25
|
+
require 'capistrano/os'
|
26
|
+
require 'capistrano/ruby'
|
27
|
+
require 'capistrano/gems'
|
28
|
+
|
data/lib/tasks/blue.rake
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
namespace :blue do
|
2
|
+
desc "Move a basic set of configs into place"
|
3
|
+
task :setup do
|
4
|
+
puts "Copying configs into place inside your application..."
|
5
|
+
puts ""
|
6
|
+
|
7
|
+
gem_path = Bundler.load.specs.detect{|s| s.name == 'blue' }.try(:full_gem_path)
|
8
|
+
|
9
|
+
puts "cp config/blue.yml"
|
10
|
+
FileUtils.cp gem_path + "/templates/blue.yml", "config/blue.yml"
|
11
|
+
puts "cp Capfile"
|
12
|
+
FileUtils.cp gem_path + "/templates/Capfile", "Capfile"
|
13
|
+
puts "cp config/deploy.rb"
|
14
|
+
FileUtils.cp gem_path + "/templates/deploy.rb", "config/deploy.rb"
|
15
|
+
|
16
|
+
FileUtils.mkdir_p("config/blue/boxes/production")
|
17
|
+
puts "cp config/blue/boxes/production/some_hostname_com.rb"
|
18
|
+
FileUtils.cp gem_path + "/templates/box.rb", "config/blue/boxes/production/some_hostname_com.rb"
|
19
|
+
|
20
|
+
puts ""
|
21
|
+
puts "#####################################################################"
|
22
|
+
puts "## Great! All done adding some configs. ##"
|
23
|
+
puts "## Now go read config/blue/boxes/production/some_hostname_com.rb ##"
|
24
|
+
puts "#####################################################################"
|
25
|
+
puts ""
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
data/templates/Capfile
ADDED
data/templates/blue.yml
ADDED
data/templates/box.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'blue'
|
2
|
+
|
3
|
+
# This class/file represents a machine.
|
4
|
+
|
5
|
+
# Both the filename, and the class's name are relevant.
|
6
|
+
# Your server's hosname probably isn't some.hostname.com
|
7
|
+
# So, rename this file, and the classname below.
|
8
|
+
|
9
|
+
class SomeHostnameCom < Blue::Box
|
10
|
+
|
11
|
+
# Blue modules get included like so:
|
12
|
+
|
13
|
+
# include Blue::Redis
|
14
|
+
# include Blue::Monit
|
15
|
+
|
16
|
+
# That should really be all you need to do in here.
|
17
|
+
end
|
18
|
+
|
19
|
+
#
|
20
|
+
# Have multiple machines? I bet you do!
|
21
|
+
# Copy this file and change things accordingly.
|
22
|
+
#
|
23
|
+
|
data/templates/deploy.rb
ADDED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: blue
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Josh Sharpe
|
@@ -15,12 +15,54 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2013-05-
|
18
|
+
date: 2013-05-24 00:00:00 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: hashie
|
22
22
|
prerelease: false
|
23
23
|
requirement: &id001 !ruby/object:Gem::Requirement
|
24
|
+
none: false
|
25
|
+
requirements:
|
26
|
+
- - ">="
|
27
|
+
- !ruby/object:Gem::Version
|
28
|
+
hash: 3
|
29
|
+
segments:
|
30
|
+
- 0
|
31
|
+
version: "0"
|
32
|
+
type: :runtime
|
33
|
+
version_requirements: *id001
|
34
|
+
- !ruby/object:Gem::Dependency
|
35
|
+
name: shadow_puppet
|
36
|
+
prerelease: false
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ">="
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
hash: 3
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
version: "0"
|
46
|
+
type: :runtime
|
47
|
+
version_requirements: *id002
|
48
|
+
- !ruby/object:Gem::Dependency
|
49
|
+
name: capistrano
|
50
|
+
prerelease: false
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
hash: 3
|
57
|
+
segments:
|
58
|
+
- 0
|
59
|
+
version: "0"
|
60
|
+
type: :runtime
|
61
|
+
version_requirements: *id003
|
62
|
+
- !ruby/object:Gem::Dependency
|
63
|
+
name: bundler
|
64
|
+
prerelease: false
|
65
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
24
66
|
none: false
|
25
67
|
requirements:
|
26
68
|
- - ~>
|
@@ -31,11 +73,11 @@ dependencies:
|
|
31
73
|
- 3
|
32
74
|
version: "1.3"
|
33
75
|
type: :development
|
34
|
-
version_requirements: *
|
76
|
+
version_requirements: *id004
|
35
77
|
- !ruby/object:Gem::Dependency
|
36
78
|
name: rake
|
37
79
|
prerelease: false
|
38
|
-
requirement: &
|
80
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
39
81
|
none: false
|
40
82
|
requirements:
|
41
83
|
- - ">="
|
@@ -45,8 +87,8 @@ dependencies:
|
|
45
87
|
- 0
|
46
88
|
version: "0"
|
47
89
|
type: :development
|
48
|
-
version_requirements: *
|
49
|
-
description:
|
90
|
+
version_requirements: *id005
|
91
|
+
description: A deployment framework for rails apps
|
50
92
|
email:
|
51
93
|
- josh.m.sharpe@gmail.com
|
52
94
|
executables: []
|
@@ -58,12 +100,35 @@ extra_rdoc_files: []
|
|
58
100
|
files:
|
59
101
|
- .gitignore
|
60
102
|
- Gemfile
|
103
|
+
- ISSUES.md
|
61
104
|
- LICENSE.txt
|
62
105
|
- README.md
|
63
106
|
- Rakefile
|
64
107
|
- blue.gemspec
|
65
108
|
- lib/blue.rb
|
109
|
+
- lib/blue/abstract_manifest.rb
|
110
|
+
- lib/blue/box.rb
|
111
|
+
- lib/blue/config.rb
|
112
|
+
- lib/blue/database_config.rb
|
113
|
+
- lib/blue/deep_merge.rb
|
114
|
+
- lib/blue/plugins.rb
|
115
|
+
- lib/blue/plugins/ntpd.rb
|
116
|
+
- lib/blue/railtie.rb
|
117
|
+
- lib/blue/template.rb
|
66
118
|
- lib/blue/version.rb
|
119
|
+
- lib/capistrano/deploy.rb
|
120
|
+
- lib/capistrano/gems.rb
|
121
|
+
- lib/capistrano/integration.rb
|
122
|
+
- lib/capistrano/local_config.rb
|
123
|
+
- lib/capistrano/os.rb
|
124
|
+
- lib/capistrano/rails.rb
|
125
|
+
- lib/capistrano/ruby.rb
|
126
|
+
- lib/capistrano/setup.rb
|
127
|
+
- lib/tasks/blue.rake
|
128
|
+
- templates/Capfile
|
129
|
+
- templates/blue.yml
|
130
|
+
- templates/box.rb
|
131
|
+
- templates/deploy.rb
|
67
132
|
homepage: ""
|
68
133
|
licenses:
|
69
134
|
- MIT
|
@@ -93,10 +158,9 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
93
158
|
requirements: []
|
94
159
|
|
95
160
|
rubyforge_project:
|
96
|
-
rubygems_version: 1.8.
|
161
|
+
rubygems_version: 1.8.24
|
97
162
|
signing_key:
|
98
163
|
specification_version: 3
|
99
|
-
summary:
|
164
|
+
summary: Helps manage all aspects of your cloud infrastructure. Install services, deploy code, restart processes, monitor, etc...
|
100
165
|
test_files: []
|
101
166
|
|
102
|
-
has_rdoc:
|