codeclimate-services 1.8.0 → 1.9.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 +4 -4
- data/.codeclimate.yml +1 -3
- data/Gemfile +5 -0
- data/circle.yml +4 -0
- data/codeclimate-services.gemspec +0 -1
- data/lib/cc/fixed_resolv.rb +29 -0
- data/lib/cc/service/http.rb +2 -10
- data/lib/cc/service/safe_webhook.rb +29 -31
- data/lib/cc/services/version.rb +1 -1
- data/spec/cc/service/github_issues_spec.rb +1 -3
- data/spec/cc/service/github_pull_requests_spec.rb +1 -3
- data/spec/cc/service/gitlab_merge_requests_spec.rb +1 -31
- data/spec/cc/service/safe_webhook_spec.rb +23 -43
- data/spec/cc/service_spec.rb +7 -7
- data/spec/spec_helper.rb +6 -4
- data/spec/support/resolv_helpers.rb +10 -0
- metadata +6 -18
- data/spec/support/resolv_helper.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4df2ee48a6422a56813233250049c38979fc3cb8
|
4
|
+
data.tar.gz: 7e58584424589e2c0b2ca337a853a4ea37e7b0fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ebb9f1f93b763a3858d6c66283ad1b27ff6507e57612301b71eeaf2077a1a034e808f98e787bbd9d9a9b2091f7f2e0bb397f38b3710c726bcd6907d5e37d51ad
|
7
|
+
data.tar.gz: db694bb54c853bf76dab733883350b38e1c3123706104e3b2a7730ebb41618b65badd9b6c7afc4ccade4ecc26db5997935cd8c5392a052987a06c156f75ab541
|
data/.codeclimate.yml
CHANGED
@@ -10,10 +10,8 @@ engines:
|
|
10
10
|
rubocop:
|
11
11
|
enabled: true
|
12
12
|
exclude_fingerprints:
|
13
|
-
# Using #=== intentionally
|
13
|
+
# Using #=== intentionally to do subnet masking
|
14
14
|
- d1afe90be49c43e85a76bfa58f637804
|
15
|
-
# High complexity in http method due to SafeWebhook check
|
16
|
-
- f05cea2d219c0f8119eb826067a18eda
|
17
15
|
ratings:
|
18
16
|
paths:
|
19
17
|
- "**.rb"
|
data/Gemfile
CHANGED
data/circle.yml
ADDED
@@ -23,7 +23,6 @@ Gem::Specification.new do |spec|
|
|
23
23
|
spec.add_dependency "activemodel", ">= 3.0"
|
24
24
|
spec.add_dependency "activesupport", ">= 3.0"
|
25
25
|
spec.add_development_dependency "bundler", ">= 1.6.2"
|
26
|
-
spec.add_development_dependency "codeclimate-test-reporter"
|
27
26
|
spec.add_development_dependency "rake"
|
28
27
|
spec.add_development_dependency "rspec"
|
29
28
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "resolv-replace"
|
2
|
+
|
3
|
+
module CC
|
4
|
+
class FixedResolv < Resolv::DNS
|
5
|
+
def self.enable!
|
6
|
+
new.tap do |instance|
|
7
|
+
Resolv::DefaultResolver.replace_resolvers([instance])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize
|
12
|
+
@addresses = {}
|
13
|
+
end
|
14
|
+
|
15
|
+
def setaddress(name, address)
|
16
|
+
addresses[name] = address
|
17
|
+
end
|
18
|
+
|
19
|
+
def each_address(name)
|
20
|
+
if addresses.key?(name)
|
21
|
+
yield addresses.fetch(name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
attr_reader :addresses
|
28
|
+
end
|
29
|
+
end
|
data/lib/cc/service/http.rb
CHANGED
@@ -53,16 +53,13 @@ module CC::Service::HTTP
|
|
53
53
|
def http_method(method, url = nil, body = nil, headers = nil)
|
54
54
|
block = Proc.new if block_given?
|
55
55
|
|
56
|
+
CC::Service::SafeWebhook.ensure_safe!(url)
|
57
|
+
|
56
58
|
http.send(method) do |req|
|
57
59
|
req.url(url) if url
|
58
60
|
req.headers.update(headers) if headers
|
59
61
|
req.body = body if body
|
60
62
|
block.call req if block
|
61
|
-
|
62
|
-
unless allow_internal_webhooks?
|
63
|
-
safe_webhook = CC::Service::SafeWebhook.new(url)
|
64
|
-
safe_webhook.validate!(req)
|
65
|
-
end
|
66
63
|
end
|
67
64
|
end
|
68
65
|
|
@@ -103,9 +100,4 @@ module CC::Service::HTTP
|
|
103
100
|
message: "Success",
|
104
101
|
}
|
105
102
|
end
|
106
|
-
|
107
|
-
def allow_internal_webhooks?
|
108
|
-
var = ENV["CODECLIMATE_ALLOW_INTERNAL_WEBHOOKS"] || ""
|
109
|
-
var == "1" || var == "true"
|
110
|
-
end
|
111
103
|
end
|
@@ -1,13 +1,13 @@
|
|
1
1
|
require "ipaddr"
|
2
|
-
require "
|
2
|
+
require "uri"
|
3
|
+
|
4
|
+
require "cc/fixed_resolv"
|
3
5
|
|
4
6
|
module CC
|
5
7
|
class Service
|
6
8
|
class SafeWebhook
|
7
|
-
|
9
|
+
InternalWebhookError = Class.new(StandardError)
|
8
10
|
|
9
|
-
# https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces
|
10
|
-
# https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses
|
11
11
|
PRIVATE_ADDRESS_SUBNETS = [
|
12
12
|
IPAddr.new("10.0.0.0/8"),
|
13
13
|
IPAddr.new("172.16.0.0/12"),
|
@@ -17,54 +17,52 @@ module CC
|
|
17
17
|
IPAddr.new("0:0:0:0:0:0:0:1"),
|
18
18
|
].freeze
|
19
19
|
|
20
|
+
def self.ensure_safe!(url)
|
21
|
+
instance = new(url)
|
22
|
+
instance.ensure_safe!
|
23
|
+
end
|
24
|
+
|
20
25
|
def self.getaddress(host)
|
21
|
-
@
|
22
|
-
@
|
26
|
+
@dns ||= Resolv::DNS.new
|
27
|
+
@dns.getaddress(host)
|
28
|
+
end
|
29
|
+
|
30
|
+
def self.setaddress(host, address)
|
31
|
+
@fixed_resolv ||= CC::FixedResolv.enable!
|
32
|
+
@fixed_resolv.setaddress(host, address)
|
23
33
|
end
|
24
34
|
|
25
35
|
def initialize(url)
|
26
36
|
@url = url
|
27
37
|
end
|
28
38
|
|
29
|
-
|
30
|
-
# anything internal, then alter the request to be for the IP directly with
|
31
|
-
# an explicit Host header given.
|
32
|
-
#
|
33
|
-
# See http://blog.fanout.io/2014/01/27/how-to-safely-invoke-webhooks/#ip-address-blacklisting
|
34
|
-
def validate!(request)
|
39
|
+
def ensure_safe!
|
35
40
|
uri = URI.parse(url)
|
36
|
-
address = self.class.getaddress(uri.host)
|
37
41
|
|
38
|
-
if internal?(
|
39
|
-
|
42
|
+
if !allow_internal_webhooks? && internal?(uri.host)
|
43
|
+
raise InternalWebhookError, "#{url.inspect} maps to an internal address"
|
40
44
|
end
|
41
|
-
|
42
|
-
alter_request(request, uri, address)
|
43
|
-
rescue URI::InvalidURIError, Resolv::ResolvError, Resolv::ResolvTimeout => ex
|
44
|
-
raise_invalid(ex.message)
|
45
45
|
end
|
46
46
|
|
47
47
|
private
|
48
48
|
|
49
49
|
attr_reader :url
|
50
50
|
|
51
|
-
def internal?(
|
52
|
-
|
51
|
+
def internal?(host)
|
52
|
+
address = self.class.getaddress(host)
|
53
|
+
|
54
|
+
self.class.setaddress(host, address)
|
53
55
|
|
54
56
|
PRIVATE_ADDRESS_SUBNETS.any? do |subnet|
|
55
|
-
subnet ===
|
57
|
+
subnet === IPAddr.new(address.to_s)
|
56
58
|
end
|
59
|
+
rescue Resolv::ResolvError
|
60
|
+
true # localhost
|
57
61
|
end
|
58
62
|
|
59
|
-
def
|
60
|
-
|
61
|
-
|
62
|
-
request.url(address_uri.to_s)
|
63
|
-
request.headers.update(Host: uri.host)
|
64
|
-
end
|
65
|
-
|
66
|
-
def raise_invalid(message)
|
67
|
-
raise InvalidWebhookURL, "The Webhook URL #{url} is invalid: #{message}"
|
63
|
+
def allow_internal_webhooks?
|
64
|
+
var = ENV["CODECLIMATE_ALLOW_INTERNAL_WEBHOOKS"] || ""
|
65
|
+
var == "1" || var == "true"
|
68
66
|
end
|
69
67
|
end
|
70
68
|
end
|
data/lib/cc/services/version.rb
CHANGED
@@ -67,10 +67,8 @@ describe CC::Service::GitHubIssues, type: :service do
|
|
67
67
|
end
|
68
68
|
|
69
69
|
it "different base url" do
|
70
|
-
stub_resolv("example.com", "1.1.1.2")
|
71
|
-
|
72
70
|
http_stubs.post request_url do |env|
|
73
|
-
expect(env[:url].to_s).to eq("http://
|
71
|
+
expect(env[:url].to_s).to eq("http://example.com/#{request_url}")
|
74
72
|
[200, {}, '{"number": 2, "html_url": "http://foo.bar"}']
|
75
73
|
end
|
76
74
|
|
@@ -107,10 +107,8 @@ describe CC::Service::GitHubPullRequests, type: :service do
|
|
107
107
|
end
|
108
108
|
|
109
109
|
it "different base url" do
|
110
|
-
stub_resolv("example.com", "1.1.1.2")
|
111
|
-
|
112
110
|
http_stubs.post("/repos/pbrisbin/foo/statuses/#{"0" * 40}") do |env|
|
113
|
-
expect(env[:url].to_s).to eq("http://
|
111
|
+
expect(env[:url].to_s).to eq("http://example.com/repos/pbrisbin/foo/statuses/#{"0" * 40}")
|
114
112
|
[422, { "x-oauth-scopes" => "gist, user, repo" }, ""]
|
115
113
|
end
|
116
114
|
|
@@ -134,44 +134,14 @@ describe CC::Service::GitlabMergeRequests, type: :service do
|
|
134
134
|
end
|
135
135
|
|
136
136
|
it "different base url" do
|
137
|
-
stub_resolv("gitlab.hal.org", "1.1.1.2")
|
138
|
-
|
139
137
|
http_stubs.post("api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}") do |env|
|
140
|
-
expect(env[:url].to_s).to eq("https://
|
138
|
+
expect(env[:url].to_s).to eq("https://gitlab.hal.org/api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}")
|
141
139
|
[404, {}, ""]
|
142
140
|
end
|
143
141
|
|
144
142
|
expect(receive_test({ base_url: "https://gitlab.hal.org" }, git_url: "ssh://git@gitlab.com/hal/hal9000.git")[:ok]).to eq(true)
|
145
143
|
end
|
146
144
|
|
147
|
-
context "SafeWebhook" do
|
148
|
-
it "rewrites the request to be for the resolved IP" do
|
149
|
-
stub_resolv("my.gitlab.com", "1.1.1.2")
|
150
|
-
|
151
|
-
http_stubs.post("api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}") do |env|
|
152
|
-
expect(env[:url].to_s).to eq("https://1.1.1.2/api/v3/projects/hal%2Fhal9000/statuses/#{"0" * 40}")
|
153
|
-
expect(env[:request_headers][:Host]).to eq("my.gitlab.com")
|
154
|
-
[404, {}, ""]
|
155
|
-
end
|
156
|
-
|
157
|
-
expect(receive_test({ base_url: "https://my.gitlab.com" }, git_url: "ssh://git@gitlab.com/hal/hal9000.git")[:ok]).to eq(true)
|
158
|
-
end
|
159
|
-
|
160
|
-
it "validates that the host doesn't resolve to something internal" do
|
161
|
-
stub_resolv("my.gitlab.com", "127.0.0.1")
|
162
|
-
|
163
|
-
expect do
|
164
|
-
receive_test({ base_url: "https://my.gitlab.com" }, git_url: "")
|
165
|
-
end.to raise_error(CC::Service::SafeWebhook::InvalidWebhookURL)
|
166
|
-
|
167
|
-
stub_resolv("my.gitlab.com", "10.0.0.9")
|
168
|
-
|
169
|
-
expect do
|
170
|
-
receive_test({ base_url: "https://my.gitlab.com" }, git_url: "")
|
171
|
-
end.to raise_error(CC::Service::SafeWebhook::InvalidWebhookURL)
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
145
|
private
|
176
146
|
|
177
147
|
def expect_status_update(repo, commit_sha, params)
|
@@ -2,59 +2,39 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
class CC::Service
|
4
4
|
describe SafeWebhook do
|
5
|
-
describe ".
|
6
|
-
it "
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
describe "#validate!" do
|
15
|
-
context "valid webhook URLs" do
|
16
|
-
it "rewrites the request to be safe" do
|
17
|
-
stub_resolv("example.com", "2.2.2.2")
|
18
|
-
|
19
|
-
request = double(headers: double)
|
20
|
-
expect(request).to receive(:url).with("https://2.2.2.2:3000/foo")
|
21
|
-
expect(request.headers).to receive(:update).with(Host: "example.com")
|
22
|
-
|
23
|
-
safe_webhook = SafeWebhook.new("https://example.com:3000/foo")
|
24
|
-
safe_webhook.validate!(request)
|
5
|
+
describe ".ensure_safe!" do
|
6
|
+
it "does not allow internal URLs" do
|
7
|
+
%w[ 127.0.0.1 192.168.0.1 10.0.1.18 ].each do |address|
|
8
|
+
stub_resolv("github.com", address)
|
9
|
+
|
10
|
+
expect do
|
11
|
+
SafeWebhook.ensure_safe!("https://github.com/api/v1/user")
|
12
|
+
end.to raise_error(SafeWebhook::InternalWebhookError)
|
25
13
|
end
|
26
14
|
end
|
27
15
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
expect { validate("http://example.com") }.to raise_error(SafeWebhook::InvalidWebhookURL)
|
33
|
-
end
|
16
|
+
it "allows internal URLs when configured to do so" do
|
17
|
+
allow(ENV).to receive(:[]).
|
18
|
+
with("CODECLIMATE_ALLOW_INTERNAL_WEBHOOKS").
|
19
|
+
and_return("1")
|
34
20
|
|
35
|
-
|
36
|
-
allow(SafeWebhook).to receive(:getaddress).and_raise(Resolv::ResolvError)
|
21
|
+
stub_resolv("github.com", "10.0.1.18")
|
37
22
|
|
38
|
-
|
39
|
-
|
23
|
+
SafeWebhook.ensure_safe!("https://github.com/api/v1/user")
|
24
|
+
end
|
40
25
|
|
41
|
-
|
42
|
-
|
26
|
+
it "allows non-internal URLs" do
|
27
|
+
stub_resolv("github.com", "1.1.1.2")
|
43
28
|
|
44
|
-
|
45
|
-
|
29
|
+
SafeWebhook.ensure_safe!("https://github.com/api/v1/user")
|
30
|
+
end
|
46
31
|
|
47
|
-
|
48
|
-
|
32
|
+
it "ensures future dns queries get the same answer" do
|
33
|
+
stub_resolv("github.com", "1.1.1.3")
|
49
34
|
|
50
|
-
|
51
|
-
end
|
35
|
+
SafeWebhook.ensure_safe!("https://github.com/api/v1/user")
|
52
36
|
|
53
|
-
|
54
|
-
request = double
|
55
|
-
safe_webhook = SafeWebhook.new(url)
|
56
|
-
safe_webhook.validate!(request)
|
57
|
-
end
|
37
|
+
expect(Resolv.getaddress("github.com").to_s).to eq "1.1.1.3"
|
58
38
|
end
|
59
39
|
end
|
60
40
|
end
|
data/spec/cc/service_spec.rb
CHANGED
@@ -32,42 +32,42 @@ describe CC::Service, type: :service do
|
|
32
32
|
it "post success" do
|
33
33
|
stub_http("/my/test/url", [200, {}, '{"ok": true, "thing": "123"}'])
|
34
34
|
|
35
|
-
response = service_post("/my/test/url", { token: "1234" }.to_json, {}) do |inner_response|
|
35
|
+
response = service_post("http://example.com/my/test/url", { token: "1234" }.to_json, {}) do |inner_response|
|
36
36
|
body = JSON.parse(inner_response.body)
|
37
37
|
{ thing: body["thing"] }
|
38
38
|
end
|
39
39
|
|
40
40
|
expect(response[:ok]).to eq(true)
|
41
41
|
expect(response[:params]).to eq('{"token":"1234"}')
|
42
|
-
expect(response[:endpoint_url]).to eq("/my/test/url")
|
42
|
+
expect(response[:endpoint_url]).to eq("http://example.com/my/test/url")
|
43
43
|
expect(response[:status]).to eq(200)
|
44
44
|
end
|
45
45
|
|
46
46
|
it "post redirect success" do
|
47
|
-
stub_http("/my/test/url", [307, { "Location" => "/my/redirect/url" }, '{"ok": false, "redirect": true}'])
|
47
|
+
stub_http("/my/test/url", [307, { "Location" => "http://example.com/my/redirect/url" }, '{"ok": false, "redirect": true}'])
|
48
48
|
stub_http("/my/redirect/url", [200, {}, '{"ok": true, "thing": "123"}'])
|
49
49
|
|
50
|
-
response = service_post_with_redirects("/my/test/url", { token: "1234" }.to_json, {}) do |inner_response|
|
50
|
+
response = service_post_with_redirects("http://example.com/my/test/url", { token: "1234" }.to_json, {}) do |inner_response|
|
51
51
|
body = JSON.parse(inner_response.body)
|
52
52
|
{ thing: body["thing"] }
|
53
53
|
end
|
54
54
|
|
55
55
|
expect(response[:ok]).to eq(true)
|
56
56
|
expect(response[:params]).to eq('{"token":"1234"}')
|
57
|
-
expect(response[:endpoint_url]).to eq("/my/test/url")
|
57
|
+
expect(response[:endpoint_url]).to eq("http://example.com/my/test/url")
|
58
58
|
expect(response[:status]).to eq(200)
|
59
59
|
end
|
60
60
|
|
61
61
|
it "post http failure" do
|
62
62
|
stub_http("/my/wrong/url", [404, {}, ""])
|
63
63
|
|
64
|
-
expect { service_post("/my/wrong/url", { token: "1234" }.to_json, {}) }.to raise_error(CC::Service::HTTPError)
|
64
|
+
expect { service_post("http://example.com/my/wrong/url", { token: "1234" }.to_json, {}) }.to raise_error(CC::Service::HTTPError)
|
65
65
|
end
|
66
66
|
|
67
67
|
it "post some other failure" do
|
68
68
|
stub_http("/my/wrong/url") { raise ArgumentError, "lol" }
|
69
69
|
|
70
|
-
expect { service_post("/my/wrong/url", { token: "1234" }.to_json, {}) }.to raise_error(ArgumentError)
|
70
|
+
expect { service_post("http://example.com/my/wrong/url", { token: "1234" }.to_json, {}) }.to raise_error(ArgumentError)
|
71
71
|
end
|
72
72
|
|
73
73
|
it "services" do
|
data/spec/spec_helper.rb
CHANGED
@@ -1,5 +1,7 @@
|
|
1
|
-
require "
|
2
|
-
|
1
|
+
require "simplecov"
|
2
|
+
SimpleCov.start do
|
3
|
+
add_filter "/spec/"
|
4
|
+
end
|
3
5
|
|
4
6
|
cwd = File.expand_path(File.dirname(__FILE__))
|
5
7
|
require "#{cwd}/../config/load"
|
@@ -34,8 +36,8 @@ RSpec.configure do |config|
|
|
34
36
|
# This setting enables warnings. It's recommended, but in some cases may
|
35
37
|
# be too noisy due to issues in dependencies.
|
36
38
|
config.warnings = true
|
37
|
-
|
38
|
-
|
39
|
+
config.before do
|
40
|
+
# Disable actual DNS resolution during specs by default
|
39
41
|
stub_resolv(anything, "1.1.1.1")
|
40
42
|
end
|
41
43
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: codeclimate-services
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.9.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bryan Helmkamp
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-
|
11
|
+
date: 2016-10-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -94,20 +94,6 @@ dependencies:
|
|
94
94
|
- - ">="
|
95
95
|
- !ruby/object:Gem::Version
|
96
96
|
version: 1.6.2
|
97
|
-
- !ruby/object:Gem::Dependency
|
98
|
-
name: codeclimate-test-reporter
|
99
|
-
requirement: !ruby/object:Gem::Requirement
|
100
|
-
requirements:
|
101
|
-
- - ">="
|
102
|
-
- !ruby/object:Gem::Version
|
103
|
-
version: '0'
|
104
|
-
type: :development
|
105
|
-
prerelease: false
|
106
|
-
version_requirements: !ruby/object:Gem::Requirement
|
107
|
-
requirements:
|
108
|
-
- - ">="
|
109
|
-
- !ruby/object:Gem::Version
|
110
|
-
version: '0'
|
111
97
|
- !ruby/object:Gem::Dependency
|
112
98
|
name: rake
|
113
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -158,10 +144,12 @@ files:
|
|
158
144
|
- bin/nokogiri
|
159
145
|
- bin/pry
|
160
146
|
- bin/rake
|
147
|
+
- circle.yml
|
161
148
|
- codeclimate-services.gemspec
|
162
149
|
- config/cacert.pem
|
163
150
|
- config/load.rb
|
164
151
|
- lib/axiom/types/password.rb
|
152
|
+
- lib/cc/fixed_resolv.rb
|
165
153
|
- lib/cc/formatters/linked_formatter.rb
|
166
154
|
- lib/cc/formatters/plain_formatter.rb
|
167
155
|
- lib/cc/formatters/snapshot_formatter.rb
|
@@ -225,7 +213,7 @@ files:
|
|
225
213
|
- spec/fixtures.rb
|
226
214
|
- spec/spec_helper.rb
|
227
215
|
- spec/support/fake_logger.rb
|
228
|
-
- spec/support/
|
216
|
+
- spec/support/resolv_helpers.rb
|
229
217
|
- spec/support/service_context.rb
|
230
218
|
homepage: ''
|
231
219
|
licenses:
|
@@ -276,5 +264,5 @@ test_files:
|
|
276
264
|
- spec/fixtures.rb
|
277
265
|
- spec/spec_helper.rb
|
278
266
|
- spec/support/fake_logger.rb
|
279
|
-
- spec/support/
|
267
|
+
- spec/support/resolv_helpers.rb
|
280
268
|
- spec/support/service_context.rb
|