fastlane 2.189.0 → 2.193.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 +92 -92
- data/deliver/lib/deliver/app_screenshot.rb +2 -1
- data/deliver/lib/deliver/app_screenshot_iterator.rb +2 -2
- data/deliver/lib/deliver/loader.rb +1 -1
- data/deliver/lib/deliver/options.rb +6 -0
- data/deliver/lib/deliver/runner.rb +9 -1
- data/deliver/lib/deliver/screenshot_comparable.rb +62 -0
- data/deliver/lib/deliver/sync_screenshots.rb +200 -0
- data/fastlane/lib/assets/completions/completion.bash +4 -1
- data/fastlane/lib/assets/completions/completion.zsh +6 -5
- data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +1 -1
- data/fastlane/lib/fastlane/actions/bundle_install.rb +13 -1
- data/fastlane/lib/fastlane/actions/clean_cocoapods_cache.rb +25 -1
- data/fastlane/lib/fastlane/actions/create_xcframework.rb +97 -17
- data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +2 -2
- data/fastlane/lib/fastlane/actions/docs/upload_to_app_store.md.erb +2 -2
- data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +1 -1
- data/fastlane/lib/fastlane/actions/notarize.rb +77 -1
- data/fastlane/lib/fastlane/actions/push_git_tags.rb +1 -1
- data/fastlane/lib/fastlane/actions/sync_code_signing.rb +1 -1
- data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +3 -1
- data/fastlane/lib/fastlane/actions/zip.rb +86 -21
- data/fastlane/lib/fastlane/features.rb +3 -0
- data/fastlane/lib/fastlane/version.rb +1 -1
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +5 -1
- data/fastlane/swift/Fastlane.swift +121 -25
- 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 +1 -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 +9 -9
- data/fastlane_core/lib/fastlane_core/build_watcher.rb +25 -6
- data/fastlane_core/lib/fastlane_core/keychain_importer.rb +11 -4
- data/fastlane_core/lib/fastlane_core/ui/disable_colors.rb +1 -0
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +41 -0
- data/match/lib/match/runner.rb +5 -5
- data/match/lib/match/storage/.git_storage.rb.swp +0 -0
- data/match/lib/match/storage/.interface.rb.swp +0 -0
- data/pilot/lib/pilot/build_manager.rb +14 -4
- data/pilot/lib/pilot/manager.rb +3 -1
- data/pilot/lib/pilot/options.rb +20 -1
- data/produce/lib/produce/commands_generator.rb +28 -0
- data/produce/lib/produce/service.rb +16 -1
- data/scan/lib/scan/xcpretty_reporter_options_generator.rb +1 -1
- data/sigh/lib/sigh/options.rb +2 -1
- data/spaceship/lib/spaceship/client.rb +6 -0
- data/spaceship/lib/spaceship/connect_api/api_client.rb +15 -1
- data/spaceship/lib/spaceship/connect_api/models/app.rb +9 -1
- data/spaceship/lib/spaceship/connect_api/models/build.rb +4 -0
- data/spaceship/lib/spaceship/connect_api/models/build_beta_detail.rb +4 -0
- data/spaceship/lib/spaceship/connect_api/models/capabilities.rb +27 -0
- data/spaceship/lib/spaceship/connect_api/models/user.rb +17 -3
- data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +26 -5
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +5 -0
- data/spaceship/lib/spaceship/connect_api/testflight/.testflight.rb.swp +0 -0
- data/spaceship/lib/spaceship/connect_api/testflight/client.rb +3 -0
- data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +46 -5
- data/spaceship/lib/spaceship/connect_api/token.rb +4 -1
- data/spaceship/lib/spaceship/connect_api/tunes/client.rb +3 -0
- data/spaceship/lib/spaceship/connect_api/users/client.rb +3 -0
- data/spaceship/lib/spaceship/connect_api/users/users.rb +58 -3
- data/spaceship/lib/spaceship/connect_api.rb +1 -0
- data/spaceship/lib/spaceship/tunes/tunes_client.rb +3 -0
- data/supply/lib/supply/client.rb +38 -5
- data/supply/lib/supply/options.rb +7 -0
- data/supply/lib/supply/uploader.rb +1 -1
- metadata +39 -19
@@ -4,6 +4,7 @@ _fastlane_complete() {
|
|
4
4
|
COMPREPLY=()
|
5
5
|
local word="${COMP_WORDS[COMP_CWORD]}"
|
6
6
|
local completions=""
|
7
|
+
local file
|
7
8
|
|
8
9
|
# look for Fastfile either in this directory or fastlane/ then grab the lane names
|
9
10
|
if [[ -e "Fastfile" ]]; then
|
@@ -12,10 +13,12 @@ _fastlane_complete() {
|
|
12
13
|
file="fastlane/Fastfile"
|
13
14
|
elif [[ -e ".fastlane/Fastfile" ]]; then
|
14
15
|
file=".fastlane/Fastfile"
|
16
|
+
else
|
17
|
+
return 1
|
15
18
|
fi
|
16
19
|
|
17
20
|
# parse 'beta' out of 'lane :beta do', etc
|
18
|
-
completions
|
21
|
+
completions="$(sed -En 's/^[ ]*lane +:([^ ]+).*$/\1/p' "$file")"
|
19
22
|
completions="$completions update_fastlane"
|
20
23
|
|
21
24
|
COMPREPLY=( $(compgen -W "$completions" -- "$word") )
|
@@ -1,7 +1,7 @@
|
|
1
1
|
#!/bin/zsh
|
2
2
|
|
3
3
|
_fastlane_complete() {
|
4
|
-
local word completions
|
4
|
+
local word completions file
|
5
5
|
word="$1"
|
6
6
|
|
7
7
|
# look for Fastfile either in this directory or fastlane/ then grab the lane names
|
@@ -11,13 +11,14 @@ _fastlane_complete() {
|
|
11
11
|
file="fastlane/Fastfile"
|
12
12
|
elif [[ -e ".fastlane/Fastfile" ]] then
|
13
13
|
file=".fastlane/Fastfile"
|
14
|
+
else
|
15
|
+
return 1
|
14
16
|
fi
|
15
17
|
|
16
18
|
# parse 'beta' out of 'lane :beta do', etc
|
17
|
-
completions
|
18
|
-
completions="$completions
|
19
|
-
update_fastlane"
|
19
|
+
completions="$(sed -En 's/^[ ]*lane +:([^ ]+).*$/\1/p' "$file")"
|
20
|
+
completions="$completions update_fastlane"
|
20
21
|
|
21
|
-
reply=( "${
|
22
|
+
reply=( "${=completions}" )
|
22
23
|
}
|
23
24
|
|
@@ -80,7 +80,7 @@ module Fastlane
|
|
80
80
|
env_name: "APP_STORE_CONNECT_API_KEY_DURATION",
|
81
81
|
description: "The token session duration",
|
82
82
|
optional: true,
|
83
|
-
default_value: Spaceship::ConnectAPI::Token::
|
83
|
+
default_value: Spaceship::ConnectAPI::Token::DEFAULT_TOKEN_DURATION,
|
84
84
|
type: Integer,
|
85
85
|
verify_block: proc do |value|
|
86
86
|
UI.user_error!("The duration can't be more than 1200 (20 minutes) and the value entered was '#{value}'") unless value <= 1200
|
@@ -24,6 +24,8 @@ module Fastlane
|
|
24
24
|
cmd << "--trust-policy" if params[:trust_policy]
|
25
25
|
cmd << "--without #{params[:without]}" if params[:without]
|
26
26
|
cmd << "--with #{params[:with]}" if params[:with]
|
27
|
+
cmd << "--frozen" if params[:frozen]
|
28
|
+
cmd << "--redownload" if params[:redownload]
|
27
29
|
|
28
30
|
return sh(cmd.join(' '))
|
29
31
|
else
|
@@ -146,7 +148,17 @@ module Fastlane
|
|
146
148
|
FastlaneCore::ConfigItem.new(key: :with,
|
147
149
|
env_name: "FL_BUNDLE_INSTALL_WITH",
|
148
150
|
description: "Include gems that are part of the specified named group",
|
149
|
-
optional: true)
|
151
|
+
optional: true),
|
152
|
+
FastlaneCore::ConfigItem.new(key: :frozen,
|
153
|
+
env_name: "FL_BUNDLE_INSTALL_FROZEN",
|
154
|
+
description: "Don't allow the Gemfile.lock to be updated after install",
|
155
|
+
type: Boolean,
|
156
|
+
default_value: false),
|
157
|
+
FastlaneCore::ConfigItem.new(key: :redownload,
|
158
|
+
env_name: "FL_BUNDLE_INSTALL_REDOWNLOAD",
|
159
|
+
description: "Force download every gem, even if the required versions are already available locally",
|
160
|
+
type: Boolean,
|
161
|
+
default_value: false)
|
150
162
|
]
|
151
163
|
end
|
152
164
|
end
|
@@ -7,6 +7,10 @@ module Fastlane
|
|
7
7
|
cmd = ['pod cache clean']
|
8
8
|
|
9
9
|
cmd << params[:name].to_s if params[:name]
|
10
|
+
cmd << '--no-ansi' if params[:no_ansi]
|
11
|
+
cmd << '--verbose' if params[:verbose]
|
12
|
+
cmd << '--silent' if params[:silent]
|
13
|
+
cmd << '--allow-root' if params[:allow_root]
|
10
14
|
cmd << '--all'
|
11
15
|
|
12
16
|
Actions.sh(cmd.join(' '))
|
@@ -24,7 +28,27 @@ module Fastlane
|
|
24
28
|
optional: true,
|
25
29
|
verify_block: proc do |value|
|
26
30
|
UI.user_error!("You must specify pod name which should be removed from cache") if value.to_s.empty?
|
27
|
-
end)
|
31
|
+
end),
|
32
|
+
FastlaneCore::ConfigItem.new(key: :no_ansi,
|
33
|
+
env_name: "FL_CLEAN_COCOAPODS_CACHE_NO_ANSI",
|
34
|
+
description: "Show output without ANSI codes",
|
35
|
+
type: Boolean,
|
36
|
+
default_value: false),
|
37
|
+
FastlaneCore::ConfigItem.new(key: :verbose,
|
38
|
+
env_name: "FL_CLEAN_COCOAPODS_CACHE_VERBOSE",
|
39
|
+
description: "Show more debugging information",
|
40
|
+
type: Boolean,
|
41
|
+
default_value: false),
|
42
|
+
FastlaneCore::ConfigItem.new(key: :silent,
|
43
|
+
env_name: "FL_CLEAN_COCOAPODS_CACHE_SILENT",
|
44
|
+
description: "Show nothing",
|
45
|
+
type: Boolean,
|
46
|
+
default_value: false),
|
47
|
+
FastlaneCore::ConfigItem.new(key: :allow_root,
|
48
|
+
env_name: "FL_CLEAN_COCOAPODS_CACHE_ALLOW_ROOT",
|
49
|
+
description: "Allows CocoaPods to run as root",
|
50
|
+
type: Boolean,
|
51
|
+
default_value: false)
|
28
52
|
]
|
29
53
|
end
|
30
54
|
|
@@ -5,12 +5,19 @@ module Fastlane
|
|
5
5
|
end
|
6
6
|
|
7
7
|
class CreateXcframeworkAction < Action
|
8
|
+
PARAMETERS_TO_OPTIONS = { headers: '-headers', dsyms: '-debug-symbols' }
|
9
|
+
|
8
10
|
def self.run(params)
|
9
|
-
|
11
|
+
artifacts = normalized_artifact_info(params[:frameworks], [:dsyms]) ||
|
12
|
+
normalized_artifact_info(params[:frameworks_with_dsyms], [:dsyms]) ||
|
13
|
+
normalized_artifact_info(params[:libraries], [:headers, :dsyms]) ||
|
14
|
+
normalized_artifact_info(params[:libraries_with_headers_or_dsyms], [:headers, :dsyms])
|
15
|
+
|
16
|
+
UI.user_error!("Please provide either :frameworks, :frameworks_with_dsyms, :libraries or :libraries_with_headers_or_dsyms to be packaged into the xcframework") unless artifacts
|
10
17
|
|
18
|
+
artifacts_type = params[:frameworks] || params[:frameworks_with_dsyms] ? '-framework' : '-library'
|
11
19
|
create_command = ['xcodebuild', '-create-xcframework']
|
12
|
-
create_command <<
|
13
|
-
create_command << params[:libraries].map { |library, headers| ['-library', "\"#{library}\""] + (headers.empty? ? [] : ['-headers', "\"#{headers}\""]) } if params[:libraries]
|
20
|
+
create_command << artifacts.map { |artifact, artifact_info| [artifacts_type, "\"#{artifact}\""] + artifact_info_as_options(artifact_info) }.flatten
|
14
21
|
create_command << ['-output', "\"#{params[:output]}\""]
|
15
22
|
create_command << ['-allow-internal-distribution'] if params[:allow_internal_distribution]
|
16
23
|
|
@@ -24,6 +31,32 @@ module Fastlane
|
|
24
31
|
sh(create_command)
|
25
32
|
end
|
26
33
|
|
34
|
+
def self.normalized_artifact_info(artifacts_with_info, valid_info)
|
35
|
+
case artifacts_with_info
|
36
|
+
when Array
|
37
|
+
artifacts_with_info.map { |artifact| [artifact, {}] }.to_h
|
38
|
+
when Hash
|
39
|
+
# Convert keys of artifact info to symbols ('dsyms' to :dsyms) and only keep keys we are interested in
|
40
|
+
# For example with valid_info = [:dsyms]
|
41
|
+
# { 'FrameworkA.framework' => { 'dsyms' => 'FrameworkA.framework.dSYM', 'foo' => bar } }
|
42
|
+
# gets converted to
|
43
|
+
# { 'FrameworkA.framework' => { dsyms: 'FrameworkA.framework.dSYM' } }
|
44
|
+
artifacts_with_info.transform_values { |artifact_info| artifact_info.transform_keys(&:to_sym).slice(*valid_info) }
|
45
|
+
else
|
46
|
+
artifacts_with_info
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.artifact_info_as_options(artifact_info)
|
51
|
+
artifact_info.map { |type, file| [PARAMETERS_TO_OPTIONS[type], "\"#{file}\""] }.flatten
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.check_artifact_info(artifact_info)
|
55
|
+
UI.user_error!("Headers and dSYMs information should be a hash") unless artifact_info.kind_of?(Hash)
|
56
|
+
UI.user_error!("#{artifact_info[:headers]} doesn't exist or is not a directory") if artifact_info[:headers] && !File.directory?(artifact_info[:headers])
|
57
|
+
UI.user_error!("#{artifact_info[:dsyms]} doesn't seem to be a dSYM archive") if artifact_info[:dsyms] && !File.directory?(artifact_info[:dsyms])
|
58
|
+
end
|
59
|
+
|
27
60
|
#####################################################
|
28
61
|
# @!group Documentation
|
29
62
|
#####################################################
|
@@ -37,13 +70,31 @@ module Fastlane
|
|
37
70
|
Utility for packaging multiple build configurations of a given library
|
38
71
|
or framework into a single xcframework.
|
39
72
|
|
40
|
-
If you want to package several frameworks just provide
|
41
|
-
|
73
|
+
If you want to package several frameworks just provide one of:
|
74
|
+
|
75
|
+
* An array containing the list of frameworks using the :frameworks parameter
|
76
|
+
(if they have no associated dSYMs):
|
77
|
+
['FrameworkA.framework', 'FrameworkB.framework']
|
78
|
+
|
79
|
+
* A hash containing the list of frameworks with their dSYMs using the
|
80
|
+
:frameworks_with_dsyms parameter:
|
81
|
+
{
|
82
|
+
'FrameworkA.framework' => {},
|
83
|
+
'FrameworkB.framework' => { dsyms: 'FrameworkB.framework.dSYM' }
|
84
|
+
}
|
42
85
|
|
43
|
-
If you want to package several libraries
|
44
|
-
|
45
|
-
|
46
|
-
|
86
|
+
If you want to package several libraries just provide one of:
|
87
|
+
|
88
|
+
* An array containing the list of libraries using the :libraries parameter
|
89
|
+
(if they have no associated headers or dSYMs):
|
90
|
+
['LibraryA.so', 'LibraryB.so']
|
91
|
+
|
92
|
+
* A hash containing the list of libraries with their headers and dSYMs
|
93
|
+
using the :libraries_with_headers_or_dsyms parameter:
|
94
|
+
{
|
95
|
+
'LibraryA.so' => { dsyms: 'libraryA.so.dSYM' },
|
96
|
+
'LibraryB.so' => { headers: 'headers' }
|
97
|
+
}
|
47
98
|
|
48
99
|
Finally specify the location of the xcframework to be generated using the :output
|
49
100
|
parameter.
|
@@ -54,27 +105,54 @@ module Fastlane
|
|
54
105
|
[
|
55
106
|
FastlaneCore::ConfigItem.new(key: :frameworks,
|
56
107
|
env_name: "FL_CREATE_XCFRAMEWORK_FRAMEWORKS",
|
57
|
-
description: "Frameworks to add to the target xcframework",
|
108
|
+
description: "Frameworks (without dSYMs) to add to the target xcframework",
|
58
109
|
type: Array,
|
59
110
|
optional: true,
|
60
|
-
conflicting_options: [:libraries],
|
111
|
+
conflicting_options: [:frameworks_with_dsyms, :libraries, :libraries_with_headers_or_dsyms],
|
61
112
|
verify_block: proc do |value|
|
62
|
-
value.each do |framework|
|
113
|
+
normalized_artifact_info(value, [:dsyms]).each do |framework, framework_info|
|
63
114
|
UI.user_error!("#{framework} doesn't end with '.framework'. Is this really a framework?") unless framework.end_with?('.framework')
|
64
115
|
UI.user_error!("Couldn't find framework at #{framework}") unless File.exist?(framework)
|
65
116
|
UI.user_error!("#{framework} doesn't seem to be a framework") unless File.directory?(framework)
|
117
|
+
check_artifact_info(framework_info)
|
118
|
+
end
|
119
|
+
end),
|
120
|
+
FastlaneCore::ConfigItem.new(key: :frameworks_with_dsyms,
|
121
|
+
env_name: "FL_CREATE_XCFRAMEWORK_FRAMEWORKS_WITH_DSYMS",
|
122
|
+
description: "Frameworks (with dSYMs) to add to the target xcframework",
|
123
|
+
type: Hash,
|
124
|
+
optional: true,
|
125
|
+
conflicting_options: [:frameworks, :libraries, :libraries_with_headers_or_dsyms],
|
126
|
+
verify_block: proc do |value|
|
127
|
+
normalized_artifact_info(value, [:dsyms]).each do |framework, framework_info|
|
128
|
+
UI.user_error!("#{framework} doesn't end with '.framework'. Is this really a framework?") unless framework.end_with?('.framework')
|
129
|
+
UI.user_error!("Couldn't find framework at #{framework}") unless File.exist?(framework)
|
130
|
+
UI.user_error!("#{framework} doesn't seem to be a framework") unless File.directory?(framework)
|
131
|
+
check_artifact_info(framework_info)
|
66
132
|
end
|
67
133
|
end),
|
68
134
|
FastlaneCore::ConfigItem.new(key: :libraries,
|
69
135
|
env_name: "FL_CREATE_XCFRAMEWORK_LIBRARIES",
|
70
|
-
description: "Libraries to add to the target xcframework
|
136
|
+
description: "Libraries (without headers or dSYMs) to add to the target xcframework",
|
137
|
+
type: Array,
|
138
|
+
optional: true,
|
139
|
+
conflicting_options: [:frameworks, :frameworks_with_dsyms, :libraries_with_headers_or_dsyms],
|
140
|
+
verify_block: proc do |value|
|
141
|
+
normalized_artifact_info(value, [:headers, :dsyms]).each do |library, library_info|
|
142
|
+
UI.user_error!("Couldn't find library at #{library}") unless File.exist?(library)
|
143
|
+
check_artifact_info(library_info)
|
144
|
+
end
|
145
|
+
end),
|
146
|
+
FastlaneCore::ConfigItem.new(key: :libraries_with_headers_or_dsyms,
|
147
|
+
env_name: "FL_CREATE_XCFRAMEWORK_LIBRARIES_WITH_HEADERS_OR_DSYMS",
|
148
|
+
description: "Libraries (with headers or dSYMs) to add to the target xcframework",
|
71
149
|
type: Hash,
|
72
150
|
optional: true,
|
73
|
-
conflicting_options: [:frameworks],
|
151
|
+
conflicting_options: [:frameworks, :frameworks_with_dsyms, :libraries],
|
74
152
|
verify_block: proc do |value|
|
75
|
-
value.each do |library,
|
153
|
+
normalized_artifact_info(value, [:headers, :dsyms]).each do |library, library_info|
|
76
154
|
UI.user_error!("Couldn't find library at #{library}") unless File.exist?(library)
|
77
|
-
|
155
|
+
check_artifact_info(library_info)
|
78
156
|
end
|
79
157
|
end),
|
80
158
|
FastlaneCore::ConfigItem.new(key: :output,
|
@@ -103,7 +181,9 @@ module Fastlane
|
|
103
181
|
def self.example_code
|
104
182
|
[
|
105
183
|
"create_xcframework(frameworks: ['FrameworkA.framework', 'FrameworkB.framework'], output: 'UniversalFramework.xcframework')",
|
106
|
-
"create_xcframework(
|
184
|
+
"create_xcframework(frameworks_with_dsyms: {'FrameworkA.framework' => {}, 'FrameworkB.framework' => { dsyms: 'FrameworkB.framework.dSYM' } }, output: 'UniversalFramework.xcframework')",
|
185
|
+
"create_xcframework(libraries: ['LibraryA.so', 'LibraryB.so'], output: 'UniversalFramework.xcframework')",
|
186
|
+
"create_xcframework(libraries_with_headers_or_dsyms: { 'LibraryA.so' => { dsyms: 'libraryA.so.dSYM' }, 'LibraryB.so' => { headers: 'LibraryBHeaders' } }, output: 'UniversalFramework.xcframework')"
|
107
187
|
]
|
108
188
|
end
|
109
189
|
|
@@ -247,7 +247,7 @@ new CleanStatusBar()
|
|
247
247
|
|
248
248
|
# Advanced _screengrab_
|
249
249
|
|
250
|
-
<details>
|
250
|
+
<details markdown="1">
|
251
251
|
<summary>Launch Arguments</summary>
|
252
252
|
|
253
253
|
You can provide additional arguments to your test cases on launch. These strings will be available in your tests through `InstrumentationRegistry.getArguments()`.
|
@@ -277,7 +277,7 @@ if (extras != null) {
|
|
277
277
|
```
|
278
278
|
</details>
|
279
279
|
|
280
|
-
<details>
|
280
|
+
<details markdown="1">
|
281
281
|
<summary>Detecting screengrab at runtime</summary>
|
282
282
|
|
283
283
|
For some apps, it is helpful to know when _screengrab_ is running so that you can display specific data for your screenshots. For iOS fastlane users, this is much like "FASTLANE_SNAPSHOT". In order to do this, you'll need to have at least two product flavors of your app.
|
@@ -104,7 +104,7 @@ deliver(
|
|
104
104
|
|
105
105
|
## More options
|
106
106
|
|
107
|
-
<details>
|
107
|
+
<details markdown="1">
|
108
108
|
<summary>View all available options and their valid values</summary>
|
109
109
|
|
110
110
|
## Available options
|
@@ -497,7 +497,7 @@ Key | Editable While Live | Directory | Filename | Deprecated Filename
|
|
497
497
|
|
498
498
|
## Reference
|
499
499
|
|
500
|
-
<details>
|
500
|
+
<details markdown="1">
|
501
501
|
<summary>View all available categories, etc.</summary>
|
502
502
|
|
503
503
|
### Available Categories
|
@@ -64,7 +64,7 @@ module Fastlane
|
|
64
64
|
['SIGH_PROFILE_PATHS', 'Paths in which certificates, key and profile are exported'],
|
65
65
|
['SIGH_UUID', 'UUID (Universally Unique IDentifier) of a provisioning profile'],
|
66
66
|
['SIGH_NAME', 'The name of the profile'],
|
67
|
-
['SIGH_PROFILE_TYPE', 'The profile type, can be
|
67
|
+
['SIGH_PROFILE_TYPE', 'The profile type, can be app-store, ad-hoc, development, enterprise, developer-id, can be used in `build_app` as a default value for `export_method`']
|
68
68
|
]
|
69
69
|
end
|
70
70
|
|
@@ -10,6 +10,8 @@ module Fastlane
|
|
10
10
|
verbose = params[:verbose]
|
11
11
|
api_key_path = params[:api_key_path]
|
12
12
|
|
13
|
+
use_notarytool = params[:use_notarytool]
|
14
|
+
|
13
15
|
# Compress and read bundle identifier only for .app bundle.
|
14
16
|
compressed_package_path = nil
|
15
17
|
if File.extname(package_path) == '.app'
|
@@ -30,6 +32,74 @@ module Fastlane
|
|
30
32
|
|
31
33
|
UI.user_error!('Could not read bundle identifier, provide as a parameter') unless bundle_id
|
32
34
|
|
35
|
+
if use_notarytool
|
36
|
+
notarytool(params, package_path, bundle_id, try_early_stapling, print_log, verbose, api_key_path, compressed_package_path)
|
37
|
+
else
|
38
|
+
altool(params, package_path, bundle_id, try_early_stapling, print_log, verbose, api_key_path, compressed_package_path)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.notarytool(params, package_path, bundle_id, try_early_stapling, print_log, verbose, api_key_path, compressed_package_path)
|
43
|
+
temp_file = nil
|
44
|
+
|
45
|
+
# Create authorization part of command with either API Key or Apple ID
|
46
|
+
auth_parts = []
|
47
|
+
if api_key_path
|
48
|
+
api_key = Spaceship::ConnectAPI::Token.from_json_file(api_key_path)
|
49
|
+
|
50
|
+
# Writes key contents to temporary file for command
|
51
|
+
require 'tempfile'
|
52
|
+
temp_file = Tempfile.new
|
53
|
+
api_key.write_key_to_file(temp_file.path)
|
54
|
+
|
55
|
+
auth_parts << "--key #{temp_file.path}"
|
56
|
+
auth_parts << "--key-id #{api_key.key_id}"
|
57
|
+
auth_parts << "--issuer #{api_key.issuer_id}"
|
58
|
+
else
|
59
|
+
auth_parts << "--apple-id #{params[:username]}"
|
60
|
+
auth_parts << "--password #{ENV['FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD']}"
|
61
|
+
auth_parts << "--team-id #{params[:asc_provider]}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Submits package and waits for processing using `xcrun notarytool submit --wait`
|
65
|
+
submit_parts = [
|
66
|
+
"xcrun notarytool submit",
|
67
|
+
(compressed_package_path || package_path).shellescape,
|
68
|
+
"--output-format json",
|
69
|
+
"--wait"
|
70
|
+
] + auth_parts
|
71
|
+
|
72
|
+
submit_command = submit_parts.join(' ')
|
73
|
+
submit_response = Actions.sh(
|
74
|
+
submit_command,
|
75
|
+
log: verbose,
|
76
|
+
error_callback: lambda { |msg|
|
77
|
+
UI.error("Error polling for notarization info: #{msg}")
|
78
|
+
}
|
79
|
+
)
|
80
|
+
|
81
|
+
notarization_info = JSON.parse(submit_response)
|
82
|
+
|
83
|
+
# Staple
|
84
|
+
case notarization_info['status']
|
85
|
+
when 'Accepted'
|
86
|
+
submission_id = notarization_info["id"]
|
87
|
+
UI.success("Successfully uploaded package to notarization service with request identifier #{submission_id}")
|
88
|
+
|
89
|
+
UI.message('Stapling package')
|
90
|
+
self.staple(package_path, verbose)
|
91
|
+
|
92
|
+
UI.success("Successfully notarized and stapled package")
|
93
|
+
when 'Invalid'
|
94
|
+
UI.user_error!("Could not notarize package with message '#{notarization_info['statusSummary']}'")
|
95
|
+
else
|
96
|
+
UI.crash!("Could not notarize package with status '#{notarization_info['status']}'")
|
97
|
+
end
|
98
|
+
ensure
|
99
|
+
temp_file.delete if temp_file
|
100
|
+
end
|
101
|
+
|
102
|
+
def self.altool(params, package_path, bundle_id, try_early_stapling, print_log, verbose, api_key_path, compressed_package_path)
|
33
103
|
UI.message('Uploading package to notarization service, might take a while')
|
34
104
|
|
35
105
|
notarization_upload_command = "xcrun altool --notarize-app -t osx -f \"#{compressed_package_path || package_path}\" --primary-bundle-id #{bundle_id} --output-format xml"
|
@@ -125,7 +195,7 @@ module Fastlane
|
|
125
195
|
|
126
196
|
def self.staple(package_path, verbose)
|
127
197
|
Actions.sh(
|
128
|
-
"xcrun stapler staple
|
198
|
+
"xcrun stapler staple #{package_path.shellescape}",
|
129
199
|
log: verbose
|
130
200
|
)
|
131
201
|
end
|
@@ -180,6 +250,12 @@ module Fastlane
|
|
180
250
|
verify_block: proc do |value|
|
181
251
|
UI.user_error!("Could not find package at '#{value}'") unless File.exist?(value)
|
182
252
|
end),
|
253
|
+
FastlaneCore::ConfigItem.new(key: :use_notarytool,
|
254
|
+
env_name: 'FL_NOTARIZE_USE_NOTARYTOOL',
|
255
|
+
description: 'Whether to `xcrun notarytool` or `xcrun altool`',
|
256
|
+
default_value: Helper.mac? && Helper.xcode_at_least?("13.0"), # Notary tool added in Xcode 13
|
257
|
+
default_value_dynamic: true,
|
258
|
+
type: Boolean),
|
183
259
|
FastlaneCore::ConfigItem.new(key: :try_early_stapling,
|
184
260
|
env_name: 'FL_NOTARIZE_TRY_EARLY_STAPLING',
|
185
261
|
description: 'Whether to try early stapling while the notarization request is in progress',
|