flipper-api 1.0.0.pre → 1.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/flipper/api/action.rb +7 -2
- data/lib/flipper/api/error_response.rb +1 -0
- data/lib/flipper/api/json_params.rb +2 -1
- data/lib/flipper/api/middleware.rb +1 -0
- data/lib/flipper/api/v1/actions/expression_gate.rb +43 -0
- data/lib/flipper/api/v1/decorators/gate.rb +4 -1
- data/lib/flipper/api.rb +1 -0
- data/lib/flipper/version.rb +1 -1
- data/spec/flipper/api/action_spec.rb +10 -0
- data/spec/flipper/api/v1/actions/expression_gate_spec.rb +157 -0
- data/spec/flipper/api/v1/actions/feature_spec.rb +20 -0
- data/spec/flipper/api/v1/actions/features_spec.rb +11 -0
- data/spec/flipper/api/v1/actions/import_spec.rb +5 -1
- data/spec/flipper/api_spec.rb +14 -0
- metadata +13 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b25c0b97a02c78eb7c67cf2f4a2471f0c1ca3d6ac07fb1199f4e9b00fce15f82
|
4
|
+
data.tar.gz: 2c00025cbdb9d13b9b38e99b8ddc79786bc2c6f540d100d7ab5c8b3bfdc68234
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a2a0ab2da9e51ce266b5b25e782163891b3b3be0428642391cb1b32d81b707097c9a869583c630d737633a004b4d23fdc9e5a616202d1507bb0c1c47f3f95917
|
7
|
+
data.tar.gz: 57f01b47c7e7ca94a70222a35062e6ff58b1e0ebcc1b03f344bb8092431140feb0b7a4e106626be516f5538894b74b852ed85407f0263160a0d9bbe59aa2cc4e
|
data/lib/flipper/api/action.rb
CHANGED
@@ -19,6 +19,7 @@ module Flipper
|
|
19
19
|
extend Forwardable
|
20
20
|
|
21
21
|
VALID_REQUEST_METHOD_NAMES = Set.new([
|
22
|
+
'head'.freeze,
|
22
23
|
'get'.freeze,
|
23
24
|
'post'.freeze,
|
24
25
|
'put'.freeze,
|
@@ -115,7 +116,7 @@ module Flipper
|
|
115
116
|
def json_response(object, status = 200)
|
116
117
|
header 'content-type', Api::CONTENT_TYPE
|
117
118
|
status(status)
|
118
|
-
body =
|
119
|
+
body = Typecast.to_json(object)
|
119
120
|
halt [@code, @headers, [body]]
|
120
121
|
end
|
121
122
|
|
@@ -147,8 +148,12 @@ module Flipper
|
|
147
148
|
private
|
148
149
|
|
149
150
|
# Private: Returns the request method converted to an action method.
|
151
|
+
# Converts head to get.
|
150
152
|
def request_method_name
|
151
|
-
@request_method_name ||=
|
153
|
+
@request_method_name ||= begin
|
154
|
+
name = @request.request_method.downcase
|
155
|
+
name == "head" ? "get" : name
|
156
|
+
end
|
152
157
|
end
|
153
158
|
|
154
159
|
# Private: split request path by "/"
|
@@ -28,6 +28,7 @@ module Flipper
|
|
28
28
|
flipper_id_invalid: Error.new(4, 'Required parameter flipper_id is missing.', 422),
|
29
29
|
name_invalid: Error.new(5, 'Required parameter name is missing.', 422),
|
30
30
|
import_invalid: Error.new(6, 'Import invalid.', 422),
|
31
|
+
expression_invalid: Error.new(7, 'The provided expression was not valid.', 422),
|
31
32
|
}.freeze
|
32
33
|
end
|
33
34
|
end
|
@@ -34,7 +34,8 @@ module Flipper
|
|
34
34
|
# This method accomplishes similar functionality
|
35
35
|
def update_params(env, data)
|
36
36
|
return if data.empty?
|
37
|
-
parsed_request_body =
|
37
|
+
parsed_request_body = Typecast.from_json(data)
|
38
|
+
env["parsed_request_body".freeze] = parsed_request_body
|
38
39
|
parsed_query_string = parse_query(env[QUERY_STRING])
|
39
40
|
parsed_query_string.merge!(parsed_request_body)
|
40
41
|
parameters = build_query(parsed_query_string)
|
@@ -14,6 +14,7 @@ module Flipper
|
|
14
14
|
@env_key = options.fetch(:env_key, 'flipper')
|
15
15
|
|
16
16
|
@action_collection = ActionCollection.new
|
17
|
+
@action_collection.add Api::V1::Actions::ExpressionGate
|
17
18
|
@action_collection.add Api::V1::Actions::PercentageOfTimeGate
|
18
19
|
@action_collection.add Api::V1::Actions::PercentageOfActorsGate
|
19
20
|
@action_collection.add Api::V1::Actions::ActorsGate
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'flipper/api/action'
|
2
|
+
require 'flipper/api/v1/decorators/feature'
|
3
|
+
|
4
|
+
module Flipper
|
5
|
+
module Api
|
6
|
+
module V1
|
7
|
+
module Actions
|
8
|
+
class ExpressionGate < Api::Action
|
9
|
+
include FeatureNameFromRoute
|
10
|
+
|
11
|
+
route %r{\A/features/(?<feature_name>.*)/expression/?\Z}
|
12
|
+
|
13
|
+
def post
|
14
|
+
feature = flipper[feature_name]
|
15
|
+
|
16
|
+
begin
|
17
|
+
expression = Flipper::Expression.build(expression_hash)
|
18
|
+
feature.enable_expression expression
|
19
|
+
decorated_feature = Decorators::Feature.new(feature)
|
20
|
+
json_response(decorated_feature.as_json, 200)
|
21
|
+
rescue NameError, ArgumentError => exception
|
22
|
+
json_error_response(:expression_invalid)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete
|
27
|
+
feature = flipper[feature_name]
|
28
|
+
feature.disable_expression
|
29
|
+
|
30
|
+
decorated_feature = Decorators::Feature.new(feature)
|
31
|
+
json_response(decorated_feature.as_json, 200)
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def expression_hash
|
37
|
+
@expression_hash ||= request.env["parsed_request_body".freeze] || {}.freeze
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -25,9 +25,12 @@ module Flipper
|
|
25
25
|
|
26
26
|
private
|
27
27
|
|
28
|
+
# Set of types that should be represented as Array in JSON.
|
29
|
+
JSON_ARRAY_TYPES = Set[:set].freeze
|
30
|
+
|
28
31
|
# json doesn't like sets
|
29
32
|
def value_as_json
|
30
|
-
data_type
|
33
|
+
JSON_ARRAY_TYPES.include?(data_type) ? value.to_a : value
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
data/lib/flipper/api.rb
CHANGED
@@ -12,6 +12,7 @@ module Flipper
|
|
12
12
|
app = ->(_) { [404, { 'content-type'.freeze => CONTENT_TYPE }, ['{}'.freeze]] }
|
13
13
|
builder = Rack::Builder.new
|
14
14
|
yield builder if block_given?
|
15
|
+
builder.use Rack::Head
|
15
16
|
builder.use Flipper::Api::JsonParams
|
16
17
|
builder.use Flipper::Middleware::SetupEnv, flipper, env_key: env_key
|
17
18
|
builder.use Flipper::Api::Middleware, env_key: env_key
|
data/lib/flipper/version.rb
CHANGED
@@ -9,6 +9,10 @@ RSpec.describe Flipper::Api::Action do
|
|
9
9
|
[200, {}, 'get']
|
10
10
|
end
|
11
11
|
|
12
|
+
def head
|
13
|
+
[200, {}, 'head']
|
14
|
+
end
|
15
|
+
|
12
16
|
def post
|
13
17
|
[200, {}, 'post']
|
14
18
|
end
|
@@ -38,6 +42,12 @@ RSpec.describe Flipper::Api::Action do
|
|
38
42
|
expect(action.run).to eq([200, {}, 'get'])
|
39
43
|
end
|
40
44
|
|
45
|
+
it 'will run head' do
|
46
|
+
fake_request = Struct.new(:request_method, :env, :session).new('HEAD', {}, {})
|
47
|
+
action = action_subclass.new(flipper, fake_request)
|
48
|
+
expect(action.run).to eq([200, {}, 'get'])
|
49
|
+
end
|
50
|
+
|
41
51
|
it 'will run post' do
|
42
52
|
fake_request = Struct.new(:request_method, :env, :session).new('POST', {}, {})
|
43
53
|
action = action_subclass.new(flipper, fake_request)
|
@@ -0,0 +1,157 @@
|
|
1
|
+
RSpec.describe Flipper::Api::V1::Actions::ExpressionGate do
|
2
|
+
let(:app) { build_api(flipper) }
|
3
|
+
let(:actor) {
|
4
|
+
Flipper::Actor.new('1', {
|
5
|
+
"plan" => "basic",
|
6
|
+
"age" => 21,
|
7
|
+
})
|
8
|
+
}
|
9
|
+
let(:expression) { Flipper.property(:plan).eq("basic") }
|
10
|
+
|
11
|
+
describe 'enable' do
|
12
|
+
before do
|
13
|
+
flipper[:my_feature].disable_expression
|
14
|
+
post '/features/my_feature/expression', JSON.dump(expression.value),
|
15
|
+
"CONTENT_TYPE" => "application/json"
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'enables feature for expression' do
|
19
|
+
expect(last_response.status).to eq(200)
|
20
|
+
expect(flipper[:my_feature].enabled?(actor)).to be_truthy
|
21
|
+
expect(flipper[:my_feature].enabled_gate_names).to eq([:expression])
|
22
|
+
end
|
23
|
+
|
24
|
+
it 'returns decorated feature with expression enabled' do
|
25
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'expression' }
|
26
|
+
expect(gate['value']).to eq(expression.value)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'disable' do
|
31
|
+
before do
|
32
|
+
flipper[:my_feature].enable_expression(expression)
|
33
|
+
delete '/features/my_feature/expression', JSON.dump({}),
|
34
|
+
"CONTENT_TYPE" => "application/json"
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'disables expression for feature' do
|
38
|
+
expect(last_response.status).to eq(200)
|
39
|
+
expect(flipper[:my_feature].enabled?(actor)).to be_falsy
|
40
|
+
expect(flipper[:my_feature].enabled_gate_names).to be_empty
|
41
|
+
end
|
42
|
+
|
43
|
+
it 'returns decorated feature with expression gate disabled' do
|
44
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'expression' }
|
45
|
+
expect(gate['value']).to be(nil)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe 'enable feature with slash in name' do
|
50
|
+
before do
|
51
|
+
flipper["my/feature"].disable_expression
|
52
|
+
post '/features/my/feature/expression', JSON.dump(expression.value),
|
53
|
+
"CONTENT_TYPE" => "application/json"
|
54
|
+
end
|
55
|
+
|
56
|
+
it 'enables feature for expression' do
|
57
|
+
expect(last_response.status).to eq(200)
|
58
|
+
expect(flipper["my/feature"].enabled?(actor)).to be_truthy
|
59
|
+
expect(flipper["my/feature"].enabled_gate_names).to eq([:expression])
|
60
|
+
end
|
61
|
+
|
62
|
+
it 'returns decorated feature with expression enabled' do
|
63
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'expression' }
|
64
|
+
expect(gate['value']).to eq(expression.value)
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe 'enable feature with space in name' do
|
69
|
+
before do
|
70
|
+
flipper["sp ace"].disable_expression
|
71
|
+
post '/features/sp%20ace/expression', JSON.dump(expression.value),
|
72
|
+
"CONTENT_TYPE" => "application/json"
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'enables feature for expression' do
|
76
|
+
expect(last_response.status).to eq(200)
|
77
|
+
expect(flipper["sp ace"].enabled?(actor)).to be_truthy
|
78
|
+
expect(flipper["sp ace"].enabled_gate_names).to eq([:expression])
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'returns decorated feature with expression enabled' do
|
82
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'expression' }
|
83
|
+
expect(gate['value']).to eq(expression.value)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
describe 'enable with no data' do
|
88
|
+
before do
|
89
|
+
post '/features/my_feature/expression', "CONTENT_TYPE" => "application/json"
|
90
|
+
end
|
91
|
+
|
92
|
+
it 'returns correct error response' do
|
93
|
+
expect(last_response.status).to eq(422)
|
94
|
+
expect(json_response).to eq(api_expression_invalid_response)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
describe 'enable with empty object' do
|
99
|
+
before do
|
100
|
+
data = {}
|
101
|
+
post '/features/my_feature/expression', JSON.dump(data),
|
102
|
+
"CONTENT_TYPE" => "application/json"
|
103
|
+
end
|
104
|
+
|
105
|
+
it 'returns correct error response' do
|
106
|
+
expect(last_response.status).to eq(422)
|
107
|
+
expect(json_response).to eq(api_expression_invalid_response)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
describe 'enable with invalid data' do
|
112
|
+
before do
|
113
|
+
data = {"blah" => "blah"}
|
114
|
+
post '/features/my_feature/expression', JSON.dump(data),
|
115
|
+
"CONTENT_TYPE" => "application/json"
|
116
|
+
end
|
117
|
+
|
118
|
+
it 'returns correct error response' do
|
119
|
+
expect(last_response.status).to eq(422)
|
120
|
+
expect(json_response).to eq(api_expression_invalid_response)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
|
124
|
+
describe 'enable missing feature' do
|
125
|
+
before do
|
126
|
+
post '/features/my_feature/expression', JSON.dump(expression.value), "CONTENT_TYPE" => "application/json"
|
127
|
+
end
|
128
|
+
|
129
|
+
it 'enables expression for feature' do
|
130
|
+
expect(last_response.status).to eq(200)
|
131
|
+
expect(flipper[:my_feature].enabled?(actor)).to be_truthy
|
132
|
+
expect(flipper[:my_feature].enabled_gate_names).to eq([:expression])
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'returns decorated feature with expression enabled' do
|
136
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'expression' }
|
137
|
+
expect(gate['value']).to eq(expression.value)
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
describe 'disable missing feature' do
|
142
|
+
before do
|
143
|
+
delete '/features/my_feature/expression', "CONTENT_TYPE" => "application/json"
|
144
|
+
end
|
145
|
+
|
146
|
+
it 'disables expression for feature' do
|
147
|
+
expect(last_response.status).to eq(200)
|
148
|
+
expect(flipper[:my_feature].enabled?(actor)).to be_falsy
|
149
|
+
expect(flipper[:my_feature].enabled_gate_names).to be_empty
|
150
|
+
end
|
151
|
+
|
152
|
+
it 'returns decorated feature with expression gate disabled' do
|
153
|
+
gate = json_response['gates'].find { |gate| gate['key'] == 'expression' }
|
154
|
+
expect(gate['value']).to be(nil)
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -20,6 +20,11 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
20
20
|
'name' => 'boolean',
|
21
21
|
'value' => 'true',
|
22
22
|
},
|
23
|
+
{
|
24
|
+
'key' => 'expression',
|
25
|
+
'name' => 'expression',
|
26
|
+
'value' => nil,
|
27
|
+
},
|
23
28
|
{
|
24
29
|
'key' => 'actors',
|
25
30
|
'name' => 'actor',
|
@@ -64,6 +69,11 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
64
69
|
'name' => 'boolean',
|
65
70
|
'value' => nil,
|
66
71
|
},
|
72
|
+
{
|
73
|
+
'key' => 'expression',
|
74
|
+
'name' => 'expression',
|
75
|
+
'value' => nil,
|
76
|
+
},
|
67
77
|
{
|
68
78
|
'key' => 'actors',
|
69
79
|
'name' => 'actor',
|
@@ -124,6 +134,11 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
124
134
|
'name' => 'boolean',
|
125
135
|
'value' => 'true',
|
126
136
|
},
|
137
|
+
{
|
138
|
+
'key' => 'expression',
|
139
|
+
'name' => 'expression',
|
140
|
+
'value' => nil,
|
141
|
+
},
|
127
142
|
{
|
128
143
|
'key' => 'actors',
|
129
144
|
'name' => 'actor',
|
@@ -168,6 +183,11 @@ RSpec.describe Flipper::Api::V1::Actions::Feature do
|
|
168
183
|
'name' => 'boolean',
|
169
184
|
'value' => 'true',
|
170
185
|
},
|
186
|
+
{
|
187
|
+
'key' => 'expression',
|
188
|
+
'name' => 'expression',
|
189
|
+
'value' => nil,
|
190
|
+
},
|
171
191
|
{
|
172
192
|
'key' => 'actors',
|
173
193
|
'name' => 'actor',
|
@@ -24,6 +24,11 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
24
24
|
'name' => 'boolean',
|
25
25
|
'value' => 'true',
|
26
26
|
},
|
27
|
+
{
|
28
|
+
'key' => 'expression',
|
29
|
+
'name' => 'expression',
|
30
|
+
'value' => nil,
|
31
|
+
},
|
27
32
|
{
|
28
33
|
'key' => 'actors',
|
29
34
|
'name' => 'actor',
|
@@ -60,6 +65,7 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
60
65
|
'state' => 'on',
|
61
66
|
'gates' => [
|
62
67
|
{ 'key' => 'boolean', 'value' => 'true'},
|
68
|
+
{"key" => "expression", "value" => nil},
|
63
69
|
{ 'key' => 'actors', 'value' => ['10']},
|
64
70
|
{'key' => 'percentage_of_actors', 'value' => nil},
|
65
71
|
{ 'key' => 'percentage_of_time', 'value' => nil},
|
@@ -140,6 +146,11 @@ RSpec.describe Flipper::Api::V1::Actions::Features do
|
|
140
146
|
'name' => 'boolean',
|
141
147
|
'value' => nil,
|
142
148
|
},
|
149
|
+
{
|
150
|
+
'key' => 'expression',
|
151
|
+
'name' => 'expression',
|
152
|
+
'value' => nil,
|
153
|
+
},
|
143
154
|
{
|
144
155
|
'key' => 'actors',
|
145
156
|
'name' => 'actor',
|
@@ -2,6 +2,8 @@ RSpec.describe Flipper::Api::V1::Actions::Import do
|
|
2
2
|
let(:app) { build_api(flipper) }
|
3
3
|
|
4
4
|
describe 'post' do
|
5
|
+
let(:expression) { Flipper.property(:plan).eq("basic") }
|
6
|
+
|
5
7
|
context 'succesful request' do
|
6
8
|
before do
|
7
9
|
flipper.enable(:search)
|
@@ -10,6 +12,7 @@ RSpec.describe Flipper::Api::V1::Actions::Import do
|
|
10
12
|
source_flipper = build_flipper
|
11
13
|
source_flipper.disable(:search)
|
12
14
|
source_flipper.enable_actor(:google_analytics, Flipper::Actor.new("User;1"))
|
15
|
+
source_flipper.enable(:analytics, expression)
|
13
16
|
|
14
17
|
export = source_flipper.export
|
15
18
|
|
@@ -23,7 +26,8 @@ RSpec.describe Flipper::Api::V1::Actions::Import do
|
|
23
26
|
it 'imports features' do
|
24
27
|
expect(flipper[:search].boolean_value).to be(false)
|
25
28
|
expect(flipper[:google_analytics].actors_value).to eq(Set["User;1"])
|
26
|
-
expect(flipper.
|
29
|
+
expect(flipper[:analytics].expression_value).to eq(expression.value)
|
30
|
+
expect(flipper.features.map(&:key)).to eq(["search", "google_analytics", "analytics"])
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
data/spec/flipper/api_spec.rb
CHANGED
@@ -14,6 +14,20 @@ RSpec.describe Flipper::Api do
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
+
describe "Head requests" do
|
18
|
+
let(:app) { build_api(flipper) }
|
19
|
+
|
20
|
+
it "are allowed but perform get and return no body" do
|
21
|
+
flipper.enable :a
|
22
|
+
flipper.disable :b
|
23
|
+
|
24
|
+
head '/features'
|
25
|
+
|
26
|
+
expect(last_response.status).to be(200)
|
27
|
+
expect(last_response.body).to be_empty
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
17
31
|
describe 'Initializing middleware lazily with a block' do
|
18
32
|
let(:app) { build_api(-> { flipper }) }
|
19
33
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: flipper-api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- John Nunemaker
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2023-08
|
11
|
+
date: 2023-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rack
|
@@ -36,14 +36,14 @@ dependencies:
|
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: 1.
|
39
|
+
version: 1.1.0
|
40
40
|
type: :runtime
|
41
41
|
prerelease: false
|
42
42
|
version_requirements: !ruby/object:Gem::Requirement
|
43
43
|
requirements:
|
44
44
|
- - "~>"
|
45
45
|
- !ruby/object:Gem::Version
|
46
|
-
version: 1.
|
46
|
+
version: 1.1.0
|
47
47
|
description:
|
48
48
|
email: support@flippercloud.io
|
49
49
|
executables: []
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- lib/flipper/api/v1/actions/actors_gate.rb
|
64
64
|
- lib/flipper/api/v1/actions/boolean_gate.rb
|
65
65
|
- lib/flipper/api/v1/actions/clear_feature.rb
|
66
|
+
- lib/flipper/api/v1/actions/expression_gate.rb
|
66
67
|
- lib/flipper/api/v1/actions/feature.rb
|
67
68
|
- lib/flipper/api/v1/actions/features.rb
|
68
69
|
- lib/flipper/api/v1/actions/groups_gate.rb
|
@@ -79,6 +80,7 @@ files:
|
|
79
80
|
- spec/flipper/api/v1/actions/actors_spec.rb
|
80
81
|
- spec/flipper/api/v1/actions/boolean_gate_spec.rb
|
81
82
|
- spec/flipper/api/v1/actions/clear_feature_spec.rb
|
83
|
+
- spec/flipper/api/v1/actions/expression_gate_spec.rb
|
82
84
|
- spec/flipper/api/v1/actions/feature_spec.rb
|
83
85
|
- spec/flipper/api/v1/actions/features_spec.rb
|
84
86
|
- spec/flipper/api/v1/actions/groups_gate_spec.rb
|
@@ -93,9 +95,9 @@ licenses:
|
|
93
95
|
metadata:
|
94
96
|
documentation_uri: https://www.flippercloud.io/docs
|
95
97
|
homepage_uri: https://www.flippercloud.io
|
96
|
-
source_code_uri: https://github.com/
|
97
|
-
bug_tracker_uri: https://github.com/
|
98
|
-
changelog_uri: https://github.com/
|
98
|
+
source_code_uri: https://github.com/flippercloud/flipper
|
99
|
+
bug_tracker_uri: https://github.com/flippercloud/flipper/issues
|
100
|
+
changelog_uri: https://github.com/flippercloud/flipper/blob/main/Changelog.md
|
99
101
|
post_install_message:
|
100
102
|
rdoc_options: []
|
101
103
|
require_paths:
|
@@ -107,11 +109,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
107
109
|
version: '0'
|
108
110
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
111
|
requirements:
|
110
|
-
- - "
|
112
|
+
- - ">="
|
111
113
|
- !ruby/object:Gem::Version
|
112
|
-
version:
|
114
|
+
version: '0'
|
113
115
|
requirements: []
|
114
|
-
rubygems_version: 3.
|
116
|
+
rubygems_version: 3.4.10
|
115
117
|
signing_key:
|
116
118
|
specification_version: 4
|
117
119
|
summary: API for the Flipper gem
|
@@ -122,6 +124,7 @@ test_files:
|
|
122
124
|
- spec/flipper/api/v1/actions/actors_spec.rb
|
123
125
|
- spec/flipper/api/v1/actions/boolean_gate_spec.rb
|
124
126
|
- spec/flipper/api/v1/actions/clear_feature_spec.rb
|
127
|
+
- spec/flipper/api/v1/actions/expression_gate_spec.rb
|
125
128
|
- spec/flipper/api/v1/actions/feature_spec.rb
|
126
129
|
- spec/flipper/api/v1/actions/features_spec.rb
|
127
130
|
- spec/flipper/api/v1/actions/groups_gate_spec.rb
|