rspec-mergify 0.1.0 → 0.1.2
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/README.md +2 -0
- data/lib/mergify/rspec/ci_insights.rb +2 -0
- data/lib/mergify/rspec/quarantine.rb +61 -16
- data/lib/mergify/rspec/resources/buildkite.rb +54 -0
- data/lib/mergify/rspec/utils.rb +5 -6
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 379b00755c80dfcba26213f7747fd42f2739c39f2cc450e36123e1703b9312f4
|
|
4
|
+
data.tar.gz: 979aaf645e9f2ad882dd00f900a5168be6f5c3ff041360e79698860e7be3790d
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: dc0c1dae123ed41a0ca6290ed79d4bcd82ec79989f8d8cf3e232e3e505592bd791d3387435d99721f5c42218839990e609d4d595ba4317e544e3b65255ed14c8
|
|
7
|
+
data.tar.gz: 1827d2eefe6a13d8efb9b6e10cc99da36e6e64b842cfee830cc872d687caabb72881b61cdffb496d74e6e8cf91ccfaf44f7bee866f31858fafc8998e23488016
|
data/README.md
CHANGED
|
@@ -35,6 +35,8 @@ The plugin activates automatically when running in CI (detected via the `CI` env
|
|
|
35
35
|
| `MERGIFY_TRACEPARENT` | W3C distributed trace context | — |
|
|
36
36
|
| `MERGIFY_TEST_JOB_NAME` | Mergify test job name | — |
|
|
37
37
|
|
|
38
|
+
For detailed documentation, see the [official guide](https://docs.mergify.com/ci-insights/test-frameworks/rspec/).
|
|
39
|
+
|
|
38
40
|
## Development
|
|
39
41
|
|
|
40
42
|
### Prerequisites
|
|
@@ -8,6 +8,7 @@ require_relative 'resources/ci'
|
|
|
8
8
|
require_relative 'resources/git'
|
|
9
9
|
require_relative 'resources/github_actions'
|
|
10
10
|
require_relative 'resources/jenkins'
|
|
11
|
+
require_relative 'resources/buildkite'
|
|
11
12
|
require_relative 'resources/mergify'
|
|
12
13
|
require_relative 'resources/rspec'
|
|
13
14
|
|
|
@@ -102,6 +103,7 @@ module Mergify
|
|
|
102
103
|
Resources::Git.detect,
|
|
103
104
|
Resources::GitHubActions.detect,
|
|
104
105
|
Resources::Jenkins.detect,
|
|
106
|
+
Resources::Buildkite.detect,
|
|
105
107
|
Resources::Mergify.detect,
|
|
106
108
|
Resources::RSpec.detect
|
|
107
109
|
]
|
|
@@ -54,11 +54,52 @@ module Mergify
|
|
|
54
54
|
|
|
55
55
|
private
|
|
56
56
|
|
|
57
|
-
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
|
58
57
|
def fetch_quarantined_tests(api_url, token, owner, repo, branch_name)
|
|
59
58
|
uri = URI("#{api_url}/v1/ci/#{owner}/repositories/#{repo}/quarantines")
|
|
60
|
-
uri.query = URI.encode_www_form(branch: branch_name)
|
|
59
|
+
uri.query = URI.encode_www_form(branch: branch_name, per_page: 100)
|
|
60
|
+
collected = walk_paginated_quarantines(uri, token)
|
|
61
|
+
@quarantined_tests = collected if collected
|
|
62
|
+
rescue Net::OpenTimeout, Net::ReadTimeout, Errno::ECONNREFUSED, SocketError => e
|
|
63
|
+
@init_error_msg = "Failed to connect to Mergify API: #{e.message}"
|
|
64
|
+
rescue JSON::ParserError => e
|
|
65
|
+
@init_error_msg = "Mergify API returned a malformed quarantine list: #{e.message}"
|
|
66
|
+
end
|
|
61
67
|
|
|
68
|
+
# Follows the RFC 5988 `next` link until exhausted. Returns the full list
|
|
69
|
+
# on success, or `nil` when the run was aborted (subscription missing or
|
|
70
|
+
# an error already recorded in @init_error_msg).
|
|
71
|
+
# rubocop:disable Metrics/MethodLength,Metrics/AbcSize
|
|
72
|
+
def walk_paginated_quarantines(uri, token)
|
|
73
|
+
collected = []
|
|
74
|
+
# Guard against a server returning a `next` link that loops back to a
|
|
75
|
+
# URL we have already fetched.
|
|
76
|
+
seen = Set.new
|
|
77
|
+
while uri
|
|
78
|
+
if seen.include?(uri.to_s)
|
|
79
|
+
@init_error_msg = 'Mergify API returned a cyclic `next` link, aborting.'
|
|
80
|
+
return nil
|
|
81
|
+
end
|
|
82
|
+
seen.add(uri.to_s)
|
|
83
|
+
|
|
84
|
+
response = perform_request(uri, token)
|
|
85
|
+
case response.code.to_i
|
|
86
|
+
when 200
|
|
87
|
+
data = JSON.parse(response.body)
|
|
88
|
+
collected.concat(data.fetch('quarantined_tests', []).map { |t| t['test_name'] })
|
|
89
|
+
next_url = parse_next_link(response['Link'])
|
|
90
|
+
uri = next_url ? URI(next_url) : nil
|
|
91
|
+
when 402
|
|
92
|
+
return nil
|
|
93
|
+
else
|
|
94
|
+
@init_error_msg = "Mergify API returned HTTP #{response.code}"
|
|
95
|
+
return nil
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
collected
|
|
99
|
+
end
|
|
100
|
+
# rubocop:enable Metrics/MethodLength,Metrics/AbcSize
|
|
101
|
+
|
|
102
|
+
def perform_request(uri, token)
|
|
62
103
|
http = Net::HTTP.new(uri.host, uri.port)
|
|
63
104
|
http.use_ssl = uri.scheme == 'https'
|
|
64
105
|
http.open_timeout = 10
|
|
@@ -66,23 +107,27 @@ module Mergify
|
|
|
66
107
|
|
|
67
108
|
request = Net::HTTP::Get.new(uri)
|
|
68
109
|
request['Authorization'] = "Bearer #{token}"
|
|
110
|
+
http.request(request)
|
|
111
|
+
end
|
|
69
112
|
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
113
|
+
# Parses RFC 8288 Link headers tolerantly: accepts both quoted
|
|
114
|
+
# (`rel="next"`) and token (`rel=next`) forms, and matches when `next`
|
|
115
|
+
# is one of several space-separated rel-types (`rel="next prev"`).
|
|
116
|
+
def parse_next_link(link_header)
|
|
117
|
+
return nil if link_header.nil? || link_header.empty?
|
|
118
|
+
|
|
119
|
+
link_header.split(',').each do |part|
|
|
120
|
+
match = part.strip.match(/\A<([^>]+)>\s*;\s*(.+)\z/)
|
|
121
|
+
next unless match && next_rel?(match[2])
|
|
122
|
+
|
|
123
|
+
return match[1]
|
|
124
|
+
end
|
|
125
|
+
nil
|
|
74
126
|
end
|
|
75
|
-
# rubocop:enable Metrics/MethodLength,Metrics/AbcSize
|
|
76
127
|
|
|
77
|
-
def
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
data = JSON.parse(response.body)
|
|
81
|
-
@quarantined_tests = data.fetch('quarantined_tests', []).map { |t| t['test_name'] }
|
|
82
|
-
when 402
|
|
83
|
-
# No subscription — silently skip
|
|
84
|
-
else
|
|
85
|
-
@init_error_msg = "Mergify API returned HTTP #{response.code}"
|
|
128
|
+
def next_rel?(params)
|
|
129
|
+
params.scan(/rel\s*=\s*(?:"([^"]+)"|([^\s;,]+))/i).any? do |quoted, token|
|
|
130
|
+
(quoted || token).split.include?('next')
|
|
86
131
|
end
|
|
87
132
|
end
|
|
88
133
|
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'opentelemetry-sdk'
|
|
4
|
+
require_relative '../utils'
|
|
5
|
+
require_relative 'git'
|
|
6
|
+
|
|
7
|
+
module Mergify
|
|
8
|
+
module RSpec
|
|
9
|
+
module Resources
|
|
10
|
+
# Detects OpenTelemetry Resource attributes for Buildkite.
|
|
11
|
+
module Buildkite
|
|
12
|
+
module_function
|
|
13
|
+
|
|
14
|
+
BUILDKITE_MAPPING = {
|
|
15
|
+
'cicd.pipeline.name' => [:to_s, 'BUILDKITE_PIPELINE_SLUG'],
|
|
16
|
+
'cicd.pipeline.task.name' => [
|
|
17
|
+
:to_s,
|
|
18
|
+
lambda {
|
|
19
|
+
label = ENV.fetch('BUILDKITE_LABEL', nil)
|
|
20
|
+
label && !label.empty? ? label : ENV.fetch('BUILDKITE_STEP_KEY', nil)
|
|
21
|
+
}
|
|
22
|
+
],
|
|
23
|
+
'cicd.pipeline.run.id' => [:to_s, 'BUILDKITE_BUILD_ID'],
|
|
24
|
+
'cicd.pipeline.run.url' => [:to_s, 'BUILDKITE_BUILD_URL'],
|
|
25
|
+
'cicd.pipeline.run.attempt' => [
|
|
26
|
+
:to_i,
|
|
27
|
+
-> { ENV.fetch('BUILDKITE_RETRY_COUNT', '0').to_i + 1 }
|
|
28
|
+
],
|
|
29
|
+
'cicd.pipeline.runner.name' => [:to_s, 'BUILDKITE_AGENT_NAME'],
|
|
30
|
+
'vcs.ref.head.name' => [:to_s, 'BUILDKITE_BRANCH'],
|
|
31
|
+
'vcs.ref.base.name' => [:to_s, 'BUILDKITE_PULL_REQUEST_BASE_BRANCH'],
|
|
32
|
+
'vcs.ref.head.revision' => [:to_s, 'BUILDKITE_COMMIT'],
|
|
33
|
+
'vcs.repository.url.full' => [:to_s, 'BUILDKITE_REPO'],
|
|
34
|
+
'vcs.repository.name' => [
|
|
35
|
+
:to_s,
|
|
36
|
+
lambda {
|
|
37
|
+
url = ENV.fetch('BUILDKITE_REPO', nil)
|
|
38
|
+
Utils.repository_name_from_url(url) if url
|
|
39
|
+
}
|
|
40
|
+
]
|
|
41
|
+
}.freeze
|
|
42
|
+
|
|
43
|
+
def detect
|
|
44
|
+
return OpenTelemetry::SDK::Resources::Resource.create({}) if Utils.ci_provider != :buildkite
|
|
45
|
+
|
|
46
|
+
git_attrs = Utils.get_attributes(Git::GIT_MAPPING)
|
|
47
|
+
buildkite_attrs = Utils.get_attributes(BUILDKITE_MAPPING)
|
|
48
|
+
merged = git_attrs.merge(buildkite_attrs)
|
|
49
|
+
OpenTelemetry::SDK::Resources::Resource.create(merged)
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/mergify/rspec/utils.rb
CHANGED
|
@@ -15,6 +15,7 @@ module Mergify
|
|
|
15
15
|
'GITHUB_ACTIONS' => :github_actions,
|
|
16
16
|
'CIRCLECI' => :circleci,
|
|
17
17
|
'JENKINS_URL' => :jenkins,
|
|
18
|
+
'BUILDKITE' => :buildkite,
|
|
18
19
|
'_RSPEC_MERGIFY_TEST' => :rspec_mergify_suite
|
|
19
20
|
}.freeze
|
|
20
21
|
|
|
@@ -101,12 +102,7 @@ module Mergify
|
|
|
101
102
|
# Attributes whose env var is unset or whose callable returns nil are omitted.
|
|
102
103
|
def get_attributes(mapping)
|
|
103
104
|
mapping.each_with_object({}) do |(attr, (cast, env_or_callable)), result|
|
|
104
|
-
value =
|
|
105
|
-
if env_or_callable.respond_to?(:call)
|
|
106
|
-
env_or_callable.call
|
|
107
|
-
else
|
|
108
|
-
ENV.fetch(env_or_callable, nil)
|
|
109
|
-
end
|
|
105
|
+
value = env_or_callable.respond_to?(:call) ? env_or_callable.call : ENV.fetch(env_or_callable, nil)
|
|
110
106
|
|
|
111
107
|
next if value.nil?
|
|
112
108
|
next if value.respond_to?(:empty?) && value.empty?
|
|
@@ -130,6 +126,9 @@ module Mergify
|
|
|
130
126
|
when :circleci
|
|
131
127
|
url = ENV.fetch('CIRCLE_REPOSITORY_URL', nil)
|
|
132
128
|
return repository_name_from_url(url) if url
|
|
129
|
+
when :buildkite
|
|
130
|
+
url = ENV.fetch('BUILDKITE_REPO', nil)
|
|
131
|
+
return repository_name_from_url(url) if url
|
|
133
132
|
when :rspec_mergify_suite
|
|
134
133
|
return 'Mergifyio/rspec-mergify'
|
|
135
134
|
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rspec-mergify
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Mergify
|
|
@@ -67,6 +67,7 @@ files:
|
|
|
67
67
|
- lib/mergify/rspec/flaky_detection.rb
|
|
68
68
|
- lib/mergify/rspec/formatter.rb
|
|
69
69
|
- lib/mergify/rspec/quarantine.rb
|
|
70
|
+
- lib/mergify/rspec/resources/buildkite.rb
|
|
70
71
|
- lib/mergify/rspec/resources/ci.rb
|
|
71
72
|
- lib/mergify/rspec/resources/git.rb
|
|
72
73
|
- lib/mergify/rspec/resources/github_actions.rb
|