rigup 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/Gemfile +2 -0
- data/README.md +1 -0
- data/Rakefile +6 -0
- data/bin/rigup +5 -0
- data/example deploy.thor +32 -0
- data/lib/rigup/cli.rb +159 -0
- data/lib/rigup/config.rb +22 -0
- data/lib/rigup/context.rb +59 -0
- data/lib/rigup/deploy_base.rb +33 -0
- data/lib/rigup/git_repo.rb +148 -0
- data/lib/rigup/install_utils.rb +94 -0
- data/lib/rigup/runability.rb +32 -0
- data/lib/rigup/svn.rb +80 -0
- data/lib/rigup/version.rb +3 -0
- data/lib/rigup.rb +14 -0
- data/notes.txt +19 -0
- data/rigup.gemspec +47 -0
- data/rigup.iml +28 -0
- data/spec/new_spec.rb +94 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/spec_utils.rb +0 -0
- metadata +167 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 074cf53541cc8dda276109cd786eed5e4c013455
|
4
|
+
data.tar.gz: ba808e6dd94614a4f0cc179fe3dccd29f1c1f517
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: d9ab780149ca55a6dca8bf1067bd723c00c532219e39196bcd8b5429c556a0bbccb790230c504c5fad0d638db0eb773436853df67dd5738d5b55f91dbd774127
|
7
|
+
data.tar.gz: a28e3901c130731e5792aa0683d11ec45534bd39840f4e4883b3861a88c33b545418c8cd2a4f1e711bbadb12f493181fc0fb227347f2375ca2376176f1be3876
|
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Toolset for deployment
|
data/Rakefile
ADDED
data/bin/rigup
ADDED
data/example deploy.thor
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
require 'rigup'
|
2
|
+
|
3
|
+
# This file will be called deploy.thor and lives in the root of the project repositiory, so it is version controlled
|
4
|
+
# and can be freely modified to suit the project requirements
|
5
|
+
class Deploy < Rigup::DeployBase # from gem, sets context and loads rigup.yml into config from site_dir
|
6
|
+
|
7
|
+
# You are free to modify these two tasks to suit your requirements
|
8
|
+
|
9
|
+
desc 'install','install the freshly delivered files'
|
10
|
+
def install
|
11
|
+
|
12
|
+
# select_suffixed_file("/config/database.yml")
|
13
|
+
# select_suffixed_file("/yore.config.xml")
|
14
|
+
# select_suffixed_file("/config/app_config.xml")
|
15
|
+
# select_suffixed_file("/system/apache.site")
|
16
|
+
#make_public_cache_dir("/public/cache")
|
17
|
+
|
18
|
+
# ensure_link("/log","/log")
|
19
|
+
# ensure_link("/pids","/tmp/pids")
|
20
|
+
# ensure_link("/uploads","/tmp/uploads")
|
21
|
+
# ensure_link("/system","/public/system")
|
22
|
+
|
23
|
+
#run "touch /log/production.log && chown : /log/production.log && chmod 666 /log/production.log"
|
24
|
+
end
|
25
|
+
|
26
|
+
desc 'restart','restart the web server'
|
27
|
+
def restart
|
28
|
+
# run "touch " + File.join("current/tmp/restart.txt",@site_dir) # && chown user:group current/tmp/restart.txt"
|
29
|
+
# run "/etc/init.d/apache2 restart --force-reload"
|
30
|
+
end
|
31
|
+
|
32
|
+
end
|
data/lib/rigup/cli.rb
ADDED
@@ -0,0 +1,159 @@
|
|
1
|
+
module Rigup
|
2
|
+
class Cli < Thor
|
3
|
+
|
4
|
+
include Rigup::Runability
|
5
|
+
include Rigup::InstallUtils
|
6
|
+
|
7
|
+
attr_reader :context, :release_path
|
8
|
+
|
9
|
+
no_commands do
|
10
|
+
|
11
|
+
def init(aPath=nil,aConfig={})
|
12
|
+
return if @initialised
|
13
|
+
@initialised = true
|
14
|
+
aPath ||= aConfig[:site_dir] || Dir.pwd
|
15
|
+
@site_dir = Buzztools::File.real_path(aPath) rescue File.expand_path(aPath)
|
16
|
+
@releases_path = File.join(@site_dir,'releases')
|
17
|
+
if File.exists?(f=File.join(@site_dir,'rigup.yml'))
|
18
|
+
file_config = YAML.load(String.from_file(f))
|
19
|
+
aConfig.merge!(file_config)
|
20
|
+
end
|
21
|
+
config = Rigup::Config.new(aConfig.merge(site_dir: @site_dir))
|
22
|
+
@context = Rigup::Context.new(
|
23
|
+
config: config,
|
24
|
+
logger: ::Logger.new(STDOUT),
|
25
|
+
pwd: Dir.pwd
|
26
|
+
)
|
27
|
+
end
|
28
|
+
|
29
|
+
def site_dir
|
30
|
+
@site_dir
|
31
|
+
end
|
32
|
+
|
33
|
+
def cache_dir
|
34
|
+
File.join(@site_dir,'shared','cached-copy')
|
35
|
+
end
|
36
|
+
|
37
|
+
def config
|
38
|
+
@context.config
|
39
|
+
end
|
40
|
+
|
41
|
+
def repo
|
42
|
+
@repo ||= GitRepo.new(@context)
|
43
|
+
end
|
44
|
+
|
45
|
+
# Prepares repo in cache dir for site
|
46
|
+
# requires params: repo_url,site
|
47
|
+
def prepare_cache # {:url=>'git://github.com/ddssda', :branch=>'master', :commit=>'ad452bcd'}
|
48
|
+
url = config[:git_url]
|
49
|
+
wd = cache_dir
|
50
|
+
|
51
|
+
suitable = if File.exists?(wd)
|
52
|
+
repo.open wd
|
53
|
+
repo.origin.url==url
|
54
|
+
else
|
55
|
+
false
|
56
|
+
end
|
57
|
+
|
58
|
+
if suitable
|
59
|
+
repo.fetch
|
60
|
+
else
|
61
|
+
if File.exists? wd
|
62
|
+
#raise RuntimeError.new('almost did bad delete') if !@core.cache_dir || @core.cache_dir.length<3 || !wd.begins_with?(@core.cache_dir)
|
63
|
+
FileUtils.rm_rf wd
|
64
|
+
end
|
65
|
+
repo.clone(url, wd)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
# Switches @repo to given branch and/or commit
|
70
|
+
# Should call prepare_cache first to create @repo
|
71
|
+
# requires params: branch and/or commit
|
72
|
+
def checkout_branch_commit
|
73
|
+
branch = config[:branch] || 'master'
|
74
|
+
commit = config[:commit]
|
75
|
+
repo.open(cache_dir)
|
76
|
+
repo.checkout(commit,branch)
|
77
|
+
#perhaps use reset --hard here
|
78
|
+
if (commit)
|
79
|
+
repo.merge(commit,['--ff-only'])
|
80
|
+
else
|
81
|
+
repo.merge('origin/'+branch,['--ff-only'])
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def update_cache(aPath=nil)
|
86
|
+
prepare_cache
|
87
|
+
checkout_branch_commit
|
88
|
+
end
|
89
|
+
|
90
|
+
def release
|
91
|
+
release = Time.now.strftime('%Y%m%d%H%M%S')
|
92
|
+
@release_path = File.expand_path(release,@releases_path)
|
93
|
+
repo.open(cache_dir)
|
94
|
+
repo.export(@release_path)
|
95
|
+
release_config = context.config.to_hash
|
96
|
+
release_config[:commit] = repo.head.sha
|
97
|
+
release_config[:branch] = repo.branch
|
98
|
+
release_config.to_yaml.to_file(File.join(@release_path,'rigup.yml'))
|
99
|
+
return @release_path
|
100
|
+
end
|
101
|
+
|
102
|
+
def link_live
|
103
|
+
ensure_link(@release_path,File.expand_path(File.join(site_dir,'current')))
|
104
|
+
end
|
105
|
+
|
106
|
+
def cleanup
|
107
|
+
@releases = run("ls -x #{@releases_path}").split.sort
|
108
|
+
count = (@keep_releases || 3).to_i
|
109
|
+
if count >= @releases.length
|
110
|
+
@context.logger.info "no old releases to clean up"
|
111
|
+
else
|
112
|
+
@context.logger.info "keeping #{count} of #{@releases.length} deployed releases"
|
113
|
+
|
114
|
+
directories = (@releases - @releases.last(count)).map { |r|
|
115
|
+
File.join(@releases_path, r)
|
116
|
+
}.join(" ")
|
117
|
+
|
118
|
+
run "rm -rf #{directories}"
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def call_release_command(aCommand)
|
123
|
+
return unless cmdline = config["#{aCommand}_command".to_sym].to_s.strip.to_nil
|
124
|
+
run cmdline, @release_path
|
125
|
+
end
|
126
|
+
|
127
|
+
end
|
128
|
+
|
129
|
+
public
|
130
|
+
|
131
|
+
desc "new GIT_URL [PATH]", "setup new site"
|
132
|
+
def new(aGitUrl,aPath=nil)
|
133
|
+
aPath ||= File.basename(aGitUrl,'.git')
|
134
|
+
init(
|
135
|
+
aPath,
|
136
|
+
git_url: aGitUrl
|
137
|
+
)
|
138
|
+
FileUtils.mkdir_p(site_dir)
|
139
|
+
FileUtils.mkdir_p(File.join(site_dir,'releases'))
|
140
|
+
FileUtils.mkdir_p(File.join(site_dir,'shared'))
|
141
|
+
|
142
|
+
#+ create rigup.yml if doesn't exist, including option values
|
143
|
+
context.config.to_hash.filter_exclude(:site_dir).to_yaml.to_file(File.join(site_dir,'rigup.yml'))
|
144
|
+
end
|
145
|
+
|
146
|
+
desc "deploy [PATH]", "deploy the given site"
|
147
|
+
def deploy(aPath=nil)
|
148
|
+
init(aPath)
|
149
|
+
update_cache
|
150
|
+
release
|
151
|
+
call_release_command(:install) # call install_command if defined eg. defaults to "thor deploy:install" eg. make changes to files
|
152
|
+
call_release_command(:block)
|
153
|
+
link_live
|
154
|
+
call_release_command(:restart) # call restart_command, defaults to "thor deploy:restart" eg. restart passenger
|
155
|
+
call_release_command(:unblock)
|
156
|
+
cleanup
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
data/lib/rigup/config.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Rigup
|
2
|
+
|
3
|
+
class Config < Buzztools::Config
|
4
|
+
|
5
|
+
DEFAULTS = {
|
6
|
+
site_dir: String,
|
7
|
+
git_url: String,
|
8
|
+
branch: String,
|
9
|
+
commit: String,
|
10
|
+
stage: 'live', # or 'staging' or 'development'
|
11
|
+
block_command: nil,
|
12
|
+
install_command: 'thor deploy:install',
|
13
|
+
restart_command: 'thor deploy:restart',
|
14
|
+
unblock_command: nil,
|
15
|
+
}
|
16
|
+
|
17
|
+
def initialize(aValues=nil)
|
18
|
+
super(DEFAULTS,aValues)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module Rigup
|
2
|
+
class Context
|
3
|
+
|
4
|
+
attr_reader :config, :options, :argv, :env, :stdout, :stdin, :stderr, :key_chain, :credentials, :logger, :pwd, :variant
|
5
|
+
attr_writer :pwd
|
6
|
+
|
7
|
+
def sudo
|
8
|
+
''
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(aValues=nil)
|
12
|
+
return if !aValues
|
13
|
+
|
14
|
+
#is_client = !!(aValues[:key_chain] || aValues[:global_options] || aValues[:options])
|
15
|
+
@config = aValues[:config]
|
16
|
+
@pwd = Buzztools::File.real_path(aValues[:pwd] || (@config && @config[:folder]) || Dir.pwd)
|
17
|
+
@options = aValues[:options]
|
18
|
+
@argv = aValues[:argv]
|
19
|
+
@env = aValues[:env]
|
20
|
+
@stdout = aValues[:stdout]
|
21
|
+
@stdin = aValues[:stdin]
|
22
|
+
@stderr = aValues[:stderr]
|
23
|
+
@key_chain = aValues[:key_chain]
|
24
|
+
@credentials = aValues[:credentials]
|
25
|
+
@logger = aValues[:logger]
|
26
|
+
@variant = aValues[:variant]
|
27
|
+
end
|
28
|
+
|
29
|
+
def git_root
|
30
|
+
@git_root ||= find_git_root
|
31
|
+
end
|
32
|
+
|
33
|
+
# http://thinkingdigitally.com/archive/capturing-output-from-puts-in-ruby/
|
34
|
+
#class SimpleSemParserTest < Test::Unit::TestCase
|
35
|
+
# def test_set_stmt_write
|
36
|
+
# out = capture_stdout do
|
37
|
+
# parser = SimpleSemParser.new
|
38
|
+
# parser.parse('set write, "Hello World!"').execute
|
39
|
+
# end
|
40
|
+
# assert_equal "Hello World!\n", out.string
|
41
|
+
# end
|
42
|
+
#end
|
43
|
+
def capture_stdout
|
44
|
+
stdout_before = @stdout
|
45
|
+
out = StringIO.new
|
46
|
+
@stdout = out
|
47
|
+
yield
|
48
|
+
return out.string
|
49
|
+
ensure
|
50
|
+
@stdout = stdout_before
|
51
|
+
end
|
52
|
+
|
53
|
+
def find_git_root
|
54
|
+
git_folder = BuzzTools::File.find_upwards(@pwd,'.git')
|
55
|
+
return git_folder && git_folder.chomp('/.git')
|
56
|
+
end
|
57
|
+
|
58
|
+
end
|
59
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
module Rigup
|
2
|
+
|
3
|
+
class DeployBase < Thor
|
4
|
+
|
5
|
+
include Rigup::Runability
|
6
|
+
include Rigup::InstallUtils
|
7
|
+
|
8
|
+
no_commands do
|
9
|
+
def initialize(*args)
|
10
|
+
super
|
11
|
+
@release_path = Dir.pwd
|
12
|
+
@site_dir = File.expand_path('../..')
|
13
|
+
@shared_path = File.expand_path('shared',@site_dir)
|
14
|
+
config = {}
|
15
|
+
if File.exists?(f=File.join(@release_path,'rigup.yml'))
|
16
|
+
file_config = YAML.load(String.from_file(f))
|
17
|
+
config.merge!(file_config)
|
18
|
+
end
|
19
|
+
@context = Rigup::Context.new(
|
20
|
+
config: Rigup::Config.new(config),
|
21
|
+
logger: ::Logger.new(STDOUT),
|
22
|
+
pwd: Dir.pwd,
|
23
|
+
)
|
24
|
+
end
|
25
|
+
|
26
|
+
def config
|
27
|
+
@context.config
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
require 'git'
|
2
|
+
|
3
|
+
module Rigup
|
4
|
+
class GitRepo
|
5
|
+
|
6
|
+
include Rigup::Runability
|
7
|
+
|
8
|
+
attr_reader :git,:configured
|
9
|
+
|
10
|
+
GIT_METHODS = [:commit,:add,:reset_hard,:path,:clone,:log,:size,:branches,:status,:remotes,:pull,:fetch,:push,:merge]
|
11
|
+
|
12
|
+
def initialize(aContext=nil)
|
13
|
+
@context = (aContext || Rigup::Context.new)
|
14
|
+
end
|
15
|
+
|
16
|
+
def method_missing(sym, *args, &block)
|
17
|
+
if @git && GIT_METHODS.include?(sym)
|
18
|
+
@git.send sym, *args, &block
|
19
|
+
else
|
20
|
+
super
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def open(aPath)
|
25
|
+
@git = ::Git.open(aPath)
|
26
|
+
end
|
27
|
+
|
28
|
+
def init(*args)
|
29
|
+
@git = ::Git.init(*args)
|
30
|
+
end
|
31
|
+
|
32
|
+
def clone(aUrl,aPath)
|
33
|
+
@git = ::Git::clone(aUrl,aPath)
|
34
|
+
end
|
35
|
+
|
36
|
+
def open?
|
37
|
+
!!@git
|
38
|
+
end
|
39
|
+
|
40
|
+
def empty?
|
41
|
+
!@git.branches[0]
|
42
|
+
end
|
43
|
+
|
44
|
+
def status
|
45
|
+
result = @git.lib.command_lines('status',['--porcelain'])
|
46
|
+
result
|
47
|
+
end
|
48
|
+
|
49
|
+
def changes?
|
50
|
+
raise RuntimeError.new('Repository must be open') unless open?
|
51
|
+
status.length > 0
|
52
|
+
end
|
53
|
+
|
54
|
+
def commit_all(*args)
|
55
|
+
result = begin
|
56
|
+
@git.commit_all(*args)
|
57
|
+
rescue ::Git::GitExecuteError => e
|
58
|
+
if e.message.index("nothing to commit (working directory clean)")
|
59
|
+
nil
|
60
|
+
else
|
61
|
+
raise e
|
62
|
+
end
|
63
|
+
end
|
64
|
+
result = commitFromString(result)
|
65
|
+
result
|
66
|
+
end
|
67
|
+
|
68
|
+
# "[master (root-commit) 6bdd9e1] first commit 1 files changed, 1 insertions(+), 0 deletions(-) create mode 100644 file1.txt"
|
69
|
+
def commitFromString(aString)
|
70
|
+
return nil if !aString || aString.empty?
|
71
|
+
sha = aString.scan(/ ([a-f0-9]+)\]/).flatten.first
|
72
|
+
@git.gcommit(sha)
|
73
|
+
end
|
74
|
+
|
75
|
+
def path
|
76
|
+
@git.dir.path
|
77
|
+
end
|
78
|
+
|
79
|
+
def origin
|
80
|
+
@git.remotes.find {|r| r.name=='origin'}
|
81
|
+
end
|
82
|
+
|
83
|
+
def url
|
84
|
+
(o = origin) && o.url
|
85
|
+
end
|
86
|
+
|
87
|
+
def checkout(commit=nil,branch=nil)
|
88
|
+
specific_commit = !!commit && !commit.index('HEAD')
|
89
|
+
if specific_commit
|
90
|
+
@git.checkout commit
|
91
|
+
else
|
92
|
+
branch ||= 'master'
|
93
|
+
@git.checkout(branch)
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
# http://stackoverflow.com/questions/2866358/git-checkout-only-files-without-repository
|
98
|
+
# http://www.clientcide.com/best-practices/exporting-files-from-git-similar-to-svn-export/
|
99
|
+
def export(aDest)
|
100
|
+
#rsync --exclude=.git /source/directory/ user@remote-server.com:/target-directory
|
101
|
+
FileUtils.cp_r(path,aDest)
|
102
|
+
FileUtils.rm_rf(File.expand_path('.git',aDest))
|
103
|
+
end
|
104
|
+
|
105
|
+
def branch
|
106
|
+
@git.current_branch
|
107
|
+
end
|
108
|
+
|
109
|
+
def sha
|
110
|
+
head.sha
|
111
|
+
end
|
112
|
+
|
113
|
+
def head
|
114
|
+
@git.log.first
|
115
|
+
end
|
116
|
+
|
117
|
+
# ::Git --no-pager diff --name-status 26bb87c3981 191d64820f2b
|
118
|
+
# result is array of paths prefixed with status letter then a tab
|
119
|
+
# see http://git-scm.com/docs/git-diff under --diff-filter=
|
120
|
+
# Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T)
|
121
|
+
def changesBetweenCommits(aFromCommit, aToCommit)
|
122
|
+
@git.lib.command_lines('diff',['--name-status',aFromCommit,aToCommit])
|
123
|
+
end
|
124
|
+
|
125
|
+
# Added (A), Copied (C), Deleted (D), Modified (M), Renamed (R), have their type (i.e. regular file, symlink, submodule, ...) changed (T)
|
126
|
+
def self.convertChangesToUploadsDeletes(changes)
|
127
|
+
uploads = []
|
128
|
+
deletes = []
|
129
|
+
changes.each do |line|
|
130
|
+
continue if line==""
|
131
|
+
tabi = line.index("\t")
|
132
|
+
status = line[0,tabi]
|
133
|
+
path = line[tabi+1..-1]
|
134
|
+
if status.index('D')
|
135
|
+
deletes << path
|
136
|
+
else
|
137
|
+
uploads << path
|
138
|
+
end
|
139
|
+
end
|
140
|
+
return uploads,deletes
|
141
|
+
end
|
142
|
+
|
143
|
+
def get_file_content(aPath,aCommitOrBranch=nil)
|
144
|
+
@git.lib.command('show',[[aCommitOrBranch||'master',aPath].join(':')]) rescue nil
|
145
|
+
end
|
146
|
+
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
module Rigup
|
2
|
+
module InstallUtils
|
3
|
+
|
4
|
+
def select_suffixed_file(aFile,aExtendedExtension=false)
|
5
|
+
ext = Buzztools::File.extension(aFile,aExtendedExtension)
|
6
|
+
no_ext = Buzztools::File.no_extension(aFile,aExtendedExtension)
|
7
|
+
dir = File.dirname(aFile)
|
8
|
+
run "#{@context.sudo} mv -f #{no_ext}.#{@context.config[:stage]}.#{ext} #{aFile}"
|
9
|
+
run "#{@context.sudo} rm -f #{no_ext}.*.#{ext}"
|
10
|
+
end
|
11
|
+
|
12
|
+
# Especially for modifiying behaviour eg. of FCKEditor without upsetting the standard files
|
13
|
+
# eg. create a public_override folder that duplicates the same structure as public,
|
14
|
+
# and contains the modified files. On deployment call
|
15
|
+
# override_folder("#{@release_path}/public") # equiv to override_folder("#{@release_path}/public", "#{@release_path}/public_override")
|
16
|
+
# and the files in public_override will be copied over public, then public_override removed
|
17
|
+
def override_folder(aFolder,aOverrideFolder=nil,aRemove=true)
|
18
|
+
aFolder = aFolder.desuffix('/')
|
19
|
+
aOverrideFolder ||= (aFolder+'_override')
|
20
|
+
run "#{@context.sudo} cp -vrf #{aOverrideFolder}/* #{aFolder}/"
|
21
|
+
run "#{@context.sudo} rm -rf #{aOverrideFolder}" if aRemove
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
# set standard permissions for web sites - readonly for apache user
|
26
|
+
def permissions_for_web(aPath,aUser=nil,aGroup=nil,aHideScm=nil)
|
27
|
+
aUser ||= @user
|
28
|
+
aGroup ||= @group
|
29
|
+
|
30
|
+
run "#{@context.sudo} chown -R #{aUser}:#{aGroup} #{aPath.ensure_suffix('/')}"
|
31
|
+
run_for_all("chmod 755",aPath,:dirs) # !!! perhaps reduce other permissions
|
32
|
+
run_for_all("chmod 644",aPath,:files)
|
33
|
+
run_for_all("chmod g+s",aPath,:dirs)
|
34
|
+
case aHideScm
|
35
|
+
when :svn then run_for_all("chmod -R 700",aPath,:dirs,"*/.svn")
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
# run this after permissions_for_web() on dirs that need to be writable by group (apache)
|
40
|
+
def permissions_for_web_writable(aPath)
|
41
|
+
run "chmod -R g+w #{aPath.ensure_suffix('/')}"
|
42
|
+
run_for_all("chmod -R 700",aPath,:dirs,"*/.svn")
|
43
|
+
end
|
44
|
+
|
45
|
+
def internal_permissions(aPath,aKind)
|
46
|
+
case aKind
|
47
|
+
when 'rails' then
|
48
|
+
permissions_for_web(aPath,@user,@group,true)
|
49
|
+
|
50
|
+
run_for_all("chmod +x",File.join(aPath,'script'),:files)
|
51
|
+
|
52
|
+
|
53
|
+
uploads = @shared_path+'/uploads'
|
54
|
+
make_public_cache_dir(uploads)
|
55
|
+
#if File.exists?(uploads)
|
56
|
+
# permissions_for_web(uploads,@user,@group,true)
|
57
|
+
# permissions_for_web_writable(uploads)
|
58
|
+
#end
|
59
|
+
#permissions_for_web_writable("#{aPath}/tmp")
|
60
|
+
make_public_cache_dir("#{aPath}/tmp")
|
61
|
+
|
62
|
+
run "#{@context.sudo} chown #{@apache_user} #{aPath}/config/environment.rb" unless DEV_MODE # very important for passenger, which uses the owner of this file to run as
|
63
|
+
|
64
|
+
when 'spree' then
|
65
|
+
internal_permissions(aPath,'rails')
|
66
|
+
when 'browsercms' then
|
67
|
+
internal_permissions(aPath,'rails')
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def apply_permissions(aPath=nil,aKind=nil)
|
72
|
+
aPath ||= @release_path
|
73
|
+
aKind ||= @kind || 'rails'
|
74
|
+
internal_permissions(aPath, aKind)
|
75
|
+
end
|
76
|
+
|
77
|
+
def ensure_link(aTo,aFrom) #,aDir=nil,aUserGroup=nil,aSudo='')
|
78
|
+
raise "Must supply from" if !aFrom
|
79
|
+
cmd = []
|
80
|
+
#cmd << "cd #{aDir}" if aDir
|
81
|
+
cmd << "#{@context.sudo} rm -rf #{aFrom}"
|
82
|
+
cmd << "#{@context.sudo} ln -sf #{aTo} #{aFrom}"
|
83
|
+
#cmd << "#{@context.sudo} chown -h #{aUserGroup} #{aFrom}" if aUserGroup
|
84
|
+
run cmd.join(' && ')
|
85
|
+
end
|
86
|
+
|
87
|
+
def make_public_cache_dir(aStartPath)
|
88
|
+
run "#{@context.sudo} mkdir -p #{aStartPath}"
|
89
|
+
permissions_for_web(aStartPath)
|
90
|
+
permissions_for_web_writable(aStartPath)
|
91
|
+
end
|
92
|
+
|
93
|
+
end
|
94
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Rigup
|
2
|
+
module Runability
|
3
|
+
|
4
|
+
def run(aCommand,aDir=nil)
|
5
|
+
@context.logger.debug aCommand
|
6
|
+
response = ::POpen4::shell(aCommand,aDir || @context.pwd)
|
7
|
+
raise Error, "Command Failed" unless (response && response[:exitcode]==0)
|
8
|
+
return response[:stdout]
|
9
|
+
end
|
10
|
+
|
11
|
+
def run_for_all(aCommand,aPath,aFilesOrDirs,aPattern=nil,aInvertPattern=false,aSudo=false)
|
12
|
+
#run "#{sudo} find . -wholename '*/.svn' -prune -o -type d -print0 |xargs -0 #{sudo} chmod 750"
|
13
|
+
#sudo find . -type f -exec echo {} \;
|
14
|
+
cmd = []
|
15
|
+
cmd << "sudo" if aSudo
|
16
|
+
cmd << "find #{aPath.ensure_suffix('/')}"
|
17
|
+
cmd << "-wholename '#{aPattern}'" if aPattern
|
18
|
+
cmd << "-prune -o" if aInvertPattern
|
19
|
+
cmd << case aFilesOrDirs.to_s[0,1]
|
20
|
+
when 'f' then '-type f'
|
21
|
+
when 'd' then '-type d'
|
22
|
+
else ''
|
23
|
+
end
|
24
|
+
cmd << "-exec"
|
25
|
+
cmd << aCommand
|
26
|
+
cmd << "'{}' \\;"
|
27
|
+
cmd = cmd.join(' ')
|
28
|
+
run cmd
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
data/lib/rigup/svn.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
module Rigup
|
2
|
+
module Svn
|
3
|
+
|
4
|
+
def svnInfo(aPath)
|
5
|
+
cmdresult = run "svn info \"#{aPath}\""
|
6
|
+
cmdresult = cmdresult.split("\n")
|
7
|
+
result = {}
|
8
|
+
cmdresult.each do |line|
|
9
|
+
parts = line.split(': ')
|
10
|
+
next if parts.length!=2 || !parts[0] || !parts[1]
|
11
|
+
result[parts[0]] = parts[1]
|
12
|
+
end
|
13
|
+
|
14
|
+
if (url = result['URL']) && (root = result['Repository Root']) && url.start_with?(root)
|
15
|
+
result['Short URL'] = url[root.length]
|
16
|
+
end
|
17
|
+
result
|
18
|
+
end
|
19
|
+
|
20
|
+
def svnCmd(aCommand,aSourceServer,aSourceUrl,aDestPath,aOptions = null)
|
21
|
+
"svn #{aCommand} \"#{aSourceServer ? File.join(aSourceServer,aSourceUrl) : aSourceUrl}\" \"#{aDestPath}\" #{aOptions || ''}"
|
22
|
+
end
|
23
|
+
|
24
|
+
def svnCheckoutCmd(aConfig,aCommmand='checkout',aOptions=nil)
|
25
|
+
options = []
|
26
|
+
options << aOptions if aOptions
|
27
|
+
options << '--username '+aConfig['vcs_username'] if aConfig['vcs_username']
|
28
|
+
options << '--password '+aConfig['vcs_password'] if aConfig['vcs_password']
|
29
|
+
options << '--revision '+aConfig['revision'] if aConfig['revision']
|
30
|
+
options = options.join ' '
|
31
|
+
|
32
|
+
rep = aConfig['repository'].to_s.chomp('/').to_nil
|
33
|
+
if rep && (branch = aConfig['branch'])
|
34
|
+
branch = '/'+branch unless branch.start_with? '/'
|
35
|
+
url = File.join(branch,aConfig['source'].to_s) if aConfig['source']
|
36
|
+
else
|
37
|
+
url = aConfig['source']
|
38
|
+
end
|
39
|
+
url = url.chomp('/')
|
40
|
+
|
41
|
+
svnCmd(aCommmand,rep,url,aConfig['destination'],options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def createSvnConfig(aMergeOptions = nil)
|
45
|
+
result = {
|
46
|
+
'repository' => @repository,
|
47
|
+
'source' => @vcs_app_path,
|
48
|
+
'branch' => @branch,
|
49
|
+
'destination' => @release_path,
|
50
|
+
'revision' => @revision
|
51
|
+
}
|
52
|
+
result.merge!(aMergeOptions) if aMergeOptions
|
53
|
+
result
|
54
|
+
end
|
55
|
+
|
56
|
+
def folderIsSvn(aPath)
|
57
|
+
return false unless File.exists?(aPath)
|
58
|
+
info = svnInfo(aPath)
|
59
|
+
return !!(info && info['URL'])
|
60
|
+
end
|
61
|
+
|
62
|
+
# ensure cache_path is an svn repo and is up to date. Checkout if not
|
63
|
+
def ensureSvnCacheUpdate(cache_path,svnConfig)
|
64
|
+
svnConfig = svnConfig.merge('destination' => cache_path)
|
65
|
+
if File.exists?(cache_path)
|
66
|
+
raise Error('Dir exists but not a svn folder') unless folderIsSvn(cache_path)
|
67
|
+
run "svn revert --non-interactive --recursive \"#{cache_path}\""
|
68
|
+
run svnCheckoutCmd(
|
69
|
+
svnConfig,
|
70
|
+
'switch',
|
71
|
+
'--non-interactive'
|
72
|
+
)
|
73
|
+
else
|
74
|
+
MiscUtils.mkdir?(MiscUtils.path_parent(cache_path))
|
75
|
+
run svnCheckoutCmd(svnConfig,'checkout','--non-interactive')
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
end
|
80
|
+
end
|
data/lib/rigup.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'thor'
|
2
|
+
require 'buzztools'
|
3
|
+
require 'logger'
|
4
|
+
require 'yaml'
|
5
|
+
require 'buzztools/extras/shell_extras'
|
6
|
+
|
7
|
+
require_relative "rigup/version"
|
8
|
+
require_relative "rigup/config"
|
9
|
+
require_relative "rigup/context"
|
10
|
+
require_relative "rigup/runability"
|
11
|
+
require_relative "rigup/install_utils"
|
12
|
+
require_relative "rigup/git_repo"
|
13
|
+
require_relative "rigup/cli"
|
14
|
+
require_relative "rigup/deploy_base"
|
data/notes.txt
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
From site root :
|
2
|
+
|
3
|
+
> cd /var/www
|
4
|
+
> rigup new repo_url mysite
|
5
|
+
+ make dir mysite
|
6
|
+
+ create rigup.yml if doesn't exist, including option values
|
7
|
+
+ make dir mysite/releases
|
8
|
+
+ make dir mysite/shared
|
9
|
+
|
10
|
+
> rigup deploy mysite
|
11
|
+
|
12
|
+
+ git clone repo_url mysite/releases/20140328234123
|
13
|
+
+ installing
|
14
|
+
|
15
|
+
|
16
|
+
> cd mysite
|
17
|
+
> rigup update
|
18
|
+
+ using plan rigup.yml
|
19
|
+
|
data/rigup.gemspec
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "rigup/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "rigup"
|
7
|
+
s.version = Rigup::VERSION
|
8
|
+
s.authors = ["Gary McGhee"]
|
9
|
+
s.email = ["contact@buzzware.com.au"]
|
10
|
+
s.homepage = "http://github.com/buzzware/rigup"
|
11
|
+
s.summary = "Toolset for deployment"
|
12
|
+
s.description = s.summary
|
13
|
+
|
14
|
+
ignores = File.readlines(".gitignore").grep(/\S+/).map {|line| line.chomp }
|
15
|
+
dotfiles = [".gitignore"]
|
16
|
+
s.files = Dir["**/*"].reject {|f| File.directory?(f) || ignores.any? {|i| File.fnmatch(i, f) } } + dotfiles
|
17
|
+
s.bindir = 'bin'
|
18
|
+
s.executables = s.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
19
|
+
s.test_files = s.files.grep(%r{^(test|spec|features)/})
|
20
|
+
|
21
|
+
s.add_dependency 'bundler', '~>1.5.3'
|
22
|
+
s.add_dependency 'thor', '~> 0.19.1'
|
23
|
+
|
24
|
+
|
25
|
+
s.add_development_dependency 'rspec', '~>2.14.0'
|
26
|
+
#s.add_development_dependency('rspec')
|
27
|
+
|
28
|
+
s.add_development_dependency('rake')
|
29
|
+
#s.add_development_dependency('rspec-core')
|
30
|
+
#s.add_development_dependency('rdoc')
|
31
|
+
#s.add_development_dependency('aruba')
|
32
|
+
#s.add_development_dependency('debugger')
|
33
|
+
#s.add_runtime_dependency('gli','2.5.0')
|
34
|
+
#s.add_runtime_dependency('termios')
|
35
|
+
#s.add_runtime_dependency('highline')
|
36
|
+
s.add_runtime_dependency('git')
|
37
|
+
#s.add_runtime_dependency('middleman')
|
38
|
+
s.add_runtime_dependency('buzztools')
|
39
|
+
s.add_runtime_dependency('POpen4')
|
40
|
+
# https://github.com/geemus/formatador
|
41
|
+
#s.add_runtime_dependency('bitbucket_rest_api')
|
42
|
+
#s.add_runtime_dependency('osx_keychain')
|
43
|
+
#s.add_runtime_dependency('json')
|
44
|
+
#s.add_runtime_dependency('net_dav')
|
45
|
+
#s.add_runtime_dependency('net-ssh')
|
46
|
+
#s.add_runtime_dependency('system_timer')
|
47
|
+
end
|
data/rigup.iml
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
<?xml version="1.0" encoding="UTF-8"?>
|
2
|
+
<module type="RUBY_MODULE" version="4">
|
3
|
+
<component name="DBNavigator.Module.ConnectionManager">
|
4
|
+
<connections />
|
5
|
+
</component>
|
6
|
+
<component name="NewModuleRootManager" inherit-compiler-output="true">
|
7
|
+
<exclude-output />
|
8
|
+
<content url="file://$MODULE_DIR$">
|
9
|
+
<sourceFolder url="file://$MODULE_DIR$" isTestSource="false" />
|
10
|
+
</content>
|
11
|
+
<orderEntry type="inheritedJdk" />
|
12
|
+
<orderEntry type="sourceFolder" forTests="false" />
|
13
|
+
<orderEntry type="library" scope="PROVIDED" name="POpen4 (v0.1.4, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
14
|
+
<orderEntry type="library" scope="PROVIDED" name="Platform (v0.4.0, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
15
|
+
<orderEntry type="library" scope="PROVIDED" name="bundler (v1.5.3, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
16
|
+
<orderEntry type="library" scope="PROVIDED" name="buzztools (v0.0.4, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
17
|
+
<orderEntry type="library" scope="PROVIDED" name="diff-lcs (v1.2.5, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
18
|
+
<orderEntry type="library" scope="PROVIDED" name="git (v1.2.6, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
19
|
+
<orderEntry type="library" scope="PROVIDED" name="open4 (v1.3.3, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
20
|
+
<orderEntry type="library" scope="PROVIDED" name="rake (v10.2.0, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
21
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec (v2.14.1, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
22
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-core (v2.14.8, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
23
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-expectations (v2.14.5, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
24
|
+
<orderEntry type="library" scope="PROVIDED" name="rspec-mocks (v2.14.6, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
25
|
+
<orderEntry type="library" scope="PROVIDED" name="thor (v0.19.1, RVM: ruby-2.0.0-p247) [gem]" level="application" />
|
26
|
+
</component>
|
27
|
+
</module>
|
28
|
+
|
data/spec/new_spec.rb
ADDED
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
#require 'file_utils'
|
3
|
+
|
4
|
+
describe 'rigup' do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
@old_dir = Dir.pwd
|
8
|
+
Dir.chdir(@dir = Dir.mktmpdir("new_spec"))
|
9
|
+
end
|
10
|
+
|
11
|
+
after :each do
|
12
|
+
Dir.chdir(@old_dir)
|
13
|
+
end
|
14
|
+
|
15
|
+
def new_site_process(aGitUrl)
|
16
|
+
@script = Rigup::Cli.new
|
17
|
+
@script.invoke(:new, [aGitUrl, 'mysite'])
|
18
|
+
Dir.exists?('mysite/releases').should be
|
19
|
+
Dir.exists?('mysite/shared').should be
|
20
|
+
File.exists?('mysite/rigup.yml').should be
|
21
|
+
|
22
|
+
@config = YAML.load_file('mysite/rigup.yml')
|
23
|
+
@config[:git_url].should == aGitUrl
|
24
|
+
end
|
25
|
+
|
26
|
+
def mock_get_repo(aUrl,aPath)
|
27
|
+
basename = File.basename(aUrl,'.git')
|
28
|
+
src = "~/repos/underscore_plus" unless File.exists?(src = "~/repos/#{basename}")
|
29
|
+
FileUtils.cp_r(File.expand_path(src),File.expand_path(aPath))
|
30
|
+
end
|
31
|
+
|
32
|
+
def stub_out_github
|
33
|
+
::Rigup::GitRepo.any_instance.stub(:clone) do |aUrl,aPath|
|
34
|
+
mock_get_repo(aUrl,aPath)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
RELEASE_INSTALL = <<-EOS
|
39
|
+
class Deploy < Thor
|
40
|
+
|
41
|
+
desc 'install','install the freshly delivered files'
|
42
|
+
def install
|
43
|
+
puts 'install'
|
44
|
+
end
|
45
|
+
|
46
|
+
desc 'restart','restart the web server'
|
47
|
+
def restart
|
48
|
+
puts 'restart'
|
49
|
+
end
|
50
|
+
|
51
|
+
end
|
52
|
+
EOS
|
53
|
+
|
54
|
+
describe "Given new project" do
|
55
|
+
|
56
|
+
it "deploy should update_cache, install and link_live" do
|
57
|
+
#Rigup::Cli.any_instance.stub(:restart => true, :install => true)
|
58
|
+
new_site_process('https://github.com/buzzware/underscore_plus.git')
|
59
|
+
::Rigup::GitRepo.any_instance.stub(:clone) do |aUrl,aPath|
|
60
|
+
mock_get_repo(aUrl,aPath)
|
61
|
+
RELEASE_INSTALL.to_file(File.join(aPath,'deploy.thor'))
|
62
|
+
end
|
63
|
+
|
64
|
+
@script2 = Rigup::Cli.new
|
65
|
+
@script2.invoke(:deploy, ['mysite'])
|
66
|
+
|
67
|
+
Dir.exists?('mysite/shared/cached-copy').should be
|
68
|
+
Dir.exists?('mysite/shared/cached-copy/.git').should be
|
69
|
+
Dir.exists?('mysite/shared/cached-copy/.git').should be
|
70
|
+
|
71
|
+
Dir.exists?('mysite/current').should be
|
72
|
+
|
73
|
+
entries = Dir.entries('mysite/releases')
|
74
|
+
entries.length.should == 3
|
75
|
+
release_path = entries.last
|
76
|
+
release_path.should =~ /#{Time.now.strftime('%Y%m%d%H')}/
|
77
|
+
|
78
|
+
# Release method should write a rigup.yml including branch, commit, stage etc (should not be in repo)
|
79
|
+
# Rigup::DeployBase then reads this and makes it accessible to install and restart methods
|
80
|
+
# Then we can do things like displaying git commit hash on page as the site knows its own full identity
|
81
|
+
release_config = YAML.load_file("mysite/releases/#{release_path}/rigup.yml")
|
82
|
+
release_config.should be_a Hash
|
83
|
+
|
84
|
+
cache_repo = ::Rigup::GitRepo.new(Rigup::Context.new)
|
85
|
+
cache_repo.open('mysite/shared/cached-copy')
|
86
|
+
|
87
|
+
release_config[:branch].should be
|
88
|
+
release_config[:branch].should == cache_repo.branch
|
89
|
+
release_config[:commit].should be
|
90
|
+
release_config[:commit].should == cache_repo.sha
|
91
|
+
release_config[:stage].should == 'live'
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require 'rspec'
|
4
|
+
require 'rigup'
|
5
|
+
require_relative 'spec_utils'
|
6
|
+
|
7
|
+
include Rigup
|
8
|
+
|
9
|
+
#RSpec.configure do |config|
|
10
|
+
# def config.escaped_path(*parts)
|
11
|
+
# Regexp.compile(parts.join('[\\\/]'))
|
12
|
+
# end unless config.respond_to? :escaped_path
|
13
|
+
#end
|
14
|
+
|
15
|
+
# Include support files.
|
16
|
+
#Dir["#{File.expand_path('../', __FILE__)}/support/**/*.rb"].each { |f| require f }
|
data/spec/spec_utils.rb
ADDED
File without changes
|
metadata
ADDED
@@ -0,0 +1,167 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: rigup
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Gary McGhee
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-04-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: bundler
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ~>
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 1.5.3
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ~>
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 1.5.3
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: thor
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ~>
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.19.1
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.19.1
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: rspec
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ~>
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: 2.14.0
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ~>
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 2.14.0
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - '>='
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - '>='
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: git
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - '>='
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: buzztools
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - '>='
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :runtime
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: POpen4
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - '>='
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
description: Toolset for deployment
|
112
|
+
email:
|
113
|
+
- contact@buzzware.com.au
|
114
|
+
executables:
|
115
|
+
- rigup
|
116
|
+
extensions: []
|
117
|
+
extra_rdoc_files: []
|
118
|
+
files:
|
119
|
+
- bin/rigup
|
120
|
+
- example deploy.thor
|
121
|
+
- Gemfile
|
122
|
+
- lib/rigup/cli.rb
|
123
|
+
- lib/rigup/config.rb
|
124
|
+
- lib/rigup/context.rb
|
125
|
+
- lib/rigup/deploy_base.rb
|
126
|
+
- lib/rigup/git_repo.rb
|
127
|
+
- lib/rigup/install_utils.rb
|
128
|
+
- lib/rigup/runability.rb
|
129
|
+
- lib/rigup/svn.rb
|
130
|
+
- lib/rigup/version.rb
|
131
|
+
- lib/rigup.rb
|
132
|
+
- notes.txt
|
133
|
+
- Rakefile
|
134
|
+
- README.md
|
135
|
+
- rigup.gemspec
|
136
|
+
- rigup.iml
|
137
|
+
- spec/new_spec.rb
|
138
|
+
- spec/spec_helper.rb
|
139
|
+
- spec/spec_utils.rb
|
140
|
+
- .gitignore
|
141
|
+
homepage: http://github.com/buzzware/rigup
|
142
|
+
licenses: []
|
143
|
+
metadata: {}
|
144
|
+
post_install_message:
|
145
|
+
rdoc_options: []
|
146
|
+
require_paths:
|
147
|
+
- lib
|
148
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
149
|
+
requirements:
|
150
|
+
- - '>='
|
151
|
+
- !ruby/object:Gem::Version
|
152
|
+
version: '0'
|
153
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
154
|
+
requirements:
|
155
|
+
- - '>='
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: '0'
|
158
|
+
requirements: []
|
159
|
+
rubyforge_project:
|
160
|
+
rubygems_version: 2.1.5
|
161
|
+
signing_key:
|
162
|
+
specification_version: 4
|
163
|
+
summary: Toolset for deployment
|
164
|
+
test_files:
|
165
|
+
- spec/new_spec.rb
|
166
|
+
- spec/spec_helper.rb
|
167
|
+
- spec/spec_utils.rb
|