fastlane 2.214.0 → 2.217.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +98 -98
- data/deliver/lib/deliver/app_screenshot.rb +20 -10
- data/deliver/lib/deliver/runner.rb +2 -1
- data/deliver/lib/deliver/submit_for_review.rb +13 -0
- data/deliver/lib/deliver/upload_metadata.rb +58 -13
- data/fastlane/lib/fastlane/actions/docs/build_app.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +8 -8
- data/fastlane/lib/fastlane/actions/docs/check_app_store_metadata.md +3 -3
- data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +1 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +1 -1
- data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +6 -2
- data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +1 -1
- data/fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb +1 -1
- data/fastlane/lib/fastlane/actions/ensure_xcode_version.rb +4 -0
- data/fastlane/lib/fastlane/actions/git_branch.rb +1 -1
- data/fastlane/lib/fastlane/actions/install_on_device.rb +1 -1
- data/fastlane/lib/fastlane/actions/nexus_upload.rb +1 -0
- data/fastlane/lib/fastlane/actions/notarize.rb +17 -2
- data/fastlane/lib/fastlane/actions/slather.rb +17 -4
- data/fastlane/lib/fastlane/helper/git_helper.rb +3 -0
- data/fastlane/lib/fastlane/helper/xcodes_helper.rb +0 -3
- data/fastlane/lib/fastlane/lane.rb +9 -1
- data/fastlane/lib/fastlane/new_action.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +3 -3
- data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -2
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +5 -1
- data/fastlane/lib/fastlane/plugins/template/lib/fastlane/plugin/%plugin_name%/helper/%plugin_name%_helper.rb.erb +1 -1
- data/fastlane/lib/fastlane/runner.rb +1 -1
- data/fastlane/lib/fastlane/version.rb +2 -2
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +67 -7
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +1 -1
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +17 -1
- data/fastlane/swift/Precheckfile.swift +1 -1
- data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
- data/fastlane/swift/Scanfile.swift +1 -1
- data/fastlane/swift/ScanfileProtocol.swift +1 -1
- data/fastlane/swift/Screengrabfile.swift +1 -1
- data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
- data/fastlane/swift/Snapshotfile.swift +1 -1
- data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
- data/fastlane/swift/formatting/Brewfile.lock.json +22 -22
- data/fastlane_core/lib/fastlane_core/cert_checker.rb +2 -2
- data/fastlane_core/lib/fastlane_core/project.rb +4 -0
- data/fastlane_core/lib/fastlane_core/queue_worker.rb +1 -1
- data/frameit/lib/frameit/device_types.rb +1 -1
- data/gym/lib/gym/module.rb +13 -2
- data/gym/lib/gym/options.rb +1 -1
- data/match/lib/match/change_password.rb +3 -9
- data/match/lib/match/commands_generator.rb +3 -6
- data/match/lib/match/encryption.rb +1 -1
- data/match/lib/match/importer.rb +3 -31
- data/match/lib/match/migrate.rb +6 -2
- data/match/lib/match/nuke.rb +3 -25
- data/match/lib/match/options.rb +20 -0
- data/match/lib/match/runner.rb +16 -37
- data/match/lib/match/setup.rb +1 -1
- data/match/lib/match/storage/git_storage.rb +9 -1
- data/match/lib/match/storage/s3_storage.rb +6 -0
- data/match/lib/match/storage.rb +56 -5
- data/precheck/lib/precheck/rules/unreachable_urls_rule.rb +1 -1
- data/snapshot/lib/assets/SnapshotHelper.swift +13 -9
- data/snapshot/lib/snapshot/reports_generator.rb +48 -7
- data/spaceship/lib/spaceship/connect_api/api_client.rb +21 -2
- data/spaceship/lib/spaceship/connect_api/models/app.rb +3 -2
- data/spaceship/lib/spaceship/connect_api/models/app_info.rb +15 -9
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +7 -0
- data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +1 -0
- data/spaceship/lib/spaceship/connect_api/models/beta_group.rb +3 -1
- data/spaceship/lib/spaceship/connect_api/models/bundle_id.rb +4 -4
- data/spaceship/lib/spaceship/connect_api/models/certificate.rb +2 -2
- data/spaceship/lib/spaceship/connect_api/models/device.rb +2 -2
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +3 -2
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +14 -8
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +8 -2
- data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +0 -3
- data/supply/lib/supply/client.rb +47 -21
- data/supply/lib/supply/image_listing.rb +15 -0
- data/supply/lib/supply/options.rb +5 -0
- data/supply/lib/supply/setup.rb +1 -1
- data/supply/lib/supply/uploader.rb +60 -18
- data/supply/lib/supply.rb +1 -0
- data/trainer/lib/trainer/xcresult.rb +1 -1
- metadata +282 -273
@@ -408,7 +408,7 @@ fastlane match adhoc --force_for_new_devices
|
|
408
408
|
|
409
409
|
##### Templates (aka: custom entitlements)
|
410
410
|
|
411
|
-
|
411
|
+
_match_ can generate profiles that contain custom entitlements by passing in the entitlement's name with the `template_name` parameter.
|
412
412
|
|
413
413
|
```
|
414
414
|
match(type: "development",
|
@@ -441,7 +441,7 @@ fastlane deliver submit_build --build_number 830 --submission_information "{\"ex
|
|
441
441
|
|
442
442
|
### App Privacy Details
|
443
443
|
|
444
|
-
Starting on December 8, 2020, Apple announced that developers are required to provide app privacy details that will help users understand an app's privacy
|
444
|
+
Starting on December 8, 2020, Apple announced that developers are required to provide app privacy details that will help users understand an app's privacy practices. _deliver_ does not allow for updating of this information but this can be done with the _upload_app_privacy_details_to_app_store_ action. More information on [Uploading App Privacy Details](https://docs.fastlane.tools/uploading-app-privacy-details)
|
445
445
|
|
446
446
|
# Credentials
|
447
447
|
|
@@ -179,6 +179,12 @@ This can be done using the `--track_promote_to` parameter. The `--track_promote_
|
|
179
179
|
Before performing a new APK upload you may want to check existing track version codes or release names, or you may simply want to provide an informational lane that displays the currently promoted version codes or release name for the production track. You can use the `google_play_track_version_codes` action to retrieve existing version codes for a package and track. You can use the `google_play_track_release_names` action to retrieve existing release names for a package and track.
|
180
180
|
For more information, see the `fastlane action google_play_track_version_codes` and `fastlane action google_play_track_release_names` help output.
|
181
181
|
|
182
|
+
## Parallel uploads
|
183
|
+
|
184
|
+
By default _supply_ will spawn 10 threads to upload the metadata concurrently (_images, screenshots, texts_). If you want to change this, set either `DELIVER_NUMBER_OF_THREADS` or `FL_NUMBER_OF_THREADS` environment variable to any value between 1 and 10.
|
185
|
+
|
186
|
+
If you want _supply_ to upload with more than 10 threads in parallel then you need to **additionally** set `FL_MAX_NUMBER_OF_THREADS` environment variable to the max number of parallel upload threads you wish to have (**Warning ⚠️** use this at your own risk!).
|
187
|
+
|
182
188
|
## Migration from AndroidPublisherV2 to AndroidPublisherV3 in _fastlane_ 2.135.0
|
183
189
|
|
184
190
|
### New Options
|
@@ -200,5 +206,3 @@ For more information, see the `fastlane action google_play_track_version_codes`
|
|
200
206
|
- Google Play will automatically remove releases that are superseded now
|
201
207
|
- `:deactivate_on_promote`
|
202
208
|
- Google Play will automatically deactivate a release from its previous track on promote
|
203
|
-
|
204
|
-
:
|
@@ -4,7 +4,7 @@
|
|
4
4
|
|
5
5
|
###### The best way to manage your TestFlight testers and builds from your terminal
|
6
6
|
|
7
|
-
|
7
|
+
_pilot_ makes it easier to manage your app on Apple’s TestFlight. You can:
|
8
8
|
|
9
9
|
- Upload & distribute builds
|
10
10
|
- Add & remove testers
|
@@ -56,7 +56,7 @@ module Fastlane
|
|
56
56
|
<<~DETAILS
|
57
57
|
Download the universal APK of a given version code from the Google Play Console.
|
58
58
|
|
59
|
-
This uses
|
59
|
+
This uses _fastlane_ `supply` (and the `AndroidPublisher` Google API) to download the Universal APK
|
60
60
|
generated by Google after you uploaded an `.aab` bundle to the Play Console.
|
61
61
|
|
62
62
|
See https://developers.google.com/android-publisher/api-ref/rest/v3/generatedapks/list
|
@@ -119,6 +119,10 @@ module Fastlane
|
|
119
119
|
def self.is_supported?(platform)
|
120
120
|
[:ios, :mac].include?(platform)
|
121
121
|
end
|
122
|
+
|
123
|
+
def self.deprecated_notes
|
124
|
+
"The xcode-install gem, which this action depends on, has been sunset. Please migrate to [xcodes](https://docs.fastlane.tools/actions/xcodes). You can find a migration guide here: [xcpretty/xcode-install/MIGRATION.md](https://github.com/xcpretty/xcode-install/blob/master/MIGRATION.md)"
|
125
|
+
end
|
122
126
|
end
|
123
127
|
end
|
124
128
|
end
|
@@ -16,7 +16,7 @@ module Fastlane
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def self.details
|
19
|
-
"If no branch could be found, this action will return an empty string. This is a wrapper for the internal action Actions.git_branch"
|
19
|
+
"If no branch could be found, this action will return an empty string. If `FL_GIT_BRANCH_DONT_USE_ENV_VARS` is `true`, it'll ignore CI ENV vars. This is a wrapper for the internal action Actions.git_branch"
|
20
20
|
end
|
21
21
|
|
22
22
|
def self.available_options
|
@@ -68,7 +68,7 @@ module Fastlane
|
|
68
68
|
end
|
69
69
|
|
70
70
|
def self.details
|
71
|
-
"Installs the ipa on the device. If no id is given, the first found iOS device will be used. Works via USB or Wi-Fi. This requires `ios-deploy` to be installed. Please have a look at [ios-deploy](https://github.com/ios-control/ios-deploy). To quickly install it, use `
|
71
|
+
"Installs the ipa on the device. If no id is given, the first found iOS device will be used. Works via USB or Wi-Fi. This requires `ios-deploy` to be installed. Please have a look at [ios-deploy](https://github.com/ios-control/ios-deploy). To quickly install it, use `brew install ios-deploy`"
|
72
72
|
end
|
73
73
|
|
74
74
|
def self.is_supported?(platform)
|
@@ -139,6 +139,7 @@ module Fastlane
|
|
139
139
|
FastlaneCore::ConfigItem.new(key: :password,
|
140
140
|
env_name: "FL_NEXUS_PASSWORD",
|
141
141
|
description: "Nexus password",
|
142
|
+
sensitive: true,
|
142
143
|
optional: false),
|
143
144
|
FastlaneCore::ConfigItem.new(key: :ssl_verify,
|
144
145
|
env_name: "FL_NEXUS_SSL_VERIFY",
|
@@ -85,9 +85,9 @@ module Fastlane
|
|
85
85
|
notarization_info = JSON.parse(submit_response)
|
86
86
|
|
87
87
|
# Staple
|
88
|
+
submission_id = notarization_info["id"]
|
88
89
|
case notarization_info['status']
|
89
90
|
when 'Accepted'
|
90
|
-
submission_id = notarization_info["id"]
|
91
91
|
UI.success("Successfully uploaded package to notarization service with request identifier #{submission_id}")
|
92
92
|
|
93
93
|
if skip_stapling
|
@@ -100,7 +100,22 @@ module Fastlane
|
|
100
100
|
UI.success("Successfully notarized and stapled package")
|
101
101
|
end
|
102
102
|
when 'Invalid'
|
103
|
-
|
103
|
+
if submission_id && print_log
|
104
|
+
log_request_parts = [
|
105
|
+
"xcrun notarytool log #{submission_id}"
|
106
|
+
] + auth_parts
|
107
|
+
log_request_command = log_request_parts.join(' ')
|
108
|
+
log_request_response = Actions.sh(
|
109
|
+
log_request_command,
|
110
|
+
log: verbose,
|
111
|
+
error_callback: lambda { |msg|
|
112
|
+
UI.error("Error requesting the notarization log: #{msg}")
|
113
|
+
}
|
114
|
+
)
|
115
|
+
UI.user_error!("Could not notarize package with message '#{log_request_response}'")
|
116
|
+
else
|
117
|
+
UI.user_error!("Could not notarize package. To see the error, please set 'print_log' to true.")
|
118
|
+
end
|
104
119
|
else
|
105
120
|
UI.crash!("Could not notarize package with status '#{notarization_info['status']}'")
|
106
121
|
end
|
@@ -35,7 +35,8 @@ module Fastlane
|
|
35
35
|
binary_basename: '--binary-basename',
|
36
36
|
arch: '--arch',
|
37
37
|
source_files: '--source-files',
|
38
|
-
decimals: '--decimals'
|
38
|
+
decimals: '--decimals',
|
39
|
+
ymlfile: '--ymlfile'
|
39
40
|
}.freeze
|
40
41
|
|
41
42
|
def self.run(params)
|
@@ -51,8 +52,8 @@ module Fastlane
|
|
51
52
|
sh(command)
|
52
53
|
end
|
53
54
|
|
54
|
-
def self.has_config_file
|
55
|
-
File.file?('.slather.yml')
|
55
|
+
def self.has_config_file?(params)
|
56
|
+
params[:ymlfile] ? File.file?(params[:ymlfile]) : File.file?('.slather.yml')
|
56
57
|
end
|
57
58
|
|
58
59
|
def self.slather_version
|
@@ -64,12 +65,20 @@ module Fastlane
|
|
64
65
|
Gem::Version.new('2.4.1') <= Gem::Version.new(slather_version)
|
65
66
|
end
|
66
67
|
|
68
|
+
def self.ymlfile_available?
|
69
|
+
Gem::Version.new('2.8.0') <= Gem::Version.new(slather_version)
|
70
|
+
end
|
71
|
+
|
67
72
|
def self.validate_params!(params)
|
68
73
|
if params[:configuration]
|
69
74
|
UI.user_error!('configuration option is available since version 2.4.1') unless configuration_available?
|
70
75
|
end
|
71
76
|
|
72
|
-
if params[:
|
77
|
+
if params[:ymlfile]
|
78
|
+
UI.user_error!('ymlfile option is available since version 2.8.0') unless ymlfile_available?
|
79
|
+
end
|
80
|
+
|
81
|
+
if params[:proj] || has_config_file?(params)
|
73
82
|
true
|
74
83
|
else
|
75
84
|
UI.user_error!("You have to provide a project with `:proj` or use a .slather.yml")
|
@@ -285,6 +294,10 @@ module Fastlane
|
|
285
294
|
description: "The amount of decimals to use for % coverage reporting",
|
286
295
|
skip_type_validation: true, # allow Integer, String
|
287
296
|
default_value: false,
|
297
|
+
optional: true),
|
298
|
+
FastlaneCore::ConfigItem.new(key: :ymlfile,
|
299
|
+
env_name: "FL_SLATHER_YMLFILE",
|
300
|
+
description: "Relative path to a file used in place of '.slather.yml'",
|
288
301
|
optional: true)
|
289
302
|
]
|
290
303
|
end
|
@@ -121,7 +121,10 @@ module Fastlane
|
|
121
121
|
|
122
122
|
# Returns the current git branch, or "HEAD" if it's not checked out to any branch
|
123
123
|
# Can be replaced using the environment variable `GIT_BRANCH`
|
124
|
+
# unless `FL_GIT_BRANCH_DONT_USE_ENV_VARS` is `true`
|
124
125
|
def self.git_branch
|
126
|
+
return self.git_branch_name_using_HEAD if FastlaneCore::Env.truthy?('FL_GIT_BRANCH_DONT_USE_ENV_VARS')
|
127
|
+
|
125
128
|
env_name = SharedValues::GIT_BRANCH_ENV_VARS.find { |env_var| FastlaneCore::Env.truthy?(env_var) }
|
126
129
|
ENV.fetch(env_name.to_s) do
|
127
130
|
self.git_branch_name_using_HEAD
|
@@ -18,9 +18,6 @@ module Fastlane
|
|
18
18
|
module Verify
|
19
19
|
def self.requirement(req)
|
20
20
|
UI.user_error!("Version must be specified") if req.nil? || req.to_s.strip.size == 0
|
21
|
-
Gem::Requirement.new(req.to_s)
|
22
|
-
rescue Gem::Requirement::BadRequirementError
|
23
|
-
UI.user_error!("The requirement '#{req}' is not a valid RubyGems style requirement")
|
24
21
|
end
|
25
22
|
end
|
26
23
|
end
|
@@ -24,11 +24,19 @@ module Fastlane
|
|
24
24
|
self.platform = platform
|
25
25
|
self.name = name
|
26
26
|
self.description = description
|
27
|
-
|
27
|
+
# We want to support _both_ lanes expecting a `Hash` (like `lane :foo do |options|`), and lanes expecting
|
28
|
+
# keyword parameters (like `lane :foo do |param1:, param2:, param3: 'default value'|`)
|
29
|
+
block_expects_keywords = !block.nil? && block.parameters.any? { |type, _| [:key, :keyreq].include?(type) }
|
30
|
+
# Conversion of the `Hash` parameters (passed by `Lane#call`) into keywords has to be explicit in Ruby 3
|
31
|
+
# https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/
|
32
|
+
self.block = block_expects_keywords ? proc { |options| block.call(**options) } : block
|
28
33
|
self.is_private = is_private
|
29
34
|
end
|
30
35
|
|
31
36
|
# Execute this lane
|
37
|
+
#
|
38
|
+
# @param [Hash] parameters The Hash of parameters to pass to the lane
|
39
|
+
#
|
32
40
|
def call(parameters)
|
33
41
|
block.call(parameters || {})
|
34
42
|
end
|
@@ -7,7 +7,7 @@ module Fastlane
|
|
7
7
|
end
|
8
8
|
|
9
9
|
def self.fetch_name
|
10
|
-
puts("Must be
|
10
|
+
puts("Must be lowercase, and use a '_' between words. Do not use '.'".green)
|
11
11
|
puts("examples: 'testflight', 'upload_to_s3'".green)
|
12
12
|
name = UI.input("Name of your action: ")
|
13
13
|
until name_valid?(name)
|
@@ -45,7 +45,7 @@ module Fastlane
|
|
45
45
|
@ui.message("\nThe gem name '#{gem_name}' is already taken on RubyGems, please choose a different plugin name.")
|
46
46
|
else
|
47
47
|
# That's a naming error
|
48
|
-
@ui.message("\nPlugin names can only contain
|
48
|
+
@ui.message("\nPlugin names can only contain lowercase letters, numbers, and underscores")
|
49
49
|
@ui.message("and should not contain 'fastlane' or 'plugin'.")
|
50
50
|
end
|
51
51
|
end
|
@@ -54,7 +54,7 @@ module Fastlane
|
|
54
54
|
end
|
55
55
|
|
56
56
|
def plugin_name_valid?(name)
|
57
|
-
# Only
|
57
|
+
# Only lowercase letters, numbers and underscores allowed
|
58
58
|
/^[a-z0-9_]+$/ =~ name &&
|
59
59
|
# Does not contain the words 'fastlane' or 'plugin' since those will become
|
60
60
|
# part of the gem name
|
@@ -79,7 +79,7 @@ module Fastlane
|
|
79
79
|
name = name.to_s.downcase
|
80
80
|
fixes = {
|
81
81
|
/[\- ]/ => '_', # dashes and spaces become underscores
|
82
|
-
/[^a-z0-9_]/ => '', # anything other than
|
82
|
+
/[^a-z0-9_]/ => '', # anything other than lowercase letters, numbers and underscores is removed
|
83
83
|
/fastlane[_]?/ => '', # 'fastlane' or 'fastlane_' is removed
|
84
84
|
/plugin[_]?/ => '' # 'plugin' or 'plugin_' is removed
|
85
85
|
}
|
@@ -13,9 +13,8 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.license = "MIT"
|
14
14
|
|
15
15
|
spec.files = Dir["lib/**/*"] + %w(README.md LICENSE)
|
16
|
-
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
17
16
|
spec.require_paths = ['lib']
|
18
|
-
|
17
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
19
18
|
spec.required_ruby_version = '>= 2.6'
|
20
19
|
|
21
20
|
# Don't add a dependency to fastlane or fastlane_re
|
@@ -124,6 +124,8 @@ Style/GuardClause:
|
|
124
124
|
Enabled: false
|
125
125
|
Style/StringLiterals:
|
126
126
|
Enabled: false
|
127
|
+
Style/QuotedSymbols:
|
128
|
+
Enabled: false
|
127
129
|
Style/ConditionalAssignment:
|
128
130
|
Enabled: false
|
129
131
|
Style/RedundantSelf:
|
@@ -164,7 +166,7 @@ Style/CollectionMethods:
|
|
164
166
|
Enabled: false
|
165
167
|
Style/MethodCallWithArgsParentheses:
|
166
168
|
Enabled: true
|
167
|
-
|
169
|
+
AllowedMethods:
|
168
170
|
- require
|
169
171
|
- require_relative
|
170
172
|
- fastlane_require
|
@@ -186,3 +188,5 @@ Style/MethodCallWithArgsParentheses:
|
|
186
188
|
- context
|
187
189
|
- before
|
188
190
|
- after
|
191
|
+
Gemspec/DevelopmentDependencies:
|
192
|
+
Enabled: false
|
@@ -15,7 +15,7 @@ module Fastlane
|
|
15
15
|
|
16
16
|
# This will take care of executing **one** lane. That's when the user triggers a lane from the CLI for example
|
17
17
|
# This method is **not** executed when switching a lane
|
18
|
-
# @param
|
18
|
+
# @param lane The name of the lane to execute
|
19
19
|
# @param platform The name of the platform to execute
|
20
20
|
# @param parameters [Hash] The parameters passed from the command line to the lane
|
21
21
|
def execute(lane, platform = nil, parameters = nil)
|
@@ -1,6 +1,6 @@
|
|
1
1
|
module Fastlane
|
2
|
-
VERSION = '2.
|
2
|
+
VERSION = '2.217.0'.freeze
|
3
3
|
DESCRIPTION = "The easiest way to automate beta deployments and releases for your iOS and Android apps".freeze
|
4
4
|
MINIMUM_XCODE_RELEASE = "7.0".freeze
|
5
|
-
RUBOCOP_REQUIREMENT = '1.
|
5
|
+
RUBOCOP_REQUIREMENT = '1.50.2'.freeze
|
6
6
|
end
|