better_heroku 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 7bee66aa4746a36e226976943195c0f108919bda
4
+ data.tar.gz: b656652bfff3acdcc4774231a2b4267bd0ed0a6e
5
+ SHA512:
6
+ metadata.gz: d4f92d4b7fa0014e40893157685dcdff329a3a35603b7286b319dbabf2218a04f0388c1597aba625c9c4d4950cbcfdccde54f5a461eaa2679a1881e0d7dc1000
7
+ data.tar.gz: fdf5ec34f75875816ec02e6d207c9f0af1250df73fc7f15d52357772570e89db934baf9a2415dba9062bf7bb6c0352813f830563851d5144207ff380a81d1b55
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2017 []().
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,191 @@
1
+ # BetterHeroku
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/better_heroku.svg)](http://badge.fury.io/rb/better_heroku)
4
+
5
+ <!-- Tocer[start]: Auto-generated, don't remove. -->
6
+
7
+ # Table of Contents
8
+
9
+ - [Features](#features)
10
+ - [Requirements](#requirements)
11
+ - [Setup](#setup)
12
+ - [Usage](#usage)
13
+ - [Authentication](#authentication)
14
+ - [Personal API tokens](#personal-api-tokens)
15
+ - [OAuth tokens](#oauth-tokens)
16
+ - [Mocking requests](#mocking-requests)
17
+ - [Tests](#tests)
18
+ - [Versioning](#versioning)
19
+ - [Code of Conduct](#code-of-conduct)
20
+ - [Contributions](#contributions)
21
+ - [License](#license)
22
+ - [History](#history)
23
+ - [Credits](#credits)
24
+
25
+ <!-- Tocer[finish]: Auto-generated, don't remove. -->
26
+
27
+ # Features
28
+
29
+ **BetterHeroku** Is a better Heroku client gem. The official "platform-api" Heroku client gem has several issues:
30
+
31
+ * The name itself is presumptuous. No mention of Heroku, assumes there's no other platform for which there's an API.
32
+ * The code is auto-generated from a `schema.json` provided by Heroku themselves. The gem is not updated nearly as
33
+ frequently as the `schema.json`, and lags behind the published APIs.
34
+ * The `schema.json` itself often lags behind the published API docs, and occasionally disagrees with them.
35
+ * It's not obvious how to consume the documented API.
36
+ * The way to get the [current account][heroku-account-info] is `heroku.account.info("~")`. The only way to know this
37
+ is to contact Heroku support.
38
+ * For a url with multiple parameters, like [info for a dyno for an app][heroku-dyno-info], is requested like
39
+ `heroku.dyno.info(app, dyno)`. The parameters are not documented, because the code is generated.
40
+ * The client provides no access to the lower-level HTTP client, Excon, to enable features such as HTTP persistence, or
41
+ to override it for testing.
42
+ * The client provides no means to add logging or instrumentation of the raw requests.
43
+
44
+ **BetterHeroku** attempts to solve all these problems by being a much simpler and less-opinionated implementation.
45
+
46
+ [heroku-account-info]: https://devcenter.heroku.com/articles/platform-api-reference#account
47
+ [heroku-dyno-info]: https://devcenter.heroku.com/articles/platform-api-reference#dyno-info
48
+
49
+ # Requirements
50
+
51
+ 0. [Ruby 2.4.0](https://www.ruby-lang.org)
52
+
53
+ # Setup
54
+
55
+ gem install better_heroku
56
+
57
+ Add the following to your Gemfile:
58
+
59
+ gem "better_heroku"
60
+
61
+ # Usage
62
+
63
+ ```ruby
64
+ client = BetterHeroku::Client.new.authenticate(token: my_token)
65
+ resp = client.get("apps", app_id)
66
+ resp.status #=> 200
67
+ resp["id"] #=> "01234567-89ab-cdef-0123-456789abcdef"
68
+ ```
69
+
70
+ The client pays no attention to the segments of the url passed in, and instead just joins them with `/`. This way, it
71
+ always matches 1:1 with the published API docs. In this example, we're using the [App Info][heroku-app-info] endpoint,
72
+ which looks like `GET /apps/{app_id_or_name}` in the docs. Just pass in the various segments in the same order, and
73
+ it'll work.
74
+
75
+ [heroku-app-info]: https://devcenter.heroku.com/articles/platform-api-reference#app-info
76
+
77
+ ## Authentication
78
+
79
+ **BetterHeroku** supports all the Heroku methods of authentication.
80
+
81
+ ### Personal API tokens
82
+
83
+ Get your personal API token from the Heroku dashboard, or from the CLI:
84
+
85
+ heroku auth:token
86
+
87
+ You'll get a UUID that you can use to make requests:
88
+
89
+ ```ruby
90
+ client = BetterHeroku::Client.new.authenticate(token: "01234567-89ab-cdef-0123-456789abcdef")
91
+ resp = client.get("apps", app_id)
92
+ ```
93
+
94
+ In one-off scripts this is fine, but for production usage I strongly recommend you put the token in a config or
95
+ environment variable.
96
+
97
+ ### OAuth tokens
98
+
99
+ When making requests on behalf of other users, you'll need to use OAuth tokens. See the
100
+ [Heroku OAuth docs][heroku-oauth-docs] for details.
101
+
102
+ Once set up, you'll have your Heroku OAuth secret. In this example, we've stored it in an environment variable called
103
+ `HEROKU_OAUTH_SECRET`. Once your users go through the web flow, you'll get back from Heroku a `token` and a
104
+ `refresh_token`. The `token` expires after 8 hours, and the `refresh_token` never expires, and may be used to obtain a
105
+ new token.
106
+
107
+ If you're not concerned about storing the token (perhaps you only make a few requests once a day, and the token would
108
+ have expired the next time you need it anyways), you can just authenticate with your secret and the refresh token:
109
+
110
+ ```ruby
111
+ client = BetterHeroku::Client.new
112
+ authenticated_client = client.oauth(secret: ENV["HEROKU_OAUTH_SECRET"], refresh_token: refresh_token)
113
+
114
+ resp = authenticated_client.get("apps", app_id)
115
+ ```
116
+
117
+ The `authenticated_client` will automatically handle refreshing the oauth token, and making requests using that. In the
118
+ unlikely situation where that object lives longer than the token expiry, it will automatically refresh again as needed.
119
+
120
+ Alternatively, the `authenticated_client` provides a callback that gets called when the refresh happens, which you can use
121
+ to persist the token for future requests:
122
+
123
+ ```ruby
124
+ authenticated_client.on_token_refresh do |response|
125
+ user.update_attribute(:oauth_token, response["access_token"])
126
+ end
127
+ ```
128
+
129
+ The `response` is the response body as documented in the [Heroku OAuth token refresh docs][heroku-token-refresh-docs].
130
+
131
+ [heroku-oauth-docs]: https://devcenter.heroku.com/articles/oauth
132
+ [heroku-token-refresh-docs]: https://devcenter.heroku.com/articles/oauth#token-refresh
133
+
134
+ ## Mocking requests
135
+
136
+ You probably don't want to always make actual requests against the Heroku API, so **BetterHeroku** provides a mechanism
137
+ to pass in the lower HTTP client. An example of what this might look like:
138
+
139
+ ```ruby
140
+ let(:http) { double(HTTP) }
141
+
142
+ it "should do awesome things" do
143
+ allow(http).to receive(:get).and_return(BetterHeroku::MockResponse.new({"id" => "01234567-89ab-cdef-0123-456789abcdef"})
144
+ client = BetterHeroku::Client.new(http: http)
145
+
146
+ resp = client.get("accounts", "01234567-89ab-cdef-0123-456789abcdef")
147
+
148
+ expect(resp["id"]).to eq "01234567-89ab-cdef-0123-456789abcdef"
149
+ end
150
+ ```
151
+
152
+ Also, be sure to check out the [FakeHTTP][fake-http] gem to mock the HTTP library with a Sinatra-like DSL.
153
+
154
+ [fake-http]: https://github.com/paul/fake_http
155
+
156
+ # Tests
157
+
158
+ To test, run:
159
+
160
+ rake
161
+
162
+ # Versioning
163
+
164
+ Read [Semantic Versioning](http://semver.org) for details. Briefly, it means:
165
+
166
+ - Patch (x.y.Z) - Incremented for small, backwards compatible, bug fixes.
167
+ - Minor (x.Y.z) - Incremented for new, backwards compatible, public API enhancements/fixes.
168
+ - Major (X.y.z) - Incremented for any backwards incompatible public API changes.
169
+
170
+ # Code of Conduct
171
+
172
+ Please note that this project is released with a [CODE OF CONDUCT](CODE_OF_CONDUCT.md). By
173
+ participating in this project you agree to abide by its terms.
174
+
175
+ # Contributions
176
+
177
+ Read [CONTRIBUTING](CONTRIBUTING.md) for details.
178
+
179
+ # License
180
+
181
+ Copyright (c) 2017 [Paul Sadauskas](mailto:psadauskas@gmail.com).
182
+ Read [LICENSE](LICENSE.md) for details.
183
+
184
+ # History
185
+
186
+ Read [CHANGES](CHANGES.md) for details.
187
+ Built with [Gemsmith](https://github.com/bkuhlmann/gemsmith).
188
+
189
+ # Credits
190
+
191
+ Developed by [Paul Sadauskas](mailto:psadauskas@gmail.com)
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "better_heroku/identity"
4
+
5
+ require "better_heroku/client"
6
+
7
+ module BetterHeroku
8
+ end
9
+
@@ -0,0 +1,29 @@
1
+ require "http"
2
+
3
+ module BetterHeroku
4
+ class Client
5
+ ACCEPT = "application/vnd.heroku+json; version=3"
6
+
7
+ attr_reader :host, :http
8
+
9
+ def initialize(host: "https://api.heroku.com", http: HTTP)
10
+ @host = host
11
+ @http = http.headers("Accept" => ACCEPT)
12
+ end
13
+
14
+ def get(*parts)
15
+ path = [host, *parts].join("/")
16
+ http.get(path)
17
+ end
18
+
19
+ def authenticate(token: token)
20
+ branch http.auth("Bearer #{token}")
21
+ end
22
+
23
+ private
24
+
25
+ def branch(http)
26
+ self.class.new http: http
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BetterHeroku
4
+ # Gem identity information.
5
+ module Identity
6
+ def self.name
7
+ "better_heroku"
8
+ end
9
+
10
+ def self.label
11
+ "BetterHeroku"
12
+ end
13
+
14
+ def self.version
15
+ "0.0.1"
16
+ end
17
+
18
+ def self.version_label
19
+ "#{label} #{version}"
20
+ end
21
+ end
22
+ end
metadata ADDED
@@ -0,0 +1,177 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: better_heroku
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Paul Sadauskas
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-02-03 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '12.0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '12.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: gemsmith
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '8.2'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '8.2'
41
+ - !ruby/object:Gem::Dependency
42
+ name: pry
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '0.10'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '0.10'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry-byebug
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.4'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.4'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-state
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rspec
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '3.5'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '3.5'
97
+ - !ruby/object:Gem::Dependency
98
+ name: guard-rspec
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '4.7'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '4.7'
111
+ - !ruby/object:Gem::Dependency
112
+ name: reek
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '4.5'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '4.5'
125
+ - !ruby/object:Gem::Dependency
126
+ name: rubocop
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.46'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.46'
139
+ description:
140
+ email:
141
+ - psadauskas@gmail.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files:
145
+ - README.md
146
+ - LICENSE.md
147
+ files:
148
+ - LICENSE.md
149
+ - README.md
150
+ - lib/better_heroku.rb
151
+ - lib/better_heroku/client.rb
152
+ - lib/better_heroku/identity.rb
153
+ homepage: https://github.com/paul/better_heroku
154
+ licenses:
155
+ - MIT
156
+ metadata: {}
157
+ post_install_message:
158
+ rdoc_options: []
159
+ require_paths:
160
+ - lib
161
+ required_ruby_version: !ruby/object:Gem::Requirement
162
+ requirements:
163
+ - - ">="
164
+ - !ruby/object:Gem::Version
165
+ version: '0'
166
+ required_rubygems_version: !ruby/object:Gem::Requirement
167
+ requirements:
168
+ - - ">="
169
+ - !ruby/object:Gem::Version
170
+ version: '0'
171
+ requirements: []
172
+ rubyforge_project:
173
+ rubygems_version: 2.6.8
174
+ signing_key:
175
+ specification_version: 4
176
+ summary: ''
177
+ test_files: []