capistrano-hivequeen 0.5.0 → 0.6.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -6,7 +6,7 @@ Gem::Specification.new do |s|
6
6
  ## If your rubyforge_project name is different, then edit it and comment out
7
7
  ## the sub! line in the Rakefile
8
8
  s.name = 'capistrano-hivequeen'
9
- s.version = '0.5.0'
9
+ s.version = '0.6.0'
10
10
  s.date = Time.now.strftime("%Y-%m-%d")
11
11
 
12
12
  ## Make sure your summary is short. The description may be as long
@@ -16,6 +16,10 @@ Capistrano::Configuration.instance(:must_exist).load do
16
16
  set :repository, HiveQueen.repository
17
17
  set :scm, :git
18
18
 
19
+ # By default, don't override deployments if there's another deployment in progress.
20
+ # From the command line, use -s override=true to force a deployment
21
+ set :override, false
22
+
19
23
  # Load capistrano multi-stage extension
20
24
  require 'fileutils' # required until https://github.com/capistrano/capistrano-ext/commit/930ca840a0b4adad0ec53546790b3f5ffe726538 is released
21
25
  require 'capistrano/ext/multistage'
@@ -8,6 +8,28 @@ Capistrano::Configuration.instance.load do
8
8
  end
9
9
  end
10
10
 
11
+ before "deploy:update", "hivequeen:start"
12
+ before "setup", "hivequeen:start"
13
+ namespace :hivequeen do
14
+ desc "[internal] Start a deployment in hivequeen"
15
+ task :start do
16
+ # TODO: is there a better way to determine what cap tasks are running?
17
+ tasks = ARGV.reject{|task_name| stage.to_s == task_name}
18
+ params = {
19
+ :task => tasks.join(' '),
20
+ :commit => real_revision,
21
+ :override => override
22
+ }
23
+ begin
24
+ deployment = HiveQueen.start_deployment(environment_id, params)
25
+ set :deployment_id, deployment['id']
26
+ at_exit { HiveQueen.finish_deployment(environment_id, deployment['id']) }
27
+ rescue HiveQueen::DeploymentError
28
+ abort "Cannot start deployment. Errors: #{$!.message}"
29
+ end
30
+ end
31
+ end
32
+
11
33
  desc "Deploy without migrations"
12
34
  task(:hotfix) { deploy.default }
13
35
 
@@ -8,11 +8,14 @@ require 'base64'
8
8
  # - environment not found
9
9
  # - environment not ready: fail
10
10
  class HiveQueen
11
+ class DeploymentError < Exception; end
12
+ class InsecureCredentials < Exception; end
13
+
11
14
  class << self
12
15
  attr_accessor :endpoint, :logger, :project, :username, :password
13
16
 
14
17
  def project_data
15
- @project_data ||= fetch("/projects/#{project}.json")
18
+ @project_data ||= get("/projects/#{project}.json")
16
19
  end
17
20
 
18
21
  def environments
@@ -30,18 +33,40 @@ class HiveQueen
30
33
  def roles(env_id)
31
34
  env_id = env_id.to_sym
32
35
  @roles ||= {}
33
- @roles[env_id] ||= fetch("/environments/#{env_id}.json")
36
+ @roles[env_id] ||= get("/environments/#{env_id}.json")
37
+ end
38
+
39
+ def start_deployment(environment_id, params)
40
+ required_params = [:task, :commit]
41
+ required_params.each do |key|
42
+ raise ArgumentError.new("#{key} is a required param") unless params.key?(key)
43
+ end
44
+ put_or_post('POST', "/environments/#{environment_id}/deployments.json", :deployment => params)
45
+ end
46
+
47
+ def finish_deployment(environment_id, deployment_id)
48
+ state = $! ? 'failed' : 'succeeded'
49
+ puts "Finishing deployment in Hivequeen. State: #{state}"
50
+ params = {:deployment => {:state => state}}
51
+ put_or_post('PUT', "/environments/#{environment_id}/deployments/#{deployment_id}.json", params)
34
52
  end
35
53
 
36
54
  # Load credentials from ~/.hivequeen
37
55
  def get_credentials!
38
56
  @username, @password = File.read(credential_path).chomp.split(':')
39
57
  raise unless username && password
58
+ # Check that credentials are not accessible to world or group
59
+ mode = File.stat(credential_path).mode
60
+ raise InsecureCredentials unless (mode % 64 == 0)
61
+ rescue InsecureCredentials
62
+ puts "#{credential_path} is insecure. Please change you password and run"
63
+ puts "chmod 600 #{credential_path}"
64
+ exit 1
40
65
  rescue Errno::ENOENT, RuntimeError
41
66
  puts "Could not read HiveQueen credentials from #{credential_path}."
42
67
  puts "#{credential_path} should contain your username and password seperated by a colon"
43
68
  puts "Run this command with your credentials:"
44
- puts " $ echo username:password > #{credential_path}"
69
+ puts " $ echo username:password > #{credential_path}; chmod 600 #{credential_path}"
45
70
  exit 1
46
71
  end
47
72
 
@@ -59,7 +84,7 @@ class HiveQueen
59
84
  { 'Authorization' => "Basic #{value}" }
60
85
  end
61
86
 
62
- def fetch(path)
87
+ def get(path)
63
88
  url = "#{endpoint}#{path}"
64
89
  logger.trace "Fetching #{url}"
65
90
  response = connection.request(:method => 'GET', :path => path, :headers => auth_header)
@@ -69,5 +94,19 @@ class HiveQueen
69
94
  JSON.parse(response.body)
70
95
  end
71
96
 
97
+ def put_or_post(method, path, data)
98
+ headers = auth_header.merge("Content-type"=>"application/json", "Accept"=>"application/json")
99
+ response = connection.request(:path => path, :method => method, :headers => headers, :body => data.to_json)
100
+ case response.status
101
+ when (200..299)
102
+ JSON.parse(response.body)
103
+ when (400..499)
104
+ errors = JSON.parse(response.body)
105
+ raise DeploymentError.new(errors.inspect)
106
+ else
107
+ raise "Request to #{path} returned #{response.status} status"
108
+ end
109
+ end
110
+
72
111
  end
73
112
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: capistrano-hivequeen
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 0
8
- - 5
8
+ - 6
9
9
  - 0
10
- version: 0.5.0
10
+ version: 0.6.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Aaron Suggs
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-10-18 00:00:00 -04:00
18
+ date: 2011-10-20 00:00:00 -04:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency