fastlane 2.240.1 → 2.241.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +51 -171
- data/bin/fastlane +4 -2
- data/credentials_manager/README.md +1 -1
- data/deliver/lib/deliver/app_screenshot.rb +8 -4
- data/deliver/lib/deliver/commands_generator.rb +1 -1
- data/deliver/lib/deliver/download_screenshots.rb +8 -1
- data/deliver/lib/deliver/sync_screenshots.rb +27 -28
- data/deliver/lib/deliver/upload_app_clip_default_experience_header_images.rb +3 -3
- data/deliver/lib/deliver/upload_metadata.rb +12 -16
- data/deliver/lib/deliver/upload_screenshots.rb +12 -14
- data/docs/README.md +25 -0
- data/fastlane/lib/assets/TeamTable.md.erb +28 -0
- data/fastlane/lib/fastlane/actions/appaloosa.rb +2 -1
- data/fastlane/lib/fastlane/actions/appium.rb +1 -1
- data/fastlane/lib/fastlane/actions/apteligent.rb +8 -1
- data/fastlane/lib/fastlane/actions/build_and_upload_to_appetize.rb +1 -1
- data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +3 -0
- data/fastlane/lib/fastlane/actions/danger.rb +5 -5
- data/fastlane/lib/fastlane/actions/docs/build_app.md +1 -2
- data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -2
- data/fastlane/lib/fastlane/actions/docs/get_certificates.md +0 -2
- data/fastlane/lib/fastlane/actions/docs/get_push_certificate.md +1 -3
- data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +13 -3
- data/fastlane/lib/fastlane/actions/ensure_no_debug_code.rb +2 -2
- data/fastlane/lib/fastlane/actions/get_managed_play_store_publishing_rights.rb +1 -0
- data/fastlane/lib/fastlane/actions/github_api.rb +1 -2
- data/fastlane/lib/fastlane/actions/hg_commit_version_bump.rb +1 -1
- data/fastlane/lib/fastlane/actions/increment_build_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/increment_version_number.rb +1 -1
- data/fastlane/lib/fastlane/actions/install_xcode_plugin.rb +16 -6
- data/fastlane/lib/fastlane/actions/lcov.rb +9 -2
- data/fastlane/lib/fastlane/actions/nexus_upload.rb +16 -4
- data/fastlane/lib/fastlane/actions/notification.rb +3 -2
- data/fastlane/lib/fastlane/actions/oclint.rb +8 -8
- data/fastlane/lib/fastlane/actions/push_to_git_remote.rb +9 -4
- data/fastlane/lib/fastlane/actions/register_device.rb +1 -1
- data/fastlane/lib/fastlane/actions/say.rb +2 -4
- data/fastlane/lib/fastlane/actions/set_pod_key.rb +3 -3
- data/fastlane/lib/fastlane/actions/sonar.rb +16 -16
- data/fastlane/lib/fastlane/actions/sourcedocs.rb +8 -8
- data/fastlane/lib/fastlane/actions/splunkmint.rb +8 -1
- data/fastlane/lib/fastlane/actions/update_project_provisioning.rb +1 -1
- data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +5 -2
- data/fastlane/lib/fastlane/actions/upload_to_testflight.rb +5 -2
- data/fastlane/lib/fastlane/actions/verify_build.rb +1 -4
- data/fastlane/lib/fastlane/actions/verify_pod_keys.rb +3 -1
- data/fastlane/lib/fastlane/actions/xcode_server_get_assets.rb +20 -19
- data/fastlane/lib/fastlane/actions/xcodebuild.rb +5 -6
- data/fastlane/lib/fastlane/actions/zip.rb +2 -1
- data/fastlane/lib/fastlane/auto_complete.rb +1 -1
- data/fastlane/lib/fastlane/cli_tools_distributor.rb +14 -0
- data/fastlane/lib/fastlane/documentation/markdown_docs_generator.rb +23 -0
- data/fastlane/lib/fastlane/environment_printer.rb +12 -25
- data/fastlane/lib/fastlane/fast_file.rb +2 -1
- data/fastlane/lib/fastlane/fastlane_require.rb +5 -1
- data/fastlane/lib/fastlane/helper/sh_helper.rb +16 -6
- data/fastlane/lib/fastlane/new_action.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_fetcher.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_info_collector.rb +1 -1
- data/fastlane/lib/fastlane/plugins/plugin_manager.rb +36 -4
- data/fastlane/lib/fastlane/plugins/template/%gem_name%.gemspec.erb +1 -1
- data/fastlane/lib/fastlane/plugins/template/.github/workflows/test.yml +1 -1
- data/fastlane/lib/fastlane/plugins/template/.rubocop.yml +3 -7
- data/fastlane/lib/fastlane/swift_lane_manager.rb +22 -4
- data/fastlane/lib/fastlane/version.rb +3 -2
- data/fastlane/swift/Deliverfile.swift +1 -1
- data/fastlane/swift/DeliverfileProtocol.swift +1 -1
- data/fastlane/swift/Fastlane.swift +39 -9
- data/fastlane/swift/Gymfile.swift +1 -1
- data/fastlane/swift/GymfileProtocol.swift +1 -1
- data/fastlane/swift/MainProcess.swift +190 -20
- data/fastlane/swift/Matchfile.swift +1 -1
- data/fastlane/swift/MatchfileProtocol.swift +10 -3
- 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 +8 -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/Rakefile +1 -0
- data/fastlane/swift/main.swift +4 -1
- data/fastlane_core/README.md +1 -1
- data/fastlane_core/lib/fastlane_core/analytics/analytics_event_builder.rb +1 -17
- data/fastlane_core/lib/fastlane_core/configuration/configuration.rb +11 -8
- data/fastlane_core/lib/fastlane_core/device_manager.rb +2 -2
- data/fastlane_core/lib/fastlane_core/helper.rb +34 -5
- data/fastlane_core/lib/fastlane_core/itunes_transporter.rb +0 -14
- data/fastlane_core/lib/fastlane_core/keychain_importer.rb +24 -27
- data/fastlane_core/lib/fastlane_core/languages.rb +0 -1
- data/fastlane_core/lib/fastlane_core/print_table.rb +5 -2
- data/fastlane_core/lib/fastlane_core/provisioning_profile.rb +10 -19
- data/fastlane_core/lib/fastlane_core/secrets.rb +77 -0
- data/fastlane_core/lib/fastlane_core/ui/fastlane_runner.rb +3 -3
- data/fastlane_core/lib/fastlane_core/ui/github_issue_inspector_reporter.rb +1 -1
- data/fastlane_core/lib/fastlane_core/ui/implementations/shell.rb +2 -1
- data/fastlane_core/lib/fastlane_core.rb +1 -0
- data/frameit/lib/frameit/device.rb +1 -1
- data/frameit/lib/frameit/frame_downloader.rb +2 -0
- data/frameit/lib/frameit/runner.rb +3 -2
- data/frameit/lib/frameit/screenshot.rb +0 -1
- data/gym/lib/gym/generators/build_command_generator.rb +4 -4
- data/gym/lib/gym/generators/package_command_generator_xcode7.rb +3 -3
- data/gym/lib/gym/runner.rb +1 -1
- data/internal/README.md +1 -1
- data/match/lib/match/generator.rb +1 -0
- data/match/lib/match/options.rb +13 -5
- data/match/lib/match/storage/git_storage.rb +43 -7
- data/match/lib/match/storage/gitlab/secure_file.rb +2 -1
- data/pem/lib/pem/module.rb +0 -4
- data/precheck/lib/precheck/rule_processor.rb +1 -0
- data/produce/lib/produce/itunes_connect.rb +1 -1
- data/produce/lib/produce/service.rb +0 -1
- data/produce/lib/produce.rb +0 -1
- data/scan/lib/scan/options.rb +7 -0
- data/scan/lib/scan/runner.rb +1 -1
- data/scan/lib/scan/test_command_generator.rb +12 -9
- data/scan/lib/scan/test_result_parser.rb +1 -0
- data/scan/lib/scan/xcpretty_reporter_options_generator.rb +2 -2
- data/screengrab/lib/screengrab/page.html.erb +12 -7
- data/screengrab/lib/screengrab/reports_generator.rb +1 -1
- data/sigh/lib/assets/resign.sh +17 -0
- data/sigh/lib/sigh/local_manage.rb +1 -1
- data/sigh/lib/sigh/options.rb +5 -0
- data/sigh/lib/sigh/resign.rb +3 -3
- data/sigh/lib/sigh/runner.rb +6 -1
- data/snapshot/lib/snapshot/page.html.erb +17 -12
- data/snapshot/lib/snapshot/reports_generator.rb +3 -1
- data/snapshot/lib/snapshot/simulator_launchers/simulator_launcher_base.rb +1 -1
- data/snapshot/lib/snapshot.rb +0 -2
- data/spaceship/README.md +2 -3
- data/spaceship/lib/spaceship/base.rb +3 -1
- data/spaceship/lib/spaceship/client.rb +65 -47
- data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +2 -0
- data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -5
- data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +9 -0
- data/spaceship/lib/spaceship/du/upload_file.rb +1 -1
- data/spaceship/lib/spaceship/errors.rb +7 -1
- data/spaceship/lib/spaceship/globals.rb +2 -2
- data/spaceship/lib/spaceship/portal/merchant.rb +127 -2
- data/spaceship/lib/spaceship/portal/portal_client.rb +58 -0
- data/spaceship/lib/spaceship/portal/ui/select_team.rb +0 -2
- data/spaceship/lib/spaceship/portal/website_push.rb +8 -2
- data/spaceship/lib/spaceship/test_flight/client.rb +0 -22
- data/spaceship/lib/spaceship/test_flight.rb +0 -1
- data/spaceship/lib/spaceship/two_step_or_factor_client.rb +11 -0
- data/supply/lib/supply/options.rb +1 -0
- data/supply/lib/supply.rb +0 -1
- metadata +55 -37
- data/produce/lib/produce/available_default_languages.rb +0 -62
- data/snapshot/lib/snapshot/screenshot_flatten.rb +0 -20
- data/snapshot/lib/snapshot/screenshot_rotate.rb +0 -36
- data/spaceship/lib/spaceship/test_flight/app_test_info.rb +0 -40
- data/supply/lib/supply/apk_listing.rb +0 -14
- /data/fastlane/lib/assets/{custom_action_template.rb → custom_action_template.rb.template} +0 -0
|
@@ -3068,6 +3068,8 @@ public func chatwork(apiToken: String,
|
|
|
3068
3068
|
|
|
3069
3069
|
This action deletes the files that get created in your repo as a result of running the _gym_ and _sigh_ commands. It doesn't delete the `fastlane/report.xml` though, this is probably more suited for the .gitignore.
|
|
3070
3070
|
|
|
3071
|
+
From _cert_ it only deletes the `.cer` file. The private key (`<certificate id>.p12`, despite its name an unencrypted PEM key) and the `.certSigningRequest` that _cert_ writes to its `output_path` when it creates a certificate are kept: _cert_ uses that `.p12` to install the certificate on a machine that doesn't have it, and on systems other than macOS it is the only copy of the key. Keep them out of version control.
|
|
3072
|
+
|
|
3071
3073
|
Useful if you quickly want to send out a test build by dropping down to the command line and typing something like `fastlane beta`, without leaving your repo in a messy state afterwards.
|
|
3072
3074
|
*/
|
|
3073
3075
|
public func cleanBuildArtifacts(excludePattern: OptionalConfigValue<String?> = .fastlaneDefault(nil)) {
|
|
@@ -5214,6 +5216,7 @@ public func getManagedPlayStorePublishingRights(jsonKey: OptionalConfigValue<Str
|
|
|
5214
5216
|
- force: Renew provisioning profiles regardless of its state - to automatically add all devices for ad hoc profiles
|
|
5215
5217
|
- includeMacInProfiles: Include Apple Silicon Mac devices in provisioning profiles for iOS/iPadOS apps
|
|
5216
5218
|
- appIdentifier: The bundle identifier of your app
|
|
5219
|
+
- offlineProfile: Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication
|
|
5217
5220
|
- apiKeyPath: Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file)
|
|
5218
5221
|
- apiKey: Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-hash-option)
|
|
5219
5222
|
- username: Your Apple ID Username
|
|
@@ -5248,6 +5251,7 @@ public func getManagedPlayStorePublishingRights(jsonKey: OptionalConfigValue<Str
|
|
|
5248
5251
|
force: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
5249
5252
|
includeMacInProfiles: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
5250
5253
|
appIdentifier: String,
|
|
5254
|
+
offlineProfile: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
5251
5255
|
apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
5252
5256
|
apiKey: OptionalConfigValue<[String: Any]?> = .fastlaneDefault(nil),
|
|
5253
5257
|
username: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
@@ -5278,6 +5282,7 @@ public func getManagedPlayStorePublishingRights(jsonKey: OptionalConfigValue<Str
|
|
|
5278
5282
|
let forceArg = force.asRubyArgument(name: "force", type: nil)
|
|
5279
5283
|
let includeMacInProfilesArg = includeMacInProfiles.asRubyArgument(name: "include_mac_in_profiles", type: nil)
|
|
5280
5284
|
let appIdentifierArg = RubyCommand.Argument(name: "app_identifier", value: appIdentifier, type: nil)
|
|
5285
|
+
let offlineProfileArg = offlineProfile.asRubyArgument(name: "offline_profile", type: nil)
|
|
5281
5286
|
let apiKeyPathArg = apiKeyPath.asRubyArgument(name: "api_key_path", type: nil)
|
|
5282
5287
|
let apiKeyArg = apiKey.asRubyArgument(name: "api_key", type: nil)
|
|
5283
5288
|
let usernameArg = username.asRubyArgument(name: "username", type: nil)
|
|
@@ -5307,6 +5312,7 @@ public func getManagedPlayStorePublishingRights(jsonKey: OptionalConfigValue<Str
|
|
|
5307
5312
|
forceArg,
|
|
5308
5313
|
includeMacInProfilesArg,
|
|
5309
5314
|
appIdentifierArg,
|
|
5315
|
+
offlineProfileArg,
|
|
5310
5316
|
apiKeyPathArg,
|
|
5311
5317
|
apiKeyArg,
|
|
5312
5318
|
usernameArg,
|
|
@@ -6923,8 +6929,8 @@ public func makeChangelogFromJenkins(fallbackChangelog: String = "",
|
|
|
6923
6929
|
- gitUserEmail: git user email to commit
|
|
6924
6930
|
- shallowClone: Make a shallow clone of the repository (truncate the history to 1 revision)
|
|
6925
6931
|
- cloneBranchDirectly: Clone just the branch specified, instead of the whole repo. This requires that the branch already exists. Otherwise the command will fail
|
|
6926
|
-
- gitBasicAuthorization: Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64
|
|
6927
|
-
- gitBearerAuthorization: Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64
|
|
6932
|
+
- gitBasicAuthorization: Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64. Needs git 2.31 or later
|
|
6933
|
+
- gitBearerAuthorization: Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64. Needs git 2.31 or later
|
|
6928
6934
|
- gitPrivateKey: Use a private key to access the git repo (e.g.: access to GitHub repository via Deploy keys), usually a id_rsa named file or the contents hereof
|
|
6929
6935
|
- googleCloudBucketName: Name of the Google Cloud Storage bucket to use
|
|
6930
6936
|
- googleCloudKeysFile: Path to the gc_keys.json file
|
|
@@ -6962,6 +6968,7 @@ public func makeChangelogFromJenkins(fallbackChangelog: String = "",
|
|
|
6962
6968
|
- outputPath: Path in which to export certificates, key and profile
|
|
6963
6969
|
- skipSetPartitionList: Skips setting the partition list (which can sometimes take a long time). Setting the partition list is usually needed to prevent Xcode from prompting to allow a cert to be used for signing
|
|
6964
6970
|
- forceLegacyEncryption: Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions
|
|
6971
|
+
- offlineProfile: Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication
|
|
6965
6972
|
- verbose: Print out extra information and all commands
|
|
6966
6973
|
|
|
6967
6974
|
More information: https://docs.fastlane.tools/actions/match/
|
|
@@ -7023,6 +7030,7 @@ public func match(type: String = matchfile.type,
|
|
|
7023
7030
|
outputPath: OptionalConfigValue<String?> = .fastlaneDefault(matchfile.outputPath),
|
|
7024
7031
|
skipSetPartitionList: OptionalConfigValue<Bool> = .fastlaneDefault(matchfile.skipSetPartitionList),
|
|
7025
7032
|
forceLegacyEncryption: OptionalConfigValue<Bool> = .fastlaneDefault(matchfile.forceLegacyEncryption),
|
|
7033
|
+
offlineProfile: OptionalConfigValue<Bool> = .fastlaneDefault(matchfile.offlineProfile),
|
|
7026
7034
|
verbose: OptionalConfigValue<Bool> = .fastlaneDefault(matchfile.verbose))
|
|
7027
7035
|
{
|
|
7028
7036
|
let typeArg = RubyCommand.Argument(name: "type", value: type, type: nil)
|
|
@@ -7082,6 +7090,7 @@ public func match(type: String = matchfile.type,
|
|
|
7082
7090
|
let outputPathArg = outputPath.asRubyArgument(name: "output_path", type: nil)
|
|
7083
7091
|
let skipSetPartitionListArg = skipSetPartitionList.asRubyArgument(name: "skip_set_partition_list", type: nil)
|
|
7084
7092
|
let forceLegacyEncryptionArg = forceLegacyEncryption.asRubyArgument(name: "force_legacy_encryption", type: nil)
|
|
7093
|
+
let offlineProfileArg = offlineProfile.asRubyArgument(name: "offline_profile", type: nil)
|
|
7085
7094
|
let verboseArg = verbose.asRubyArgument(name: "verbose", type: nil)
|
|
7086
7095
|
let array: [RubyCommand.Argument?] = [typeArg,
|
|
7087
7096
|
additionalCertTypesArg,
|
|
@@ -7140,6 +7149,7 @@ public func match(type: String = matchfile.type,
|
|
|
7140
7149
|
outputPathArg,
|
|
7141
7150
|
skipSetPartitionListArg,
|
|
7142
7151
|
forceLegacyEncryptionArg,
|
|
7152
|
+
offlineProfileArg,
|
|
7143
7153
|
verboseArg]
|
|
7144
7154
|
let args: [RubyCommand.Argument] = array
|
|
7145
7155
|
.filter { $0?.value != nil }
|
|
@@ -7170,8 +7180,8 @@ public func match(type: String = matchfile.type,
|
|
|
7170
7180
|
- gitUserEmail: git user email to commit
|
|
7171
7181
|
- shallowClone: Make a shallow clone of the repository (truncate the history to 1 revision)
|
|
7172
7182
|
- cloneBranchDirectly: Clone just the branch specified, instead of the whole repo. This requires that the branch already exists. Otherwise the command will fail
|
|
7173
|
-
- gitBasicAuthorization: Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64
|
|
7174
|
-
- gitBearerAuthorization: Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64
|
|
7183
|
+
- gitBasicAuthorization: Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64. Needs git 2.31 or later
|
|
7184
|
+
- gitBearerAuthorization: Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64. Needs git 2.31 or later
|
|
7175
7185
|
- gitPrivateKey: Use a private key to access the git repo (e.g.: access to GitHub repository via Deploy keys), usually a id_rsa named file or the contents hereof
|
|
7176
7186
|
- googleCloudBucketName: Name of the Google Cloud Storage bucket to use
|
|
7177
7187
|
- googleCloudKeysFile: Path to the gc_keys.json file
|
|
@@ -7209,6 +7219,7 @@ public func match(type: String = matchfile.type,
|
|
|
7209
7219
|
- outputPath: Path in which to export certificates, key and profile
|
|
7210
7220
|
- skipSetPartitionList: Skips setting the partition list (which can sometimes take a long time). Setting the partition list is usually needed to prevent Xcode from prompting to allow a cert to be used for signing
|
|
7211
7221
|
- forceLegacyEncryption: Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions
|
|
7222
|
+
- offlineProfile: Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication
|
|
7212
7223
|
- verbose: Print out extra information and all commands
|
|
7213
7224
|
|
|
7214
7225
|
Use the match_nuke action to revoke your certificates and provisioning profiles.
|
|
@@ -7274,6 +7285,7 @@ public func matchNuke(type: String = "development",
|
|
|
7274
7285
|
outputPath: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
7275
7286
|
skipSetPartitionList: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
7276
7287
|
forceLegacyEncryption: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
7288
|
+
offlineProfile: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
7277
7289
|
verbose: OptionalConfigValue<Bool> = .fastlaneDefault(false))
|
|
7278
7290
|
{
|
|
7279
7291
|
let typeArg = RubyCommand.Argument(name: "type", value: type, type: nil)
|
|
@@ -7333,6 +7345,7 @@ public func matchNuke(type: String = "development",
|
|
|
7333
7345
|
let outputPathArg = outputPath.asRubyArgument(name: "output_path", type: nil)
|
|
7334
7346
|
let skipSetPartitionListArg = skipSetPartitionList.asRubyArgument(name: "skip_set_partition_list", type: nil)
|
|
7335
7347
|
let forceLegacyEncryptionArg = forceLegacyEncryption.asRubyArgument(name: "force_legacy_encryption", type: nil)
|
|
7348
|
+
let offlineProfileArg = offlineProfile.asRubyArgument(name: "offline_profile", type: nil)
|
|
7336
7349
|
let verboseArg = verbose.asRubyArgument(name: "verbose", type: nil)
|
|
7337
7350
|
let array: [RubyCommand.Argument?] = [typeArg,
|
|
7338
7351
|
additionalCertTypesArg,
|
|
@@ -7391,6 +7404,7 @@ public func matchNuke(type: String = "development",
|
|
|
7391
7404
|
outputPathArg,
|
|
7392
7405
|
skipSetPartitionListArg,
|
|
7393
7406
|
forceLegacyEncryptionArg,
|
|
7407
|
+
offlineProfileArg,
|
|
7394
7408
|
verboseArg]
|
|
7395
7409
|
let args: [RubyCommand.Argument] = array
|
|
7396
7410
|
.filter { $0?.value != nil }
|
|
@@ -7581,8 +7595,8 @@ public func notarize(package: String,
|
|
|
7581
7595
|
- message: The message to display in the notification
|
|
7582
7596
|
- sound: The name of a sound to play when the notification appears (names are listed in Sound Preferences)
|
|
7583
7597
|
- activate: Bundle identifier of application to be opened when the notification is clicked
|
|
7584
|
-
- appIcon: The URL of an image to display instead of the application icon
|
|
7585
|
-
- contentImage: The
|
|
7598
|
+
- appIcon: **DEPRECATED!** The URL of an image to display instead of the application icon
|
|
7599
|
+
- contentImage: The local path of an image to display attached to the notification (Mavericks+)
|
|
7586
7600
|
- open: URL of the resource to be opened when the notification is clicked
|
|
7587
7601
|
- execute: Shell command to run when the notification is clicked
|
|
7588
7602
|
*/
|
|
@@ -9002,6 +9016,7 @@ public func rubyVersion() {
|
|
|
9002
9016
|
- codeCoverage: Should code coverage be generated? (Xcode 7 and up)
|
|
9003
9017
|
- addressSanitizer: Should the address sanitizer be turned on?
|
|
9004
9018
|
- threadSanitizer: Should the thread sanitizer be turned on?
|
|
9019
|
+
- collectTestDiagnostics: Whether verbose and long-running diagnostics (like sysdiagnoses or log archives) are collected when testing. Valid values are: on-failure or never. If not specified, the value in the test plan is used. Equivalent to -collect-test-diagnostics (Xcode 14 and up)
|
|
9005
9020
|
- openReport: Should the HTML report be opened when tests are completed?
|
|
9006
9021
|
- outputDirectory: The directory in which all reports will be stored
|
|
9007
9022
|
- outputStyle: Define how the output should look like. Valid values are: standard, basic, rspec, or raw (disables xcpretty during xcodebuild)
|
|
@@ -9090,6 +9105,7 @@ public func rubyVersion() {
|
|
|
9090
9105
|
codeCoverage: OptionalConfigValue<Bool?> = .fastlaneDefault(nil),
|
|
9091
9106
|
addressSanitizer: OptionalConfigValue<Bool?> = .fastlaneDefault(nil),
|
|
9092
9107
|
threadSanitizer: OptionalConfigValue<Bool?> = .fastlaneDefault(nil),
|
|
9108
|
+
collectTestDiagnostics: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
9093
9109
|
openReport: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
9094
9110
|
outputDirectory: String = "./test_output",
|
|
9095
9111
|
outputStyle: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
@@ -9174,6 +9190,7 @@ public func rubyVersion() {
|
|
|
9174
9190
|
let codeCoverageArg = codeCoverage.asRubyArgument(name: "code_coverage", type: nil)
|
|
9175
9191
|
let addressSanitizerArg = addressSanitizer.asRubyArgument(name: "address_sanitizer", type: nil)
|
|
9176
9192
|
let threadSanitizerArg = threadSanitizer.asRubyArgument(name: "thread_sanitizer", type: nil)
|
|
9193
|
+
let collectTestDiagnosticsArg = collectTestDiagnostics.asRubyArgument(name: "collect_test_diagnostics", type: nil)
|
|
9177
9194
|
let openReportArg = openReport.asRubyArgument(name: "open_report", type: nil)
|
|
9178
9195
|
let outputDirectoryArg = RubyCommand.Argument(name: "output_directory", value: outputDirectory, type: nil)
|
|
9179
9196
|
let outputStyleArg = outputStyle.asRubyArgument(name: "output_style", type: nil)
|
|
@@ -9257,6 +9274,7 @@ public func rubyVersion() {
|
|
|
9257
9274
|
codeCoverageArg,
|
|
9258
9275
|
addressSanitizerArg,
|
|
9259
9276
|
threadSanitizerArg,
|
|
9277
|
+
collectTestDiagnosticsArg,
|
|
9260
9278
|
openReportArg,
|
|
9261
9279
|
outputDirectoryArg,
|
|
9262
9280
|
outputStyleArg,
|
|
@@ -9453,6 +9471,7 @@ public func say(text: [String],
|
|
|
9453
9471
|
- codeCoverage: Should code coverage be generated? (Xcode 7 and up)
|
|
9454
9472
|
- addressSanitizer: Should the address sanitizer be turned on?
|
|
9455
9473
|
- threadSanitizer: Should the thread sanitizer be turned on?
|
|
9474
|
+
- collectTestDiagnostics: Whether verbose and long-running diagnostics (like sysdiagnoses or log archives) are collected when testing. Valid values are: on-failure or never. If not specified, the value in the test plan is used. Equivalent to -collect-test-diagnostics (Xcode 14 and up)
|
|
9456
9475
|
- openReport: Should the HTML report be opened when tests are completed?
|
|
9457
9476
|
- outputDirectory: The directory in which all reports will be stored
|
|
9458
9477
|
- outputStyle: Define how the output should look like. Valid values are: standard, basic, rspec, or raw (disables xcpretty during xcodebuild)
|
|
@@ -9541,6 +9560,7 @@ public func say(text: [String],
|
|
|
9541
9560
|
codeCoverage: OptionalConfigValue<Bool?> = .fastlaneDefault(scanfile.codeCoverage),
|
|
9542
9561
|
addressSanitizer: OptionalConfigValue<Bool?> = .fastlaneDefault(scanfile.addressSanitizer),
|
|
9543
9562
|
threadSanitizer: OptionalConfigValue<Bool?> = .fastlaneDefault(scanfile.threadSanitizer),
|
|
9563
|
+
collectTestDiagnostics: OptionalConfigValue<String?> = .fastlaneDefault(scanfile.collectTestDiagnostics),
|
|
9544
9564
|
openReport: OptionalConfigValue<Bool> = .fastlaneDefault(scanfile.openReport),
|
|
9545
9565
|
outputDirectory: String = scanfile.outputDirectory,
|
|
9546
9566
|
outputStyle: OptionalConfigValue<String?> = .fastlaneDefault(scanfile.outputStyle),
|
|
@@ -9625,6 +9645,7 @@ public func say(text: [String],
|
|
|
9625
9645
|
let codeCoverageArg = codeCoverage.asRubyArgument(name: "code_coverage", type: nil)
|
|
9626
9646
|
let addressSanitizerArg = addressSanitizer.asRubyArgument(name: "address_sanitizer", type: nil)
|
|
9627
9647
|
let threadSanitizerArg = threadSanitizer.asRubyArgument(name: "thread_sanitizer", type: nil)
|
|
9648
|
+
let collectTestDiagnosticsArg = collectTestDiagnostics.asRubyArgument(name: "collect_test_diagnostics", type: nil)
|
|
9628
9649
|
let openReportArg = openReport.asRubyArgument(name: "open_report", type: nil)
|
|
9629
9650
|
let outputDirectoryArg = RubyCommand.Argument(name: "output_directory", value: outputDirectory, type: nil)
|
|
9630
9651
|
let outputStyleArg = outputStyle.asRubyArgument(name: "output_style", type: nil)
|
|
@@ -9708,6 +9729,7 @@ public func say(text: [String],
|
|
|
9708
9729
|
codeCoverageArg,
|
|
9709
9730
|
addressSanitizerArg,
|
|
9710
9731
|
threadSanitizerArg,
|
|
9732
|
+
collectTestDiagnosticsArg,
|
|
9711
9733
|
openReportArg,
|
|
9712
9734
|
outputDirectoryArg,
|
|
9713
9735
|
outputStyleArg,
|
|
@@ -10311,6 +10333,7 @@ public func setupTravis(force: OptionalConfigValue<Bool> = .fastlaneDefault(fals
|
|
|
10311
10333
|
- force: Renew provisioning profiles regardless of its state - to automatically add all devices for ad hoc profiles
|
|
10312
10334
|
- includeMacInProfiles: Include Apple Silicon Mac devices in provisioning profiles for iOS/iPadOS apps
|
|
10313
10335
|
- appIdentifier: The bundle identifier of your app
|
|
10336
|
+
- offlineProfile: Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication
|
|
10314
10337
|
- apiKeyPath: Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file)
|
|
10315
10338
|
- apiKey: Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-hash-option)
|
|
10316
10339
|
- username: Your Apple ID Username
|
|
@@ -10345,6 +10368,7 @@ public func setupTravis(force: OptionalConfigValue<Bool> = .fastlaneDefault(fals
|
|
|
10345
10368
|
force: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
10346
10369
|
includeMacInProfiles: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
10347
10370
|
appIdentifier: String,
|
|
10371
|
+
offlineProfile: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
10348
10372
|
apiKeyPath: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
10349
10373
|
apiKey: OptionalConfigValue<[String: Any]?> = .fastlaneDefault(nil),
|
|
10350
10374
|
username: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
@@ -10375,6 +10399,7 @@ public func setupTravis(force: OptionalConfigValue<Bool> = .fastlaneDefault(fals
|
|
|
10375
10399
|
let forceArg = force.asRubyArgument(name: "force", type: nil)
|
|
10376
10400
|
let includeMacInProfilesArg = includeMacInProfiles.asRubyArgument(name: "include_mac_in_profiles", type: nil)
|
|
10377
10401
|
let appIdentifierArg = RubyCommand.Argument(name: "app_identifier", value: appIdentifier, type: nil)
|
|
10402
|
+
let offlineProfileArg = offlineProfile.asRubyArgument(name: "offline_profile", type: nil)
|
|
10378
10403
|
let apiKeyPathArg = apiKeyPath.asRubyArgument(name: "api_key_path", type: nil)
|
|
10379
10404
|
let apiKeyArg = apiKey.asRubyArgument(name: "api_key", type: nil)
|
|
10380
10405
|
let usernameArg = username.asRubyArgument(name: "username", type: nil)
|
|
@@ -10404,6 +10429,7 @@ public func setupTravis(force: OptionalConfigValue<Bool> = .fastlaneDefault(fals
|
|
|
10404
10429
|
forceArg,
|
|
10405
10430
|
includeMacInProfilesArg,
|
|
10406
10431
|
appIdentifierArg,
|
|
10432
|
+
offlineProfileArg,
|
|
10407
10433
|
apiKeyPathArg,
|
|
10408
10434
|
apiKeyArg,
|
|
10409
10435
|
usernameArg,
|
|
@@ -11536,8 +11562,8 @@ public func swiftlint(mode: String = "lint",
|
|
|
11536
11562
|
- gitUserEmail: git user email to commit
|
|
11537
11563
|
- shallowClone: Make a shallow clone of the repository (truncate the history to 1 revision)
|
|
11538
11564
|
- cloneBranchDirectly: Clone just the branch specified, instead of the whole repo. This requires that the branch already exists. Otherwise the command will fail
|
|
11539
|
-
- gitBasicAuthorization: Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64
|
|
11540
|
-
- gitBearerAuthorization: Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64
|
|
11565
|
+
- gitBasicAuthorization: Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64. Needs git 2.31 or later
|
|
11566
|
+
- gitBearerAuthorization: Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64. Needs git 2.31 or later
|
|
11541
11567
|
- gitPrivateKey: Use a private key to access the git repo (e.g.: access to GitHub repository via Deploy keys), usually a id_rsa named file or the contents hereof
|
|
11542
11568
|
- googleCloudBucketName: Name of the Google Cloud Storage bucket to use
|
|
11543
11569
|
- googleCloudKeysFile: Path to the gc_keys.json file
|
|
@@ -11575,6 +11601,7 @@ public func swiftlint(mode: String = "lint",
|
|
|
11575
11601
|
- outputPath: Path in which to export certificates, key and profile
|
|
11576
11602
|
- skipSetPartitionList: Skips setting the partition list (which can sometimes take a long time). Setting the partition list is usually needed to prevent Xcode from prompting to allow a cert to be used for signing
|
|
11577
11603
|
- forceLegacyEncryption: Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions
|
|
11604
|
+
- offlineProfile: Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication
|
|
11578
11605
|
- verbose: Print out extra information and all commands
|
|
11579
11606
|
|
|
11580
11607
|
More information: https://docs.fastlane.tools/actions/match/
|
|
@@ -11636,6 +11663,7 @@ public func syncCodeSigning(type: String = "development",
|
|
|
11636
11663
|
outputPath: OptionalConfigValue<String?> = .fastlaneDefault(nil),
|
|
11637
11664
|
skipSetPartitionList: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
11638
11665
|
forceLegacyEncryption: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
11666
|
+
offlineProfile: OptionalConfigValue<Bool> = .fastlaneDefault(false),
|
|
11639
11667
|
verbose: OptionalConfigValue<Bool> = .fastlaneDefault(false))
|
|
11640
11668
|
{
|
|
11641
11669
|
let typeArg = RubyCommand.Argument(name: "type", value: type, type: nil)
|
|
@@ -11695,6 +11723,7 @@ public func syncCodeSigning(type: String = "development",
|
|
|
11695
11723
|
let outputPathArg = outputPath.asRubyArgument(name: "output_path", type: nil)
|
|
11696
11724
|
let skipSetPartitionListArg = skipSetPartitionList.asRubyArgument(name: "skip_set_partition_list", type: nil)
|
|
11697
11725
|
let forceLegacyEncryptionArg = forceLegacyEncryption.asRubyArgument(name: "force_legacy_encryption", type: nil)
|
|
11726
|
+
let offlineProfileArg = offlineProfile.asRubyArgument(name: "offline_profile", type: nil)
|
|
11698
11727
|
let verboseArg = verbose.asRubyArgument(name: "verbose", type: nil)
|
|
11699
11728
|
let array: [RubyCommand.Argument?] = [typeArg,
|
|
11700
11729
|
additionalCertTypesArg,
|
|
@@ -11753,6 +11782,7 @@ public func syncCodeSigning(type: String = "development",
|
|
|
11753
11782
|
outputPathArg,
|
|
11754
11783
|
skipSetPartitionListArg,
|
|
11755
11784
|
forceLegacyEncryptionArg,
|
|
11785
|
+
offlineProfileArg,
|
|
11756
11786
|
verboseArg]
|
|
11757
11787
|
let args: [RubyCommand.Argument] = array
|
|
11758
11788
|
.filter { $0?.value != nil }
|
|
@@ -14215,4 +14245,4 @@ public let snapshotfile: Snapshotfile = .init()
|
|
|
14215
14245
|
|
|
14216
14246
|
// Please don't remove the lines below
|
|
14217
14247
|
// They are used to detect outdated files
|
|
14218
|
-
// FastlaneRunnerAPIVersion [0.9.
|
|
14248
|
+
// FastlaneRunnerAPIVersion [0.9.210]
|
|
@@ -9,9 +9,6 @@
|
|
|
9
9
|
//
|
|
10
10
|
|
|
11
11
|
import Foundation
|
|
12
|
-
#if canImport(SwiftShell)
|
|
13
|
-
import SwiftShell
|
|
14
|
-
#endif
|
|
15
12
|
|
|
16
13
|
let argumentProcessor = ArgumentProcessor(args: CommandLine.arguments)
|
|
17
14
|
let timeout = argumentProcessor.commandTimeout
|
|
@@ -20,9 +17,7 @@ class MainProcess {
|
|
|
20
17
|
var doneRunningLane = false
|
|
21
18
|
var thread: Thread!
|
|
22
19
|
#if SWIFT_PACKAGE
|
|
23
|
-
var
|
|
24
|
-
var timeBetweenPrints = Int.min
|
|
25
|
-
var rubySocketCommand: AsyncCommand!
|
|
20
|
+
var rubySocketCommand: Process!
|
|
26
21
|
#endif
|
|
27
22
|
|
|
28
23
|
@objc func connectToFastlaneAndRunLane(_ fastfile: LaneFile?) {
|
|
@@ -44,24 +39,199 @@ class MainProcess {
|
|
|
44
39
|
#endif
|
|
45
40
|
thread.name = "worker thread"
|
|
46
41
|
#if SWIFT_PACKAGE
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
rubySocketCommand =
|
|
53
|
-
|
|
54
|
-
rubySocketCommand.stderror.onStringOutput { print($0) }
|
|
55
|
-
rubySocketCommand.stdout.onStringOutput { stdout in
|
|
56
|
-
print(stdout)
|
|
57
|
-
self.timeBetweenPrints = Int(self.lastPrintDate.timeIntervalSinceNow)
|
|
58
|
-
}
|
|
42
|
+
killExistingSocketServerProcesses(port: argumentProcessor.port)
|
|
43
|
+
abortIfPortIsInUse(argumentProcessor.port)
|
|
44
|
+
|
|
45
|
+
rubySocketCommand = Process()
|
|
46
|
+
rubySocketCommand.launchPath = "/usr/bin/env"
|
|
47
|
+
rubySocketCommand.arguments = fastlaneLaunchArguments() + ["socket_server", "-c", String(timeout), "-p", String(argumentProcessor.port)]
|
|
48
|
+
rubySocketCommand.launch()
|
|
59
49
|
|
|
60
|
-
|
|
61
|
-
_ = Runner.waitWithPolling(self.timeBetweenPrints, toEventually: { $0 > 5 }, timeout: 10)
|
|
50
|
+
waitUntilSocketServerIsListening(port: argumentProcessor.port, serverProcess: rubySocketCommand)
|
|
62
51
|
thread.start()
|
|
63
52
|
#endif
|
|
64
53
|
}
|
|
54
|
+
|
|
55
|
+
#if SWIFT_PACKAGE
|
|
56
|
+
/// Resolves how to invoke fastlane, replacing the previous login-shell
|
|
57
|
+
/// `eval $(path_helper)` + `which fastlane` lookup that broke under
|
|
58
|
+
/// rbenv / bundler / system-ruby mixes (#29238). First match wins:
|
|
59
|
+
/// 1. FASTLANE_SPM_BIN environment variable (explicit override)
|
|
60
|
+
/// 2. bundler binstub bin/fastlane next to the Gemfile
|
|
61
|
+
/// 3. Gemfile (BUNDLE_GEMFILE, or found from the working directory up, as Bundler does) -> bundle exec fastlane
|
|
62
|
+
/// 4. fastlane on PATH
|
|
63
|
+
func fastlaneLaunchArguments() -> [String] {
|
|
64
|
+
if let bin = ProcessInfo.processInfo.environment["FASTLANE_SPM_BIN"],
|
|
65
|
+
!bin.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty
|
|
66
|
+
{
|
|
67
|
+
// The shell splits the value, so quoted paths with spaces work; our arguments
|
|
68
|
+
// pass through "$@" untouched, and exec keeps the launched process ID.
|
|
69
|
+
return ["/bin/sh", "-c", "exec \(bin) \"$@\"", "sh"]
|
|
70
|
+
}
|
|
71
|
+
guard let bundleRoot = bundleRootDirectory() else {
|
|
72
|
+
return ["fastlane"]
|
|
73
|
+
}
|
|
74
|
+
let binstub = bundleRoot + "/bin/fastlane"
|
|
75
|
+
if FileManager.default.isExecutableFile(atPath: binstub) {
|
|
76
|
+
return [binstub]
|
|
77
|
+
}
|
|
78
|
+
return ["bundle", "exec", "fastlane"]
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/// The directory of the Gemfile Bundler would use: BUNDLE_GEMFILE, else the
|
|
82
|
+
/// nearest Gemfile or gems.rb from the working directory up.
|
|
83
|
+
func bundleRootDirectory() -> String? {
|
|
84
|
+
let workingDirectory = FileManager.default.currentDirectoryPath
|
|
85
|
+
if let gemfile = ProcessInfo.processInfo.environment["BUNDLE_GEMFILE"], !gemfile.isEmpty {
|
|
86
|
+
let path = gemfile.hasPrefix("/") ? gemfile : workingDirectory + "/" + gemfile
|
|
87
|
+
return (path as NSString).deletingLastPathComponent
|
|
88
|
+
}
|
|
89
|
+
var directory = workingDirectory
|
|
90
|
+
while true {
|
|
91
|
+
for name in ["Gemfile", "gems.rb"] where FileManager.default.fileExists(atPath: directory + "/" + name) {
|
|
92
|
+
return directory
|
|
93
|
+
}
|
|
94
|
+
let parent = (directory as NSString).deletingLastPathComponent
|
|
95
|
+
if parent == directory || parent.isEmpty {
|
|
96
|
+
return nil
|
|
97
|
+
}
|
|
98
|
+
directory = parent
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/// The ruby socket server performs a single `accept` (see
|
|
103
|
+
/// fastlane/server/socket_server.rb), so probing readiness with a TCP
|
|
104
|
+
/// connection would consume that accept and shut the server down.
|
|
105
|
+
/// Poll the LISTEN state read-only via lsof instead of the previous
|
|
106
|
+
/// "stdout quiet for 5 seconds" heuristic.
|
|
107
|
+
private func waitUntilSocketServerIsListening(port: UInt32, serverProcess: Process) {
|
|
108
|
+
let deadline = Date(timeIntervalSinceNow: 30)
|
|
109
|
+
while Date() < deadline {
|
|
110
|
+
if !serverProcess.isRunning {
|
|
111
|
+
log(message: "fastlane socket_server exited with status \(serverProcess.terminationStatus) before listening. Check that the resolved fastlane installation works (e.g. `bundle exec fastlane --version`).")
|
|
112
|
+
exit(1)
|
|
113
|
+
}
|
|
114
|
+
if isPortListening(port, by: serverProcess.processIdentifier) {
|
|
115
|
+
return
|
|
116
|
+
}
|
|
117
|
+
Thread.sleep(forTimeInterval: 0.2)
|
|
118
|
+
}
|
|
119
|
+
// Don't leak the socket server: it's still running (just not
|
|
120
|
+
// listening yet) on this timeout path, so terminate it before exit.
|
|
121
|
+
terminate(serverProcess: serverProcess)
|
|
122
|
+
log(message: "fastlane socket_server did not start listening on port \(port) within 30 seconds")
|
|
123
|
+
exit(1)
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/// Terminate the socket server, escalating SIGTERM to SIGKILL if it
|
|
127
|
+
/// doesn't exit promptly, so the timeout path never leaves an orphan.
|
|
128
|
+
private func terminate(serverProcess: Process) {
|
|
129
|
+
serverProcess.terminate()
|
|
130
|
+
let killDeadline = Date(timeIntervalSinceNow: 2)
|
|
131
|
+
while serverProcess.isRunning, Date() < killDeadline {
|
|
132
|
+
Thread.sleep(forTimeInterval: 0.1)
|
|
133
|
+
}
|
|
134
|
+
if serverProcess.isRunning {
|
|
135
|
+
_ = outputOfProcess(arguments: ["/bin/kill", "-9", String(serverProcess.processIdentifier)])
|
|
136
|
+
serverProcess.waitUntilExit()
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/// Clears a stale socket server left by a previously crashed run on this
|
|
141
|
+
/// port. Scoped to LISTENing ruby processes (`-sTCP:LISTEN -a -c ruby`)
|
|
142
|
+
/// so it never kills an unrelated service or a connected client that
|
|
143
|
+
/// happens to share the port.
|
|
144
|
+
private func killExistingSocketServerProcesses(port: UInt32) {
|
|
145
|
+
let pids = outputOfProcess(arguments: [lsofPath, "-t", "-nP", "-iTCP:\(port)", "-sTCP:LISTEN", "-a", "-c", "ruby"])
|
|
146
|
+
.split(separator: "\n")
|
|
147
|
+
pids.forEach { _ = outputOfProcess(arguments: ["/bin/kill", "-9", String($0)]) }
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/// socket_server listens on whichever of 127.0.0.1 and ::1 is free, while the runner connects to `localhost`,
|
|
151
|
+
/// so a process holding the port on either address would receive the runner's commands.
|
|
152
|
+
private func abortIfPortIsInUse(_ port: UInt32) {
|
|
153
|
+
guard isAddressInUse(family: AF_INET, port: port) || isAddressInUse(family: AF_INET6, port: port) else {
|
|
154
|
+
return
|
|
155
|
+
}
|
|
156
|
+
// lsof only lists this user's processes unless run as root
|
|
157
|
+
let holders = outputOfProcess(arguments: [lsofPath, "-nP", "-iTCP:\(port)", "-sTCP:LISTEN"])
|
|
158
|
+
let holder = holders.isEmpty ? " by a process of another user" : ":\n\(holders)"
|
|
159
|
+
log(message: "Port \(port) is already in use on localhost\(holder)\nStop it, or choose another port for the runner with `swiftServerPort`.")
|
|
160
|
+
exit(1)
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
/// Binding fails with EADDRINUSE when another socket listens on that address and port, whoever owns it.
|
|
164
|
+
func isAddressInUse(family: Int32, port: UInt32) -> Bool {
|
|
165
|
+
let socketDescriptor = socket(family, SOCK_STREAM, 0)
|
|
166
|
+
guard socketDescriptor >= 0 else {
|
|
167
|
+
return false
|
|
168
|
+
}
|
|
169
|
+
defer { close(socketDescriptor) }
|
|
170
|
+
// Ignore connections left in TIME_WAIT by an earlier run, as the Ruby server does
|
|
171
|
+
var reuse: Int32 = 1
|
|
172
|
+
setsockopt(socketDescriptor, SOL_SOCKET, SO_REUSEADDR, &reuse, socklen_t(MemoryLayout<Int32>.size))
|
|
173
|
+
|
|
174
|
+
let result: Int32
|
|
175
|
+
if family == AF_INET {
|
|
176
|
+
var address = sockaddr_in()
|
|
177
|
+
address.sin_len = UInt8(MemoryLayout<sockaddr_in>.size)
|
|
178
|
+
address.sin_family = sa_family_t(AF_INET)
|
|
179
|
+
address.sin_port = in_port_t(UInt16(port).bigEndian)
|
|
180
|
+
address.sin_addr.s_addr = inet_addr("127.0.0.1")
|
|
181
|
+
result = withUnsafePointer(to: &address) {
|
|
182
|
+
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) { bind(socketDescriptor, $0, socklen_t(MemoryLayout<sockaddr_in>.size)) }
|
|
183
|
+
}
|
|
184
|
+
} else {
|
|
185
|
+
var address = sockaddr_in6()
|
|
186
|
+
address.sin6_len = UInt8(MemoryLayout<sockaddr_in6>.size)
|
|
187
|
+
address.sin6_family = sa_family_t(AF_INET6)
|
|
188
|
+
address.sin6_port = in_port_t(UInt16(port).bigEndian)
|
|
189
|
+
address.sin6_addr = in6addr_loopback
|
|
190
|
+
result = withUnsafePointer(to: &address) {
|
|
191
|
+
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) { bind(socketDescriptor, $0, socklen_t(MemoryLayout<sockaddr_in6>.size)) }
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
return result != 0 && errno == EADDRINUSE
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/// Only the process we launched counts: another process listening on the port is not our server
|
|
198
|
+
private func isPortListening(_ port: UInt32, by processIdentifier: Int32) -> Bool {
|
|
199
|
+
let result = runProcess(arguments: [lsofPath, "-t", "-nP", "-iTCP:\(port)", "-sTCP:LISTEN"])
|
|
200
|
+
// `env` exits 127 when lsof can't be found. Without this guard the
|
|
201
|
+
// probe would silently return false on every poll, then kill the
|
|
202
|
+
// freshly launched server after the 30s timeout with a misleading
|
|
203
|
+
// "did not start listening" message. Fail fast with the real cause.
|
|
204
|
+
if result.status == 127 {
|
|
205
|
+
log(message: "Could not run lsof (\(lsofPath)) to check socket server readiness. lsof ships at /usr/sbin/lsof on macOS; ensure it is installed and reachable.")
|
|
206
|
+
exit(1)
|
|
207
|
+
}
|
|
208
|
+
return result.output.split(separator: "\n").contains { $0 == Substring(String(processIdentifier)) }
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/// Prefer the absolute macOS path so port checks don't depend on PATH;
|
|
212
|
+
/// fall back to a PATH lookup if lsof lives somewhere non-standard.
|
|
213
|
+
private var lsofPath: String {
|
|
214
|
+
let standardPath = "/usr/sbin/lsof"
|
|
215
|
+
return FileManager.default.isExecutableFile(atPath: standardPath) ? standardPath : "lsof"
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
private func outputOfProcess(arguments: [String]) -> String {
|
|
219
|
+
return runProcess(arguments: arguments).output
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
private func runProcess(arguments: [String]) -> (output: String, status: Int32) {
|
|
223
|
+
let process = Process()
|
|
224
|
+
let pipe = Pipe()
|
|
225
|
+
process.launchPath = "/usr/bin/env"
|
|
226
|
+
process.arguments = arguments
|
|
227
|
+
process.standardOutput = pipe
|
|
228
|
+
process.standardError = FileHandle.nullDevice
|
|
229
|
+
process.launch()
|
|
230
|
+
process.waitUntilExit()
|
|
231
|
+
let data = pipe.fileHandleForReading.readDataToEndOfFile()
|
|
232
|
+
return (String(data: data, encoding: .utf8) ?? "", process.terminationStatus)
|
|
233
|
+
}
|
|
234
|
+
#endif
|
|
65
235
|
}
|
|
66
236
|
|
|
67
237
|
public class Main {
|
|
@@ -56,10 +56,10 @@ public protocol MatchfileProtocol: AnyObject {
|
|
|
56
56
|
/// Clone just the branch specified, instead of the whole repo. This requires that the branch already exists. Otherwise the command will fail
|
|
57
57
|
var cloneBranchDirectly: Bool { get }
|
|
58
58
|
|
|
59
|
-
/// Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64
|
|
59
|
+
/// Use a basic authorization header to access the git repo (e.g.: access via HTTPS, GitHub Actions, etc), usually a string in Base64. Needs git 2.31 or later
|
|
60
60
|
var gitBasicAuthorization: String? { get }
|
|
61
61
|
|
|
62
|
-
/// Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64
|
|
62
|
+
/// Use a bearer authorization header to access the git repo (e.g.: access to an Azure DevOps repository), usually a string in Base64. Needs git 2.31 or later
|
|
63
63
|
var gitBearerAuthorization: String? { get }
|
|
64
64
|
|
|
65
65
|
/// Use a private key to access the git repo (e.g.: access to GitHub repository via Deploy keys), usually a id_rsa named file or the contents hereof
|
|
@@ -173,6 +173,9 @@ public protocol MatchfileProtocol: AnyObject {
|
|
|
173
173
|
/// Force encryption to use legacy cbc algorithm for backwards compatibility with older match versions
|
|
174
174
|
var forceLegacyEncryption: Bool { get }
|
|
175
175
|
|
|
176
|
+
/// Enable profile with 'Offline Support' (7 day validity). Requires Apple ID login, not supported with App Store Connect API key authentication
|
|
177
|
+
var offlineProfile: Bool { get }
|
|
178
|
+
|
|
176
179
|
/// Print out extra information and all commands
|
|
177
180
|
var verbose: Bool { get }
|
|
178
181
|
}
|
|
@@ -406,6 +409,10 @@ public extension MatchfileProtocol {
|
|
|
406
409
|
return false
|
|
407
410
|
}
|
|
408
411
|
|
|
412
|
+
var offlineProfile: Bool {
|
|
413
|
+
return false
|
|
414
|
+
}
|
|
415
|
+
|
|
409
416
|
var verbose: Bool {
|
|
410
417
|
return false
|
|
411
418
|
}
|
|
@@ -413,4 +420,4 @@ public extension MatchfileProtocol {
|
|
|
413
420
|
|
|
414
421
|
// Please don't remove the lines below
|
|
415
422
|
// They are used to detect outdated files
|
|
416
|
-
// FastlaneRunnerAPIVersion [0.9.
|
|
423
|
+
// FastlaneRunnerAPIVersion [0.9.154]
|
|
@@ -77,6 +77,9 @@ public protocol ScanfileProtocol: AnyObject {
|
|
|
77
77
|
/// Should the thread sanitizer be turned on?
|
|
78
78
|
var threadSanitizer: Bool? { get }
|
|
79
79
|
|
|
80
|
+
/// Whether verbose and long-running diagnostics (like sysdiagnoses or log archives) are collected when testing. Valid values are: on-failure or never. If not specified, the value in the test plan is used. Equivalent to -collect-test-diagnostics (Xcode 14 and up)
|
|
81
|
+
var collectTestDiagnostics: String? { get }
|
|
82
|
+
|
|
80
83
|
/// Should the HTML report be opened when tests are completed?
|
|
81
84
|
var openReport: Bool { get }
|
|
82
85
|
|
|
@@ -353,6 +356,10 @@ public extension ScanfileProtocol {
|
|
|
353
356
|
return nil
|
|
354
357
|
}
|
|
355
358
|
|
|
359
|
+
var collectTestDiagnostics: String? {
|
|
360
|
+
return nil
|
|
361
|
+
}
|
|
362
|
+
|
|
356
363
|
var openReport: Bool {
|
|
357
364
|
return false
|
|
358
365
|
}
|
|
@@ -588,4 +595,4 @@ public extension ScanfileProtocol {
|
|
|
588
595
|
|
|
589
596
|
// Please don't remove the lines below
|
|
590
597
|
// They are used to detect outdated files
|
|
591
|
-
// FastlaneRunnerAPIVersion [0.9.
|
|
598
|
+
// FastlaneRunnerAPIVersion [0.9.165]
|