diffux_ci 0.4.3 → 0.4.4
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/bin/diffux +11 -14
- data/lib/diffux_ci/action.rb +33 -0
- data/lib/{diffux_ci-diffs.html.erb → diffux_ci/diffs.html.erb} +0 -0
- data/lib/diffux_ci/logger.rb +40 -0
- data/lib/{public → diffux_ci/public}/diffux_ci-runner.js +1 -1
- data/lib/{public → diffux_ci/public}/diffux_ci-styles.css +0 -0
- data/lib/{diffux_ci_runner.rb → diffux_ci/runner.rb} +26 -24
- data/lib/diffux_ci/server.rb +53 -0
- data/lib/diffux_ci/uploader.rb +70 -0
- data/lib/diffux_ci/utils.rb +80 -0
- data/lib/{diffux_ci_version.rb → diffux_ci/version.rb} +1 -1
- data/lib/{views → diffux_ci/views}/debug.erb +0 -0
- data/lib/{views → diffux_ci/views}/index.erb +0 -0
- data/lib/{views → diffux_ci/views}/review.erb +0 -0
- data/lib/diffux_ci.rb +5 -0
- metadata +20 -18
- data/lib/diffux_ci_action.rb +0 -31
- data/lib/diffux_ci_server.rb +0 -53
- data/lib/diffux_ci_uploader.rb +0 -69
- data/lib/diffux_ci_utils.rb +0 -78
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 655dc75096ce2012e0e6f1ccd231d57c086d4d7b
|
4
|
+
data.tar.gz: 8f3a8617e9b91e630efd7c8ba79b323dcff33c2f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f6f420363c7def23d0115ebc21a12782f68c2863a7888a423cc15342a4c86d882f00779b379b34b3b585bbe36ead7033c98f042f47f537cc4201286af60ad6eb
|
7
|
+
data.tar.gz: 9497fc103436f030f9b2978496707e6ad4be3de35fc6cbfc7da9650203e149b8359f6eeaffc26402a59006829cc00cd7dd60647401b4338c60286ef8a5279c02
|
data/bin/diffux
CHANGED
@@ -1,9 +1,6 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
require '
|
4
|
-
require 'diffux_ci_action'
|
5
|
-
require 'diffux_ci_uploader'
|
6
|
-
require 'diffux_ci_version'
|
3
|
+
require 'diffux_ci'
|
7
4
|
require 'fileutils'
|
8
5
|
|
9
6
|
help_text = <<-EOS
|
@@ -24,22 +21,22 @@ case action
|
|
24
21
|
when 'run'
|
25
22
|
Thread.abort_on_exception = true
|
26
23
|
Thread.new do
|
27
|
-
require '
|
24
|
+
require 'diffux_ci/runner'
|
28
25
|
exit
|
29
26
|
end
|
30
|
-
require '
|
27
|
+
require 'diffux_ci/server'
|
31
28
|
|
32
29
|
when 'debug'
|
33
|
-
system 'open',
|
34
|
-
require '
|
30
|
+
system 'open', DiffuxCI::Utils.construct_url('/debug')
|
31
|
+
require 'diffux_ci/server'
|
35
32
|
|
36
33
|
when 'review'
|
37
|
-
system 'open',
|
38
|
-
require '
|
34
|
+
system 'open', DiffuxCI::Utils.construct_url('/review')
|
35
|
+
require 'diffux_ci/server'
|
39
36
|
|
40
37
|
when 'clean'
|
41
|
-
if File.directory?
|
42
|
-
FileUtils.remove_entry_secure
|
38
|
+
if File.directory? DiffuxCI::Utils.config['snapshots_folder']
|
39
|
+
FileUtils.remove_entry_secure DiffuxCI::Utils.config['snapshots_folder']
|
43
40
|
end
|
44
41
|
|
45
42
|
when 'approve', 'reject'
|
@@ -47,11 +44,11 @@ when 'approve', 'reject'
|
|
47
44
|
abort 'Missing example description' unless example_description
|
48
45
|
viewport_name = ARGV[2]
|
49
46
|
abort 'Missing viewport name' unless viewport_name
|
50
|
-
|
47
|
+
DiffuxCI::Action.new(example_description, viewport_name).send(action)
|
51
48
|
|
52
49
|
when 'upload_diffs'
|
53
50
|
# `upload_diffs` returns a URL to a static html file
|
54
|
-
puts
|
51
|
+
puts DiffuxCI::Uploader.new.upload_diffs
|
55
52
|
|
56
53
|
when '--version'
|
57
54
|
puts "diffux_ci version #{DiffuxCI::VERSION}"
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'diffux_ci/utils'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module DiffuxCI
|
5
|
+
class Action
|
6
|
+
def initialize(example_description, viewport_name)
|
7
|
+
@example_description = example_description
|
8
|
+
@viewport_name = viewport_name
|
9
|
+
end
|
10
|
+
|
11
|
+
def approve
|
12
|
+
diff_path = DiffuxCI::Utils.path_to(
|
13
|
+
@example_description, @viewport_name, 'diff.png')
|
14
|
+
baseline_path = DiffuxCI::Utils.path_to(
|
15
|
+
@example_description, @viewport_name, 'baseline.png')
|
16
|
+
candidate_path = DiffuxCI::Utils.path_to(
|
17
|
+
@example_description, @viewport_name, 'candidate.png')
|
18
|
+
|
19
|
+
FileUtils.rm(diff_path, force: true)
|
20
|
+
FileUtils.mv(candidate_path, baseline_path) if File.exist? candidate_path
|
21
|
+
end
|
22
|
+
|
23
|
+
def reject
|
24
|
+
diff_path = DiffuxCI::Utils.path_to(
|
25
|
+
@example_description, @viewport_name, 'diff.png')
|
26
|
+
candidate_path = DiffuxCI::Utils.path_to(
|
27
|
+
@example_description, @viewport_name, 'candidate.png')
|
28
|
+
|
29
|
+
FileUtils.rm(diff_path, force: true)
|
30
|
+
FileUtils.rm(candidate_path, force: true)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
File without changes
|
@@ -0,0 +1,40 @@
|
|
1
|
+
module DiffuxCI
|
2
|
+
# Used for all CLI output
|
3
|
+
class Logger
|
4
|
+
# @param out [IO] the output destination
|
5
|
+
def initialize(out = STDOUT)
|
6
|
+
@out = out
|
7
|
+
end
|
8
|
+
|
9
|
+
# Print the specified output
|
10
|
+
# @param str [String] the output to send
|
11
|
+
# @param newline [Boolean] whether to append a newline
|
12
|
+
def log(str, newline = true)
|
13
|
+
@out.print(str)
|
14
|
+
@out.print("\n") if newline
|
15
|
+
end
|
16
|
+
|
17
|
+
# Mark the string in cyan
|
18
|
+
# @param str [String] the str to format
|
19
|
+
def cyan(str)
|
20
|
+
color(36, str)
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
# Whether this logger is outputting to a TTY
|
26
|
+
#
|
27
|
+
# @return [Boolean]
|
28
|
+
def tty?
|
29
|
+
@out.respond_to?(:tty?) && @out.tty?
|
30
|
+
end
|
31
|
+
|
32
|
+
# Mark the string in a color
|
33
|
+
# @see http://ascii-table.com/ansi-escape-sequences.php
|
34
|
+
# @param color_code [Number] the ANSI color code
|
35
|
+
# @param str [String] the str to format
|
36
|
+
def color(color_code, str)
|
37
|
+
tty? ? str : "\033[#{color_code}m#{str}\033[0m"
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
@@ -101,7 +101,7 @@ window.diffux = {
|
|
101
101
|
*
|
102
102
|
* @param {String} exampleDescription
|
103
103
|
* @param {Function} doneFunc injected by driver.execute_async_script in
|
104
|
-
*
|
104
|
+
* diffux_ci/runner.rb
|
105
105
|
*/
|
106
106
|
renderExample: function(exampleDescription, doneFunc) {
|
107
107
|
try {
|
File without changes
|
@@ -6,12 +6,12 @@ require 'diffux_core/snapshot_comparison_image/before'
|
|
6
6
|
require 'diffux_core/snapshot_comparison_image/overlayed'
|
7
7
|
require 'diffux_core/snapshot_comparison_image/after'
|
8
8
|
require 'oily_png'
|
9
|
-
require '
|
9
|
+
require 'diffux_ci'
|
10
10
|
require 'fileutils'
|
11
11
|
require 'yaml'
|
12
12
|
|
13
13
|
def resolve_viewports(example)
|
14
|
-
configured_viewports =
|
14
|
+
configured_viewports = DiffuxCI::Utils.config['viewports']
|
15
15
|
|
16
16
|
viewports =
|
17
17
|
example['options']['viewports'] || [configured_viewports.first.first]
|
@@ -24,7 +24,7 @@ end
|
|
24
24
|
def init_driver
|
25
25
|
tries = 0
|
26
26
|
begin
|
27
|
-
driver = Selenium::WebDriver.for
|
27
|
+
driver = Selenium::WebDriver.for DiffuxCI::Utils.config['driver'].to_sym
|
28
28
|
rescue Selenium::WebDriver::Error::WebDriverError => e
|
29
29
|
# "unable to obtain stable firefox connection in 60 seconds"
|
30
30
|
#
|
@@ -40,10 +40,11 @@ def init_driver
|
|
40
40
|
driver
|
41
41
|
end
|
42
42
|
|
43
|
+
log = DiffuxCI::Logger.new(STDOUT)
|
43
44
|
driver = init_driver
|
44
45
|
|
45
46
|
begin
|
46
|
-
driver.navigate.to
|
47
|
+
driver.navigate.to DiffuxCI::Utils.construct_url('/')
|
47
48
|
|
48
49
|
# Check for errors during startup
|
49
50
|
errors = driver.execute_script('return window.diffux.errors;')
|
@@ -80,21 +81,21 @@ begin
|
|
80
81
|
viewport = example_by_viewport[:viewport]
|
81
82
|
examples = example_by_viewport[:examples]
|
82
83
|
|
83
|
-
|
84
|
+
log.log "#{viewport['name']} (#{viewport['width']}x#{viewport['height']})"
|
84
85
|
|
85
86
|
# Resize window to the right size before rendering
|
86
87
|
driver.manage.window.resize_to(viewport['width'], viewport['height'])
|
87
88
|
|
88
89
|
examples.each do |example|
|
89
90
|
if example == examples.last
|
90
|
-
|
91
|
+
log.log '└─ ', false
|
91
92
|
else
|
92
|
-
|
93
|
+
log.log '├─ ', false
|
93
94
|
end
|
94
95
|
description = example['description']
|
95
|
-
|
96
|
+
log.log " #{description} ", false
|
96
97
|
|
97
|
-
|
98
|
+
log.log '.', false
|
98
99
|
|
99
100
|
# Render the example
|
100
101
|
|
@@ -114,20 +115,20 @@ begin
|
|
114
115
|
window.diffux.renderExample(arguments[0], doneFunc);
|
115
116
|
EOS
|
116
117
|
rendered = driver.execute_async_script(script, description)
|
117
|
-
|
118
|
+
log.log '.', false
|
118
119
|
|
119
120
|
if rendered['error']
|
120
121
|
fail <<-EOS
|
121
122
|
Error while rendering "#{description}" @#{viewport['name']}:
|
122
123
|
#{rendered['error']}
|
123
124
|
Debug by pointing your browser to
|
124
|
-
#{
|
125
|
+
#{DiffuxCI::Utils.construct_url('/', description: description)}
|
125
126
|
EOS
|
126
127
|
end
|
127
128
|
|
128
129
|
# Crop the screenshot to the size of the rendered element
|
129
130
|
screenshot = ChunkyPNG::Image.from_blob(driver.screenshot_as(:png))
|
130
|
-
|
131
|
+
log.log '.', false
|
131
132
|
|
132
133
|
# In our JavaScript we are rounding up, which can sometimes give us a
|
133
134
|
# dimensions that are larger than the screenshot dimensions. We need to
|
@@ -146,11 +147,11 @@ begin
|
|
146
147
|
rendered['top'],
|
147
148
|
crop_width,
|
148
149
|
crop_height)
|
149
|
-
|
150
|
+
log.log '.', false
|
150
151
|
end
|
151
152
|
|
152
153
|
# Run the diff if needed
|
153
|
-
baseline_path =
|
154
|
+
baseline_path = DiffuxCI::Utils.path_to(
|
154
155
|
description, viewport['name'], 'baseline.png')
|
155
156
|
|
156
157
|
if File.exist? baseline_path
|
@@ -160,23 +161,24 @@ begin
|
|
160
161
|
ChunkyPNG::Image.from_file(baseline_path),
|
161
162
|
screenshot
|
162
163
|
).compare!
|
163
|
-
|
164
|
+
log.log '.', false
|
164
165
|
|
165
166
|
if comparison[:diff_image]
|
166
167
|
# There was a visual difference between the new snapshot and the
|
167
168
|
# baseline, so we want to write the diff image and the new snapshot
|
168
169
|
# image to disk. This will allow it to be reviewed by someone.
|
169
|
-
diff_path =
|
170
|
+
diff_path = DiffuxCI::Utils.path_to(
|
170
171
|
description, viewport['name'], 'diff.png')
|
171
172
|
comparison[:diff_image].save(diff_path, :fast_rgba)
|
172
|
-
|
173
|
+
log.log '.', false
|
173
174
|
|
174
|
-
candidate_path =
|
175
|
+
candidate_path = DiffuxCI::Utils.path_to(
|
175
176
|
description, viewport['name'], 'candidate.png')
|
176
177
|
screenshot.save(candidate_path, :fast_rgba)
|
177
|
-
|
178
|
+
log.log '.', false
|
178
179
|
|
179
|
-
|
180
|
+
percent = comparison[:diff_in_percent].round(1)
|
181
|
+
log.log log.cyan(" #{percent}% (#{candidate_path})")
|
180
182
|
result_summary[:diff_examples] << {
|
181
183
|
description: description,
|
182
184
|
viewport: viewport['name']
|
@@ -184,7 +186,7 @@ begin
|
|
184
186
|
else
|
185
187
|
# No visual difference was found, so we don't need to do any more
|
186
188
|
# work.
|
187
|
-
|
189
|
+
log.log ' No diff.'
|
188
190
|
result_summary[:okay_examples] << {
|
189
191
|
description: description,
|
190
192
|
viewport: viewport['name']
|
@@ -199,8 +201,8 @@ begin
|
|
199
201
|
FileUtils.mkdir_p(dirname)
|
200
202
|
end
|
201
203
|
screenshot.save(baseline_path, :fast_rgba)
|
202
|
-
|
203
|
-
|
204
|
+
log.log '.', false
|
205
|
+
log.log " First snapshot created (#{baseline_path})"
|
204
206
|
result_summary[:new_examples] << {
|
205
207
|
description: description,
|
206
208
|
viewport: viewport['name']
|
@@ -209,7 +211,7 @@ begin
|
|
209
211
|
end
|
210
212
|
end
|
211
213
|
|
212
|
-
result_summary_file = File.join(
|
214
|
+
result_summary_file = File.join(DiffuxCI::Utils.config['snapshots_folder'],
|
213
215
|
'result_summary.yaml')
|
214
216
|
File.open(result_summary_file, 'w') do |file|
|
215
217
|
file.write result_summary.to_yaml
|
@@ -0,0 +1,53 @@
|
|
1
|
+
require 'sinatra/base'
|
2
|
+
require 'yaml'
|
3
|
+
|
4
|
+
module DiffuxCI
|
5
|
+
class Server < Sinatra::Base
|
6
|
+
configure do
|
7
|
+
enable :static
|
8
|
+
set :port, DiffuxCI::Utils.config['port']
|
9
|
+
end
|
10
|
+
|
11
|
+
helpers do
|
12
|
+
def h(text)
|
13
|
+
Rack::Utils.escape_html(text)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
get '/' do
|
18
|
+
@config = DiffuxCI::Utils.config
|
19
|
+
erb :index
|
20
|
+
end
|
21
|
+
|
22
|
+
get '/debug' do
|
23
|
+
@config = DiffuxCI::Utils.config
|
24
|
+
erb :debug
|
25
|
+
end
|
26
|
+
|
27
|
+
get '/review' do
|
28
|
+
@snapshots = DiffuxCI::Utils.current_snapshots
|
29
|
+
erb :review
|
30
|
+
end
|
31
|
+
|
32
|
+
get '/resource' do
|
33
|
+
file = params[:file]
|
34
|
+
if file.start_with? 'http'
|
35
|
+
redirect file
|
36
|
+
else
|
37
|
+
send_file file
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
post '/reject' do
|
42
|
+
DiffuxCI::Action.new(params[:description], params[:viewport]).reject
|
43
|
+
redirect back
|
44
|
+
end
|
45
|
+
|
46
|
+
post '/approve' do
|
47
|
+
DiffuxCI::Action.new(params[:description], params[:viewport]).approve
|
48
|
+
redirect back
|
49
|
+
end
|
50
|
+
|
51
|
+
run!
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 's3'
|
2
|
+
require 'securerandom'
|
3
|
+
|
4
|
+
module DiffuxCI
|
5
|
+
class Uploader
|
6
|
+
def initialize
|
7
|
+
@s3_access_key_id = DiffuxCI::Utils.config['s3_access_key_id']
|
8
|
+
@s3_secret_access_key = DiffuxCI::Utils.config['s3_secret_access_key']
|
9
|
+
@s3_bucket_name = DiffuxCI::Utils.config['s3_bucket_name']
|
10
|
+
end
|
11
|
+
|
12
|
+
def upload_diffs
|
13
|
+
result_summary = YAML.load(File.read(File.join(
|
14
|
+
DiffuxCI::Utils.config['snapshots_folder'], 'result_summary.yaml')))
|
15
|
+
|
16
|
+
return [] if result_summary[:diff_examples].empty? &&
|
17
|
+
result_summary[:new_examples].empty?
|
18
|
+
|
19
|
+
bucket = find_or_build_bucket
|
20
|
+
dir = SecureRandom.uuid
|
21
|
+
|
22
|
+
diff_images = result_summary[:diff_examples].map do |diff|
|
23
|
+
image = bucket.objects.build(
|
24
|
+
"#{dir}/#{diff[:description]}_#{diff[:viewport]}.png")
|
25
|
+
image.content = open(DiffuxCI::Utils.path_to(diff[:description],
|
26
|
+
diff[:viewport],
|
27
|
+
'diff.png'))
|
28
|
+
image.content_type = 'image/png'
|
29
|
+
image.save
|
30
|
+
diff[:url] = image.url
|
31
|
+
diff
|
32
|
+
end
|
33
|
+
|
34
|
+
new_images = result_summary[:new_examples].map do |example|
|
35
|
+
image = bucket.objects.build(
|
36
|
+
"#{dir}/#{example[:description]}_#{example[:viewport]}.png")
|
37
|
+
image.content = open(DiffuxCI::Utils.path_to(example[:description],
|
38
|
+
example[:viewport],
|
39
|
+
'baseline.png'))
|
40
|
+
image.content_type = 'image/png'
|
41
|
+
image.save
|
42
|
+
example[:url] = image.url
|
43
|
+
example
|
44
|
+
end
|
45
|
+
|
46
|
+
html = bucket.objects.build("#{dir}/index.html")
|
47
|
+
path = File.expand_path(
|
48
|
+
File.join(File.dirname(__FILE__), 'diffs.html.erb'))
|
49
|
+
html.content = ERB.new(File.read(path)).result(binding)
|
50
|
+
html.content_type = 'text/html'
|
51
|
+
html.save
|
52
|
+
html.url
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
|
57
|
+
def find_or_build_bucket
|
58
|
+
service = S3::Service.new(access_key_id: @s3_access_key_id,
|
59
|
+
secret_access_key: @s3_secret_access_key)
|
60
|
+
bucket = service.buckets.find(@s3_bucket_name)
|
61
|
+
|
62
|
+
if bucket.nil?
|
63
|
+
bucket = service.buckets.build(@s3_bucket_name)
|
64
|
+
bucket.save(location: :us)
|
65
|
+
end
|
66
|
+
|
67
|
+
bucket
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'yaml'
|
2
|
+
require 'erb'
|
3
|
+
require 'uri'
|
4
|
+
require 'base64'
|
5
|
+
|
6
|
+
module DiffuxCI
|
7
|
+
class Utils
|
8
|
+
def self.config
|
9
|
+
@@config ||= {
|
10
|
+
'snapshots_folder' => './snapshots',
|
11
|
+
'source_files' => [],
|
12
|
+
'stylesheets' => [],
|
13
|
+
'port' => 4567,
|
14
|
+
'driver' => :firefox,
|
15
|
+
'viewports' => {
|
16
|
+
'large' => {
|
17
|
+
'width' => 1024,
|
18
|
+
'height' => 768
|
19
|
+
},
|
20
|
+
'medium' => {
|
21
|
+
'width' => 640,
|
22
|
+
'height' => 888
|
23
|
+
},
|
24
|
+
'small' => {
|
25
|
+
'width' => 320,
|
26
|
+
'height' => 444
|
27
|
+
}
|
28
|
+
}
|
29
|
+
}.merge(config_from_file)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.config_from_file
|
33
|
+
config_file_name = ENV['DIFFUX_CI_CONFIG_FILE'] || '.diffux_ci.yaml'
|
34
|
+
YAML.load(ERB.new(File.read(config_file_name)).result)
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.normalize_description(description)
|
38
|
+
Base64.encode64(description).strip
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.path_to(description, viewport_name, file_name)
|
42
|
+
File.join(
|
43
|
+
config['snapshots_folder'],
|
44
|
+
normalize_description(description),
|
45
|
+
"@#{viewport_name}",
|
46
|
+
file_name
|
47
|
+
)
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.construct_url(absolute_path, params = {})
|
51
|
+
query = URI.encode_www_form(params) unless params.empty?
|
52
|
+
|
53
|
+
URI::HTTP.build(host: 'localhost',
|
54
|
+
port: config['port'],
|
55
|
+
path: absolute_path,
|
56
|
+
query: query).to_s
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.current_snapshots
|
60
|
+
prepare_file = lambda do |file|
|
61
|
+
viewport_dir = File.expand_path('..', file)
|
62
|
+
description_dir = File.expand_path('..', viewport_dir)
|
63
|
+
{
|
64
|
+
description: Base64.decode64(File.basename(description_dir)),
|
65
|
+
viewport: File.basename(viewport_dir).sub('@', ''),
|
66
|
+
file: file
|
67
|
+
}
|
68
|
+
end
|
69
|
+
|
70
|
+
snapshots_folder = DiffuxCI::Utils.config['snapshots_folder']
|
71
|
+
diff_files = Dir.glob("#{snapshots_folder}/**/diff.png")
|
72
|
+
baselines = Dir.glob("#{snapshots_folder}/**/baseline.png")
|
73
|
+
|
74
|
+
{
|
75
|
+
diffs: diff_files.map(&prepare_file),
|
76
|
+
baselines: baselines.map(&prepare_file)
|
77
|
+
}
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
File without changes
|
File without changes
|
File without changes
|
data/lib/diffux_ci.rb
ADDED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: diffux_ci
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Henric Trotzig
|
@@ -51,20 +51,20 @@ dependencies:
|
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '2.
|
54
|
+
version: '2.53'
|
55
55
|
- - ">="
|
56
56
|
- !ruby/object:Gem::Version
|
57
|
-
version: 2.
|
57
|
+
version: 2.53.0
|
58
58
|
type: :runtime
|
59
59
|
prerelease: false
|
60
60
|
version_requirements: !ruby/object:Gem::Requirement
|
61
61
|
requirements:
|
62
62
|
- - "~>"
|
63
63
|
- !ruby/object:Gem::Version
|
64
|
-
version: '2.
|
64
|
+
version: '2.53'
|
65
65
|
- - ">="
|
66
66
|
- !ruby/object:Gem::Version
|
67
|
-
version: 2.
|
67
|
+
version: 2.53.0
|
68
68
|
- !ruby/object:Gem::Dependency
|
69
69
|
name: thin
|
70
70
|
requirement: !ruby/object:Gem::Requirement
|
@@ -135,19 +135,21 @@ extensions: []
|
|
135
135
|
extra_rdoc_files: []
|
136
136
|
files:
|
137
137
|
- bin/diffux
|
138
|
-
- lib/diffux_ci
|
139
|
-
- lib/
|
140
|
-
- lib/
|
141
|
-
- lib/
|
142
|
-
- lib/
|
143
|
-
- lib/
|
144
|
-
- lib/
|
145
|
-
- lib/
|
138
|
+
- lib/diffux_ci.rb
|
139
|
+
- lib/diffux_ci/action.rb
|
140
|
+
- lib/diffux_ci/diffs.html.erb
|
141
|
+
- lib/diffux_ci/logger.rb
|
142
|
+
- lib/diffux_ci/public/diffux_ci-runner.js
|
143
|
+
- lib/diffux_ci/public/diffux_ci-styles.css
|
144
|
+
- lib/diffux_ci/runner.rb
|
145
|
+
- lib/diffux_ci/server.rb
|
146
|
+
- lib/diffux_ci/uploader.rb
|
147
|
+
- lib/diffux_ci/utils.rb
|
148
|
+
- lib/diffux_ci/version.rb
|
149
|
+
- lib/diffux_ci/views/debug.erb
|
150
|
+
- lib/diffux_ci/views/index.erb
|
151
|
+
- lib/diffux_ci/views/review.erb
|
146
152
|
- lib/public/diffux_ci-scripts.js
|
147
|
-
- lib/public/diffux_ci-styles.css
|
148
|
-
- lib/views/debug.erb
|
149
|
-
- lib/views/index.erb
|
150
|
-
- lib/views/review.erb
|
151
153
|
homepage: http://rubygems.org/gems/diffux_ci
|
152
154
|
licenses:
|
153
155
|
- MIT
|
@@ -168,7 +170,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
168
170
|
version: '0'
|
169
171
|
requirements: []
|
170
172
|
rubyforge_project:
|
171
|
-
rubygems_version: 2.
|
173
|
+
rubygems_version: 2.5.1
|
172
174
|
signing_key:
|
173
175
|
specification_version: 4
|
174
176
|
summary: Diffux-CI
|
data/lib/diffux_ci_action.rb
DELETED
@@ -1,31 +0,0 @@
|
|
1
|
-
require 'diffux_ci_utils'
|
2
|
-
require 'fileutils'
|
3
|
-
|
4
|
-
class DiffuxCIAction
|
5
|
-
def initialize(example_description, viewport_name)
|
6
|
-
@example_description = example_description
|
7
|
-
@viewport_name = viewport_name
|
8
|
-
end
|
9
|
-
|
10
|
-
def approve
|
11
|
-
diff_path = DiffuxCIUtils.path_to(
|
12
|
-
@example_description, @viewport_name, 'diff.png')
|
13
|
-
baseline_path = DiffuxCIUtils.path_to(
|
14
|
-
@example_description, @viewport_name, 'baseline.png')
|
15
|
-
candidate_path = DiffuxCIUtils.path_to(
|
16
|
-
@example_description, @viewport_name, 'candidate.png')
|
17
|
-
|
18
|
-
FileUtils.rm(diff_path, force: true)
|
19
|
-
FileUtils.mv(candidate_path, baseline_path) if File.exist? candidate_path
|
20
|
-
end
|
21
|
-
|
22
|
-
def reject
|
23
|
-
diff_path = DiffuxCIUtils.path_to(
|
24
|
-
@example_description, @viewport_name, 'diff.png')
|
25
|
-
candidate_path = DiffuxCIUtils.path_to(
|
26
|
-
@example_description, @viewport_name, 'candidate.png')
|
27
|
-
|
28
|
-
FileUtils.rm(diff_path, force: true)
|
29
|
-
FileUtils.rm(candidate_path, force: true)
|
30
|
-
end
|
31
|
-
end
|
data/lib/diffux_ci_server.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'sinatra/base'
|
2
|
-
require 'yaml'
|
3
|
-
require 'diffux_ci_utils'
|
4
|
-
require 'diffux_ci_action'
|
5
|
-
|
6
|
-
class DiffuxCIServer < Sinatra::Base
|
7
|
-
configure do
|
8
|
-
enable :static
|
9
|
-
set :port, DiffuxCIUtils.config['port']
|
10
|
-
end
|
11
|
-
|
12
|
-
helpers do
|
13
|
-
def h(text)
|
14
|
-
Rack::Utils.escape_html(text)
|
15
|
-
end
|
16
|
-
end
|
17
|
-
|
18
|
-
get '/' do
|
19
|
-
@config = DiffuxCIUtils.config
|
20
|
-
erb :index
|
21
|
-
end
|
22
|
-
|
23
|
-
get '/debug' do
|
24
|
-
@config = DiffuxCIUtils.config
|
25
|
-
erb :debug
|
26
|
-
end
|
27
|
-
|
28
|
-
get '/review' do
|
29
|
-
@snapshots = DiffuxCIUtils.current_snapshots
|
30
|
-
erb :review
|
31
|
-
end
|
32
|
-
|
33
|
-
get '/resource' do
|
34
|
-
file = params[:file]
|
35
|
-
if file.start_with? 'http'
|
36
|
-
redirect file
|
37
|
-
else
|
38
|
-
send_file file
|
39
|
-
end
|
40
|
-
end
|
41
|
-
|
42
|
-
post '/reject' do
|
43
|
-
DiffuxCIAction.new(params[:description], params[:viewport]).reject
|
44
|
-
redirect back
|
45
|
-
end
|
46
|
-
|
47
|
-
post '/approve' do
|
48
|
-
DiffuxCIAction.new(params[:description], params[:viewport]).approve
|
49
|
-
redirect back
|
50
|
-
end
|
51
|
-
|
52
|
-
run!
|
53
|
-
end
|
data/lib/diffux_ci_uploader.rb
DELETED
@@ -1,69 +0,0 @@
|
|
1
|
-
require 'diffux_ci_utils'
|
2
|
-
require 's3'
|
3
|
-
require 'securerandom'
|
4
|
-
|
5
|
-
class DiffuxCIUploader
|
6
|
-
def initialize
|
7
|
-
@s3_access_key_id = DiffuxCIUtils.config['s3_access_key_id']
|
8
|
-
@s3_secret_access_key = DiffuxCIUtils.config['s3_secret_access_key']
|
9
|
-
@s3_bucket_name = DiffuxCIUtils.config['s3_bucket_name']
|
10
|
-
end
|
11
|
-
|
12
|
-
def upload_diffs
|
13
|
-
result_summary = YAML.load(File.read(File.join(
|
14
|
-
DiffuxCIUtils.config['snapshots_folder'], 'result_summary.yaml')))
|
15
|
-
|
16
|
-
return [] if result_summary[:diff_examples].empty? &&
|
17
|
-
result_summary[:new_examples].empty?
|
18
|
-
|
19
|
-
bucket = find_or_build_bucket
|
20
|
-
dir = SecureRandom.uuid
|
21
|
-
|
22
|
-
diff_images = result_summary[:diff_examples].map do |diff|
|
23
|
-
image = bucket.objects.build(
|
24
|
-
"#{dir}/#{diff[:description]}_#{diff[:viewport]}.png")
|
25
|
-
image.content = open(DiffuxCIUtils.path_to(diff[:description],
|
26
|
-
diff[:viewport],
|
27
|
-
'diff.png'))
|
28
|
-
image.content_type = 'image/png'
|
29
|
-
image.save
|
30
|
-
diff[:url] = image.url
|
31
|
-
diff
|
32
|
-
end
|
33
|
-
|
34
|
-
new_images = result_summary[:new_examples].map do |example|
|
35
|
-
image = bucket.objects.build(
|
36
|
-
"#{dir}/#{example[:description]}_#{example[:viewport]}.png")
|
37
|
-
image.content = open(DiffuxCIUtils.path_to(example[:description],
|
38
|
-
example[:viewport],
|
39
|
-
'baseline.png'))
|
40
|
-
image.content_type = 'image/png'
|
41
|
-
image.save
|
42
|
-
example[:url] = image.url
|
43
|
-
example
|
44
|
-
end
|
45
|
-
|
46
|
-
html = bucket.objects.build("#{dir}/index.html")
|
47
|
-
path = File.expand_path(
|
48
|
-
File.join(File.dirname(__FILE__), 'diffux_ci-diffs.html.erb'))
|
49
|
-
html.content = ERB.new(File.read(path)).result(binding)
|
50
|
-
html.content_type = 'text/html'
|
51
|
-
html.save
|
52
|
-
html.url
|
53
|
-
end
|
54
|
-
|
55
|
-
private
|
56
|
-
|
57
|
-
def find_or_build_bucket
|
58
|
-
service = S3::Service.new(access_key_id: @s3_access_key_id,
|
59
|
-
secret_access_key: @s3_secret_access_key)
|
60
|
-
bucket = service.buckets.find(@s3_bucket_name)
|
61
|
-
|
62
|
-
if bucket.nil?
|
63
|
-
bucket = service.buckets.build(@s3_bucket_name)
|
64
|
-
bucket.save(location: :us)
|
65
|
-
end
|
66
|
-
|
67
|
-
bucket
|
68
|
-
end
|
69
|
-
end
|
data/lib/diffux_ci_utils.rb
DELETED
@@ -1,78 +0,0 @@
|
|
1
|
-
require 'yaml'
|
2
|
-
require 'erb'
|
3
|
-
require 'uri'
|
4
|
-
require 'base64'
|
5
|
-
|
6
|
-
class DiffuxCIUtils
|
7
|
-
def self.config
|
8
|
-
@@config ||= {
|
9
|
-
'snapshots_folder' => './snapshots',
|
10
|
-
'source_files' => [],
|
11
|
-
'stylesheets' => [],
|
12
|
-
'port' => 4567,
|
13
|
-
'driver' => :firefox,
|
14
|
-
'viewports' => {
|
15
|
-
'large' => {
|
16
|
-
'width' => 1024,
|
17
|
-
'height' => 768
|
18
|
-
},
|
19
|
-
'medium' => {
|
20
|
-
'width' => 640,
|
21
|
-
'height' => 888
|
22
|
-
},
|
23
|
-
'small' => {
|
24
|
-
'width' => 320,
|
25
|
-
'height' => 444
|
26
|
-
}
|
27
|
-
}
|
28
|
-
}.merge(config_from_file)
|
29
|
-
end
|
30
|
-
|
31
|
-
def self.config_from_file
|
32
|
-
config_file_name = ENV['DIFFUX_CI_CONFIG_FILE'] || '.diffux_ci.yaml'
|
33
|
-
YAML.load(ERB.new(File.read(config_file_name)).result)
|
34
|
-
end
|
35
|
-
|
36
|
-
def self.normalize_description(description)
|
37
|
-
Base64.encode64(description).strip
|
38
|
-
end
|
39
|
-
|
40
|
-
def self.path_to(description, viewport_name, file_name)
|
41
|
-
File.join(
|
42
|
-
config['snapshots_folder'],
|
43
|
-
normalize_description(description),
|
44
|
-
"@#{viewport_name}",
|
45
|
-
file_name
|
46
|
-
)
|
47
|
-
end
|
48
|
-
|
49
|
-
def self.construct_url(absolute_path, params = {})
|
50
|
-
query = URI.encode_www_form(params) unless params.empty?
|
51
|
-
|
52
|
-
URI::HTTP.build(host: 'localhost',
|
53
|
-
port: config['port'],
|
54
|
-
path: absolute_path,
|
55
|
-
query: query).to_s
|
56
|
-
end
|
57
|
-
|
58
|
-
def self.current_snapshots
|
59
|
-
prepare_file = lambda do |file|
|
60
|
-
viewport_dir = File.expand_path('..', file)
|
61
|
-
description_dir = File.expand_path('..', viewport_dir)
|
62
|
-
{
|
63
|
-
description: Base64.decode64(File.basename(description_dir)),
|
64
|
-
viewport: File.basename(viewport_dir).sub('@', ''),
|
65
|
-
file: file
|
66
|
-
}
|
67
|
-
end
|
68
|
-
|
69
|
-
snapshots_folder = DiffuxCIUtils.config['snapshots_folder']
|
70
|
-
diff_files = Dir.glob("#{snapshots_folder}/**/diff.png")
|
71
|
-
baselines = Dir.glob("#{snapshots_folder}/**/baseline.png")
|
72
|
-
|
73
|
-
{
|
74
|
-
diffs: diff_files.map(&prepare_file),
|
75
|
-
baselines: baselines.map(&prepare_file)
|
76
|
-
}
|
77
|
-
end
|
78
|
-
end
|