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.
@@ -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: 2
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,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,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,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
@@ -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,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
+