rox-rollout 5.1.2 → 6.0.1
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 +10 -0
- data/Jenkinsfile +212 -0
- data/README.md +1 -1
- data/cbci-templates/sdkci-e2e.yml +29 -0
- data/cbci-templates/sdkci-unit.yml +67 -0
- data/e2e-server/run_server.sh +3 -1
- data/examples/simple_example.rb +78 -0
- data/lib/rox/core/configuration/configuration_parser.rb +12 -3
- data/lib/rox/core/consts/environment.rb +14 -2
- data/lib/rox/core/core.rb +12 -8
- data/lib/rox/core/entities/flag.rb +4 -0
- data/lib/rox/core/entities/rox_double.rb +4 -0
- data/lib/rox/core/entities/rox_int.rb +4 -0
- data/lib/rox/core/entities/rox_string.rb +4 -0
- data/lib/rox/core/helpers/api_key.rb +28 -0
- data/lib/rox/core/network/state_sender.rb +47 -4
- data/lib/rox/core/properties/custom_property_type.rb +1 -0
- data/lib/rox/core/properties/property_factory.rb +13 -1
- data/lib/rox/core/roxx/parser.rb +9 -0
- data/lib/rox/server/rox_options.rb +39 -2
- data/lib/rox/server/rox_server.rb +20 -11
- data/lib/rox/version.rb +1 -1
- data/rox.gemspec +6 -6
- metadata +24 -21
- data/.github/workflows/e2e_tests.yaml +0 -52
- data/.github/workflows/unit_tests.yaml +0 -20
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 73d64c9e8123a69712c15cada3f6c9b2642c12953a8c25250eb9963d845dae41
|
|
4
|
+
data.tar.gz: 1e14bc76699a72e0f34dc3a5039025ab184049807b930a2c0fa407915c5380b1
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a615f9162c302b51d2359d0bc645fa1965a0d28c556678ee7e8a471cc7d1e5cbfef1ca73b06aaaaa91335665c30309286747c31e3930ad4d09fb4547936f1e53
|
|
7
|
+
data.tar.gz: c92c4de2381d270ab77dfc543efe00eaa0182d217a0e1e792a5934c58d8cf1c9f0e8d22138839dfd3d63c0ca434835cb8eabe28fdc76a3335bb4e7867da09a44
|
data/.gitignore
CHANGED
data/Jenkinsfile
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
pipeline {
|
|
2
|
+
agent any
|
|
3
|
+
|
|
4
|
+
libraries {
|
|
5
|
+
lib('fm-shared-library@main')
|
|
6
|
+
}//end libraries. Github Repo: https://github.com/rollout/fm-cbci-shared-library
|
|
7
|
+
|
|
8
|
+
options {
|
|
9
|
+
timeout(time: 45, unit: 'MINUTES')
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
stages {
|
|
13
|
+
stage('Checkout') {
|
|
14
|
+
steps {
|
|
15
|
+
checkout scm
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
stage("Run Unit tests"){
|
|
20
|
+
parallel {
|
|
21
|
+
stage("ruby-2.6") {
|
|
22
|
+
agent {
|
|
23
|
+
kubernetes {
|
|
24
|
+
inheritFrom 'ruby'
|
|
25
|
+
yamlFile './cbci-templates/sdkci-unit.yml'
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
steps {
|
|
30
|
+
container(name: "ruby-2-6", shell: "sh") {
|
|
31
|
+
withCredentials([
|
|
32
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_SSH_KEY', keyFileVariable: 'SDK_E2E_SSH_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
33
|
+
]) {
|
|
34
|
+
echo "Executing Run tests"
|
|
35
|
+
sh script: 'gem install bundler -v 2.4.22 && bundle install && bundle exec rake test',
|
|
36
|
+
label: "Running unit tests"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
stage("ruby-2.7") {
|
|
42
|
+
agent {
|
|
43
|
+
kubernetes {
|
|
44
|
+
inheritFrom 'ruby'
|
|
45
|
+
yamlFile './cbci-templates/sdkci-unit.yml'
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
steps {
|
|
50
|
+
container(name: "ruby-2-7", shell: "sh") {
|
|
51
|
+
withCredentials([
|
|
52
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_SSH_KEY', keyFileVariable: 'SDK_E2E_SSH_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
53
|
+
]) {
|
|
54
|
+
echo "Executing Run tests"
|
|
55
|
+
sh script: 'gem install bundler -v 2.4.22 && bundle install && bundle exec rake test',
|
|
56
|
+
label: "Running unit tests"
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
stage("ruby-3.0") {
|
|
62
|
+
agent {
|
|
63
|
+
kubernetes {
|
|
64
|
+
inheritFrom 'ruby'
|
|
65
|
+
yamlFile './cbci-templates/sdkci-unit.yml'
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
steps {
|
|
70
|
+
container(name: "ruby-3-0", shell: "sh") {
|
|
71
|
+
withCredentials([
|
|
72
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_SSH_KEY', keyFileVariable: 'SDK_E2E_SSH_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
73
|
+
]) {
|
|
74
|
+
echo "Executing Run tests"
|
|
75
|
+
sh script: 'gem install bundler -v 2.4.22 && bundle install && bundle exec rake test',
|
|
76
|
+
label: "Running unit tests"
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
stage("ruby-3.1") {
|
|
82
|
+
agent {
|
|
83
|
+
kubernetes {
|
|
84
|
+
inheritFrom 'ruby'
|
|
85
|
+
yamlFile './cbci-templates/sdkci-unit.yml'
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
steps {
|
|
90
|
+
container(name: "ruby-3-1", shell: "sh") {
|
|
91
|
+
withCredentials([
|
|
92
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_SSH_KEY', keyFileVariable: 'SDK_E2E_SSH_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
93
|
+
]) {
|
|
94
|
+
echo "Executing Run tests"
|
|
95
|
+
sh script: 'gem install bundler -v 2.4.22 && bundle install && bundle exec rake test',
|
|
96
|
+
label: "Running unit tests"
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
stage("ruby-3.2") {
|
|
102
|
+
agent {
|
|
103
|
+
kubernetes {
|
|
104
|
+
inheritFrom 'ruby'
|
|
105
|
+
yamlFile './cbci-templates/sdkci-unit.yml'
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
steps {
|
|
110
|
+
container(name: "ruby-3-2", shell: "sh") {
|
|
111
|
+
withCredentials([
|
|
112
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_SSH_KEY', keyFileVariable: 'SDK_E2E_SSH_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
113
|
+
]) {
|
|
114
|
+
echo "Executing Run tests"
|
|
115
|
+
sh script: 'gem install bundler -v 2.4.22 && bundle install && bundle exec rake test',
|
|
116
|
+
label: "Running unit tests"
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
stage("ruby-3.3") {
|
|
122
|
+
agent {
|
|
123
|
+
kubernetes {
|
|
124
|
+
inheritFrom 'ruby'
|
|
125
|
+
yamlFile './cbci-templates/sdkci-unit.yml'
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
steps {
|
|
130
|
+
container(name: "ruby-3-3", shell: "sh") {
|
|
131
|
+
withCredentials([
|
|
132
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_SSH_KEY', keyFileVariable: 'SDK_E2E_SSH_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
133
|
+
]) {
|
|
134
|
+
echo "Executing Run tests"
|
|
135
|
+
sh script: 'gem install bundler -v 2.4.22 && bundle install && bundle exec rake test',
|
|
136
|
+
label: "Running unit tests"
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
post{
|
|
143
|
+
success{
|
|
144
|
+
script {
|
|
145
|
+
echo 'Unit Tests OK; posting results'
|
|
146
|
+
currentBuild.result = 'SUCCESS'
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
failure{
|
|
150
|
+
echo 'Unit Tests Failed;'
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
stage("Run E2E tests"){
|
|
155
|
+
agent {
|
|
156
|
+
kubernetes {
|
|
157
|
+
inheritFrom 'default'
|
|
158
|
+
yamlFile './cbci-templates/sdkci-e2e.yml'
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
steps {
|
|
163
|
+
container("rox-proxy") {
|
|
164
|
+
waitForRoxProxy()
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
container(name: "server", shell: 'sh') {
|
|
168
|
+
withCredentials([
|
|
169
|
+
string(credentialsId: 'TEST_E2E_BEARER', variable: 'TEST_E2E_BEARER'),
|
|
170
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_SSH_KEY', keyFileVariable: 'SDK_E2E_SSH_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
171
|
+
sshUserPrivateKey(credentialsId: 'SDK_E2E_TESTS_DEPLOY_KEY', keyFileVariable: 'SDK_E2E_TESTS_DEPLOY_KEY', passphraseVariable: '', usernameVariable: 'cloudbees.eslint@cloudbees.com'),
|
|
172
|
+
]) {
|
|
173
|
+
script {
|
|
174
|
+
addGitHubFingerprint()
|
|
175
|
+
TESTENVPARAMS = "QA_E2E_BEARER=$TEST_E2E_BEARER API_HOST=https://api.test.rollout.io CD_API_ENDPOINT=https://api.test.rollout.io/device/get_configuration CD_S3_ENDPOINT=https://rox-conf.test.rollout.io/ SS_API_ENDPOINT=https://api.test.rollout.io/device/update_state_store/ SS_S3_ENDPOINT=https://rox-state.test.rollout.io/ CLIENT_DATA_CACHE_KEY=client_data ANALYTICS_ENDPOINT=https://analytic.test.rollout.io/ NOTIFICATIONS_ENDPOINT=https://push.test.rollout.io/sse"
|
|
176
|
+
ROOT_DIR = pwd()
|
|
177
|
+
|
|
178
|
+
withEnv(["GIT_SSH_COMMAND=ssh -i ${SDK_E2E_SSH_KEY}"]) {
|
|
179
|
+
echo "Executing E2E tests"
|
|
180
|
+
sh script: """
|
|
181
|
+
apt-get update && apt-get install -y curl gnupg
|
|
182
|
+
curl -sL https://deb.nodesource.com/setup_lts.x | bash -
|
|
183
|
+
apt-get install -y nodejs && npm install -g yarn
|
|
184
|
+
|
|
185
|
+
git clone git@github.com:rollout/sdk-end-2-end-tests.git
|
|
186
|
+
ln -s ${ROOT_DIR}/e2e-server/ ${ROOT_DIR}/sdk-end-2-end-tests/drivers/ruby
|
|
187
|
+
|
|
188
|
+
cd ${ROOT_DIR}/sdk-end-2-end-tests/drivers/nodejs && yarn install --frozen-lockfile
|
|
189
|
+
cd ${ROOT_DIR}/sdk-end-2-end-tests && yarn install --frozen-lockfile
|
|
190
|
+
|
|
191
|
+
${TESTENVPARAMS} SDK_LANG=ruby NODE_ENV=container yarn test:env
|
|
192
|
+
""", label: "Pull SDK end2 tests repository"
|
|
193
|
+
}// end withEnv
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
post{
|
|
199
|
+
success{
|
|
200
|
+
script {
|
|
201
|
+
echo 'E2E Tests OK; posting results'
|
|
202
|
+
currentBuild.result = 'SUCCESS'
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
failure{
|
|
206
|
+
echo 'E2E Tests Failed;'
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
data/README.md
CHANGED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
kind: Pod
|
|
3
|
+
metadata:
|
|
4
|
+
name: rox-ruby-sdk-e2e
|
|
5
|
+
spec:
|
|
6
|
+
serviceAccountName: ops-gcr-rw
|
|
7
|
+
containers:
|
|
8
|
+
- name: server
|
|
9
|
+
image: ruby:3.2
|
|
10
|
+
tty: true
|
|
11
|
+
resources:
|
|
12
|
+
requests:
|
|
13
|
+
memory: "1Gi"
|
|
14
|
+
cpu: "1000m"
|
|
15
|
+
limits:
|
|
16
|
+
memory: "2Gi"
|
|
17
|
+
cpu: "1000m"
|
|
18
|
+
- name: rox-proxy
|
|
19
|
+
image: rollout/simple-proxy
|
|
20
|
+
tty: true
|
|
21
|
+
ports:
|
|
22
|
+
- containerPort: 8080
|
|
23
|
+
resources:
|
|
24
|
+
requests:
|
|
25
|
+
memory: "1Gi"
|
|
26
|
+
cpu: "1000m"
|
|
27
|
+
limits:
|
|
28
|
+
memory: "1Gi"
|
|
29
|
+
cpu: "1000m"
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
apiVersion: v1
|
|
2
|
+
kind: Pod
|
|
3
|
+
metadata:
|
|
4
|
+
name: rox-ruby-sdk-unit
|
|
5
|
+
spec:
|
|
6
|
+
serviceAccountName: ops-gcr-rw
|
|
7
|
+
containers:
|
|
8
|
+
- name: ruby-2-6
|
|
9
|
+
image: ruby:2.6
|
|
10
|
+
tty: true
|
|
11
|
+
resources:
|
|
12
|
+
requests:
|
|
13
|
+
memory: "1Gi"
|
|
14
|
+
cpu: "1000m"
|
|
15
|
+
limits:
|
|
16
|
+
memory: "2Gi"
|
|
17
|
+
cpu: "1000m"
|
|
18
|
+
- name: ruby-2-7
|
|
19
|
+
image: ruby:2.7
|
|
20
|
+
tty: true
|
|
21
|
+
resources:
|
|
22
|
+
requests:
|
|
23
|
+
memory: "1Gi"
|
|
24
|
+
cpu: "1000m"
|
|
25
|
+
limits:
|
|
26
|
+
memory: "2Gi"
|
|
27
|
+
cpu: "1000m"
|
|
28
|
+
- name: ruby-3-0
|
|
29
|
+
image: ruby:3.0
|
|
30
|
+
tty: true
|
|
31
|
+
resources:
|
|
32
|
+
requests:
|
|
33
|
+
memory: "1Gi"
|
|
34
|
+
cpu: "1000m"
|
|
35
|
+
limits:
|
|
36
|
+
memory: "2Gi"
|
|
37
|
+
cpu: "1000m"
|
|
38
|
+
- name: ruby-3-1
|
|
39
|
+
image: ruby:3.1
|
|
40
|
+
tty: true
|
|
41
|
+
resources:
|
|
42
|
+
requests:
|
|
43
|
+
memory: "1Gi"
|
|
44
|
+
cpu: "1000m"
|
|
45
|
+
limits:
|
|
46
|
+
memory: "2Gi"
|
|
47
|
+
cpu: "1000m"
|
|
48
|
+
- name: ruby-3-2
|
|
49
|
+
image: ruby:3.2
|
|
50
|
+
tty: true
|
|
51
|
+
resources:
|
|
52
|
+
requests:
|
|
53
|
+
memory: "1Gi"
|
|
54
|
+
cpu: "1000m"
|
|
55
|
+
limits:
|
|
56
|
+
memory: "2Gi"
|
|
57
|
+
cpu: "1000m"
|
|
58
|
+
- name: ruby-3-3
|
|
59
|
+
image: ruby:3.3
|
|
60
|
+
tty: true
|
|
61
|
+
resources:
|
|
62
|
+
requests:
|
|
63
|
+
memory: "1Gi"
|
|
64
|
+
cpu: "1000m"
|
|
65
|
+
limits:
|
|
66
|
+
memory: "2Gi"
|
|
67
|
+
cpu: "1000m"
|
data/e2e-server/run_server.sh
CHANGED
|
@@ -8,9 +8,11 @@ gem install sinatra --conservative
|
|
|
8
8
|
gem install sinatra-contrib --conservative
|
|
9
9
|
gem install json --conservative
|
|
10
10
|
gem install em-eventsource --conservative
|
|
11
|
+
gem install rackup
|
|
12
|
+
gem install webrick
|
|
11
13
|
|
|
12
14
|
nohup ruby ./server.rb $1 1>"$DIR"/log_"$1".out 2>&1 &
|
|
13
15
|
while true ; do
|
|
14
16
|
curl -p http://127.0.0.1:$1/status-check && exit
|
|
15
17
|
sleep 1
|
|
16
|
-
done
|
|
18
|
+
done
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Simple example to test Rox SDK with Ruby 3.3
|
|
5
|
+
require 'bundler/setup'
|
|
6
|
+
require 'rox/server/rox_server'
|
|
7
|
+
require 'rox/server/flags/rox_flag'
|
|
8
|
+
require 'rox/server/flags/rox_string'
|
|
9
|
+
|
|
10
|
+
# Define a container class for flags
|
|
11
|
+
class FeatureFlags
|
|
12
|
+
attr_reader :enable_tutorial, :color_variant, :timeout_value
|
|
13
|
+
|
|
14
|
+
def initialize
|
|
15
|
+
@enable_tutorial = Rox::Server::RoxFlag.new(false)
|
|
16
|
+
@color_variant = Rox::Server::RoxString.new('blue', ['red', 'green', 'blue'])
|
|
17
|
+
@timeout_value = Rox::Server::RoxInt.new(30, [10, 30, 60])
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Initialize flags
|
|
22
|
+
flags = FeatureFlags.new
|
|
23
|
+
|
|
24
|
+
# Register flags
|
|
25
|
+
puts "Registering feature flags..."
|
|
26
|
+
Rox::Server::RoxServer.register(flags)
|
|
27
|
+
|
|
28
|
+
# Set custom properties
|
|
29
|
+
puts "Setting custom properties..."
|
|
30
|
+
Rox::Server::RoxServer.set_custom_string_property('tier', 'premium')
|
|
31
|
+
Rox::Server::RoxServer.set_custom_boolean_property('is_beta') { true }
|
|
32
|
+
|
|
33
|
+
# Setup SDK with test API key
|
|
34
|
+
puts "Setting up Rox SDK..."
|
|
35
|
+
puts "Ruby version: #{RUBY_VERSION}"
|
|
36
|
+
puts "Rox SDK version: #{Rox::VERSION}"
|
|
37
|
+
|
|
38
|
+
begin
|
|
39
|
+
# Use a test API key in valid format (24-char hex for MongoDB ObjectId)
|
|
40
|
+
# This will fail to connect but will test initialization
|
|
41
|
+
api_key = '507f1f77bcf86cd799439011'
|
|
42
|
+
|
|
43
|
+
options = Rox::Server::RoxOptions.new(
|
|
44
|
+
version: '1.0.0',
|
|
45
|
+
fetch_interval: 60
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
Rox::Server::RoxServer.setup(api_key, options)
|
|
49
|
+
|
|
50
|
+
# Give it a moment to initialize
|
|
51
|
+
sleep 2
|
|
52
|
+
|
|
53
|
+
# Test flag evaluation (will use defaults since we can't fetch)
|
|
54
|
+
puts "\nTesting flag evaluation:"
|
|
55
|
+
puts "enable_tutorial: #{flags.enable_tutorial.enabled?(nil)}"
|
|
56
|
+
puts "color_variant: #{flags.color_variant.value(nil)}"
|
|
57
|
+
puts "timeout_value: #{flags.timeout_value.value(nil)}"
|
|
58
|
+
|
|
59
|
+
# Test dynamic API
|
|
60
|
+
puts "\nTesting dynamic API:"
|
|
61
|
+
dynamic_api = Rox::Server::RoxServer.dynamic_api
|
|
62
|
+
puts "Dynamic flag (default false): #{dynamic_api.enabled?('dynamic.test', false, nil)}"
|
|
63
|
+
puts "Dynamic value (default 'test'): #{dynamic_api.value('dynamic.string', 'test', nil)}"
|
|
64
|
+
|
|
65
|
+
puts "\n✅ Ruby #{RUBY_VERSION} compatibility test PASSED!"
|
|
66
|
+
puts "SDK initialized and flags evaluated successfully."
|
|
67
|
+
|
|
68
|
+
rescue StandardError => e
|
|
69
|
+
puts "\n❌ Error: #{e.message}"
|
|
70
|
+
puts e.backtrace.first(5)
|
|
71
|
+
exit 1
|
|
72
|
+
ensure
|
|
73
|
+
# Shutdown SDK
|
|
74
|
+
puts "\nShutting down SDK..."
|
|
75
|
+
Rox::Server::RoxServer.shutdown
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
puts "\nSample app completed successfully!"
|
|
@@ -10,10 +10,11 @@ require 'rox/core/logging/logging'
|
|
|
10
10
|
module Rox
|
|
11
11
|
module Core
|
|
12
12
|
class ConfigurationParser
|
|
13
|
-
def initialize(signature_verifier, error_reporter, configuration_fetched_invoker)
|
|
13
|
+
def initialize(signature_verifier, error_reporter, configuration_fetched_invoker, rox_options = nil)
|
|
14
14
|
@signature_verifier = signature_verifier
|
|
15
15
|
@error_reporter = error_reporter
|
|
16
16
|
@configuration_fetched_invoker = configuration_fetched_invoker
|
|
17
|
+
@rox_options = rox_options
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def parse(fetch_result, sdk_settings)
|
|
@@ -31,8 +32,8 @@ module Rox
|
|
|
31
32
|
return nil
|
|
32
33
|
end
|
|
33
34
|
|
|
34
|
-
if fetch_result.source != ConfigurationSource::ROXY && !@signature_verifier.verify(json_obj['data'],
|
|
35
|
-
|
|
35
|
+
if signature_verification_enabled? && fetch_result.source != ConfigurationSource::ROXY && !@signature_verifier.verify(json_obj['data'],
|
|
36
|
+
json_obj['signature_v0'])
|
|
36
37
|
@configuration_fetched_invoker.invoke_error(FetcherError::SIGNATURE_VERIFICATION_ERROR)
|
|
37
38
|
@error_reporter.report('Failed to validate signature',
|
|
38
39
|
StandardError.new("Data : #{json_obj['data']} Signature : #{json_obj['signature_v0']}"))
|
|
@@ -81,6 +82,14 @@ module Rox
|
|
|
81
82
|
def parse_target_group(data)
|
|
82
83
|
TargetGroupModel.new(data['_id'], data['condition'])
|
|
83
84
|
end
|
|
85
|
+
|
|
86
|
+
private
|
|
87
|
+
|
|
88
|
+
def signature_verification_enabled?
|
|
89
|
+
return true if @rox_options.nil?
|
|
90
|
+
|
|
91
|
+
!@rox_options.disable_signature_verification
|
|
92
|
+
end
|
|
84
93
|
end
|
|
85
94
|
end
|
|
86
95
|
end
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'rox/server/self_managed_options'
|
|
2
|
+
|
|
1
3
|
module Rox
|
|
2
4
|
module Core
|
|
3
5
|
module Environment
|
|
@@ -50,6 +52,16 @@ module Rox
|
|
|
50
52
|
@notifications_path
|
|
51
53
|
end
|
|
52
54
|
|
|
55
|
+
def self.set_platform(rox_options)
|
|
56
|
+
@cdn_path = 'https://rox-conf.cloudbees.io'
|
|
57
|
+
@state_cdn_path = 'https://rox-state.cloudbees.io'
|
|
58
|
+
alternative_api_url = rox_options&.self_managed_options&.server_url || 'https://api.cloudbees.io'
|
|
59
|
+
@api_path = "#{alternative_api_url}/device/get_configuration"
|
|
60
|
+
@state_api_path = "#{alternative_api_url}/device/update_state_store"
|
|
61
|
+
@analytics_path = rox_options&.self_managed_options&.analytics_url || 'https://fm-analytics.cloudbees.io'
|
|
62
|
+
@notifications_path = 'https://sdk-notification-service.cloudbees.io/sse'
|
|
63
|
+
end
|
|
64
|
+
|
|
53
65
|
private
|
|
54
66
|
def self.setQA()
|
|
55
67
|
@cdn_path = 'https://qa-conf.rollout.io'
|
|
@@ -75,11 +87,11 @@ module Rox
|
|
|
75
87
|
alternative_api_url = rox_options&.self_managed_options&.server_url || 'https://x-api.rollout.io'
|
|
76
88
|
@api_path = "#{alternative_api_url}/device/get_configuration"
|
|
77
89
|
@state_api_path = "#{alternative_api_url}/device/update_state_store"
|
|
78
|
-
@analytics_path = rox_options&.self_managed_options&.analytics_url ||'https://analytic.rollout.io'
|
|
90
|
+
@analytics_path = rox_options&.self_managed_options&.analytics_url || 'https://analytic.rollout.io'
|
|
79
91
|
@notifications_path = 'https://push.rollout.io/sse'
|
|
80
92
|
end
|
|
81
93
|
end
|
|
82
94
|
end
|
|
83
95
|
end
|
|
84
96
|
|
|
85
|
-
Rox::Core::Environment.reset
|
|
97
|
+
Rox::Core::Environment.reset
|
data/lib/rox/core/core.rb
CHANGED
|
@@ -25,11 +25,14 @@ require 'rox/core/security/signature_verifier'
|
|
|
25
25
|
require 'rox/core/security/signature_verifier_mock'
|
|
26
26
|
require 'rox/core/utils/periodic_task'
|
|
27
27
|
require 'rox/core/client/dynamic_api'
|
|
28
|
+
require 'rox/core/helpers/api_key'
|
|
28
29
|
require 'rox/core/error_handling/userspace_unhandled_error_invoker'
|
|
29
30
|
|
|
30
31
|
module Rox
|
|
31
32
|
module Core
|
|
32
33
|
class Core
|
|
34
|
+
include Rox::Core::Helpers::ApiKey
|
|
35
|
+
|
|
33
36
|
def initialize
|
|
34
37
|
@flag_repository = FlagRepository.new
|
|
35
38
|
@custom_property_repository = CustomPropertyRepository.new
|
|
@@ -59,7 +62,7 @@ module Rox
|
|
|
59
62
|
def setup(sdk_settings, device_properties)
|
|
60
63
|
@sdk_settings = sdk_settings
|
|
61
64
|
@rox_options = device_properties.rox_options
|
|
62
|
-
|
|
65
|
+
reset_environment!(sdk_settings&.api_key, @rox_options)
|
|
63
66
|
|
|
64
67
|
experiments_extensions = ExperimentsExtensions.new(@parser, @target_group_repository, @flag_repository,
|
|
65
68
|
@experiment_repository)
|
|
@@ -156,7 +159,7 @@ module Rox
|
|
|
156
159
|
SignatureVerifier.new
|
|
157
160
|
end
|
|
158
161
|
configuration_parser = ConfigurationParser.new(signature_verifier, @error_reporter,
|
|
159
|
-
@configuration_fetched_invoker)
|
|
162
|
+
@configuration_fetched_invoker, @rox_options)
|
|
160
163
|
result = @configuration_fetcher.fetch
|
|
161
164
|
return if result.nil?
|
|
162
165
|
|
|
@@ -220,12 +223,13 @@ module Rox
|
|
|
220
223
|
@state_sender.dump_state
|
|
221
224
|
end
|
|
222
225
|
|
|
223
|
-
def
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
226
|
+
def reset_environment!(api_key, rox_options)
|
|
227
|
+
raise ArgumentError, 'Blank Feature Flag API key - must be specified' unless api_key
|
|
228
|
+
|
|
229
|
+
if is_cbp?(api_key)
|
|
230
|
+
Rox::Core::Environment.set_platform(rox_options)
|
|
231
|
+
else
|
|
232
|
+
Rox::Core::Environment.reset(rox_options)
|
|
229
233
|
end
|
|
230
234
|
end
|
|
231
235
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
|
|
2
|
+
module Rox
|
|
3
|
+
module Core
|
|
4
|
+
module Helpers
|
|
5
|
+
module ApiKey
|
|
6
|
+
MONGO_API_KEY_PATTERN = /^[a-f\d]{24}$/
|
|
7
|
+
UUID_API_KEY_PATTERN = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i
|
|
8
|
+
|
|
9
|
+
def is_cbp?(api_key)
|
|
10
|
+
validate_api_key(api_key) && UUID_API_KEY_PATTERN.match?(api_key)
|
|
11
|
+
rescue ArgumentError
|
|
12
|
+
false
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def validate_api_key(api_key)
|
|
16
|
+
if api_key&.strip&.empty?
|
|
17
|
+
raise ArgumentError, 'Blank Rollout api key - must be specified'
|
|
18
|
+
elsif !MONGO_API_KEY_PATTERN.match(api_key) && !UUID_API_KEY_PATTERN.match(api_key)
|
|
19
|
+
raise ArgumentError, 'Illegal Rollout api key'
|
|
20
|
+
else
|
|
21
|
+
true
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
end
|
|
28
|
+
end
|
|
@@ -8,10 +8,13 @@ require 'rox/core/network/request'
|
|
|
8
8
|
require 'rox/core/network/request_data'
|
|
9
9
|
require 'rox/core/network/response'
|
|
10
10
|
require 'rox/core/utils/debouncer'
|
|
11
|
+
require 'rox/core/helpers/api_key'
|
|
11
12
|
|
|
12
13
|
module Rox
|
|
13
14
|
module Core
|
|
14
15
|
class StateSender
|
|
16
|
+
include Rox::Core::Helpers::ApiKey
|
|
17
|
+
|
|
15
18
|
def initialize(sdk_settings, device_properties, flag_repository, custom_property_repository)
|
|
16
19
|
@sdk_settings = sdk_settings
|
|
17
20
|
@device_properties = device_properties
|
|
@@ -27,8 +30,8 @@ module Rox
|
|
|
27
30
|
|
|
28
31
|
def send
|
|
29
32
|
rollout_key = @device_properties.rollout_key
|
|
30
|
-
serialized_feature_flags =
|
|
31
|
-
serialized_custom_properties =
|
|
33
|
+
serialized_feature_flags = seralize_flag_repository
|
|
34
|
+
serialized_custom_properties = serialize_custom_properties_repository
|
|
32
35
|
|
|
33
36
|
state_payload = StateSender.state_payload(serialized_feature_flags, serialized_custom_properties,
|
|
34
37
|
@device_properties, @sdk_settings.dev_mode_secret)
|
|
@@ -39,7 +42,7 @@ module Rox
|
|
|
39
42
|
response = get_state_from_CDN(rollout_key, md5_signature)
|
|
40
43
|
if response.success?
|
|
41
44
|
Rox::Core::Logging.logger.debug('Successfully fetched state from CDN')
|
|
42
|
-
return
|
|
45
|
+
return response, nil
|
|
43
46
|
else
|
|
44
47
|
Rox::Core::Logging.logger.debug('Failed to fetch state from CDN. Sending state to API...')
|
|
45
48
|
end
|
|
@@ -52,6 +55,7 @@ module Rox
|
|
|
52
55
|
'Failed to send state to API.'
|
|
53
56
|
end
|
|
54
57
|
Rox::Core::Logging.logger.debug(message)
|
|
58
|
+
return response, state_payload
|
|
55
59
|
end
|
|
56
60
|
|
|
57
61
|
def dump_state
|
|
@@ -108,7 +112,7 @@ module Rox
|
|
|
108
112
|
def self.seralize_flag_repository_with_values(flag_repository)
|
|
109
113
|
flags = []
|
|
110
114
|
flag_repository.all_flags.sort_by(&:name).each do |f|
|
|
111
|
-
flags <<
|
|
115
|
+
flags << {
|
|
112
116
|
name: f.name,
|
|
113
117
|
enabled: f.enabled?,
|
|
114
118
|
defaultValue: f.default_value,
|
|
@@ -142,6 +146,45 @@ module Rox
|
|
|
142
146
|
end
|
|
143
147
|
properties
|
|
144
148
|
end
|
|
149
|
+
|
|
150
|
+
private
|
|
151
|
+
|
|
152
|
+
def cbp?
|
|
153
|
+
# Memoize assuming that @sdk_settings are not mutable during state sender lifetime
|
|
154
|
+
@cbp ||= is_cbp?(@sdk_settings&.api_key)
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def seralize_flag_repository
|
|
158
|
+
flags = []
|
|
159
|
+
@flag_repository.all_flags.sort_by(&:name).each do |f|
|
|
160
|
+
flag = {
|
|
161
|
+
name: f.name,
|
|
162
|
+
defaultValue: f.default_value,
|
|
163
|
+
options: f.options
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
flag[:externalType] = f.external_type if cbp?
|
|
167
|
+
|
|
168
|
+
flags << flag
|
|
169
|
+
end
|
|
170
|
+
flags
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def serialize_custom_properties_repository
|
|
174
|
+
properties = []
|
|
175
|
+
@custom_property_repository.all_custom_properties.sort_by(&:name).each do |p|
|
|
176
|
+
# Check not to send date custom properties to rollout
|
|
177
|
+
return if !is_cbp?(@sdk_settings&.api_key) && p.type.external_type == DateTime
|
|
178
|
+
|
|
179
|
+
properties << {
|
|
180
|
+
name: p.name,
|
|
181
|
+
type: p.type.type,
|
|
182
|
+
externalType: p.type.external_type
|
|
183
|
+
}
|
|
184
|
+
end
|
|
185
|
+
properties
|
|
186
|
+
end
|
|
187
|
+
|
|
145
188
|
end
|
|
146
189
|
end
|
|
147
190
|
end
|
|
@@ -113,6 +113,17 @@ module Rox
|
|
|
113
113
|
)
|
|
114
114
|
end
|
|
115
115
|
|
|
116
|
+
def internal_datetime
|
|
117
|
+
type = Rox::Core::CustomPropertyType::DATETIME
|
|
118
|
+
|
|
119
|
+
Rox::Core::DeviceProperty.new(
|
|
120
|
+
"now",
|
|
121
|
+
type
|
|
122
|
+
) do
|
|
123
|
+
Time.now
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
|
|
116
127
|
# rubocop:disable Metrics/MethodLength
|
|
117
128
|
def all_properties
|
|
118
129
|
[
|
|
@@ -124,7 +135,8 @@ module Rox
|
|
|
124
135
|
internal_app_key,
|
|
125
136
|
internal_distinct_id,
|
|
126
137
|
internal_lib_version,
|
|
127
|
-
internal_api_version
|
|
138
|
+
internal_api_version,
|
|
139
|
+
internal_datetime
|
|
128
140
|
]
|
|
129
141
|
end
|
|
130
142
|
end
|
data/lib/rox/core/roxx/parser.rb
CHANGED
|
@@ -169,6 +169,15 @@ module Rox
|
|
|
169
169
|
stack.push(TokenType::UNDEFINED)
|
|
170
170
|
end
|
|
171
171
|
end
|
|
172
|
+
|
|
173
|
+
add_operator('tsToNum') do |_parser, stack, _context|
|
|
174
|
+
datetime = stack.pop
|
|
175
|
+
if datetime.is_a?(DateTime)
|
|
176
|
+
stack.push(datetime.to_time.to_i)
|
|
177
|
+
else
|
|
178
|
+
stack.push(TokenType::UNDEFINED)
|
|
179
|
+
end
|
|
180
|
+
end
|
|
172
181
|
end
|
|
173
182
|
end
|
|
174
183
|
end
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
require 'rox/core/logging/logging'
|
|
2
2
|
require 'rox/server/logging/server_logger'
|
|
3
|
+
require 'rox/core/helpers/api_key'
|
|
3
4
|
|
|
4
5
|
module Rox
|
|
5
6
|
module Server
|
|
6
7
|
class RoxOptions
|
|
8
|
+
include Rox::Core::Helpers::ApiKey
|
|
9
|
+
|
|
7
10
|
attr_reader :dev_mode_key, :version, :fetch_interval,
|
|
8
11
|
:logger, :impression_handler,
|
|
9
12
|
:configuration_fetched_handler,
|
|
10
13
|
:roxy_url, :self_managed_options,
|
|
11
14
|
:network_configurations_options,
|
|
12
|
-
:dynamic_property_rule_handler
|
|
15
|
+
:dynamic_property_rule_handler,
|
|
16
|
+
:disable_signature_verification
|
|
13
17
|
|
|
14
18
|
def initialize(
|
|
15
19
|
dev_mode_key: nil,
|
|
@@ -21,7 +25,8 @@ module Rox
|
|
|
21
25
|
roxy_url: nil,
|
|
22
26
|
self_managed_options: nil,
|
|
23
27
|
network_configurations_options: nil,
|
|
24
|
-
dynamic_property_rule_handler: nil
|
|
28
|
+
dynamic_property_rule_handler: nil,
|
|
29
|
+
disable_signature_verification: nil
|
|
25
30
|
)
|
|
26
31
|
@dev_mode_key = dev_mode_key || 'stam'
|
|
27
32
|
@version = version || '0.0'
|
|
@@ -42,11 +47,43 @@ module Rox
|
|
|
42
47
|
@dynamic_property_rule_handler = dynamic_property_rule_handler || proc do |prop_name, context|
|
|
43
48
|
context ? context[prop_name] : nil
|
|
44
49
|
end
|
|
50
|
+
@disable_signature_verification = disable_signature_verification
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
def self_managed?
|
|
48
54
|
!@self_managed_options.nil?
|
|
49
55
|
end
|
|
56
|
+
|
|
57
|
+
def clone_with_options(options = {})
|
|
58
|
+
# Check if any keys that are not present as attributes were given as params
|
|
59
|
+
redundant_keys = options.keys - valid_attributes
|
|
60
|
+
|
|
61
|
+
# Filter options if there are such keys that are not present
|
|
62
|
+
if !redundant_keys.empty?
|
|
63
|
+
options = options.reduce({}) do |acc, (key, value)|
|
|
64
|
+
acc[key] = value unless redundant_keys.include?(key)
|
|
65
|
+
acc
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
valid_attributes.each do |va|
|
|
70
|
+
unless options.key?(va)
|
|
71
|
+
options[va] = self.instance_variable_get("@#{va}".to_sym)
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
self.class.new(**options)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
private
|
|
79
|
+
|
|
80
|
+
def valid_attributes
|
|
81
|
+
return @valid_attributes if @valid_attributes
|
|
82
|
+
|
|
83
|
+
cons = self.class.instance_method(:initialize)
|
|
84
|
+
key_parameters = cons.parameters.select { |type, name| type == :keyreq || type == :key }
|
|
85
|
+
@valid_attributes = key_parameters.map(&:last)
|
|
86
|
+
end
|
|
50
87
|
end
|
|
51
88
|
end
|
|
52
89
|
end
|
|
@@ -14,9 +14,20 @@ module Rox
|
|
|
14
14
|
|
|
15
15
|
class << self
|
|
16
16
|
def setup(api_key, rox_options = nil)
|
|
17
|
-
validate_api_key
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
# @core.setup calls validate_api_key internally anyway, but it will happen in another thread
|
|
18
|
+
# because of the report_on_exception code below (which might effect older [maybe not supported Ruby versions])
|
|
19
|
+
# decided to call it explicity here too (to keep the current behavor)
|
|
20
|
+
# anyway, this also short circuit the initialization (no need for the initialization and Thread.new)
|
|
21
|
+
# and only costs us calling the validation twice instead of once
|
|
22
|
+
@core.validate_api_key(api_key)
|
|
23
|
+
|
|
24
|
+
rox_options = if rox_options.nil?
|
|
25
|
+
Rox::Server::RoxOptions.new(disable_signature_verification: @core.is_cbp?(api_key))
|
|
26
|
+
else
|
|
27
|
+
rox_options = rox_options.clone_with_options({
|
|
28
|
+
disable_signature_verification: @core.is_cbp?(api_key) || rox_options.disable_signature_verification
|
|
29
|
+
})
|
|
30
|
+
end
|
|
20
31
|
sdk_settings = Rox::Server::SdkSettings.new(api_key, rox_options.dev_mode_key)
|
|
21
32
|
server_properties = Rox::Server::ServerProperties.new(sdk_settings, rox_options)
|
|
22
33
|
|
|
@@ -93,6 +104,12 @@ module Rox
|
|
|
93
104
|
&block))
|
|
94
105
|
end
|
|
95
106
|
|
|
107
|
+
def set_custom_datetime_property(name, value = nil, &block)
|
|
108
|
+
@core.add_custom_property(
|
|
109
|
+
Rox::Core::CustomProperty.new(name, Rox::Core::CustomPropertyType::DATETIME, value, &block)
|
|
110
|
+
)
|
|
111
|
+
end
|
|
112
|
+
|
|
96
113
|
def dynamic_api
|
|
97
114
|
@core.dynamic_api(Rox::Server::ServerEntitiesProvider.new)
|
|
98
115
|
end
|
|
@@ -100,14 +117,6 @@ module Rox
|
|
|
100
117
|
def dump_state
|
|
101
118
|
@core.dump_state
|
|
102
119
|
end
|
|
103
|
-
|
|
104
|
-
private
|
|
105
|
-
|
|
106
|
-
def validate_api_key(api_key)
|
|
107
|
-
raise ArgumentError, 'api_key is not valid' if (api_key =~ /^[a-f\d]{24}$/).nil?
|
|
108
|
-
|
|
109
|
-
true
|
|
110
|
-
end
|
|
111
120
|
end
|
|
112
121
|
end
|
|
113
122
|
end
|
data/lib/rox/version.rb
CHANGED
data/rox.gemspec
CHANGED
|
@@ -24,10 +24,10 @@ Gem::Specification.new do |spec|
|
|
|
24
24
|
|
|
25
25
|
spec.add_runtime_dependency 'em-eventsource', '~> 0.3.2'
|
|
26
26
|
|
|
27
|
-
spec.add_development_dependency 'bundler', '~> 2.4
|
|
28
|
-
spec.add_development_dependency 'minitest', '~> 5.
|
|
29
|
-
spec.add_development_dependency 'pry-byebug', '~> 3.
|
|
30
|
-
spec.add_development_dependency 'rake', '~>
|
|
31
|
-
spec.add_development_dependency 'rubocop', '~> 1.
|
|
32
|
-
spec.add_development_dependency 'webmock', '~> 3.
|
|
27
|
+
spec.add_development_dependency 'bundler', '~> 2.4'
|
|
28
|
+
spec.add_development_dependency 'minitest', '~> 5.20'
|
|
29
|
+
spec.add_development_dependency 'pry-byebug', '~> 3.9'
|
|
30
|
+
spec.add_development_dependency 'rake', '~> 13.0'
|
|
31
|
+
spec.add_development_dependency 'rubocop', '~> 1.50'
|
|
32
|
+
spec.add_development_dependency 'webmock', '~> 3.20'
|
|
33
33
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rox-rollout
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version:
|
|
4
|
+
version: 6.0.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- CloudBees
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-03-27 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: em-eventsource
|
|
@@ -30,85 +30,85 @@ dependencies:
|
|
|
30
30
|
requirements:
|
|
31
31
|
- - "~>"
|
|
32
32
|
- !ruby/object:Gem::Version
|
|
33
|
-
version: 2.4
|
|
33
|
+
version: '2.4'
|
|
34
34
|
type: :development
|
|
35
35
|
prerelease: false
|
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
|
37
37
|
requirements:
|
|
38
38
|
- - "~>"
|
|
39
39
|
- !ruby/object:Gem::Version
|
|
40
|
-
version: 2.4
|
|
40
|
+
version: '2.4'
|
|
41
41
|
- !ruby/object:Gem::Dependency
|
|
42
42
|
name: minitest
|
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
|
44
44
|
requirements:
|
|
45
45
|
- - "~>"
|
|
46
46
|
- !ruby/object:Gem::Version
|
|
47
|
-
version: '5.
|
|
47
|
+
version: '5.20'
|
|
48
48
|
type: :development
|
|
49
49
|
prerelease: false
|
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
|
51
51
|
requirements:
|
|
52
52
|
- - "~>"
|
|
53
53
|
- !ruby/object:Gem::Version
|
|
54
|
-
version: '5.
|
|
54
|
+
version: '5.20'
|
|
55
55
|
- !ruby/object:Gem::Dependency
|
|
56
56
|
name: pry-byebug
|
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
|
58
58
|
requirements:
|
|
59
59
|
- - "~>"
|
|
60
60
|
- !ruby/object:Gem::Version
|
|
61
|
-
version: 3.
|
|
61
|
+
version: '3.9'
|
|
62
62
|
type: :development
|
|
63
63
|
prerelease: false
|
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
|
65
65
|
requirements:
|
|
66
66
|
- - "~>"
|
|
67
67
|
- !ruby/object:Gem::Version
|
|
68
|
-
version: 3.
|
|
68
|
+
version: '3.9'
|
|
69
69
|
- !ruby/object:Gem::Dependency
|
|
70
70
|
name: rake
|
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
|
72
72
|
requirements:
|
|
73
73
|
- - "~>"
|
|
74
74
|
- !ruby/object:Gem::Version
|
|
75
|
-
version: '
|
|
75
|
+
version: '13.0'
|
|
76
76
|
type: :development
|
|
77
77
|
prerelease: false
|
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
|
79
79
|
requirements:
|
|
80
80
|
- - "~>"
|
|
81
81
|
- !ruby/object:Gem::Version
|
|
82
|
-
version: '
|
|
82
|
+
version: '13.0'
|
|
83
83
|
- !ruby/object:Gem::Dependency
|
|
84
84
|
name: rubocop
|
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
|
86
86
|
requirements:
|
|
87
87
|
- - "~>"
|
|
88
88
|
- !ruby/object:Gem::Version
|
|
89
|
-
version: '1.
|
|
89
|
+
version: '1.50'
|
|
90
90
|
type: :development
|
|
91
91
|
prerelease: false
|
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
|
93
93
|
requirements:
|
|
94
94
|
- - "~>"
|
|
95
95
|
- !ruby/object:Gem::Version
|
|
96
|
-
version: '1.
|
|
96
|
+
version: '1.50'
|
|
97
97
|
- !ruby/object:Gem::Dependency
|
|
98
98
|
name: webmock
|
|
99
99
|
requirement: !ruby/object:Gem::Requirement
|
|
100
100
|
requirements:
|
|
101
101
|
- - "~>"
|
|
102
102
|
- !ruby/object:Gem::Version
|
|
103
|
-
version: 3.
|
|
103
|
+
version: '3.20'
|
|
104
104
|
type: :development
|
|
105
105
|
prerelease: false
|
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
|
107
107
|
requirements:
|
|
108
108
|
- - "~>"
|
|
109
109
|
- !ruby/object:Gem::Version
|
|
110
|
-
version: 3.
|
|
111
|
-
description:
|
|
110
|
+
version: '3.20'
|
|
111
|
+
description:
|
|
112
112
|
email:
|
|
113
113
|
- support@rollout.io
|
|
114
114
|
executables: []
|
|
@@ -116,20 +116,22 @@ extensions: []
|
|
|
116
116
|
extra_rdoc_files: []
|
|
117
117
|
files:
|
|
118
118
|
- ".editorconfig"
|
|
119
|
-
- ".github/workflows/e2e_tests.yaml"
|
|
120
|
-
- ".github/workflows/unit_tests.yaml"
|
|
121
119
|
- ".gitignore"
|
|
122
120
|
- ".rubocop.yml"
|
|
123
121
|
- Gemfile
|
|
122
|
+
- Jenkinsfile
|
|
124
123
|
- LICENSE
|
|
125
124
|
- README.md
|
|
126
125
|
- Rakefile
|
|
127
126
|
- bin/console
|
|
128
127
|
- bin/setup
|
|
128
|
+
- cbci-templates/sdkci-e2e.yml
|
|
129
|
+
- cbci-templates/sdkci-unit.yml
|
|
129
130
|
- e2e-server/.gitignore
|
|
130
131
|
- e2e-server/run_server.sh
|
|
131
132
|
- e2e-server/server.rb
|
|
132
133
|
- example/local.rb
|
|
134
|
+
- examples/simple_example.rb
|
|
133
135
|
- lib/rox.rb
|
|
134
136
|
- lib/rox/core/analytics/backoff_policy.rb
|
|
135
137
|
- lib/rox/core/analytics/client.rb
|
|
@@ -168,6 +170,7 @@ files:
|
|
|
168
170
|
- lib/rox/core/error_handling/exception_trigger.rb
|
|
169
171
|
- lib/rox/core/error_handling/userspace_handler_exception.rb
|
|
170
172
|
- lib/rox/core/error_handling/userspace_unhandled_error_invoker.rb
|
|
173
|
+
- lib/rox/core/helpers/api_key.rb
|
|
171
174
|
- lib/rox/core/impression/impression_args.rb
|
|
172
175
|
- lib/rox/core/impression/impression_invoker.rb
|
|
173
176
|
- lib/rox/core/impression/models/experiment.rb
|
|
@@ -232,7 +235,7 @@ homepage: https://github.com/rollout/rox-ruby
|
|
|
232
235
|
licenses:
|
|
233
236
|
- Nonstandard
|
|
234
237
|
metadata: {}
|
|
235
|
-
post_install_message:
|
|
238
|
+
post_install_message:
|
|
236
239
|
rdoc_options: []
|
|
237
240
|
require_paths:
|
|
238
241
|
- lib
|
|
@@ -247,8 +250,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
247
250
|
- !ruby/object:Gem::Version
|
|
248
251
|
version: '0'
|
|
249
252
|
requirements: []
|
|
250
|
-
rubygems_version: 3.
|
|
251
|
-
signing_key:
|
|
253
|
+
rubygems_version: 3.5.9
|
|
254
|
+
signing_key:
|
|
252
255
|
specification_version: 4
|
|
253
256
|
summary: Feature Management ROX Ruby SDK
|
|
254
257
|
test_files: []
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
name: E2E tests
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches:
|
|
6
|
-
- master
|
|
7
|
-
pull_request:
|
|
8
|
-
branches:
|
|
9
|
-
- master
|
|
10
|
-
|
|
11
|
-
jobs:
|
|
12
|
-
build:
|
|
13
|
-
|
|
14
|
-
runs-on: macos-latest
|
|
15
|
-
|
|
16
|
-
steps:
|
|
17
|
-
- uses: actions/checkout@v3
|
|
18
|
-
with:
|
|
19
|
-
path: rox-ruby
|
|
20
|
-
- name: Checkout e2e tests
|
|
21
|
-
uses: actions/checkout@v3
|
|
22
|
-
with:
|
|
23
|
-
repository: rollout/sdk-end-2-end-tests
|
|
24
|
-
ref: master
|
|
25
|
-
token: ${{ secrets.E2E_PAT }}
|
|
26
|
-
path: sdk-end-2-end-tests
|
|
27
|
-
- name: link driver
|
|
28
|
-
working-directory: ./sdk-end-2-end-tests/drivers
|
|
29
|
-
run: ln -s $GITHUB_WORKSPACE/rox-ruby/e2e-server ruby
|
|
30
|
-
- name: build e2e node driver
|
|
31
|
-
working-directory: ./sdk-end-2-end-tests/drivers/nodejs
|
|
32
|
-
run: |
|
|
33
|
-
yarn install --frozen-lockfile
|
|
34
|
-
- name: build and run e2e
|
|
35
|
-
working-directory: ./sdk-end-2-end-tests
|
|
36
|
-
run: |
|
|
37
|
-
yarn install --frozen-lockfile
|
|
38
|
-
QA_E2E_BEARER=$QA_E2E_BEARER API_HOST=https://api.test.rollout.io CD_API_ENDPOINT=https://api.test.rollout.io/device/get_configuration CD_S3_ENDPOINT=https://rox-conf.test.rollout.io/ SS_API_ENDPOINT=https://api.test.rollout.io/device/update_state_store/ SS_S3_ENDPOINT=https://rox-state.test.rollout.io/ CLIENT_DATA_CACHE_KEY=client_data ANALYTICS_ENDPOINT=https://analytic.test.rollout.io/ NOTIFICATIONS_ENDPOINT=https://push.test.rollout.io/sse SDK_LANG=ruby NODE_ENV=container yarn test:env
|
|
39
|
-
env:
|
|
40
|
-
QA_E2E_BEARER: ${{ secrets.QA_E2E_BEARER }}
|
|
41
|
-
- name: Show e2e server driver logs
|
|
42
|
-
if: ${{ always() }}
|
|
43
|
-
run: cat ./sdk-end-2-end-tests/drivers/ruby/log_1234.out || echo "no log file"
|
|
44
|
-
- name: Show e2e server sync driver logs
|
|
45
|
-
if: ${{ always() }}
|
|
46
|
-
run: cat ./sdk-end-2-end-tests/drivers/nodejs/log_1233.out || echo "no log file"
|
|
47
|
-
- name: Show e2e server init ClientData driver logs
|
|
48
|
-
if: ${{ always() }}
|
|
49
|
-
run: cat ./sdk-end-2-end-tests/drivers/ruby/log_2234.out || echo "no log file"
|
|
50
|
-
- name: Show e2e server init ClientData sync driver logs
|
|
51
|
-
if: ${{ always() }}
|
|
52
|
-
run: cat ./sdk-end-2-end-tests/drivers/nodejs/log_2233.out || echo "no log file"
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
name: Unit Tests
|
|
2
|
-
|
|
3
|
-
on: [push]
|
|
4
|
-
|
|
5
|
-
jobs:
|
|
6
|
-
test:
|
|
7
|
-
strategy:
|
|
8
|
-
fail-fast: false
|
|
9
|
-
matrix:
|
|
10
|
-
os: [ubuntu-latest]
|
|
11
|
-
ruby: [2.6, 2.7, '3.0', 3.1, 3.2]
|
|
12
|
-
runs-on: ${{ matrix.os }}
|
|
13
|
-
steps:
|
|
14
|
-
- uses: actions/checkout@v3
|
|
15
|
-
- uses: ruby/setup-ruby@v1
|
|
16
|
-
with:
|
|
17
|
-
ruby-version: ${{ matrix.ruby }}
|
|
18
|
-
bundler: 2.4.6
|
|
19
|
-
bundler-cache: true # runs 'bundle install' and caches installed gems automatically
|
|
20
|
-
- run: bundle exec rake test
|