hipflag 1.0.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: b18769b4735bce8450b1d48e4815d7f5f7987f7492a32b40fd93953cd6b5860a
4
+ data.tar.gz: ecc90db5da2ed8d47ea65174668312a49befdeefd4fb033db07358250f0da8f1
5
+ SHA512:
6
+ metadata.gz: e5b902e6afbd6c385d157499b21d427243127c468ef44661943bfcce87ef63abe5bfda594fd907df4c986cd8018349489059c0f6a1e4cebe2e2f1849802c1677
7
+ data.tar.gz: caa46f5249e3aacf285d3c56929e517556dca4c22380f46948572608847a551556f3f39f1d8b015e60346714f67231b48ec7ce6a03dd321849801d1a3b278a0f
@@ -0,0 +1,11 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
9
+ .rspec_status
10
+ .byebug_history
11
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,5 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.6.3
5
+ before_install: gem install bundler -v 1.16.2
data/Gemfile ADDED
@@ -0,0 +1,13 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'byebug', '~> 11.0'
7
+ gem 'pry', '~> 0.12'
8
+ end
9
+
10
+ group :test do
11
+ gem 'rspec', '~> 3.8'
12
+ gem 'webmock', '~> 3.5.1'
13
+ end
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2019 Hipflag
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,168 @@
1
+ # hipflag
2
+
3
+ [![Build Status](https://travis-ci.org/hipflag/hipflag_ruby.svg?branch=master)](https://travis-ci.org/hipflag/hipflag_ruby)
4
+
5
+ <img src="https://static.hipflag.com/images/logo.png" width="272" alt="Hipflag logo">
6
+
7
+ This gem is a Ruby client for interacting with [Hipflag API](https://www.hipflag.com/docs).
8
+
9
+ [Hipflag](https://www.hipflag.com) is a tool that allows to control and roll out new product features with flags. It offers a simple UI to enable/disable feature flags. It also let users to enable flags for a given percentage of users
10
+
11
+ ## Installation
12
+
13
+ Add this line to your application's Gemfile:
14
+
15
+ ```ruby
16
+ gem 'hipflag'
17
+ ```
18
+
19
+ or install it yourself as:
20
+
21
+ $ gem install hipflag
22
+
23
+ ## Usage
24
+
25
+ ### Initializing a client
26
+
27
+ The client can be configured globally:
28
+
29
+ ```ruby
30
+ Hipflag.configure do |config|
31
+ config.public_key = '**************'
32
+ config.secret_key = '**************'
33
+ end
34
+
35
+ Hipflag::Client.new
36
+ ```
37
+
38
+ or by instance:
39
+
40
+ ```ruby
41
+ Hipflag::Client.new(public_key: '*******', secret_key: '*******')
42
+ ```
43
+
44
+ ### Client methods
45
+
46
+ Clients methods returns a `Hipflag::Response` object. This kind of objects contain methods to get the status of the request (ie: `#ok?`, `#created?`, ...) and a method called `#json` which returns a JSON representation of the response.
47
+
48
+ #### Flag
49
+ ##### #flag(flag_id)
50
+
51
+ It returns relevant information about a specific flag
52
+
53
+ ```ruby
54
+ client.flag('new-header').json
55
+ ```
56
+
57
+ Response
58
+ ```ruby
59
+ {
60
+ 'flag' => {
61
+ 'active' => true,
62
+ 'name' => 'new-header'
63
+ }
64
+ }
65
+ ```
66
+
67
+ It is possible to pass a `user_id` to check if the flag is enabled for that given user:
68
+
69
+ ```ruby
70
+ client.flag('new-header', user_id: 123).json
71
+ ```
72
+
73
+ If a flag is not found, the client raises a `Hipflag::Client:NotFound` exception. Example:
74
+
75
+ ```ruby
76
+ client.flag('unknown-flag')
77
+ ```
78
+
79
+ Exception raised:
80
+ ```
81
+ Hipflag::Client::NotFound: Resource not found
82
+ ```
83
+
84
+ ##### #update_flag(flag_id, params)
85
+
86
+ This method updates a specific flag
87
+
88
+ ```ruby
89
+ client.update_flag('new-header', rollout: 75).json
90
+ ```
91
+
92
+ Response
93
+ ```ruby
94
+ {
95
+ 'flag' => {
96
+ 'enabled' => true,
97
+ 'rollout' => 75,
98
+ 'name' => 'new-header'
99
+ }
100
+ }
101
+ ```
102
+
103
+ ```ruby
104
+ client.update_flag('new-header', enabled: false).json
105
+ ```
106
+
107
+ Response
108
+ ```ruby
109
+ {
110
+ 'flag' => {
111
+ 'enabled' => false,
112
+ 'rollout' => 75,
113
+ 'name' => 'new-header'
114
+ }
115
+ }
116
+ ```
117
+
118
+ If Hipflag cannot update a flag because a param is not valid, the client raises an exception including the error message. For example:
119
+
120
+ ```ruby
121
+ client.update_flag('new-header', rollout: 500).json
122
+ ```
123
+
124
+ Exception raised
125
+ ```
126
+ Hipflag::Client::UnprocessableEntity: {"message"=>{"rollout"=>["must be less than or equal to 100"]}}
127
+ ```
128
+
129
+ You can get the list of editable attributes in the [documentation](https://www.hipflag.com/docs).
130
+
131
+ ### Client errors
132
+
133
+ `Hipflag::Client` methods can raise several exceptions when performing requests:
134
+
135
+ * `Hipflag::Client::Unauthorized`: Request is not properly authenticated
136
+ * `Hipflag::Client::ServerError`: Hipflag API is not responding
137
+ * `Hipflag::Client::NotFound`: Resource is not found (`404`)
138
+ * `Hipflag::Client::UnprocessableEntity`: Request could not be processed
139
+
140
+ ### How to retrieve the authentication keys
141
+
142
+ You can get your personal `Public`and `Secret` keys at https://www.hipflag.com/users/me
143
+
144
+ ### How to using in Rails
145
+
146
+ The best way to use the client in a Rails application is adding a initializer: `config/initializers/hipflag.rb`:
147
+
148
+ ```ruby
149
+ Hipflag.configure do |config|
150
+ config.public_key = '**************'
151
+ config.secret_key = '**************'
152
+ end
153
+ ```
154
+
155
+ Then you can instantiate the client already containing the configuration:
156
+
157
+ ```ruby
158
+ Hipflag::Client.new
159
+ => #<Hipflag::Client:0x00007faa173be430 @public_key="**********", @secret_key="**********">
160
+ ```
161
+
162
+ ## Contributing
163
+
164
+ Bug reports and pull requests are welcome on GitHub at https://github.com/hipflag/hipflag_ruby. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [Contributor Covenant](http://contributor-covenant.org) code of conduct.
165
+
166
+ ## License
167
+
168
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT)
@@ -0,0 +1,6 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $stdout.sync = true
4
+
5
+ require 'bundler/setup'
6
+ require 'hipflag'
7
+ require 'pry'
8
+
9
+ ARGV.clear
10
+ Pry.start
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
@@ -0,0 +1,28 @@
1
+ lib = File.expand_path('../lib', __FILE__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require 'hipflag/version'
4
+
5
+ Gem::Specification.new do |spec|
6
+ spec.name = 'hipflag'
7
+ spec.version = Hipflag::VERSION
8
+ spec.authors = ['Hipflag']
9
+ spec.email = ['info@hipflag.com']
10
+
11
+ spec.summary = %q{Ruby client for interacting with Hipflag API}
12
+ spec.description = %q{This gem is a Ruby client for interacting with Hipflag API. Hipflag is a tool that allows to control and roll out new product features with flags}
13
+ spec.homepage = 'https://github.com/hipflag/hipflag_ruby'
14
+ spec.license = 'MIT'
15
+
16
+ spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do
17
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(spec)/}) }
18
+ end
19
+ spec.bindir = 'bin'
20
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
21
+ spec.require_paths = ['lib']
22
+
23
+ spec.add_dependency 'patron', '~> 0.13.1'
24
+ spec.add_dependency 'oj', '~> 3.7.12'
25
+ spec.add_dependency 'zeitwerk', '~> 2.1.6'
26
+ spec.add_development_dependency 'bundler', '~> 1.17'
27
+ spec.add_development_dependency 'rake', '~> 12.3'
28
+ end
@@ -0,0 +1,11 @@
1
+ require 'zeitwerk'
2
+ loader = Zeitwerk::Loader.for_gem
3
+ loader.enable_reloading
4
+ loader.setup
5
+ loader.reload
6
+
7
+ module Hipflag
8
+ class << self
9
+ include Hipflag::Configurable
10
+ end
11
+ end
@@ -0,0 +1,58 @@
1
+ require 'patron'
2
+
3
+ module Hipflag
4
+ class Client
5
+ include Client::Flag
6
+
7
+ NotFound = Class.new(RuntimeError)
8
+ ServerError = Class.new(RuntimeError)
9
+ Unauthorized = Class.new(RuntimeError)
10
+ UnprocessableEntity = Class.new(RuntimeError)
11
+
12
+ BASE_URL = 'https://api.hipflag.com/v1/'
13
+ TIMEOUT = 10
14
+
15
+ attr_reader(*Configurable::OPTIONS)
16
+
17
+ def initialize(options = {})
18
+ Configurable::OPTIONS.each do |key|
19
+ instance_variable_set(:"@#{key}", options[key] || Hipflag.send(key))
20
+ end
21
+
22
+ http_client.base_url = BASE_URL
23
+ end
24
+
25
+ private
26
+
27
+ def http_client
28
+ @http_client ||= Patron::Session.new do |config|
29
+ config.timeout = TIMEOUT
30
+ config.headers = {
31
+ 'Content-Type' => 'application/json',
32
+ 'X-Auth-Public' => @public_key,
33
+ 'X-Auth-Secret' => @secret_key
34
+ }
35
+ end
36
+ end
37
+
38
+ def perform_request(method, url, params = {})
39
+ handle_errors do
40
+ Response.new(http_client.request(method, url, {}, params))
41
+ end
42
+ end
43
+
44
+ def handle_errors
45
+ yield.tap do |response|
46
+ if response.unauthorized?
47
+ raise Unauthorized, 'Unauthorized'
48
+ elsif response.unprocessable?
49
+ raise UnprocessableEntity, response.json
50
+ elsif response.server_error?
51
+ raise ServerError, 'Server is not available'
52
+ elsif response.not_found?
53
+ raise NotFound, 'Resource not found'
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,21 @@
1
+ module Hipflag
2
+ class Client
3
+ module Flag
4
+ def flag(flag_id, user_id: nil)
5
+ perform_request(:get, "flags/#{flag_id}?#{flag_params(user_id)}")
6
+ end
7
+
8
+ def update_flag(flag_id, params)
9
+ perform_request(:put, "flags/#{flag_id}", data: { flag: params }.to_json)
10
+ end
11
+
12
+ private
13
+
14
+ def flag_params(user_id)
15
+ return if user_id.nil?
16
+
17
+ URI.encode_www_form(user_id: user_id)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,11 @@
1
+ module Hipflag
2
+ module Configurable
3
+ OPTIONS = %i[public_key secret_key].freeze
4
+
5
+ attr_accessor(*OPTIONS)
6
+
7
+ def configure
8
+ yield self
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ require 'delegate'
2
+ require 'oj'
3
+
4
+ module Hipflag
5
+ class Response < SimpleDelegator
6
+ alias_method :object, :__getobj__
7
+
8
+ def json
9
+ Oj.load(object.body)
10
+ end
11
+
12
+ def ok?
13
+ object.status == 200
14
+ end
15
+
16
+ def created?
17
+ object.status == 201
18
+ end
19
+
20
+ def no_content?
21
+ object.status == 204
22
+ end
23
+
24
+ def unauthorized?
25
+ object.status == 401
26
+ end
27
+
28
+ def not_found?
29
+ object.status == 404
30
+ end
31
+
32
+ def unprocessable?
33
+ object.status == 422
34
+ end
35
+
36
+ def server_error?
37
+ object.status >= 500
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,3 @@
1
+ module Hipflag
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,132 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hipflag
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Hipflag
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2019-05-08 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: patron
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 0.13.1
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 0.13.1
27
+ - !ruby/object:Gem::Dependency
28
+ name: oj
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: 3.7.12
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: 3.7.12
41
+ - !ruby/object:Gem::Dependency
42
+ name: zeitwerk
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: 2.1.6
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: 2.1.6
55
+ - !ruby/object:Gem::Dependency
56
+ name: bundler
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '1.17'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '1.17'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '12.3'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '12.3'
83
+ description: This gem is a Ruby client for interacting with Hipflag API. Hipflag is
84
+ a tool that allows to control and roll out new product features with flags
85
+ email:
86
+ - info@hipflag.com
87
+ executables:
88
+ - console
89
+ - setup
90
+ extensions: []
91
+ extra_rdoc_files: []
92
+ files:
93
+ - ".gitignore"
94
+ - ".rspec"
95
+ - ".travis.yml"
96
+ - Gemfile
97
+ - LICENSE.txt
98
+ - README.md
99
+ - Rakefile
100
+ - bin/console
101
+ - bin/setup
102
+ - hipflag.gemspec
103
+ - lib/hipflag.rb
104
+ - lib/hipflag/client.rb
105
+ - lib/hipflag/client/flag.rb
106
+ - lib/hipflag/configurable.rb
107
+ - lib/hipflag/response.rb
108
+ - lib/hipflag/version.rb
109
+ homepage: https://github.com/hipflag/hipflag_ruby
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubygems_version: 3.0.1
129
+ signing_key:
130
+ specification_version: 4
131
+ summary: Ruby client for interacting with Hipflag API
132
+ test_files: []