fastlane-plugin-snapshot_test 0.1.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a098870c72f522fd964d25677e67ea4261bc7dd9d2fe8cacaa129a82b2d98c21
4
- data.tar.gz: a71eb32a3d7680fed8ec459704df16ecf41c7944106cf9a20eee9df513e16eae
3
+ metadata.gz: 369ce048fb4948441d4f3c47f4f22ff8a9c650b20cb8885f89ee1f82793928eb
4
+ data.tar.gz: f0582347d70ebc8e36c8d9230b7e530229e4d99b15e0e1e4ce8053d65f2a7ae2
5
5
  SHA512:
6
- metadata.gz: dadc72f1ac54582138ee9e54c40970ec727e0b99329e8f402e6c063cc5c559d12cbe8b7b904edb878e888e3cb3e5700677a0b9ab088788ca99cb63f49dda8a54
7
- data.tar.gz: a1694820bd772d51179d2f61be4556a3bd67a2f0896f5c22d7808723efe8e8fc6700333566683627b79c0c3ed32c5fa5c8b9458588a3cb2800732d1c2223572f
6
+ metadata.gz: 3c90e1cb6ebff04d0a7196683bcc848771c2e899e3e7d4f71ad5d5ea669d80473a78c84dcdff439c748d18218a52b4dc30d6fcf7c98ef96e993bdb37a55c35df
7
+ data.tar.gz: 5d1923dc1562593e98a55586b05ffc5699d4c8bdf20aa64b7fcc2ba4baf89065febcb1701543512b89e01b10a4b204bb5261780f5c5404ccffb727aca02263e7
@@ -0,0 +1,165 @@
1
+ require 'fastlane/action'
2
+ require_relative '../../helper/helper'
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class ScreenshotNotifierAction < Action
7
+ def self.run(params)
8
+ Helper.authenticate(params[:gcloud_service_key_file])
9
+ commit_hash = Helper.get_current_commit_hash
10
+
11
+ UI.message "Upload screenshots to cloud storage"
12
+ Action.sh "gsutil -m rsync -d -r #{params[:screenshot_dir]} gs://#{params[:screenshot_bucket]}/#{commit_hash}"
13
+
14
+ UI.message "Delete previous PR comments"
15
+ GitHubNotifier.delete_comments(
16
+ params[:github_owner],
17
+ params[:github_repository],
18
+ params[:github_pr_number],
19
+ "## Screenshots of each devices",
20
+ params[:github_api_token]
21
+ )
22
+
23
+ UI.message "Post screenshots as PR comments"
24
+ screenshot_dir = params[:screenshot_dir]
25
+ devices = Dir.chdir("#{screenshot_dir}") do
26
+ Dir.glob("*").select { |path| FileTest.directory? path }.sort
27
+ end
28
+ if devices.empty?
29
+ UI.message("That screenshot dir is empty")
30
+ return
31
+ end
32
+
33
+ header = "<tr><td>Screen Name</td>\n#{devices.map { |device| "<td>#{device}</td>\n" }.inject(&:+)}</tr>"
34
+ rows = Dir.glob("#{screenshot_dir}/#{devices[0]}/*.jpg")
35
+ .map { |path| File.basename(path) }
36
+ .map { |file_name|
37
+ cells = devices.map { |device|
38
+ file_path = "#{screenshot_dir}/#{device}/#{file_name}"
39
+ next "<td></td>" unless File.exist?(file_path)
40
+ ratio = Helper.calc_aspect_ratio(file_path)
41
+ is_portrait = ratio >= 1.0
42
+ size_attr = if params[:image_length] != nil
43
+ if is_portrait
44
+ height = params[:image_length]
45
+ width = height / ratio
46
+ "height=\"#{height}px\" width=\"#{width}px\""
47
+ else
48
+ width = params[:image_length] * ratio
49
+ height = width * ratio
50
+ "height=\"#{height}px\" width=\"#{width}px\""
51
+ end
52
+ else
53
+ ""
54
+ end
55
+
56
+ url = object_url(params[:screenshot_bucket], "#{commit_hash}/#{device}/#{file_name}")
57
+ "<td><img src=\"#{url}\" #{size_attr}/></td>\n"
58
+ }.inject(&:+)
59
+ "<tr><td>#{file_name}</td>\n#{cells}</tr>\n"
60
+ }.inject(&:+)
61
+
62
+ table = "<table>#{header}#{rows}</table>"
63
+ comment = if params[:fold_result]
64
+ "## Screenshots of each devices\n\n"\
65
+ "<details>"\
66
+ "<summary>Open</summary>"\
67
+ "#{table}"\
68
+ "</details>"
69
+ else
70
+ "## Screenshots of each devices\n\n"\
71
+ "#{table}"
72
+ end
73
+ UI.message comment
74
+ GitHubNotifier.put_comment(
75
+ params[:github_owner],
76
+ params[:github_repository],
77
+ params[:github_pr_number],
78
+ comment,
79
+ params[:github_api_token]
80
+ )
81
+ end
82
+
83
+ def self.object_url(bucket, path)
84
+ Helper.firebase_object_url(bucket, path)
85
+ end
86
+
87
+ def self.description
88
+ "Post Screenshots to Pull Request"
89
+ end
90
+
91
+ def self.details
92
+ "Post Screenshots to Pull Request"
93
+ end
94
+
95
+ def self.available_options
96
+ [
97
+ FastlaneCore::ConfigItem.new(key: :gcloud_service_key_file,
98
+ env_name: "GCLOUD_SERVICE_KEY_FILE",
99
+ description: "File path containing the gcloud auth key. Default: Created from GCLOUD_SERVICE_KEY environment variable",
100
+ type: String,
101
+ optional: false),
102
+ FastlaneCore::ConfigItem.new(key: :screenshot_bucket,
103
+ env_name: "SCREENSHOT_BUCKET",
104
+ description: "Bucket name to store screenshots",
105
+ type: String,
106
+ optional: false),
107
+ FastlaneCore::ConfigItem.new(key: :screenshot_dir,
108
+ env_name: "SCREENSHOT_DIR",
109
+ description: "Directory that has screenshots",
110
+ type: String,
111
+ optional: false),
112
+ FastlaneCore::ConfigItem.new(key: :fold_result,
113
+ env_name: "FOLD_RESULT",
114
+ description: "Fold screenshots table",
115
+ type: Boolean,
116
+ optional: false,
117
+ default_value: false),
118
+ FastlaneCore::ConfigItem.new(key: :github_owner,
119
+ env_name: "GITHUB_OWNER",
120
+ description: "Owner name",
121
+ type: String,
122
+ optional: false),
123
+ FastlaneCore::ConfigItem.new(key: :github_repository,
124
+ env_name: "GITHUB_REPOSITORY",
125
+ description: "Repository name",
126
+ type: String,
127
+ optional: false),
128
+ FastlaneCore::ConfigItem.new(key: :github_pr_number,
129
+ env_name: "GITHUB_PR_NUMBER",
130
+ description: "Pull request number",
131
+ type: String,
132
+ optional: false),
133
+ FastlaneCore::ConfigItem.new(key: :github_api_token,
134
+ env_name: "GITHUB_API_TOKEN",
135
+ description: "GitHub API Token",
136
+ type: String,
137
+ optional: false),
138
+ FastlaneCore::ConfigItem.new(key: :image_length,
139
+ env_name: "IMAGE_LENGTH",
140
+ description: "Length px of the long side of screenshots",
141
+ is_string: false,
142
+ optional: true)
143
+ ]
144
+ end
145
+
146
+ def self.output
147
+ # Define the shared values you are going to provide
148
+ # Example
149
+ []
150
+ end
151
+
152
+ def self.return_value
153
+ # If your method provides a return value, you can describe here what it does
154
+ end
155
+
156
+ def self.authors
157
+ ["MoyuruAizawa"]
158
+ end
159
+
160
+ def self.is_supported?(platform)
161
+ platform == :android
162
+ end
163
+ end
164
+ end
165
+ end
@@ -1,10 +1,13 @@
1
- require_relative '../helper/github_notifier'
2
- require_relative '../helper/helper'
1
+ require 'fastlane/action'
2
+
3
+ require_relative '../../helper/comparator'
4
+ require_relative '../../helper/github_notifier'
5
+ require_relative '../../helper/helper'
3
6
  require 'json'
4
7
 
5
8
  module Fastlane
6
9
  module Actions
7
- class SnapshotTestAction < Action
10
+ class CompareSnapshotAction < Action
8
11
  def self.run(params)
9
12
  Helper.authenticate(params[:gcloud_service_key_file])
10
13
 
@@ -32,7 +35,7 @@ module Fastlane
32
35
  `rm -rf #{working_dir}/diff`
33
36
  `mkdir #{working_dir}/diff`
34
37
  result = Comparator.compare_dir("#{working_dir}/expected", "#{working_dir}/actual", "#{working_dir}/diff", params[:fuzz])
35
- open("#{working_dir}/result.json", "w") {|io| io.puts(JSON.pretty_generate(result))}
38
+ open("#{working_dir}/result.json", "w") { |io| io.puts(JSON.pretty_generate(result)) }
36
39
  Action.sh "gsutil -m rsync -d -r #{working_dir} gs://#{snapshot_bucket}/#{Helper.get_current_commit_hash}"
37
40
 
38
41
  UI.message result
@@ -46,18 +49,18 @@ module Fastlane
46
49
  bucket = params[:snapshot_bucket]
47
50
  commit_hash = Helper.get_current_commit_hash
48
51
 
49
- message = <<-EOS
50
- ## Snapshot Test Result
51
- Commit Hash: #{commit_hash}
52
-
53
- #{summary_table(result[:new_items], result[:deleted_items], result[:changed_items], result[:passed_items])}
54
-
55
- #{changed_items_table(result[:changed_items], bucket, commit_hash, params[:working_dir], params[:image_length])}
56
-
57
- #{new_items_table(result[:new_items], bucket, commit_hash, params[:working_dir], params[:image_length])}
58
-
59
- #{deleted_items_list(result[:deleted_items])}
60
- EOS
52
+ message = <<-USAGE.strip_heredoc
53
+ ## Snapshot Test Result
54
+ Commit Hash: #{commit_hash}
55
+
56
+ #{summary_table(result[:new_items], result[:deleted_items], result[:changed_items], result[:passed_items])}
57
+
58
+ #{changed_items_table(result[:changed_items], bucket, commit_hash, params[:working_dir], params[:image_length])}
59
+
60
+ #{new_items_table(result[:new_items], bucket, commit_hash, params[:working_dir], params[:image_length])}
61
+
62
+ #{deleted_items_list(result[:deleted_items])}
63
+ USAGE
61
64
 
62
65
  GitHubNotifier.fold_comments(
63
66
  params[:github_owner],
@@ -92,7 +95,7 @@ Commit Hash: #{commit_hash}
92
95
  return "" if changed_items.empty?
93
96
 
94
97
  header = "<tr><td></td><td>Before</td><td>After</td><td>Diff</td></tr>"
95
- cells = changed_items.map {|item|
98
+ cells = changed_items.map { |item|
96
99
  size_attr = generate_size_attr("#{working_dir}/actual/#{item}", image_height)
97
100
 
98
101
  before = "<img src=\"#{object_url(bucket, commit_hash, item, "expected")}\" #{size_attr} />"
@@ -107,9 +110,9 @@ Commit Hash: #{commit_hash}
107
110
  def self.new_items_table(new_items, bucket, commit_hash, working_dir, image_height)
108
111
  return "" if new_items.empty?
109
112
 
110
- rows = new_items.each_slice(3).map {|oneline_items|
111
- labels = oneline_items.map {|item| "<td>#{item}</td>"}.inject(&:+)
112
- imgs = oneline_items.map {|item|
113
+ rows = new_items.each_slice(3).map { |oneline_items|
114
+ labels = oneline_items.map { |item| "<td>#{item}</td>" }.inject(&:+)
115
+ imgs = oneline_items.map { |item|
113
116
  size_attr = generate_size_attr("#{working_dir}/actual/#{item}", image_height)
114
117
  "<td><img src=\"#{object_url(bucket, commit_hash, item, "actual")}\" #{size_attr} /></td>"
115
118
  }.inject(&:+)
@@ -122,7 +125,7 @@ Commit Hash: #{commit_hash}
122
125
  def self.deleted_items_list(deleted_items)
123
126
  return "" if deleted_items.empty?
124
127
 
125
- "### Deleted Screenshots\n<details><summary>Open</summary>\n\n#{deleted_items.map {|item| "- #{item}\n"}.inject(&:+)}</details>\n"
128
+ "### Deleted Screenshots\n<details><summary>Open</summary>\n\n#{deleted_items.map { |item| "- #{item}\n" }.inject(&:+)}</details>\n"
126
129
  end
127
130
 
128
131
  def self.object_url(bucket, commit_hash, item_name, image_type)
@@ -151,7 +154,7 @@ Commit Hash: #{commit_hash}
151
154
  end
152
155
 
153
156
  def self.authors
154
- ["Moyuru Aizawa"]
157
+ ["MoyuruAizawa"]
155
158
  end
156
159
 
157
160
  def self.available_options
@@ -1,8 +1,10 @@
1
- require_relative '../helper/helper'
1
+ require 'fastlane/action'
2
+
3
+ require_relative '../../helper/helper'
2
4
 
3
5
  module Fastlane
4
6
  module Actions
5
- class SaveSnapshotAction < Action
7
+ class UploadSnapshotAction < Action
6
8
  def self.run(params)
7
9
  Helper.authenticate(params[:gcloud_service_key_file])
8
10
 
@@ -17,11 +19,11 @@ module Fastlane
17
19
  end
18
20
 
19
21
  def self.description
20
- "Save Snapshot"
22
+ "Upload Snapshot"
21
23
  end
22
24
 
23
25
  def self.details
24
- "Save Snapshot"
26
+ "Upload Snapshot"
25
27
  end
26
28
 
27
29
  def self.available_options
@@ -1,6 +1,8 @@
1
+ require 'fastlane/action'
2
+
1
3
  module Fastlane
2
4
  module Actions
3
- class ScreenshotAction < Action
5
+ class TakeScreenshotAction < Action
4
6
  def self.run(params)
5
7
  download_dir = params[:download_dir]
6
8
 
@@ -11,15 +11,15 @@ module Fastlane
11
11
 
12
12
  def self.compare_dir(expected_dir, actual_dir, diff_dir, fuzz)
13
13
  UI.message "Compare #{expected_dir} and #{actual_dir}"
14
- expect_items = Dir.glob("#{expected_dir}/*.jpg").map {|path| File.basename(path)}
15
- actual_items = Dir.glob("#{actual_dir}/*.jpg").map {|path| File.basename(path)}
14
+ expect_items = Dir.glob("#{expected_dir}/*.jpg").map { |path| File.basename(path) }
15
+ actual_items = Dir.glob("#{actual_dir}/*.jpg").map { |path| File.basename(path) }
16
16
 
17
17
  new_items = actual_items - expect_items
18
18
  deleted_items = expect_items - actual_items
19
19
  passed_items = []
20
20
  changed_items = []
21
21
 
22
- (actual_items & expect_items).each {|fileName|
22
+ (actual_items & expect_items).each { |fileName|
23
23
  is_passed = compare("#{actual_dir}/#{fileName}", "#{expected_dir}/#{fileName}", "#{diff_dir}/#{fileName}", fuzz)
24
24
  if is_passed
25
25
  passed_items << fileName
@@ -8,8 +8,8 @@ module Fastlane
8
8
  def self.fold_comments(github_owner, github_repository, github_pr_number, comment_prefix, summary, github_api_token)
9
9
  res = get_comments(github_owner, github_repository, github_pr_number, github_api_token)
10
10
  JSON.parse(res.body)
11
- .select {|comment| comment["body"].start_with?(comment_prefix)}
12
- .each {|comment|
11
+ .select { |comment| comment["body"] != nil && comment["body"].start_with?(comment_prefix) }
12
+ .each { |comment|
13
13
  body = "<details><summary>#{summary}</summary>\n#{comment["body"]}\n\n</details>\n"
14
14
  patch_comment(github_owner, github_repository, comment["id"], body, github_api_token)
15
15
  }
@@ -18,8 +18,8 @@ module Fastlane
18
18
  def self.delete_comments(github_owner, github_repository, github_pr_number, comment_prefix, github_api_token)
19
19
  res = get_comments(github_owner, github_repository, github_pr_number, github_api_token)
20
20
  JSON.parse(res.body)
21
- .select {|comment| comment["body"].start_with?(comment_prefix)}
22
- .each {|comment| delete_comment(github_owner, github_repository, comment["id"], github_api_token)}
21
+ .select { |comment| comment["body"] != nil && comment["body"].start_with?(comment_prefix) }
22
+ .each { |comment| delete_comment(github_owner, github_repository, comment["id"], github_api_token) }
23
23
  end
24
24
 
25
25
  def self.get_comments(github_owner, github_repository, github_pr_number, github_api_token)
@@ -31,7 +31,7 @@ module Fastlane
31
31
  req["Content-Type"] = "application/json"
32
32
  req["Authorization"] = "token #{github_api_token}"
33
33
 
34
- res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) {|http| http.request(req)}
34
+ res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) { |http| http.request(req) }
35
35
  UI.message "#{res.code}\n#{res.body}"
36
36
 
37
37
  res
@@ -47,7 +47,7 @@ module Fastlane
47
47
  req["Authorization"] = "token #{github_api_token}"
48
48
  req.body = {:body => body}.to_json
49
49
 
50
- res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) {|http| http.request(req)}
50
+ res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) { |http| http.request(req) }
51
51
  UI.message "#{res.code}\n#{res.body}"
52
52
 
53
53
  res
@@ -63,7 +63,7 @@ module Fastlane
63
63
  req["Authorization"] = "token #{github_api_token}"
64
64
  req.body = {:body => body}.to_json
65
65
 
66
- res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) {|http| http.request(req)}
66
+ res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) { |http| http.request(req) }
67
67
  UI.message "#{res.code}\n#{res.body}"
68
68
 
69
69
  res
@@ -78,7 +78,7 @@ module Fastlane
78
78
  req["Content-Type"] = "application/json"
79
79
  req["Authorization"] = "token #{github_api_token}"
80
80
 
81
- res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) {|http| http.request(req)}
81
+ res = Net::HTTP.start(uri.hostname, uri.port, {use_ssl: uri.scheme = "https"}) { |http| http.request(req) }
82
82
  UI.message "#{res.code}\n#{res.body}"
83
83
 
84
84
  res
@@ -20,9 +20,9 @@ module Fastlane
20
20
  def self.find_base_commit_hash(bucket_name, base_branch, current_branch)
21
21
  base_commit_hash = Action.sh("git merge-base origin/#{base_branch} #{current_branch}").chomp!
22
22
  dirs = `gsutil ls gs://#{bucket_name}/ | grep -e "/$"`.split("\n")
23
- .map {|s| s[/(?<=gs:\/\/#{bucket_name}\/)(.*)(?=\/)/]}
23
+ .map { |s| s[/(?<=gs:\/\/#{bucket_name}\/)(.*)(?=\/)/] }
24
24
  hashes = Action.sh("git log origin/#{base_branch} --pretty=%H").split("\n")
25
- hashes[hashes.index(base_commit_hash)..-1].each {|hash|
25
+ hashes[hashes.index(base_commit_hash)..-1].each { |hash|
26
26
  if dirs.include?(hash)
27
27
  return hash
28
28
  end
@@ -36,6 +36,7 @@ module Fastlane
36
36
 
37
37
  def self.calc_aspect_ratio(imagePath)
38
38
  width, height = FastImage.size(imagePath)
39
+ UI.message "Image(#{imagePath}) size #{width} * #{height}"
39
40
  height / width.to_f
40
41
  end
41
42
  end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module SnapshotTest
3
- VERSION = "0.1.0"
3
+ VERSION = "0.2.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-snapshot_test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Moyuru Aizawa
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-08-09 00:00:00.000000000 Z
11
+ date: 2019-09-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pry
@@ -145,9 +145,10 @@ files:
145
145
  - LICENSE
146
146
  - README.md
147
147
  - lib/fastlane/plugin/snapshot_test.rb
148
- - lib/fastlane/plugin/snapshot_test/actions/save_snapshot_action.rb
149
- - lib/fastlane/plugin/snapshot_test/actions/screenshot_action.rb
150
- - lib/fastlane/plugin/snapshot_test/actions/snapshot_test_action.rb
148
+ - lib/fastlane/plugin/snapshot_test/actions/compatibility/screenshot_notifier_action.rb
149
+ - lib/fastlane/plugin/snapshot_test/actions/regression/compare_snapshot_action.rb
150
+ - lib/fastlane/plugin/snapshot_test/actions/regression/upload_snapshot_action.rb
151
+ - lib/fastlane/plugin/snapshot_test/actions/take_screenshot_action.rb
151
152
  - lib/fastlane/plugin/snapshot_test/helper/comparator.rb
152
153
  - lib/fastlane/plugin/snapshot_test/helper/github_notifier.rb
153
154
  - lib/fastlane/plugin/snapshot_test/helper/helper.rb
@@ -171,7 +172,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
172
  - !ruby/object:Gem::Version
172
173
  version: '0'
173
174
  requirements: []
174
- rubygems_version: 3.0.3
175
+ rubygems_version: 3.0.6
175
176
  signing_key:
176
177
  specification_version: 4
177
178
  summary: Compare snapshots