fastlane 2.158.0 → 2.163.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (123) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +74 -74
  3. data/cert/lib/cert/options.rb +28 -1
  4. data/cert/lib/cert/runner.rb +50 -33
  5. data/deliver/lib/deliver/app_screenshot_iterator.rb +4 -4
  6. data/deliver/lib/deliver/module.rb +2 -0
  7. data/deliver/lib/deliver/options.rb +20 -4
  8. data/deliver/lib/deliver/runner.rb +36 -8
  9. data/deliver/lib/deliver/upload_metadata.rb +49 -9
  10. data/deliver/lib/deliver/upload_price_tier.rb +7 -2
  11. data/deliver/lib/deliver/upload_screenshots.rb +25 -8
  12. data/{pilot/lib/pilot/.manager.rb.swp → fastlane/lib/fastlane/.erb_template_helper.rb.swp} +0 -0
  13. data/fastlane/lib/fastlane/actions/{.slack.rb.swp → .git_commit.rb.swp} +0 -0
  14. data/fastlane/lib/fastlane/actions/.register_device.rb.swp +0 -0
  15. data/fastlane/lib/fastlane/actions/.register_devices.rb.swp +0 -0
  16. data/fastlane/lib/fastlane/actions/actions_helper.rb +20 -1
  17. data/fastlane/lib/fastlane/actions/app_store_build_number.rb +39 -3
  18. data/fastlane/lib/fastlane/actions/app_store_connect_api_key.rb +15 -1
  19. data/fastlane/lib/fastlane/actions/check_app_store_metadata.rb +1 -0
  20. data/fastlane/lib/fastlane/actions/clean_build_artifacts.rb +1 -0
  21. data/fastlane/lib/fastlane/actions/docs/capture_android_screenshots.md +2 -2
  22. data/fastlane/lib/fastlane/actions/docs/capture_ios_screenshots.md +1 -1
  23. data/fastlane/lib/fastlane/actions/docs/create_app_online.md +1 -1
  24. data/fastlane/lib/fastlane/actions/docs/frame_screenshots.md +3 -2
  25. data/fastlane/lib/fastlane/actions/docs/run_tests.md +2 -2
  26. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +3 -3
  27. data/fastlane/lib/fastlane/actions/docs/upload_to_play_store.md +2 -2
  28. data/fastlane/lib/fastlane/actions/docs/upload_to_testflight.md +2 -2
  29. data/fastlane/lib/fastlane/actions/download_dsyms.rb +32 -7
  30. data/fastlane/lib/fastlane/actions/ensure_git_status_clean.rb +13 -2
  31. data/fastlane/lib/fastlane/actions/get_certificates.rb +1 -0
  32. data/fastlane/lib/fastlane/actions/get_provisioning_profile.rb +1 -0
  33. data/fastlane/lib/fastlane/actions/latest_testflight_build_number.rb +15 -0
  34. data/fastlane/lib/fastlane/actions/register_device.rb +46 -5
  35. data/fastlane/lib/fastlane/actions/register_devices.rb +46 -15
  36. data/fastlane/lib/fastlane/actions/sync_code_signing.rb +1 -0
  37. data/fastlane/lib/fastlane/actions/upload_to_app_store.rb +3 -2
  38. data/fastlane/lib/fastlane/helper/git_helper.rb +2 -0
  39. data/fastlane/lib/fastlane/swift_fastlane_api_generator.rb +6 -4
  40. data/fastlane/lib/fastlane/swift_fastlane_function.rb +1 -1
  41. data/fastlane/lib/fastlane/version.rb +1 -1
  42. data/fastlane/swift/Actions.swift +2 -1
  43. data/fastlane/swift/Appfile.swift +2 -4
  44. data/fastlane/swift/ArgumentProcessor.swift +2 -6
  45. data/fastlane/swift/ControlCommand.swift +2 -5
  46. data/fastlane/swift/Deliverfile.swift +5 -2
  47. data/fastlane/swift/DeliverfileProtocol.swift +18 -7
  48. data/fastlane/swift/Fastfile.swift +5 -1
  49. data/fastlane/swift/Fastlane.swift +2368 -2251
  50. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.pbxproj +5 -5
  51. data/fastlane/swift/Gymfile.swift +5 -2
  52. data/fastlane/swift/GymfileProtocol.swift +6 -3
  53. data/fastlane/swift/LaneFileProtocol.swift +49 -40
  54. data/fastlane/swift/MainProcess.swift +77 -0
  55. data/fastlane/swift/Matchfile.swift +5 -2
  56. data/fastlane/swift/MatchfileProtocol.swift +21 -6
  57. data/fastlane/swift/Plugins.swift +2 -1
  58. data/fastlane/swift/Precheckfile.swift +5 -2
  59. data/fastlane/swift/PrecheckfileProtocol.swift +14 -3
  60. data/fastlane/swift/RubyCommand.swift +2 -6
  61. data/fastlane/swift/RubyCommandable.swift +2 -6
  62. data/fastlane/swift/Runner.swift +5 -9
  63. data/fastlane/swift/RunnerArgument.swift +2 -6
  64. data/fastlane/swift/Scanfile.swift +5 -2
  65. data/fastlane/swift/ScanfileProtocol.swift +6 -3
  66. data/fastlane/swift/Screengrabfile.swift +5 -2
  67. data/fastlane/swift/ScreengrabfileProtocol.swift +6 -3
  68. data/fastlane/swift/Snapshotfile.swift +5 -2
  69. data/fastlane/swift/SnapshotfileProtocol.swift +6 -3
  70. data/fastlane/swift/SocketClient.swift +3 -7
  71. data/fastlane/swift/SocketClientDelegateProtocol.swift +2 -6
  72. data/fastlane/swift/SocketResponse.swift +2 -6
  73. data/fastlane/swift/formatting/Brewfile.lock.json +18 -10
  74. data/fastlane/swift/main.swift +4 -8
  75. data/fastlane/swift/upgrade_manifest.json +1 -1
  76. data/fastlane_core/lib/fastlane_core/analytics/analytics_session.rb +6 -7
  77. data/fastlane_core/lib/fastlane_core/keychain_importer.rb +2 -2
  78. data/frameit/lib/frameit/editor.rb +1 -0
  79. data/gym/lib/gym/generators/package_command_generator_xcode7.rb +2 -2
  80. data/match/lib/match/generator.rb +6 -1
  81. data/match/lib/match/importer.rb +44 -8
  82. data/match/lib/match/migrate.rb +13 -2
  83. data/match/lib/match/nuke.rb +65 -22
  84. data/match/lib/match/options.rb +27 -2
  85. data/match/lib/match/runner.rb +38 -10
  86. data/match/lib/match/spaceship_ensure.rb +27 -21
  87. data/match/lib/match/storage/google_cloud_storage.rb +20 -3
  88. data/match/lib/match/storage/s3_storage.rb +19 -3
  89. data/pilot/lib/pilot/options.rb +2 -2
  90. data/precheck/lib/precheck/options.rb +16 -0
  91. data/precheck/lib/precheck/runner.rb +20 -1
  92. data/sigh/lib/sigh/download_all.rb +16 -4
  93. data/sigh/lib/sigh/options.rb +21 -0
  94. data/sigh/lib/sigh/runner.rb +80 -38
  95. data/snapshot/lib/assets/SnapshotHelper.swift +21 -2
  96. data/spaceship/README.md +1 -1
  97. data/spaceship/lib/spaceship/{connect_api/.DS_Store → .DS_Store} +0 -0
  98. data/spaceship/lib/spaceship/client.rb +9 -4
  99. data/spaceship/lib/spaceship/connect_api.rb +25 -0
  100. data/spaceship/lib/spaceship/connect_api/api_client.rb +12 -3
  101. data/spaceship/lib/spaceship/connect_api/client.rb +38 -15
  102. data/{fastlane/lib/fastlane/actions/.update_project_provisioning.rb.swp → spaceship/lib/spaceship/connect_api/models/.app_store_version_submission.rb.swp} +0 -0
  103. data/spaceship/lib/spaceship/connect_api/models/app.rb +17 -9
  104. data/spaceship/lib/spaceship/connect_api/models/app_info.rb +1 -0
  105. data/spaceship/lib/spaceship/connect_api/models/app_screenshot.rb +3 -1
  106. data/spaceship/lib/spaceship/connect_api/models/app_screenshot_set.rb +2 -2
  107. data/spaceship/lib/spaceship/connect_api/models/app_store_version.rb +3 -5
  108. data/spaceship/lib/spaceship/connect_api/models/app_store_version_localization.rb +3 -5
  109. data/spaceship/lib/spaceship/connect_api/models/beta_tester.rb +2 -1
  110. data/spaceship/lib/spaceship/connect_api/models/certificate.rb +42 -0
  111. data/spaceship/lib/spaceship/connect_api/models/device.rb +5 -0
  112. data/spaceship/lib/spaceship/connect_api/models/profile.rb +7 -1
  113. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +59 -0
  114. data/spaceship/lib/spaceship/connect_api/provisioning/provisioning.rb +45 -2
  115. data/spaceship/lib/spaceship/connect_api/spaceship.rb +3 -2
  116. data/spaceship/lib/spaceship/connect_api/testflight/testflight.rb +13 -0
  117. data/spaceship/lib/spaceship/connect_api/token.rb +6 -1
  118. data/spaceship/lib/spaceship/connect_api/tunes/tunes.rb +17 -9
  119. data/spaceship/lib/spaceship/connect_api/users/users.rb +40 -0
  120. data/spaceship/lib/spaceship/helper/net_http_generic_request.rb +11 -5
  121. metadata +27 -25
  122. data/fastlane/lib/fastlane/actions/.hockey.rb.swp +0 -0
  123. data/fastlane/swift/FastlaneSwiftRunner/FastlaneSwiftRunner.xcodeproj/project.xcworkspace/xcuserdata/josh.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
@@ -1,3 +1,5 @@
1
+ require 'base64'
2
+
1
3
  module Fastlane
2
4
  module Actions
3
5
  module SharedValues
@@ -9,6 +11,7 @@ module Fastlane
9
11
  key_id = options[:key_id]
10
12
  issuer_id = options[:issuer_id]
11
13
  key_content = options[:key_content]
14
+ is_key_content_base64 = options[:is_key_content_base64]
12
15
  key_filepath = options[:key_filepath]
13
16
  duration = options[:duration]
14
17
  in_house = options[:in_house]
@@ -17,17 +20,22 @@ module Fastlane
17
20
  UI.user_error!(":key_content or :key_filepath is required")
18
21
  end
19
22
 
23
+ # New lines don't get read properly when coming from an ENV
24
+ # Replacing them literal version with a new line
25
+ key_content = key_content.gsub('\n', "\n") if key_content
26
+
20
27
  # This hash matches the named arguments on
21
28
  # the Spaceship::ConnectAPI::Token.create method
22
29
  key = {
23
30
  key_id: key_id,
24
31
  issuer_id: issuer_id,
25
32
  key: key_content || File.binread(key_filepath),
33
+ is_key_content_base64: is_key_content_base64,
26
34
  duration: duration,
27
35
  in_house: in_house
28
36
  }
29
37
 
30
- Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY] = key
38
+ Actions.lane_context.set_sensitive(SharedValues::APP_STORE_CONNECT_API_KEY, key)
31
39
 
32
40
  return key
33
41
  end
@@ -55,8 +63,14 @@ module Fastlane
55
63
  FastlaneCore::ConfigItem.new(key: :key_content,
56
64
  env_name: "APP_STORE_CONNECT_API_KEY_KEY",
57
65
  description: "The content of the key p8 file",
66
+ sensitive: true,
58
67
  optional: true,
59
68
  conflicting_options: [:filepath]),
69
+ FastlaneCore::ConfigItem.new(key: :is_key_content_base64,
70
+ env_name: "APP_STORE_CONNECT_API_KEY_IS_KEY_CONTENT_BASE64",
71
+ description: "Whether :key_content is Base64 encoded or not",
72
+ type: Boolean,
73
+ default_value: false),
60
74
  FastlaneCore::ConfigItem.new(key: :duration,
61
75
  env_name: "APP_STORE_CONNECT_API_KEY_DURATION",
62
76
  description: "The token session duration",
@@ -7,6 +7,7 @@ module Fastlane
7
7
  def self.run(config)
8
8
  require 'precheck'
9
9
  Precheck.config = config
10
+ Precheck.config[:api_key] ||= Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
10
11
  return Precheck::Runner.new.run
11
12
  end
12
13
 
@@ -23,6 +23,7 @@ module Fastlane
23
23
 
24
24
  Actions.lane_context[Actions::SharedValues::SIGH_PROFILE_PATHS] = nil
25
25
  Actions.lane_context[Actions::SharedValues::DSYM_PATHS] = nil
26
+ Actions.lane_context[Actions::SharedValues::DSYM_LATEST_UPLOADED_DATE] = nil
26
27
 
27
28
  UI.success('Cleaned up build artifacts 🐙')
28
29
  end
@@ -198,7 +198,7 @@ class JUnit4StyleTests {
198
198
 
199
199
  ```
200
200
 
201
- There is an [example project](https://github.com/fastlane/fastlane/tree/master/screengrab/example/src/androidTest/java/tools/fastlane/localetester) showing how to use use JUnit 3 or 4 and Espresso with the screengrab Java library to capture screenshots during a UI test run.
201
+ There is an [example project](https://github.com/fastlane/fastlane/tree/master/screengrab/example/src/androidTest/java/tools/fastlane/localetester) showing how to use JUnit 3 or 4 and Espresso with the screengrab Java library to capture screenshots during a UI test run.
202
202
 
203
203
  Using JUnit 4 is preferable because of its ability to perform actions before and after the entire test class is run. This means you will change the device's locale far fewer times when compared with JUnit 3 running those commands before and after each test method.
204
204
 
@@ -251,7 +251,7 @@ new CleanStatusBar()
251
251
  <details>
252
252
  <summary>Launch Arguments</summary>
253
253
 
254
- You can provide additional arguments to your testcases on launch. These strings will be available in your tests through `InstrumentationRegistry.getArguments()`.
254
+ You can provide additional arguments to your test cases on launch. These strings will be available in your tests through `InstrumentationRegistry.getArguments()`.
255
255
 
256
256
  ```ruby
257
257
  screengrab(
@@ -251,7 +251,7 @@ to update your `SnapshotHelper.swift` files. In case you modified your `Snapshot
251
251
 
252
252
  ## Launch Arguments
253
253
 
254
- You can provide additional arguments to your app on launch. These strings will be available in your app (eg. not in the testing target) through `ProcessInfo.processInfo.arguments`. Alternatively, use user-default syntax (`-key value`) and they will be available as key-value pairs in `UserDefaults.standard`.
254
+ You can provide additional arguments to your app on launch. These strings will be available in your app (e.g. not in the testing target) through `ProcessInfo.processInfo.arguments`. Alternatively, use user-default syntax (`-key value`) and they will be available as key-value pairs in `UserDefaults.standard`.
255
255
 
256
256
  ```ruby-skip-tests
257
257
  launch_arguments([
@@ -2,7 +2,7 @@
2
2
  <img src="/img/actions/produce.png" width="250">
3
3
  </p>
4
4
 
5
- ###### Create new iOS apps on App Store Connect and Dev Portal using your command line
5
+ ###### Create new iOS apps on App Store Connect and Apple Developer Portal using your command line
6
6
 
7
7
  _produce_ creates new iOS apps on both the Apple Developer Portal and App Store Connect with the minimum required information.
8
8
 
@@ -133,7 +133,7 @@ The general parameters are defined in the `default` key and can be:
133
133
  | `stack_title` | Specifies whether _frameit_ should display the keyword above the title when both keyword and title are defined. If it is false, the title and keyword will be displayed side by side when both keyword and title are defined. | `false` |
134
134
  | `title_below_image` | Specifies whether _frameit_ should place the title and optional keyword below the device frame. If it is false, it will be placed above the device frame. | `false` |
135
135
  | `show_complete_frame` | Specifies whether _frameit_ should shrink the device frame so that it is completely shown in the framed screenshot. If it is false, clipping of the device frame might occur at the bottom (when `title_below_image` is `false`) or top (when `title_below_image` is `true`) of the framed screenshot. | `false` |
136
- | `padding` | The content of the framed screenshot will be resized to match the specified `padding` around all edges. The vertical padding is also applied between the text and the top or bottom (depending on `title_below_image`) of the device frame. <p> There are 3 different options of specyfying the padding: <p> 1. Default: An integer value that defines both horizontal and vertical padding in pixels. <br> 2. A string that defines (different) padding values in pixels for horizontal and vertical padding. The syntax is `"<horizontal>x<vertical>"`, e.g. `"30x60"`. <br> 3. A string that defines (different) padding values in percentage for horizontal and vertical padding. The syntax is `"<horizontal>%x<vertical>%"`, e.g. `"5%x10%"`. <br> **Note:** The percentage is calculated from the smallest image dimension (height or width). <p> A combination of option 2 and 3 is possible, e.g. `"5%x40"`. | `50` |
136
+ | `padding` | The content of the framed screenshot will be resized to match the specified `padding` around all edges. The vertical padding is also applied between the text and the top or bottom (depending on `title_below_image`) of the device frame. <p> There are 3 different options of specifying the padding: <p> 1. Default: An integer value that defines both horizontal and vertical padding in pixels. <br> 2. A string that defines (different) padding values in pixels for horizontal and vertical padding. The syntax is `"<horizontal>x<vertical>"`, e.g. `"30x60"`. <br> 3. A string that defines (different) padding values in percentage for horizontal and vertical padding. The syntax is `"<horizontal>%x<vertical>%"`, e.g. `"5%x10%"`. <br> **Note:** The percentage is calculated from the smallest image dimension (height or width). <p> A combination of option 2 and 3 is possible, e.g. `"5%x40"`. | `50` |
137
137
  | `interline_spacing` | Specifies whether _frameit_ should add or subtract this many pixels between the individual lines of text. This only applies to a multi-line `title` and/or `keyword` to expand or squash together the individual lines of text. | `0` |
138
138
  | `font_scale_factor` | Specifies whether _frameit_ should increase or decrease the font size of the text. Is ignored for `keyword` or `title`, if `font_size` is specified. | `0.1` |
139
139
  | `frame` | Overrides the color of the frame to be used. (Valid values are `BLACK`, `WHITE`, `GOLD` and `ROSE_GOLD`) | NA |
@@ -161,9 +161,10 @@ The `keyword` and `title` parameters are both used in `default` and `data`. They
161
161
 
162
162
  | Key | Description | Default value |
163
163
  |-----|-------------|---------------|
164
- | `color` | The font color for the text. Specify a hex/html color code. | `#000000` (black) |
164
+ | `color` | The font color for the text. Specify a HEX/HTML color code. | `#000000` (black) |
165
165
  | `font` | The font family for the text. Specify the (relative) path to the font file (e.g. an OpenType Font). | The default `imagemagick` font, which is system dependent. |
166
166
  | `font_size` | The font size for the text specified in points. If not specified or `0`, font will be scaled automatically to fit the available space. _frameit_ still shrinks the text, if it would not fit. | NA |
167
+ | `font_weight` | The [font weight for the text](https://imagemagick.org/script/command-line-options.php#weight). Specify an integer value (e.g. 900). | NA |
167
168
  | `text` | The text that should be used for the `keyword` or `title`. <p> Note: If you want to use localised text, use [`.strings` files](#strings-files). | NA |
168
169
 
169
170
  ### Example
@@ -81,7 +81,7 @@ _scan_ uses the latest APIs and tools to make running tests plain simple and off
81
81
  👱 | Automatically switches to the [travis formatter](https://github.com/kattrali/xcpretty-travis-formatter) when running on Travis
82
82
  📖 | Helps you resolve common test errors like simulator not responding
83
83
 
84
- _scan_ uses a plain `xcodebuild` command, therefore keeping 100% compatible with `xcodebuild`. To generate the nice output, _scan_ uses [xcpretty](https://github.com/supermarin/xcpretty). You can alway access the raw output in `~/Library/Logs/scan`.
84
+ _scan_ uses a plain `xcodebuild` command, therefore keeping 100% compatible with `xcodebuild`. To generate the nice output, _scan_ uses [xcpretty](https://github.com/supermarin/xcpretty). You can always access the raw output in `~/Library/Logs/scan`.
85
85
 
86
86
  ![img/actions/scanScreenshot.png](/img/actions/scanScreenshot.png)
87
87
  ![img/actions/slack.png](/img/actions/slack.png)
@@ -100,7 +100,7 @@ That's all you need to run your tests. If you want more control, here are some a
100
100
  fastlane scan --workspace "Example.xcworkspace" --scheme "AppName" --device "iPhone 6" --clean
101
101
  ```
102
102
 
103
- If you need to use a different xcode install, use `xcode-select` or define `DEVELOPER_DIR`:
103
+ If you need to use a different Xcode install, use `xcode-select` or define `DEVELOPER_DIR`:
104
104
 
105
105
  ```no-highlight
106
106
  DEVELOPER_DIR="/Applications/Xcode6.2.app" scan
@@ -130,9 +130,9 @@ match
130
130
 
131
131
  You can find more information about GitHub basic authentication and personal token generation here: [https://developer.github.com/v3/auth/#basic-authentication](https://developer.github.com/v3/auth/#basic-authentication)
132
132
 
133
- ##### Git Storage on Azure Devops
133
+ ##### Git Storage on Azure DevOps
134
134
 
135
- If you're running a pipeline on Azure Devops and using git storage in a another repository on the same project, you might want to use `bearer` token authentication.
135
+ If you're running a pipeline on Azure DevOps and using git storage in a another repository on the same project, you might want to use `bearer` token authentication.
136
136
 
137
137
  Using parameter:
138
138
 
@@ -533,7 +533,7 @@ Storing your private keys in a Git repo may sound off-putting at first. We did a
533
533
 
534
534
  ### Google Cloud Storage
535
535
 
536
- All your keys and provisioning profiles are encrypted using Google managed keys.
536
+ All your keys and provisioning profiles are encrypted using Google managed keys.
537
537
 
538
538
  ### What could happen if someone stole a private key?
539
539
 
@@ -49,7 +49,7 @@ The previous p12 configuration is still currently supported.
49
49
 
50
50
  ## Quick Start
51
51
 
52
- > Before using _supply_ to connect to Google Play Store, you'll need to set up your app manually first by uploading at least one build to Google Play Store. See [fastane/fastlane#14686](https://github.com/fastlane/fastlane/issues/14686) for more info.
52
+ > Before using _supply_ to connect to Google Play Store, you'll need to set up your app manually first by uploading at least one build to Google Play Store. See [fastlane/fastlane#14686](https://github.com/fastlane/fastlane/issues/14686) for more info.
53
53
 
54
54
  - `cd [your_project_folder]`
55
55
  - `fastlane supply init`
@@ -198,6 +198,6 @@ For more information, see the `fastlane action google_play_track_version_codes`
198
198
  - `:check_superseded_tracks`
199
199
  - Google Play will automatically remove releases that are superseded now
200
200
  - `:deactivate_on_promote`
201
- - Google Play will automatically deactive a release from its previous track on promote
201
+ - Google Play will automatically deactivate a release from its previous track on promote
202
202
 
203
203
  :
@@ -32,7 +32,7 @@ For all commands, you can either use an [API Key](#app-store-connect-api-key) or
32
32
 
33
33
  The App Store Connect API Key is the preferred authentication method (if you are able to use it).
34
34
 
35
- - Uses offial App Store Connect API
35
+ - Uses official App Store Connect API
36
36
  - No need for 2FA
37
37
  - Better performance over Apple ID
38
38
 
@@ -244,7 +244,7 @@ If you are on multiple App Store Connect teams, iTunes Transporter may need a pr
244
244
 
245
245
  ## Use an Application Specific Password to upload
246
246
 
247
- _pilot_/`upload_to_testflight` can use an [Application Specific Password via the `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` envirionment variable](https://docs.fastlane.tools/best-practices/continuous-integration/#application-specific-passwords) to upload a binary if both the `skip_waiting_for_build_processing` and `apple_id` options are set. (If any of those are not set, it will use the normal Apple login process that might require 2FA authentication.)
247
+ _pilot_/`upload_to_testflight` can use an [Application Specific Password via the `FASTLANE_APPLE_APPLICATION_SPECIFIC_PASSWORD` environment variable](https://docs.fastlane.tools/best-practices/continuous-integration/#application-specific-passwords) to upload a binary if both the `skip_waiting_for_build_processing` and `apple_id` options are set. (If any of those are not set, it will use the normal Apple login process that might require 2FA authentication.)
248
248
 
249
249
  ## Role for App Store Connect User
250
250
  _pilot_/`upload_to_testflight` updates build information and testers after the build has finished processing. App Store Connect requires the "App Manager" or "Admin" role for your Apple account to update this information. The "Developer" role will allow builds to be uploaded but _will not_ allow updating of build information and testers.
@@ -2,6 +2,7 @@ module Fastlane
2
2
  module Actions
3
3
  module SharedValues
4
4
  DSYM_PATHS = :DSYM_PATHS
5
+ DSYM_LATEST_UPLOADED_DATE = :DSYM_LATEST_UPLOADED_DATE
5
6
  end
6
7
  class DownloadDsymsAction < Action
7
8
  # rubocop:disable Metrics/PerceivedComplexity
@@ -9,6 +10,7 @@ module Fastlane
9
10
  require 'openssl'
10
11
  require 'spaceship'
11
12
  require 'net/http'
13
+ require 'date'
12
14
 
13
15
  # Team selection passed though FASTLANE_ITC_TEAM_ID and FASTLANE_ITC_TEAM_NAME environment variables
14
16
  # Prompts select team if multiple teams and none specified
@@ -30,6 +32,7 @@ module Fastlane
30
32
  wait_for_dsym_processing = params[:wait_for_dsym_processing]
31
33
  wait_timeout = params[:wait_timeout]
32
34
  min_version = Gem::Version.new(params[:min_version]) if params[:min_version]
35
+ after_uploaded_date = DateTime.parse(params[:after_uploaded_date]) unless params[:after_uploaded_date].nil?
33
36
 
34
37
  platform = Spaceship::ConnectAPI::Platform.map(itc_platform)
35
38
 
@@ -81,6 +84,7 @@ module Fastlane
81
84
  builds.each do |build|
82
85
  asc_app_version = build.app_version
83
86
  asc_build_number = build.version
87
+ uploaded_date = DateTime.parse(build.uploaded_date)
84
88
 
85
89
  message = []
86
90
  message << "Found train (version): #{asc_app_version}"
@@ -97,6 +101,11 @@ module Fastlane
97
101
  next
98
102
  end
99
103
 
104
+ if after_uploaded_date && after_uploaded_date >= uploaded_date
105
+ UI.verbose("Upload date #{after_uploaded_date} not reached: #{uploaded_date}")
106
+ next
107
+ end
108
+
100
109
  message = []
101
110
  message << "Found build version: #{asc_build_number}"
102
111
  message << ", comparing to supplied build_number: #{build_number}" if build_number
@@ -108,11 +117,11 @@ module Fastlane
108
117
  end
109
118
 
110
119
  UI.verbose("Build_version: #{asc_build_number} matches #{build_number}, grabbing dsym_url") if build_number
111
- get_details_and_download_dsym(app: app, train: asc_app_version, build_number: asc_build_number, platform: itc_platform, wait_for_dsym_processing: wait_for_dsym_processing, wait_timeout: wait_timeout, output_directory: output_directory)
120
+ get_details_and_download_dsym(app: app, train: asc_app_version, build_number: asc_build_number, uploaded_date: uploaded_date, platform: itc_platform, wait_for_dsym_processing: wait_for_dsym_processing, wait_timeout: wait_timeout, output_directory: output_directory)
112
121
  end
113
122
  end
114
123
 
115
- def self.get_details_and_download_dsym(app: nil, train: nil, build_number: nil, platform: nil, wait_for_dsym_processing: nil, wait_timeout: nil, output_directory: nil)
124
+ def self.get_details_and_download_dsym(app: nil, train: nil, build_number: nil, uploaded_date: nil, platform: nil, wait_for_dsym_processing: nil, wait_timeout: nil, output_directory: nil)
116
125
  start = Time.now
117
126
  download_url = nil
118
127
 
@@ -144,7 +153,7 @@ module Fastlane
144
153
  end
145
154
 
146
155
  if download_url
147
- self.download(download_url, app.bundle_id, train, build_number, output_directory)
156
+ self.download(download_url, app.bundle_id, train, build_number, uploaded_date, output_directory)
148
157
  return if build_number
149
158
  else
150
159
  UI.message("No dSYM URL for #{build_number} (#{train})")
@@ -159,19 +168,26 @@ module Fastlane
159
168
  latest_build = Spaceship::ConnectAPI.get_builds(filter: filter, sort: "-uploadedDate", includes: "preReleaseVersion").first
160
169
 
161
170
  if latest_build.nil?
162
- UI.user_error!("Could not find latest bulid for version #{version}")
171
+ UI.user_error!("Could not find latest build for version #{version}")
163
172
  end
164
173
 
165
174
  return latest_build
166
175
  end
167
176
 
168
- def self.download(download_url, bundle_id, train_number, build_version, output_directory)
177
+ def self.download(download_url, bundle_id, train_number, build_version, uploaded_date, output_directory)
169
178
  result = self.download_file(download_url)
170
179
  path = write_dsym(result, bundle_id, train_number, build_version, output_directory)
171
180
  UI.success("🔑 Successfully downloaded dSYM file for #{train_number} - #{build_version} to '#{path}'")
172
181
 
173
182
  Actions.lane_context[SharedValues::DSYM_PATHS] ||= []
174
183
  Actions.lane_context[SharedValues::DSYM_PATHS] << File.expand_path(path)
184
+
185
+ unless uploaded_date.nil?
186
+ Actions.lane_context[SharedValues::DSYM_LATEST_UPLOADED_DATE] ||= uploaded_date
187
+ current_latest = Actions.lane_context[SharedValues::DSYM_LATEST_UPLOADED_DATE]
188
+ Actions.lane_context[SharedValues::DSYM_LATEST_UPLOADED_DATE] = [current_latest, uploaded_date].max
189
+ UI.verbose("Most recent build uploaded_date #{Actions.lane_context[SharedValues::DSYM_LATEST_UPLOADED_DATE]}")
190
+ end
175
191
  end
176
192
 
177
193
  def self.write_dsym(data, bundle_id, train_number, build_number, output_directory)
@@ -192,6 +208,7 @@ module Fastlane
192
208
  else
193
209
  http = Net::HTTP.new(uri.host, uri.port)
194
210
  end
211
+ http.read_timeout = 300
195
212
  http.use_ssl = (uri.scheme == "https")
196
213
  res = http.get(uri.request_uri)
197
214
  res.body
@@ -286,6 +303,12 @@ module Fastlane
286
303
  env_name: "DOWNLOAD_DSYMS_MIN_VERSION",
287
304
  description: "The minimum app version for dSYMs you wish to download",
288
305
  optional: true),
306
+ FastlaneCore::ConfigItem.new(key: :after_uploaded_date,
307
+ short_option: "-d",
308
+ env_name: "DOWNLOAD_DSYMS_AFTER_UPLOADED_DATE",
309
+ description: "The uploaded date after which you wish to download dSYMs",
310
+ optional: true,
311
+ is_string: true),
289
312
  FastlaneCore::ConfigItem.new(key: :output_directory,
290
313
  short_option: "-s",
291
314
  env_name: "DOWNLOAD_DSYMS_OUTPUT_DIRECTORY",
@@ -310,7 +333,8 @@ module Fastlane
310
333
 
311
334
  def self.output
312
335
  [
313
- ['DSYM_PATHS', 'An array to all the zipped dSYM files']
336
+ ['DSYM_PATHS', 'An array to all the zipped dSYM files'],
337
+ ['DSYM_LATEST_UPLOADED_DATE', 'Date of the most recent uploaded time of successfully downloaded dSYM files']
314
338
  ]
315
339
  end
316
340
 
@@ -332,7 +356,8 @@ module Fastlane
332
356
  'download_dsyms(version: "1.0.0", build_number: "345")',
333
357
  'download_dsyms(version: "1.0.1", build_number: 42)',
334
358
  'download_dsyms(version: "live")',
335
- 'download_dsyms(min_version: "1.2.3")'
359
+ 'download_dsyms(min_version: "1.2.3")',
360
+ 'download_dsyms(after_uploaded_date: "2020-09-11T19:00:00+01:00")'
336
361
  ]
337
362
  end
338
363
 
@@ -7,7 +7,13 @@ module Fastlane
7
7
  # Raises an exception and stop the lane execution if the repo is not in a clean state
8
8
  class EnsureGitStatusCleanAction < Action
9
9
  def self.run(params)
10
- repo_status = Actions.sh("git status --porcelain")
10
+ if params[:ignored]
11
+ ignored_file = params[:ignored]
12
+ repo_status = Actions.sh("git status --porcelain --ignored #{ignored_file}")
13
+ else
14
+ repo_status = Actions.sh("git status --porcelain")
15
+ end
16
+
11
17
  repo_clean = repo_status.empty?
12
18
 
13
19
  if repo_clean
@@ -65,7 +71,12 @@ module Fastlane
65
71
  description: "The flag whether to show the git diff if the repo is dirty",
66
72
  optional: true,
67
73
  default_value: false,
68
- is_string: false)
74
+ is_string: false),
75
+ FastlaneCore::ConfigItem.new(key: :ignored,
76
+ env_name: "FL_ENSURE_GIT_STATUS_CLEAN_IGNORED_FILE",
77
+ description: "The flag whether to ignore file the git status if the repo is dirty",
78
+ optional: true,
79
+ is_string: true)
69
80
  ]
70
81
  end
71
82
 
@@ -13,6 +13,7 @@ module Fastlane
13
13
 
14
14
  begin
15
15
  Cert.config = params # we alread have the finished config
16
+ Cert.config[:api_key] ||= Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
16
17
 
17
18
  Cert::Runner.new.launch
18
19
  cert_file_path = ENV["CER_FILE_PATH"]
@@ -15,6 +15,7 @@ module Fastlane
15
15
  require 'credentials_manager/appfile_config'
16
16
 
17
17
  Sigh.config = values # we already have the finished config
18
+ Sigh.config[:api_key] ||= Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
18
19
 
19
20
  path = Sigh::Manager.start
20
21
 
@@ -37,6 +37,21 @@ module Fastlane
37
37
  user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
38
38
 
39
39
  [
40
+ FastlaneCore::ConfigItem.new(key: :api_key_path,
41
+ env_name: "APPSTORE_BUILD_NUMBER_API_KEY_PATH",
42
+ description: "Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file)",
43
+ optional: true,
44
+ conflicting_options: [:api_key],
45
+ verify_block: proc do |value|
46
+ UI.user_error!("Couldn't find API key JSON file at path '#{value}'") unless File.exist?(value)
47
+ end),
48
+ FastlaneCore::ConfigItem.new(key: :api_key,
49
+ env_name: "APPSTORE_BUILD_NUMBER_API_KEY",
50
+ description: "Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/#use-return-value-and-pass-in-as-an-option)",
51
+ type: Hash,
52
+ optional: true,
53
+ sensitive: true,
54
+ conflicting_options: [:api_key_path]),
40
55
  FastlaneCore::ConfigItem.new(key: :live,
41
56
  short_option: "-l",
42
57
  env_name: "CURRENT_BUILD_NUMBER_LIVE",
@@ -11,23 +11,39 @@ module Fastlane
11
11
  require 'spaceship'
12
12
 
13
13
  name = params[:name]
14
+ platform = params[:platform]
14
15
  udid = params[:udid]
15
16
 
16
- credentials = CredentialsManager::AccountManager.new(user: params[:username])
17
- Spaceship.login(credentials.user, credentials.password)
18
- Spaceship.select_team
17
+ platform = Spaceship::ConnectAPI::BundleIdPlatform.map(platform)
18
+
19
+ if (token = api_token(params))
20
+ UI.message("Using App Store Connect API token...")
21
+ Spaceship::ConnectAPI.token = token
22
+ else
23
+ UI.message("Login to App Store Connect (#{params[:username]})")
24
+ credentials = CredentialsManager::AccountManager.new(user: params[:username])
25
+ Spaceship::ConnectAPI.login(credentials.user, credentials.password, use_portal: true, use_tunes: false)
26
+ UI.message("Login successful")
27
+ end
19
28
 
20
29
  begin
21
- Spaceship::Device.create!(name: name, udid: udid)
30
+ Spaceship::ConnectAPI::Device.create(name: name, platform: platform, udid: udid)
22
31
  rescue => ex
23
32
  UI.error(ex.to_s)
24
- UI.crash!("Failed to register new device (name: #{name}, UDID: #{udid})")
33
+ UI.crash!("Failed to register new device (name: #{name}, platform: #{platform}, UDID: #{udid})")
25
34
  end
26
35
 
27
36
  UI.success("Successfully registered new device")
28
37
  return udid
29
38
  end
30
39
 
40
+ def self.api_token(params)
41
+ params[:api_key] ||= Actions.lane_context[SharedValues::APP_STORE_CONNECT_API_KEY]
42
+ api_token ||= Spaceship::ConnectAPI::Token.create(params[:api_key]) if params[:api_key]
43
+ api_token ||= Spaceship::ConnectAPI::Token.from_json_file(params[:api_key_path]) if params[:api_key_path]
44
+ return api_token
45
+ end
46
+
31
47
  def self.description
32
48
  "Registers a new device to the Apple Dev Portal"
33
49
  end
@@ -35,14 +51,38 @@ module Fastlane
35
51
  def self.available_options
36
52
  user = CredentialsManager::AppfileConfig.try_fetch_value(:apple_dev_portal_id)
37
53
  user ||= CredentialsManager::AppfileConfig.try_fetch_value(:apple_id)
54
+ platform = Actions.lane_context[Actions::SharedValues::PLATFORM_NAME].to_s
38
55
 
39
56
  [
40
57
  FastlaneCore::ConfigItem.new(key: :name,
41
58
  env_name: "FL_REGISTER_DEVICE_NAME",
42
59
  description: "Provide the name of the device to register as"),
60
+ FastlaneCore::ConfigItem.new(key: :platform,
61
+ env_name: "FL_REGISTER_DEVICE_PLATFORM",
62
+ description: "Provide the platform of the device to register as (ios, mac)",
63
+ optional: true,
64
+ default_value: platform.empty? ? "ios" : platform,
65
+ verify_block: proc do |value|
66
+ UI.user_error!("The platform can only be ios or mac") unless %('ios', 'mac').include?(value)
67
+ end),
43
68
  FastlaneCore::ConfigItem.new(key: :udid,
44
69
  env_name: "FL_REGISTER_DEVICE_UDID",
45
70
  description: "Provide the UDID of the device to register as"),
71
+ FastlaneCore::ConfigItem.new(key: :api_key_path,
72
+ env_name: "FL_REGISTER_DEVICE_API_KEY_PATH",
73
+ description: "Path to your App Store Connect API Key JSON file (https://docs.fastlane.tools/app-store-connect-api/#using-fastlane-api-key-json-file)",
74
+ optional: true,
75
+ conflicting_options: [:api_key],
76
+ verify_block: proc do |value|
77
+ UI.user_error!("Couldn't find API key JSON file at path '#{value}'") unless File.exist?(value)
78
+ end),
79
+ FastlaneCore::ConfigItem.new(key: :api_key,
80
+ env_name: "FL_REGISTER_DEVICE_API_KEY",
81
+ description: "Your App Store Connect API Key information (https://docs.fastlane.tools/app-store-connect-api/#use-return-value-and-pass-in-as-an-option)",
82
+ type: Hash,
83
+ optional: true,
84
+ sensitive: true,
85
+ conflicting_options: [:api_key_path]),
46
86
  FastlaneCore::ConfigItem.new(key: :team_id,
47
87
  env_name: "REGISTER_DEVICE_TEAM_ID",
48
88
  code_gen_sensitive: true,
@@ -66,6 +106,7 @@ module Fastlane
66
106
  FastlaneCore::ConfigItem.new(key: :username,
67
107
  env_name: "DELIVER_USER",
68
108
  description: "Optional: Your Apple ID",
109
+ optional: true,
69
110
  default_value: user,
70
111
  default_value_dynamic: true)
71
112
  ]