git-deployer 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +78 -0
- data/example/README.textile +14 -0
- data/example/hooks/clone +31 -0
- data/example/hooks/update +24 -0
- data/example/tasks.rb +12 -0
- data/example/www/index.html +15 -0
- data/git-deployer.gemspec +24 -0
- data/hooks/project/clone.exec.erb +53 -0
- data/hooks/project/clone.source.erb +55 -0
- data/hooks/project/update.exec.erb +64 -0
- data/hooks/project/update.source.erb +60 -0
- data/hooks/server/post-receive.erb +95 -0
- data/tasks/git-deployer.nake +280 -0
- metadata +75 -0
data/README.textile
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
h1. About
|
2
|
+
|
3
|
+
This is simple and flexible deployment solution based on Git post-receive hook.
|
4
|
+
|
5
|
+
* You don't have to install anything on your server
|
6
|
+
* It works with whichever thinkable solution, Rails, Merb, "Rango":http://github.com/botanicus/rango, Sinatra or even Django or static pages, it just doesn't matter!
|
7
|
+
* Deployment to more servers is supported.
|
8
|
+
|
9
|
+
h1. Usage
|
10
|
+
|
11
|
+
* Run @gem install git-deployer --development@
|
12
|
+
* Add following lines to your file with "Nake":http://github.com/botanicus/nake tasks (I'll refer this file as @tasks.rb@):
|
13
|
+
|
14
|
+
<pre>
|
15
|
+
begin
|
16
|
+
load "git-deployer.nake"
|
17
|
+
Task["deployer:setup"].config[:servers] = {
|
18
|
+
server1: {
|
19
|
+
user: "www",
|
20
|
+
host: "127.0.0.1",
|
21
|
+
repo: "/var/sources/deploy-test.git",
|
22
|
+
path: "/var/www/deploy-test"
|
23
|
+
}
|
24
|
+
}
|
25
|
+
rescue LoadError
|
26
|
+
warn "You have to install git-deployer gem if you want to deploy to remote servers!"
|
27
|
+
end
|
28
|
+
</pre>
|
29
|
+
|
30
|
+
* Install hooks via @./tasks.rb deployer:install@
|
31
|
+
* Edit @hooks/clone@ and @hooks/update@
|
32
|
+
* Install @post-receive@ hook and create necessary directories via @./tasks.rb deployer:install@
|
33
|
+
* Push your changes via @git push origin master@
|
34
|
+
|
35
|
+
That's it. When you run @git push origin master@ for the first time, it should found that given branch isn't cloned yet, so it should
|
36
|
+
|
37
|
+
h1. Available tasks
|
38
|
+
|
39
|
+
h3. Task @deployer:install@
|
40
|
+
|
41
|
+
This task will copy @hooks/clone@ and @hooks/update@ hooks to your project. This step is mandatory.
|
42
|
+
|
43
|
+
h3. Task @deployer:setup@
|
44
|
+
|
45
|
+
It can take one or more optional arguments with
|
46
|
+
It takes the same arguments resp. configuration options as @deployer:compile_hook@ task
|
47
|
+
|
48
|
+
h3. Task @deployer:compile_hook@
|
49
|
+
|
50
|
+
This task will copy @hooks/post-receive@ hook to your project. This step is optional and you will use the task you in case that you aren't happy with the default @post-receive@ hook distributed with git-deployer and you want to customize things. But you shouldn't need this, there is a bunch of arguments which you can use for influencing the generated @post-receive@ hook.
|
51
|
+
|
52
|
+
h3. Task @deployer:remote:copy_hook@
|
53
|
+
|
54
|
+
Again, you typically don't need this task, because it run during @deployer:setup@. However if you changed something in the @post-receive@ hook, you might want to run this task which will install @post-receive@ on remote servers. By default the hook will be installed to all the servers, but you can specify just a subset via @./tasks.rb deployer:remote:copy_hook server1 server2@.
|
55
|
+
|
56
|
+
h4. Setup
|
57
|
+
|
58
|
+
h2. Restricting Just for @deploy@ Branch
|
59
|
+
|
60
|
+
You might not want to deploy every branch you push to origin.
|
61
|
+
|
62
|
+
h3. Task @deployer:run@
|
63
|
+
|
64
|
+
If you pushed to the remote server but the hook failed, this is the way how you can re-run it. Just fix the problem and run @./tasks.rb deployer:run@. By default it runs on all the servers, but you can run it just on some servers via @./tasks.rb deployer:run server1 server2@.
|
65
|
+
|
66
|
+
h3. Task @deploy@
|
67
|
+
|
68
|
+
This task is useful for deployment to *multiple servers*. Just run @git push server1 master && git push server1 master@ or @./tasks.rb deploy@ which is a shortcut for pushing current branch to all or specified remote servers.
|
69
|
+
|
70
|
+
h1. FAQ
|
71
|
+
|
72
|
+
*Q:* _I had typo in my hooks, so it failed during deploy, how can I rerun it?_
|
73
|
+
|
74
|
+
*A:* @./tasks.rb deployer:run@ with optional argument which
|
75
|
+
|
76
|
+
*Q:* _You are using "Nake":http://github.com/botanicus/nake, but everyone's using Rake. Is there any chance that you will support Rake in future?_
|
77
|
+
|
78
|
+
*A:* The trouble with Rake is that Rake doesn't support configuration and it also really suck in command-line parsing. If Rake will support at least the command line arguments in a reasonable way, I can think about it.
|
@@ -0,0 +1,14 @@
|
|
1
|
+
h1. About
|
2
|
+
|
3
|
+
This is a "git-deployer":http://github.com/botanicus/git-deployer demo.
|
4
|
+
|
5
|
+
h1. Usage
|
6
|
+
|
7
|
+
# Copy this directory out of the git-deployer repository.
|
8
|
+
# Edit connection details in @tasks.rb@.
|
9
|
+
# Ensure you have "Nake":http://github.com/botanicus/nake task manager installed.
|
10
|
+
# Run @./tasks.rb deployer:setup@
|
11
|
+
# Run @git init && git add . && git commit -a -m "Initial import"@ and then @git remote add@ with the URL of remote repository.
|
12
|
+
# Run @git push origin master@ and see what's going on.
|
13
|
+
|
14
|
+
Of course if you want to see something real, you have to point your web server to this repository, probably via vhost.
|
data/example/hooks/clone
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
# === Documentation === #
|
2
|
+
# This is just a standard shell script, which is loaded from the
|
3
|
+
# post-receive hook when a new branch is created.
|
4
|
+
|
5
|
+
# Just don't forget that gems you have on your local machine probably
|
6
|
+
# aren't installed at the server, at least before you run gem bundle.
|
7
|
+
|
8
|
+
# Your working directory is root of your application which was just cloned
|
9
|
+
# here. (Probably) unlike to your local machine, basename is name of the branch,
|
10
|
+
# not name of the application. It shouldn't matter in most cases, but sometimes
|
11
|
+
# it does, for example in Python where you are using import myapp.something.
|
12
|
+
# 1) Write an awful perl-ish script with sed -i / perl -i / ruby -i and just replace
|
13
|
+
# the name in your code. It might work, but come on, you don't want to do that.
|
14
|
+
# 2) Your application will be as a subdirectory of the root of the repository,
|
15
|
+
# so you may call it whatever you want.
|
16
|
+
# 3) Obviously the best solution is to change the post-receive script, for example:
|
17
|
+
# Task["deployer:compile_hook"].config[:target] = "myappname"
|
18
|
+
|
19
|
+
# Make sure this script isn't executable, otherwise the script will simply run,
|
20
|
+
# so you won't have access to shell functions from the post-receive hook.
|
21
|
+
# However this is useful if you want to run this script under another interpret.
|
22
|
+
# If you want to install hooks which will be executed rather than just
|
23
|
+
# loaded, use ./tasks.rb deployer:install --executable or add
|
24
|
+
# Task["deployer:install"].config[:executable] = false to your tasks.rb
|
25
|
+
|
26
|
+
# Also, post-receive hook run under /bin/sh by default, but you might want to
|
27
|
+
# use something more advance like bash or zsh. Since these shells are compatible
|
28
|
+
# with the original sh, it's easy, just run ./tasks.rb deployer:compile_hook --shebang="#!/bin/zsh"
|
29
|
+
# or add Task["deployer:compile_hook"].config[:shebang] = "#!/bin/zsh" to your tasks.rb and reinstall the hooks.
|
30
|
+
|
31
|
+
. "hooks/update"
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# === Documentation === #
|
2
|
+
# This is just a standard shell script, which is loaded from the
|
3
|
+
# post-receive hook each time a branch is updated.
|
4
|
+
|
5
|
+
# Just don't forget that gems you have on your local machine probably
|
6
|
+
# aren't installed at the server, at least before you run gem bundle.
|
7
|
+
|
8
|
+
# Your working directory is root of your application which was just cloned
|
9
|
+
# here. (Probably) unlike to your local machine, basename is name of the branch,
|
10
|
+
# not name of the application. It shouldn't matter in most cases, but sometimes
|
11
|
+
# it does, for example in Python where you are using import myapp.something.
|
12
|
+
# 1) Write an awful perl-ish script with sed -i / perl -i / ruby -i and just replace
|
13
|
+
# the name in your code. It might work, but come on, you don't want to do that.
|
14
|
+
# 2) Your application will be as a subdirectory of the root of the repository,
|
15
|
+
# so you may call it whatever you want.
|
16
|
+
# 3) Obviously the best solution is to change the post-receive script, for example:
|
17
|
+
# Task["deployer:compile_hook"].config[:target] = "myappname"
|
18
|
+
|
19
|
+
# Make sure this script isn't executable, otherwise the script will simply run,
|
20
|
+
# so you won't have access to shell functions from the post-receive hook.
|
21
|
+
# However this is useful if you want to run this script under another interpret.
|
22
|
+
# If you want to install hooks which will be executed rather than just
|
23
|
+
# loaded, use ./tasks.rb deployer:install --executable or add
|
24
|
+
# Task["deployer:install"].config[:executable] = false to your tasks.rb
|
data/example/tasks.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
#!/usr/bin/env nake
|
2
|
+
|
3
|
+
# TODO: rewrite the example to Rango, it would be more interesting
|
4
|
+
# Or maybe add more examples for jekyll, nanoc, Django, maybe Rails.
|
5
|
+
$:.unshift(File.join(File.dirname(__FILE__), "..", "tasks"))
|
6
|
+
|
7
|
+
load "git-deployer.nake"
|
8
|
+
|
9
|
+
Task["deployer:setup"].config[:user] = "TODO"
|
10
|
+
Task["deployer:setup"].config[:host] = "TODO"
|
11
|
+
Task["deployer:setup"].config[:path] = "/var/www/deploy-test"
|
12
|
+
|
@@ -0,0 +1,15 @@
|
|
1
|
+
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
|
2
|
+
"http://www.w3.org/TR/html4/loose.dtd">
|
3
|
+
<html>
|
4
|
+
<head>
|
5
|
+
<meta http-equiv="Content-type" content="text/html; charset=utf-8">
|
6
|
+
<title>Hello World!</title>
|
7
|
+
</head>
|
8
|
+
|
9
|
+
<body>
|
10
|
+
<h1>Hello World!</h1>
|
11
|
+
<p>
|
12
|
+
This is an example page for <a href="http://github.com/botanicus/git-deployer">git-deployer</a>.
|
13
|
+
</p>
|
14
|
+
</body>
|
15
|
+
</html>
|
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env gem build
|
2
|
+
# encoding: utf-8
|
3
|
+
|
4
|
+
Gem::Specification.new do |s|
|
5
|
+
s.name = "git-deployer"
|
6
|
+
s.version = "0.0.1"
|
7
|
+
s.authors = ["Jakub Šťastný aka Botanicus"]
|
8
|
+
s.homepage = "http://github.com/botanicus/git-deployer"
|
9
|
+
s.summary = "Easy deploy system based on Git hooks"
|
10
|
+
s.description = "" # TODO: long description
|
11
|
+
s.cert_chain = nil
|
12
|
+
s.email = ["knava.bestvinensis", "gmail.com"].join("@")
|
13
|
+
s.has_rdoc = false
|
14
|
+
|
15
|
+
# files
|
16
|
+
s.files = Dir.glob("**/*") - Dir.glob("*.gem")
|
17
|
+
s.require_paths = ["tasks"]
|
18
|
+
|
19
|
+
# dependencies
|
20
|
+
s.add_development_dependency "nake"
|
21
|
+
|
22
|
+
# RubyForge
|
23
|
+
s.rubyforge_project = "git-deployer"
|
24
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
<%= options[:shebang] %>
|
2
|
+
|
3
|
+
# === Documentation === #
|
4
|
+
# This hook run when a new branch is pushed. It's just a standard
|
5
|
+
# executable script, feel free to use ruby, python, shell or whatever.
|
6
|
+
|
7
|
+
# Just don't forget that gems you have on your local machine probably
|
8
|
+
# aren't installed at the server, at least before you run gem bundle.
|
9
|
+
|
10
|
+
# Your working directory is root of your application which was just cloned
|
11
|
+
# here. (Probably) unlike to your local machine, basename is name of the branch,
|
12
|
+
# not name of the application. It shouldn't matter in most cases, but sometimes
|
13
|
+
# it does, for example in Python where you are using import myapp.something.
|
14
|
+
# 1) Write an awful perl-ish script with sed -i / perl -i / ruby -i and just replace
|
15
|
+
# the name in your code. It might work, but come on, you don't want to do that.
|
16
|
+
# 2) Your application will be as a subdirectory of the root of the repository,
|
17
|
+
# so you may call it whatever you want.
|
18
|
+
# 3) Obviously the best solution is to change the post-receive script, for example:
|
19
|
+
# Task["deployer:compile_hook"].config[:target] = "myappname"
|
20
|
+
|
21
|
+
# Make sure this script is executable, otherwise the script will be just
|
22
|
+
# loaded from post-receive hook, which means your shebang will be ignored.
|
23
|
+
# However this is useful when you want to use functions defined in the hook.
|
24
|
+
# If you want to install hooks which will be loaded rather than just
|
25
|
+
# executed, use ./tasks.rb deployer:install --no-executable or add
|
26
|
+
# Task["deployer:install"].config[:executable] = false to your tasks.rb
|
27
|
+
|
28
|
+
# Ruby on Rails
|
29
|
+
export RAILS_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
30
|
+
echo "Please edit config/database.yml and rerun this hook via ./tasks.rb deployer:run if you need so"
|
31
|
+
test -f config/database.yml.sample && cp config/database.yml.sample config/database.yml
|
32
|
+
rake db:create
|
33
|
+
exec "hooks/update"
|
34
|
+
|
35
|
+
# Rango
|
36
|
+
export RACK_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
37
|
+
echo "Please edit environments.rb and rerun this hook via ./tasks.rb deployer:run if you need so"
|
38
|
+
test -f environments_sample.rb && cp environments_sample.rb environments.rb
|
39
|
+
exec "hooks/update"
|
40
|
+
|
41
|
+
# Django
|
42
|
+
echo "Please edit settings_local.py and rerun this hook via ./tasks.rb deployer:run if you need so"
|
43
|
+
test -f settings_local_sample.py && cp settings_local_sample.py settings_local.py
|
44
|
+
|
45
|
+
# === Hints === #
|
46
|
+
# If each branch means a subdomain, you can generate vhosts in this
|
47
|
+
# hook. If you do so, then don't forget to restart your server!
|
48
|
+
# git push origin alpha => alpha.example.com
|
49
|
+
# git push origin beta => beta.example.com
|
50
|
+
# git push origin master => example.com
|
51
|
+
|
52
|
+
echo "Don't forget to edit hooks/clone\!"
|
53
|
+
exit 1
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# === Documentation === #
|
2
|
+
# This is just a standard shell script, which is loaded from the
|
3
|
+
# post-receive hook when a new branch is created.
|
4
|
+
|
5
|
+
# Just don't forget that gems you have on your local machine probably
|
6
|
+
# aren't installed at the server, at least before you run gem bundle.
|
7
|
+
|
8
|
+
# Your working directory is root of your application which was just cloned
|
9
|
+
# here. (Probably) unlike to your local machine, basename is name of the branch,
|
10
|
+
# not name of the application. It shouldn't matter in most cases, but sometimes
|
11
|
+
# it does, for example in Python where you are using import myapp.something.
|
12
|
+
# 1) Write an awful perl-ish script with sed -i / perl -i / ruby -i and just replace
|
13
|
+
# the name in your code. It might work, but come on, you don't want to do that.
|
14
|
+
# 2) Your application will be as a subdirectory of the root of the repository,
|
15
|
+
# so you may call it whatever you want.
|
16
|
+
# 3) Obviously the best solution is to change the post-receive script, for example:
|
17
|
+
# Task["deployer:compile_hook"].config[:target] = "myappname"
|
18
|
+
|
19
|
+
# Make sure this script isn't executable, otherwise the script will simply run,
|
20
|
+
# so you won't have access to shell functions from the post-receive hook.
|
21
|
+
# However this is useful if you want to run this script under another interpret.
|
22
|
+
# If you want to install hooks which will be executed rather than just
|
23
|
+
# loaded, use ./tasks.rb deployer:install --executable or add
|
24
|
+
# Task["deployer:install"].config[:executable] = false to your tasks.rb
|
25
|
+
|
26
|
+
# Also, post-receive hook run under /bin/sh by default, but you might want to
|
27
|
+
# use something more advance like bash or zsh. Since these shells are compatible
|
28
|
+
# with the original sh, it's easy, just run ./tasks.rb deployer:compile_hook --shebang="#!/bin/zsh"
|
29
|
+
# or add Task["deployer:compile_hook"].config[:shebang] = "#!/bin/zsh" to your tasks.rb and reinstall the hooks.
|
30
|
+
|
31
|
+
# Ruby on Rails
|
32
|
+
export RAILS_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
33
|
+
info "Please edit config/database.yml and rerun this hook via ./tasks.rb deployer:run if you need so"
|
34
|
+
test -f config/database.yml.sample && cp config/database.yml.sample config/database.yml
|
35
|
+
rake db:create
|
36
|
+
. "hooks/update"
|
37
|
+
|
38
|
+
# Rango
|
39
|
+
export RACK_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
40
|
+
info "Please edit environments.rb and rerun this hook via ./tasks.rb deployer:run if you need so"
|
41
|
+
test -f environments_sample.rb && cp environments_sample.rb environments.rb
|
42
|
+
. "hooks/update"
|
43
|
+
|
44
|
+
# Django
|
45
|
+
info "Please edit settings_local.py and rerun this hook via ./tasks.rb deployer:run if you need so"
|
46
|
+
test -f settings_local_sample.py && cp settings_local_sample.py settings_local.py
|
47
|
+
|
48
|
+
# === Hints === #
|
49
|
+
# If each branch means a subdomain, you can generate vhosts in this
|
50
|
+
# hook. If you do so, then don't forget to restart your server!
|
51
|
+
# git push origin alpha => alpha.example.com
|
52
|
+
# git push origin beta => beta.example.com
|
53
|
+
# git push origin master => example.com
|
54
|
+
|
55
|
+
abort "Don't forget to edit hooks/clone\!"
|
@@ -0,0 +1,64 @@
|
|
1
|
+
<%= options[:shebang] %>
|
2
|
+
|
3
|
+
# === Documentation === #
|
4
|
+
# This hooks run each time the branch is updated. If a new branch is created,
|
5
|
+
# than the clone hook runs first. It's just a standard executable script, feel
|
6
|
+
# free to use ruby, python, shell or whatever.
|
7
|
+
|
8
|
+
# Just don't forget that gems you have on your local machine probably
|
9
|
+
# aren't installed at the server, at least before you run gem bundle.
|
10
|
+
|
11
|
+
# Your working directory is root of your application which was just cloned
|
12
|
+
# here. (Probably) unlike to your local machine, basename is name of the branch,
|
13
|
+
# not name of the application. It shouldn't matter in most cases, but sometimes
|
14
|
+
# it does, for example in Python where you are using import myapp.something.
|
15
|
+
# 1) Write an awful perl-ish script with sed -i / perl -i / ruby -i and just replace
|
16
|
+
# the name in your code. It might work, but come on, you don't want to do that.
|
17
|
+
# 2) Your application will be as a subdirectory of the root of the repository,
|
18
|
+
# so you may call it whatever you want.
|
19
|
+
# 3) Obviously the best solution is to change the post-receive script, for example:
|
20
|
+
# Task["deployer:compile_hook"].config[:target] = "myappname"
|
21
|
+
|
22
|
+
# Make sure this script is executable, otherwise the script will be just
|
23
|
+
# loaded from post-receive hook, which means your shebang will be ignored.
|
24
|
+
# However this is useful when you want to use functions defined in the hook.
|
25
|
+
# If you want to install hooks which will be loaded rather than just
|
26
|
+
# executed, use ./tasks.rb deployer:install --no-executable or add
|
27
|
+
# Task["deployer:install"].config[:executable] = false to your tasks.rb
|
28
|
+
|
29
|
+
# === Setup === #
|
30
|
+
# If we have everything bundled in bin, we have to put bin to the beginning of the PATH
|
31
|
+
# variable, so all commands like rake etc will be loaded from bin, if they are in there
|
32
|
+
export PATH="bin:$PATH" # TODO: maybe you are using script directory instead of bin?
|
33
|
+
|
34
|
+
# Ruby on Rails
|
35
|
+
export RAILS_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
36
|
+
gem bundle --cached # this requires bundler installed on your server
|
37
|
+
rake db:migrate
|
38
|
+
#rake db:seed
|
39
|
+
|
40
|
+
# Rango
|
41
|
+
export RACK_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
42
|
+
gem bundle --cached
|
43
|
+
./tasks.rb db:autoupgrade
|
44
|
+
#./tasks.rb db:seed
|
45
|
+
|
46
|
+
# Django
|
47
|
+
# load data from fixtures
|
48
|
+
echo "Running syncdb ..."
|
49
|
+
python "manage.py syncdb --noinput"
|
50
|
+
|
51
|
+
# Jekyll
|
52
|
+
# point your vhost to the _site directory
|
53
|
+
jekyll --pygments
|
54
|
+
|
55
|
+
# Nanoc
|
56
|
+
# point your vhost to the output directory
|
57
|
+
nanoc3 compile
|
58
|
+
|
59
|
+
# Restart passenger application
|
60
|
+
echo "Restarting Passenger ..."
|
61
|
+
touch tmp/restart.txt
|
62
|
+
|
63
|
+
echo "Don't forget to edit hooks/update\!"
|
64
|
+
exit 1
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# === Documentation === #
|
2
|
+
# This is just a standard shell script, which is loaded from the
|
3
|
+
# post-receive hook each time a branch is updated.
|
4
|
+
|
5
|
+
# Just don't forget that gems you have on your local machine probably
|
6
|
+
# aren't installed at the server, at least before you run gem bundle.
|
7
|
+
|
8
|
+
# Your working directory is root of your application which was just cloned
|
9
|
+
# here. (Probably) unlike to your local machine, basename is name of the branch,
|
10
|
+
# not name of the application. It shouldn't matter in most cases, but sometimes
|
11
|
+
# it does, for example in Python where you are using import myapp.something.
|
12
|
+
# 1) Write an awful perl-ish script with sed -i / perl -i / ruby -i and just replace
|
13
|
+
# the name in your code. It might work, but come on, you don't want to do that.
|
14
|
+
# 2) Your application will be as a subdirectory of the root of the repository,
|
15
|
+
# so you may call it whatever you want.
|
16
|
+
# 3) Obviously the best solution is to change the post-receive script, for example:
|
17
|
+
# Task["deployer:compile_hook"].config[:target] = "myappname"
|
18
|
+
|
19
|
+
# Make sure this script isn't executable, otherwise the script will simply run,
|
20
|
+
# so you won't have access to shell functions from the post-receive hook.
|
21
|
+
# However this is useful if you want to run this script under another interpret.
|
22
|
+
# If you want to install hooks which will be executed rather than just
|
23
|
+
# loaded, use ./tasks.rb deployer:install --executable or add
|
24
|
+
# Task["deployer:install"].config[:executable] = false to your tasks.rb
|
25
|
+
|
26
|
+
# === Setup === #
|
27
|
+
# If we have everything bundled in bin, we have to put bin to the beginning of the PATH
|
28
|
+
# variable, so all commands like rake etc will be loaded from bin, if they are in there
|
29
|
+
export PATH="bin:$PATH" # TODO: maybe you are using script directory instead of bin?
|
30
|
+
|
31
|
+
# Ruby on Rails
|
32
|
+
export RAILS_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
33
|
+
gem bundle --cached # this requires bundler installed on your server
|
34
|
+
rake db:migrate
|
35
|
+
#rake db:seed
|
36
|
+
|
37
|
+
# Rango
|
38
|
+
export RACK_ENV="stagging" # if you are deploying to more servers, you might want to setup this in your /etc/profile
|
39
|
+
gem bundle --cached
|
40
|
+
./tasks.rb db:autoupgrade
|
41
|
+
#./tasks.rb db:seed
|
42
|
+
|
43
|
+
# Django
|
44
|
+
# load data from fixtures
|
45
|
+
info "Running syncdb ..."
|
46
|
+
python "manage.py syncdb --noinput"
|
47
|
+
|
48
|
+
# Jekyll
|
49
|
+
# point your vhost to the _site directory
|
50
|
+
jekyll --pygments
|
51
|
+
|
52
|
+
# Nanoc
|
53
|
+
# point your vhost to the output directory
|
54
|
+
nanoc3 compile
|
55
|
+
|
56
|
+
# Restart passenger application
|
57
|
+
info "Restarting Passenger ..."
|
58
|
+
touch tmp/restart.txt
|
59
|
+
|
60
|
+
abort "Don't forget to edit hooks/update\!"
|
@@ -0,0 +1,95 @@
|
|
1
|
+
<%= shebang %>
|
2
|
+
|
3
|
+
# This script is SH-compatible, but it doesn't mean you have to use SH.
|
4
|
+
# You can use bash or zsh and enjoy features of more powerful shells, just change the shebang!
|
5
|
+
|
6
|
+
# POST-RECEIVE HOOK
|
7
|
+
# ARGV: empty
|
8
|
+
# STDIN: [OLD HEAD] [NEW HEAD] refs/heads/alpha
|
9
|
+
|
10
|
+
<% if colors %>
|
11
|
+
export TERM="xterm-color"
|
12
|
+
|
13
|
+
abort() { printf "\e[1;31m$*\e[0m\n"; exit 1; }
|
14
|
+
success() { printf "\e[1;32m$*\e[0m\n"; }
|
15
|
+
info() { printf "\e[1;34m$*\e[0m\n"; }
|
16
|
+
debug() { $DEBUG && printf "\e[1;33m$*\e[0m\n"; }
|
17
|
+
<% else %>
|
18
|
+
abort() { printf "$*\n"; exit 1; }
|
19
|
+
success() { printf "$*\n"; }
|
20
|
+
info() { printf "$*\n"; }
|
21
|
+
debug() { $DEBUG && printf "$*\n"; }
|
22
|
+
<% end %>
|
23
|
+
run() { info $* ; $*; }
|
24
|
+
|
25
|
+
set -- $(cat /dev/stdin)
|
26
|
+
|
27
|
+
old=$1 && new=$2 && ref=$3
|
28
|
+
export BRANCH=$(basename $ref)
|
29
|
+
export DEBUG=<%= debug %>
|
30
|
+
export TARGET="<%= File.join(path, target) %>"
|
31
|
+
export REPO="<%= repo %>"
|
32
|
+
|
33
|
+
<% if branch %>
|
34
|
+
# restrict deployment just to given branch
|
35
|
+
if [ $BRANCH != <%= branch %> ]
|
36
|
+
info "Branch $BRANCH isn't supposed to be deployable, finishing"
|
37
|
+
exit
|
38
|
+
fi
|
39
|
+
<% end %>
|
40
|
+
|
41
|
+
cd $(dirname $TARGET) # the target might not exist yet
|
42
|
+
|
43
|
+
# GIT_DIR is "." which should points to bare repozitory
|
44
|
+
GIT_DIR="$REPO"
|
45
|
+
|
46
|
+
info "Reading /etc/profile ..."
|
47
|
+
. /etc/profile
|
48
|
+
|
49
|
+
debug
|
50
|
+
debug "=== Environment ==="
|
51
|
+
debug "PATH: $PATH"
|
52
|
+
debug "USER: $USER"
|
53
|
+
debug "TERM: $TERM"
|
54
|
+
debug "Ruby version: $(ruby --version)"
|
55
|
+
debug "Ruby path: $(which ruby)"
|
56
|
+
debug
|
57
|
+
debug "=== Git-deployer ==="
|
58
|
+
debug "TARGET: $TARGET"
|
59
|
+
debug "BRANCH: $BRANCH"
|
60
|
+
debug "REPO: $REPO"
|
61
|
+
debug "PWD: $PWD"
|
62
|
+
debug
|
63
|
+
|
64
|
+
if [ -d $TARGET ] ; then
|
65
|
+
cd $TARGET
|
66
|
+
info "Updating $BRANCH in `pwd` ... (from $old' to '$new')"
|
67
|
+
git fetch
|
68
|
+
git reset $new --hard
|
69
|
+
else
|
70
|
+
info "Cloning $BRANCH to $(pwd)/$TARGET (HEAD: '$new') ..."
|
71
|
+
git clone $REPO $TARGET
|
72
|
+
cd $TARGET
|
73
|
+
if [ -x "hooks/clone" ] ; then
|
74
|
+
info "[$PWD] Running clone hook"
|
75
|
+
exec "./hooks/clone"
|
76
|
+
elif [ -f "hooks/clone" ] ; then
|
77
|
+
info "[$PWD] Loading clone hook"
|
78
|
+
. "./hooks/clone" # so user can use functions defined in this hook in his clone hook
|
79
|
+
exit $?
|
80
|
+
else
|
81
|
+
abort "No clone hook found!"
|
82
|
+
fi
|
83
|
+
fi
|
84
|
+
|
85
|
+
# Update hook
|
86
|
+
if [ -x "hooks/update" ] ; then
|
87
|
+
info "[$PWD] Running update hook"
|
88
|
+
exec "./hooks/update"
|
89
|
+
elif [ -f "hooks/update" ] ; then
|
90
|
+
info "[$PWD] Loading update hook"
|
91
|
+
. "./hooks/update" # so user can use functions defined in this hook in his update hook
|
92
|
+
exit $?
|
93
|
+
else
|
94
|
+
abort "No update hook found!"
|
95
|
+
fi
|
@@ -0,0 +1,280 @@
|
|
1
|
+
#!/usr/bin/env nake
|
2
|
+
|
3
|
+
# TODO: what about a console support as capistrano has? Would be so helpful! Or at least ./tasks.rb deployer:ssh which starts ssh session for a server and cd to application path.
|
4
|
+
# TODO: run a command on all/given servers, like if you forget to create tmp in your clone hook
|
5
|
+
|
6
|
+
require "nake/template"
|
7
|
+
|
8
|
+
# === Helpers === #
|
9
|
+
|
10
|
+
# TODO: put it to nake
|
11
|
+
class Nake::Task
|
12
|
+
def run_from_task(task, *args)
|
13
|
+
self.call(*args)
|
14
|
+
rescue SystemExit => exception
|
15
|
+
Kernel.abort "Exception during task #{task}: #{exception.message}. Please re-run the task.\n#{exception.backtrace.join("\n- ")}"
|
16
|
+
rescue Exception => exception
|
17
|
+
abort "Exception during task #{task}: #{exception.message}. Please re-run the task.\n#{exception.backtrace.join("\n- ")}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
module SshMixin
|
22
|
+
def ssh(server, command)
|
23
|
+
sh "ssh %{user}@%{host} '#{command}'" % server
|
24
|
+
end
|
25
|
+
|
26
|
+
def servers(*names, &block)
|
27
|
+
names.map! { |name| name.to_sym }
|
28
|
+
config = Task["deployer:setup"].config
|
29
|
+
|
30
|
+
if ! config.has_key?(:servers) || config[:servers].empty?
|
31
|
+
abort "You have to configure servers. Read documentation online at http://github.com/botanicus/git-deployer"
|
32
|
+
end
|
33
|
+
|
34
|
+
names = config[:servers].keys if names.empty?
|
35
|
+
names.each do |name|
|
36
|
+
server = config[:servers][name]
|
37
|
+
raise "There isn't any server named #{name}. Please specify one of #{config[:servers].keys} or add #{name} to your configuration." if server.nil?
|
38
|
+
|
39
|
+
[:user, :host, :repo, :path].each do |key|
|
40
|
+
unless server.has_key?(key)
|
41
|
+
abort "Server #{name} doesn't have key #{key}, you have to provide it!"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
info "Server #{name} #{server.inspect}"
|
46
|
+
block.call(name, server)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
# === Tasks === #
|
52
|
+
|
53
|
+
# @settings
|
54
|
+
# Task["deployer:install"].config[:executable] = true
|
55
|
+
# @options
|
56
|
+
# --[no-]force Overwrite local hooks. Default is false.
|
57
|
+
# --[no-]executable Install hooks as executable scripts, so you can use whichever interpret,
|
58
|
+
# but you can't access to shell functions from post-receive.
|
59
|
+
Task.new("deployer:install") do |task|
|
60
|
+
task.description = "Install clone and update hooks to the project."
|
61
|
+
|
62
|
+
# path to the given hook
|
63
|
+
task.define_singleton_method(:path) do |name, options|
|
64
|
+
basename = options[:executable] ? "#{name}.exec.erb" : "#{name}.source.erb"
|
65
|
+
File.join(File.dirname(__FILE__), "..", "hooks", "project", basename)
|
66
|
+
end
|
67
|
+
|
68
|
+
# install given hook from its template
|
69
|
+
task.define_singleton_method(:install) do |source, target, options|
|
70
|
+
mkdir_p File.dirname(target)
|
71
|
+
note "Creating #{target} from #{source}"
|
72
|
+
if ! File.exist?(target) || options[:force]
|
73
|
+
erb source, target, options: options
|
74
|
+
sh "chmod +x #{target}" if options[:executable]
|
75
|
+
else
|
76
|
+
abort "File #{target} already exist. Run this hook with --force to override the file."
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
task.define do |options|
|
81
|
+
self.install(self.path("clone", options), "hooks/clone", options)
|
82
|
+
self.install(self.path("update", options), "hooks/update", options)
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
# @settings
|
87
|
+
# Task["deployer:setup"].config[:servers] = {
|
88
|
+
# server1: {
|
89
|
+
# user: "www",
|
90
|
+
# host: "127.0.0.1",
|
91
|
+
# repo: "/var/sources/deploy-test.git",
|
92
|
+
# path: "/var/www/deploy-test"
|
93
|
+
# }
|
94
|
+
# }
|
95
|
+
# @options
|
96
|
+
# --[no-]force Overwrite remote repository and application path. Default is false.
|
97
|
+
# Also, this tasks takes the same arguments as deployer:remote:copy_hook.
|
98
|
+
# @see Task["deployer:remote:copy_hook"] for configuring generation of the post-receive hook.
|
99
|
+
Task.new("deployer:setup") do |task|
|
100
|
+
task.description = "Install Git hooks on remote server"
|
101
|
+
task.extend(SshMixin)
|
102
|
+
|
103
|
+
task.define do |options|
|
104
|
+
servers do |name, server|
|
105
|
+
if options[:force]
|
106
|
+
ssh server, "test -d %{path} && rm -rf %{path}; test -d %{repo} && rm -rf %{repo}"
|
107
|
+
end
|
108
|
+
|
109
|
+
unless ssh server, "test -d %{path}"
|
110
|
+
ssh server, "mkdir -p %{path}" || abort("Creating of some necessary directories failed.")
|
111
|
+
else
|
112
|
+
abort "Path %{path} already exist. Try to run with --force if you want to overwrite it." % server
|
113
|
+
end
|
114
|
+
|
115
|
+
unless ssh server, "test -d %{repo}"
|
116
|
+
ssh server, "mkdir -p %{repo}" || abort("Creating of some necessary directories failed.")
|
117
|
+
ssh server, "cd %{repo} && git init --bare" || abort("There was a problems during attempt to create a bare repository.")
|
118
|
+
sh "git remote add #{name} %{user}@%{host}:%{repo}" % server
|
119
|
+
else
|
120
|
+
abort "Repository %{repo} already exist. Try to run with --force if you want to overwrite it." % server
|
121
|
+
end
|
122
|
+
|
123
|
+
info "Setup at server #{name} finished"
|
124
|
+
end
|
125
|
+
|
126
|
+
# copy post-receive hooks
|
127
|
+
Task["deployer:remote:copy_hook"].run_from_task("deployer:setup", [], options)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
# @options
|
132
|
+
# This tasks takes the same arguments as deployer:compile_hook.
|
133
|
+
# @see Task["deployer:compile_hook"] for configuring generation of the post-receive hook.
|
134
|
+
Task.new("deployer:remote:copy_hook") do |task|
|
135
|
+
task.description = "Copy Git hook to remote server"
|
136
|
+
task.extend(SshMixin)
|
137
|
+
|
138
|
+
# TODO: change gemspec to require Ruby 1.9
|
139
|
+
task.define_singleton_method(:template) do |path|
|
140
|
+
path.end_with?(".erb") ? path : compile_template(path)
|
141
|
+
end
|
142
|
+
|
143
|
+
# Template precedence:
|
144
|
+
# 1) hooks/post-receive.server_name
|
145
|
+
# 2) hooks/post-receive.server_name.erb
|
146
|
+
# 3) hooks/post-receive
|
147
|
+
# 3) hooks/post-receive.erb
|
148
|
+
# 5) the default template distributed with git-deployer
|
149
|
+
task.define_singleton_method(:find_template) do |name|
|
150
|
+
["hooks/post-receive.#{name}", "hooks/post-receive"].find do |template|
|
151
|
+
File.exist?(template)
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
# @return [String] path to the post-receive hook which was generated
|
156
|
+
task.define_singleton_method(:compile_template) do |name|
|
157
|
+
path = ["hooks/post-receive.#{name}.erb", "hooks/post-receive.erb"].find do |template|
|
158
|
+
if File.exist?(template)
|
159
|
+
info "Compiling template #{template}"
|
160
|
+
Task["deployer:compile_hook"].call(template, name, options)
|
161
|
+
end
|
162
|
+
end
|
163
|
+
path.sub(/\.erb$/, "") if path
|
164
|
+
end
|
165
|
+
|
166
|
+
task.define_singleton_method(:upload) do |server, local_path|
|
167
|
+
sh "scp #{local_path} %{user}@%{host}:%{repo}/hooks/post-receive" % server
|
168
|
+
ssh server, "chmod +x %{repo}/hooks/post-receive"
|
169
|
+
end
|
170
|
+
|
171
|
+
task.define do |*names, options|
|
172
|
+
servers(*names) do |name, server|
|
173
|
+
# generate the hook if it doesn't exist
|
174
|
+
if local_path = self.find_template(name)
|
175
|
+
info "Using hook #{local_path}"
|
176
|
+
self.upload(server, local_path)
|
177
|
+
elsif local_path = self.compile_template(name)
|
178
|
+
self.upload(server, local_path)
|
179
|
+
sh "rm #{local_path}"
|
180
|
+
else
|
181
|
+
template = File.join(File.dirname(__FILE__), "..", "hooks", "server", "post-receive.erb")
|
182
|
+
info "Generating hook from default post-receive template"
|
183
|
+
Task["deployer:compile_hook"].call([template, name], options)
|
184
|
+
local_path = "hooks/post-receive.#{name}"
|
185
|
+
self.upload(server, local_path)
|
186
|
+
sh "rm #{local_path}"
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
192
|
+
# TODO: Task["deployer:compile_hook"].config[:colors] is fine, but there should be also server-specific configuration in Task["deployer:setup"].config[:servers][:origin][:colors]
|
193
|
+
|
194
|
+
# @example
|
195
|
+
# ./tasks.rb deployer:compile_hook hooks/post-receive.erb --colors
|
196
|
+
# @settings
|
197
|
+
# Task["deployer:compile_hook"].config[:colors] = false
|
198
|
+
# Task["deployer:compile_hook"].config[:debug] = true
|
199
|
+
# Task["deployer:compile_hook"].config[:branch] = "master"
|
200
|
+
# Task["deployer:compile_hook"].config[:shebang] = "#!/usr/bin/env ruby"
|
201
|
+
# Task["deployer:compile_hook"].config[:target] = "$BRANCH"
|
202
|
+
# @options
|
203
|
+
# --[no-]force Overwrite local post-receive hook. Default is keep it.
|
204
|
+
# --[no-]colors Do not use colors in the hook. Some servers might have problems with them.
|
205
|
+
# --[no-]debug Print debug messages from the post-receive hook.
|
206
|
+
# --branch=deploy Deploy just this specified branch. Default is deploy all of them.
|
207
|
+
# --shebang='#!/bin/zsh' Use this shebang in the post-receive hook.
|
208
|
+
# --target='$BRANCH' Relative path from the apps root to the application. So if we have apps root in /var/www/myapp and we
|
209
|
+
# specify target to '$BRANCH', then each branch will be located in directory with same name as the branch,
|
210
|
+
# i. e. /var/www/myapp/master. Empty target means put everything directly into the apps root. It's reasonable
|
211
|
+
# just if you specify also the --branch=mybranch switch, otherwise the code will be reset in each push to the
|
212
|
+
# different branch which isn't probably what you want. But if you deploy just one branch, then it's OK.
|
213
|
+
Task.new("deployer:compile_hook") do |task|
|
214
|
+
task.description = "Copy Git hook locally, so you can edit it and at the next remote copy it will be used instead of the hook distributed with git-deployer."
|
215
|
+
task.extend(SshMixin)
|
216
|
+
|
217
|
+
# default configuration
|
218
|
+
task.config[:shebang] = "#!/bin/sh"
|
219
|
+
task.config[:debug] = true
|
220
|
+
task.config[:colors] = true
|
221
|
+
task.config[:branch] = nil
|
222
|
+
task.config[:target] = "$BRANCH"
|
223
|
+
|
224
|
+
# We have to generate one hook for each server configuration because we have to specify local paths
|
225
|
+
task.define do |source = nil, server_name = nil, options|
|
226
|
+
abort "[#1] You have to specify the template you want to compile!" if source.nil?
|
227
|
+
abort "[#2] You have to specify the the server_name!" if server_name.nil?
|
228
|
+
abort "First argument has to be a template with .erb extension!" unless source.end_with?(".erb")
|
229
|
+
server = Task["deployer:setup"].config[:servers][server_name]
|
230
|
+
target = "hooks/post-receive.#{server_name}"
|
231
|
+
if ! File.exist?(target) || options[:force]
|
232
|
+
info "Creating #{target} from template #{source}"
|
233
|
+
erb source, target, {repo: server[:repo], path: server[:path]}.merge(config).merge(options)
|
234
|
+
else
|
235
|
+
abort "File #{target} already exist. Run this task with --force option to override."
|
236
|
+
end
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
Task.new("deployer:copy_hook") do |task|
|
241
|
+
task.description = "Copy Git hook locally, so you can edit it and at the next remote copy it will be used instead of the hook distributed with git-deployer."
|
242
|
+
|
243
|
+
task.define do |target = "hooks/post-receive", options|
|
244
|
+
source = File.join(File.dirname(__FILE__), "..", "hooks", "server", "post-receive.erb")
|
245
|
+
if ! File.exist?(target) || options[:force]
|
246
|
+
cp source, target
|
247
|
+
else
|
248
|
+
abort "File #{target} already exist. Run this task with --force option to override."
|
249
|
+
end
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
Task.new("deployer:run") do |task|
|
254
|
+
task.description = "Run remote hook"
|
255
|
+
task.extend(SshMixin)
|
256
|
+
|
257
|
+
# STDIN for post-receive:
|
258
|
+
# SHA1 SHA1 refs/heads/master
|
259
|
+
task.define do
|
260
|
+
servers do |name, server|
|
261
|
+
head = `git rev-parse HEAD`
|
262
|
+
refs = `cat .git/HEAD | awk '{ print $2 }'`
|
263
|
+
ssh server, "cd %{path} && echo #{head} #{head} #{refs} | ./hooks/post-receive"
|
264
|
+
end
|
265
|
+
end
|
266
|
+
end
|
267
|
+
|
268
|
+
# ./tasks.rb deployer:remove
|
269
|
+
# ./tasks.rb deployer:remove server1 server2
|
270
|
+
Task.new("deployer:remove") do |task|
|
271
|
+
task.description = "Remove created directory for remote servers"
|
272
|
+
task.config = Task["deployer:setup"].config
|
273
|
+
task.extend(SshMixin)
|
274
|
+
|
275
|
+
task.define do |*names, options|
|
276
|
+
servers(names) do |name, server|
|
277
|
+
ssh "rm -rf %{path}; rm -rf %repo"
|
278
|
+
end
|
279
|
+
end
|
280
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: git-deployer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- "Jakub \xC5\xA0\xC5\xA5astn\xC3\xBD aka Botanicus"
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain:
|
11
|
+
date: 2010-01-03 00:00:00 +01:00
|
12
|
+
default_executable:
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: nake
|
16
|
+
type: :development
|
17
|
+
version_requirement:
|
18
|
+
version_requirements: !ruby/object:Gem::Requirement
|
19
|
+
requirements:
|
20
|
+
- - ">="
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: "0"
|
23
|
+
version:
|
24
|
+
description: ""
|
25
|
+
email: knava.bestvinensis@gmail.com
|
26
|
+
executables: []
|
27
|
+
|
28
|
+
extensions: []
|
29
|
+
|
30
|
+
extra_rdoc_files: []
|
31
|
+
|
32
|
+
files:
|
33
|
+
- example/hooks/clone
|
34
|
+
- example/hooks/update
|
35
|
+
- example/README.textile
|
36
|
+
- example/tasks.rb
|
37
|
+
- example/www/index.html
|
38
|
+
- git-deployer.gemspec
|
39
|
+
- hooks/project/clone.exec.erb
|
40
|
+
- hooks/project/clone.source.erb
|
41
|
+
- hooks/project/update.exec.erb
|
42
|
+
- hooks/project/update.source.erb
|
43
|
+
- hooks/server/post-receive.erb
|
44
|
+
- README.textile
|
45
|
+
- tasks/git-deployer.nake
|
46
|
+
has_rdoc: true
|
47
|
+
homepage: http://github.com/botanicus/git-deployer
|
48
|
+
licenses: []
|
49
|
+
|
50
|
+
post_install_message:
|
51
|
+
rdoc_options: []
|
52
|
+
|
53
|
+
require_paths:
|
54
|
+
- tasks
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
requirements:
|
57
|
+
- - ">="
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
version: "0"
|
60
|
+
version:
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
requirements:
|
63
|
+
- - ">="
|
64
|
+
- !ruby/object:Gem::Version
|
65
|
+
version: "0"
|
66
|
+
version:
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project: git-deployer
|
70
|
+
rubygems_version: 1.3.5
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: Easy deploy system based on Git hooks
|
74
|
+
test_files: []
|
75
|
+
|