chrismetcalf-cap-ext-webistrano 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README.markdown +63 -0
- data/Rakefile +34 -0
- data/VERSION.yml +4 -0
- data/lib/cap_ext_webistrano.rb +47 -0
- data/lib/cap_ext_webistrano/deployment.rb +7 -0
- data/lib/cap_ext_webistrano/project.rb +17 -0
- data/lib/cap_ext_webistrano/stage.rb +7 -0
- data/lib/cap_ext_webistrano/task.rb +52 -0
- data/test/cap_ext_webistrano_shoulda.rb +31 -0
- data/test/capistrano_stub.rb +39 -0
- data/test/project_shoulda.rb +9 -0
- data/test/task_shoulda.rb +92 -0
- data/test/test_helper.rb +11 -0
- metadata +86 -0
data/README.markdown
ADDED
@@ -0,0 +1,63 @@
|
|
1
|
+
A drop-n replacement for Capistrano so you can run tasks in Webistrano from
|
2
|
+
your command line just using the cap command.
|
3
|
+
|
4
|
+
Installation
|
5
|
+
============
|
6
|
+
|
7
|
+
gem install mattmatt-cap-ext-webistrano
|
8
|
+
|
9
|
+
Usage
|
10
|
+
=====
|
11
|
+
|
12
|
+
You can still use the capify command to generate the initial files required by
|
13
|
+
Capistrano.
|
14
|
+
|
15
|
+
In your Capfile, insert the following lines at the end.
|
16
|
+
|
17
|
+
gem 'mattmatt-cap-ext-webistrano'
|
18
|
+
require 'cap_ext_webistrano'
|
19
|
+
|
20
|
+
The Webistrano extensions require a couple of configuration options that you
|
21
|
+
can specify in your deploy.rb. They're pretty much the standard options you'd
|
22
|
+
configure for your application with Capistrano.
|
23
|
+
|
24
|
+
set :application, "My project" # The project as named in Webistrano
|
25
|
+
set :user, "admin"
|
26
|
+
set :password, "admin"
|
27
|
+
set :stage, "test" # specify the stage you want to deploy
|
28
|
+
set :webistrano_home, "http://webistrano.mydomain.com"
|
29
|
+
|
30
|
+
If you only have one stage in your project this should do, however with
|
31
|
+
several stages it'd be better to ask for the stage to be deployed:
|
32
|
+
|
33
|
+
set :stage do
|
34
|
+
Capistrano::CLI.ui.ask "Specify the stage to deploy: "
|
35
|
+
end
|
36
|
+
|
37
|
+
You can ask for the password too:
|
38
|
+
|
39
|
+
set :password do
|
40
|
+
Capistrano::CLI.password_prompt "Enter the deploy password: "
|
41
|
+
end
|
42
|
+
|
43
|
+
Optionally, you can specify configuration that you had setup webistrano to
|
44
|
+
prompt it:
|
45
|
+
|
46
|
+
set :prompt_config, { :password => 'mysecretpassword' }
|
47
|
+
|
48
|
+
Changes
|
49
|
+
=======
|
50
|
+
|
51
|
+
- Added support for prompt configuration (Lucas Mundim)
|
52
|
+
- Restore prefix_options hash as Active Resource lost it when reload method is called (Lucas Mundim)
|
53
|
+
- Solved "regular expression too big" exception error on large string
|
54
|
+
output (Michael Lim)
|
55
|
+
- Workaround to solve bug in @deployment.reload() not loading the site url
|
56
|
+
correctly (Michael Lim)
|
57
|
+
|
58
|
+
License
|
59
|
+
=======
|
60
|
+
|
61
|
+
(c) 2009 Mathias Meyer
|
62
|
+
|
63
|
+
Released under the MIT license.
|
data/Rakefile
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
require 'rake/testtask'
|
4
|
+
|
5
|
+
begin
|
6
|
+
require 'jeweler'
|
7
|
+
Jeweler::Tasks.new do |s|
|
8
|
+
s.name = 'cap-ext-webistrano'
|
9
|
+
s.summary = 'A drop-in replacement for Capistrano to fire off Webistrano deployments transparently without losing the joy of using the cap command. You need a fully configured Webistrano installation.'
|
10
|
+
s.email = 'meyer@paperplanes.de'
|
11
|
+
s.homepage = 'http://github.com/mattmatt/cap-ext-webistrano'
|
12
|
+
s.authors = ["Mathias Meyer"]
|
13
|
+
s.files = FileList["[A-Z]*", "{lib,test}/**/*"]
|
14
|
+
s.add_dependency 'capistrano'
|
15
|
+
s.add_dependency 'activeresource'
|
16
|
+
end
|
17
|
+
rescue LoadError
|
18
|
+
puts "Jeweler, or one of its dependencies, is not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "Default Task"
|
22
|
+
task :default => ["test"]
|
23
|
+
|
24
|
+
desc "Runs the unit tests"
|
25
|
+
task :test => "test:unit"
|
26
|
+
|
27
|
+
namespace :test do
|
28
|
+
desc "Unit tests"
|
29
|
+
Rake::TestTask.new(:unit) do |t|
|
30
|
+
t.libs << 'test/unit'
|
31
|
+
t.pattern = "test/*_shoulda.rb"
|
32
|
+
t.verbose = true
|
33
|
+
end
|
34
|
+
end
|
data/VERSION.yml
ADDED
@@ -0,0 +1,47 @@
|
|
1
|
+
$:.unshift(File.dirname(File.expand_path(__FILE__)))
|
2
|
+
require 'cap_ext_webistrano/task'
|
3
|
+
require 'active_resource'
|
4
|
+
require 'cap_ext_webistrano/project'
|
5
|
+
|
6
|
+
module CapExtWebistrano
|
7
|
+
def task(*args, &blk)
|
8
|
+
original_task(*args, &hijack_runner)
|
9
|
+
end
|
10
|
+
|
11
|
+
def after(*args)
|
12
|
+
end
|
13
|
+
|
14
|
+
def on(*args)
|
15
|
+
end
|
16
|
+
|
17
|
+
def before(*args)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
Capistrano::Configuration::Namespaces.class_eval do
|
22
|
+
alias :original_task :task
|
23
|
+
include CapExtWebistrano
|
24
|
+
end
|
25
|
+
|
26
|
+
Capistrano::Configuration::Execution.class_eval do
|
27
|
+
alias :original_find_and_execute_task :find_and_execute_task
|
28
|
+
|
29
|
+
def hijack_runner
|
30
|
+
@hijack_runner ||= lambda { CapExtWebistrano::Task.new(current_task.fully_qualified_name, self).run }
|
31
|
+
end
|
32
|
+
|
33
|
+
def hijack_capistrano
|
34
|
+
tasks.each {|tsk| tsk.last.instance_variable_set(:@body, hijack_runner)}
|
35
|
+
namespaces.each {|nmspace| nmspace.last.tasks.each {|tsk| tsk.last.instance_variable_set(:@body, hijack_runner)}}
|
36
|
+
end
|
37
|
+
|
38
|
+
def find_and_execute_task(task, hooks = {})
|
39
|
+
hijack_capistrano
|
40
|
+
@callbacks = {}
|
41
|
+
begin
|
42
|
+
original_find_and_execute_task(task, {})
|
43
|
+
rescue Capistrano::NoSuchTaskError
|
44
|
+
CapExtWebistrano::Task.new(task, self).run
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'active_resource'
|
2
|
+
|
3
|
+
class Project < ActiveResource::Base
|
4
|
+
def self.configure(config)
|
5
|
+
Project.site = config[:webistrano_home]
|
6
|
+
Project.user = config[:user]
|
7
|
+
Project.password = config[:password]
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.find_by_name(name)
|
11
|
+
project = find(:all).find {|project| project.name == name}
|
12
|
+
end
|
13
|
+
|
14
|
+
def find_stage(name)
|
15
|
+
Stage.find(:all, :params => {:project_id => id}).find {|stage| stage.name == name}
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
require 'cap_ext_webistrano/project'
|
2
|
+
require 'cap_ext_webistrano/stage'
|
3
|
+
require 'cap_ext_webistrano/deployment'
|
4
|
+
|
5
|
+
module CapExtWebistrano
|
6
|
+
class Task
|
7
|
+
attr_accessor :task, :log
|
8
|
+
|
9
|
+
def initialize(task, config)
|
10
|
+
@task = task
|
11
|
+
@config = config
|
12
|
+
@log = ""
|
13
|
+
end
|
14
|
+
|
15
|
+
def set_access_data
|
16
|
+
[Project, Stage, Deployment].each do |klazz|
|
17
|
+
klazz.configure(@config)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def loop_latest_deployment
|
22
|
+
still_running = true
|
23
|
+
prefix_options = @deployment.prefix_options
|
24
|
+
while still_running
|
25
|
+
sleep 5
|
26
|
+
@deployment.prefix_options.merge!(prefix_options)
|
27
|
+
@deployment.reload
|
28
|
+
print_diff(@deployment)
|
29
|
+
still_running = false unless @deployment.completed_at.nil?
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def print_diff(deployment)
|
34
|
+
if deployment.log
|
35
|
+
diff = deployment.log
|
36
|
+
diff.slice!(log)
|
37
|
+
print diff
|
38
|
+
log << diff
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def run
|
43
|
+
set_access_data
|
44
|
+
@project = Project.find_by_name(@config[:application])
|
45
|
+
@stage = @project.find_stage(@config[:stage])
|
46
|
+
params = { :task => task, :stage_id => @stage.id, :project_id => @project.id, :description => @config[:description] }
|
47
|
+
params.merge!(:prompt_config => @config[:prompt_config]) if @config.exists?(:prompt_config)
|
48
|
+
@deployment = Deployment.create(params)
|
49
|
+
loop_latest_deployment
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
$:.unshift(File.dirname(File.expand_path(__FILE__)))
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
require 'cap_ext_webistrano'
|
5
|
+
require 'capistrano_stub'
|
6
|
+
require 'cap_ext_webistrano/task'
|
7
|
+
|
8
|
+
class CapExtWebistranoTest < Test::Unit::TestCase
|
9
|
+
context "when executing tasks" do
|
10
|
+
setup do
|
11
|
+
@cap = CapistranoStub.new
|
12
|
+
CapExtWebistrano::Task.stubs(:new).returns @cap
|
13
|
+
end
|
14
|
+
|
15
|
+
should "convert all tasks to use the hijacking task" do
|
16
|
+
@cap.find_and_execute_task("deploy")
|
17
|
+
assert_nothing_raised {@cap.task.body.call}
|
18
|
+
end
|
19
|
+
|
20
|
+
should "call run on the task runner" do
|
21
|
+
@cap.find_and_execute_task("deploy")
|
22
|
+
assert @cap.ran
|
23
|
+
end
|
24
|
+
|
25
|
+
should "just call tasks that don't exist locally" do
|
26
|
+
@cap.stubs(:original_find_and_execute_task).raises(Capistrano::NoSuchTaskError.new, "the task activate:web does not exist")
|
27
|
+
@cap.find_and_execute_task("acticate:web")
|
28
|
+
assert @cap.ran
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'capistrano'
|
2
|
+
|
3
|
+
class CapistranoStub
|
4
|
+
include Capistrano::Configuration::Namespaces
|
5
|
+
include Capistrano::Configuration::Execution
|
6
|
+
attr_accessor :task, :ran
|
7
|
+
|
8
|
+
def logger
|
9
|
+
Logger.new(STDOUT)
|
10
|
+
end
|
11
|
+
|
12
|
+
def find_task(*args)
|
13
|
+
@task ||= Capistrano::TaskDefinition.new("deploy", top, {}) { raise "This shouldn't be raised" }
|
14
|
+
end
|
15
|
+
|
16
|
+
def original_find_and_execute_task(*args)
|
17
|
+
find_task.body.call
|
18
|
+
end
|
19
|
+
|
20
|
+
def namespaces
|
21
|
+
{:default => top}
|
22
|
+
end
|
23
|
+
|
24
|
+
def tasks
|
25
|
+
@tasks = {"deploy" => find_task}
|
26
|
+
end
|
27
|
+
|
28
|
+
def current_task
|
29
|
+
find_task
|
30
|
+
end
|
31
|
+
|
32
|
+
def [](key)
|
33
|
+
"admin"
|
34
|
+
end
|
35
|
+
|
36
|
+
def run
|
37
|
+
@ran = true
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
$:.unshift(File.dirname(File.expand_path(__FILE__)))
|
2
|
+
require 'test_helper.rb'
|
3
|
+
require 'cap_ext_webistrano/project'
|
4
|
+
require 'cap_ext_webistrano/task'
|
5
|
+
require 'cap_ext_webistrano/stage'
|
6
|
+
require 'cap_ext_webistrano/deployment'
|
7
|
+
|
8
|
+
|
9
|
+
class TaskTest < Test::Unit::TestCase
|
10
|
+
context "with a new task" do
|
11
|
+
setup do
|
12
|
+
@config = Capistrano::Configuration.new
|
13
|
+
@config[:webistrano_home] = "http://localhost:3000"
|
14
|
+
@config[:password] = "bacon"
|
15
|
+
@config[:user] = "chunky"
|
16
|
+
@task = CapExtWebistrano::Task.new("deploy", @config)
|
17
|
+
@task.set_access_data
|
18
|
+
@task.stubs(:sleep)
|
19
|
+
end
|
20
|
+
|
21
|
+
context "when setting up the configuration data" do
|
22
|
+
should "set the access data for project" do
|
23
|
+
assert_equal "http://localhost:3000", Project.site.to_s
|
24
|
+
assert_equal "chunky", Project.user
|
25
|
+
assert_equal "bacon", Project.password
|
26
|
+
end
|
27
|
+
|
28
|
+
should "set the access data for the stage" do
|
29
|
+
assert_equal "http://localhost:3000/projects/:project_id", Stage.site.to_s
|
30
|
+
assert_equal "chunky", Stage.user
|
31
|
+
assert_equal "bacon", Stage.password
|
32
|
+
end
|
33
|
+
|
34
|
+
should "set the access data for the deployment" do
|
35
|
+
assert_equal "http://localhost:3000/projects/:project_id/stages/:stage_id", Deployment.site.to_s
|
36
|
+
assert_equal "chunky", Deployment.user
|
37
|
+
assert_equal "bacon", Deployment.password
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
context "when running the task" do
|
42
|
+
setup do
|
43
|
+
@project1 = Project.new(:name => "Bacon", :id => 2)
|
44
|
+
@project2 = Project.new(:name => "Chunky", :id => 1)
|
45
|
+
Project.stubs(:find).returns([@project1, @project2])
|
46
|
+
@stage1 = Stage.new(:name => "test", :id => 3)
|
47
|
+
Stage.stubs(:find).returns([@stage1])
|
48
|
+
@deployment = Deployment.new(:completed_at => Time.now, :log => "Chunky bacon!")
|
49
|
+
Deployment.stubs(:create).returns @deployment
|
50
|
+
Deployment.stubs(:find).returns(@deployment)
|
51
|
+
@config[:application] = "Bacon"
|
52
|
+
@config[:stage] = "test"
|
53
|
+
end
|
54
|
+
|
55
|
+
should "find the project" do
|
56
|
+
Project.expects(:find).returns([@project1, @project2])
|
57
|
+
@task.run
|
58
|
+
end
|
59
|
+
|
60
|
+
should "find the stage" do
|
61
|
+
Stage.expects(:find).with(:all, :params => {:project_id => 2}).returns([@stage1])
|
62
|
+
@task.run
|
63
|
+
end
|
64
|
+
|
65
|
+
should "create a deployment" do
|
66
|
+
Deployment.expects(:create).with(:task => "deploy", :project_id => 2, :stage_id => 3).returns(@deployment)
|
67
|
+
@task.run
|
68
|
+
end
|
69
|
+
|
70
|
+
should "find the latest deployment" do
|
71
|
+
Deployment.expects(:find).returns @deployment
|
72
|
+
@task.run
|
73
|
+
end
|
74
|
+
|
75
|
+
context "when requesting the deployment multiple times" do
|
76
|
+
setup do
|
77
|
+
@seq = sequence("latest")
|
78
|
+
@deployment1 = Deployment.new(:completed_at => nil, :log => "Chunky bacon", :id => 2)
|
79
|
+
@deployment2 = Deployment.new(:completed_at => Time.now, :log => "Chunky bacon is my bitch", :id => 2)
|
80
|
+
Deployment.stubs(:create).returns(@deployment1)
|
81
|
+
end
|
82
|
+
|
83
|
+
should "concat the deployment log" do
|
84
|
+
Deployment.expects(:find).returns(@deployment1).in_sequence(@seq)
|
85
|
+
Deployment.expects(:find).returns(@deployment2).in_sequence(@seq)
|
86
|
+
@task.run
|
87
|
+
assert_equal "Chunky bacon is my bitch", @task.log
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
data/test/test_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,86 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: chrismetcalf-cap-ext-webistrano
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.2
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Mathias Meyer
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2009-06-25 00:00:00 -07:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: capistrano
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: "0"
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: activeresource
|
27
|
+
type: :runtime
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: "0"
|
34
|
+
version:
|
35
|
+
description:
|
36
|
+
email: meyer@paperplanes.de
|
37
|
+
executables: []
|
38
|
+
|
39
|
+
extensions: []
|
40
|
+
|
41
|
+
extra_rdoc_files: []
|
42
|
+
|
43
|
+
files:
|
44
|
+
- Rakefile
|
45
|
+
- README.markdown
|
46
|
+
- VERSION.yml
|
47
|
+
- lib/cap_ext_webistrano
|
48
|
+
- lib/cap_ext_webistrano/deployment.rb
|
49
|
+
- lib/cap_ext_webistrano/project.rb
|
50
|
+
- lib/cap_ext_webistrano/stage.rb
|
51
|
+
- lib/cap_ext_webistrano/task.rb
|
52
|
+
- lib/cap_ext_webistrano.rb
|
53
|
+
- test/cap_ext_webistrano_shoulda.rb
|
54
|
+
- test/capistrano_stub.rb
|
55
|
+
- test/project_shoulda.rb
|
56
|
+
- test/task_shoulda.rb
|
57
|
+
- test/test_helper.rb
|
58
|
+
has_rdoc: true
|
59
|
+
homepage: http://github.com/mattmatt/cap-ext-webistrano
|
60
|
+
post_install_message:
|
61
|
+
rdoc_options:
|
62
|
+
- --inline-source
|
63
|
+
- --charset=UTF-8
|
64
|
+
require_paths:
|
65
|
+
- lib
|
66
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
67
|
+
requirements:
|
68
|
+
- - ">="
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: "0"
|
71
|
+
version:
|
72
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - ">="
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: "0"
|
77
|
+
version:
|
78
|
+
requirements: []
|
79
|
+
|
80
|
+
rubyforge_project:
|
81
|
+
rubygems_version: 1.2.0
|
82
|
+
signing_key:
|
83
|
+
specification_version: 2
|
84
|
+
summary: A drop-in replacement for Capistrano to fire off Webistrano deployments transparently without losing the joy of using the cap command. You need a fully configured Webistrano installation.
|
85
|
+
test_files: []
|
86
|
+
|