blue 0.0.1 → 0.0.2
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 +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:
|