buildkite-test_collector 1.1.1 → 1.2.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 96fb0d0c08ff10d420388b2438ae199c7fbf72878d1fa5631c68b27e70f11cac
4
- data.tar.gz: 78846d669900e535d1e03bd7494611dd124f2c1bae59471ad41b5b0d9f1efb1b
3
+ metadata.gz: 457b9dff2d6567d8be85f8a3e120500b04ef33aa93b9a1fa971c781cc8ff9471
4
+ data.tar.gz: 85a55ce20a129628d2379f73a62da0e29cef6cae0359987b986e23ce71a3ed86
5
5
  SHA512:
6
- metadata.gz: c7151f06cf10d7aeb296b9d8c9294f9cdab0b07fc01112176cdc28ad55f7b65d4aa51fcc21dfd179eb58bc6c69592583f58335dece7f3b46ac1e2ba7718da369
7
- data.tar.gz: cb1157c4a4cfaa719d852f2ac271bd09bbd25a461b4f6a9c002063d7461e3bb06e8107342cceb77dada1cda8090c3643aa3e2827aac7355fea90b51bbae4f7f0
6
+ metadata.gz: 6d3f6a44bcb2743e2389b1ae8fc15dfce3721aec0f161cbc147843c6759a00eb29ffa16f917665f571cb7f62ec81c059a08e67323629196fa03cc73e601155ed
7
+ data.tar.gz: 9131b6ced770ab95c5a98c399cc45d108aab5bdc74d9f8e4c7a7ea9bb63d9d07126f0b93e2f759b2fad4b0b76761679ccc7bc580298c2586fbdbf33e14c8fe0d
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # CHANGELOG
2
2
 
3
+ ## v1.2.3
4
+
5
+ - Add ability to specify execution prefix/suffix #140 - @JuanitoFatas
6
+
7
+ ## v1.1.3
8
+ - Use a private reference to JSON.parse to prevent it being mocked #149 - @ghcan
9
+
10
+ ## v1.1.2
11
+
12
+ - Remove branch reference prefix in Github Actions #136 - @gchan
13
+ - Make ruby collector work better for non-web app #128 - @JuanitoFatas
14
+ - Avoid linters complaining about double quotes #137 - @SocalNick
15
+ - Revert "Allow specifying run name prefix and suffix" #139 - @JuanitoFatas
16
+ - Update Code of Conduct contact email address #143 - @JuanitoFatas
17
+ - Suppress errors when connecting to Buildkite #145 - @swebb
18
+ - Add some design documentation to understand how the gem works #146 - @swebb
19
+ - Fix logging level from debug to error #147 - @gchan
20
+
3
21
  ## v1.1.1
4
22
 
5
23
  - Strip CR/LF from token input #127 - @gchan
data/CODE_OF_CONDUCT.md CHANGED
@@ -61,7 +61,7 @@ representative at an online or offline event.
61
61
 
62
62
  Instances of abusive, harassing, or otherwise unacceptable behavior may be
63
63
  reported to the community leaders responsible for enforcement at
64
- `support+analytics@buildkite.com`.
64
+ [coc@buildkite.com](mailto:coc@buildkite.com).
65
65
  All complaints will be reviewed and investigated promptly and fairly.
66
66
 
67
67
  All community leaders are obligated to respect the privacy and security of the
data/DESIGN.md ADDED
@@ -0,0 +1,19 @@
1
+ # Design
2
+
3
+ ## Threads
4
+
5
+ The Buildkite ruby collector uses websockets and ActionCable to send and
6
+ receive data with Buildkite. Execution information starts transmitting as soon
7
+ as possible, without waiting for the test suite to finish running.
8
+
9
+ This gem uses 3 ruby threads:
10
+
11
+ * main thread: acts as the producer. It collects span data from the
12
+ test suite and enqueues it into the send queue.
13
+ * write thread: acts as the consumer. Removes data from the send queue and
14
+ sends it to Buildkite.
15
+ * read thread: receives and processes messages from Buildkite.
16
+
17
+ ## Data
18
+
19
+ Trace data is stored in spans. See [Buildkite::TestCollector::Tracer](lib/buildkite/test_collector/tracer.rb) for more information.
data/Gemfile.lock CHANGED
@@ -1,23 +1,23 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- buildkite-test_collector (1.1.1)
4
+ buildkite-test_collector (1.2.3)
5
5
  activesupport (>= 5.2, < 8)
6
6
  websocket (~> 1.2)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activesupport (7.0.3)
11
+ activesupport (7.0.3.1)
12
12
  concurrent-ruby (~> 1.0, >= 1.0.2)
13
13
  i18n (>= 1.6, < 2)
14
14
  minitest (>= 5.1)
15
15
  tzinfo (~> 2.0)
16
16
  concurrent-ruby (1.1.10)
17
17
  diff-lcs (1.4.4)
18
- i18n (1.10.0)
18
+ i18n (1.12.0)
19
19
  concurrent-ruby (~> 1.0)
20
- minitest (5.16.1)
20
+ minitest (5.16.3)
21
21
  rake (13.0.6)
22
22
  rspec (3.10.0)
23
23
  rspec-core (~> 3.10.0)
@@ -32,7 +32,7 @@ GEM
32
32
  diff-lcs (>= 1.2.0, < 2.0)
33
33
  rspec-support (~> 3.10.0)
34
34
  rspec-support (3.10.3)
35
- tzinfo (2.0.4)
35
+ tzinfo (2.0.5)
36
36
  concurrent-ruby (~> 1.0)
37
37
  websocket (1.2.9)
38
38
 
data/README.md CHANGED
@@ -22,7 +22,7 @@ Or add this to your Gemfile’s test group:
22
22
 
23
23
  ```ruby
24
24
  group :test do
25
- gem "buildkite-test_collector"
25
+ gem 'buildkite-test_collector'
26
26
  end
27
27
  ```
28
28
 
@@ -34,7 +34,7 @@ Add the following code to your RSpec setup file:
34
34
 
35
35
  ```ruby
36
36
  # spec/spec_helper.rb
37
- require "buildkite/test_collector"
37
+ require 'buildkite/test_collector'
38
38
  Buildkite::TestCollector.configure(hook: :rspec)
39
39
  ```
40
40
 
@@ -50,7 +50,7 @@ Add the following code to your Minitest setup file:
50
50
 
51
51
  ```ruby
52
52
  # test/test_helper.rb
53
- require "buildkite/test_collector"
53
+ require 'buildkite/test_collector'
54
54
  Buildkite::TestCollector.configure(hook: :minitest)
55
55
  ```
56
56
 
@@ -94,6 +94,8 @@ bundle exec rspec
94
94
 
95
95
  Useful resources for developing collectors include the [Buildkite Test Analytics docs](https://buildkite.com/docs/test-analytics).
96
96
 
97
+ See [DESIGN.md](DESIGN.md) for an overview of the design of this gem.
98
+
97
99
  ## 👩‍💻 Contributing
98
100
 
99
101
  Bug reports and pull requests are welcome on GitHub at https://github.com/buildkite/test-collector-ruby
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "securerandom"
4
-
5
3
  class Buildkite::TestCollector::CI
6
4
  def self.env
7
5
  new.env
@@ -37,10 +35,10 @@ class Buildkite::TestCollector::CI
37
35
  "job_id" => ENV["BUILDKITE_ANALYTICS_JOB_ID"],
38
36
  "message" => ENV["BUILDKITE_ANALYTICS_MESSAGE"],
39
37
  "debug" => ENV["BUILDKITE_ANALYTICS_DEBUG_ENABLED"],
38
+ "execution_name_prefix" => ENV["BUILDKITE_ANALYTICS_EXECUTION_NAME_PREFIX"],
39
+ "execution_name_suffix" => ENV["BUILDKITE_ANALYTICS_EXECUTION_NAME_SUFFIX"],
40
40
  "version" => Buildkite::TestCollector::VERSION,
41
41
  "collector" => Buildkite::TestCollector::NAME,
42
- "run_name_prefix" => ENV["BUILDKITE_ANALYTICS_RUN_NAME_PREFIX"],
43
- "run_name_suffix" => ENV["BUILDKITE_ANALYTICS_RUN_NAME_SUFFIX"],
44
42
  }.compact
45
43
  end
46
44
 
@@ -69,7 +67,7 @@ class Buildkite::TestCollector::CI
69
67
  "CI" => "github_actions",
70
68
  "key" => "#{ENV["GITHUB_ACTION"]}-#{ENV["GITHUB_RUN_NUMBER"]}-#{ENV["GITHUB_RUN_ATTEMPT"]}",
71
69
  "url" => File.join("https://github.com", ENV["GITHUB_REPOSITORY"], "actions/runs", ENV["GITHUB_RUN_ID"]),
72
- "branch" => ENV["GITHUB_REF"],
70
+ "branch" => ENV["GITHUB_REF_NAME"],
73
71
  "commit_sha" => ENV["GITHUB_SHA"],
74
72
  "number" => ENV["GITHUB_RUN_NUMBER"],
75
73
  }
@@ -0,0 +1,4 @@
1
+ module Buildkite::TestCollector
2
+ class Error < StandardError; end
3
+ class TimeoutError < ::Timeout::Error; end
4
+ end
@@ -2,7 +2,6 @@
2
2
 
3
3
  require "minitest"
4
4
 
5
- require_relative "../uploader"
6
5
  require_relative "../minitest_plugin"
7
6
 
8
7
  Buildkite::TestCollector.uploader = Buildkite::TestCollector::Uploader
@@ -13,4 +12,4 @@ end
13
12
 
14
13
  Buildkite::TestCollector.enable_tracing!
15
14
 
16
- Buildkite::TestCollector::Uploader.configure
15
+ Buildkite::TestCollector.safe { Buildkite::TestCollector::Uploader.configure }
@@ -3,7 +3,6 @@
3
3
  require "rspec/core"
4
4
  require "rspec/expectations"
5
5
 
6
- require_relative "../uploader"
7
6
  require_relative "../rspec_plugin/reporter"
8
7
  require_relative "../rspec_plugin/trace"
9
8
 
@@ -13,7 +12,7 @@ RSpec.configure do |config|
13
12
  config.before(:suite) do
14
13
  config.add_formatter Buildkite::TestCollector::RSpecPlugin::Reporter
15
14
 
16
- Buildkite::TestCollector::Uploader.configure
15
+ Buildkite::TestCollector.safe { Buildkite::TestCollector::Uploader.configure }
17
16
  end
18
17
 
19
18
  config.around(:each) do |example|
@@ -1,8 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "logger"
4
- require "time"
5
-
6
3
  module Buildkite::TestCollector
7
4
  class Logger < ::Logger
8
5
  class Formatter < ::Logger::Formatter
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/hash/indifferent_access"
4
-
5
3
  module Buildkite::TestCollector::MinitestPlugin
6
4
  class Trace
7
5
  attr_accessor :example
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ # Minitest finds this file before setup code
4
+ require_relative "tracer"
5
+
3
6
  require_relative "minitest_plugin/reporter"
4
7
  require_relative "minitest_plugin/trace"
5
8
 
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "time"
4
-
5
3
  module Buildkite::TestCollector::RSpecPlugin
6
4
  class Reporter
7
5
  RSpec::Core::Formatters.register self, :example_passed, :example_failed, :example_pending, :dump_summary
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/hash/indifferent_access"
4
-
5
3
  module Buildkite::TestCollector::RSpecPlugin
6
4
  class Trace
7
5
  attr_accessor :example, :failure_reason, :failure_expanded
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "socket_connection"
4
-
5
3
  module Buildkite::TestCollector
6
4
  class Session
7
5
  # Picked 75 as the magic timeout number as it's longer than the TCP timeout of 60s 🤷‍♀️
@@ -9,15 +7,19 @@ module Buildkite::TestCollector
9
7
  MAX_RECONNECTION_ATTEMPTS = ENV.fetch("BUILDKITE_ANALYTICS_RECONNECTION_ATTEMPTS") { 3 }.to_i
10
8
  WAIT_BETWEEN_RECONNECTIONS = ENV.fetch("BUILDKITE_ANALYTICS_RECONNECTION_WAIT") { 5 }.to_i
11
9
 
10
+ # We keep a private reference so that mocking libraries won't break JSON
11
+ JSON_PARSE = JSON.method(:parse)
12
+ private_constant :JSON_PARSE
13
+
12
14
  class RejectedSubscription < StandardError; end
13
15
  class InitialConnectionFailure < StandardError; end
14
16
 
15
17
  DISCONNECTED_EXCEPTIONS = [
16
- SocketConnection::HandshakeError,
18
+ Buildkite::TestCollector::SocketConnection::HandshakeError,
19
+ Buildkite::TestCollector::TimeoutError,
20
+ Buildkite::TestCollector::SocketConnection::SocketError,
17
21
  RejectedSubscription,
18
- TimeoutError,
19
22
  InitialConnectionFailure,
20
- SocketConnection::SocketError
21
23
  ]
22
24
 
23
25
  def initialize(url, authorization_header, channel)
@@ -41,7 +43,7 @@ module Buildkite::TestCollector
41
43
  begin
42
44
  reconnection_count += 1
43
45
  connect
44
- rescue TimeoutError, InitialConnectionFailure => e
46
+ rescue Buildkite::TestCollector::TimeoutError, InitialConnectionFailure => e
45
47
  Buildkite::TestCollector.logger.warn("buildkite-test_collector could not establish an initial connection with Buildkite due to #{e}. Attempting retry #{reconnection_count} of #{MAX_RECONNECTION_ATTEMPTS}...")
46
48
  if reconnection_count > MAX_RECONNECTION_ATTEMPTS
47
49
  Buildkite::TestCollector.logger.error "buildkite-test_collector could not establish an initial connection with Buildkite due to #{e.message} after #{MAX_RECONNECTION_ATTEMPTS} attempts. You may be missing some data for this test suite, please contact support if this issue persists."
@@ -122,7 +124,7 @@ module Buildkite::TestCollector
122
124
  end
123
125
 
124
126
  def handle(_connection, data)
125
- data = JSON.parse(data)
127
+ data = JSON_PARSE.call(data)
126
128
  case data["type"]
127
129
  when "ping"
128
130
  # In absence of other message, the server sends us a ping every 3 seconds
@@ -1,9 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "socket"
4
- require "openssl"
5
- require "json"
6
-
7
3
  module Buildkite::TestCollector
8
4
  class SocketConnection
9
5
  class HandshakeError < StandardError; end
@@ -65,7 +61,7 @@ module Buildkite::TestCollector
65
61
 
66
62
  # Setting up a new thread that listens on the socket, and processes incoming
67
63
  # comms from the server
68
- @thread = Thread.new do
64
+ @read_thread = Thread.new do
69
65
  Buildkite::TestCollector.logger.debug("listening in on socket")
70
66
  frame = WebSocket::Frame::Incoming::Client.new
71
67
 
@@ -82,7 +78,7 @@ module Buildkite::TestCollector
82
78
  rescue EOFError => e
83
79
  Buildkite::TestCollector.logger.warn("#{e}")
84
80
  if @socket
85
- Buildkite::TestCollector.logger.warn("attempting disconnected flow")
81
+ Buildkite::TestCollector.logger.error("attempting disconnected flow")
86
82
  @session.disconnected(self)
87
83
  disconnect
88
84
  end
@@ -151,7 +147,7 @@ module Buildkite::TestCollector
151
147
  socket = @socket
152
148
  @socket = nil
153
149
  socket&.close
154
- @thread&.join unless @thread == Thread.current
150
+ @read_thread&.join unless @read_thread == Thread.current
155
151
  end
156
152
  end
157
153
  end
@@ -1,8 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "active_support/core_ext/hash/indifferent_access"
4
-
5
3
  module Buildkite::TestCollector
4
+ # Traces the execution of an application by creating and storing spans of information.
5
+ #
6
+ # This class contains two data structures:
7
+ #
8
+ # - A stack (called @stack) that traces the entering & leaving of each part of the application.
9
+ # - A tree made up of many Span nodes. Each Span is a node in the tree. Each
10
+ # span is also stored in the stack. The root of the tree is called @top and
11
+ # is stored at @stack[0].
12
+ #
13
+ # When the trace is complete the stack MUST contain a single node @top, which
14
+ # is the root of the tree (see #finalize). The tree is converted into a hash
15
+ # in #as_json which recursively calls #as_json on all of it's children.
6
16
  class Tracer
7
17
  # https://github.com/buildkite/test-collector-ruby/issues/131
8
18
  class MonotonicTime
@@ -1,20 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require "openssl"
4
- require "websocket"
5
-
6
- require_relative "tracer"
7
- require_relative "network"
8
- require_relative "object"
9
- require_relative "session"
10
- require_relative "ci"
11
- require_relative "http_client"
12
-
13
- require "active_support"
14
- require "active_support/notifications"
15
-
16
- require "securerandom"
17
-
18
3
  module Buildkite::TestCollector
19
4
  class Uploader
20
5
  def self.traces
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Buildkite
4
4
  module TestCollector
5
- VERSION = "1.1.1"
5
+ VERSION = "1.2.3"
6
6
  NAME = "buildkite-test_collector"
7
7
  end
8
8
  end
@@ -1,16 +1,39 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ module Buildkite
4
+ module TestCollector
5
+ end
6
+ end
7
+
8
+ require "json"
9
+ require "logger"
10
+ require "net/http"
11
+ require "openssl"
12
+ require "time"
3
13
  require "timeout"
4
14
  require "tmpdir"
15
+ require "securerandom"
16
+ require "socket"
17
+ require "websocket"
18
+
19
+ require "active_support/core_ext/object/blank"
20
+ require "active_support/core_ext/hash/indifferent_access"
21
+ require "active_support/notifications"
5
22
 
6
23
  require_relative "test_collector/version"
24
+ require_relative "test_collector/error"
7
25
  require_relative "test_collector/logger"
26
+ require_relative "test_collector/ci"
27
+ require_relative "test_collector/http_client"
28
+ require_relative "test_collector/uploader"
29
+ require_relative "test_collector/network"
30
+ require_relative "test_collector/object"
31
+ require_relative "test_collector/tracer"
32
+ require_relative "test_collector/socket_connection"
33
+ require_relative "test_collector/session"
8
34
 
9
35
  module Buildkite
10
36
  module TestCollector
11
- class Error < StandardError; end
12
- class TimeoutError < ::Timeout::Error; end
13
-
14
37
  DEFAULT_URL = "https://analytics-api.buildkite.com/v1/uploads"
15
38
 
16
39
  class << self
@@ -78,5 +101,12 @@ module Buildkite
78
101
  Buildkite::TestCollector::Uploader.tracer&.backfill(:sql, finish - start, **{ query: payload[:sql] })
79
102
  end
80
103
  end
104
+
105
+ def self.safe(&block)
106
+ block.call
107
+ rescue StandardError => e
108
+ logger.error("Buildkite::TestCollector received exception: #{e}")
109
+ logger.error("Backtrace:\n#{e.backtrace.join("\n")}")
110
+ end
81
111
  end
82
112
  end
@@ -1,3 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Minitest finds this file before setup code
4
+ require_relative "../buildkite/test_collector"
5
+ require_relative "../buildkite/test_collector/minitest_plugin/reporter"
6
+
1
7
  module Minitest
2
8
  def self.plugin_buildkite_collector_init(options)
3
9
  if defined?(Buildkite::TestCollector::MinitestPlugin) && Buildkite::TestCollector.respond_to?(:uploader)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: buildkite-test_collector
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.2.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Buildkite
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-06-30 00:00:00.000000000 Z
11
+ date: 2022-08-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
@@ -84,6 +84,7 @@ files:
84
84
  - CHANGELOG.md
85
85
  - CODEOWNERS
86
86
  - CODE_OF_CONDUCT.md
87
+ - DESIGN.md
87
88
  - Gemfile
88
89
  - Gemfile.lock
89
90
  - LICENSE.txt
@@ -95,6 +96,7 @@ files:
95
96
  - buildkite.yaml
96
97
  - lib/buildkite/test_collector.rb
97
98
  - lib/buildkite/test_collector/ci.rb
99
+ - lib/buildkite/test_collector/error.rb
98
100
  - lib/buildkite/test_collector/http_client.rb
99
101
  - lib/buildkite/test_collector/library_hooks/minitest.rb
100
102
  - lib/buildkite/test_collector/library_hooks/rspec.rb