ci_runner 0.2.0 → 0.4.0

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: fb83fde059747332cee33b4a0d313d2eaefb735ec3fe0e291141e8a18a535fa3
4
- data.tar.gz: 6dd4960bce217bbebba6a22b6e1863d0baaf7190c5835c1fc63de9d0cc86e94e
3
+ metadata.gz: 6573071a75fdc013ce2cb451567a5610d4928d8e10e336bba6296b1b046f1b82
4
+ data.tar.gz: b171257681c40b76b71c5113c243bdc9ee3992e2522b3128e980527eaab151bf
5
5
  SHA512:
6
- metadata.gz: f1e747da3d2101445f77645cc9f4d37f1f36b53702a85b735aecac605576b0d060037b56a54fcd3269c65a4313ebc3a3b00cab05d4acfbfd0785f3138911d51e
7
- data.tar.gz: 65a90464a386601f2bd6caaaa61ec6ea6188bd65688ddf9e32db0ee7006aff914bc3d3104271d5a4607f0252a1936514ee301b16bb3a708e1d32b7a12bc75c9d
6
+ metadata.gz: 40a798ad29846ca92722b56ef4f1bae2a1f76358de371ebf95fec1053b135882cbbb494430d77cc720ed3d60795413b994fc7288261e1c4d2bc981b0a003b45f
7
+ data.tar.gz: c1cde1a84e5c4cdc87b4763a85388373b187a43518f72330a3a1c7855f51ca33f358b1831977d708105731ebd61c75c25184f7cfb4ec9abcb7c0b32458e247d1
@@ -53,8 +53,10 @@ module CIRunner
53
53
  end
54
54
 
55
55
  # @return [Boolean]
56
+ #
57
+ # @see https://docs.github.com/en/rest/commits/statuses#get-the-combined-status-for-a-specific-reference
56
58
  def failed?
57
- @status == "failure"
59
+ ["error", "failure"].include?(status)
58
60
  end
59
61
  end
60
62
  end
@@ -0,0 +1,88 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require "uri"
5
+
6
+ module CIRunner
7
+ module Check
8
+ # Check class used when a project is configured to run its CI using Buildkite.
9
+ class Buildkite < Base
10
+ include ConcurrentDownload
11
+
12
+ attr_reader :url # :private:
13
+
14
+ # @param args (See Base#initialize)
15
+ # @param url [String] The html URL pointing to the Buildkite build.
16
+ def initialize(*args, url)
17
+ super(*args)
18
+
19
+ @url = url
20
+ end
21
+
22
+ # Used to tell the user which CI provider we are downloading the log output from.
23
+ #
24
+ # @return [String]
25
+ def provider
26
+ "Buildkite"
27
+ end
28
+
29
+ # Download the CI logs for this Buildkite build.
30
+ #
31
+ # The Buildkite API scopes tokens per organizations (token generated for org A can't access
32
+ # resource on org B, even for public resources). This means that for opensource projects using
33
+ # Buildkite, users that are not members of the buildkite org normally can't use CI Runner.
34
+ #
35
+ # To bypass this problem, for builds that are public, CI Runner uses a different API.
36
+ # For private build, CI runner will check if the user had stored a Buildkite token in its config.
37
+ #
38
+ # @return [Tempfile]
39
+ def download_log
40
+ uri = URI(url)
41
+ _, org, pipeline, _, build = uri.path.split("/")
42
+ @client = Client::Buildkite.new
43
+
44
+ unless @client.public_build?(org, pipeline, build)
45
+ token = retrieve_token_from_config(org, url)
46
+ @client = Client::AuthenticatedBuildkite.new(token)
47
+ end
48
+
49
+ @client.job_logs(org, pipeline, build).each do |log_url|
50
+ @queue << log_url
51
+ end
52
+
53
+ process_queue
54
+ end
55
+
56
+ private
57
+
58
+ # @param url [String]
59
+ #
60
+ # @return [void]
61
+ def process(url)
62
+ @client.reset!
63
+ response = @client.download_log(url)
64
+
65
+ @tempfile.write(response.read)
66
+ end
67
+
68
+ # Retrieve a Buildkite token from the user confg.
69
+ #
70
+ # @param organization [String] The organization that owns this buildkite build.
71
+ # @param url [String] The FQDN pointing to the buildkite build.
72
+ #
73
+ # @return [String] The token
74
+ #
75
+ # @raise [Error] If no token for that organization exists in the config.
76
+ def retrieve_token_from_config(organization, url)
77
+ token = Configuration::User.instance.buildkite_token(organization.downcase)
78
+
79
+ token || raise(Error, <<~EOM)
80
+ Can't get the log output from the Buildkite build #{url} because it requires authentication.
81
+
82
+ Please store a Buildkite token scoped to the organization #{organization} and retry.
83
+ See {{command:ci_runner help buildkite_token}}
84
+ EOM
85
+ end
86
+ end
87
+ end
88
+ end
@@ -4,7 +4,6 @@ require_relative "base"
4
4
  require "uri"
5
5
  require "open-uri"
6
6
  require "json"
7
- require "tempfile"
8
7
 
9
8
  module CIRunner
10
9
  module Check
@@ -54,6 +53,8 @@ module CIRunner
54
53
 
55
54
  # Check class used when a project is configured to run its CI using CircleCI.
56
55
  class CircleCI < Base
56
+ include ConcurrentDownload
57
+
57
58
  attr_reader :url # :private:
58
59
 
59
60
  # @param args (See Base#initialize)
@@ -62,8 +63,6 @@ module CIRunner
62
63
  super(*args)
63
64
 
64
65
  @url = url
65
- @queue = Queue.new
66
- @tempfile = Tempfile.new
67
66
  end
68
67
 
69
68
  # Used to tell the user which CI provider we are downloading the log output from.
@@ -102,37 +101,10 @@ module CIRunner
102
101
  end
103
102
 
104
103
  process_queue
105
-
106
- @tempfile.tap(&:flush)
107
- end
108
-
109
- # @return [Boolean]
110
- #
111
- # @see https://docs.github.com/en/rest/commits/statuses#get-the-combined-status-for-a-specific-reference
112
- def failed?
113
- ["error", "failure"].include?(status)
114
104
  end
115
105
 
116
106
  private
117
107
 
118
- # Implement a queuing system in order to download log files in parallel.
119
- #
120
- # @return [void]
121
- def process_queue
122
- max_threads = 6
123
- threads = []
124
-
125
- max_threads.times do
126
- threads << Thread.new do
127
- while (element = dequeue)
128
- process(element)
129
- end
130
- end
131
- end
132
-
133
- threads.each(&:join)
134
- end
135
-
136
108
  # @param step [Step]
137
109
  #
138
110
  # @return [void]
@@ -144,15 +116,6 @@ module CIRunner
144
116
  @tempfile.write(log_output)
145
117
  end
146
118
 
147
- # Dequeue a CircleCI Step from the queue.
148
- #
149
- # @return [Step, nil]
150
- def dequeue
151
- @queue.pop(true)
152
- rescue ThreadError
153
- nil
154
- end
155
-
156
119
  # The URL on the commit status will look something like: https://circleci.com/gh/owner/repo/1234?query_string.
157
120
  # We want the `1234` which is the builder number.
158
121
  #
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "tempfile"
4
+
5
+ module CIRunner
6
+ module Check
7
+ # Module used to dowload multiple logfiles in parallel.
8
+ #
9
+ # Some CI providers doesn't have an API to download a single log file for the whole
10
+ # build, and instead one log file is produced per step. CI Runner needs to download
11
+ # the logfile of all steps in the build in order to rerun all test that failed.
12
+ module ConcurrentDownload
13
+ def initialize(...)
14
+ @queue = Queue.new
15
+ @tempfile = Tempfile.new
16
+
17
+ super(...)
18
+ end
19
+
20
+ private
21
+
22
+ # Implement a queuing system in order to download log files in parallel.
23
+ #
24
+ # @return [void]
25
+ def process_queue
26
+ max_threads = 6
27
+ threads = []
28
+
29
+ max_threads.times do
30
+ threads << Thread.new do
31
+ while (element = dequeue)
32
+ process(element)
33
+ end
34
+ end
35
+ end
36
+
37
+ threads.each(&:join)
38
+
39
+ @tempfile.tap(&:flush)
40
+ end
41
+
42
+ # Process item in the queue.
43
+ def process
44
+ raise(NotImplementedError)
45
+ end
46
+
47
+ # Dequeue a CircleCI Step from the queue.
48
+ #
49
+ # @return [Step, nil]
50
+ def dequeue
51
+ @queue.pop(true)
52
+ rescue ThreadError
53
+ nil
54
+ end
55
+ end
56
+ end
57
+ end
data/lib/ci_runner/cli.rb CHANGED
@@ -35,6 +35,7 @@ module CIRunner
35
35
  def rerun
36
36
  ::CLI::UI::StdoutRouter.enable
37
37
 
38
+ check_for_new_version
38
39
  runner = nil
39
40
 
40
41
  ::CLI::UI.frame("Preparing CI Runner") do
@@ -117,8 +118,56 @@ module CIRunner
117
118
  end
118
119
  end
119
120
 
121
+ desc "buildkite_token TOKEN ORGANIZATION", "Save a Buildkite token in your config."
122
+ long_desc <<~EOM
123
+ Save a personal access Buildkite token in the ~/.ci_runner/config.yml file.
124
+ Storing a Buildkite token is required to retrieve log from private Buildkite builds.
125
+
126
+ The ORGANIZATION, should be the name of the organization the token has access to.
127
+
128
+ You can get a token from Buildkite by following this link: https://buildkite.com/user/api-access-tokens/new?description=CI%20Runner&scopes[]=read_builds&scopes[]=read_build_logs
129
+ EOM
130
+ def buildkite_token(token, organization)
131
+ ::CLI::UI::StdoutRouter.enable
132
+
133
+ required_scopes = ["read_builds", "read_build_logs"]
134
+ token_scopes = Client::AuthenticatedBuildkite.new(token).access_token["scopes"]
135
+ missing_scopes = required_scopes - token_scopes
136
+
137
+ if missing_scopes.empty?
138
+ Configuration::User.instance.save_buildkite_token(token, organization)
139
+
140
+ ::CLI::UI.puts(<<~EOM)
141
+ {{success:Your token is valid!}}
142
+
143
+ {{info:The token has been saved in this file: #{Configuration::User.instance.config_file}}}
144
+ EOM
145
+ else
146
+ ::CLI::UI.puts("{{red:\nYour token is missing required scope(s): #{missing_scopes.join(",")}")
147
+ end
148
+ rescue Client::Error => e
149
+ ::CLI::UI.puts("{{red:\nYour token doesn't seem to be valid. The response from Buildkite was: #{e.message}}}")
150
+
151
+ exit(false)
152
+ end
153
+
120
154
  private
121
155
 
156
+ # Inform the user of a possible new CI Runner version.
157
+ #
158
+ # @return [void]
159
+ def check_for_new_version
160
+ version_verifier = VersionVerifier.new
161
+ return unless version_verifier.new_ci_runner_version?
162
+
163
+ ::CLI::UI.puts(<<~EOM)
164
+ {{info:A newer version of CI Runner is available (#{version_verifier.upstream_version}).}}
165
+ {{info:You can update CI Runner by running}} {{command:gem update ci_runner}}
166
+ EOM
167
+ rescue StandardError
168
+ nil
169
+ end
170
+
122
171
  # Retrieve all the GitHub CI checks for a given commit. Will be used to interactively prompt
123
172
  # the user which one to rerun.
124
173
  #
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require "stringio"
5
+
6
+ module CIRunner
7
+ module Client
8
+ # Client used to retrieve private Resources on buildkite.
9
+ #
10
+ # For public resources, the API can be used but only a limited number of users will be
11
+ # be able to access it as it requires a token scoped for the organization (most users
12
+ # working on opensource project aren't member of the organization they contribute to).
13
+ #
14
+ # @see https://forum.buildkite.community/t/api-access-to-public-builds/1425/2
15
+ # @see Client::Buildkite
16
+ #
17
+ class AuthenticatedBuildkite < Base
18
+ API_ENDPOINT = "api.buildkite.com"
19
+
20
+ # Retrieve URLs to download job logs for all steps.
21
+ #
22
+ # @param org [String] The organizatio name.
23
+ # @param pipeline [String] The pipeline name.
24
+ # @param number [Integer] The build number.
25
+ #
26
+ # @return [Array<String>] An array of URLs
27
+ #
28
+ # @see https://buildkite.com/docs/apis/rest-api/builds#get-a-build
29
+ def job_logs(org, pipeline, number)
30
+ build = get("/v2/organizations/#{org}/pipelines/#{pipeline}/builds/#{number}")
31
+
32
+ build["jobs"].map do |job|
33
+ job["raw_log_url"]
34
+ end
35
+ end
36
+
37
+ # @param url [String] A URL pointing to a log output resource.
38
+ #
39
+ # @return [StringIO]
40
+ #
41
+ # @see https://buildkite.com/docs/apis/rest-api/jobs#get-a-jobs-log-output
42
+ def download_log(url)
43
+ StringIO.new(get(url))
44
+ end
45
+
46
+ # Get information about an access token. Used to check if the token has the correct scopes.
47
+ #
48
+ # @see https://buildkite.com/docs/apis/rest-api/access-token
49
+ #
50
+ # @return [Hash] See Buildkite doc
51
+ def access_token
52
+ get("/v2/access-token")
53
+ end
54
+
55
+ private
56
+
57
+ # Add authentication before making the request.
58
+ #
59
+ # @param request [Net::HTTPRequest] A subclass of Net::HTTPRequest.
60
+ #
61
+ # @return [void]
62
+ def authentication(request)
63
+ request["Authorization"] = "Bearer #{@access_token}"
64
+ end
65
+ end
66
+ end
67
+ end
@@ -24,6 +24,14 @@ module CIRunner
24
24
  @client = client
25
25
  end
26
26
 
27
+ # Set a new Client object.
28
+ # NET::HTTP is not threadsafe so each time we need to make requests concurrently we need to use a new client.
29
+ #
30
+ # @return [void]
31
+ def reset!
32
+ @client = self.class.default_client
33
+ end
34
+
27
35
  private
28
36
 
29
37
  # Add authentication before making the request.
@@ -32,7 +40,6 @@ module CIRunner
32
40
  #
33
41
  # @return [void]
34
42
  def authentication(request)
35
- raise(NotImplementedError, "Subclass responsability")
36
43
  end
37
44
 
38
45
  # Perform an authenticated GET request.
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative "base"
4
+ require "open-uri"
5
+
6
+ module CIRunner
7
+ module Client
8
+ # Client used for public Buildkite resources.
9
+ # Allow any users to download log output for builds that are in organizations they
10
+ # are not a member of.
11
+ #
12
+ # This client doesn't use the official buildkite API. The data returned are not exactly the same.
13
+ class Buildkite < Base
14
+ API_ENDPOINT = "buildkite.com"
15
+
16
+ # Check if the build is public and can be accessed without authentication.
17
+ #
18
+ # @param org [String] The organizatio name.
19
+ # @param pipeline [String] The pipeline name.
20
+ # @param number [Integer] The build number.
21
+ #
22
+ # @return [Boolean]
23
+ def public_build?(org, pipeline, build_number)
24
+ job_logs(org, pipeline, build_number)
25
+
26
+ true
27
+ rescue Error => e
28
+ return false if e.error_code == 403
29
+
30
+ raise(e)
31
+ end
32
+
33
+ # Retrieve URL paths to download job logs for all steps.
34
+ #
35
+ # @param org [String] The organizatio name.
36
+ # @param pipeline [String] The pipeline name.
37
+ # @param number [Integer] The build number.
38
+ #
39
+ # @return [Array<String>] An array of URL paths
40
+ def job_logs(org, pipeline, build_number)
41
+ @build ||= get("/#{org}/#{pipeline}/builds/#{build_number}")
42
+
43
+ @build["jobs"].map do |job|
44
+ job["base_path"] + "/raw_log"
45
+ end
46
+ end
47
+
48
+ # Download raw log output for a job.
49
+ #
50
+ # @param path [String] A URL path
51
+ #
52
+ # @return [Tempfile, IO] Depending on the size of the response. Quirk of URI.open.
53
+ def download_log(path)
54
+ redirection_url = get(path)
55
+
56
+ URI.open(redirection_url)
57
+ end
58
+ end
59
+ end
60
+ end
@@ -22,6 +22,17 @@ module CIRunner
22
22
  get("/user")
23
23
  end
24
24
 
25
+ # Get the latest release of a repository.
26
+ #
27
+ # @param repository [String] The full repository name, including the owner (rails/rails)
28
+ #
29
+ # @return [Hash] See GitHub documentation.
30
+ #
31
+ # https://docs.github.com/en/rest/releases/releases#get-the-latest-release
32
+ def latest_release(repository)
33
+ get("/repos/#{repository}/releases/latest")
34
+ end
35
+
25
36
  # Makes an API request to get the CI checks for the +commit+.
26
37
  #
27
38
  # @param repository [String] The full repository name, including the owner (rails/rails)
@@ -68,6 +68,36 @@ module CIRunner
68
68
  save!(@yaml_config)
69
69
  end
70
70
 
71
+ # Retrieve the stored Buildkite access token of the user that has access to the +organization+.
72
+ #
73
+ # @return [String, nil] Depending if the user ran the `ci_runner buildkite TOKEN ORGANIZATION` command.
74
+ def buildkite_token(organization)
75
+ @yaml_config.dig("buildkite", "tokens", organization.downcase)
76
+ end
77
+
78
+ # Write the Buildkite token to the user configuration file.
79
+ #
80
+ # @param token [String] A valid Buildkite access token.
81
+ # @param organization [String] The name of the organization the token has access to.
82
+ #
83
+ # @return [void]
84
+ def save_buildkite_token(token, organization)
85
+ existing_tokens = @yaml_config.dig("buildkite", "tokens") || {}
86
+ existing_tokens[organization.downcase] = token
87
+
88
+ @yaml_config["buildkite"] = { "tokens" => existing_tokens }
89
+
90
+ save!(@yaml_config)
91
+ end
92
+
93
+ # @return [Pathname] The path of the CI Runner directory configuration.
94
+ #
95
+ # @example
96
+ # puts config_directory # ~/.ci_runner
97
+ def config_directory
98
+ config_file.dirname
99
+ end
100
+
71
101
  # @return [Pathname] The path of the configuration file.
72
102
  #
73
103
  # @example
@@ -74,6 +74,7 @@ module CIRunner
74
74
  t.libs << "#{rake_load_path}"
75
75
  t.libs << "#{minitest_plugin_path}"
76
76
  t.test_files = #{failures.map(&:path)}
77
+ t.ruby_opts = ["-W0"] if ENV["NO_WARNING"]
77
78
  end
78
79
 
79
80
  Rake::Task[:__ci_runner_test].invoke
@@ -89,7 +90,7 @@ module CIRunner
89
90
  env["RUBY"] = ruby_path.to_s if ruby_path&.exist?
90
91
  env["BUNDLE_GEMFILE"] = gemfile_path.to_s if gemfile_path&.exist?
91
92
 
92
- execute_within_frame(env, "bundle exec ruby -r'rake/testtask' #{rakefile_path}")
93
+ execute_within_frame(env, "bundle exec ruby -I'#{rake_load_path}' -r'rake/testtask' #{rakefile_path}")
93
94
 
94
95
  DRb.stop_service
95
96
  end
@@ -56,6 +56,9 @@ module CIRunner
56
56
 
57
57
  regex = %r{.*/?(test/.*?)\Z}
58
58
  unless path.to_s.match?(regex)
59
+ # TODO(on: '2022-09-17', to: "edouard-chin") Revisit this as it's too brittle.
60
+ # If a test file doesn't live the in the `test/` root folder, this will raise an error.
61
+ # I should instead warn the user and move on.
59
62
  raise "Can't create a relative path."
60
63
  end
61
64
 
@@ -129,6 +129,8 @@ module CIRunner
129
129
  case uri.host
130
130
  when "circleci.com"
131
131
  Check::CircleCI.new(repository, commit, *commit_status.values_at("context", "state", "target_url"))
132
+ when "buildkite.com"
133
+ Check::Buildkite.new(repository, commit, *commit_status.values_at("context", "state", "target_url"))
132
134
  else
133
135
  Check::Unsupported.new(repository, commit, *commit_status.values_at("context", "state"))
134
136
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module CIRunner
4
- VERSION = "0.2.0"
4
+ VERSION = "0.4.0"
5
5
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "fileutils"
4
+
5
+ module CIRunner
6
+ # Class used to check if a newer version of CI Runner has been released.
7
+ # This is used to inform the user to update its gem.
8
+ #
9
+ # The check only runs every week.
10
+ class VersionVerifier
11
+ SEVEN_DAYS = 86_400 * 7
12
+
13
+ # Check if the user is running the latest version of CI Runner.
14
+ #
15
+ # @return [Boolean]
16
+ def new_ci_runner_version?
17
+ return false unless check?
18
+
19
+ fetch_upstream_version
20
+ FileUtils.touch(last_checked)
21
+
22
+ upstream_version > Gem::Version.new(VERSION)
23
+ end
24
+
25
+ # Makes a request to GitHub to get the latest release on the Edouard-chin/ci_runner repository
26
+ #
27
+ # @return [Gem::Version] An instance of Gem::Version
28
+ def upstream_version
29
+ @upstream_version ||= begin
30
+ release = Client::Github.new(Configuration::User.instance.github_token).latest_release("Edouard-chin/ci_runner")
31
+
32
+ Gem::Version.new(release["tag_name"].sub(/\Av/, ""))
33
+ end
34
+ end
35
+ alias_method :fetch_upstream_version, :upstream_version
36
+
37
+ # Path of a file used to store when we last checked for a release.
38
+ #
39
+ # @return [Pathname]
40
+ def last_checked
41
+ Configuration::User.instance.config_directory.join("last-checked")
42
+ end
43
+
44
+ private
45
+
46
+ # @return [Boolean] Whether we checked for a release in the 7 days.
47
+ def check?
48
+ Time.now > (File.stat(last_checked).mtime + SEVEN_DAYS)
49
+ rescue Errno::ENOENT
50
+ true
51
+ end
52
+ end
53
+ end
data/lib/ci_runner.rb CHANGED
@@ -6,22 +6,27 @@ require_relative "ci_runner/version"
6
6
  module CIRunner
7
7
  Error = Class.new(StandardError)
8
8
 
9
- autoload :CLI, "ci_runner/cli"
10
- autoload :GitHelper, "ci_runner/git_helper"
11
- autoload :TestRunFinder, "ci_runner/test_run_finder"
12
- autoload :LogDownloader, "ci_runner/log_downloader"
13
- autoload :TestFailure, "ci_runner/test_failure"
9
+ autoload :CLI, "ci_runner/cli"
10
+ autoload :GitHelper, "ci_runner/git_helper"
11
+ autoload :TestRunFinder, "ci_runner/test_run_finder"
12
+ autoload :LogDownloader, "ci_runner/log_downloader"
13
+ autoload :TestFailure, "ci_runner/test_failure"
14
+ autoload :VersionVerifier, "ci_runner/version_verifier"
14
15
 
15
16
  module Check
16
- autoload :Github, "ci_runner/check/github"
17
- autoload :CircleCI, "ci_runner/check/circle_ci"
18
- autoload :Unsupported, "ci_runner/check/unsupported"
17
+ autoload :Buildkite, "ci_runner/check/buildkite"
18
+ autoload :Github, "ci_runner/check/github"
19
+ autoload :CircleCI, "ci_runner/check/circle_ci"
20
+ autoload :Unsupported, "ci_runner/check/unsupported"
21
+ autoload :ConcurrentDownload, "ci_runner/check/concurrent_download"
19
22
  end
20
23
 
21
24
  module Client
22
- autoload :Error, "ci_runner/client/error"
23
- autoload :Github, "ci_runner/client/github"
24
- autoload :CircleCI, "ci_runner/client/circle_ci"
25
+ autoload :Error, "ci_runner/client/error"
26
+ autoload :Github, "ci_runner/client/github"
27
+ autoload :CircleCI, "ci_runner/client/circle_ci"
28
+ autoload :Buildkite, "ci_runner/client/buildkite"
29
+ autoload :AuthenticatedBuildkite, "ci_runner/client/authenticated_buildkite"
25
30
  end
26
31
 
27
32
  module Configuration
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ci_runner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Edouard Chin
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-22 00:00:00.000000000 Z
11
+ date: 2024-01-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cli-ui
@@ -113,11 +113,15 @@ files:
113
113
  - exe/ci_runner
114
114
  - lib/ci_runner.rb
115
115
  - lib/ci_runner/check/base.rb
116
+ - lib/ci_runner/check/buildkite.rb
116
117
  - lib/ci_runner/check/circle_ci.rb
118
+ - lib/ci_runner/check/concurrent_download.rb
117
119
  - lib/ci_runner/check/github.rb
118
120
  - lib/ci_runner/check/unsupported.rb
119
121
  - lib/ci_runner/cli.rb
122
+ - lib/ci_runner/client/authenticated_buildkite.rb
120
123
  - lib/ci_runner/client/base.rb
124
+ - lib/ci_runner/client/buildkite.rb
121
125
  - lib/ci_runner/client/circle_ci.rb
122
126
  - lib/ci_runner/client/error.rb
123
127
  - lib/ci_runner/client/github.rb
@@ -131,6 +135,7 @@ files:
131
135
  - lib/ci_runner/test_failure.rb
132
136
  - lib/ci_runner/test_run_finder.rb
133
137
  - lib/ci_runner/version.rb
138
+ - lib/ci_runner/version_verifier.rb
134
139
  - lib/minitest/ci_runner_plugin.rb
135
140
  homepage: https://github.com/Edouard-chin/ci_runner
136
141
  licenses:
@@ -156,7 +161,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
156
161
  - !ruby/object:Gem::Version
157
162
  version: '0'
158
163
  requirements: []
159
- rubygems_version: 3.3.19
164
+ rubygems_version: 3.5.3
160
165
  signing_key:
161
166
  specification_version: 4
162
167
  summary: Re-run failing tests from CI on your local machine without copy/pasting.