apperol 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: db158e412b26ecb904f357742bd9e6560d573627
4
+ data.tar.gz: 9d9939c3ec0104b2a3c1b860268b9a6cee9c22ae
5
+ SHA512:
6
+ metadata.gz: d15027aed70b6c7850587104b070477df35d4eecca06a640c4ab5a1c583b61a88682aa4cbf7a50881cd1ef2a33dff2eba09e124cb170b923d6201b8c3b5b366d
7
+ data.tar.gz: 059e5e660c1b8c106ec44492df8d5505e128fe04f264f7ff78c065778ee15a41a8f2849cb5985d3ca7a1d885825daf453b6b1a1a1aedc2fbe686325f1c71ceda
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in apperol.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Yannick
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,48 @@
1
+ # Apperol
2
+
3
+ Create apps from heroku repositories on GitHub.
4
+ Use app.json to customize options.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'apperol'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install apperol
21
+
22
+ ## Usage
23
+
24
+ ```
25
+ Usage: apperol [options] [app_extension]
26
+ -p, --personal Force app in personal apps instead of orgs
27
+ -s, --stack stack Stack for app on heroku
28
+ -b, --branch branch Branch to setup app from
29
+ -r, --repo repo GitHub repository source
30
+ -o, --org org GitHub org where the current repo is located
31
+ -u, --user user GitHub user where the current repo is located
32
+ -h, --help Displays Help
33
+
34
+ ```
35
+
36
+ ## Information
37
+
38
+ - App will be named [current_dir]-[app_extension] e.g.: direwolf-staging
39
+ - Apperol CLI will have many options based on `env` part of the `app.json`
40
+ - Apperol CLI uses heroku org by default, use `-r user/repo` to specify yours.
41
+
42
+ ## Contributing
43
+
44
+ 1. Fork it ( https://github.com/[my-github-username]/apperol/fork )
45
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
46
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
47
+ 4. Push to the branch (`git push origin my-new-feature`)
48
+ 5. Create a new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/apperol.gemspec ADDED
@@ -0,0 +1,26 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'apperol/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "apperol"
8
+ spec.version = Apperol::VERSION
9
+ spec.authors = ["Yannick"]
10
+ spec.email = ["yannick@heroku.com"]
11
+ spec.summary = %q{Create heroku app from heroku repository}
12
+ spec.description = %q{Create heroku app from heroku repository with app.json}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_development_dependency "bundler", "~> 1.7"
22
+ spec.add_development_dependency "rake", "~> 10.0"
23
+
24
+ spec.add_dependency "netrc", "~> 0.8.0"
25
+ spec.add_dependency "spinning_cursor", "~> 0.3.0"
26
+ end
data/bin/apperol ADDED
@@ -0,0 +1,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'apperol'
4
+ puts Apperol::CLI.new(ARGV).call
5
+
@@ -0,0 +1,244 @@
1
+ require "bundler"
2
+ require "net/http"
3
+ require "openssl"
4
+ require "json"
5
+ require "optparse"
6
+ require "netrc"
7
+ require "spinning_cursor"
8
+
9
+ module Apperol
10
+ class CLI
11
+ EX_USAGE = 64
12
+
13
+ def initialize(args = [])
14
+ @options = {}
15
+
16
+ parser = OptionParser.new do|opts|
17
+ opts.banner = "Usage: apperol [options] [app_extension]"
18
+ app_json["env"].each do |key, definition|
19
+ option_key_name = key.downcase.gsub("_", "-")
20
+ option_key_key = key.downcase.to_sym
21
+ # Set default
22
+ @options[option_key_key] = definition["value"]
23
+ opts.on("--#{option_key_name} value", "#{definition["description"]} (Default: '#{definition["value"]}')") do |value|
24
+ @options[option_key_key] = value
25
+ end
26
+ end
27
+ opts.on("-p", "--personal", "Force app in personal apps instead of orgs") do
28
+ @options[:personal] = true
29
+ end
30
+ opts.on("-r", "--repo repo", "GitHub repository used for the deploy") do |repo|
31
+ @options[:repo] = repo
32
+ end
33
+ opts.on("-o", "--org org", "GitHub org where current repo is located") do |org|
34
+ @options[:org] = org
35
+ end
36
+ opts.on("-u", "--user user", "GitHub user where current repo is located") do |user|
37
+ @options[:org] = user
38
+ end
39
+ opts.on("-s", "--stack stack", "Stack for app on heroku") do |stack|
40
+ @options[:stack] = stack
41
+ end
42
+ opts.on("-b", "--branch branch", "Branch to setup app from") do |branch|
43
+ @options[:branch] = branch
44
+ end
45
+ opts.on('-h', '--help', 'Displays Help') do
46
+ puts opts
47
+ exit EX_USAGE
48
+ end
49
+ end
50
+ parser.parse!(args)
51
+
52
+ @app_extension = args.shift
53
+
54
+ unless @app_extension
55
+ $stderr.puts("usage: apperol [options] [app_extension]")
56
+ exit EX_USAGE
57
+ end
58
+ end
59
+
60
+ def call
61
+ heroku_app_setup
62
+ end
63
+
64
+ def heroku_app_setup
65
+ req = Net::HTTP::Post.new(app_setup_url, initheader = heroku_headers)
66
+ req.basic_auth *heroku_creds
67
+ req.body = app_setup_payload
68
+ $stdout.puts("Setting up heroku app #{heroku_app_name}-#{@app_extension}")
69
+ res = heroku_http.request(req)
70
+ if res.code != "202"
71
+ $stderr.puts JSON.parse(res.body)["message"]
72
+ exit 1
73
+ else
74
+ poll_app_status(JSON.parse(res.body))
75
+ end
76
+ end
77
+
78
+ def poll_app_status(response)
79
+ req = Net::HTTP::Get.new(app_setup_url(response["id"]), initheader = heroku_headers)
80
+ req.basic_auth *heroku_creds
81
+ res = {}
82
+ spin_wait("Setting up your app", "App setup done") do
83
+ loop do
84
+ res = JSON.parse(heroku_http.request(req).body)
85
+ break unless res["status"] == "pending"
86
+ end
87
+ end
88
+ if res["status"] == "succeeded"
89
+ unless res["postdeploy"].empty?
90
+ $stdout.puts(res["postdeploy"]["output"])
91
+ end
92
+ $stdout.puts("Application #{res["app"]["name"]}.herokuapp.com has been successfully created.")
93
+ exit 0
94
+ else
95
+ $stderr.puts("error: #{res["failure_message"]}")
96
+ unless res["manifest_errors"].empty?
97
+ $stderr.puts(" #{res["manifest_errors"]}")
98
+ end
99
+ unless res["postdeploy"].empty?
100
+ $stderr.puts(res["postdeploy"]["output"])
101
+ end
102
+ exit 1
103
+ end
104
+ end
105
+
106
+ def spin_wait(banner_txt, message_txt)
107
+ SpinningCursor.run do
108
+ banner banner_txt
109
+ type :dots
110
+ message message_txt
111
+ end
112
+
113
+ yield
114
+
115
+ SpinningCursor.stop
116
+ end
117
+
118
+ def app_setup_url(id = nil)
119
+ URI("https://api.heroku.com/app-setups/#{id}")
120
+ end
121
+
122
+ def heroku_headers
123
+ {
124
+ "Content-Type" => "application/json",
125
+ "Accept" => "application/vnd.heroku+json; version=3"
126
+ }
127
+ end
128
+
129
+ def heroku_http
130
+ @heroku_http ||= Net::HTTP.new(app_setup_url.hostname, app_setup_url.port).tap do |http|
131
+ http.use_ssl = true
132
+ end
133
+ end
134
+
135
+ def app_setup_payload
136
+ payload = {
137
+ app: {
138
+ name: "#{heroku_app_name}-#{@app_extension}",
139
+ stack: stack
140
+ },
141
+ source_blob: { url: github_tarball_location },
142
+ overrides: { env: {}}
143
+ }
144
+ required_not_filled = []
145
+ app_json["env"].each do |key, definition|
146
+ value = @options[key.downcase.to_sym]
147
+ if definition["required"] && value.strip.empty?
148
+ required_not_filled << key
149
+ end
150
+ payload[:overrides][:env][key] = value
151
+ end
152
+ unless required_not_filled.empty?
153
+ $stderr.puts("error: Required fields not filled. Please specify them. #{required_not_filled}")
154
+ exit 1
155
+ end
156
+ payload[:app][:organization] = "heroku" unless personal_app?
157
+ payload.to_json
158
+ end
159
+
160
+ def github_tarball_location
161
+ $stdout.puts("Getting tarball location for empirical branch #{github_branch}")
162
+ req = Net::HTTP::Get.new(github_url)
163
+ req.basic_auth *github_creds
164
+ res = github_http.request(req)
165
+ if res["Location"]
166
+ res["Location"]
167
+ else
168
+ $stderr.puts("error: No tarball found for #{github_url} : #{JSON.parse(res.body)["message"]}")
169
+ exit 1
170
+ end
171
+ end
172
+
173
+ def github_http
174
+ @github_http ||= Net::HTTP.new(github_url.hostname, github_url.port).tap do |http|
175
+ http.use_ssl = true
176
+ end
177
+ end
178
+
179
+ def personal_app?
180
+ @options.fetch(:personal, false)
181
+ end
182
+
183
+ def repo
184
+ @options.fetch(:repo, default_repo)
185
+ end
186
+
187
+ def default_repo
188
+ "#{org}/#{heroku_app_name}"
189
+ end
190
+
191
+ def org
192
+ @options.fetch(:org, "heroku")
193
+ end
194
+
195
+ def rollbar_token
196
+ @options.fetch(:rollbar_token) {
197
+ $stdout.puts("Missing rollbar_token option, its not required but you won't have exception tracking")
198
+ ""
199
+ }
200
+ end
201
+
202
+ def github_branch
203
+ @options.fetch(:branch, "master")
204
+ end
205
+
206
+ def stack
207
+ @options.fetch(:stack, "cedar-14")
208
+ end
209
+
210
+ def rack_env
211
+ @options.fetch(:rack_env) {
212
+ @app_extension == "production" ? "production" : "staging"
213
+ }
214
+ end
215
+
216
+ def github_url
217
+ @github_url ||= URI("https://api.github.com/repos/#{repo}/tarball/#{github_branch}")
218
+ end
219
+
220
+ def github_creds
221
+ netrc["api.github.com"]
222
+ end
223
+
224
+ def heroku_creds
225
+ netrc["api.heroku.com"]
226
+ end
227
+
228
+ def netrc
229
+ @netrc ||= Netrc.read
230
+ end
231
+
232
+ def heroku_app_name
233
+ Dir.pwd.split("/").last
234
+ end
235
+
236
+ def app_json
237
+ unless File.exists?("app.json")
238
+ $stderr.puts("No app.json file here")
239
+ exit 1
240
+ end
241
+ @app_json ||= JSON.parse(File.read("app.json"))
242
+ end
243
+ end
244
+ end
@@ -0,0 +1,3 @@
1
+ module Apperol
2
+ VERSION = "0.0.1"
3
+ end
data/lib/apperol.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "apperol/version"
2
+ require "apperol/cli"
3
+
4
+ module Apperol
5
+ end
metadata ADDED
@@ -0,0 +1,111 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: apperol
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Yannick
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-10-22 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: netrc
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 0.8.0
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 0.8.0
55
+ - !ruby/object:Gem::Dependency
56
+ name: spinning_cursor
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: 0.3.0
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: 0.3.0
69
+ description: Create heroku app from heroku repository with app.json
70
+ email:
71
+ - yannick@heroku.com
72
+ executables:
73
+ - apperol
74
+ extensions: []
75
+ extra_rdoc_files: []
76
+ files:
77
+ - ".gitignore"
78
+ - Gemfile
79
+ - LICENSE.txt
80
+ - README.md
81
+ - Rakefile
82
+ - apperol.gemspec
83
+ - bin/apperol
84
+ - lib/apperol.rb
85
+ - lib/apperol/cli.rb
86
+ - lib/apperol/version.rb
87
+ homepage: ''
88
+ licenses:
89
+ - MIT
90
+ metadata: {}
91
+ post_install_message:
92
+ rdoc_options: []
93
+ require_paths:
94
+ - lib
95
+ required_ruby_version: !ruby/object:Gem::Requirement
96
+ requirements:
97
+ - - ">="
98
+ - !ruby/object:Gem::Version
99
+ version: '0'
100
+ required_rubygems_version: !ruby/object:Gem::Requirement
101
+ requirements:
102
+ - - ">="
103
+ - !ruby/object:Gem::Version
104
+ version: '0'
105
+ requirements: []
106
+ rubyforge_project:
107
+ rubygems_version: 2.2.2
108
+ signing_key:
109
+ specification_version: 4
110
+ summary: Create heroku app from heroku repository
111
+ test_files: []