fastlane 2.179.0 → 2.180.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +84 -84
  3. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +1 -1
  4. data/fastlane/lib/fastlane/actions/jira.rb +61 -14
  5. data/fastlane/lib/fastlane/actions/notarize.rb +98 -51
  6. data/fastlane/lib/fastlane/actions/sourcedocs.rb +164 -0
  7. data/fastlane/lib/fastlane/setup/setup.rb +23 -10
  8. data/fastlane/lib/fastlane/swift_runner_upgrader.rb +2 -0
  9. data/fastlane/lib/fastlane/version.rb +1 -1
  10. data/fastlane/swift/Deliverfile.swift +1 -1
  11. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  12. data/fastlane/swift/Fastlane.swift +87 -21
  13. data/fastlane/swift/Gymfile.swift +1 -1
  14. data/fastlane/swift/GymfileProtocol.swift +1 -1
  15. data/fastlane/swift/LaneFileProtocol.swift +9 -3
  16. data/fastlane/swift/Matchfile.swift +1 -1
  17. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  18. data/fastlane/swift/Precheckfile.swift +1 -1
  19. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  20. data/fastlane/swift/RubyCommand.swift +1 -1
  21. data/fastlane/swift/Scanfile.swift +1 -1
  22. data/fastlane/swift/ScanfileProtocol.swift +5 -1
  23. data/fastlane/swift/Screengrabfile.swift +1 -1
  24. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  25. data/fastlane/swift/Snapshotfile.swift +1 -1
  26. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  27. data/fastlane/swift/SocketClient.swift +2 -1
  28. data/fastlane/swift/SocketResponse.swift +4 -2
  29. data/fastlane/swift/formatting/Brewfile.lock.json +3 -3
  30. data/fastlane_core/lib/fastlane_core/queue_worker.rb +2 -2
  31. data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +12 -1
  32. data/match/lib/match/change_password.rb +1 -1
  33. data/scan/lib/scan/options.rb +10 -5
  34. data/scan/lib/scan/runner.rb +52 -1
  35. data/scan/lib/scan/test_command_generator.rb +8 -8
  36. data/snapshot/lib/assets/SnapshotHelper.swift +1 -1
  37. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +1 -1
  38. data/spaceship/lib/spaceship/connect_api/token.rb +7 -1
  39. metadata +18 -18
  40. data/gym/lib/gym/.runner.rb.swp +0 -0
@@ -196,4 +196,4 @@ public extension GymfileProtocol {
196
196
 
197
197
  // Please don't remove the lines below
198
198
  // They are used to detect outdated files
199
- // FastlaneRunnerAPIVersion [0.9.65]
199
+ // FastlaneRunnerAPIVersion [0.9.66]
@@ -17,20 +17,20 @@ public protocol LaneFileProtocol: class {
17
17
  func recordLaneDescriptions()
18
18
  func beforeAll(with lane: String)
19
19
  func afterAll(with lane: String)
20
- func onError(currentLane: String, errorInfo: String)
20
+ func onError(currentLane: String, errorInfo: String, errorClass: String?, errorMessage: String?)
21
21
  }
22
22
 
23
23
  public extension LaneFileProtocol {
24
24
  var fastlaneVersion: String { return "" } // Defaults to "" because that means any is fine
25
25
  func beforeAll(with _: String) {} // No-op by default
26
26
  func afterAll(with _: String) {} // No-op by default
27
- func onError(currentLane _: String, errorInfo _: String) {} // No-op by default
28
27
  func recordLaneDescriptions() {} // No-op by default
29
28
  }
30
29
 
31
30
  @objcMembers
32
31
  open class LaneFile: NSObject, LaneFileProtocol {
33
32
  private(set) static var fastfileInstance: LaneFile?
33
+ private static var onErrorCalled = Set<String>()
34
34
 
35
35
  private static func trimLaneFromName(laneName: String) -> String {
36
36
  return String(laneName.prefix(laneName.count - 4))
@@ -40,6 +40,10 @@ open class LaneFile: NSObject, LaneFileProtocol {
40
40
  return String(laneName.prefix(laneName.count - 12))
41
41
  }
42
42
 
43
+ public func onError(currentLane: String, errorInfo _: String, errorClass _: String?, errorMessage _: String?) {
44
+ LaneFile.onErrorCalled.insert(currentLane)
45
+ }
46
+
43
47
  private static var laneFunctionNames: [String] {
44
48
  var lanes: [String] = []
45
49
  var methodCount: UInt32 = 0
@@ -137,7 +141,9 @@ open class LaneFile: NSObject, LaneFileProtocol {
137
141
  _ = fastfileInstance.perform(NSSelectorFromString(laneMethod), with: parameters)
138
142
 
139
143
  // Call only on success.
140
- fastfileInstance.afterAll(with: lane)
144
+ if !LaneFile.onErrorCalled.contains(lane) {
145
+ fastfileInstance.afterAll(with: lane)
146
+ }
141
147
 
142
148
  log(message: "Done running lane: \(lane) 🚀")
143
149
  return true
@@ -17,4 +17,4 @@ public class Matchfile: MatchfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.179.0
20
+ // Generated with fastlane 2.180.0
@@ -184,4 +184,4 @@ public extension MatchfileProtocol {
184
184
 
185
185
  // Please don't remove the lines below
186
186
  // They are used to detect outdated files
187
- // FastlaneRunnerAPIVersion [0.9.59]
187
+ // FastlaneRunnerAPIVersion [0.9.60]
@@ -17,4 +17,4 @@ public class Precheckfile: PrecheckfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.179.0
20
+ // Generated with fastlane 2.180.0
@@ -52,4 +52,4 @@ public extension PrecheckfileProtocol {
52
52
 
53
53
  // Please don't remove the lines below
54
54
  // They are used to detect outdated files
55
- // FastlaneRunnerAPIVersion [0.9.58]
55
+ // FastlaneRunnerAPIVersion [0.9.59]
@@ -51,7 +51,7 @@ struct RubyCommand: RubyCommandable {
51
51
  if type == .stringClosure {
52
52
  return "{\"name\" : \"\(name)\", \"value\" : \"ignored_for_closure\"\(typeJson)}"
53
53
  } else if let array = someValue as? [String] {
54
- return "{\"name\" : \"\(name)\", \"value\" : \"\(array.joined(separator: ","))\"\(typeJson)}"
54
+ return "{\"name\" : \"\(name)\", \"value\" : \(array)\(typeJson)}"
55
55
  } else if let hash = someValue as? [String: Any] {
56
56
  let jsonData = try! JSONSerialization.data(withJSONObject: hash, options: [])
57
57
  let jsonString = String(data: jsonData, encoding: .utf8)!
@@ -17,4 +17,4 @@ public class Scanfile: ScanfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.179.0
20
+ // Generated with fastlane 2.180.0
@@ -209,6 +209,9 @@ public protocol ScanfileProtocol: class {
209
209
  /// Lets xcodebuild use system's scm configuration
210
210
  var useSystemScm: Bool { get }
211
211
 
212
+ /// The number of times a test can fail before scan should stop retrying
213
+ var numberOfRetries: Int { get }
214
+
212
215
  /// Should this step stop the build if the tests fail? Set this to false if you're using trainer
213
216
  var failBuild: Bool { get }
214
217
  }
@@ -283,9 +286,10 @@ public extension ScanfileProtocol {
283
286
  var skipPackageDependenciesResolution: Bool { return false }
284
287
  var disablePackageAutomaticUpdates: Bool { return false }
285
288
  var useSystemScm: Bool { return false }
289
+ var numberOfRetries: Int { return 0 }
286
290
  var failBuild: Bool { return true }
287
291
  }
288
292
 
289
293
  // Please don't remove the lines below
290
294
  // They are used to detect outdated files
291
- // FastlaneRunnerAPIVersion [0.9.70]
295
+ // FastlaneRunnerAPIVersion [0.9.71]
@@ -17,4 +17,4 @@ public class Screengrabfile: ScreengrabfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.179.0
20
+ // Generated with fastlane 2.180.0
@@ -96,4 +96,4 @@ public extension ScreengrabfileProtocol {
96
96
 
97
97
  // Please don't remove the lines below
98
98
  // They are used to detect outdated files
99
- // FastlaneRunnerAPIVersion [0.9.60]
99
+ // FastlaneRunnerAPIVersion [0.9.61]
@@ -17,4 +17,4 @@ public class Snapshotfile: SnapshotfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.179.0
20
+ // Generated with fastlane 2.180.0
@@ -196,4 +196,4 @@ public extension SnapshotfileProtocol {
196
196
 
197
197
  // Please don't remove the lines below
198
198
  // They are used to detect outdated files
199
- // FastlaneRunnerAPIVersion [0.9.54]
199
+ // FastlaneRunnerAPIVersion [0.9.55]
@@ -302,7 +302,8 @@ extension SocketClient: StreamDelegate {
302
302
  self.closeSession(sendAbort: false)
303
303
  }
304
304
 
305
- case let .failure(failureInformation):
305
+ case let .failure(failureInformation, failureClass, failureMessage):
306
+ LaneFile.fastfileInstance?.onError(currentLane: ArgumentProcessor(args: CommandLine.arguments).currentLane, errorInfo: failureInformation.joined(), errorClass: failureClass, errorMessage: failureMessage)
306
307
  socketDelegate?.commandExecuted(serverResponse: .serverError) {
307
308
  $0.writeSemaphore.signal()
308
309
  self.handleFailure(message: failureInformation)
@@ -13,7 +13,7 @@ import Foundation
13
13
  struct SocketResponse {
14
14
  enum ResponseType {
15
15
  case parseFailure(failureInformation: [String])
16
- case failure(failureInformation: [String])
16
+ case failure(failureInformation: [String], failureClass: String?, failureMessage: String?)
17
17
  case readyForNext(returnedObject: String?, closureArgumentValue: String?)
18
18
  case clientInitiatedCancel
19
19
 
@@ -40,7 +40,9 @@ struct SocketResponse {
40
40
  return
41
41
  }
42
42
 
43
- self = .failure(failureInformation: failureInformation)
43
+ let failureClass = statusDictionary["failure_class"] as? String
44
+ let failureMessage = statusDictionary["failure_message"] as? String
45
+ self = .failure(failureInformation: failureInformation, failureClass: failureClass, failureMessage: failureMessage)
44
46
  return
45
47
  }
46
48
  self = .parseFailure(failureInformation: ["Message status: \(status) not a supported status"])
@@ -33,10 +33,10 @@
33
33
  "system": {
34
34
  "macos": {
35
35
  "catalina": {
36
- "HOMEBREW_VERSION": "3.0.9-4-g9308a25",
36
+ "HOMEBREW_VERSION": "3.0.11-37-g6d0275f",
37
37
  "HOMEBREW_PREFIX": "/usr/local",
38
- "Homebrew/homebrew-core": "2e6c683b1705308ab02e71f996733b1ad05942d0",
39
- "CLT": "11.0.33.12",
38
+ "Homebrew/homebrew-core": "ef0489237f06f73c1148f10ea1001def194b6808",
39
+ "CLT": "11.0.0.33.12",
40
40
  "Xcode": "12.2",
41
41
  "macOS": "10.15.7"
42
42
  },
@@ -16,12 +16,12 @@ module FastlaneCore
16
16
  @queue = Queue.new
17
17
  end
18
18
 
19
- # @param job (Object) - An arbitary object that keeps parameters
19
+ # @param job (Object) - An arbitrary object that keeps parameters
20
20
  def enqueue(job)
21
21
  @queue.push(job)
22
22
  end
23
23
 
24
- # @param jobs (Array<Object>) - An array of arbitary object that keeps parameters
24
+ # @param jobs (Array<Object>) - An array of arbitrary object that keeps parameters
25
25
  def batch_enqueue(jobs)
26
26
  raise(ArgumentError, "Enqueue Array instead of #{jobs.class}") unless jobs.kind_of?(Array)
27
27
  jobs.each { |job| enqueue(job) }
@@ -69,7 +69,7 @@ module FastlaneCore
69
69
  end
70
70
 
71
71
  def command_output(message)
72
- actual = (message.split("\r").last || "") # as clearing the line will remove the `>` and the time stamp
72
+ actual = (encode_as_utf_8_if_possible(message).split("\r").last || "") # as clearing the line will remove the `>` and the time stamp
73
73
  actual.split("\n").each do |msg|
74
74
  if FastlaneCore::Env.truthy?("FASTLANE_DISABLE_OUTPUT_FORMAT")
75
75
  log.info(msg)
@@ -150,6 +150,17 @@ module FastlaneCore
150
150
 
151
151
  private
152
152
 
153
+ def encode_as_utf_8_if_possible(message)
154
+ return message if message.valid_encoding?
155
+
156
+ # genstrings outputs UTF-16, so we should try to use this encoding if it turns out to be valid
157
+ test_message = message.dup
158
+ return message.encode(Encoding::UTF_8, Encoding::UTF_16) if test_message.force_encoding(Encoding::UTF_16).valid_encoding?
159
+
160
+ # replace any invalid with empty string
161
+ message.encode(Encoding::UTF_8, invalid: :replace)
162
+ end
163
+
153
164
  def verify_interactive!(message)
154
165
  return if interactive?
155
166
  important(message)
@@ -40,7 +40,7 @@ module Match
40
40
  encryption.store_password(new_password)
41
41
 
42
42
  message = "[fastlane] Changed passphrase"
43
- files_to_commit = encryption.encrypt_files(new_password)
43
+ files_to_commit = encryption.encrypt_files(password: new_password)
44
44
  storage.save_changes!(files_to_commit: files_to_commit, custom_message: message)
45
45
  end
46
46
 
@@ -472,11 +472,16 @@ module Scan
472
472
  type: Boolean,
473
473
  default_value: false),
474
474
  FastlaneCore::ConfigItem.new(key: :use_system_scm,
475
- env_name: "SCAN_USE_SYSTEM_SCM",
476
- description: "Lets xcodebuild use system's scm configuration",
477
- optional: true,
478
- type: Boolean,
479
- default_value: false)
475
+ env_name: "SCAN_USE_SYSTEM_SCM",
476
+ description: "Lets xcodebuild use system's scm configuration",
477
+ optional: true,
478
+ type: Boolean,
479
+ default_value: false),
480
+ FastlaneCore::ConfigItem.new(key: :number_of_retries,
481
+ env_name: 'SCAN_NUMBER_OF_RETRIES',
482
+ description: "The number of times a test can fail before scan should stop retrying",
483
+ type: Integer,
484
+ default_value: 0)
480
485
 
481
486
  ]
482
487
  end
@@ -51,7 +51,12 @@ module Scan
51
51
  end
52
52
  end
53
53
 
54
+ execute(retries: Scan.config[:number_of_retries])
55
+ end
56
+
57
+ def execute(retries: 0)
54
58
  command = @test_command_generator.generate
59
+
55
60
  prefix_hash = [
56
61
  {
57
62
  prefix: "Running Tests: ",
@@ -71,7 +76,12 @@ module Scan
71
76
  error: proc do |error_output|
72
77
  begin
73
78
  exit_status = $?.exitstatus
74
- ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
79
+ if retries > 0
80
+ # If there are retries remaining, run the tests again
81
+ return retry_execute(retries: retries, error_output: error_output)
82
+ else
83
+ ErrorHandler.handle_build_error(error_output, @test_command_generator.xcodebuild_log_path)
84
+ end
75
85
  rescue => ex
76
86
  SlackPoster.new.run({
77
87
  build_errors: 1
@@ -79,9 +89,50 @@ module Scan
79
89
  raise ex
80
90
  end
81
91
  end)
92
+
82
93
  exit_status
83
94
  end
84
95
 
96
+ def retry_execute(retries:, error_output: "")
97
+ tests = retryable_tests(error_output)
98
+
99
+ if tests.empty?
100
+ UI.crash!("Failed to find failed tests to retry (could not parse error output)")
101
+ end
102
+
103
+ Scan.config[:only_testing] = tests
104
+ UI.important("Retrying tests: #{Scan.config[:only_testing].join(', ')}")
105
+
106
+ retries -= 1
107
+ UI.important("Number of retries remaining: #{retries}")
108
+
109
+ return execute(retries: retries)
110
+ end
111
+
112
+ def retryable_tests(input)
113
+ input = Helper.strip_ansi_colors(input)
114
+
115
+ retryable_tests = []
116
+
117
+ failing_tests = input.split("Failing tests:\n").fetch(1, [])
118
+ .split("\n\n").first
119
+
120
+ suites = failing_tests.split(/(?=\n\s+[\w\s]+:\n)/)
121
+
122
+ suites.each do |suite|
123
+ suite_name = suite.match(/\s*([\w\s]+):/).captures.first
124
+
125
+ test_cases = suite.split(":\n").fetch(1, []).split("\n").each
126
+ .select { |line| line.match?(/^\s+/) }
127
+ .map { |line| line.strip.gsub(".", "/").gsub("()", "") }
128
+ .map { |line| suite_name + "/" + line }
129
+
130
+ retryable_tests += test_cases
131
+ end
132
+
133
+ return retryable_tests.uniq
134
+ end
135
+
85
136
  def handle_results(tests_exit_status)
86
137
  if Scan.config[:disable_xcpretty]
87
138
  unless tests_exit_status == 0
@@ -162,16 +162,16 @@ module Scan
162
162
  Scan.cache[:build_path]
163
163
  end
164
164
 
165
+ # The path to the result bundle
165
166
  def result_bundle_path
166
- unless Scan.cache[:result_bundle_path]
167
- ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
168
- path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + ext
169
- if File.directory?(path)
170
- FileUtils.remove_dir(path)
171
- end
172
- Scan.cache[:result_bundle_path] = path
167
+ ext = FastlaneCore::Helper.xcode_version.to_i >= 11 ? '.xcresult' : '.test_result'
168
+ path = File.join(Scan.config[:output_directory], Scan.config[:scheme]) + ext
169
+ if File.directory?(path)
170
+ FileUtils.remove_dir(path)
173
171
  end
174
- return Scan.cache[:result_bundle_path]
172
+ Scan.cache[:result_bundle_path] = path
173
+
174
+ return path
175
175
  end
176
176
  end
177
177
  end
@@ -302,4 +302,4 @@ private extension CGFloat {
302
302
 
303
303
  // Please don't remove the lines below
304
304
  // They are used to detect outdated configuration files
305
- // SnapshotHelperVersion [1.24]
305
+ // SnapshotHelperVersion [1.25]
@@ -112,7 +112,7 @@ module Spaceship
112
112
  timeout_minutes = (ENV["SPACESHIP_SCREENSHOT_UPLOAD_TIMEOUT"] || 20).to_i
113
113
 
114
114
  loop do
115
- # This error handling needs to be revised since any error occured can reach here.
115
+ # This error handling needs to be revised since any error occurred can reach here.
116
116
  # It should handle errors based on what status code is.
117
117
  puts("Waiting for screenshots to appear before uploading. This is unlikely to be recovered unless it's 503 error. error=\"#{error}\"")
118
118
  sleep(30)
@@ -60,14 +60,16 @@ module Spaceship
60
60
  key_id: key_id,
61
61
  issuer_id: issuer_id,
62
62
  key: OpenSSL::PKey::EC.new(key),
63
+ key_raw: key,
63
64
  duration: duration,
64
65
  in_house: in_house
65
66
  )
66
67
  end
67
68
 
68
- def initialize(key_id: nil, issuer_id: nil, key: nil, duration: nil, in_house: nil)
69
+ def initialize(key_id: nil, issuer_id: nil, key: nil, key_raw: nil, duration: nil, in_house: nil)
69
70
  @key_id = key_id
70
71
  @key = key
72
+ @key_raw = key_raw
71
73
  @issuer_id = issuer_id
72
74
  @duration = duration
73
75
  @in_house = in_house
@@ -97,6 +99,10 @@ module Spaceship
97
99
  def expired?
98
100
  @expiration < Time.now
99
101
  end
102
+
103
+ def write_key_to_file(path)
104
+ File.open(path, 'w') { |f| f.write(@key_raw) }
105
+ end
100
106
  end
101
107
  end
102
108
  end
metadata CHANGED
@@ -1,37 +1,37 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.179.0
4
+ version: 2.180.0
5
5
  platform: ruby
6
6
  authors:
7
- - Luka Mirosevic
8
- - Max Ott
9
- - Joshua Liebowitz
10
- - Jérôme Lacoste
11
- - Manu Wallner
12
- - Stefan Natchev
13
- - Andrew McBurney
7
+ - Jimmy Dee
14
8
  - Roger Oba
15
9
  - Daniel Jankowski
16
10
  - Satoshi Namai
17
- - Jimmy Dee
18
- - Kohki Miki
19
- - Iulian Onofrei
20
- - Fumiya Nakamura
21
- - Josh Holtz
22
- - Helmut Januschka
11
+ - Joshua Liebowitz
12
+ - Max Ott
13
+ - Manu Wallner
23
14
  - Felix Krause
24
- - Jan Piotrowski
15
+ - Fumiya Nakamura
25
16
  - Aaron Brager
26
17
  - Maksym Grebenets
27
18
  - Jorge Revuelta H
19
+ - Helmut Januschka
20
+ - Olivier Halligon
21
+ - Iulian Onofrei
22
+ - Stefan Natchev
23
+ - Andrew McBurney
24
+ - Josh Holtz
28
25
  - Danielle Tomlinson
26
+ - Kohki Miki
27
+ - Jan Piotrowski
28
+ - Jérôme Lacoste
29
+ - Luka Mirosevic
29
30
  - Matthew Ellis
30
- - Olivier Halligon
31
31
  autorequire:
32
32
  bindir: bin
33
33
  cert_chain: []
34
- date: 2021-03-26 00:00:00.000000000 Z
34
+ date: 2021-04-08 00:00:00.000000000 Z
35
35
  dependencies:
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: slack-notifier
@@ -1210,6 +1210,7 @@ files:
1210
1210
  - fastlane/lib/fastlane/actions/slather.rb
1211
1211
  - fastlane/lib/fastlane/actions/snapshot.rb
1212
1212
  - fastlane/lib/fastlane/actions/sonar.rb
1213
+ - fastlane/lib/fastlane/actions/sourcedocs.rb
1213
1214
  - fastlane/lib/fastlane/actions/spaceship_logs.rb
1214
1215
  - fastlane/lib/fastlane/actions/spaceship_stats.rb
1215
1216
  - fastlane/lib/fastlane/actions/splunkmint.rb
@@ -1468,7 +1469,6 @@ files:
1468
1469
  - gym/lib/assets/GymfileTemplate.swift
1469
1470
  - gym/lib/assets/wrap_xcodebuild/xcbuild-safe.sh
1470
1471
  - gym/lib/gym.rb
1471
- - gym/lib/gym/.runner.rb.swp
1472
1472
  - gym/lib/gym/code_signing_mapping.rb
1473
1473
  - gym/lib/gym/commands_generator.rb
1474
1474
  - gym/lib/gym/detect_values.rb