cap-ext-webistrano 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
@@ -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.
@@ -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
@@ -0,0 +1,4 @@
1
+ ---
2
+ :minor: 1
3
+ :patch: 4
4
+ :major: 0
@@ -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,7 @@
1
+ class Deployment < ActiveResource::Base
2
+ def self.configure(config)
3
+ Deployment.site = "#{config[:webistrano_home]}/projects/:project_id/stages/:stage_id"
4
+ Deployment.user = config[:user]
5
+ Deployment.password = config[:password]
6
+ end
7
+ 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,7 @@
1
+ class Stage < ActiveResource::Base
2
+ def self.configure(config)
3
+ Stage.site = "#{config[:webistrano_home]}/projects/:project_id"
4
+ Stage.user = config[:user]
5
+ Stage.password = config[:password]
6
+ end
7
+ end
@@ -0,0 +1,53 @@
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
+ exit(-1) unless @deployment.status == "success"
51
+ end
52
+ end
53
+ 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,9 @@
1
+ $:.unshift(File.dirname(File.expand_path(__FILE__)))
2
+ require 'test_helper.rb'
3
+ require 'cap_ext_webistrano/project'
4
+
5
+ class ProjectTestCase < Test::Unit::TestCase
6
+ should "set the base url for project" do
7
+ Project.site = "http://localhots:3000"
8
+ end
9
+ end
@@ -0,0 +1,93 @@
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!", :status => "success")
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, :description => nil).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
+ @deployment1.stubs(:status).returns("success")
81
+ Deployment.stubs(:create).returns(@deployment1)
82
+ end
83
+
84
+ should "concat the deployment log" do
85
+ Deployment.expects(:find).returns(@deployment1).in_sequence(@seq)
86
+ Deployment.expects(:find).returns(@deployment2).in_sequence(@seq)
87
+ @task.run
88
+ assert_equal "Chunky bacon is my bitch", @task.log
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,11 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+
4
+ gem 'thoughtbot-shoulda', '>= 2.0.0'
5
+ require 'shoulda'
6
+ gem 'capistrano'
7
+ require 'capistrano'
8
+ gem 'mocha'
9
+ require 'mocha'
10
+
11
+ $:.unshift(File.join(File.dirname(File.expand_path(__FILE__)), "..", "lib"))
metadata ADDED
@@ -0,0 +1,108 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cap-ext-webistrano
3
+ version: !ruby/object:Gem::Version
4
+ hash: 19
5
+ prerelease: false
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 4
10
+ version: 0.1.4
11
+ platform: ruby
12
+ authors:
13
+ - Mathias Meyer
14
+ - Jon Moses
15
+ autorequire:
16
+ bindir: bin
17
+ cert_chain: []
18
+
19
+ date: 2010-10-29 00:00:00 -04:00
20
+ default_executable:
21
+ dependencies:
22
+ - !ruby/object:Gem::Dependency
23
+ name: capistrano
24
+ prerelease: false
25
+ requirement: &id001 !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ">="
29
+ - !ruby/object:Gem::Version
30
+ hash: 3
31
+ segments:
32
+ - 0
33
+ version: "0"
34
+ type: :runtime
35
+ version_requirements: *id001
36
+ - !ruby/object:Gem::Dependency
37
+ name: activeresource
38
+ prerelease: false
39
+ requirement: &id002 !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ">="
43
+ - !ruby/object:Gem::Version
44
+ hash: 3
45
+ segments:
46
+ - 0
47
+ version: "0"
48
+ type: :runtime
49
+ version_requirements: *id002
50
+ description:
51
+ email: jon@burningbush.us
52
+ executables: []
53
+
54
+ extensions: []
55
+
56
+ extra_rdoc_files: []
57
+
58
+ files:
59
+ - Rakefile
60
+ - README.markdown
61
+ - VERSION.yml
62
+ - lib/cap_ext_webistrano/deployment.rb
63
+ - lib/cap_ext_webistrano/project.rb
64
+ - lib/cap_ext_webistrano/stage.rb
65
+ - lib/cap_ext_webistrano/task.rb
66
+ - lib/cap_ext_webistrano.rb
67
+ - test/cap_ext_webistrano_shoulda.rb
68
+ - test/capistrano_stub.rb
69
+ - test/project_shoulda.rb
70
+ - test/task_shoulda.rb
71
+ - test/test_helper.rb
72
+ has_rdoc: true
73
+ homepage: http://github.com/jmoses/cap-ext-webistrano
74
+ licenses: []
75
+
76
+ post_install_message:
77
+ rdoc_options:
78
+ - --inline-source
79
+ - --charset=UTF-8
80
+ require_paths:
81
+ - lib
82
+ required_ruby_version: !ruby/object:Gem::Requirement
83
+ none: false
84
+ requirements:
85
+ - - ">="
86
+ - !ruby/object:Gem::Version
87
+ hash: 3
88
+ segments:
89
+ - 0
90
+ version: "0"
91
+ required_rubygems_version: !ruby/object:Gem::Requirement
92
+ none: false
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ hash: 3
97
+ segments:
98
+ - 0
99
+ version: "0"
100
+ requirements: []
101
+
102
+ rubyforge_project:
103
+ rubygems_version: 1.3.7
104
+ signing_key:
105
+ specification_version: 2
106
+ 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.
107
+ test_files: []
108
+