diffux_ci 0.4.3 → 0.4.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|