gun 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +1 -0
- data/Rakefile +2 -0
- data/bin/.gun.swp +0 -0
- data/bin/gun +97 -0
- data/bin/gunify +179 -0
- data/gun.gemspec +23 -0
- data/lib/gun.rb +8 -0
- data/lib/gun/trigger.rb +14 -0
- data/lib/gun/version.rb +3 -0
- metadata +105 -0
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 matt
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Gun deployment gem barebones for now
|
data/Rakefile
ADDED
data/bin/.gun.swp
ADDED
Binary file
|
data/bin/gun
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'trollop'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
|
7
|
+
## Here's a program called "gun". We want this behavior:
|
8
|
+
##
|
9
|
+
## gun staging deploy => deploys code to staging
|
10
|
+
## gun production deploy => deploys to production
|
11
|
+
##
|
12
|
+
##
|
13
|
+
##
|
14
|
+
## There are some global options, which appear to the left of the subcommand.
|
15
|
+
## There are some subcommand options, which appear to the right.
|
16
|
+
##
|
17
|
+
## Subcommand options can be specific to the subcommand. 'staging' might take
|
18
|
+
## different options from 'production'.
|
19
|
+
##
|
20
|
+
## We do this by calling Trollop twice; one for the global options and once for
|
21
|
+
## the subcommand options. We need to tell Trollop what the subcommands are, so
|
22
|
+
## that it stops processing the global options when it encounters one of them.
|
23
|
+
|
24
|
+
SUB_COMMANDS = %w(staging production)
|
25
|
+
global_opts = Trollop::options do
|
26
|
+
banner "gun - simple trigger happy deployment"
|
27
|
+
#opt :dry_run, "Don't actually do anything", :short => "-n"
|
28
|
+
opt :staging, "Run a command on staging", :short => "-s"
|
29
|
+
opt :production, "Run a command on production", :short => "-p"
|
30
|
+
stop_on SUB_COMMANDS
|
31
|
+
end
|
32
|
+
|
33
|
+
##These are the default settings
|
34
|
+
machine = {
|
35
|
+
:location => 'nolocationselected',
|
36
|
+
:ssh_port => '22',
|
37
|
+
:ssh_user => 'root'
|
38
|
+
}
|
39
|
+
|
40
|
+
require File.join(Dir.pwd, 'lib/gun_trigger' )
|
41
|
+
|
42
|
+
cmd = ARGV.shift # get the command
|
43
|
+
sub_cmd = ARGV.shift # get the subcommand
|
44
|
+
cmd_opts = case cmd
|
45
|
+
when "staging" # parse delete options
|
46
|
+
Trollop::options do
|
47
|
+
opt :uname, "Check Kernel Version on staging server"
|
48
|
+
opt :deploy, "Deploy to staging server"
|
49
|
+
end
|
50
|
+
machine.merge!(GunTrigger::STAGING)
|
51
|
+
when "production" # parse delete options
|
52
|
+
Trollop::options do
|
53
|
+
opt :deploy, "Deploy to production server"
|
54
|
+
end
|
55
|
+
machine.merge!(GunTrigger::PRODUCTION)
|
56
|
+
else
|
57
|
+
usage =<<EOS
|
58
|
+
Usage:
|
59
|
+
gun [environment] [action]
|
60
|
+
where [environment] is:
|
61
|
+
staging
|
62
|
+
production
|
63
|
+
EOS
|
64
|
+
puts usage
|
65
|
+
Trollop::die "Unknown environment"
|
66
|
+
#Error unknown command"
|
67
|
+
#Trollop::options do
|
68
|
+
# opt :deploy, "Deploy to production server"
|
69
|
+
#end
|
70
|
+
end
|
71
|
+
|
72
|
+
gt = GunTrigger.new(machine)
|
73
|
+
|
74
|
+
sub_cmd_opts = case sub_cmd
|
75
|
+
when "uname"
|
76
|
+
puts 'Calling uname for ' + cmd
|
77
|
+
gt.uname
|
78
|
+
when "deploy"
|
79
|
+
puts 'Doing deployment for ' + cmd
|
80
|
+
gt.deploy
|
81
|
+
else
|
82
|
+
usage = ''
|
83
|
+
usage =<<EOS
|
84
|
+
Usage:
|
85
|
+
gun #{cmd} [action]
|
86
|
+
where [action] is:
|
87
|
+
deploy
|
88
|
+
uname
|
89
|
+
EOS
|
90
|
+
puts usage
|
91
|
+
end
|
92
|
+
|
93
|
+
#puts "Global options: #{global_opts.inspect}"
|
94
|
+
#puts "Subcommand: #{cmd.inspect}"
|
95
|
+
#puts "Subcommand options: #{cmd_opts.inspect}"
|
96
|
+
#puts "Remaining arguments: #{ARGV.inspect}"
|
97
|
+
|
data/bin/gunify
ADDED
@@ -0,0 +1,179 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require 'fileutils'
|
5
|
+
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
opts.banner = "Usage: #{File.basename($0)} [path]"
|
8
|
+
|
9
|
+
opts.on("-h", "--help", "Displays this help info") do
|
10
|
+
puts opts
|
11
|
+
exit 0
|
12
|
+
end
|
13
|
+
|
14
|
+
begin
|
15
|
+
opts.parse!(ARGV)
|
16
|
+
rescue OptionParser::ParseError => e
|
17
|
+
warn e.message
|
18
|
+
puts opts
|
19
|
+
exit 1
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if ARGV.empty?
|
24
|
+
abort "Please specify the directory to gunify, e.g. `#{File.basename($0)} .'"
|
25
|
+
elsif !File.exists?(ARGV.first)
|
26
|
+
abort "`#{ARGV.first}' does not exist."
|
27
|
+
elsif !File.directory?(ARGV.first)
|
28
|
+
abort "`#{ARGV.first}' is not a directory."
|
29
|
+
elsif ARGV.length > 1
|
30
|
+
abort "Too many arguments; please specify only the directory to capify."
|
31
|
+
end
|
32
|
+
|
33
|
+
def unindent(string)
|
34
|
+
indentation = string[/\A\s*/]
|
35
|
+
string.strip.gsub(/^#{indentation}/, "")
|
36
|
+
end
|
37
|
+
|
38
|
+
files = {
|
39
|
+
"lib/gun_trigger.rb" => <<-FILE
|
40
|
+
require 'rye'
|
41
|
+
require 'fileutils'
|
42
|
+
|
43
|
+
|
44
|
+
class GunTrigger
|
45
|
+
|
46
|
+
STAGING = {
|
47
|
+
:project_name => 'thedepot',
|
48
|
+
:location => 'testthedepot.com',
|
49
|
+
:ssh_port => '2203',
|
50
|
+
:ssh_user => 'root',
|
51
|
+
:repository => "httpdocs/thedepot",
|
52
|
+
:local_checkout_directory => '/tmp',
|
53
|
+
:remote_release_directory => '/http/thedepot',
|
54
|
+
:remote_codebase_directory => '/usr/local/src/thedepot',
|
55
|
+
:public_folder_owner => 'dude:whiterussia',
|
56
|
+
:rails_root_owner => 'dude:whiterussia',
|
57
|
+
:product_images_folder => "public/images/products",
|
58
|
+
:remote_product_image_folder => "/var/www/vhosts/thedepto/public/images",
|
59
|
+
:db_file => "database.staging.yml"
|
60
|
+
}
|
61
|
+
|
62
|
+
PRODUCTION = {
|
63
|
+
:location => 'thedpot.com'
|
64
|
+
}
|
65
|
+
|
66
|
+
def initialize(machine)
|
67
|
+
@machine = machine
|
68
|
+
end
|
69
|
+
|
70
|
+
def uname
|
71
|
+
puts '+++Running uname'
|
72
|
+
lbox = Rye::Box.new( @machine[:location], { :port => @machine[:ssh_port], :user => @machine[:ssh_user]} )
|
73
|
+
puts lbox.uname(:a)
|
74
|
+
end
|
75
|
+
|
76
|
+
def deploy
|
77
|
+
puts '+++ Deploying to ' + @machine[:location]
|
78
|
+
#Rye::Cmd.add_command :
|
79
|
+
lbox = Rye::Box.new( @machine[:location], { :port => @machine[:ssh_port], :user => @machine[:ssh_user]} )
|
80
|
+
release_date = Time.now.strftime("%Y%m%d%H%M%S")
|
81
|
+
puts '+++ Creating folder ' + release_date
|
82
|
+
checkout_code( @machine[:local_checkout_directory], release_date )
|
83
|
+
puts "+++ Running copy"
|
84
|
+
copy_code( lbox, release_date )
|
85
|
+
#do mysql related stuff here
|
86
|
+
run_bundler(lbox, release_date)
|
87
|
+
run_migrations(lbox, release_date)
|
88
|
+
link_to_current_codebase(lbox, release_date)
|
89
|
+
set_permissions(lbox, release_date)
|
90
|
+
restart_webserver(lbox)
|
91
|
+
end
|
92
|
+
|
93
|
+
def set_permissions(box, release_date)
|
94
|
+
box.chown "-R", @machine[:rails_root_owner], File.join(@machine[:remote_codebase_directory], release_date )
|
95
|
+
box.chown "-R", @machine[:public_folder_owner], File.join(@machine[:remote_codebase_directory], release_date, "public" )
|
96
|
+
box.chown "-R", @machine[:rails_root_owner], File.join(@machine[:remote_codebase_directory], "current")
|
97
|
+
box.chown "-R", @machine[:public_folder_owner], File.join(@machine[:remote_codebase_directory], "current", "public" )
|
98
|
+
end
|
99
|
+
|
100
|
+
def run_migrations(box, release_date)
|
101
|
+
puts box.mv File.join(@machine[:remote_codebase_directory], release_date, "config", @machine[:db_file]), File.join(@machine[:remote_codebase_directory], release_date, "config", 'database.yml')
|
102
|
+
puts box.rake "-f", File.join(@machine[:remote_codebase_directory], release_date, "Rakefile"), "db:migrate", "RAILS_ENV=production"
|
103
|
+
end
|
104
|
+
|
105
|
+
def run_bundler(box, release_date)
|
106
|
+
box.disable_safe_mode
|
107
|
+
cmd = "cd " + File.join(@machine[:remote_codebase_directory], release_date) + "; " + 'bundle install'
|
108
|
+
puts "+++ Running " + cmd
|
109
|
+
puts box.execute cmd
|
110
|
+
box.enable_safe_mode
|
111
|
+
end
|
112
|
+
|
113
|
+
def link_to_current_codebase(box, release_date)
|
114
|
+
box.disable_safe_mode
|
115
|
+
puts "+++ Running rm -f " + File.join(@machine[:remote_codebase_directory], "current")
|
116
|
+
puts box.rm '-f', File.join(@machine[:remote_codebase_directory], "current")
|
117
|
+
puts "+++ Running ln -s " + File.join(@machine[:remote_codebase_directory], release_date) + " " + File.join(@machine[:remote_codebase_directory], "current")
|
118
|
+
puts box.ln "-s", File.join(@machine[:remote_codebase_directory], release_date), File.join(@machine[:remote_codebase_directory], "current")
|
119
|
+
remote_images_dest_folder = File.join(@machine[:remote_codebase_directory], "current", @machine[:product_images_folder])
|
120
|
+
puts "+++ Running rm -fr " + remote_images_dest_folder
|
121
|
+
puts box.rm '-fr', remote_images_dest_folder
|
122
|
+
box.enable_safe_mode
|
123
|
+
puts "+++ Running ln -s " + @machine[:remote_product_image_folder] + " " + remote_images_dest_folder
|
124
|
+
puts box.ln "-s", @machine[:remote_product_image_folder], remote_images_dest_folder
|
125
|
+
end
|
126
|
+
|
127
|
+
def restart_webserver(box)
|
128
|
+
box.disable_safe_mode
|
129
|
+
puts box.execute "service httpd restart"
|
130
|
+
box.enable_safe_mode
|
131
|
+
end
|
132
|
+
|
133
|
+
def copy_code( box, release_date )
|
134
|
+
#tarball the code
|
135
|
+
cmd = "cd " + @machine[:local_checkout_directory] + "; tar czvf " + @machine[:project_name] + ".tar.gz " + "./" + release_date
|
136
|
+
puts '+++ running ' + cmd
|
137
|
+
system(cmd)
|
138
|
+
#copy code
|
139
|
+
puts '+++ running file upload ' + File.join(@machine[:local_checkout_directory], @machine[:project_name] + '.tar.gz') + ' to ' + File.join(@machine[:remote_codebase_directory], @machine[:project_name] + ".tar.gz")
|
140
|
+
box.file_upload File.join(@machine[:local_checkout_directory], @machine[:project_name] + '.tar.gz'), File.join(@machine[:remote_codebase_directory], @machine[:project_name] + ".tar.gz")
|
141
|
+
#unzip code
|
142
|
+
puts "+++ running tar -xzv " + File.join(@machine[:remote_codebase_directory], @machine[:project_name] + '.tar.gz')
|
143
|
+
#box.run_command "tar -xzvf " + File.join(@machine[:remote_codebase_directory], @machine[:project_name] + '.tar.gz')
|
144
|
+
box.cd @machine[:remote_codebase_directory]
|
145
|
+
puts box.tar "-xzvf", File.join(@machine[:remote_codebase_directory], @machine[:project_name] + '.tar.gz')
|
146
|
+
end
|
147
|
+
|
148
|
+
def checkout_code(rlocation, sfolder)
|
149
|
+
FileUtils.mkdir( rlocation + '/' + sfolder )
|
150
|
+
cmd = "cd " + rlocation + ";cvs checkout -d ./" + sfolder + " " + @machine[:repository]
|
151
|
+
puts "+++ Running " + cmd
|
152
|
+
system(cmd)
|
153
|
+
end
|
154
|
+
|
155
|
+
def rollback
|
156
|
+
end
|
157
|
+
end
|
158
|
+
FILE
|
159
|
+
}
|
160
|
+
|
161
|
+
base = ARGV.shift
|
162
|
+
files.each do |file, content|
|
163
|
+
file = File.join(base, file)
|
164
|
+
if File.exists?(file)
|
165
|
+
warn "[skip] '#{file}' already exists"
|
166
|
+
elsif File.exists?(file.downcase)
|
167
|
+
warn "[skip] '#{file.downcase}' exists, which could conflict with `#{file}'"
|
168
|
+
else
|
169
|
+
unless File.exists?(File.dirname(file))
|
170
|
+
puts "[add] making directory '#{File.dirname(file)}'"
|
171
|
+
FileUtils.mkdir(File.dirname(file))
|
172
|
+
end
|
173
|
+
puts "[add] writing '#{file}'"
|
174
|
+
File.open(file, "w") { |f| f.write(content) }
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
puts "[done] gunified!"
|
179
|
+
|
data/gun.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/gun/version', __FILE__)
|
3
|
+
Gem::Specification.new do |gem|
|
4
|
+
gem.authors = ["Matt Carr"]
|
5
|
+
gem.email = ["bikokid@gmail.com"]
|
6
|
+
|
7
|
+
gem.files = `git ls-files`.split($\)
|
8
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
9
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
10
|
+
gem.name = 'gun'
|
11
|
+
gem.require_paths = ["lib"]
|
12
|
+
gem.version = Gun::VERSION
|
13
|
+
|
14
|
+
gem.requirements = "Gun requires trollop, and rye gems to run."
|
15
|
+
|
16
|
+
gem.add_dependency("trollop")
|
17
|
+
gem.add_dependency("rye")
|
18
|
+
|
19
|
+
gem.date = '2012-08-19'
|
20
|
+
gem.summary = "Gun for deployment"
|
21
|
+
gem.description = "Deploy your applications with the simple pull of a trigger"
|
22
|
+
gem.homepage = 'http://rubygems.org/gems/gun'
|
23
|
+
end
|
data/lib/gun.rb
ADDED
data/lib/gun/trigger.rb
ADDED
data/lib/gun/version.rb
ADDED
metadata
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gun
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Matt Carr
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2012-08-19 00:00:00 Z
|
19
|
+
dependencies:
|
20
|
+
- !ruby/object:Gem::Dependency
|
21
|
+
name: trollop
|
22
|
+
prerelease: false
|
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: rye
|
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
|
+
description: Deploy your applications with the simple pull of a trigger
|
49
|
+
email:
|
50
|
+
- bikokid@gmail.com
|
51
|
+
executables:
|
52
|
+
- .gun.swp
|
53
|
+
- gun
|
54
|
+
- gunify
|
55
|
+
extensions: []
|
56
|
+
|
57
|
+
extra_rdoc_files: []
|
58
|
+
|
59
|
+
files:
|
60
|
+
- Gemfile
|
61
|
+
- LICENSE
|
62
|
+
- README.md
|
63
|
+
- Rakefile
|
64
|
+
- bin/.gun.swp
|
65
|
+
- bin/gun
|
66
|
+
- bin/gunify
|
67
|
+
- gun.gemspec
|
68
|
+
- lib/gun.rb
|
69
|
+
- lib/gun/trigger.rb
|
70
|
+
- lib/gun/version.rb
|
71
|
+
homepage: http://rubygems.org/gems/gun
|
72
|
+
licenses: []
|
73
|
+
|
74
|
+
post_install_message:
|
75
|
+
rdoc_options: []
|
76
|
+
|
77
|
+
require_paths:
|
78
|
+
- lib
|
79
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
81
|
+
requirements:
|
82
|
+
- - ">="
|
83
|
+
- !ruby/object:Gem::Version
|
84
|
+
hash: 3
|
85
|
+
segments:
|
86
|
+
- 0
|
87
|
+
version: "0"
|
88
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
89
|
+
none: false
|
90
|
+
requirements:
|
91
|
+
- - ">="
|
92
|
+
- !ruby/object:Gem::Version
|
93
|
+
hash: 3
|
94
|
+
segments:
|
95
|
+
- 0
|
96
|
+
version: "0"
|
97
|
+
requirements:
|
98
|
+
- Gun requires trollop, and rye gems to run.
|
99
|
+
rubyforge_project:
|
100
|
+
rubygems_version: 1.8.24
|
101
|
+
signing_key:
|
102
|
+
specification_version: 3
|
103
|
+
summary: Gun for deployment
|
104
|
+
test_files: []
|
105
|
+
|