apperol 0.0.7 → 0.0.8
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 +4 -4
- data/.gitignore +1 -0
- data/apperol.gemspec +1 -1
- data/lib/apperol/cli.rb +67 -93
- data/lib/apperol/creds.rb +29 -0
- data/lib/apperol/github_client.rb +29 -0
- data/lib/apperol/heroku_client.rb +54 -0
- data/lib/apperol/response.rb +24 -0
- data/lib/apperol/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5ac9811222d781a47081d4c75503a5c4a0d1fdd6
|
4
|
+
data.tar.gz: 42f10ad07bf9cf917604fd01425fa35538bd95ff
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 96ec2f030b2e8f6fc5e4a628cb8377e9bc41141fe48397742c592d73448e5b78b219f45c3a42ebbd9bab24196220f36d7f534b72a4a31e35588cf32b84feba61
|
7
|
+
data.tar.gz: b46aa47a94c0dd798cf9812b8e486d690c45cf92c659929718018c49aabd2a347180390c6e98458c4a9b8f0bf2b8b05bbdc4dd40be3668e7623ab35d190ec078
|
data/apperol.gemspec
CHANGED
@@ -7,7 +7,7 @@ Gem::Specification.new do |spec|
|
|
7
7
|
spec.name = "apperol"
|
8
8
|
spec.version = Apperol::VERSION
|
9
9
|
spec.authors = ["Yannick"]
|
10
|
-
spec.email = ["yannick@heroku.com"]
|
10
|
+
spec.email = ["yannick@heroku.com", "opensource@heroku.com"]
|
11
11
|
spec.summary = %q{Create heroku app from heroku repository}
|
12
12
|
spec.description = %q{Create heroku app from heroku repository with app.json}
|
13
13
|
spec.homepage = "https://github.com/ys/apperol"
|
data/lib/apperol/cli.rb
CHANGED
@@ -7,6 +7,9 @@ require "netrc"
|
|
7
7
|
require "spinning_cursor"
|
8
8
|
|
9
9
|
require_relative "app_json"
|
10
|
+
require_relative "creds"
|
11
|
+
require_relative "heroku_client"
|
12
|
+
require_relative "github_client"
|
10
13
|
|
11
14
|
module Apperol
|
12
15
|
class CLI
|
@@ -48,66 +51,91 @@ module Apperol
|
|
48
51
|
@app_extension = args.shift
|
49
52
|
|
50
53
|
unless @app_extension
|
51
|
-
$stderr.puts(
|
54
|
+
$stderr.puts(parser.help)
|
52
55
|
exit EX_USAGE
|
53
56
|
end
|
54
57
|
end
|
55
58
|
|
56
59
|
def call
|
57
|
-
|
60
|
+
launch_app_setup do |response|
|
61
|
+
build_id = response["id"]
|
62
|
+
output_stream_url = get_output_stream_url(build_id)
|
63
|
+
stream_build(output_stream_url)
|
64
|
+
finalizing_setup(build_id)
|
65
|
+
end
|
58
66
|
end
|
59
67
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
req.body = app_setup_payload
|
68
|
+
private
|
69
|
+
|
70
|
+
def launch_app_setup
|
64
71
|
$stdout.puts("Setting up heroku app #{heroku_app_name}-#{@app_extension}")
|
65
|
-
|
66
|
-
if
|
67
|
-
$stderr.puts
|
72
|
+
response = heroku_client.post(app_setup_url, app_setup_payload)
|
73
|
+
if response.status != 202
|
74
|
+
$stderr.puts response.body["message"]
|
68
75
|
exit 1
|
69
76
|
else
|
70
|
-
|
77
|
+
yield response.body
|
71
78
|
end
|
72
79
|
end
|
73
80
|
|
74
|
-
def
|
75
|
-
|
76
|
-
|
77
|
-
res = {}
|
78
|
-
spin_wait("Setting up your app", "App setup done") do
|
79
|
-
loop do
|
80
|
-
res = JSON.parse(heroku_http.request(req).body)
|
81
|
-
break unless res["status"] == "pending"
|
82
|
-
end
|
81
|
+
def get_output_stream_url(build_id)
|
82
|
+
response = loop_on_build_until(build_id) do |response|
|
83
|
+
!response.body["build"]["output_stream_url"].nil? || response.body["status"] != "pending"
|
83
84
|
end
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
85
|
+
response.body["build"]["output_stream_url"]
|
86
|
+
end
|
87
|
+
|
88
|
+
def stream_build(url)
|
89
|
+
heroku_client.stream_build(url) do |chunk|
|
90
|
+
puts chunk
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def finalizing_setup(build_id)
|
95
|
+
response = loop_on_build_until(build_id) do |response|
|
96
|
+
response.body["status"] != "pending"
|
97
|
+
end
|
98
|
+
if response.body["status"] == "succeeded"
|
99
|
+
$stdout.puts("Application #{response.body["app"]["name"]}.herokuapp.com has been successfully created.")
|
89
100
|
exit 0
|
90
101
|
else
|
91
|
-
$stderr.puts("error: #{
|
92
|
-
unless
|
93
|
-
$stderr.puts(" #{
|
102
|
+
$stderr.puts("error: #{response.body["failure_message"]}")
|
103
|
+
unless response.body["manifest_errors"].empty?
|
104
|
+
$stderr.puts(" #{response.body["manifest_errors"]}")
|
94
105
|
end
|
95
|
-
unless
|
96
|
-
$stderr.puts(
|
106
|
+
unless response.body["postdeploy"].empty?
|
107
|
+
$stderr.puts(response.body["postdeploy"]["output"])
|
97
108
|
end
|
98
109
|
exit 1
|
99
110
|
end
|
100
111
|
end
|
101
112
|
|
113
|
+
def loop_on_build_until(build_id)
|
114
|
+
response = nil
|
115
|
+
spin_wait("Setting up your app", "App setup done") do
|
116
|
+
loop do
|
117
|
+
response = heroku_client.get(app_setup_url(build_id))
|
118
|
+
break if yield(response)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
response
|
122
|
+
end
|
123
|
+
|
124
|
+
def heroku_client
|
125
|
+
@heroku_client ||= Apperol::HerokuClient.new
|
126
|
+
end
|
127
|
+
|
128
|
+
def github_client
|
129
|
+
@github_client ||= Apperol::GithubClient.new
|
130
|
+
end
|
131
|
+
|
102
132
|
def spin_wait(banner_txt, message_txt)
|
103
133
|
SpinningCursor.run do
|
104
134
|
banner banner_txt
|
105
135
|
type :dots
|
106
136
|
message message_txt
|
107
137
|
end
|
108
|
-
|
109
138
|
yield
|
110
|
-
|
111
139
|
SpinningCursor.stop
|
112
140
|
end
|
113
141
|
|
@@ -115,19 +143,6 @@ module Apperol
|
|
115
143
|
URI("https://api.heroku.com/app-setups/#{id}")
|
116
144
|
end
|
117
145
|
|
118
|
-
def heroku_headers
|
119
|
-
{
|
120
|
-
"Content-Type" => "application/json",
|
121
|
-
"Accept" => "application/vnd.heroku+json; version=3"
|
122
|
-
}
|
123
|
-
end
|
124
|
-
|
125
|
-
def heroku_http
|
126
|
-
@heroku_http ||= Net::HTTP.new(app_setup_url.hostname, app_setup_url.port).tap do |http|
|
127
|
-
http.use_ssl = true
|
128
|
-
end
|
129
|
-
end
|
130
|
-
|
131
146
|
def app_setup_payload
|
132
147
|
payload = {
|
133
148
|
app: {
|
@@ -155,27 +170,13 @@ module Apperol
|
|
155
170
|
end
|
156
171
|
|
157
172
|
def github_tarball_location
|
158
|
-
$stdout.puts("Getting tarball location for
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
else
|
163
|
-
$stderr.puts("error: No tarball found for #{github_url + tarball_path} : #{JSON.parse(res.body)["message"]}")
|
173
|
+
$stdout.puts("Getting tarball location for #{repo} on branch #{branch}")
|
174
|
+
location = github_client.tarball(repo, branch)
|
175
|
+
unless location
|
176
|
+
$stderr.puts("error: No tarball found for #{repo}")
|
164
177
|
exit 1
|
165
178
|
end
|
166
|
-
|
167
|
-
|
168
|
-
def github_get(path)
|
169
|
-
puts github_url + path
|
170
|
-
req = Net::HTTP::Get.new(github_url + path)
|
171
|
-
req.basic_auth *github_creds
|
172
|
-
github_http.request(req)
|
173
|
-
end
|
174
|
-
|
175
|
-
def github_http
|
176
|
-
@github_http ||= Net::HTTP.new(github_url.hostname, github_url.port).tap do |http|
|
177
|
-
http.use_ssl = true
|
178
|
-
end
|
179
|
+
location
|
179
180
|
end
|
180
181
|
|
181
182
|
def personal_app?
|
@@ -196,19 +197,12 @@ module Apperol
|
|
196
197
|
|
197
198
|
def user
|
198
199
|
@user ||= @options.fetch(:user) {
|
199
|
-
res =
|
200
|
-
|
201
|
-
}
|
202
|
-
end
|
203
|
-
|
204
|
-
def rollbar_token
|
205
|
-
@options.fetch(:rollbar_token) {
|
206
|
-
$stdout.puts("Missing rollbar_token option, its not required but you won't have exception tracking")
|
207
|
-
""
|
200
|
+
res = github_client.get("/user")
|
201
|
+
res.body["login"]
|
208
202
|
}
|
209
203
|
end
|
210
204
|
|
211
|
-
def
|
205
|
+
def branch
|
212
206
|
@options.fetch(:branch, "master")
|
213
207
|
end
|
214
208
|
|
@@ -222,26 +216,6 @@ module Apperol
|
|
222
216
|
}
|
223
217
|
end
|
224
218
|
|
225
|
-
def github_url
|
226
|
-
URI("https://api.github.com")
|
227
|
-
end
|
228
|
-
|
229
|
-
def tarball_path
|
230
|
-
"/repos/#{repo}/tarball/#{github_branch}"
|
231
|
-
end
|
232
|
-
|
233
|
-
def github_creds
|
234
|
-
netrc["api.github.com"]
|
235
|
-
end
|
236
|
-
|
237
|
-
def heroku_creds
|
238
|
-
netrc["api.heroku.com"]
|
239
|
-
end
|
240
|
-
|
241
|
-
def netrc
|
242
|
-
@netrc ||= Netrc.read
|
243
|
-
end
|
244
|
-
|
245
219
|
def heroku_app_name
|
246
220
|
Dir.pwd.split("/").last
|
247
221
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Apperol
|
2
|
+
class Creds
|
3
|
+
class << self
|
4
|
+
def heroku
|
5
|
+
instance.heroku
|
6
|
+
end
|
7
|
+
|
8
|
+
def github
|
9
|
+
instance.github
|
10
|
+
end
|
11
|
+
|
12
|
+
def instance
|
13
|
+
@instance ||= new
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def heroku
|
18
|
+
netrc["api.heroku.com"]
|
19
|
+
end
|
20
|
+
|
21
|
+
def github
|
22
|
+
netrc["api.github.com"]
|
23
|
+
end
|
24
|
+
|
25
|
+
def netrc
|
26
|
+
@netrc ||= Netrc.read
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require_relative "response"
|
2
|
+
|
3
|
+
module Apperol
|
4
|
+
class GithubClient
|
5
|
+
|
6
|
+
def tarball(repository, branch = "master")
|
7
|
+
tarball_path = "/repos/#{repository}/tarball/#{branch}"
|
8
|
+
res = get(tarball_path)
|
9
|
+
res.header("Location")
|
10
|
+
end
|
11
|
+
|
12
|
+
def get(path)
|
13
|
+
req = Net::HTTP::Get.new(url + path)
|
14
|
+
req.basic_auth *Apperol::Creds.github
|
15
|
+
res = client.request(req)
|
16
|
+
Apperol::Response.new(res.code, res.body, headers: res.to_hash)
|
17
|
+
end
|
18
|
+
|
19
|
+
def client
|
20
|
+
@client ||= Net::HTTP.new(url.hostname, url.port).tap do |http|
|
21
|
+
http.use_ssl = true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def url
|
26
|
+
URI("https://api.github.com")
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative "response"
|
2
|
+
|
3
|
+
module Apperol
|
4
|
+
class HerokuClient
|
5
|
+
|
6
|
+
def get(url)
|
7
|
+
request = Net::HTTP::Get.new(url, initheader = default_headers)
|
8
|
+
request.basic_auth *Apperol::Creds.heroku
|
9
|
+
res = client.request(request)
|
10
|
+
Apperol::Response.new(res.code, res.body)
|
11
|
+
end
|
12
|
+
|
13
|
+
def post(url, body)
|
14
|
+
request = Net::HTTP::Post.new(url, initheader = default_headers)
|
15
|
+
request.basic_auth *Apperol::Creds.heroku
|
16
|
+
request.body = body
|
17
|
+
res = client.request(request)
|
18
|
+
Apperol::Response.new(res.code, res.body)
|
19
|
+
end
|
20
|
+
|
21
|
+
def stream_build(url)
|
22
|
+
req = Net::HTTP::Get.new(url, initheader = default_headers)
|
23
|
+
req.basic_auth *Apperol::Creds.heroku
|
24
|
+
builds_client.request req do |response|
|
25
|
+
response.read_body do |chunk|
|
26
|
+
yield chunk
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def builds_client
|
32
|
+
@builds_client ||= Net::HTTP.new(builds_url.hostname, 443).tap do |http|
|
33
|
+
http.use_ssl = true
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def builds_url
|
38
|
+
URI("https://build-output.heroku.com")
|
39
|
+
end
|
40
|
+
|
41
|
+
def default_headers
|
42
|
+
{
|
43
|
+
"Content-Type" => "application/json",
|
44
|
+
"Accept" => "application/vnd.heroku+json; version=edge"
|
45
|
+
}
|
46
|
+
end
|
47
|
+
|
48
|
+
def client
|
49
|
+
@client ||= Net::HTTP.new("api.heroku.com", 443).tap do |http|
|
50
|
+
http.use_ssl = true
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Apperol
|
2
|
+
class Response
|
3
|
+
attr_accessor :status, :original_body, :headers
|
4
|
+
|
5
|
+
def initialize(status, body, options = {})
|
6
|
+
@status = status.to_i
|
7
|
+
@original_body = body
|
8
|
+
@headers = options[:headers]
|
9
|
+
end
|
10
|
+
|
11
|
+
def body
|
12
|
+
@body ||= JSON.parse(original_body)
|
13
|
+
end
|
14
|
+
|
15
|
+
def header(key)
|
16
|
+
@headers[key.downcase].first
|
17
|
+
end
|
18
|
+
|
19
|
+
def [](key)
|
20
|
+
puts @headers
|
21
|
+
@headers[key.downcase].first
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
data/lib/apperol/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: apperol
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.8
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yannick
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-
|
11
|
+
date: 2014-11-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -69,6 +69,7 @@ dependencies:
|
|
69
69
|
description: Create heroku app from heroku repository with app.json
|
70
70
|
email:
|
71
71
|
- yannick@heroku.com
|
72
|
+
- opensource@heroku.com
|
72
73
|
executables:
|
73
74
|
- apperol
|
74
75
|
extensions: []
|
@@ -84,6 +85,10 @@ files:
|
|
84
85
|
- lib/apperol.rb
|
85
86
|
- lib/apperol/app_json.rb
|
86
87
|
- lib/apperol/cli.rb
|
88
|
+
- lib/apperol/creds.rb
|
89
|
+
- lib/apperol/github_client.rb
|
90
|
+
- lib/apperol/heroku_client.rb
|
91
|
+
- lib/apperol/response.rb
|
87
92
|
- lib/apperol/version.rb
|
88
93
|
homepage: https://github.com/ys/apperol
|
89
94
|
licenses:
|