percy-client 1.9.2 → 1.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.rubocop.yml +67 -0
- data/.rubocop_todo.yml +101 -0
- data/.travis.yml +7 -4
- data/Gemfile +6 -1
- data/Rakefile +0 -1
- data/lib/percy.rb +13 -9
- data/lib/percy/client.rb +10 -10
- data/lib/percy/client/builds.rb +6 -8
- data/lib/percy/client/connection.rb +5 -3
- data/lib/percy/client/environment.rb +26 -18
- data/lib/percy/client/resources.rb +1 -2
- data/lib/percy/client/snapshots.rb +4 -4
- data/lib/percy/client/version.rb +1 -1
- data/spec/lib/percy/client/builds_spec.rb +7 -5
- data/spec/lib/percy/client/connection_spec.rb +4 -4
- data/spec/lib/percy/client/environment_spec.rb +32 -6
- data/spec/lib/percy/client/resources_spec.rb +4 -4
- data/spec/lib/percy/client/snapshots_spec.rb +7 -5
- data/spec/lib/percy/client_spec.rb +1 -1
- data/spec/lib/percy/config_spec.rb +10 -8
- data/spec/lib/percy_spec.rb +1 -1
- data/spec/support/vcr_setup.rb +1 -1
- metadata +5 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: faeea13f560dc02b0e342b7ff1b150f1cb328992
|
4
|
+
data.tar.gz: 66c65cadf25bf1f38c43d8408235aa383dd0649a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c8cdecfd7259f45698e015f57b09c2f7c6800daacaea64c88ba36cf5b905220bedc98a3b5c9141743d15e651ea838f23df1742d5d76dc6884dfbe8c98b4c1c88
|
7
|
+
data.tar.gz: f6c3d6f4f5fa2870c6cde224e954c297ff49b88700cbdd0417a43eadcbada8cd053d2a3aa265a6aa575e5afe019d4b7daeb826fd0eb3c6dc0bc5f5f3012e4198
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
require: rubocop-rspec
|
2
|
+
inherit_from: .rubocop_todo.yml
|
3
|
+
AllCops:
|
4
|
+
Include:
|
5
|
+
- Rakefile
|
6
|
+
- lib/**/*.rake
|
7
|
+
|
8
|
+
Lint/EndAlignment:
|
9
|
+
EnforcedStyleAlignWith: variable
|
10
|
+
|
11
|
+
Metrics/LineLength:
|
12
|
+
Max: 101
|
13
|
+
|
14
|
+
Style/AlignParameters:
|
15
|
+
EnforcedStyle: with_fixed_indentation
|
16
|
+
|
17
|
+
Style/CaseIndentation:
|
18
|
+
EnforcedStyle: end
|
19
|
+
|
20
|
+
Style/Documentation:
|
21
|
+
Enabled: false
|
22
|
+
|
23
|
+
Style/DoubleNegation:
|
24
|
+
Enabled: false
|
25
|
+
|
26
|
+
Style/IndentArray:
|
27
|
+
EnforcedStyle: consistent
|
28
|
+
|
29
|
+
Style/MultilineMethodCallIndentation:
|
30
|
+
EnforcedStyle: indented
|
31
|
+
|
32
|
+
Style/MultilineOperationIndentation:
|
33
|
+
EnforcedStyle: indented
|
34
|
+
|
35
|
+
# Disable Style/NumericLiterals so numbers don't need underscores
|
36
|
+
Style/NumericLiterals:
|
37
|
+
Enabled: false
|
38
|
+
|
39
|
+
Style/NumericPredicate:
|
40
|
+
EnforcedStyle: comparison
|
41
|
+
|
42
|
+
Style/RedundantBegin:
|
43
|
+
Enabled: false
|
44
|
+
|
45
|
+
Style/RegexpLiteral:
|
46
|
+
EnforcedStyle: slashes
|
47
|
+
AllowInnerSlashes: true
|
48
|
+
|
49
|
+
Style/SpaceInsideHashLiteralBraces:
|
50
|
+
EnforcedStyle: no_space
|
51
|
+
|
52
|
+
Style/TrailingCommaInArguments:
|
53
|
+
EnforcedStyleForMultiline: consistent_comma
|
54
|
+
|
55
|
+
Style/TrailingCommaInLiteral:
|
56
|
+
EnforcedStyleForMultiline: consistent_comma
|
57
|
+
|
58
|
+
RSpec/MessageSpies:
|
59
|
+
EnforcedStyle: receive
|
60
|
+
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
# Will be able to do this in >= v1.11
|
66
|
+
# RSpec/DescribedClass:
|
67
|
+
# EnforcedStyle: explicit
|
data/.rubocop_todo.yml
ADDED
@@ -0,0 +1,101 @@
|
|
1
|
+
# This configuration was generated by
|
2
|
+
# `rubocop --auto-gen-config`
|
3
|
+
# on 2017-02-11 20:36:15 -0800 using RuboCop version 0.47.1.
|
4
|
+
# The point is for the user to remove these configuration records
|
5
|
+
# one by one as the offenses are removed from the code base.
|
6
|
+
# Note that changes in the inspected code, or installation of new
|
7
|
+
# versions of RuboCop, may require this file to be generated again.
|
8
|
+
|
9
|
+
# Offense count: 1
|
10
|
+
Lint/EmptyWhen:
|
11
|
+
Exclude:
|
12
|
+
- 'lib/percy/client/environment.rb'
|
13
|
+
|
14
|
+
# Offense count: 13
|
15
|
+
Metrics/AbcSize:
|
16
|
+
Max: 65
|
17
|
+
|
18
|
+
# Offense count: 24
|
19
|
+
# Configuration parameters: CountComments, ExcludedMethods.
|
20
|
+
Metrics/BlockLength:
|
21
|
+
Max: 450
|
22
|
+
|
23
|
+
# Offense count: 10
|
24
|
+
Metrics/CyclomaticComplexity:
|
25
|
+
Max: 14
|
26
|
+
|
27
|
+
# Offense count: 1
|
28
|
+
# Configuration parameters: AllowHeredoc, AllowURI, URISchemes, IgnoreCopDirectives, IgnoredPatterns.
|
29
|
+
# URISchemes: http, https
|
30
|
+
Metrics/LineLength:
|
31
|
+
Max: 101
|
32
|
+
|
33
|
+
# Offense count: 14
|
34
|
+
# Configuration parameters: CountComments.
|
35
|
+
Metrics/MethodLength:
|
36
|
+
Max: 57
|
37
|
+
|
38
|
+
# Offense count: 1
|
39
|
+
# Configuration parameters: CountComments.
|
40
|
+
Metrics/ModuleLength:
|
41
|
+
Max: 220
|
42
|
+
|
43
|
+
# Offense count: 6
|
44
|
+
Metrics/PerceivedComplexity:
|
45
|
+
Max: 13
|
46
|
+
|
47
|
+
# Offense count: 4
|
48
|
+
RSpec/AnyInstance:
|
49
|
+
Exclude:
|
50
|
+
- 'spec/lib/percy/client/builds_spec.rb'
|
51
|
+
- 'spec/lib/percy/client/snapshots_spec.rb'
|
52
|
+
|
53
|
+
# Offense count: 113
|
54
|
+
# Configuration parameters: SkipBlocks.
|
55
|
+
RSpec/DescribedClass:
|
56
|
+
Exclude:
|
57
|
+
- 'spec/lib/percy/client/environment_spec.rb'
|
58
|
+
- 'spec/lib/percy/client_spec.rb'
|
59
|
+
- 'spec/lib/percy_spec.rb'
|
60
|
+
|
61
|
+
# Offense count: 22
|
62
|
+
# Configuration parameters: Max.
|
63
|
+
RSpec/ExampleLength:
|
64
|
+
Exclude:
|
65
|
+
- 'spec/lib/percy/client/builds_spec.rb'
|
66
|
+
- 'spec/lib/percy/client/connection_spec.rb'
|
67
|
+
- 'spec/lib/percy/client/environment_spec.rb'
|
68
|
+
- 'spec/lib/percy/client/resources_spec.rb'
|
69
|
+
- 'spec/lib/percy/client/snapshots_spec.rb'
|
70
|
+
- 'spec/lib/percy/config_spec.rb'
|
71
|
+
- 'spec/lib/percy_spec.rb'
|
72
|
+
|
73
|
+
# Offense count: 20
|
74
|
+
# Configuration parameters: SupportedStyles.
|
75
|
+
# SupportedStyles: implicit, each, example
|
76
|
+
RSpec/HookArgument:
|
77
|
+
EnforcedStyle: each
|
78
|
+
|
79
|
+
# Offense count: 8
|
80
|
+
# Configuration parameters: AssignmentOnly.
|
81
|
+
RSpec/InstanceVariable:
|
82
|
+
Exclude:
|
83
|
+
- 'spec/lib/percy/client/environment_spec.rb'
|
84
|
+
|
85
|
+
# Offense count: 27
|
86
|
+
RSpec/MultipleExpectations:
|
87
|
+
Max: 10
|
88
|
+
|
89
|
+
# Offense count: 12
|
90
|
+
# Configuration parameters: EnforcedStyle, SupportedStyles.
|
91
|
+
# SupportedStyles: not_to, to_not
|
92
|
+
RSpec/NotToNot:
|
93
|
+
Exclude:
|
94
|
+
- 'spec/lib/percy/client/builds_spec.rb'
|
95
|
+
- 'spec/lib/percy/client/environment_spec.rb'
|
96
|
+
- 'spec/lib/percy_spec.rb'
|
97
|
+
|
98
|
+
# Offense count: 1
|
99
|
+
Style/MethodMissing:
|
100
|
+
Exclude:
|
101
|
+
- 'lib/percy.rb'
|
data/.travis.yml
CHANGED
@@ -8,10 +8,13 @@ addons:
|
|
8
8
|
- libgmp-dev
|
9
9
|
cache: bundler
|
10
10
|
rvm:
|
11
|
-
-
|
12
|
-
- 2.
|
13
|
-
- 2.
|
11
|
+
- ruby-2.2.6
|
12
|
+
- ruby-2.3.3
|
13
|
+
- ruby-2.4.0
|
14
14
|
- ruby-head
|
15
15
|
before_install:
|
16
|
+
- gem update --system
|
16
17
|
- gem update bundler
|
17
|
-
script:
|
18
|
+
script:
|
19
|
+
- bundle exec rspec
|
20
|
+
- bundle exec rubocop -D
|
data/Gemfile
CHANGED
data/Rakefile
CHANGED
data/lib/percy.rb
CHANGED
@@ -25,25 +25,29 @@ module Percy
|
|
25
25
|
@logger if defined?(@logger)
|
26
26
|
@logger ||= Logger.new(STDOUT)
|
27
27
|
@logger.level = config.debug ? Logger::DEBUG : Logger::INFO
|
28
|
-
@logger.formatter = proc do |severity,
|
29
|
-
|
28
|
+
@logger.formatter = proc do |severity, _datetime, _progname, msg|
|
29
|
+
"[percy][#{severity}] #{msg}\n"
|
30
30
|
end
|
31
31
|
@logger
|
32
32
|
end
|
33
33
|
|
34
34
|
# @private
|
35
|
-
|
36
|
-
|
37
|
-
|
35
|
+
if RUBY_VERSION >= '1.9'
|
36
|
+
def self.respond_to_missing?(method_name, include_private = false)
|
37
|
+
client.respond_to?(method_name, include_private)
|
38
|
+
end
|
39
|
+
end
|
38
40
|
|
39
41
|
# @private
|
40
|
-
|
41
|
-
|
42
|
-
|
42
|
+
if RUBY_VERSION < '1.9'
|
43
|
+
def self.respond_to?(method_name, include_private = false)
|
44
|
+
client.respond_to?(method_name, include_private) || super
|
45
|
+
end
|
46
|
+
end
|
43
47
|
|
44
48
|
# @private
|
45
49
|
def self.method_missing(method_name, *args, &block)
|
46
|
-
return super
|
50
|
+
return super unless client.respond_to?(method_name)
|
47
51
|
client.send(method_name, *args, &block)
|
48
52
|
end
|
49
53
|
private :method_missing
|
data/lib/percy/client.rb
CHANGED
@@ -14,7 +14,7 @@ module Percy
|
|
14
14
|
include Percy::Client::Snapshots
|
15
15
|
include Percy::Client::Resources
|
16
16
|
|
17
|
-
class Error <
|
17
|
+
class Error < RuntimeError; end
|
18
18
|
class TimeoutError < Error; end
|
19
19
|
class ConnectionFailed < Error; end
|
20
20
|
class HttpError < Error
|
@@ -32,18 +32,18 @@ module Percy
|
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
|
-
class ClientError < HttpError; end
|
36
|
-
class BadRequestError < ClientError; end
|
37
|
-
class UnauthorizedError < ClientError; end
|
38
|
-
class PaymentRequiredError < ClientError; end
|
39
|
-
class ForbiddenError < ClientError; end
|
35
|
+
class ClientError < HttpError; end # 4xx;
|
36
|
+
class BadRequestError < ClientError; end # 400.
|
37
|
+
class UnauthorizedError < ClientError; end # 401.
|
38
|
+
class PaymentRequiredError < ClientError; end # 402.
|
39
|
+
class ForbiddenError < ClientError; end # 403.
|
40
40
|
class NotFoundError < ClientError; end # 404.
|
41
41
|
class ConflictError < ClientError; end # 409.
|
42
42
|
|
43
|
-
class ServerError < HttpError; end
|
44
|
-
class InternalServerError < ServerError; end
|
45
|
-
class BadGatewayError < ServerError; end
|
46
|
-
class ServiceUnavailableError < ServerError; end
|
43
|
+
class ServerError < HttpError; end # 5xx.
|
44
|
+
class InternalServerError < ServerError; end # 500.
|
45
|
+
class BadGatewayError < ServerError; end # 502.
|
46
|
+
class ServiceUnavailableError < ServerError; end # 503.
|
47
47
|
|
48
48
|
attr_reader :config
|
49
49
|
|
data/lib/percy/client/builds.rb
CHANGED
@@ -14,7 +14,7 @@ module Percy
|
|
14
14
|
# Only pass parallelism data if it all exists and there is more than 1 shard.
|
15
15
|
in_parallel_environment = parallel_nonce && \
|
16
16
|
parallel_total_shards && parallel_total_shards > 1
|
17
|
-
|
17
|
+
unless in_parallel_environment
|
18
18
|
parallel_nonce = nil
|
19
19
|
parallel_total_shards = nil
|
20
20
|
end
|
@@ -36,18 +36,18 @@ module Percy
|
|
36
36
|
'parallel-nonce' => parallel_nonce,
|
37
37
|
'parallel-total-shards' => parallel_total_shards,
|
38
38
|
},
|
39
|
-
}
|
39
|
+
},
|
40
40
|
}
|
41
41
|
|
42
42
|
if resources
|
43
|
-
|
44
|
-
raise ArgumentError
|
45
|
-
'resources argument must be an iterable of Percy::Client::Resource objects'
|
43
|
+
unless resources.respond_to?(:each)
|
44
|
+
raise ArgumentError,
|
45
|
+
'resources argument must be an iterable of Percy::Client::Resource objects'
|
46
46
|
end
|
47
47
|
relationships_data = {
|
48
48
|
'relationships' => {
|
49
49
|
'resources' => {
|
50
|
-
'data' => resources.map
|
50
|
+
'data' => resources.map(&:serialize),
|
51
51
|
},
|
52
52
|
},
|
53
53
|
}
|
@@ -71,5 +71,3 @@ module Percy
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
74
|
-
|
75
|
-
|
@@ -39,12 +39,14 @@ module Percy
|
|
39
39
|
error_class = Percy::Client::BadGatewayError
|
40
40
|
when 503
|
41
41
|
error_class = Percy::Client::ServiceUnavailableError
|
42
|
-
when CLIENT_ERROR_STATUS_RANGE
|
42
|
+
when CLIENT_ERROR_STATUS_RANGE # Catchall.
|
43
43
|
error_class = Percy::Client::HttpError
|
44
44
|
end
|
45
|
+
return unless error_class
|
45
46
|
raise error_class.new(
|
46
|
-
|
47
|
-
|
47
|
+
env.status, env.method.upcase, env.url, env.body,
|
48
|
+
"Got #{env.status} (#{env.method.upcase} #{env.url}):\n#{env.body}",
|
49
|
+
)
|
48
50
|
end
|
49
51
|
end
|
50
52
|
|
@@ -9,34 +9,35 @@ module Percy
|
|
9
9
|
'COMMITTER_EMAIL:%ae',
|
10
10
|
'COMMITTED_DATE:%ai',
|
11
11
|
# Note: order is important, this must come last because the regex is a multiline match.
|
12
|
-
'COMMIT_MESSAGE:%B'
|
12
|
+
'COMMIT_MESSAGE:%B',
|
13
13
|
].freeze
|
14
14
|
|
15
|
-
class Error <
|
16
|
-
class RepoNotFoundError <
|
15
|
+
class Error < RuntimeError; end
|
16
|
+
class RepoNotFoundError < RuntimeError; end
|
17
17
|
|
18
18
|
def self.current_ci
|
19
19
|
return :travis if ENV['TRAVIS_BUILD_ID']
|
20
|
-
return :jenkins if ENV['JENKINS_URL'] && ENV['ghprbPullId']
|
20
|
+
return :jenkins if ENV['JENKINS_URL'] && ENV['ghprbPullId'] # Pull Request Builder plugin.
|
21
21
|
return :circle if ENV['CIRCLECI']
|
22
22
|
return :codeship if ENV['CI_NAME'] && ENV['CI_NAME'] == 'codeship'
|
23
23
|
return :drone if ENV['DRONE'] == 'true'
|
24
24
|
return :semaphore if ENV['SEMAPHORE'] == 'true'
|
25
25
|
return :buildkite if ENV['BUILDKITE'] == 'true'
|
26
|
+
return :gitlab if ENV['GITLAB_CI']
|
26
27
|
end
|
27
28
|
|
28
29
|
# @return [Hash] All commit data from the current commit. Might be empty if commit data could
|
29
30
|
# not be found.
|
30
31
|
def self.commit
|
31
32
|
output = _raw_commit_output(_commit_sha) if _commit_sha
|
32
|
-
output = _raw_commit_output('HEAD')
|
33
|
+
output = _raw_commit_output('HEAD') unless output
|
33
34
|
|
34
35
|
# Use the specified SHA or, if not given, the parsed SHA at HEAD.
|
35
36
|
commit_sha = _commit_sha || output && output.match(/COMMIT_SHA:(.*)/)[1]
|
36
37
|
|
37
38
|
# If not running in a git repo, allow nils for certain commit attributes.
|
38
|
-
extract_or_nil =
|
39
|
-
|
39
|
+
extract_or_nil = ->(regex) { (output && output.match(regex) || [])[1] }
|
40
|
+
{
|
40
41
|
# The only required attribute:
|
41
42
|
branch: branch,
|
42
43
|
# An optional but important attribute:
|
@@ -48,7 +49,7 @@ module Percy
|
|
48
49
|
# These GIT_ environment vars are from the Jenkins Git Plugin, but could be
|
49
50
|
# used generically. This behavior may change in the future.
|
50
51
|
author_name: extract_or_nil.call(/AUTHOR_NAME:(.*)/) || ENV['GIT_AUTHOR_NAME'],
|
51
|
-
author_email: extract_or_nil.call(/AUTHOR_EMAIL:(.*)/)
|
52
|
+
author_email: extract_or_nil.call(/AUTHOR_EMAIL:(.*)/) || ENV['GIT_AUTHOR_EMAIL'],
|
52
53
|
committer_name: extract_or_nil.call(/COMMITTER_NAME:(.*)/) || ENV['GIT_COMMITTER_NAME'],
|
53
54
|
committer_email: extract_or_nil.call(/COMMITTER_EMAIL:(.*)/) || ENV['GIT_COMMITTER_EMAIL'],
|
54
55
|
}
|
@@ -80,14 +81,16 @@ module Percy
|
|
80
81
|
# Buildkite mixes SHAs and non-SHAs in BUILDKITE_COMMIT, so we return null if non-SHA.
|
81
82
|
return if ENV['BUILDKITE_COMMIT'] == 'HEAD'
|
82
83
|
ENV['BUILDKITE_COMMIT']
|
84
|
+
when :gitlab
|
85
|
+
ENV['CI_BUILD_REF']
|
83
86
|
end
|
84
87
|
end
|
85
88
|
|
86
89
|
# @private
|
87
90
|
def self._raw_commit_output(commit_sha)
|
88
|
-
format = GIT_FORMAT_LINES.join('%n')
|
91
|
+
format = GIT_FORMAT_LINES.join('%n') # "git show" format uses %n for newlines.
|
89
92
|
output = `git show --quiet #{commit_sha} --format="#{format}" 2> /dev/null`.strip
|
90
|
-
return if
|
93
|
+
return if $CHILD_STATUS.to_i != 0
|
91
94
|
output
|
92
95
|
end
|
93
96
|
|
@@ -114,9 +117,12 @@ module Percy
|
|
114
117
|
ENV['BRANCH_NAME']
|
115
118
|
when :buildkite
|
116
119
|
ENV['BUILDKITE_BRANCH']
|
120
|
+
when :gitlab
|
121
|
+
ENV['CI_BUILD_REF_NAME']
|
117
122
|
else
|
118
123
|
_raw_branch_output
|
119
124
|
end
|
125
|
+
|
120
126
|
if result == ''
|
121
127
|
STDERR.puts '[percy] Warning: not in a git repo, setting PERCY_BRANCH to "master".'
|
122
128
|
result = 'master'
|
@@ -138,7 +144,7 @@ module Percy
|
|
138
144
|
|
139
145
|
def self.repo
|
140
146
|
return ENV['PERCY_PROJECT'] if ENV['PERCY_PROJECT']
|
141
|
-
return ENV['PERCY_REPO_SLUG'] if ENV['PERCY_REPO_SLUG']
|
147
|
+
return ENV['PERCY_REPO_SLUG'] if ENV['PERCY_REPO_SLUG'] # Deprecated.
|
142
148
|
|
143
149
|
case current_ci
|
144
150
|
when :travis
|
@@ -150,15 +156,15 @@ module Percy
|
|
150
156
|
else
|
151
157
|
origin_url = _get_origin_url.strip
|
152
158
|
if origin_url == ''
|
153
|
-
raise Percy::Client::Environment::RepoNotFoundError
|
154
|
-
'No local git repository found. '
|
155
|
-
'You can manually set PERCY_PROJECT to fix this. See https://percy.io/docs'
|
159
|
+
raise Percy::Client::Environment::RepoNotFoundError,
|
160
|
+
'No local git repository found. ' \
|
161
|
+
'You can manually set PERCY_PROJECT to fix this. See https://percy.io/docs'
|
156
162
|
end
|
157
163
|
match = origin_url.match(Regexp.new('[:/]([^/]+\/[^/]+?)(\.git)?\Z'))
|
158
|
-
|
159
|
-
raise Percy::Client::Environment::RepoNotFoundError
|
160
|
-
"Could not determine repository name from URL: #{origin_url.inspect}\n"
|
161
|
-
|
164
|
+
unless match
|
165
|
+
raise Percy::Client::Environment::RepoNotFoundError,
|
166
|
+
"Could not determine repository name from URL: #{origin_url.inspect}\n" \
|
167
|
+
'You can manually set PERCY_PROJECT to fix this. See https://percy.io/docs'
|
162
168
|
end
|
163
169
|
match[1]
|
164
170
|
end
|
@@ -204,6 +210,8 @@ module Percy
|
|
204
210
|
ENV['SEMAPHORE_BUILD_NUMBER']
|
205
211
|
when :buildkite
|
206
212
|
ENV['BUILDKITE_BUILD_ID']
|
213
|
+
when :gitlab
|
214
|
+
ENV['CI_BUILD_ID']
|
207
215
|
end
|
208
216
|
end
|
209
217
|
|
@@ -4,7 +4,6 @@ require 'addressable/uri'
|
|
4
4
|
|
5
5
|
module Percy
|
6
6
|
class Client
|
7
|
-
|
8
7
|
# A simple data container object used to pass data to create_snapshot.
|
9
8
|
class Resource
|
10
9
|
attr_accessor :sha
|
@@ -48,7 +47,7 @@ module Percy
|
|
48
47
|
content_msg = content.nil? ? '' : "content.length: #{content.length}"
|
49
48
|
"<Resource #{sha} #{resource_url} is_root:#{!!is_root} #{mimetype} #{content_msg}>"
|
50
49
|
end
|
51
|
-
|
50
|
+
alias to_s inspect
|
52
51
|
end
|
53
52
|
|
54
53
|
module Resources
|
@@ -2,9 +2,9 @@ module Percy
|
|
2
2
|
class Client
|
3
3
|
module Snapshots
|
4
4
|
def create_snapshot(build_id, resources, options = {})
|
5
|
-
|
6
|
-
raise ArgumentError
|
7
|
-
'resources argument must be an iterable of Percy::Client::Resource objects'
|
5
|
+
unless resources.respond_to?(:each)
|
6
|
+
raise ArgumentError,
|
7
|
+
'resources argument must be an iterable of Percy::Client::Resource objects'
|
8
8
|
end
|
9
9
|
|
10
10
|
widths = options[:widths] || config.default_widths
|
@@ -18,7 +18,7 @@ module Percy
|
|
18
18
|
},
|
19
19
|
'relationships' => {
|
20
20
|
'resources' => {
|
21
|
-
'data' => resources.map
|
21
|
+
'data' => resources.map(&:serialize),
|
22
22
|
},
|
23
23
|
},
|
24
24
|
},
|
data/lib/percy/client/version.rb
CHANGED
@@ -7,7 +7,8 @@ RSpec.describe Percy::Client::Builds, :vcr do
|
|
7
7
|
# Whitebox test to check POST data.
|
8
8
|
expect_any_instance_of(Percy::Client).to \
|
9
9
|
receive(:post)
|
10
|
-
.with(
|
10
|
+
.with(
|
11
|
+
/\/api\/v1\/repos\/fotinakis\/percy-examples\/builds\//,
|
11
12
|
'data' => {
|
12
13
|
'type' => 'builds',
|
13
14
|
'attributes' => {
|
@@ -25,7 +26,7 @@ RSpec.describe Percy::Client::Builds, :vcr do
|
|
25
26
|
'parallel-total-shards' => nil,
|
26
27
|
},
|
27
28
|
},
|
28
|
-
|
29
|
+
).and_call_original
|
29
30
|
|
30
31
|
build = Percy.create_build('fotinakis/percy-examples')
|
31
32
|
expect(build).to be
|
@@ -73,7 +74,8 @@ RSpec.describe Percy::Client::Builds, :vcr do
|
|
73
74
|
# Whitebox test to check POST data.
|
74
75
|
expect_any_instance_of(Percy::Client).to \
|
75
76
|
receive(:post)
|
76
|
-
.with(
|
77
|
+
.with(
|
78
|
+
/\/api\/v1\/repos\/fotinakis\/percy-examples\/builds\//,
|
77
79
|
'data' => {
|
78
80
|
'type' => 'builds',
|
79
81
|
'attributes' => {
|
@@ -91,7 +93,7 @@ RSpec.describe Percy::Client::Builds, :vcr do
|
|
91
93
|
'parallel-total-shards' => 4,
|
92
94
|
},
|
93
95
|
},
|
94
|
-
|
96
|
+
)
|
95
97
|
|
96
98
|
Percy.create_build('fotinakis/percy-examples')
|
97
99
|
end
|
@@ -112,7 +114,7 @@ RSpec.describe Percy::Client::Builds, :vcr do
|
|
112
114
|
it 'finalizes a build' do
|
113
115
|
build = Percy.create_build('fotinakis/percy-examples')
|
114
116
|
result = Percy.finalize_build(build['data']['id'])
|
115
|
-
expect(result).to eq(
|
117
|
+
expect(result).to eq('success' => true)
|
116
118
|
end
|
117
119
|
end
|
118
120
|
end
|
@@ -8,7 +8,7 @@ RSpec.describe Percy::Client::Connection do
|
|
8
8
|
it 'performs a GET request to the api_url and parses response' do
|
9
9
|
stub_request(:get, "#{Percy.config.api_url}/test").to_return(body: {foo: true}.to_json)
|
10
10
|
data = Percy.client.get("#{Percy.config.api_url}/test")
|
11
|
-
expect(data).to eq(
|
11
|
+
expect(data).to eq('foo' => true)
|
12
12
|
end
|
13
13
|
it 'raises customized timeout errors' do
|
14
14
|
stub_request(:get, "#{Percy.config.api_url}/test").to_raise(Faraday::TimeoutError)
|
@@ -28,7 +28,7 @@ RSpec.describe Percy::Client::Connection do
|
|
28
28
|
.then.to_return(body: {foo: true}.to_json, status: 200)
|
29
29
|
|
30
30
|
data = Percy.client.get("#{Percy.config.api_url}/test")
|
31
|
-
expect(data).to eq(
|
31
|
+
expect(data).to eq('foo' => true)
|
32
32
|
end
|
33
33
|
it 'raises error after 3 retries' do
|
34
34
|
stub_request(:get, "#{Percy.config.api_url}/test")
|
@@ -42,7 +42,7 @@ RSpec.describe Percy::Client::Connection do
|
|
42
42
|
it 'performs a POST request to the api_url and parses response' do
|
43
43
|
stub_request(:post, "#{Percy.config.api_url}/test").to_return(body: {foo: true}.to_json)
|
44
44
|
data = Percy.client.post("#{Percy.config.api_url}/test", {})
|
45
|
-
expect(data).to eq(
|
45
|
+
expect(data).to eq('foo' => true)
|
46
46
|
end
|
47
47
|
it 'raises customized timeout errors' do
|
48
48
|
stub_request(:post, "#{Percy.config.api_url}/test").to_raise(Faraday::TimeoutError)
|
@@ -101,7 +101,7 @@ RSpec.describe Percy::Client::Connection do
|
|
101
101
|
.then.to_return(body: {foo: true}.to_json, status: 200)
|
102
102
|
|
103
103
|
data = Percy.client.post("#{Percy.config.api_url}/test", {})
|
104
|
-
expect(data).to eq(
|
104
|
+
expect(data).to eq('foo' => true)
|
105
105
|
end
|
106
106
|
it 'raises error after 3 retries' do
|
107
107
|
stub_request(:post, "#{Percy.config.api_url}/test")
|
@@ -6,7 +6,7 @@ RSpec.describe Percy::Client::Environment do
|
|
6
6
|
ENV['PERCY_TARGET_BRANCH'] = nil
|
7
7
|
ENV['PERCY_PULL_REQUEST'] = nil
|
8
8
|
ENV['PERCY_PROJECT'] = nil
|
9
|
-
ENV['PERCY_REPO_SLUG'] = nil
|
9
|
+
ENV['PERCY_REPO_SLUG'] = nil # Deprecated.
|
10
10
|
ENV['PERCY_PARALLEL_NONCE'] = nil
|
11
11
|
ENV['PERCY_PARALLEL_TOTAL'] = nil
|
12
12
|
|
@@ -51,7 +51,7 @@ RSpec.describe Percy::Client::Environment do
|
|
51
51
|
ENV['DRONE_BRANCH'] = nil
|
52
52
|
ENV['CI_PULL_REQUEST'] = nil
|
53
53
|
|
54
|
-
# Unset Semaphore CI vars
|
54
|
+
# Unset Semaphore CI vars.
|
55
55
|
ENV['CI'] = nil
|
56
56
|
ENV['SEMAPHORE'] = nil
|
57
57
|
ENV['REVISION'] = nil
|
@@ -61,12 +61,18 @@ RSpec.describe Percy::Client::Environment do
|
|
61
61
|
ENV['SEMAPHORE_CURRENT_THREAD'] = nil
|
62
62
|
ENV['PULL_REQUEST_NUMBER'] = nil
|
63
63
|
|
64
|
-
# Unset Buildkite CI vars
|
64
|
+
# Unset Buildkite CI vars.
|
65
65
|
ENV['BUILDKITE'] = nil
|
66
66
|
ENV['BUILDKITE_COMMIT'] = nil
|
67
67
|
ENV['BUILDKITE_BRANCH'] = nil
|
68
68
|
ENV['BUILDKITE_PULL_REQUEST'] = nil
|
69
69
|
ENV['BUILDKITE_BUILD_ID'] = nil
|
70
|
+
|
71
|
+
# Unset Gitlab CI vars.
|
72
|
+
ENV['GITLAB_CI'] = nil
|
73
|
+
ENV['CI_BUILD_REF'] = nil
|
74
|
+
ENV['CI_BUILD_REF_NAME'] = nil
|
75
|
+
ENV['CI_BUILD_ID'] = nil
|
70
76
|
end
|
71
77
|
|
72
78
|
before(:each) do
|
@@ -183,7 +189,8 @@ RSpec.describe Percy::Client::Environment do
|
|
183
189
|
it 'errors if unable to parse local repo name' do
|
184
190
|
expect(Percy::Client::Environment).to receive(:_get_origin_url).once.and_return('foo')
|
185
191
|
expect { Percy::Client::Environment.repo }.to raise_error(
|
186
|
-
Percy::Client::Environment::RepoNotFoundError
|
192
|
+
Percy::Client::Environment::RepoNotFoundError,
|
193
|
+
)
|
187
194
|
end
|
188
195
|
end
|
189
196
|
describe '#parallel_nonce' do
|
@@ -301,7 +308,7 @@ RSpec.describe Percy::Client::Environment do
|
|
301
308
|
ENV['CI_NAME'] = 'codeship'
|
302
309
|
ENV['CI_BRANCH'] = 'codeship-branch'
|
303
310
|
ENV['CI_BUILD_NUMBER'] = 'codeship-build-number'
|
304
|
-
ENV['CI_PULL_REQUEST'] = 'false'
|
311
|
+
ENV['CI_PULL_REQUEST'] = 'false' # This is always false on Codeship, unfortunately.
|
305
312
|
ENV['CI_COMMIT_ID'] = 'codeship-commit-sha'
|
306
313
|
ENV['CI_NODE_TOTAL'] = ''
|
307
314
|
end
|
@@ -385,7 +392,7 @@ RSpec.describe Percy::Client::Environment do
|
|
385
392
|
expect(Percy::Client::Environment.branch).to eq('buildkite-branch')
|
386
393
|
expect(Percy::Client::Environment._commit_sha).to eq('buildkite-commit-sha')
|
387
394
|
expect(Percy::Client::Environment.pull_request_number).to be_nil
|
388
|
-
expect(Percy::Client::Environment.repo).to eq('percy/percy-client')
|
395
|
+
expect(Percy::Client::Environment.repo).to eq('percy/percy-client') # From git, not env.
|
389
396
|
expect(Percy::Client::Environment.parallel_nonce).to eq('buildkite-build-id')
|
390
397
|
expect(Percy::Client::Environment.parallel_total_shards).to be_nil
|
391
398
|
end
|
@@ -406,6 +413,25 @@ RSpec.describe Percy::Client::Environment do
|
|
406
413
|
end
|
407
414
|
end
|
408
415
|
end
|
416
|
+
context 'in Gitlab CI' do
|
417
|
+
before(:each) do
|
418
|
+
ENV['GITLAB_CI'] = 'yes'
|
419
|
+
ENV['CI_BUILD_REF'] = 'gitlab-commit-sha'
|
420
|
+
ENV['CI_BUILD_REF_NAME'] = 'gitlab-branch'
|
421
|
+
ENV['CI_BUILD_ID'] = 'gitlab-build-id'
|
422
|
+
end
|
423
|
+
|
424
|
+
it 'has the correct properties' do
|
425
|
+
expect(Percy::Client::Environment.current_ci).to eq(:gitlab)
|
426
|
+
expect(Percy::Client::Environment.branch).to eq('gitlab-branch')
|
427
|
+
expect(Percy::Client::Environment._commit_sha).to eq('gitlab-commit-sha')
|
428
|
+
expect(Percy::Client::Environment.pull_request_number).to be_nil
|
429
|
+
expect(Percy::Client::Environment.parallel_nonce).to eq('gitlab-build-id')
|
430
|
+
expect(Percy::Client::Environment.parallel_total_shards).to be_nil
|
431
|
+
# TODO: repo is deprecated, remove this:
|
432
|
+
expect(Percy::Client::Environment.repo).to eq('percy/percy-client') # From git, not env.
|
433
|
+
end
|
434
|
+
end
|
409
435
|
describe 'local git repo methods' do
|
410
436
|
describe '#commit' do
|
411
437
|
it 'returns current local commit data' do
|
@@ -7,7 +7,7 @@ RSpec.describe Percy::Client::Resources, :vcr do
|
|
7
7
|
describe 'Percy::Client::Resource' do
|
8
8
|
it 'can be initialized with minimal data' do
|
9
9
|
resource = Percy::Client::Resource.new('/foo.html', sha: sha)
|
10
|
-
expect(resource.serialize).to eq(
|
10
|
+
expect(resource.serialize).to eq(
|
11
11
|
'type' => 'resources',
|
12
12
|
'id' => sha,
|
13
13
|
'attributes' => {
|
@@ -15,7 +15,7 @@ RSpec.describe Percy::Client::Resources, :vcr do
|
|
15
15
|
'mimetype' => nil,
|
16
16
|
'is-root' => nil,
|
17
17
|
},
|
18
|
-
|
18
|
+
)
|
19
19
|
end
|
20
20
|
it 'can be initialized with all data' do
|
21
21
|
resource = Percy::Client::Resource.new(
|
@@ -25,7 +25,7 @@ RSpec.describe Percy::Client::Resources, :vcr do
|
|
25
25
|
mimetype: 'text/html',
|
26
26
|
content: content,
|
27
27
|
)
|
28
|
-
expect(resource.serialize).to eq(
|
28
|
+
expect(resource.serialize).to eq(
|
29
29
|
'type' => 'resources',
|
30
30
|
'id' => sha,
|
31
31
|
'attributes' => {
|
@@ -33,7 +33,7 @@ RSpec.describe Percy::Client::Resources, :vcr do
|
|
33
33
|
'mimetype' => 'text/html',
|
34
34
|
'is-root' => true,
|
35
35
|
},
|
36
|
-
|
36
|
+
)
|
37
37
|
end
|
38
38
|
it 'errors if not given sha or content' do
|
39
39
|
expect { Percy::Client::Resource.new('/foo.html') }.to raise_error(ArgumentError)
|
@@ -12,7 +12,8 @@ RSpec.describe Percy::Client::Snapshots, :vcr do
|
|
12
12
|
# Whitebox test to catch POST data that is sent but is not returned in the API response.
|
13
13
|
expect_any_instance_of(Percy::Client).to \
|
14
14
|
receive(:post)
|
15
|
-
.with(
|
15
|
+
.with(
|
16
|
+
/snapshots\/$/,
|
16
17
|
'data' => {
|
17
18
|
'type' => 'snapshots',
|
18
19
|
'attributes' => {
|
@@ -45,7 +46,7 @@ RSpec.describe Percy::Client::Snapshots, :vcr do
|
|
45
46
|
},
|
46
47
|
},
|
47
48
|
},
|
48
|
-
|
49
|
+
)
|
49
50
|
.and_call_original
|
50
51
|
|
51
52
|
snapshot = Percy.create_snapshot(
|
@@ -70,7 +71,8 @@ RSpec.describe Percy::Client::Snapshots, :vcr do
|
|
70
71
|
# Whitebox test to catch POST data that is sent but is not returned in the API response.
|
71
72
|
expect_any_instance_of(Percy::Client).to \
|
72
73
|
receive(:post)
|
73
|
-
.with(
|
74
|
+
.with(
|
75
|
+
/snapshots\/$/,
|
74
76
|
'data' => {
|
75
77
|
'type' => 'snapshots',
|
76
78
|
'attributes' => {
|
@@ -103,7 +105,7 @@ RSpec.describe Percy::Client::Snapshots, :vcr do
|
|
103
105
|
},
|
104
106
|
},
|
105
107
|
},
|
106
|
-
|
108
|
+
)
|
107
109
|
.and_call_original
|
108
110
|
|
109
111
|
snapshot = Percy.create_snapshot(
|
@@ -135,7 +137,7 @@ RSpec.describe Percy::Client::Snapshots, :vcr do
|
|
135
137
|
snapshot = Percy.create_snapshot(build['data']['id'], resources, name: 'homepage')
|
136
138
|
|
137
139
|
result = Percy.finalize_snapshot(snapshot['data']['id'])
|
138
|
-
expect(result).to eq(
|
140
|
+
expect(result).to eq('success' => true)
|
139
141
|
end
|
140
142
|
end
|
141
143
|
end
|
@@ -2,17 +2,19 @@ RSpec.describe Percy::Config do
|
|
2
2
|
let(:config) { described_class.new }
|
3
3
|
|
4
4
|
it 'returns the correct defaults' do
|
5
|
-
expect(config.keys).to eq(
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
5
|
+
expect(config.keys).to eq(
|
6
|
+
[
|
7
|
+
:access_token,
|
8
|
+
:api_url,
|
9
|
+
:debug,
|
10
|
+
:repo,
|
11
|
+
:default_widths,
|
12
|
+
],
|
13
|
+
)
|
12
14
|
expect(config.access_token).to be_nil
|
13
15
|
expect(config.api_url).to eq(ENV['PERCY_API'])
|
14
16
|
expect(config.debug).to eq(false)
|
15
17
|
expect(config.repo).to eq('percy/percy-client')
|
16
18
|
expect(config.default_widths).to eq([])
|
17
19
|
end
|
18
|
-
end
|
20
|
+
end
|
data/spec/lib/percy_spec.rb
CHANGED
data/spec/support/vcr_setup.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: percy-client
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.10.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Perceptual Inc.
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-
|
11
|
+
date: 2017-02-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -131,9 +131,10 @@ extra_rdoc_files: []
|
|
131
131
|
files:
|
132
132
|
- ".gitignore"
|
133
133
|
- ".rspec"
|
134
|
+
- ".rubocop.yml"
|
135
|
+
- ".rubocop_todo.yml"
|
134
136
|
- ".travis.yml"
|
135
137
|
- Gemfile
|
136
|
-
- Gemfile.lock
|
137
138
|
- Guardfile
|
138
139
|
- LICENSE
|
139
140
|
- README.md
|
@@ -187,7 +188,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
187
188
|
version: '0'
|
188
189
|
requirements: []
|
189
190
|
rubyforge_project:
|
190
|
-
rubygems_version: 2.
|
191
|
+
rubygems_version: 2.4.8
|
191
192
|
signing_key:
|
192
193
|
specification_version: 4
|
193
194
|
summary: Percy::Client
|