hastci 0.1.2 → 0.1.3

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b5b2325eb3310d82c948100ad8944303a1cafc0f3824497fa68ff3a2d229184b
4
- data.tar.gz: 93b8a6e612a613d8491624008fa0e334653aff2b769e437385141c56ad62372b
3
+ metadata.gz: c539e7bbcfc1e63ae87f60a4802989e13917dfd260c90f5b4ae034790351bfc5
4
+ data.tar.gz: 3246b32dbd057b5435404c37d1938049e96bbcb27643df0a69cb1f07c4b6d2d6
5
5
  SHA512:
6
- metadata.gz: d8d05f307a3408f5238081361f11c5fafbf5e5f1c1eb822bbeaf8dd42fb172bc4048ca7ae6d3303aa5cf77de543f51cea829313e7efaee814c74df59680debe3
7
- data.tar.gz: 9b557ef0c58252027907cb79197d00273e100a7735b2072203d68c897c6a966cb0b47d0d985993ebcedf2954ab1238cdab9333902352a28cdb8fd3344d0a5397
6
+ metadata.gz: 6fbd3844f3a7791f4ca01a315bce6e999b5431dbe7aeb89e70e897c1ba467664d985943bd50bcd7b71854e4c563624a8fe54001da2f22424371857a71af800c1
7
+ data.tar.gz: 86d5796be2b12d15b5a5b26b9ec57ad8c7862a88cf4d57af663db85164608a49483048eb747c99a4799326d788aa881eed99059c7f3236a24455a077f68f9f32
@@ -4,7 +4,7 @@ module HastCI
4
4
  class AckWorker
5
5
  DEFAULT_QUEUE_SIZE = 1000
6
6
  DEFAULT_FLUSH_TIMEOUT = 10
7
- EMPTY_QUEUE_POLL_INTERVAL = 0.05
7
+ EMPTY_QUEUE_POLL_INTERVAL = 0.5
8
8
  SHUTDOWN_TIMEOUT = 10
9
9
 
10
10
  private_constant :DEFAULT_QUEUE_SIZE, :DEFAULT_FLUSH_TIMEOUT, :EMPTY_QUEUE_POLL_INTERVAL,
@@ -147,27 +147,18 @@ module HastCI
147
147
  end
148
148
 
149
149
  def build_logs(failed_examples)
150
- {
151
- summary: summary_for(failed_examples),
152
- failures: failed_examples.map { |example| failure_payload(example) }
153
- }
154
- end
155
-
156
- def summary_for(failed_examples)
157
- return "passed" if failed_examples.empty?
150
+ return [] if failed_examples.empty?
158
151
 
159
- "failed: #{failed_examples.length}"
160
- end
152
+ failed_examples.map do |example|
153
+ exception = example.exception
161
154
 
162
- def failure_payload(example)
163
- exception = example.exception
164
-
165
- {
166
- file: example.metadata[:file_path],
167
- line: example.metadata[:line_number],
168
- message: exception&.message,
169
- backtrace: Array(exception&.backtrace)
170
- }
155
+ {
156
+ file: example.metadata[:file_path],
157
+ line: example.metadata[:line_number],
158
+ message: exception&.message,
159
+ backtrace: Array(exception&.backtrace)
160
+ }
161
+ end
171
162
  end
172
163
 
173
164
  def ordered_task_names(example_groups)
@@ -7,6 +7,8 @@ require "uri"
7
7
 
8
8
  module HastCI
9
9
  class ApiClient
10
+ OriginalNetHTTP = Net::HTTP
11
+
10
12
  DEFAULT_MAX_RETRIES = 5
11
13
  DEFAULT_INITIAL_BACKOFF = 0.5
12
14
  DEFAULT_MAX_BACKOFF = 30
@@ -28,11 +30,13 @@ module HastCI
28
30
 
29
31
  private_constant :API_PATH_PREFIX, :CONNECTION_DEFAULT, :CONNECTION_HEARTBEAT, :CONNECTION_ACK
30
32
 
31
- def initialize(config:, sleeper: Kernel.method(:sleep), max_retries: nil, random: Random.new)
33
+ def initialize(config:, sleeper: Kernel.method(:sleep), max_retries: nil, random: Random.new,
34
+ http_class: OriginalNetHTTP)
32
35
  @config = config
33
36
  @max_retries = max_retries || config.api_max_retries || DEFAULT_MAX_RETRIES
34
37
  @sleeper = sleeper
35
38
  @random = random
39
+ @http_class = http_class
36
40
 
37
41
  @base_url = URI.parse(config.api_base_url)
38
42
  @api_key = config.api_key
@@ -140,7 +144,7 @@ module HastCI
140
144
 
141
145
  def get_json(path, pool: CONNECTION_DEFAULT)
142
146
  uri = build_uri(path)
143
- request = Net::HTTP::Get.new(uri)
147
+ request = @http_class::Get.new(uri)
144
148
  request["Authorization"] = "Bearer #{@api_key}"
145
149
 
146
150
  execute_request(request, pool: pool)
@@ -148,7 +152,7 @@ module HastCI
148
152
 
149
153
  def post_json(path, body, pool: CONNECTION_DEFAULT)
150
154
  uri = build_uri(path)
151
- request = Net::HTTP::Post.new(uri)
155
+ request = @http_class::Post.new(uri)
152
156
  request["Content-Type"] = "application/json"
153
157
  request["Authorization"] = "Bearer #{@api_key}"
154
158
  request.body = JSON.generate(body)
@@ -226,7 +230,7 @@ module HastCI
226
230
  end
227
231
 
228
232
  def create_connection
229
- http = Net::HTTP.new(@base_url.host, @base_url.port)
233
+ http = @http_class.new(@base_url.host, @base_url.port)
230
234
  http.use_ssl = @base_url.scheme == "https"
231
235
  http.open_timeout = DEFAULT_OPEN_TIMEOUT
232
236
  http.read_timeout = DEFAULT_READ_TIMEOUT
data/lib/hastci/cli.rb CHANGED
@@ -86,12 +86,15 @@ module HastCI
86
86
  private_class_method :configure_logging
87
87
 
88
88
  # :nocov:
89
- def self.setup_interrupt_handler(session, err, &on_interrupt)
89
+ def self.setup_interrupt_handler(session, err, signal_enqueuer: nil, &on_interrupt)
90
90
  signals = Queue.new
91
91
  signal_count = 0
92
+ enqueue_signal = signal_enqueuer || lambda do |queue, signal|
93
+ Thread.new { queue << signal }
94
+ end
92
95
 
93
- trap("INT") { signals << "SIGINT" }
94
- trap("TERM") { signals << "SIGTERM" }
96
+ trap("INT") { enqueue_signal.call(signals, "SIGINT") }
97
+ trap("TERM") { enqueue_signal.call(signals, "SIGTERM") }
95
98
 
96
99
  watcher = Thread.new do
97
100
  loop do
data/lib/hastci/config.rb CHANGED
@@ -5,7 +5,7 @@ require "securerandom"
5
5
  module HastCI
6
6
  class Config
7
7
  DEFAULT_API_BASE_URL = "https://hastci.com"
8
- DEFAULT_CLAIM_BATCH_SIZE = 10
8
+ DEFAULT_CLAIM_BATCH_SIZE = 3
9
9
  DEFAULT_HEARTBEAT_INTERVAL = 15
10
10
  DEFAULT_SEEDING_TIMEOUT = 300
11
11
  DEFAULT_LOG_LEVEL = "INFO"
@@ -3,8 +3,8 @@
3
3
  module HastCI
4
4
  class Session
5
5
  DEFAULT_POLL_INTERVAL = 0.5
6
- DEFAULT_BUFFER_MIN_SIZE = 3
7
- DEFAULT_BUFFER_MAX_SIZE = 10
6
+ DEFAULT_BUFFER_MIN_SIZE = 1
7
+ DEFAULT_BUFFER_MAX_SIZE = 3
8
8
  DEFAULT_SEEDING_POLL_INTERVAL = 1.0
9
9
 
10
10
  STOP_REASONS = %i[user_interrupt server_cancelled].freeze
@@ -54,20 +54,24 @@ module HastCI
54
54
  end
55
55
 
56
56
  def next_task
57
- error = @error_collector.first_error
58
- raise error if error
59
-
60
- task = @queue.pop
61
-
62
- if task.nil?
57
+ loop do
63
58
  error = @error_collector.first_error
64
59
  raise error if error
65
60
 
66
- return nil
67
- end
61
+ return nil if queue_closed_and_empty?
62
+
63
+ begin
64
+ task = @queue.pop(true)
65
+ rescue ThreadError
66
+ @sleeper.call(@poll_interval)
67
+ next
68
+ end
69
+
70
+ return nil if task.nil?
68
71
 
69
- signal_prefetch_if_needed
70
- task
72
+ signal_prefetch_if_needed
73
+ return task
74
+ end
71
75
  end
72
76
 
73
77
  def size
@@ -84,6 +88,10 @@ module HastCI
84
88
 
85
89
  private
86
90
 
91
+ def queue_closed_and_empty?
92
+ @queue.respond_to?(:closed?) && @queue.closed? && @queue.empty?
93
+ end
94
+
87
95
  def signal_prefetch_if_needed
88
96
  @mutex.synchronize do
89
97
  @prefetch_condition.signal if @queue.size < @min_size
@@ -117,9 +125,7 @@ module HastCI
117
125
 
118
126
  def wait_for_prefetch_signal
119
127
  @mutex.synchronize do
120
- while @running && !@drained && @queue.size >= @min_size
121
- @prefetch_condition.wait(@mutex, @poll_interval)
122
- end
128
+ @prefetch_condition.wait(@mutex, @poll_interval) while @running && !@drained && @queue.size >= @min_size
123
129
  end
124
130
  end
125
131
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  # :nocov:
4
4
  module HastCI
5
- VERSION = "0.1.2"
5
+ VERSION = "0.1.3"
6
6
  end
7
7
  # :nocov:
@@ -373,16 +373,69 @@
373
373
  "body": {
374
374
  "status": "passed",
375
375
  "duration_s": 1.5,
376
- "logs": {
377
- "summary": "1 example, 0 failures",
378
- "failures": [
376
+ "logs": [
379
377
  ]
378
+ },
379
+ "matchingRules": {
380
+ "$.path": {
381
+ "match": "regex",
382
+ "regex": "^\\/api\\/v1\\/tasks\\/\\d+\\/acknowledgment$"
380
383
  }
384
+ }
385
+ },
386
+ "response": {
387
+ "status": 200,
388
+ "headers": {
389
+ "Content-Type": "application/json"
390
+ },
391
+ "body": {
392
+ "ok": true
393
+ }
394
+ }
395
+ },
396
+ {
397
+ "description": "a request to ack a task with failures",
398
+ "providerState": "a task exists",
399
+ "request": {
400
+ "method": "post",
401
+ "path": "/api/v1/tasks/101/acknowledgment",
402
+ "headers": {
403
+ "Authorization": "Bearer test-api-key",
404
+ "Content-Type": "application/json"
405
+ },
406
+ "body": {
407
+ "status": "failed",
408
+ "duration_s": 2.0,
409
+ "logs": [
410
+ {
411
+ "file": "spec/models/user_spec.rb",
412
+ "line": 123,
413
+ "message": "Expected 1, got 2",
414
+ "backtrace": [
415
+ "spec/models/user_spec.rb:123:in `block'"
416
+ ]
417
+ }
418
+ ]
381
419
  },
382
420
  "matchingRules": {
383
421
  "$.path": {
384
422
  "match": "regex",
385
423
  "regex": "^\\/api\\/v1\\/tasks\\/\\d+\\/acknowledgment$"
424
+ },
425
+ "$.body.logs[0].file": {
426
+ "match": "type"
427
+ },
428
+ "$.body.logs[0].line": {
429
+ "match": "type"
430
+ },
431
+ "$.body.logs[0].message": {
432
+ "match": "type"
433
+ },
434
+ "$.body.logs[0].backtrace": {
435
+ "min": 1
436
+ },
437
+ "$.body.logs[0].backtrace[*].*": {
438
+ "match": "type"
386
439
  }
387
440
  }
388
441
  },
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hastci
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.2
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wojciech Wrona