heroku_deployer 0.1
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.
- checksums.yaml +7 -0
- data/lib/amitree/git_client.rb +28 -0
- data/lib/amitree/heroku_client.rb +83 -0
- data/lib/heroku/new_api.rb +21 -0
- metadata +118 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 738576c9402da6ea58a47a34b432a9d1a8447f17
|
4
|
+
data.tar.gz: 7175f54727b6e9adedd2dc4a57c100c9d600a926
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 95f00f9e747d02ababc1af63bd8065aed134cc95d023a44fb57340efad7945e184919efd44d71a0919e1edd53e6cbe362e583f4a20ecd91739127eddcfa28754
|
7
|
+
data.tar.gz: 3691d23c33927c4bc6ad34adce55c6c9f0c325b4246abf2964d7504eb311535ff59129b157fdc4f8ee3e9d25ed0669abb7ee391887fad9c945b3eeafa04b3d92
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
|
3
|
+
module Amitree
|
4
|
+
class GitClient
|
5
|
+
def initialize(repository, username, password)
|
6
|
+
@repository = repository
|
7
|
+
@client = Octokit::Client.new login: username, password: password
|
8
|
+
end
|
9
|
+
|
10
|
+
def commits_between(rev1, rev2)
|
11
|
+
result = @client.compare @repository, rev1, rev2
|
12
|
+
result.commits
|
13
|
+
end
|
14
|
+
|
15
|
+
def commit_messages_between(rev1, rev2)
|
16
|
+
commits_between(rev1, rev2).map(&:commit).map(&:message)
|
17
|
+
end
|
18
|
+
|
19
|
+
def stories_worked_on_between(rev1, rev2)
|
20
|
+
messages = commit_messages_between(rev1, rev2)
|
21
|
+
messages.map{|msg| msg.scan /(?<=#)\d+/}.flatten.uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def link_to(rev)
|
25
|
+
"https://github.com/#{@repository}/commit/#{rev}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'heroku-api'
|
2
|
+
require 'heroku/new_api'
|
3
|
+
require 'rendezvous'
|
4
|
+
|
5
|
+
module Amitree
|
6
|
+
class HerokuClient
|
7
|
+
class Error < StandardError
|
8
|
+
end
|
9
|
+
|
10
|
+
def initialize(api_key, staging_app_name, production_app_name)
|
11
|
+
@heroku = Heroku::API.new(:api_key => api_key)
|
12
|
+
# We need to use the new API (not currently supported by the heroku-api gem) for deploy_to_production
|
13
|
+
@heroku_new = Heroku::NewAPI.new(:api_key => api_key)
|
14
|
+
@staging_app_name = staging_app_name
|
15
|
+
@production_app_name = production_app_name
|
16
|
+
@promoted_release_regexp = /Promote #{@staging_app_name} (v\d+)/
|
17
|
+
end
|
18
|
+
|
19
|
+
def current_production_release
|
20
|
+
get_releases(@production_app_name)[-1]
|
21
|
+
end
|
22
|
+
|
23
|
+
def last_promoted_production_release
|
24
|
+
get_releases(@production_app_name).reverse.detect{|release| promoted_from_staging?(release)} or raise Error.new "Can't find a production release that was promoted from staging!"
|
25
|
+
end
|
26
|
+
|
27
|
+
def staging_release_name(production_release)
|
28
|
+
unless production_release['descr'] =~ @promoted_release_regexp
|
29
|
+
raise Error.new "Production release was not promoted from staging: #{production_release['descr']}"
|
30
|
+
end
|
31
|
+
$1
|
32
|
+
end
|
33
|
+
|
34
|
+
def promoted_from_staging?(release)
|
35
|
+
release['descr'] =~ @promoted_release_regexp
|
36
|
+
end
|
37
|
+
|
38
|
+
def staging_releases_since(staging_release_name)
|
39
|
+
staging_releases = get_releases(@staging_app_name)
|
40
|
+
index = staging_releases.index { |release| release['name'] == staging_release_name }
|
41
|
+
if index.nil?
|
42
|
+
raise Error.new "Could not find staging release #{staging_release_name}"
|
43
|
+
end
|
44
|
+
staging_releases.slice(index+1, staging_releases.length)
|
45
|
+
end
|
46
|
+
|
47
|
+
def deploy_to_production(staging_release_name, options={})
|
48
|
+
slug = staging_slug(staging_release_name)
|
49
|
+
puts "Deploying slug to production: #{slug}"
|
50
|
+
unless options[:dry_run]
|
51
|
+
@heroku_new.post_release(@production_app_name, {'slug' => slug, 'description' => "Promote #{@staging_app_name} #{staging_release_name}"})
|
52
|
+
db_migrate_on_production
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def staging_slug(staging_release_name)
|
57
|
+
unless staging_release_name =~ /\Av(\d+)\z/
|
58
|
+
raise Error.new "Unexpected release name: #{staging_release_name}"
|
59
|
+
end
|
60
|
+
result = @heroku_new.get_release(@staging_app_name, $1)
|
61
|
+
result.body['slug']['id'] || raise(Error.new("Could not find slug in API response: #{result.inspect}"))
|
62
|
+
end
|
63
|
+
|
64
|
+
def db_migrate_on_production
|
65
|
+
heroku_run(@production_app_name, 'rake db:migrate db:seed')
|
66
|
+
end
|
67
|
+
|
68
|
+
private
|
69
|
+
def get_releases(app_name)
|
70
|
+
@heroku.get_releases(app_name).body
|
71
|
+
end
|
72
|
+
|
73
|
+
def heroku_run(app_name, command)
|
74
|
+
puts "Running command on #{app_name}: #{command}..."
|
75
|
+
data = @heroku.post_ps(app_name, command, { attach: true }).body
|
76
|
+
read, write = IO.pipe
|
77
|
+
Rendezvous.start(url: data['rendezvous_url'], input: read)
|
78
|
+
read.close
|
79
|
+
write.close
|
80
|
+
puts "Done."
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'multi_json'
|
2
|
+
|
3
|
+
module Heroku
|
4
|
+
class NewAPI < API
|
5
|
+
def initialize(options={})
|
6
|
+
options[:headers] ||= {}
|
7
|
+
options[:headers]['Accept'] = 'application/vnd.heroku+json; version=3'
|
8
|
+
super(options)
|
9
|
+
end
|
10
|
+
|
11
|
+
# POST /apps/:app/releases/:release
|
12
|
+
def post_release(app, query={})
|
13
|
+
request(
|
14
|
+
:expects => 201,
|
15
|
+
:method => :post,
|
16
|
+
:path => "/apps/#{app}/releases",
|
17
|
+
:body => MultiJson.dump(query)
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
metadata
ADDED
@@ -0,0 +1,118 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: heroku_deployer
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: '0.1'
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Nick Wargnier
|
8
|
+
- Tony Novak
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2014-05-23 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rspec
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
requirements:
|
18
|
+
- - '='
|
19
|
+
- !ruby/object:Gem::Version
|
20
|
+
version: 2.14.1
|
21
|
+
type: :development
|
22
|
+
prerelease: false
|
23
|
+
version_requirements: !ruby/object:Gem::Requirement
|
24
|
+
requirements:
|
25
|
+
- - '='
|
26
|
+
- !ruby/object:Gem::Version
|
27
|
+
version: 2.14.1
|
28
|
+
- !ruby/object:Gem::Dependency
|
29
|
+
name: octokit
|
30
|
+
requirement: !ruby/object:Gem::Requirement
|
31
|
+
requirements:
|
32
|
+
- - '='
|
33
|
+
- !ruby/object:Gem::Version
|
34
|
+
version: 2.7.1
|
35
|
+
type: :runtime
|
36
|
+
prerelease: false
|
37
|
+
version_requirements: !ruby/object:Gem::Requirement
|
38
|
+
requirements:
|
39
|
+
- - '='
|
40
|
+
- !ruby/object:Gem::Version
|
41
|
+
version: 2.7.1
|
42
|
+
- !ruby/object:Gem::Dependency
|
43
|
+
name: heroku-api
|
44
|
+
requirement: !ruby/object:Gem::Requirement
|
45
|
+
requirements:
|
46
|
+
- - '='
|
47
|
+
- !ruby/object:Gem::Version
|
48
|
+
version: 0.3.17
|
49
|
+
type: :runtime
|
50
|
+
prerelease: false
|
51
|
+
version_requirements: !ruby/object:Gem::Requirement
|
52
|
+
requirements:
|
53
|
+
- - '='
|
54
|
+
- !ruby/object:Gem::Version
|
55
|
+
version: 0.3.17
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: rendezvous
|
58
|
+
requirement: !ruby/object:Gem::Requirement
|
59
|
+
requirements:
|
60
|
+
- - '='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: 0.0.2
|
63
|
+
type: :runtime
|
64
|
+
prerelease: false
|
65
|
+
version_requirements: !ruby/object:Gem::Requirement
|
66
|
+
requirements:
|
67
|
+
- - '='
|
68
|
+
- !ruby/object:Gem::Version
|
69
|
+
version: 0.0.2
|
70
|
+
- !ruby/object:Gem::Dependency
|
71
|
+
name: pivotal-tracker
|
72
|
+
requirement: !ruby/object:Gem::Requirement
|
73
|
+
requirements:
|
74
|
+
- - '='
|
75
|
+
- !ruby/object:Gem::Version
|
76
|
+
version: 0.5.12
|
77
|
+
type: :runtime
|
78
|
+
prerelease: false
|
79
|
+
version_requirements: !ruby/object:Gem::Requirement
|
80
|
+
requirements:
|
81
|
+
- - '='
|
82
|
+
- !ruby/object:Gem::Version
|
83
|
+
version: 0.5.12
|
84
|
+
description: Gem that handles automatic deployment of code to Heroku, integrating
|
85
|
+
with Pivotal Tracker and Git
|
86
|
+
email: engineering@amitree.com
|
87
|
+
executables: []
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- lib/amitree/git_client.rb
|
92
|
+
- lib/amitree/heroku_client.rb
|
93
|
+
- lib/heroku/new_api.rb
|
94
|
+
homepage: http://rubygems.org/gems/heroku_deployer
|
95
|
+
licenses:
|
96
|
+
- MIT
|
97
|
+
metadata: {}
|
98
|
+
post_install_message:
|
99
|
+
rdoc_options: []
|
100
|
+
require_paths:
|
101
|
+
- lib
|
102
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
103
|
+
requirements:
|
104
|
+
- - "~>"
|
105
|
+
- !ruby/object:Gem::Version
|
106
|
+
version: '2.0'
|
107
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: '0'
|
112
|
+
requirements: []
|
113
|
+
rubyforge_project:
|
114
|
+
rubygems_version: 2.2.2
|
115
|
+
signing_key:
|
116
|
+
specification_version: 4
|
117
|
+
summary: Heroku Deployer
|
118
|
+
test_files: []
|