pubnub 5.1.2 → 5.2.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pubnub might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/.github/workflows/release.yml +5 -0
- data/.github/workflows/run-tests.yml +84 -0
- data/.github/workflows/run-validations.yml +22 -0
- data/.pubnub.yml +11 -4
- data/.tool-versions +1 -1
- data/CHANGELOG.md +9 -0
- data/Gemfile.lock +1 -1
- data/VERSION +1 -1
- data/lib/pubnub/client/events.rb +1 -0
- data/lib/pubnub/client.rb +3 -0
- data/lib/pubnub/constants.rb +5 -1
- data/lib/pubnub/event.rb +37 -13
- data/lib/pubnub/events/add_message_action.rb +86 -0
- data/lib/pubnub/events/get_message_actions.rb +78 -0
- data/lib/pubnub/events/remove_message_actions.rb +68 -0
- data/lib/pubnub/schemas/envelope_schema.rb +1 -1
- data/lib/pubnub/validators/add_message_action.rb +51 -0
- data/lib/pubnub/validators/get_message_actions.rb +24 -0
- data/lib/pubnub/validators/remove_message_action.rb +35 -0
- data/lib/pubnub/version.rb +1 -1
- metadata +10 -6
- data/.github/workflows/run_acceptance_tests.yml +0 -46
- data/.github/workflows/validate-pubnub-yml.yml +0 -24
- data/.github/workflows/validate-yml.js +0 -95
- data/.travis.yml +0 -34
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 54a4586bf266ad9fd5d51168e215ac8dcf0f31a765ac15129314e184d4ae6a97
|
4
|
+
data.tar.gz: e814f4fee3cecaf6ba20c2ad0f349af4b5eabf7507261fcadd986339624a8bdc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 71223b6e8268f6a126e780f55ce1b57488e73d86b0185fe283b9665cde7aa470b3a9168fddd99b7090f3f5a1ff04ac5b49fd1ef12cb0b14c06b76f24828375a9
|
7
|
+
data.tar.gz: 5133e307589a55f0b352a016b3301cfff3c946fb0e750c391ceca648e2551bb7f970b321be8365a26d3f2bbff5771de2dc6ec1665a2ce84dfb65b13fd20ed4da
|
@@ -56,3 +56,8 @@ jobs:
|
|
56
56
|
token: ${{ secrets.GH_TOKEN }}
|
57
57
|
jira-api-key: ${{ secrets.JIRA_API_KEY }}
|
58
58
|
last-service: true
|
59
|
+
- name: Upload test reports
|
60
|
+
uses: ./.github/.release/actions/actions/test-reports/upload
|
61
|
+
with:
|
62
|
+
token: ${{ secrets.GH_TOKEN }}
|
63
|
+
acceptance-tests-workflow: Tests
|
@@ -0,0 +1,84 @@
|
|
1
|
+
name: Tests
|
2
|
+
|
3
|
+
on:
|
4
|
+
push:
|
5
|
+
workflow_dispatch:
|
6
|
+
|
7
|
+
|
8
|
+
jobs:
|
9
|
+
tests:
|
10
|
+
name: Integration and Unit tests
|
11
|
+
runs-on: ubuntu-latest
|
12
|
+
steps:
|
13
|
+
- name: Checkout repository
|
14
|
+
uses: actions/checkout@v3
|
15
|
+
with:
|
16
|
+
token: ${{ secrets.GH_TOKEN }}
|
17
|
+
- name: Setup Ruby 2.5.8
|
18
|
+
uses: ruby/setup-ruby@v1
|
19
|
+
with:
|
20
|
+
ruby-version: 2.5.8
|
21
|
+
bundler-cache: true
|
22
|
+
- name: Build and run tests for Ruby 2.5.8
|
23
|
+
run: bundle exec rspec
|
24
|
+
- name: Setup Ruby 2.6.6
|
25
|
+
uses: ruby/setup-ruby@v1
|
26
|
+
with:
|
27
|
+
ruby-version: 2.6.6
|
28
|
+
bundler-cache: true
|
29
|
+
- name: Build and run tests for Ruby 2.6.6
|
30
|
+
run: bundle exec rspec
|
31
|
+
- name: Setup Ruby 2.7.1
|
32
|
+
uses: ruby/setup-ruby@v1
|
33
|
+
with:
|
34
|
+
ruby-version: 2.7.1
|
35
|
+
bundler-cache: true
|
36
|
+
- name: Build and run tests for Ruby 2.7.1
|
37
|
+
run: bundle exec rspec
|
38
|
+
- name: Setup JRuby
|
39
|
+
uses: ruby/setup-ruby@v1
|
40
|
+
with:
|
41
|
+
ruby-version: jruby
|
42
|
+
bundler-cache: true
|
43
|
+
acceptance:
|
44
|
+
name: Acceptance tests
|
45
|
+
runs-on: ubuntu-latest
|
46
|
+
steps:
|
47
|
+
- name: Checkout project
|
48
|
+
uses: actions/checkout@v3
|
49
|
+
- name: Checkout mock-server action
|
50
|
+
uses: actions/checkout@v3
|
51
|
+
with:
|
52
|
+
repository: pubnub/client-engineering-deployment-tools
|
53
|
+
ref: v1
|
54
|
+
token: ${{ secrets.GH_TOKEN }}
|
55
|
+
path: .github/.release/actions
|
56
|
+
- name: Run mock server action
|
57
|
+
uses: ./.github/.release/actions/actions/mock-server
|
58
|
+
with:
|
59
|
+
token: ${{ secrets.GH_TOKEN }}
|
60
|
+
- name: Setup Ruby 3.0
|
61
|
+
uses: ruby/setup-ruby@v1
|
62
|
+
with:
|
63
|
+
ruby-version: 3.0
|
64
|
+
bundler-cache: true
|
65
|
+
- name: Run acceptance tests (optional)
|
66
|
+
run: bundle exec cucumber sdk-specifications/features/ -p mock -p run_beta -p report_beta -f pretty
|
67
|
+
continue-on-error: true
|
68
|
+
- name: Run acceptance tests (required)
|
69
|
+
run: bundle exec cucumber sdk-specifications/features/ -p mock -p run_main -p report_main -f pretty
|
70
|
+
- name: Combine test results
|
71
|
+
if: always()
|
72
|
+
run: |
|
73
|
+
sudo npm install -g junit-report-merger &&
|
74
|
+
jrm ./main.xml "./main/**/*.xml" &&
|
75
|
+
jrm ./beta.xml "./beta/**/*.xml"
|
76
|
+
- name: Expose acceptance tests reports
|
77
|
+
uses: actions/upload-artifact@v3
|
78
|
+
if: always()
|
79
|
+
with:
|
80
|
+
name: acceptance-test-reports
|
81
|
+
path: |
|
82
|
+
main.xml
|
83
|
+
beta.xml
|
84
|
+
retention-days: 7
|
@@ -0,0 +1,22 @@
|
|
1
|
+
name: Validations
|
2
|
+
|
3
|
+
on: [push]
|
4
|
+
|
5
|
+
jobs:
|
6
|
+
validators:
|
7
|
+
name: "Validate .pubnub.yml"
|
8
|
+
runs-on: ubuntu-latest
|
9
|
+
steps:
|
10
|
+
- name: Checkout project
|
11
|
+
uses: actions/checkout@v3
|
12
|
+
- name: Checkout validator action
|
13
|
+
uses: actions/checkout@v3
|
14
|
+
with:
|
15
|
+
repository: pubnub/client-engineering-deployment-tools
|
16
|
+
ref: v1
|
17
|
+
token: ${{ secrets.GH_TOKEN }}
|
18
|
+
path: .github/.release/actions
|
19
|
+
- name: "Run '.pubnub.yml' file validation"
|
20
|
+
uses: ./.github/.release/actions/actions/validators/pubnub-yml
|
21
|
+
with:
|
22
|
+
token: ${{ secrets.GH_TOKEN }}
|
data/.pubnub.yml
CHANGED
@@ -1,6 +1,13 @@
|
|
1
1
|
---
|
2
|
-
version: "5.
|
2
|
+
version: "5.2.0"
|
3
3
|
changelog:
|
4
|
+
- date: 2022-12-12
|
5
|
+
version: v5.2.0
|
6
|
+
changes:
|
7
|
+
- type: feature
|
8
|
+
text: "Add api which allow to work with message actions endpoints."
|
9
|
+
- type: improvement
|
10
|
+
text: "Migrate test suite run from Travis to GitHub Actions."
|
4
11
|
- date: 2022-11-23
|
5
12
|
version: v5.1.2
|
6
13
|
changes:
|
@@ -642,7 +649,7 @@ sdks:
|
|
642
649
|
- x86-64
|
643
650
|
- distribution-type: package
|
644
651
|
distribution-repository: RubyGems
|
645
|
-
package-name: pubnub-5.
|
652
|
+
package-name: pubnub-5.2.0.gem
|
646
653
|
location: https://rubygems.org/gems/pubnub
|
647
654
|
requires:
|
648
655
|
- name: addressable
|
@@ -747,8 +754,8 @@ sdks:
|
|
747
754
|
- x86-64
|
748
755
|
- distribution-type: library
|
749
756
|
distribution-repository: GitHub release
|
750
|
-
package-name: pubnub-5.
|
751
|
-
location: https://github.com/pubnub/ruby/releases/download/v5.
|
757
|
+
package-name: pubnub-5.2.0.gem
|
758
|
+
location: https://github.com/pubnub/ruby/releases/download/v5.2.0/pubnub-5.2.0.gem
|
752
759
|
requires:
|
753
760
|
- name: addressable
|
754
761
|
min-version: 2.0.0
|
data/.tool-versions
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby 3.
|
1
|
+
ruby jruby-9.3.8.0
|
data/CHANGELOG.md
CHANGED
data/Gemfile.lock
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
5.
|
1
|
+
5.2.0
|
data/lib/pubnub/client/events.rb
CHANGED
@@ -6,6 +6,7 @@ module Pubnub
|
|
6
6
|
module Events
|
7
7
|
EVENTS = %w[publish subscribe presence leave history here_now audit grant grant_token revoke_token delete_messages
|
8
8
|
revoke time heartbeat where_now set_state state channel_registration message_counts signal
|
9
|
+
add_message_action get_message_actions remove_message_action
|
9
10
|
add_channels_to_push list_push_provisions remove_channels_from_push remove_device_from_push
|
10
11
|
set_uuid_metadata set_channel_metadata remove_uuid_metadata remove_channel_metadata
|
11
12
|
get_uuid_metadata get_all_uuid_metadata get_channel_metadata get_all_channels_metadata
|
data/lib/pubnub/client.rb
CHANGED
@@ -31,6 +31,9 @@ require 'pubnub/client/paged_history'
|
|
31
31
|
require 'pubnub/client/helpers'
|
32
32
|
require 'pubnub/client/getters_setters'
|
33
33
|
|
34
|
+
require 'pubnub/validators/get_message_actions'
|
35
|
+
require 'pubnub/validators/add_message_action'
|
36
|
+
require 'pubnub/validators/remove_message_action'
|
34
37
|
require 'pubnub/validators/common_validator'
|
35
38
|
require 'pubnub/validators/client'
|
36
39
|
require 'pubnub/validators/audit'
|
data/lib/pubnub/constants.rb
CHANGED
@@ -61,6 +61,9 @@ module Pubnub
|
|
61
61
|
OPERATION_REVOKE_TOKEN = :revoke_token
|
62
62
|
OPERATION_REVOKE = :revoke
|
63
63
|
OPERATION_DELETE = :delete
|
64
|
+
OPERATION_ADD_MESSAGE_ACTION = :add_message_action
|
65
|
+
OPERATION_REMOVE_MESSAGE_ACTION = :remove_message_action
|
66
|
+
OPERATION_GET_MESSAGE_ACTIONS = :get_message_actions
|
64
67
|
OPERATION_LIST_ALL_CHANNEL_GROUPS = :list_all_channel_groups
|
65
68
|
OPERATION_LIST_ALL_CHANNELS_IN_CHANNEL_GROUP = :list_all_channels_in_channel_group
|
66
69
|
OPERATION_MESSAGE_COUNTS = :message_counts
|
@@ -86,7 +89,8 @@ module Pubnub
|
|
86
89
|
|
87
90
|
OPERATIONS = [
|
88
91
|
OPERATION_SUBSCRIBE, OPERATION_HEARTBEAT, OPERATION_PRESENCE, OPERATION_TIME, OPERATION_HISTORY,
|
89
|
-
OPERATION_HERE_NOW, OPERATION_GLOBAL_HERE_NOW, OPERATION_GET_STATE,
|
92
|
+
OPERATION_HERE_NOW, OPERATION_GLOBAL_HERE_NOW, OPERATION_GET_STATE, OPERATION_ADD_MESSAGE_ACTION,
|
93
|
+
OPERATION_REMOVE_MESSAGE_ACTION, OPERATION_GET_MESSAGE_ACTIONS, OPERATION_LIST_ALL_CHANNEL_GROUPS,
|
90
94
|
OPERATION_LIST_ALL_CHANNELS_IN_CHANNEL_GROUP, OPERATION_CHANNEL_GROUP_ADD, OPERATION_CHANNEL_GROUP_REMOVE,
|
91
95
|
OPERATION_AUDIT, OPERATION_GRANT, OPERATION_GRANT_TOKEN, OPERATION_REVOKE, OPERATION_WHERE_NOW,
|
92
96
|
OPERATION_MESSAGE_COUNTS, OPERATION_ADD_CHANNELS_TO_PUSH, OPERATION_LIST_PUSH_PROVISIONS,
|
data/lib/pubnub/event.rb
CHANGED
@@ -53,11 +53,11 @@ module Pubnub
|
|
53
53
|
|
54
54
|
telemetry_time_start = ::Time.now.to_f
|
55
55
|
response = case operation_http_method
|
56
|
-
when
|
56
|
+
when 'get'
|
57
57
|
sender.get(uri.to_s, header: header)
|
58
|
-
when
|
58
|
+
when 'post'
|
59
59
|
sender.post(uri.to_s, body: compressed_body, header: header)
|
60
|
-
when
|
60
|
+
when 'patch'
|
61
61
|
sender.patch(uri.to_s, body: compressed_body, header: header)
|
62
62
|
else
|
63
63
|
sender.delete(uri.to_s, header: header)
|
@@ -112,18 +112,21 @@ module Pubnub
|
|
112
112
|
|
113
113
|
def operation_http_method
|
114
114
|
case @event
|
115
|
-
when Pubnub::Constants::OPERATION_DELETE, Pubnub::Constants::
|
116
|
-
Pubnub::Constants::
|
117
|
-
|
115
|
+
when Pubnub::Constants::OPERATION_DELETE, Pubnub::Constants::OPERATION_REMOVE_MESSAGE_ACTION,
|
116
|
+
Pubnub::Constants::OPERATION_REMOVE_CHANNEL_METADATA, Pubnub::Constants::OPERATION_REMOVE_UUID_METADATA,
|
117
|
+
Pubnub::Constants::OPERATION_REVOKE_TOKEN
|
118
|
+
'delete'
|
118
119
|
when Pubnub::Constants::OPERATION_SET_UUID_METADATA, Pubnub::Constants::OPERATION_SET_CHANNEL_METADATA,
|
119
120
|
Pubnub::Constants::OPERATION_SET_CHANNEL_MEMBERS, Pubnub::Constants::OPERATION_SET_MEMBERSHIPS,
|
120
121
|
Pubnub::Constants::OPERATION_REMOVE_CHANNEL_MEMBERS, Pubnub::Constants::OPERATION_REMOVE_MEMBERSHIPS
|
121
|
-
|
122
|
+
'patch'
|
123
|
+
when Pubnub::Constants::OPERATION_ADD_MESSAGE_ACTION
|
124
|
+
'post'
|
122
125
|
else
|
123
126
|
if @compressed_body.nil? || @compressed_body.empty?
|
124
|
-
|
127
|
+
'get'
|
125
128
|
else
|
126
|
-
|
129
|
+
'post'
|
127
130
|
end
|
128
131
|
end
|
129
132
|
end
|
@@ -168,14 +171,14 @@ module Pubnub
|
|
168
171
|
def create_variables_from_options(options)
|
169
172
|
variables = %w[channel channels message http_sync callback
|
170
173
|
ssl cipher_key random_iv secret_key auth_key
|
171
|
-
publish_key subscribe_key timetoken
|
174
|
+
publish_key subscribe_key timetoken action_timetoken message_timetoken
|
172
175
|
open_timeout read_timeout idle_timeout heartbeat
|
173
176
|
group action read write delete manage ttl presence start
|
174
177
|
end count limit reverse presence_callback store skip_validate
|
175
178
|
state channel_group channel_groups compressed meta customs include_token
|
176
179
|
replicate with_presence cipher_key_selector include_meta join update get
|
177
180
|
add remove push_token push_gateway environment topic authorized_uuid
|
178
|
-
authorized_user_id token
|
181
|
+
authorized_user_id token type value
|
179
182
|
]
|
180
183
|
|
181
184
|
options = options.each_with_object({}) { |option, obj| obj[option.first.to_sym] = option.last }
|
@@ -229,7 +232,8 @@ module Pubnub
|
|
229
232
|
}
|
230
233
|
end
|
231
234
|
|
232
|
-
def error_envelope(
|
235
|
+
def error_envelope(parsed_response, error, req_res_objects)
|
236
|
+
error_information = nil
|
233
237
|
case error
|
234
238
|
when JSON::ParserError
|
235
239
|
error_category = Pubnub::Constants::STATUS_NON_JSON_RESPONSE
|
@@ -243,6 +247,12 @@ module Pubnub
|
|
243
247
|
else
|
244
248
|
error_category = Pubnub::Constants::STATUS_ERROR
|
245
249
|
code = req_res_objects[:response].code
|
250
|
+
# Trying to receive useful information about error.
|
251
|
+
unless parsed_response.nil?
|
252
|
+
error_msg, error_details = error_details_from_response parsed_response
|
253
|
+
error_information = { message: error_msg, details: error_details } unless error_msg.nil?
|
254
|
+
end
|
255
|
+
|
246
256
|
end
|
247
257
|
|
248
258
|
Pubnub::ErrorEnvelope.new(
|
@@ -254,7 +264,7 @@ module Pubnub
|
|
254
264
|
operation: current_operation,
|
255
265
|
client_request: req_res_objects[:request],
|
256
266
|
server_response: req_res_objects[:response],
|
257
|
-
data:
|
267
|
+
data: error_information,
|
258
268
|
category: error_category,
|
259
269
|
error: true,
|
260
270
|
auto_retried: false,
|
@@ -263,5 +273,19 @@ module Pubnub
|
|
263
273
|
}
|
264
274
|
)
|
265
275
|
end
|
276
|
+
|
277
|
+
def error_details_from_response(parsed_response)
|
278
|
+
return [nil, nil] if parsed_response.nil?
|
279
|
+
|
280
|
+
error_msg = parsed_response.include?('message') ? parsed_response['message'] : nil
|
281
|
+
error_details = nil
|
282
|
+
|
283
|
+
if parsed_response.include?('error') && parsed_response['error'].is_a?(Hash)
|
284
|
+
error_msg = parsed_response['error']['message'] if parsed_response['error'].include? 'message'
|
285
|
+
error_details = parsed_response['error']['details'] if parsed_response['error'].include? 'details'
|
286
|
+
end
|
287
|
+
|
288
|
+
[error_msg, error_details]
|
289
|
+
end
|
266
290
|
end
|
267
291
|
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# Toplevel Pubnub module.
|
2
|
+
module Pubnub
|
3
|
+
# Holds add message action functionality
|
4
|
+
class AddMessageAction < SingleEvent
|
5
|
+
include Concurrent::Async
|
6
|
+
include Pubnub::Validator::AddMessageAction
|
7
|
+
|
8
|
+
def initialize(options, app)
|
9
|
+
@event = current_operation
|
10
|
+
@telemetry_name = :l_msga
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
def fire
|
15
|
+
Pubnub.logger.debug('Pubnub::Add Message Action') { "Fired event #{self.class}" }
|
16
|
+
type_payload = { type: @type, value: @value}
|
17
|
+
body = Formatter.format_message(type_payload, '', false, false)
|
18
|
+
|
19
|
+
response = send_request(body, { "Content-Type": 'application/json' })
|
20
|
+
|
21
|
+
envelopes = fire_callbacks(handle(response, uri))
|
22
|
+
finalize_event(envelopes)
|
23
|
+
envelopes
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def current_operation
|
29
|
+
Pubnub::Constants::OPERATION_ADD_MESSAGE_ACTION
|
30
|
+
end
|
31
|
+
|
32
|
+
def path
|
33
|
+
'/' + [
|
34
|
+
'v1',
|
35
|
+
'message-actions',
|
36
|
+
@subscribe_key,
|
37
|
+
'channel',
|
38
|
+
Formatter.channels_for_url(@channel),
|
39
|
+
'message',
|
40
|
+
@message_timetoken,
|
41
|
+
].join('/')
|
42
|
+
end
|
43
|
+
|
44
|
+
def valid_envelope(parsed_response, req_res_objects)
|
45
|
+
data = parsed_response['data']
|
46
|
+
|
47
|
+
Pubnub::Envelope.new(
|
48
|
+
event: @event,
|
49
|
+
event_options: @given_options,
|
50
|
+
timetoken: nil,
|
51
|
+
|
52
|
+
result: {
|
53
|
+
code: req_res_objects[:response].code,
|
54
|
+
operation: current_operation,
|
55
|
+
client_request: req_res_objects[:request],
|
56
|
+
server_response: req_res_objects[:response],
|
57
|
+
data: {
|
58
|
+
type: data['type'],
|
59
|
+
value: data['value'],
|
60
|
+
uuid: data['uuid'],
|
61
|
+
action_timetoken: data['actionTimetoken'].to_i,
|
62
|
+
message_timetoken: data['messageTimetoken'].to_i
|
63
|
+
}
|
64
|
+
},
|
65
|
+
|
66
|
+
status: {
|
67
|
+
code: req_res_objects[:response].code,
|
68
|
+
operation: current_operation,
|
69
|
+
client_request: req_res_objects[:request],
|
70
|
+
server_response: req_res_objects[:response],
|
71
|
+
data: nil,
|
72
|
+
category: Pubnub::Constants::STATUS_ACK,
|
73
|
+
error: false,
|
74
|
+
auto_retried: false,
|
75
|
+
|
76
|
+
current_timetoken: nil,
|
77
|
+
last_timetoken: nil,
|
78
|
+
subscribed_channels: nil,
|
79
|
+
subscribed_channel_groups: nil,
|
80
|
+
|
81
|
+
config: get_config
|
82
|
+
}
|
83
|
+
)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
# Toplevel Pubnub module.
|
2
|
+
module Pubnub
|
3
|
+
# Holds get message actions functionality
|
4
|
+
class GetMessageActions < SingleEvent
|
5
|
+
include Concurrent::Async
|
6
|
+
include Pubnub::Validator::GetMessageActions
|
7
|
+
|
8
|
+
def initialize(options, app)
|
9
|
+
@event = current_operation
|
10
|
+
@telemetry_name = :l_msga
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def parameters
|
17
|
+
parameters = super
|
18
|
+
parameters['start'] = @start unless @start.nil?
|
19
|
+
parameters['end'] = @end unless @end.nil?
|
20
|
+
parameters['limit'] = @limit unless @limit.nil?
|
21
|
+
parameters
|
22
|
+
end
|
23
|
+
|
24
|
+
def current_operation
|
25
|
+
Pubnub::Constants::OPERATION_GET_MESSAGE_ACTIONS
|
26
|
+
end
|
27
|
+
|
28
|
+
def path
|
29
|
+
'/' + [
|
30
|
+
'v1',
|
31
|
+
'message-actions',
|
32
|
+
@subscribe_key,
|
33
|
+
'channel',
|
34
|
+
Formatter.channels_for_url(@channel)
|
35
|
+
].join('/')
|
36
|
+
end
|
37
|
+
|
38
|
+
def valid_envelope(parsed_response, req_res_objects)
|
39
|
+
actions = parsed_response['data'].map do |v|
|
40
|
+
v['message_timetoken'] = v['messageTimetoken'].to_i
|
41
|
+
v['action_timetoken'] = v['actionTimetoken'].to_i
|
42
|
+
v.delete_if { |key| %w[messageTimetoken actionTimetoken].include? key }
|
43
|
+
end
|
44
|
+
|
45
|
+
Pubnub::Envelope.new(
|
46
|
+
event: @event,
|
47
|
+
event_options: @given_options,
|
48
|
+
timetoken: nil,
|
49
|
+
|
50
|
+
result: {
|
51
|
+
code: req_res_objects[:response].code,
|
52
|
+
operation: current_operation,
|
53
|
+
client_request: req_res_objects[:request],
|
54
|
+
server_response: req_res_objects[:response],
|
55
|
+
data: actions
|
56
|
+
},
|
57
|
+
|
58
|
+
status: {
|
59
|
+
code: req_res_objects[:response].code,
|
60
|
+
operation: current_operation,
|
61
|
+
client_request: req_res_objects[:request],
|
62
|
+
server_response: req_res_objects[:response],
|
63
|
+
data: nil,
|
64
|
+
category: Pubnub::Constants::STATUS_ACK,
|
65
|
+
error: false,
|
66
|
+
auto_retried: false,
|
67
|
+
|
68
|
+
current_timetoken: nil,
|
69
|
+
last_timetoken: nil,
|
70
|
+
subscribed_channels: nil,
|
71
|
+
subscribed_channel_groups: nil,
|
72
|
+
|
73
|
+
config: get_config
|
74
|
+
}
|
75
|
+
)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# Toplevel Pubnub module.
|
2
|
+
module Pubnub
|
3
|
+
# Holds get message actions functionality
|
4
|
+
class RemoveMessageAction < SingleEvent
|
5
|
+
include Concurrent::Async
|
6
|
+
include Pubnub::Validator::RemoveMessageAction
|
7
|
+
|
8
|
+
def initialize(options, app)
|
9
|
+
@event = current_operation
|
10
|
+
@telemetry_name = :l_msga
|
11
|
+
super
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def current_operation
|
17
|
+
Pubnub::Constants::OPERATION_REMOVE_MESSAGE_ACTION
|
18
|
+
end
|
19
|
+
|
20
|
+
def path
|
21
|
+
'/' + [
|
22
|
+
'v1',
|
23
|
+
'message-actions',
|
24
|
+
@subscribe_key,
|
25
|
+
'channel',
|
26
|
+
Formatter.channels_for_url(@channel),
|
27
|
+
'message',
|
28
|
+
@message_timetoken,
|
29
|
+
'action',
|
30
|
+
@action_timetoken
|
31
|
+
].join('/')
|
32
|
+
end
|
33
|
+
|
34
|
+
def valid_envelope(parsed_response, req_res_objects)
|
35
|
+
Pubnub::Envelope.new(
|
36
|
+
event: @event,
|
37
|
+
event_options: @given_options,
|
38
|
+
timetoken: nil,
|
39
|
+
|
40
|
+
result: {
|
41
|
+
code: req_res_objects[:response].code,
|
42
|
+
operation: current_operation,
|
43
|
+
client_request: req_res_objects[:request],
|
44
|
+
server_response: req_res_objects[:response],
|
45
|
+
data: parsed_response['data']
|
46
|
+
},
|
47
|
+
|
48
|
+
status: {
|
49
|
+
code: req_res_objects[:response].code,
|
50
|
+
operation: current_operation,
|
51
|
+
client_request: req_res_objects[:request],
|
52
|
+
server_response: req_res_objects[:response],
|
53
|
+
data: nil,
|
54
|
+
category: Pubnub::Constants::STATUS_ACK,
|
55
|
+
error: false,
|
56
|
+
auto_retried: false,
|
57
|
+
|
58
|
+
current_timetoken: nil,
|
59
|
+
last_timetoken: nil,
|
60
|
+
subscribed_channels: nil,
|
61
|
+
subscribed_channel_groups: nil,
|
62
|
+
|
63
|
+
config: get_config
|
64
|
+
}
|
65
|
+
)
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# Toplevel Pubnub module.
|
2
|
+
module Pubnub
|
3
|
+
# Validator module that holds all validators modules
|
4
|
+
module Validator
|
5
|
+
# Validator for AddMessageAction event
|
6
|
+
module AddMessageAction
|
7
|
+
include CommonValidator
|
8
|
+
|
9
|
+
def validate!
|
10
|
+
return if @skip_validate
|
11
|
+
|
12
|
+
validate_channel!
|
13
|
+
validate_type!
|
14
|
+
validate_value!
|
15
|
+
validate_timetoken!
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def validate_channel!
|
21
|
+
return unless @channel.nil? || @channel.empty?
|
22
|
+
|
23
|
+
raise ArgumentError, { message: ':channel is required for AddMessageAction event.' }
|
24
|
+
end
|
25
|
+
|
26
|
+
def validate_type!
|
27
|
+
if @type.is_a? String
|
28
|
+
raise ArgumentError, {message:':type is required for AddMessageAction event.'} if @type.empty?
|
29
|
+
else
|
30
|
+
raise ArgumentError, {message:':type should be String.'}
|
31
|
+
end
|
32
|
+
raise ArgumentError, {message:':type should be not longer than 15 characters.'} unless @type.length <= 15
|
33
|
+
end
|
34
|
+
|
35
|
+
def validate_value!
|
36
|
+
if @value.is_a? String
|
37
|
+
raise ArgumentError, {message:':value is required for AddMessageAction event.'} if @type.empty?
|
38
|
+
else
|
39
|
+
raise ArgumentError, {message:':value should be String.'}
|
40
|
+
end
|
41
|
+
raise ArgumentError, {message:':value should be String.'} unless @value.is_a? String
|
42
|
+
end
|
43
|
+
|
44
|
+
def validate_timetoken!
|
45
|
+
raise ArgumentError, {message:':message_timetoken is required for AddMessageAction event.'} if @message_timetoken.nil?
|
46
|
+
raise ArgumentError, {message:':message_timetoken should be Numeric.'} unless @message_timetoken.is_a? Numeric
|
47
|
+
raise ArgumentError, {message:':message_timetoken should be PubNub timetoken larger than 0.'} unless @message_timetoken.positive?
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# Toplevel Pubnub module.
|
2
|
+
module Pubnub
|
3
|
+
# Validator module that holds all validators modules
|
4
|
+
module Validator
|
5
|
+
# Validator for module GetMessageActions event
|
6
|
+
module GetMessageActions
|
7
|
+
include CommonValidator
|
8
|
+
|
9
|
+
def validate!
|
10
|
+
return if @skip_validate
|
11
|
+
|
12
|
+
validate_channel!
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
|
17
|
+
def validate_channel!
|
18
|
+
return unless @channel.nil? || @channel.empty?
|
19
|
+
|
20
|
+
raise ArgumentError, { message: ':channel is required for GetMessageAction event.' }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# Toplevel Pubnub module.
|
2
|
+
module Pubnub
|
3
|
+
# Validator module that holds all validators modules
|
4
|
+
module Validator
|
5
|
+
# Validator for RemoveMessageAction event
|
6
|
+
module RemoveMessageAction
|
7
|
+
include CommonValidator
|
8
|
+
|
9
|
+
def validate!
|
10
|
+
return if @skip_validate
|
11
|
+
|
12
|
+
validate_channel!
|
13
|
+
validate_timetokens!
|
14
|
+
end
|
15
|
+
|
16
|
+
private
|
17
|
+
|
18
|
+
def validate_channel!
|
19
|
+
return unless @channel.nil? || @channel.empty?
|
20
|
+
|
21
|
+
raise ArgumentError, { message: ':channel is required for RemoveMessageAction event.' }
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_timetokens!
|
25
|
+
raise ArgumentError, {message:':message_timetoken is required for RemoveMessageAction event.'} if @message_timetoken.nil?
|
26
|
+
raise ArgumentError, {message:':message_timetoken should be Numeric.'} unless @message_timetoken.is_a? Numeric
|
27
|
+
raise ArgumentError, {message:':message_timetoken should be PubNub timetoken larger than 0.'} unless @message_timetoken.positive?
|
28
|
+
|
29
|
+
raise ArgumentError, {message:':action_timetoken is required for RemoveMessageAction event.'} if @action_timetoken.nil?
|
30
|
+
raise ArgumentError, {message:':action_timetoken should be Numeric.'} unless @action_timetoken.is_a? Numeric
|
31
|
+
raise ArgumentError, {message:':action_timetoken should be PubNub timetoken larger than 0.'} unless @action_timetoken.positive?
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
data/lib/pubnub/version.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pubnub
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- PubNub
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-
|
11
|
+
date: 2022-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: addressable
|
@@ -133,14 +133,12 @@ files:
|
|
133
133
|
- ".github/workflows/commands-handler.yml"
|
134
134
|
- ".github/workflows/release.yml"
|
135
135
|
- ".github/workflows/release/versions.json"
|
136
|
-
- ".github/workflows/
|
137
|
-
- ".github/workflows/
|
138
|
-
- ".github/workflows/validate-yml.js"
|
136
|
+
- ".github/workflows/run-tests.yml"
|
137
|
+
- ".github/workflows/run-validations.yml"
|
139
138
|
- ".gitignore"
|
140
139
|
- ".pubnub.yml"
|
141
140
|
- ".rubocop.yml"
|
142
141
|
- ".tool-versions"
|
143
|
-
- ".travis.yml"
|
144
142
|
- ".yardopts"
|
145
143
|
- CHANGELOG.md
|
146
144
|
- Gemfile
|
@@ -181,6 +179,7 @@ files:
|
|
181
179
|
- lib/pubnub/event/formatter.rb
|
182
180
|
- lib/pubnub/event/signature.rb
|
183
181
|
- lib/pubnub/events/add_channels_to_push.rb
|
182
|
+
- lib/pubnub/events/add_message_action.rb
|
184
183
|
- lib/pubnub/events/audit.rb
|
185
184
|
- lib/pubnub/events/channel_registration.rb
|
186
185
|
- lib/pubnub/events/delete_messages.rb
|
@@ -189,6 +188,7 @@ files:
|
|
189
188
|
- lib/pubnub/events/get_channel_members.rb
|
190
189
|
- lib/pubnub/events/get_channel_metadata.rb
|
191
190
|
- lib/pubnub/events/get_memberships.rb
|
191
|
+
- lib/pubnub/events/get_message_actions.rb
|
192
192
|
- lib/pubnub/events/get_uuid_metadata.rb
|
193
193
|
- lib/pubnub/events/grant.rb
|
194
194
|
- lib/pubnub/events/grant_token.rb
|
@@ -205,6 +205,7 @@ files:
|
|
205
205
|
- lib/pubnub/events/remove_channels_from_push.rb
|
206
206
|
- lib/pubnub/events/remove_device_from_push.rb
|
207
207
|
- lib/pubnub/events/remove_memberships.rb
|
208
|
+
- lib/pubnub/events/remove_message_actions.rb
|
208
209
|
- lib/pubnub/events/remove_uuid_metadata.rb
|
209
210
|
- lib/pubnub/events/revoke.rb
|
210
211
|
- lib/pubnub/events/revoke_token.rb
|
@@ -236,6 +237,7 @@ files:
|
|
236
237
|
- lib/pubnub/telemetry.rb
|
237
238
|
- lib/pubnub/uuid.rb
|
238
239
|
- lib/pubnub/validators/add_channels_to_push.rb
|
240
|
+
- lib/pubnub/validators/add_message_action.rb
|
239
241
|
- lib/pubnub/validators/audit.rb
|
240
242
|
- lib/pubnub/validators/channel_registration.rb
|
241
243
|
- lib/pubnub/validators/client.rb
|
@@ -246,6 +248,7 @@ files:
|
|
246
248
|
- lib/pubnub/validators/get_channel_members.rb
|
247
249
|
- lib/pubnub/validators/get_channel_metadata.rb
|
248
250
|
- lib/pubnub/validators/get_memberships.rb
|
251
|
+
- lib/pubnub/validators/get_message_actions.rb
|
249
252
|
- lib/pubnub/validators/get_uuid_metadata.rb
|
250
253
|
- lib/pubnub/validators/grant.rb
|
251
254
|
- lib/pubnub/validators/grant_token.rb
|
@@ -262,6 +265,7 @@ files:
|
|
262
265
|
- lib/pubnub/validators/remove_channels_from_push.rb
|
263
266
|
- lib/pubnub/validators/remove_device_from_push.rb
|
264
267
|
- lib/pubnub/validators/remove_memberships.rb
|
268
|
+
- lib/pubnub/validators/remove_message_action.rb
|
265
269
|
- lib/pubnub/validators/remove_uuid_metadata.rb
|
266
270
|
- lib/pubnub/validators/revoke.rb
|
267
271
|
- lib/pubnub/validators/revoke_token.rb
|
@@ -1,46 +0,0 @@
|
|
1
|
-
name: run_acceptance_tests
|
2
|
-
|
3
|
-
on: [push]
|
4
|
-
|
5
|
-
jobs:
|
6
|
-
build:
|
7
|
-
name: Perform Acceptance BDD tests
|
8
|
-
runs-on: ubuntu-latest
|
9
|
-
steps:
|
10
|
-
- name: Checkout project
|
11
|
-
uses: actions/checkout@v3
|
12
|
-
- name: Checkout mock-server action
|
13
|
-
uses: actions/checkout@v3
|
14
|
-
with:
|
15
|
-
repository: pubnub/client-engineering-deployment-tools
|
16
|
-
ref: v1
|
17
|
-
token: ${{ secrets.GH_TOKEN }}
|
18
|
-
path: client-engineering-deployment-tools
|
19
|
-
- name: Run mock server action
|
20
|
-
uses: ./client-engineering-deployment-tools/actions/mock-server
|
21
|
-
with:
|
22
|
-
token: ${{ secrets.GH_TOKEN }}
|
23
|
-
- name: Install dependencies
|
24
|
-
run: |
|
25
|
-
sudo gem install bundler &&
|
26
|
-
bundle install
|
27
|
-
- name: Run acceptance tests (optional)
|
28
|
-
run: bundle exec cucumber sdk-specifications/features/ -p mock -p run_beta -p report_beta -f pretty
|
29
|
-
continue-on-error: true
|
30
|
-
- name: Run acceptance tests (required)
|
31
|
-
run: bundle exec cucumber sdk-specifications/features/ -p mock -p run_main -p report_main -f pretty
|
32
|
-
- name: Combine test results
|
33
|
-
if: always()
|
34
|
-
run: |
|
35
|
-
sudo npm install -g junit-report-merger &&
|
36
|
-
jrm ./main.xml "./main/**/*.xml" &&
|
37
|
-
jrm ./beta.xml "./beta/**/*.xml"
|
38
|
-
- name: Expose main report
|
39
|
-
uses: actions/upload-artifact@v3
|
40
|
-
if: always()
|
41
|
-
with:
|
42
|
-
name: acceptance-test-reports
|
43
|
-
path: |
|
44
|
-
main.xml
|
45
|
-
beta.xml
|
46
|
-
retention-days: 7
|
@@ -1,24 +0,0 @@
|
|
1
|
-
name: validate-pubnub-yml
|
2
|
-
|
3
|
-
# Controls when the action will run. Workflow runs when manually triggered using the UI
|
4
|
-
# or API.
|
5
|
-
on: [push]
|
6
|
-
|
7
|
-
jobs:
|
8
|
-
build:
|
9
|
-
name: Validate PubNub yml
|
10
|
-
runs-on: ubuntu-latest
|
11
|
-
steps:
|
12
|
-
- uses: actions/checkout@v3
|
13
|
-
- name: Use Node.js
|
14
|
-
uses: actions/setup-node@v1
|
15
|
-
with:
|
16
|
-
node-version: '12.x'
|
17
|
-
- name: Install dependencies
|
18
|
-
run: |
|
19
|
-
npm install ajv@6.12.6
|
20
|
-
npm install yaml@1.10.0
|
21
|
-
npm install node-fetch@2.6.1
|
22
|
-
npm install chalk@2.4.2
|
23
|
-
- name: Validate
|
24
|
-
run: GITHUB_TOKEN=${{ secrets.GH_TOKEN }} node ./.github/workflows/validate-yml.js
|
@@ -1,95 +0,0 @@
|
|
1
|
-
const YAML = require('yaml')
|
2
|
-
const Ajv = require('ajv');
|
3
|
-
const fetch = require('node-fetch');
|
4
|
-
const fs = require('fs');
|
5
|
-
const chalk = require('chalk');
|
6
|
-
|
7
|
-
const ghToken = process.env.GITHUB_TOKEN;
|
8
|
-
const ghHeaders = {'User-Agent': 'sdk-bot', 'Authorization': 'token ' + ghToken,'Accept': 'application/vnd.github.v3.raw'};
|
9
|
-
|
10
|
-
const sdkReposJSONBranch = "develop";
|
11
|
-
let sdkReposJSONPath = "http://api.github.com/repos/pubnub/documentation-resources/contents/website-common/tools/build/sdk-repos.json?ref=" + sdkReposJSONBranch;
|
12
|
-
startExecution(sdkReposJSONPath);
|
13
|
-
|
14
|
-
async function startExecution(sdkReposJSONPath){
|
15
|
-
console.log('JSON:', sdkReposJSONPath);
|
16
|
-
var sdkRepos = await requestGetFromGithub(sdkReposJSONPath);
|
17
|
-
var sdkReposAndFeatureMappingArray = parseReposAndFeatureMapping(sdkRepos);
|
18
|
-
var schemaText = await requestGetFromGithub(sdkReposAndFeatureMappingArray[2]);
|
19
|
-
|
20
|
-
schema = JSON.parse(schemaText);
|
21
|
-
var yaml = fs.readFileSync(".pubnub.yml", 'utf8');
|
22
|
-
|
23
|
-
if(yaml != null){
|
24
|
-
yml = YAML.parse(yaml);
|
25
|
-
var ajv = new Ajv({schemaId: 'id', "verbose":true, "allErrors": true});
|
26
|
-
const validate = ajv.compile(schema);
|
27
|
-
const valid = validate(yml);
|
28
|
-
if (validate.errors!= null) {
|
29
|
-
console.log(chalk.cyan("==================================="));
|
30
|
-
console.log(chalk.red(yml["version"] + " validation errors..."));
|
31
|
-
console.log(chalk.cyan("==================================="));
|
32
|
-
console.log(validate.errors);
|
33
|
-
console.log(chalk.cyan("==================================="));
|
34
|
-
var result = {code:1, repo: yml["version"], msg: "validation errors"};
|
35
|
-
printResult(result);
|
36
|
-
process.exit(1);
|
37
|
-
}
|
38
|
-
else {
|
39
|
-
var result = {code: 0, repo: yml["version"], msg: "validation pass"};
|
40
|
-
printResult(result);
|
41
|
-
}
|
42
|
-
} else {
|
43
|
-
var result = {code:1, repo: "yml null", msg: "validation errors"};
|
44
|
-
printResult(result);
|
45
|
-
process.exit(1);
|
46
|
-
}
|
47
|
-
}
|
48
|
-
|
49
|
-
function printResult(result){
|
50
|
-
var str = result.repo + ", " + result.msg;
|
51
|
-
if(result.code === 0){
|
52
|
-
console.log(chalk.green(str) + ", Code: " + result.code);
|
53
|
-
} else {
|
54
|
-
console.log(chalk.red(str) + ", Code: " + result.code);
|
55
|
-
}
|
56
|
-
}
|
57
|
-
|
58
|
-
async function requestGetFromGithub(url){
|
59
|
-
try {
|
60
|
-
const response = await fetch(url, {
|
61
|
-
headers: ghHeaders,
|
62
|
-
method: 'get',
|
63
|
-
});
|
64
|
-
if(response.status == 200){
|
65
|
-
const json = await response.text();
|
66
|
-
return json;
|
67
|
-
} else {
|
68
|
-
console.error(chalk.red("res.status: " + response.status + "\n URL: " + url));
|
69
|
-
return null;
|
70
|
-
}
|
71
|
-
|
72
|
-
} catch (error) {
|
73
|
-
console.error(chalk.red("requestGetFromGithub: " + error + "\n URL: " + url));
|
74
|
-
return null;
|
75
|
-
}
|
76
|
-
}
|
77
|
-
|
78
|
-
function parseReposAndFeatureMapping(body){
|
79
|
-
if(body != null){
|
80
|
-
var sdkRepos = JSON.parse(body);
|
81
|
-
var locations = sdkRepos["locations"];
|
82
|
-
if(locations!=null){
|
83
|
-
var sdkURLs = locations["sdks"];
|
84
|
-
var featureMappingURL = locations["featureMapping"];
|
85
|
-
var pubnubYAMLSchemaURL = locations["pubnubYAMLSchema"];
|
86
|
-
return [sdkURLs, featureMappingURL, pubnubYAMLSchemaURL];
|
87
|
-
} else {
|
88
|
-
console.log(chalk.red("response locations null"));
|
89
|
-
return null;
|
90
|
-
}
|
91
|
-
} else {
|
92
|
-
console.log(chalk.red("response body null"));
|
93
|
-
return null;
|
94
|
-
}
|
95
|
-
}
|
data/.travis.yml
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
language: ruby
|
2
|
-
dist: xenial
|
3
|
-
os: linux
|
4
|
-
|
5
|
-
before_install:
|
6
|
-
# See https://github.com/travis-ci/travis-ci/issues/5861
|
7
|
-
- gem update --system
|
8
|
-
- gem install bundler
|
9
|
-
- gem update bundler
|
10
|
-
|
11
|
-
bundler_args: --without development
|
12
|
-
|
13
|
-
|
14
|
-
stages:
|
15
|
-
- name: "test"
|
16
|
-
|
17
|
-
jobs:
|
18
|
-
include:
|
19
|
-
- name: 'Ruby 2.5.8'
|
20
|
-
rvm: '2.5.8'
|
21
|
-
script: bundle exec rspec
|
22
|
-
- name: 'Ruby 2.6.6'
|
23
|
-
rvm: '2.6.6'
|
24
|
-
script: bundle exec rspec
|
25
|
-
- name: 'Ruby 2.7.1'
|
26
|
-
rvm: '2.7.1'
|
27
|
-
script: bundle exec rspec
|
28
|
-
- name: 'Ruby JRuby'
|
29
|
-
rvm: 'jruby-9.3.4.0'
|
30
|
-
env: JRUBY_TEST=true NO_COVERAGE=true JRUBY_OPTS="--server -J-Xms2048m -J-Xmx2048m -J-XX:-UseGCOverheadLimit -J-XX:+CMSClassUnloadingEnabled"
|
31
|
-
jdk: oraclejdk11
|
32
|
-
script:
|
33
|
-
- jruby -S rspec ./spec/examples/
|
34
|
-
- jruby -S rspec ./spec/lib/
|