fastlane 2.213.0 → 2.214.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (36) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +92 -92
  3. data/deliver/lib/deliver/upload_price_tier.rb +1 -1
  4. data/fastlane/lib/assets/custom_action_template.rb +18 -12
  5. data/fastlane/lib/fastlane/actions/docs/sync_code_signing.md +5 -3
  6. data/fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb +124 -0
  7. data/fastlane/lib/fastlane/version.rb +1 -1
  8. data/fastlane/swift/Deliverfile.swift +1 -1
  9. data/fastlane/swift/DeliverfileProtocol.swift +1 -1
  10. data/fastlane/swift/Fastlane.swift +59 -4
  11. data/fastlane/swift/Gymfile.swift +1 -1
  12. data/fastlane/swift/GymfileProtocol.swift +1 -1
  13. data/fastlane/swift/Matchfile.swift +1 -1
  14. data/fastlane/swift/MatchfileProtocol.swift +1 -1
  15. data/fastlane/swift/Precheckfile.swift +1 -1
  16. data/fastlane/swift/PrecheckfileProtocol.swift +1 -1
  17. data/fastlane/swift/Scanfile.swift +1 -1
  18. data/fastlane/swift/ScanfileProtocol.swift +1 -1
  19. data/fastlane/swift/Screengrabfile.swift +1 -1
  20. data/fastlane/swift/ScreengrabfileProtocol.swift +1 -1
  21. data/fastlane/swift/Snapshotfile.swift +1 -1
  22. data/fastlane/swift/SnapshotfileProtocol.swift +1 -1
  23. data/fastlane/swift/formatting/Brewfile.lock.json +18 -18
  24. data/gym/lib/gym/generators/build_command_generator.rb +1 -1
  25. data/match/lib/match/storage/gitlab/client.rb +40 -14
  26. data/match/lib/match/storage/gitlab_secure_files.rb +7 -2
  27. data/scan/lib/scan/test_command_generator.rb +1 -1
  28. data/snapshot/lib/snapshot/test_command_generator.rb +1 -1
  29. data/spaceship/lib/spaceship/client.rb +0 -1
  30. data/spaceship/lib/spaceship/connect_api/models/user.rb +38 -0
  31. data/spaceship/lib/spaceship/connect_api/models/user_invitation.rb +5 -15
  32. data/spaceship/lib/spaceship/connect_api/users/users.rb +34 -0
  33. data/supply/lib/supply/client.rb +33 -0
  34. data/supply/lib/supply/generated_universal_apk.rb +24 -0
  35. data/supply/lib/supply.rb +1 -0
  36. metadata +22 -20
@@ -208,4 +208,4 @@ public extension GymfileProtocol {
208
208
 
209
209
  // Please don't remove the lines below
210
210
  // They are used to detect outdated files
211
- // FastlaneRunnerAPIVersion [0.9.119]
211
+ // FastlaneRunnerAPIVersion [0.9.120]
@@ -17,4 +17,4 @@ public class Matchfile: MatchfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.213.0
20
+ // Generated with fastlane 2.214.0
@@ -212,4 +212,4 @@ public extension MatchfileProtocol {
212
212
 
213
213
  // Please don't remove the lines below
214
214
  // They are used to detect outdated files
215
- // FastlaneRunnerAPIVersion [0.9.113]
215
+ // FastlaneRunnerAPIVersion [0.9.114]
@@ -17,4 +17,4 @@ public class Precheckfile: PrecheckfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.213.0
20
+ // Generated with fastlane 2.214.0
@@ -52,4 +52,4 @@ public extension PrecheckfileProtocol {
52
52
 
53
53
  // Please don't remove the lines below
54
54
  // They are used to detect outdated files
55
- // FastlaneRunnerAPIVersion [0.9.112]
55
+ // FastlaneRunnerAPIVersion [0.9.113]
@@ -17,4 +17,4 @@ public class Scanfile: ScanfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.213.0
20
+ // Generated with fastlane 2.214.0
@@ -320,4 +320,4 @@ public extension ScanfileProtocol {
320
320
 
321
321
  // Please don't remove the lines below
322
322
  // They are used to detect outdated files
323
- // FastlaneRunnerAPIVersion [0.9.124]
323
+ // FastlaneRunnerAPIVersion [0.9.125]
@@ -17,4 +17,4 @@ public class Screengrabfile: ScreengrabfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.213.0
20
+ // Generated with fastlane 2.214.0
@@ -96,4 +96,4 @@ public extension ScreengrabfileProtocol {
96
96
 
97
97
  // Please don't remove the lines below
98
98
  // They are used to detect outdated files
99
- // FastlaneRunnerAPIVersion [0.9.114]
99
+ // FastlaneRunnerAPIVersion [0.9.115]
@@ -17,4 +17,4 @@ public class Snapshotfile: SnapshotfileProtocol {
17
17
  // during the `init` process, and you won't see this message
18
18
  }
19
19
 
20
- // Generated with fastlane 2.213.0
20
+ // Generated with fastlane 2.214.0
@@ -204,4 +204,4 @@ public extension SnapshotfileProtocol {
204
204
 
205
205
  // Please don't remove the lines below
206
206
  // They are used to detect outdated files
207
- // FastlaneRunnerAPIVersion [0.9.108]
207
+ // FastlaneRunnerAPIVersion [0.9.109]
@@ -2,45 +2,45 @@
2
2
  "entries": {
3
3
  "brew": {
4
4
  "swiftformat": {
5
- "version": "0.51.9",
5
+ "version": "0.51.12",
6
6
  "bottle": {
7
7
  "rebuild": 0,
8
8
  "root_url": "https://ghcr.io/v2/homebrew/core",
9
9
  "files": {
10
10
  "arm64_ventura": {
11
11
  "cellar": ":any_skip_relocation",
12
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:bbb01c5c7fcde4f8b17945c2c8386b099848c9cd4fda8bcfd032c2420d5d1b65",
13
- "sha256": "bbb01c5c7fcde4f8b17945c2c8386b099848c9cd4fda8bcfd032c2420d5d1b65"
12
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:272dadfe917e9296713f7d41739d315679d77485bcedf9f5f5700523947a9635",
13
+ "sha256": "272dadfe917e9296713f7d41739d315679d77485bcedf9f5f5700523947a9635"
14
14
  },
15
15
  "arm64_monterey": {
16
16
  "cellar": ":any_skip_relocation",
17
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:f04596d4567e86f46e0740ea3e9d1e2e19fa1cdf137a70287342b6ce937ddf8d",
18
- "sha256": "f04596d4567e86f46e0740ea3e9d1e2e19fa1cdf137a70287342b6ce937ddf8d"
17
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:fe6ace3786c1e3461c2d7e649e86fecf692e816ef143b1602daaf8ccca674426",
18
+ "sha256": "fe6ace3786c1e3461c2d7e649e86fecf692e816ef143b1602daaf8ccca674426"
19
19
  },
20
20
  "arm64_big_sur": {
21
21
  "cellar": ":any_skip_relocation",
22
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:d8b6f0f30662dd4c2e1eb64d614fe2765ad664e2ac10a346004f94ed6ed6cdf2",
23
- "sha256": "d8b6f0f30662dd4c2e1eb64d614fe2765ad664e2ac10a346004f94ed6ed6cdf2"
22
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:e8c39e62f11cead0543225c79a1e3f461f4a3de7595332a2068cf465bd5cb522",
23
+ "sha256": "e8c39e62f11cead0543225c79a1e3f461f4a3de7595332a2068cf465bd5cb522"
24
24
  },
25
25
  "ventura": {
26
26
  "cellar": ":any_skip_relocation",
27
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:dc2be8c829dc26595577f8b5daa071324f341c4f144cc46bf0a47520d44fc76e",
28
- "sha256": "dc2be8c829dc26595577f8b5daa071324f341c4f144cc46bf0a47520d44fc76e"
27
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:c39102257e34cc3fff2fec1f439b7d62bc5c4404c3d82d58e0b94db325aae3e2",
28
+ "sha256": "c39102257e34cc3fff2fec1f439b7d62bc5c4404c3d82d58e0b94db325aae3e2"
29
29
  },
30
30
  "monterey": {
31
31
  "cellar": ":any_skip_relocation",
32
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:a88b992a2316fa06dd13944c6bb16d00522de0cc21aae17ede07e65d700c6800",
33
- "sha256": "a88b992a2316fa06dd13944c6bb16d00522de0cc21aae17ede07e65d700c6800"
32
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:19ce480a2e73c5bbed64e9b0822d99b9d705d53afc29501265933798bd571dcf",
33
+ "sha256": "19ce480a2e73c5bbed64e9b0822d99b9d705d53afc29501265933798bd571dcf"
34
34
  },
35
35
  "big_sur": {
36
36
  "cellar": ":any_skip_relocation",
37
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:ba2cf56b5845bb33265a3e32737c5defa6e310987f785e1dfe6e7dc114a12555",
38
- "sha256": "ba2cf56b5845bb33265a3e32737c5defa6e310987f785e1dfe6e7dc114a12555"
37
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:653f90a848b51b79c19ec387ff1f76d892c00a4cb8824a4618793a9bc33b9b3a",
38
+ "sha256": "653f90a848b51b79c19ec387ff1f76d892c00a4cb8824a4618793a9bc33b9b3a"
39
39
  },
40
40
  "x86_64_linux": {
41
41
  "cellar": "/home/linuxbrew/.linuxbrew/Cellar",
42
- "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:d1f82ed96ee9f8f239e9396bff00a0feac937fe12840d05fb6d5c01fe9161f03",
43
- "sha256": "d1f82ed96ee9f8f239e9396bff00a0feac937fe12840d05fb6d5c01fe9161f03"
42
+ "url": "https://ghcr.io/v2/homebrew/core/swiftformat/blobs/sha256:e3ef2e5695bfdcda2b072211f3071e9c06056e18e3a95a3d60d3d502aa4e8c27",
43
+ "sha256": "e3ef2e5695bfdcda2b072211f3071e9c06056e18e3a95a3d60d3d502aa4e8c27"
44
44
  }
45
45
  }
46
46
  }
@@ -74,12 +74,12 @@
74
74
  "macOS": "12.5"
75
75
  },
76
76
  "ventura": {
77
- "HOMEBREW_VERSION": "4.0.18-59-gf7b3225",
77
+ "HOMEBREW_VERSION": "4.0.28-67-ge9ac36a",
78
78
  "HOMEBREW_PREFIX": "/opt/homebrew",
79
79
  "Homebrew/homebrew-core": "api",
80
80
  "CLT": "",
81
- "Xcode": "14.1",
82
- "macOS": "13.2.1"
81
+ "Xcode": "14.3",
82
+ "macOS": "13.4"
83
83
  }
84
84
  }
85
85
  }
@@ -80,7 +80,7 @@ module Gym
80
80
  if Gym.config[:disable_xcpretty] || formatter == ''
81
81
  UI.verbose("Not using an xcodebuild formatter")
82
82
  elsif !options.empty?
83
- UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
83
+ UI.important("Detected legacy xcpretty being used, so formatting with xcpretty")
84
84
  UI.important("Option(s) used: #{options.join(', ')}")
85
85
  pipe += pipe_xcpretty
86
86
  elsif formatter == 'xcpretty'
@@ -40,6 +40,8 @@ module Match
40
40
  def files
41
41
  @files ||= begin
42
42
  url = URI.parse(base_url)
43
+ # 100 is maximum number of Secure files available on Gitlab https://docs.gitlab.com/ee/api/secure_files.html
44
+ url.query = [url.query, "per_page=100"].compact.join('&')
43
45
 
44
46
  request = Net::HTTP::Get.new(url.request_uri)
45
47
 
@@ -69,32 +71,56 @@ module Match
69
71
  "name" => target_file
70
72
  )
71
73
 
72
- response = execute_request(url, request)
74
+ execute_request(url, request, target_file)
75
+ end
76
+ end
77
+
78
+ def execute_request(url, request, target_file = nil)
79
+ request[authentication_key] = authentication_value
80
+
81
+ http = Net::HTTP.new(url.host, url.port)
82
+ http.use_ssl = url.instance_of?(URI::HTTPS)
83
+
84
+ begin
85
+ response = http.request(request)
86
+ rescue Errno::ECONNREFUSED, SocketError => message
87
+ UI.user_error!("GitLab connection error: #{message}")
88
+ end
73
89
 
74
- log_upload_error(response, target_file) if response.code != "201"
90
+ unless response.kind_of?(Net::HTTPSuccess)
91
+ handle_response_error(response, target_file)
75
92
  end
93
+
94
+ response
76
95
  end
77
96
 
78
- def log_upload_error(response, target_file)
97
+ def handle_response_error(response, target_file = nil)
98
+ error_prefix = "GitLab storage error:"
99
+ file_debug_string = "File: #{target_file}" unless target_file.nil?
100
+ api_debug_string = "API: #{@api_v4_url}"
101
+ debug_info = "(#{[file_debug_string, api_debug_string].compact.join(', ')})"
102
+
79
103
  begin
80
- response_body = JSON.parse(response.body)
104
+ parsed = JSON.parse(response.body)
81
105
  rescue JSON::ParserError
82
- response_body = response.body
83
106
  end
84
107
 
85
- if response_body["message"] && (response_body["message"]["name"] == ["has already been taken"])
86
- UI.error("#{target_file} already exists in GitLab project #{@project_id}, file not uploaded")
108
+ if parsed && parsed["message"] && (parsed["message"]["name"] == ["has already been taken"])
109
+ error_handler = :error
110
+ error = "#{target_file} already exists in GitLab project #{@project_id}, file not uploaded"
87
111
  else
88
- UI.error("Upload error for #{target_file}: #{response_body}")
112
+ error_handler = :user_error!
113
+ error = "#{response.code}: #{response.body}"
89
114
  end
90
- end
115
+ error_message = [error_prefix, error, debug_info].join(' ')
91
116
 
92
- def execute_request(url, request)
93
- request[authentication_key] = authentication_value
117
+ UI.send(error_handler, error_message)
118
+ end
94
119
 
95
- http = Net::HTTP.new(url.host, url.port)
96
- http.use_ssl = url.instance_of?(URI::HTTPS)
97
- http.request(request)
120
+ def prompt_for_access_token
121
+ unless authentication_key
122
+ @private_token = UI.input("Please supply a GitLab personal or project access token: ")
123
+ end
98
124
  end
99
125
  end
100
126
  end
@@ -47,7 +47,8 @@ module Match
47
47
  team_id: params[:team_id],
48
48
  team_name: params[:team_name],
49
49
  api_key_path: params[:api_key_path],
50
- api_key: params[:api_key]
50
+ api_key: params[:api_key],
51
+ gitlab_host: params[:gitlab_host]
51
52
  )
52
53
  end
53
54
 
@@ -60,7 +61,8 @@ module Match
60
61
  team_id: nil,
61
62
  team_name: nil,
62
63
  api_key_path: nil,
63
- api_key: nil)
64
+ api_key: nil,
65
+ gitlab_host: nil)
64
66
 
65
67
  @readonly = readonly
66
68
  @username = username
@@ -68,6 +70,7 @@ module Match
68
70
  @team_name = team_name
69
71
  @api_key_path = api_key_path
70
72
  @api_key = api_key
73
+ @gitlab_host = gitlab_host
71
74
 
72
75
  @job_token = job_token
73
76
  @private_token = private_token
@@ -95,6 +98,8 @@ module Match
95
98
  end
96
99
 
97
100
  def download
101
+ gitlab_client.prompt_for_access_token
102
+
98
103
  # Check if we already have a functional working_directory
99
104
  return if @working_directory
100
105
 
@@ -132,7 +132,7 @@ module Scan
132
132
  if formatter == ''
133
133
  UI.verbose("Not using an xcodebuild formatter")
134
134
  elsif !options.empty?
135
- UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
135
+ UI.important("Detected legacy xcpretty being used, so formatting with xcpretty")
136
136
  UI.important("Option(s) used: #{options.join(', ')}")
137
137
  pipe << pipe_xcpretty
138
138
  elsif formatter == 'xcpretty'
@@ -34,7 +34,7 @@ module Snapshot
34
34
  if Snapshot.config[:disable_xcpretty] || formatter == ''
35
35
  UI.verbose("Not using an xcodebuild formatter")
36
36
  elsif !options.empty?
37
- UI.important("Detected legacy xcpretty being used so formatting wth xcpretty")
37
+ UI.important("Detected legacy xcpretty being used, so formatting with xcpretty")
38
38
  UI.important("Option(s) used: #{options.join(', ')}")
39
39
  pipe += pipe_xcpretty
40
40
  elsif formatter == 'xcpretty'
@@ -533,7 +533,6 @@ module Spaceship
533
533
 
534
534
  if try_upgrade_2fa_later(response)
535
535
  store_cookie
536
- fetch_olympus_session
537
536
  return true
538
537
  end
539
538
 
@@ -42,6 +42,20 @@ module Spaceship
42
42
  return "users"
43
43
  end
44
44
 
45
+ module UserRole
46
+ ADMIN = "ADMIN"
47
+ FINANCE = "FINANCE"
48
+ TECHNICAL = "TECHNICAL"
49
+ SALES = "SALES"
50
+ MARKETING = "MARKETING"
51
+ DEVELOPER = "DEVELOPER"
52
+ ACCOUNT_HOLDER = "ACCOUNT_HOLDER"
53
+ READ_ONLY = "READ_ONLY"
54
+ APP_MANAGER = "APP_MANAGER"
55
+ ACCESS_TO_REPORTS = "ACCESS_TO_REPORTS"
56
+ CUSTOMER_SUPPORT = "CUSTOMER_SUPPORT"
57
+ end
58
+
45
59
  #
46
60
  # API
47
61
  #
@@ -57,6 +71,30 @@ module Spaceship
57
71
  return all(client: client, filter: { email: email }, includes: includes)
58
72
  end
59
73
 
74
+ # @param client [ConnectAPI] ConnectAPI client.
75
+ # @param all_apps_visible [Boolean] If all apps must be visible to a user. true - if a user must see all apps, you must not provide visible_app_ids, `false` - a user must see only a limited list of apps, and you must provide visible_app_ids. nil if no change is needed.
76
+ # @param provisioning_allowed [Bool] If a user with a Developer or App Manager role must have access to Certificates, Identifiers & Profiles. true - if a user must be able to create new certificates and provisioning profiles, `false` - otherwise. nil if no change is needed.
77
+ # @param roles [Array] Array of strings describing user roles. You can use defined constants in the UserRole, or refer to the Apple Documentation https://developer.apple.com/documentation/appstoreconnectapi/userrole . Pass nil if no change is needed.
78
+ # @param visible_app_ids [Array] Array of strings with application identifiers the user needs access to. nil if no apps change is needed or user must have access to all apps.
79
+ # @return (User) Modified user.
80
+ def update(client: nil, all_apps_visible: nil, provisioning_allowed: nil, roles: nil, visible_app_ids: nil)
81
+ client ||= Spaceship::ConnectAPI
82
+
83
+ all_apps_visible = all_apps_visible.nil? ? self.all_apps_visible : all_apps_visible
84
+ provisioning_allowed = provisioning_allowed.nil? ? self.provisioning_allowed : provisioning_allowed
85
+ roles ||= self.roles
86
+ visible_app_ids ||= self.visible_apps.map(&:id)
87
+
88
+ resp = client.patch_user(
89
+ user_id: self.id,
90
+ all_apps_visible: all_apps_visible,
91
+ provisioning_allowed: provisioning_allowed,
92
+ roles: roles,
93
+ visible_app_ids: visible_app_ids
94
+ )
95
+ return resp.to_models.first
96
+ end
97
+
60
98
  def delete!(client: nil)
61
99
  client ||= Spaceship::ConnectAPI
62
100
  client.delete_user(user_id: id)
@@ -1,4 +1,6 @@
1
1
  require_relative '../model'
2
+ require_relative 'user'
3
+
2
4
  module Spaceship
3
5
  class ConnectAPI
4
6
  class UserInvitation
@@ -28,19 +30,7 @@ module Spaceship
28
30
  "visibleApps"
29
31
  ].join(",")
30
32
 
31
- module UserRole
32
- ADMIN = "ADMIN"
33
- FINANCE = "FINANCE"
34
- TECHNICAL = "TECHNICAL"
35
- SALES = "SALES"
36
- MARKETING = "MARKETING"
37
- DEVELOPER = "DEVELOPER"
38
- ACCOUNT_HOLDER = "ACCOUNT_HOLDER"
39
- READ_ONLY = "READ_ONLY"
40
- APP_MANAGER = "APP_MANAGER"
41
- ACCESS_TO_REPORTS = "ACCESS_TO_REPORTS"
42
- CUSTOMER_SUPPORT = "CUSTOMER_SUPPORT"
43
- end
33
+ UserRole = Spaceship::ConnectAPI::User::UserRole
44
34
 
45
35
  def self.type
46
36
  return "userInvitations"
@@ -64,8 +54,8 @@ module Spaceship
64
54
  # Create and post user invitation
65
55
  # App Store Connect allows for the following combinations of `all_apps_visible` and `visible_app_ids`:
66
56
  # - if `all_apps_visible` is `nil`, you don't have to provide values for `visible_app_ids`
67
- # - if `all_apps_visible` is true, you must provide values for `visible_app_ids`.
68
- # - if `all_apps_visible` is false, you must not provide values for `visible_app_ids`.
57
+ # - if `all_apps_visible` is false, you must provide values for `visible_app_ids`.
58
+ # - if `all_apps_visible` is true, you must not provide values for `visible_app_ids`.
69
59
  def self.create(client: nil, email: nil, first_name: nil, last_name: nil, roles: [], provisioning_allowed: nil, all_apps_visible: nil, visible_app_ids: [])
70
60
  client ||= Spaceship::ConnectAPI
71
61
  resp = client.post_user_invitation(
@@ -28,6 +28,36 @@ module Spaceship
28
28
  users_request_client.delete("users/#{user_id}")
29
29
  end
30
30
 
31
+ # Update existing user
32
+ def patch_user(user_id:, all_apps_visible:, provisioning_allowed:, roles:, visible_app_ids:)
33
+ body = {
34
+ data: {
35
+ type: 'users',
36
+ id: user_id,
37
+ attributes: {
38
+ allAppsVisible: all_apps_visible,
39
+ provisioningAllowed: provisioning_allowed,
40
+ roles: roles
41
+ },
42
+ relationships: {
43
+ visibleApps: {
44
+ data: visible_app_ids.map do |app_id|
45
+ {
46
+ type: "apps",
47
+ id: app_id
48
+ }
49
+ end
50
+ }
51
+ }
52
+ }
53
+ }
54
+
55
+ # Avoid API error: You cannot set visible apps for this user because the user's roles give them access to all apps.
56
+ body[:data].delete(:relationships) if all_apps_visible
57
+
58
+ users_request_client.patch("users/#{user_id}", body)
59
+ end
60
+
31
61
  # Add app permissions for user
32
62
  # @deprecated Use {#post_user_visible_apps} instead.
33
63
  def add_user_visible_apps(user_id: nil, app_ids: nil)
@@ -116,6 +146,10 @@ module Spaceship
116
146
  }
117
147
  }
118
148
  }
149
+
150
+ # Avoid API error: You cannot set visible apps for this user because the user's roles give them access to all apps.
151
+ body[:data].delete(:relationships) if all_apps_visible
152
+
119
153
  users_request_client.post("userInvitations", body)
120
154
  end
121
155
 
@@ -305,6 +305,39 @@ module Supply
305
305
  return latest_version
306
306
  end
307
307
 
308
+ # Get the list of Universal APKs generated by Google from the AAB for a particular version code
309
+ #
310
+ # @param [Fixnum] version_code
311
+ # Version code of the app bundle.
312
+ # @raise [FastlaneError] (Google Api Error) If no APK was found for the provided `package_name` and `version_code`
313
+ # @return [Array<GeneratedUniversalApk>]
314
+ #
315
+ def list_generated_universal_apks(package_name:, version_code:)
316
+ result = call_google_api { client.list_generatedapks(package_name, version_code) }
317
+
318
+ result.generated_apks.map do |row|
319
+ GeneratedUniversalApk.new(package_name, version_code, row.certificate_sha256_hash, row.generated_universal_apk.download_id)
320
+ end
321
+ end
322
+
323
+ # Download a Universal APK generated by Google for a particular version code
324
+ #
325
+ # @param [Supply::GeneratedUniversalApk] generated_universal_apk
326
+ # The GeneratedUniversalApk object retrieved from a call to `list_generated_univeral_apks`
327
+ # @param [IO, String] destination
328
+ # IO stream or filename to receive content download
329
+ #
330
+ def download_generated_universal_apk(generated_universal_apk:, destination:)
331
+ call_google_api {
332
+ client.download_generatedapk(
333
+ generated_universal_apk.package_name,
334
+ generated_universal_apk.version_code,
335
+ generated_universal_apk.download_id,
336
+ download_dest: destination
337
+ )
338
+ }
339
+ end
340
+
308
341
  #####################################################
309
342
  # @!group Modifying data
310
343
  #####################################################
@@ -0,0 +1,24 @@
1
+ module Supply
2
+ # A model representing the returned values from a call to Client#list_generated_universal_apks
3
+ class GeneratedUniversalApk
4
+ attr_accessor :package_name
5
+ attr_accessor :version_code
6
+ attr_accessor :certificate_sha256_hash
7
+ attr_accessor :download_id
8
+
9
+ # Initializes the Generated Universal APK model
10
+ def initialize(package_name, version_code, certificate_sha256_hash, download_id)
11
+ self.package_name = package_name
12
+ self.version_code = version_code
13
+ self.certificate_sha256_hash = certificate_sha256_hash
14
+ self.download_id = download_id
15
+ end
16
+
17
+ def ==(other)
18
+ self.package_name == other.package_name \
19
+ && self.version_code == other.version_code \
20
+ && self.certificate_sha256_hash == other.certificate_sha256_hash \
21
+ && self.download_id == other.download_id
22
+ end
23
+ end
24
+ end
data/supply/lib/supply.rb CHANGED
@@ -3,6 +3,7 @@ require 'supply/options'
3
3
  require 'supply/client'
4
4
  require 'supply/listing'
5
5
  require 'supply/apk_listing'
6
+ require 'supply/generated_universal_apk'
6
7
  require 'supply/release_listing'
7
8
  require 'supply/uploader'
8
9
  require 'supply/languages'
metadata CHANGED
@@ -1,39 +1,39 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.213.0
4
+ version: 2.214.0
5
5
  platform: ruby
6
6
  authors:
7
- - Danielle Tomlinson
7
+ - Iulian Onofrei
8
8
  - Josh Holtz
9
- - Olivier Halligon
10
- - Satoshi Namai
11
- - Helmut Januschka
12
- - Max Ott
13
- - Felix Krause
14
- - Daniel Jankowski
15
- - Joshua Liebowitz
16
9
  - Fumiya Nakamura
17
- - Aaron Brager
10
+ - Olivier Halligon
11
+ - Maksym Grebenets
18
12
  - Kohki Miki
19
- - Luka Mirosevic
13
+ - Jimmy Dee
14
+ - Jan Piotrowski
15
+ - Andrew McBurney
16
+ - Aaron Brager
17
+ - Helmut Januschka
20
18
  - Matthew Ellis
21
- - Roger Oba
19
+ - Luka Mirosevic
20
+ - Max Ott
22
21
  - Stefan Natchev
23
- - Iulian Onofrei
24
- - Maksym Grebenets
25
- - Jan Piotrowski
26
22
  - Jérôme Lacoste
27
- - Manish Rathi
23
+ - Felix Krause
24
+ - Jorge Revuelta H
25
+ - Joshua Liebowitz
28
26
  - Łukasz Grabowski
27
+ - Satoshi Namai
28
+ - Daniel Jankowski
29
29
  - Manu Wallner
30
- - Andrew McBurney
31
- - Jimmy Dee
32
- - Jorge Revuelta H
30
+ - Danielle Tomlinson
31
+ - Roger Oba
32
+ - Manish Rathi
33
33
  autorequire:
34
34
  bindir: bin
35
35
  cert_chain: []
36
- date: 2023-05-24 00:00:00.000000000 Z
36
+ date: 2023-07-14 00:00:00.000000000 Z
37
37
  dependencies:
38
38
  - !ruby/object:Gem::Dependency
39
39
  name: xcodeproj
@@ -1094,6 +1094,7 @@ files:
1094
1094
  - fastlane/lib/fastlane/actions/download_app_privacy_details_from_app_store.rb
1095
1095
  - fastlane/lib/fastlane/actions/download_dsyms.rb
1096
1096
  - fastlane/lib/fastlane/actions/download_from_play_store.rb
1097
+ - fastlane/lib/fastlane/actions/download_universal_apk_from_google_play.rb
1097
1098
  - fastlane/lib/fastlane/actions/dsym_zip.rb
1098
1099
  - fastlane/lib/fastlane/actions/echo.rb
1099
1100
  - fastlane/lib/fastlane/actions/ensure_bundle_exec.rb
@@ -1850,6 +1851,7 @@ files:
1850
1851
  - supply/lib/supply/apk_listing.rb
1851
1852
  - supply/lib/supply/client.rb
1852
1853
  - supply/lib/supply/commands_generator.rb
1854
+ - supply/lib/supply/generated_universal_apk.rb
1853
1855
  - supply/lib/supply/languages.rb
1854
1856
  - supply/lib/supply/listing.rb
1855
1857
  - supply/lib/supply/options.rb