fastlane-plugin-appcenter 1.7.0 → 1.11.0
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 +5 -5
- data/README.md +30 -6
- data/lib/fastlane/plugin/appcenter/actions/appcenter_fetch_version_number.rb +103 -0
- data/lib/fastlane/plugin/appcenter/actions/appcenter_upload_action.rb +119 -21
- data/lib/fastlane/plugin/appcenter/helper/appcenter_helper.rb +400 -91
- data/lib/fastlane/plugin/appcenter/version.rb +1 -1
- metadata +23 -9
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 1c1262b958ae0ddbf9a6bfa6d63b4f032f1518c706154e6c70b35adbe2c441e2
|
4
|
+
data.tar.gz: c2ffa81d7a6e4c8fb369c5d4612a0aea7c02c2cd589a3fdcb900d8b407f2eaae
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eb06867a95f13d484796bd47be5cad11df03e949ffffbcbf8cbe14d675c8577506e184176248ba8102fc338ab934e9d03e06938030591d9d9a72beec557f7894
|
7
|
+
data.tar.gz: b1fadb157505f3138621dffd8e95a64d306f89439ab25259c60c6a9e08d9a9dbe97d0b09b4c1daf8db70e2c9241d87225523784cb3f9c5e900c98d3a85b0b05f
|
data/README.md
CHANGED
@@ -21,6 +21,8 @@ With [App Center](https://appcenter.ms) you can continuously build, test, releas
|
|
21
21
|
|
22
22
|
`appcenter_upload` allows you to upload and [distribute](https://docs.microsoft.com/en-us/appcenter/distribution/uploading) apps to your testers on App Center as well as to upload .dSYM files to [collect detailed crash reports](https://docs.microsoft.com/en-us/appcenter/crashes/ios) in App Center.
|
23
23
|
|
24
|
+
`appcenter_fetch_version_number` allows you to obtain the latest version number (short or full) for an app. This is useful for tasks such as getting the latest version of an app so that an increment action can take place on CI, or checking that an upload has been successful.
|
25
|
+
|
24
26
|
## Usage
|
25
27
|
|
26
28
|
To get started, first, [obtain an API token](https://appcenter.ms/settings/apitokens) in App Center. The API Token is used to authenticate with the App Center API in each call.
|
@@ -29,7 +31,6 @@ To get started, first, [obtain an API token](https://appcenter.ms/settings/apito
|
|
29
31
|
appcenter_fetch_devices(
|
30
32
|
api_token: "<appcenter token>",
|
31
33
|
owner_name: "<appcenter account name of the owner of the app (username or organization URL name)>",
|
32
|
-
owner_type: "user", # Default is user - set to organization for appcenter organizations
|
33
34
|
app_name: "<appcenter app name>",
|
34
35
|
destinations: "*", # Default is 'Collaborators', use '*' for all distribution groups
|
35
36
|
devices_file: "devices.txt" # Default. If you customize, the extension must be .txt
|
@@ -47,6 +48,21 @@ appcenter_upload(
|
|
47
48
|
)
|
48
49
|
```
|
49
50
|
|
51
|
+
```ruby
|
52
|
+
appcenter_fetch_version_number(
|
53
|
+
api_token: "<appcenter token>",
|
54
|
+
owner_name: "<appcenter account name of the owner of the app (username or organization URL name)>",
|
55
|
+
app_name: "<appcenter app name (as seen in app URL)>",
|
56
|
+
version: "a specific version to get the last release for" # optional, don't set this value to get the last upload of all versions
|
57
|
+
)
|
58
|
+
```
|
59
|
+
|
60
|
+
The `appcenter_fetch_version_number` returns a hash that contains the id, the version number, and the build number. The version corresponds to the `short_version` and the build number to the `version` known by App Center for a given release:
|
61
|
+
```ruby
|
62
|
+
{"id"=>1, "version"=>"1.0.0", "build_number"=>"1.0.0.1234"} # iOS apps contain the full version plus build number due to the way that Apple use CFBundleVersion for this value
|
63
|
+
{"id"=>588, "version"=>"1.2.0", "build_number"=>"1615"}
|
64
|
+
```
|
65
|
+
|
50
66
|
### Help
|
51
67
|
|
52
68
|
Once installed, information and help for an action can be printed out with this command:
|
@@ -74,7 +90,6 @@ Here is the list of all existing parameters:
|
|
74
90
|
| Key & Env Var | Description |
|
75
91
|
|-----------------|--------------------|
|
76
92
|
| `api_token` <br/> `APPCENTER_API_TOKEN` | API Token for App Center |
|
77
|
-
| `owner_type` <br/> `APPCENTER_OWNER_TYPE` | Owner type, either 'user' or 'organization' (default: `user`) |
|
78
93
|
| `owner_name` <br/> `APPCENTER_OWNER_NAME` | Owner name, as found in the App's URL in App Center |
|
79
94
|
| `destinations` <br/> `APPCENTER_DISTRIBUTE_DESTINATIONS` | Comma separated list of distribution group names. Default is 'Collaborators', use '*' for all distribution groups |
|
80
95
|
| `devices_file` <br/> `FL_REGISTER_DEVICES_FILE` | File to save the devices list to. Same environment variable as _fastlane_'s `register_devices` action |
|
@@ -88,7 +103,7 @@ Here is the list of all existing parameters:
|
|
88
103
|
| `owner_name` <br/> `APPCENTER_OWNER_NAME` | Owner name as found in the App's URL in App Center |
|
89
104
|
| `app_name` <br/> `APPCENTER_APP_NAME` | App name as found in the App's URL in App Center. If there is no app with such name, you will be prompted to create one |
|
90
105
|
| `app_display_name` <br/> `APPCENTER_APP_DISPLAY_NAME` | App display name to use when creating a new app |
|
91
|
-
| `app_os` <br/> `APPCENTER_APP_OS` | App OS. Used for new app creation, if app 'app_name' was not found |
|
106
|
+
| `app_os` <br/> `APPCENTER_APP_OS` | App OS can be Android, iOS, macOS, Windows, Custom. Used for new app creation, if app 'app_name' was not found |
|
92
107
|
| `app_platform` <br/> `APPCENTER_APP_PLATFORM` | App Platform. Used for new app creation, if app 'app_name' was not found |
|
93
108
|
| `file` <br/> `APPCENTER_DISTRIBUTE_FILE` | File path to the release build to publish |
|
94
109
|
| `upload_build_only` <br/> `APPCENTER_DISTRIBUTE_UPLOAD_BUILD_ONLY` | Flag to upload only the build to App Center. Skips uploading symbols or mapping (default: `false`) |
|
@@ -96,7 +111,7 @@ Here is the list of all existing parameters:
|
|
96
111
|
| `upload_dsym_only` <br/> `APPCENTER_DISTRIBUTE_UPLOAD_DSYM_ONLY` | Flag to upload only the dSYM file to App Center (default: `false`) |
|
97
112
|
| `mapping` <br/> `APPCENTER_DISTRIBUTE_ANDROID_MAPPING` | Path to your Android mapping.txt |
|
98
113
|
| `upload_mapping_only` <br/> `APPCENTER_DISTRIBUTE_UPLOAD_ANDROID_MAPPING_ONLY` | Flag to upload only the mapping.txt file to App Center (default: `false`) |
|
99
|
-
| `destinations` <br/> `APPCENTER_DISTRIBUTE_DESTINATIONS` | Comma separated list of destination names. Both distribution groups and stores are supported. All names are required to be of the same destination type (default: `Collaborators`) |
|
114
|
+
| `destinations` <br/> `APPCENTER_DISTRIBUTE_DESTINATIONS` | Comma separated list of destination names, use '*' for all distribution groups if destination type is 'group'. Both distribution groups and stores are supported. All names are required to be of the same destination type (default: `Collaborators`) |
|
100
115
|
| `destination_type` <br/> `APPCENTER_DISTRIBUTE_DESTINATION_TYPE` | Destination type of distribution destination. 'group' and 'store' are supported (default: `group`) |
|
101
116
|
| `mandatory_update` <br/> `APPCENTER_DISTRIBUTE_MANDATORY_UPDATE` | Require users to update to this release. Ignored if destination type is 'store' (default: `false`) |
|
102
117
|
| `notify_testers` <br/> `APPCENTER_DISTRIBUTE_NOTIFY_TESTERS` | Send email notification about release. Ignored if destination type is 'store' (default: `false`) |
|
@@ -105,10 +120,19 @@ Here is the list of all existing parameters:
|
|
105
120
|
| `release_notes_link` <br/> `APPCENTER_DISTRIBUTE_RELEASE_NOTES_LINK` | Additional release notes link |
|
106
121
|
| `build_number` <br/> `APPCENTER_DISTRIBUTE_BUILD_NUMBER` | The build number, required for macOS .pkg and .dmg builds, as well as Android ProGuard `mapping.txt` when using `upload_mapping_only` |
|
107
122
|
| `version` <br/> `APPCENTER_DISTRIBUTE_VERSION` | The build version, required for .pkg, .dmg, .zip and .msi builds, as well as Android ProGuard `mapping.txt` when using `upload_mapping_only` |
|
108
|
-
| `timeout` <br/> `APPCENTER_DISTRIBUTE_TIMEOUT` | Request timeout in seconds |
|
123
|
+
| `timeout` <br/> `APPCENTER_DISTRIBUTE_TIMEOUT` | Request timeout in seconds applied to individual HTTP requests. Some commands use multiple HTTP requests, large file uploads are also split in multiple HTTP requests |
|
109
124
|
| `dsa_signature` <br/> `APPCENTER_DISTRIBUTE_DSA_SIGNATURE` | DSA signature of the macOS or Windows release for Sparkle update feed |
|
125
|
+
| `ed_signature` <br/> `APPCENTER_DISTRIBUTE_ED_SIGNATURE` | EdDSA signature of the macOS or Windows release for Sparkle update feed |
|
110
126
|
| `strict` <br/> `APPCENTER_STRICT_MODE` | Strict mode, set to 'true' to fail early in case a potential error was detected |
|
111
127
|
|
128
|
+
#### `appcenter_fetch_version_number`
|
129
|
+
|
130
|
+
| Key & Env Var | Description |
|
131
|
+
|-----------------|--------------------|
|
132
|
+
| `api_token` <br/> `APPCENTER_API_TOKEN` | API Token for App Center |
|
133
|
+
| `owner_name` <br/> `APPCENTER_OWNER_NAME` | Owner name, as found in the App's URL in App Center |
|
134
|
+
| `app_name` <br/> `APPCENTER_APP_NAME` | App name as found in the App's URL in App Center. If there is no app with such name, you will be prompted to create one |
|
135
|
+
| `version` <br/> `APPCENTER_APP_VERSION` | App version to get the last release for instead of the last release of all versions |
|
112
136
|
|
113
137
|
## Example
|
114
138
|
|
@@ -162,4 +186,4 @@ Check out [SECURITY.md](SECURITY.md) for any security concern with this project.
|
|
162
186
|
|
163
187
|
## Contact
|
164
188
|
|
165
|
-
We're on Twitter as [@vsappcenter](https://www.twitter.com/vsappcenter). Additionally you can reach out to us on the [App Center](https://appcenter.ms/apps) portal
|
189
|
+
We're on Twitter as [@vsappcenter](https://www.twitter.com/vsappcenter). Additionally you can reach out to us on the [App Center](https://appcenter.ms/apps) portal. Open the "?" menu on the top right corner of screen, then use "Contact support" to file a support ticket. Our support team is there to answer your questions and help you solve your problems.
|
@@ -0,0 +1,103 @@
|
|
1
|
+
require "json"
|
2
|
+
require "net/http"
|
3
|
+
require "fastlane_core/ui/ui"
|
4
|
+
|
5
|
+
module Fastlane
|
6
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
7
|
+
|
8
|
+
module Actions
|
9
|
+
class AppcenterFetchVersionNumberAction < Action
|
10
|
+
def self.description
|
11
|
+
"Fetches the latest version number of an app or the last build number of a version from App Center"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.authors
|
15
|
+
["jspargo", "ShopKeep", "Qutaibah"]
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.run(params)
|
19
|
+
api_token = params[:api_token]
|
20
|
+
app_name = params[:app_name]
|
21
|
+
owner_name = params[:owner_name]
|
22
|
+
version = params[:version]
|
23
|
+
|
24
|
+
releases = Helper::AppcenterHelper.fetch_releases(
|
25
|
+
api_token: api_token,
|
26
|
+
owner_name: owner_name,
|
27
|
+
app_name: app_name,
|
28
|
+
)
|
29
|
+
|
30
|
+
UI.abort_with_message!("No versions found for '#{app_name}' owned by #{owner_name}") unless releases
|
31
|
+
|
32
|
+
sorted_releases = releases
|
33
|
+
|
34
|
+
if version.nil?
|
35
|
+
sorted_releases = releases.sort_by { |release| release["id"] }
|
36
|
+
else
|
37
|
+
sorted_releases = releases.select { |release| release["short_version"] == version }.sort_by { |release| release["id"] }
|
38
|
+
end
|
39
|
+
|
40
|
+
latest_release = sorted_releases.last
|
41
|
+
|
42
|
+
if latest_release.nil?
|
43
|
+
if version.nil?
|
44
|
+
UI.user_error!("This app has no releases yet")
|
45
|
+
return nil
|
46
|
+
end
|
47
|
+
UI.user_error!("The provided version (#{version}) has no releases yet")
|
48
|
+
return nil
|
49
|
+
end
|
50
|
+
|
51
|
+
return {
|
52
|
+
"id" => latest_release["id"],
|
53
|
+
"version" => latest_release["short_version"],
|
54
|
+
"build_number" => latest_release["version"],
|
55
|
+
}
|
56
|
+
end
|
57
|
+
|
58
|
+
def self.available_options
|
59
|
+
[
|
60
|
+
FastlaneCore::ConfigItem.new(key: :api_token,
|
61
|
+
env_name: "APPCENTER_API_TOKEN",
|
62
|
+
description: "API Token for App Center Access",
|
63
|
+
verify_block: proc do |value|
|
64
|
+
UI.user_error!("No API token for App Center given, pass using `api_token: 'token'`") unless value && !value.empty?
|
65
|
+
end),
|
66
|
+
FastlaneCore::ConfigItem.new(key: :owner_name,
|
67
|
+
env_name: "APPCENTER_OWNER_NAME",
|
68
|
+
description: "Name of the owner of the application on App Center",
|
69
|
+
verify_block: proc do |value|
|
70
|
+
UI.user_error!("No owner name for App Center given, pass using `owner_name: 'owner name'`") unless value && !value.empty?
|
71
|
+
end),
|
72
|
+
FastlaneCore::ConfigItem.new(key: :app_name,
|
73
|
+
env_name: "APPCENTER_APP_NAME",
|
74
|
+
description: "Name of the application on App Center",
|
75
|
+
verify_block: proc do |value|
|
76
|
+
UI.user_error!("No app name for App Center given, pass using `app_name: 'app name'`") unless value && !value.empty?
|
77
|
+
end),
|
78
|
+
FastlaneCore::ConfigItem.new(key: :version,
|
79
|
+
env_name: "APPCENTER_APP_VERSION",
|
80
|
+
description: "The version to get the latest release for",
|
81
|
+
optional: true,
|
82
|
+
type: String),
|
83
|
+
|
84
|
+
]
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.is_supported?(platform)
|
88
|
+
[:ios, :android].include?(platform)
|
89
|
+
end
|
90
|
+
|
91
|
+
def self.get_apps(api_token)
|
92
|
+
host_uri = URI.parse("https://api.appcenter.ms")
|
93
|
+
http = Net::HTTP.new(host_uri.host, host_uri.port)
|
94
|
+
http.use_ssl = true
|
95
|
+
apps_request = Net::HTTP::Get.new("/v0.1/apps")
|
96
|
+
apps_request["X-API-Token"] = api_token
|
97
|
+
apps_response = http.request(apps_request)
|
98
|
+
return [] unless apps_response.kind_of?(Net::HTTPOK)
|
99
|
+
return JSON.parse(apps_response.body)
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
@@ -9,6 +9,23 @@ module Fastlane
|
|
9
9
|
windows: %w(.appx .appxbundle .appxupload .msix .msixbundle .msixupload .zip .msi),
|
10
10
|
custom: %w(.zip)
|
11
11
|
}
|
12
|
+
CONTENT_TYPES = {
|
13
|
+
apk: "application/vnd.android.package-archive",
|
14
|
+
aab: "application/vnd.android.package-archive",
|
15
|
+
msi: "application/x-msi",
|
16
|
+
plist: "application/xml",
|
17
|
+
aetx: "application/c-x509-ca-cert",
|
18
|
+
cer: "application/pkix-cert",
|
19
|
+
xap: "application/x-silverlight-app",
|
20
|
+
appx: "application/x-appx",
|
21
|
+
appxbundle: "application/x-appxbundle",
|
22
|
+
appxupload: "application/x-appxupload",
|
23
|
+
appxsym: "application/x-appxupload",
|
24
|
+
msix: "application/x-msix",
|
25
|
+
msixbundle: "application/x-msixbundle",
|
26
|
+
msixupload: "application/x-msixupload",
|
27
|
+
msixsym: "application/x-msixupload",
|
28
|
+
}
|
12
29
|
ALL_SUPPORTED_EXTENSIONS = SUPPORTED_EXTENSIONS.values.flatten.sort!.uniq!
|
13
30
|
STORE_ONLY_EXTENSIONS = %w(.aab)
|
14
31
|
STORE_SUPPORTED_EXTENSIONS = %w(.aab .apk .ipa)
|
@@ -22,6 +39,13 @@ module Fastlane
|
|
22
39
|
end
|
23
40
|
|
24
41
|
class AppcenterUploadAction < Action
|
42
|
+
def self.is_apple_build(file)
|
43
|
+
return false unless file
|
44
|
+
|
45
|
+
file_ext = Helper::AppcenterHelper.file_extname_full(file)
|
46
|
+
((Constants::SUPPORTED_EXTENSIONS[:ios] + Constants::SUPPORTED_EXTENSIONS[:mac])).include? file_ext
|
47
|
+
end
|
48
|
+
|
25
49
|
# run whole upload process for dSYM files
|
26
50
|
def self.run_dsym_upload(params)
|
27
51
|
values = params.values
|
@@ -35,8 +59,9 @@ module Fastlane
|
|
35
59
|
|
36
60
|
dsym_path = nil
|
37
61
|
if dsym
|
38
|
-
# we can use dsym parameter
|
39
|
-
|
62
|
+
# we can use dsym parameter for all apple builds
|
63
|
+
self.optional_error("dsym parameter can only be used with Apple builds (ios, mac)") unless !file || self.is_apple_build(file)
|
64
|
+
dsym_path = dsym
|
40
65
|
else
|
41
66
|
# if dsym is not set, but build is ipa - check default path
|
42
67
|
if file && File.exist?(file) && File.extname(file) == '.ipa'
|
@@ -118,6 +143,7 @@ module Fastlane
|
|
118
143
|
build_number = params[:build_number]
|
119
144
|
version = params[:version]
|
120
145
|
dsa_signature = params[:dsa_signature]
|
146
|
+
ed_signature = params[:ed_signature]
|
121
147
|
|
122
148
|
if release_notes.length >= Constants::MAX_RELEASE_NOTES_LENGTH
|
123
149
|
unless should_clip
|
@@ -145,6 +171,7 @@ module Fastlane
|
|
145
171
|
self.optional_error("Can't distribute #{file_ext} to groups, please use `destination_type: 'store'`") if Constants::STORE_ONLY_EXTENSIONS.include? file_ext
|
146
172
|
else
|
147
173
|
self.optional_error("Can't distribute #{file_ext} to stores, please use `destination_type: 'group'`") unless Constants::STORE_SUPPORTED_EXTENSIONS.include? file_ext
|
174
|
+
UI.user_error!("The combination of `destinations: '*'` and `destination_type: 'store'` is invalid, please use `destination_type: 'group'` or explicitly specify the destinations") if destinations == "*"
|
148
175
|
end
|
149
176
|
|
150
177
|
release_upload_body = nil
|
@@ -171,27 +198,57 @@ module Fastlane
|
|
171
198
|
File.delete zip_file
|
172
199
|
end
|
173
200
|
UI.message("Creating zip archive: #{zip_file}")
|
174
|
-
file = Actions::ZipAction.run(path: file, output_path: zip_file)
|
201
|
+
file = Actions::ZipAction.run(path: file, output_path: zip_file, symlinks: true)
|
175
202
|
end
|
176
203
|
|
177
204
|
UI.message("Starting release upload...")
|
178
205
|
upload_details = Helper::AppcenterHelper.create_release_upload(api_token, owner_name, app_name, release_upload_body)
|
179
206
|
if upload_details
|
180
|
-
upload_id = upload_details['
|
181
|
-
|
207
|
+
upload_id = upload_details['id']
|
208
|
+
|
209
|
+
UI.message("Setting Metadata...")
|
210
|
+
content_type = Constants::CONTENT_TYPES[File.extname(file)&.delete('.').downcase.to_sym] || "application/octet-stream"
|
211
|
+
set_metadata_url = "#{upload_details['upload_domain']}/upload/set_metadata/#{upload_details['package_asset_id']}?file_name=#{File.basename(file)}&file_size=#{File.size(file)}&token=#{upload_details['url_encoded_token']}&content_type=#{content_type}"
|
212
|
+
chunk_size = Helper::AppcenterHelper.set_release_upload_metadata(set_metadata_url, api_token, owner_name, app_name, upload_id, timeout)
|
213
|
+
UI.abort_with_message!("Upload aborted") unless chunk_size
|
182
214
|
|
183
215
|
UI.message("Uploading release binary...")
|
184
|
-
|
216
|
+
upload_url = "#{upload_details['upload_domain']}/upload/upload_chunk/#{upload_details['package_asset_id']}?token=#{upload_details['url_encoded_token']}"
|
217
|
+
uploaded = Helper::AppcenterHelper.upload_build(api_token, owner_name, app_name, file, upload_id, upload_url, content_type, chunk_size, timeout)
|
218
|
+
UI.abort_with_message!("Upload aborted") unless uploaded
|
219
|
+
|
220
|
+
UI.message("Finishing release...")
|
221
|
+
finish_url = "#{upload_details['upload_domain']}/upload/finished/#{upload_details['package_asset_id']}?token=#{upload_details['url_encoded_token']}"
|
222
|
+
finished = Helper::AppcenterHelper.finish_release_upload(finish_url, api_token, owner_name, app_name, upload_id, timeout)
|
223
|
+
UI.abort_with_message!("Upload aborted") unless finished
|
224
|
+
|
225
|
+
UI.message("Waiting for release to be ready...")
|
226
|
+
release_status_url = "v0.1/apps/#{owner_name}/#{app_name}/uploads/releases/#{upload_id}"
|
227
|
+
release_id = Helper::AppcenterHelper.poll_for_release_id(api_token, release_status_url)
|
185
228
|
|
186
|
-
if
|
187
|
-
release_id = uploaded['release_id']
|
229
|
+
if release_id.is_a? Integer
|
188
230
|
release_url = Helper::AppcenterHelper.get_release_url(owner_type, owner_name, app_name, release_id)
|
189
231
|
UI.message("Release '#{release_id}' committed: #{release_url}")
|
190
232
|
|
191
233
|
release = Helper::AppcenterHelper.update_release(api_token, owner_name, app_name, release_id, release_notes)
|
192
|
-
Helper::AppcenterHelper.update_release_metadata(api_token, owner_name, app_name, release_id, dsa_signature)
|
193
|
-
|
194
|
-
destinations_array =
|
234
|
+
Helper::AppcenterHelper.update_release_metadata(api_token, owner_name, app_name, release_id, dsa_signature, ed_signature)
|
235
|
+
|
236
|
+
destinations_array = []
|
237
|
+
if destinations == '*'
|
238
|
+
UI.message("Looking up all distribution groups for #{owner_name}/#{app_name}")
|
239
|
+
distribution_groups = Helper::AppcenterHelper.fetch_distribution_groups(
|
240
|
+
api_token: api_token,
|
241
|
+
owner_name: owner_name,
|
242
|
+
app_name: app_name
|
243
|
+
)
|
244
|
+
|
245
|
+
UI.abort_with_message!("Failed to list distribution groups for #{owner_name}/#{app_name}") unless distribution_groups
|
246
|
+
|
247
|
+
destinations_array = distribution_groups.map {|h| h['name'] }
|
248
|
+
else
|
249
|
+
destinations_array = destinations.split(',').map(&:strip)
|
250
|
+
end
|
251
|
+
|
195
252
|
destinations_array.each do |destination_name|
|
196
253
|
destination = Helper::AppcenterHelper.get_destination(api_token, owner_name, app_name, destination_type, destination_name)
|
197
254
|
if destination
|
@@ -228,10 +285,11 @@ module Fastlane
|
|
228
285
|
app_platform = params[:app_platform]
|
229
286
|
|
230
287
|
platforms = {
|
231
|
-
Android: %w[Java React-Native Xamarin],
|
232
|
-
iOS: %w[Objective-C-Swift React-Native Xamarin],
|
288
|
+
Android: %w[Java React-Native Xamarin Unity],
|
289
|
+
iOS: %w[Objective-C-Swift React-Native Xamarin Unity],
|
233
290
|
macOS: %w[Objective-C-Swift],
|
234
|
-
Windows: %w[UWP WPF WinForms Unity]
|
291
|
+
Windows: %w[UWP WPF WinForms Unity],
|
292
|
+
Custom: %w[Custom]
|
235
293
|
}
|
236
294
|
|
237
295
|
begin
|
@@ -260,6 +318,30 @@ module Fastlane
|
|
260
318
|
end
|
261
319
|
end
|
262
320
|
|
321
|
+
def self.add_app_to_distribution_group_if_needed(params)
|
322
|
+
return unless params[:destination_type] == 'group' && params[:owner_type] == 'organization' && params[:destinations] != '*'
|
323
|
+
|
324
|
+
app_distribution_groups = Helper::AppcenterHelper.fetch_distribution_groups(
|
325
|
+
api_token: params[:api_token],
|
326
|
+
owner_name: params[:owner_name],
|
327
|
+
app_name: params[:app_name]
|
328
|
+
)
|
329
|
+
|
330
|
+
group_names = app_distribution_groups.map { |g| g['name'] }
|
331
|
+
destination_names = params[:destinations].split(',').map(&:strip)
|
332
|
+
|
333
|
+
destination_names.each do |destination_name|
|
334
|
+
unless group_names.include? destination_name
|
335
|
+
Helper::AppcenterHelper.add_new_app_to_distribution_group(
|
336
|
+
api_token: params[:api_token],
|
337
|
+
owner_name: params[:owner_name],
|
338
|
+
app_name: params[:app_name],
|
339
|
+
destination_name: destination_name
|
340
|
+
)
|
341
|
+
end
|
342
|
+
end
|
343
|
+
end
|
344
|
+
|
263
345
|
def self.run(params)
|
264
346
|
values = params.values
|
265
347
|
upload_build_only = params[:upload_build_only]
|
@@ -270,10 +352,10 @@ module Fastlane
|
|
270
352
|
|
271
353
|
# if app found or successfully created
|
272
354
|
if self.get_or_create_app(params)
|
355
|
+
self.add_app_to_distribution_group_if_needed(params)
|
273
356
|
release = self.run_release_upload(params) unless upload_dsym_only || upload_mapping_only
|
274
357
|
params[:version] = release['short_version'] if release
|
275
358
|
params[:build_number] = release['version'] if release
|
276
|
-
|
277
359
|
self.run_dsym_upload(params) unless upload_mapping_only || upload_build_only
|
278
360
|
self.run_mapping_upload(params) unless upload_dsym_only || upload_build_only
|
279
361
|
end
|
@@ -344,7 +426,7 @@ module Fastlane
|
|
344
426
|
|
345
427
|
FastlaneCore::ConfigItem.new(key: :app_os,
|
346
428
|
env_name: "APPCENTER_APP_OS",
|
347
|
-
description: "App OS. Used for new app creation, if app 'app_name' was not found",
|
429
|
+
description: "App OS can be Android, iOS, macOS, Windows, Custom. Used for new app creation, if app 'app_name' was not found",
|
348
430
|
optional: true,
|
349
431
|
type: String),
|
350
432
|
|
@@ -424,7 +506,7 @@ module Fastlane
|
|
424
506
|
self.optional_error("Extension not supported: '#{file_ext}'. Supported formats for platform '#{platform}': #{accepted_formats.join ' '}") unless accepted_formats.include? file_ext
|
425
507
|
end
|
426
508
|
end),
|
427
|
-
|
509
|
+
|
428
510
|
FastlaneCore::ConfigItem.new(key: :upload_build_only,
|
429
511
|
env_name: "APPCENTER_DISTRIBUTE_UPLOAD_BUILD_ONLY",
|
430
512
|
description: "Flag to upload only the build to App Center. Skips uploading symbols or mapping",
|
@@ -460,6 +542,7 @@ module Fastlane
|
|
460
542
|
FastlaneCore::ConfigItem.new(key: :mapping,
|
461
543
|
env_name: "APPCENTER_DISTRIBUTE_ANDROID_MAPPING",
|
462
544
|
description: "Path to your Android mapping.txt",
|
545
|
+
default_value: (defined? SharedValues::GRADLE_MAPPING_TXT_OUTPUT_PATH) && Actions.lane_context[SharedValues::GRADLE_MAPPING_TXT_OUTPUT_PATH] || nil,
|
463
546
|
optional: true,
|
464
547
|
type: String,
|
465
548
|
verify_block: proc do |value|
|
@@ -489,12 +572,11 @@ module Fastlane
|
|
489
572
|
|
490
573
|
FastlaneCore::ConfigItem.new(key: :destinations,
|
491
574
|
env_name: "APPCENTER_DISTRIBUTE_DESTINATIONS",
|
492
|
-
description: "Comma separated list of destination names. Both distribution groups and stores are supported. All names are required to be of the same destination type",
|
575
|
+
description: "Comma separated list of destination names, use '*' for all distribution groups if destination type is 'group'. Both distribution groups and stores are supported. All names are required to be of the same destination type",
|
493
576
|
default_value: Actions.lane_context[SharedValues::APPCENTER_DISTRIBUTE_DESTINATIONS] || "Collaborators",
|
494
577
|
optional: true,
|
495
578
|
type: String),
|
496
579
|
|
497
|
-
|
498
580
|
FastlaneCore::ConfigItem.new(key: :destination_type,
|
499
581
|
env_name: "APPCENTER_DISTRIBUTE_DESTINATION_TYPE",
|
500
582
|
description: "Destination type of distribution destination. 'group' and 'store' are supported",
|
@@ -553,7 +635,7 @@ module Fastlane
|
|
553
635
|
|
554
636
|
FastlaneCore::ConfigItem.new(key: :timeout,
|
555
637
|
env_name: "APPCENTER_DISTRIBUTE_TIMEOUT",
|
556
|
-
description: "Request timeout in seconds",
|
638
|
+
description: "Request timeout in seconds applied to individual HTTP requests. Some commands use multiple HTTP requests, large file uploads are also split in multiple HTTP requests",
|
557
639
|
optional: true,
|
558
640
|
type: Integer),
|
559
641
|
|
@@ -562,7 +644,13 @@ module Fastlane
|
|
562
644
|
description: "DSA signature of the macOS or Windows release for Sparkle update feed",
|
563
645
|
optional: true,
|
564
646
|
type: String),
|
565
|
-
|
647
|
+
|
648
|
+
FastlaneCore::ConfigItem.new(key: :ed_signature,
|
649
|
+
env_name: "APPCENTER_DISTRIBUTE_ED_SIGNATURE",
|
650
|
+
description: "EdDSA signature of the macOS or Windows release for Sparkle update feed",
|
651
|
+
optional: true,
|
652
|
+
type: String),
|
653
|
+
|
566
654
|
FastlaneCore::ConfigItem.new(key: :strict,
|
567
655
|
env_name: "APPCENTER_STRICT_MODE",
|
568
656
|
description: "Strict mode, set to 'true' to fail early in case a potential error was detected",
|
@@ -608,6 +696,16 @@ module Fastlane
|
|
608
696
|
release_notes: "release notes",
|
609
697
|
notify_testers: false
|
610
698
|
)',
|
699
|
+
'appcenter_upload(
|
700
|
+
api_token: "...",
|
701
|
+
owner_name: "appcenter_owner",
|
702
|
+
app_name: "testing_ios_app",
|
703
|
+
file: "./app-release.ipa",
|
704
|
+
destinations: "*",
|
705
|
+
destination_type: "group",
|
706
|
+
release_notes: "release notes",
|
707
|
+
notify_testers: false
|
708
|
+
)',
|
611
709
|
'appcenter_upload(
|
612
710
|
api_token: "...",
|
613
711
|
owner_name: "appcenter_owner",
|