fastlane-plugin-mobile_center 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 658f351985d0f8f3958fb121e99949e346f65029
4
+ data.tar.gz: 8ec5929738adbb7d2c219029ea580cc633b70bfb
5
+ SHA512:
6
+ metadata.gz: 1d5b9afc23e560e849b73926a1dd43c63bff9be52809c09c0cc52225e15c698716eede20531a8364d9d8f8bc97f657cedf15ecdfc66211d396cac35d60a83551
7
+ data.tar.gz: 4a9dcc774dd40042d99451ec7d1b5a1f598c291e414aed61d206ad7c984cf1badc7c44fade4ae777e5421c8f8a96f33727516ba68485e6feba53ea4dd6744a46
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) Microsoft Corporation. All rights reserved.
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # mobile_center plugin
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-mobile_center)
4
+
5
+ ## Getting Started
6
+
7
+ This project is a [_fastlane_](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-mobile_center`, add it to your project by running:
8
+
9
+ ```bash
10
+ fastlane add_plugin mobile_center
11
+ ```
12
+
13
+ ## About mobile_center
14
+
15
+ Plugin for [Mobile Center](https://mobile.azure.com). Provides `mobile_center_upload` action for [release distribution](https://docs.microsoft.com/en-us/mobile-center/distribution/uploading) and [dSYM uploads](https://docs.microsoft.com/en-us/mobile-center/crashes/ios)
16
+
17
+ ## Usage
18
+
19
+ Obtain an [API token](https://docs.microsoft.com/en-us/mobile-center/api-docs/). API Token is used for authentication for all Mobile Center API calls.
20
+
21
+ ```
22
+ mobile_center_upload(
23
+ api_token: <mobile center token>,
24
+ owner_name: <your mobile center account name>,
25
+ app_name: <your app name>,
26
+ apk: <path to android build binary>
27
+ )
28
+ ```
29
+
30
+ ## Example
31
+
32
+ Check out the [example `Fastfile`](fastlane/Fastfile) to see how to use this plugin. Try it by cloning the repo, running `fastlane install_plugins` and `bundle exec fastlane test`.
33
+
34
+ Sample uses `.env` for setting private variables like API token, owner name, .etc. You need to replace it in `Fastfile` by your own values.
35
+
36
+ There are three examples in `test` lane:
37
+ - upload release for android with minimum required parameters
38
+ - upload release for ios with all set parameters
39
+ - upload only dSYM file for ios
40
+
41
+ ## Run tests for this plugin
42
+
43
+ To run both the tests, and code style validation, run
44
+
45
+ ```
46
+ rake
47
+ ```
48
+
49
+ To automatically fix many of the styling issues, use
50
+ ```
51
+ rubocop -a
52
+ ```
53
+
54
+ ## Issues and Feedback
55
+
56
+ For any other issues and feedback about this plugin, please submit it to this repository.
57
+
58
+ ## Troubleshooting
59
+
60
+ If you have trouble using plugins, check out the [Plugins Troubleshooting](https://docs.fastlane.tools/plugins/plugins-troubleshooting/) guide.
61
+
62
+ ## Using _fastlane_ Plugins
63
+
64
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://docs.fastlane.tools/plugins/create-plugin/).
65
+
66
+ ## About _fastlane_
67
+
68
+ _fastlane_ is the easiest way to automate beta deployments and releases for your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
69
+
70
+ ## Contributing
71
+
72
+ This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
73
+
74
+ ## Contact
75
+
76
+ ### Intercom
77
+
78
+ If you have further questions, want to provide feedback or you are running into issues, log in to the [Mobile Center](https://mobile.azure.com) portal and use the blue Intercom button on the bottom right to start a conversation with us.
79
+
80
+ ### Twitter
81
+
82
+ We're on Twitter as [@mobilecenter](https://www.twitter.com/mobilecenter).
@@ -0,0 +1,16 @@
1
+ require 'fastlane/plugin/mobile_center/version'
2
+
3
+ module Fastlane
4
+ module MobileCenter
5
+ # Return all .rb files inside the "actions" and "helper" directory
6
+ def self.all_classes
7
+ Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
8
+ end
9
+ end
10
+ end
11
+
12
+ # By default we want to import all available actions and helpers
13
+ # A plugin can contain any number of actions and plugins
14
+ Fastlane::MobileCenter.all_classes.each do |current|
15
+ require current
16
+ end
@@ -0,0 +1,472 @@
1
+ # rubocop:disable Metrics/ClassLength
2
+ module Fastlane
3
+ module Actions
4
+ module SharedValues
5
+ MOBILE_CENTER_DOWNLOAD_LINK = :MOBILE_CENTER_DOWNLOAD_LINK
6
+ MOBILE_CENTER_BUILD_INFORMATION = :MOBILE_CENTER_BUILD_INFORMATION
7
+ end
8
+
9
+ class MobileCenterUploadAction < Action
10
+ # create request
11
+ def self.connection(upload_url = false, dsym = false)
12
+ require 'faraday'
13
+ require 'faraday_middleware'
14
+
15
+ options = {
16
+ url: upload_url ? upload_url : "https://api.mobile.azure.com"
17
+ }
18
+
19
+ Faraday.new(options) do |builder|
20
+ if upload_url
21
+ builder.request :multipart unless dsym
22
+ builder.request :url_encoded unless dsym
23
+ else
24
+ builder.request :json
25
+ end
26
+ builder.response :json, content_type: /\bjson$/
27
+ builder.use FaradayMiddleware::FollowRedirects
28
+ builder.adapter :net_http
29
+ end
30
+ end
31
+
32
+ # creates new release upload
33
+ # returns:
34
+ # upload_id
35
+ # upload_url
36
+ def self.create_release_upload(api_token, owner_name, app_name)
37
+ connection = self.connection
38
+
39
+ response = connection.post do |req|
40
+ req.url("/v0.1/apps/#{owner_name}/#{app_name}/release_uploads")
41
+ req.headers['X-API-Token'] = api_token
42
+ req.headers['internal-request-source'] = "fastlane"
43
+ req.body = {}
44
+ end
45
+
46
+ case response.status
47
+ when 200...300
48
+ if ENV['DEBUG']
49
+ UI.message("DEBUG: #{JSON.pretty_generate(response.body)}\n")
50
+ end
51
+ response.body
52
+ when 401
53
+ UI.user_error!("Auth Error, provided invalid token")
54
+ false
55
+ when 404
56
+ UI.error("Not found, invalid owner or application name")
57
+ false
58
+ else
59
+ UI.error("Error #{response.status}: #{response.body}")
60
+ false
61
+ end
62
+ end
63
+
64
+ # creates new dSYM upload in mobile center
65
+ # returns:
66
+ # symbol_upload_id
67
+ # upload_url
68
+ # expiration_date
69
+ def self.create_dsym_upload(api_token, owner_name, app_name)
70
+ connection = self.connection
71
+
72
+ response = connection.post do |req|
73
+ req.url("/v0.1/apps/#{owner_name}/#{app_name}/symbol_uploads")
74
+ req.headers['X-API-Token'] = api_token
75
+ req.headers['internal-request-source'] = "fastlane"
76
+ req.body = {
77
+ symbol_type: 'Apple'
78
+ }
79
+ end
80
+
81
+ case response.status
82
+ when 200...300
83
+ if ENV['DEBUG']
84
+ UI.message("DEBUG: #{JSON.pretty_generate(response.body)}\n")
85
+ end
86
+ response.body
87
+ when 401
88
+ UI.user_error!("Auth Error, provided invalid token")
89
+ false
90
+ when 404
91
+ UI.error("Not found, invalid owner or application name")
92
+ false
93
+ else
94
+ UI.error("Error #{response.status}: #{response.body}")
95
+ false
96
+ end
97
+ end
98
+
99
+ # committs or aborts dsym upload
100
+ def self.update_dsym_upload(api_token, owner_name, app_name, symbol_upload_id, status)
101
+ connection = self.connection
102
+
103
+ response = connection.patch do |req|
104
+ req.url("/v0.1/apps/#{owner_name}/#{app_name}/symbol_uploads/#{symbol_upload_id}")
105
+ req.headers['X-API-Token'] = api_token
106
+ req.headers['internal-request-source'] = "fastlane"
107
+ req.body = {
108
+ "status" => status
109
+ }
110
+ end
111
+
112
+ case response.status
113
+ when 200...300
114
+ if ENV['DEBUG']
115
+ UI.message("DEBUG: #{JSON.pretty_generate(response.body)}\n")
116
+ end
117
+ response.body
118
+ else
119
+ UI.error("Error #{response.status}: #{response.body}")
120
+ false
121
+ end
122
+ end
123
+
124
+ # upload dSYM files to specified upload url
125
+ # if succeed, then commits the upload
126
+ # otherwise aborts
127
+ def self.upload_dsym(api_token, owner_name, app_name, dsym, symbol_upload_id, upload_url)
128
+ connection = self.connection(upload_url, true)
129
+
130
+ response = connection.put do |req|
131
+ req.headers['x-ms-blob-type'] = "BlockBlob"
132
+ req.headers['Content-Length'] = File.size(dsym).to_s
133
+ req.headers['internal-request-source'] = "fastlane"
134
+ req.body = Faraday::UploadIO.new(dsym, 'application/octet-stream') if dsym and File.exist?(dsym)
135
+ end
136
+
137
+ case response.status
138
+ when 200...300
139
+ self.update_dsym_upload(api_token, owner_name, app_name, symbol_upload_id, 'committed')
140
+ UI.success("dSYM uploaded")
141
+ else
142
+ UI.error("Error uploading dSYM #{response.status}: #{response.body}")
143
+ self.update_dsym_upload(api_token, owner_name, app_name, symbol_upload_id, 'aborted')
144
+ UI.error("dSYM upload aborted")
145
+ false
146
+ end
147
+ end
148
+
149
+ # upload binary for specified upload_url
150
+ # if succeed, then commits the release
151
+ # otherwise aborts
152
+ def self.upload_build(api_token, owner_name, app_name, file, upload_id, upload_url)
153
+ connection = self.connection(upload_url)
154
+
155
+ options = {}
156
+ options[:upload_id] = upload_id
157
+ # ipa field is used both for .apk and .ipa files
158
+ options[:ipa] = Faraday::UploadIO.new(file, 'application/octet-stream') if file and File.exist?(file)
159
+
160
+ response = connection.post do |req|
161
+ req.headers['internal-request-source'] = "fastlane"
162
+ req.body = options
163
+ end
164
+
165
+ case response.status
166
+ when 200...300
167
+ UI.message("Binary uploaded")
168
+ self.update_release_upload(api_token, owner_name, app_name, upload_id, 'committed')
169
+ else
170
+ UI.error("Error uploading binary #{response.status}: #{response.body}")
171
+ self.update_release_upload(api_token, owner_name, app_name, upload_id, 'aborted')
172
+ UI.error("Release aborted")
173
+ false
174
+ end
175
+ end
176
+
177
+ # Commits or aborts the upload process for a release
178
+ def self.update_release_upload(api_token, owner_name, app_name, upload_id, status)
179
+ connection = self.connection
180
+
181
+ response = connection.patch do |req|
182
+ req.url("/v0.1/apps/#{owner_name}/#{app_name}/release_uploads/#{upload_id}")
183
+ req.headers['X-API-Token'] = api_token
184
+ req.headers['internal-request-source'] = "fastlane"
185
+ req.body = {
186
+ "status" => status
187
+ }
188
+ end
189
+
190
+ case response.status
191
+ when 200...300
192
+ if ENV['DEBUG']
193
+ UI.message("DEBUG: #{JSON.pretty_generate(response.body)}\n")
194
+ end
195
+ response.body
196
+ else
197
+ UI.error("Error #{response.status}: #{response.body}")
198
+ false
199
+ end
200
+ end
201
+
202
+ # add release to distribution group
203
+ def self.add_to_group(api_token, release_url, group_name, release_notes = '')
204
+ connection = self.connection
205
+
206
+ response = connection.patch do |req|
207
+ req.url("/#{release_url}")
208
+ req.headers['X-API-Token'] = api_token
209
+ req.headers['internal-request-source'] = "fastlane"
210
+ req.body = {
211
+ "distribution_group_name" => group_name,
212
+ "release_notes" => release_notes
213
+ }
214
+ end
215
+
216
+ case response.status
217
+ when 200...300
218
+ release = response.body
219
+ download_url = release['download_url']
220
+
221
+ if ENV['DEBUG']
222
+ UI.message("DEBUG: #{JSON.pretty_generate(release)}")
223
+ end
224
+
225
+ Actions.lane_context[SharedValues::MOBILE_CENTER_DOWNLOAD_LINK] = download_url
226
+ Actions.lane_context[SharedValues::MOBILE_CENTER_BUILD_INFORMATION] = release
227
+
228
+ UI.message("Public Download URL: #{download_url}") if download_url
229
+ UI.success("Release #{release['short_version']} was successfully distributed")
230
+
231
+ release
232
+ when 404
233
+ UI.error("Not found, invalid distribution group name")
234
+ false
235
+ else
236
+ UI.error("Error adding to group #{response.status}: #{response.body}")
237
+ false
238
+ end
239
+ end
240
+
241
+ # run whole upload process for dSYM files
242
+ def self.run_dsym_upload(params)
243
+ values = params.values
244
+ api_token = params[:api_token]
245
+ owner_name = params[:owner_name]
246
+ app_name = params[:app_name]
247
+ file = params[:ipa]
248
+ dsym = params[:dsym]
249
+
250
+ dsym_path = nil
251
+ if dsym
252
+ # we can use dsym parameter only if build file is ipa
253
+ if !file or File.extname(file) == '.ipa'
254
+ dsym_path = dsym
255
+ end
256
+ else
257
+ # if dsym is note set, but build is ipa - check default path
258
+ if file and File.exist?(file) and File.extname(file) == '.ipa'
259
+ dsym_path = file.to_s.gsub('.ipa', '.dSYM.zip')
260
+ UI.message("dSYM is found")
261
+ end
262
+ end
263
+
264
+ # if we provided valid dsym path, or <ipa_path>.dSYM.zip was found, start dSYM upload
265
+ if dsym_path and File.exist?(dsym_path)
266
+ if File.directory?(dsym_path)
267
+ UI.message("dSYM path is folder, zipping...")
268
+ dsym_path = Actions::ZipAction.run(path: dsym, output_path: dsym + ".zip")
269
+ UI.message("dSYM files zipped")
270
+ end
271
+
272
+ values[:dsym_path] = dsym_path
273
+
274
+ UI.message("Starting dSYM upload...")
275
+ dsym_upload_details = self.create_dsym_upload(api_token, owner_name, app_name)
276
+
277
+ if dsym_upload_details
278
+ symbol_upload_id = dsym_upload_details['symbol_upload_id']
279
+ upload_url = dsym_upload_details['upload_url']
280
+
281
+ UI.message("Uploading dSYM...")
282
+ self.upload_dsym(api_token, owner_name, app_name, dsym_path, symbol_upload_id, upload_url)
283
+ end
284
+ end
285
+ end
286
+
287
+ # run whole upload process for release
288
+ def self.run_release_upload(params)
289
+ api_token = params[:api_token]
290
+ owner_name = params[:owner_name]
291
+ app_name = params[:app_name]
292
+ group = params[:group]
293
+
294
+ file = [
295
+ params[:ipa],
296
+ params[:apk]
297
+ ].detect { |e| !e.to_s.empty? }
298
+
299
+ UI.user_error!("Couldn't find build file at path '#{file}'") unless file and File.exist?(file)
300
+ UI.user_error!("No Distribute Group given, pass using `group: 'group name'`") unless group and !group.empty?
301
+
302
+ UI.message("Starting release upload...")
303
+ upload_details = self.create_release_upload(api_token, owner_name, app_name)
304
+ if upload_details
305
+ upload_id = upload_details['upload_id']
306
+ upload_url = upload_details['upload_url']
307
+
308
+ UI.message("Uploading release binary...")
309
+ uploaded = self.upload_build(api_token, owner_name, app_name, file, upload_id, upload_url)
310
+
311
+ if uploaded
312
+ release_url = uploaded['release_url']
313
+ UI.message("Release committed")
314
+ self.add_to_group(api_token, release_url, group, params[:release_notes])
315
+ end
316
+ end
317
+ end
318
+
319
+ def self.run(params)
320
+ values = params.values
321
+ upload_dsym_only = params[:upload_dsym_only]
322
+
323
+ self.run_release_upload(params) unless upload_dsym_only
324
+ self.run_dsym_upload(params)
325
+
326
+ return values if Helper.test?
327
+ end
328
+
329
+ def self.description
330
+ "Distribute new release to Mobile Center"
331
+ end
332
+
333
+ def self.authors
334
+ ["Microsoft"]
335
+ end
336
+
337
+ def self.details
338
+ [
339
+ "Symbols will also be uploaded automatically if a `app.dSYM.zip` file is found next to `app.ipa`. In case it is located in a different place you can specify the path explicitly in `:dsym` parameter."
340
+ ]
341
+ end
342
+
343
+ def self.available_options
344
+ [
345
+ FastlaneCore::ConfigItem.new(key: :api_token,
346
+ env_name: "MOBILE_CENTER_API_TOKEN",
347
+ description: "API Token for Mobile Center",
348
+ optional: false,
349
+ type: String,
350
+ verify_block: proc do |value|
351
+ UI.user_error!("No API token for Mobile Center given, pass using `api_token: 'token'`") unless value and !value.empty?
352
+ end),
353
+
354
+ FastlaneCore::ConfigItem.new(key: :owner_name,
355
+ env_name: "MOBILE_CENTER_OWNER_NAME",
356
+ description: "Owner name",
357
+ optional: false,
358
+ type: String,
359
+ verify_block: proc do |value|
360
+ UI.user_error!("No Owner name for Mobile Center given, pass using `owner_name: 'name'`") unless value and !value.empty?
361
+ end),
362
+
363
+ FastlaneCore::ConfigItem.new(key: :app_name,
364
+ env_name: "MOBILE_CENTER_APP_NAME",
365
+ description: "App name",
366
+ optional: false,
367
+ type: String,
368
+ verify_block: proc do |value|
369
+ UI.user_error!("No App name given, pass using `app_name: 'app name'`") unless value and !value.empty?
370
+ end),
371
+
372
+ FastlaneCore::ConfigItem.new(key: :apk,
373
+ env_name: "MOBILE_CENTER_DISTRIBUTE_APK",
374
+ description: "Build release path for android build",
375
+ default_value: Actions.lane_context[SharedValues::GRADLE_APK_OUTPUT_PATH],
376
+ optional: true,
377
+ type: String,
378
+ conflicting_options: [:ipa],
379
+ conflict_block: proc do |value|
380
+ UI.user_error!("You can't use 'apk' and '#{value.key}' options in one run")
381
+ end,
382
+ verify_block: proc do |value|
383
+ accepted_formats = [".apk"]
384
+ UI.user_error!("Only \".apk\" formats are allowed, you provided \"#{File.extname(value)}\"") unless accepted_formats.include? File.extname(value)
385
+ end),
386
+
387
+ FastlaneCore::ConfigItem.new(key: :ipa,
388
+ env_name: "MOBILE_CENTER_DISTRIBUTE_IPA",
389
+ description: "Build release path for ios build",
390
+ default_value: Actions.lane_context[SharedValues::IPA_OUTPUT_PATH],
391
+ optional: true,
392
+ type: String,
393
+ conflicting_options: [:apk],
394
+ conflict_block: proc do |value|
395
+ UI.user_error!("You can't use 'ipa' and '#{value.key}' options in one run")
396
+ end,
397
+ verify_block: proc do |value|
398
+ accepted_formats = [".ipa"]
399
+ UI.user_error!("Only \".ipa\" formats are allowed, you provided \"#{File.extname(value)}\"") unless accepted_formats.include? File.extname(value)
400
+ end),
401
+
402
+ FastlaneCore::ConfigItem.new(key: :dsym,
403
+ env_name: "MOBILE_CENTER_DISTRIBUTE_DSYM",
404
+ description: "Path to your symbols file. For iOS provide path to app.dSYM.zip",
405
+ default_value: Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH],
406
+ optional: true,
407
+ type: String,
408
+ verify_block: proc do |value|
409
+ if value
410
+ UI.user_error!("Couldn't find dSYM file at path '#{value}'") unless File.exist?(value)
411
+ end
412
+ end),
413
+
414
+ FastlaneCore::ConfigItem.new(key: :upload_dsym_only,
415
+ env_name: "MOBILE_CENTER_DISTRIBUTE_UPLOAD_DSYM_ONLY",
416
+ description: "Flag to upload only the dSYM file to Mobile Center",
417
+ optional: true,
418
+ is_string: false,
419
+ default_value: false),
420
+
421
+ FastlaneCore::ConfigItem.new(key: :group,
422
+ env_name: "MOBILE_CENTER_DISTRIBUTE_GROUP",
423
+ description: "Distribute group name",
424
+ default_value: "Collaborators",
425
+ optional: true,
426
+ type: String),
427
+
428
+ FastlaneCore::ConfigItem.new(key: :release_notes,
429
+ env_name: "MOBILE_CENTER_DISTRIBUTE_RELEASE_NOTES",
430
+ description: "Release notes",
431
+ default_value: Actions.lane_context[SharedValues::FL_CHANGELOG] || "No changelog given",
432
+ optional: true,
433
+ type: String)
434
+ ]
435
+ end
436
+
437
+ def self.output
438
+ [
439
+ ['MOBILE_CENTER_DOWNLOAD_LINK', 'The newly generated download link for this build'],
440
+ ['MOBILE_CENTER_BUILD_INFORMATION', 'contains all keys/values from the Mobile CEnter API']
441
+ ]
442
+ end
443
+
444
+ def self.is_supported?(platform)
445
+ true
446
+ end
447
+
448
+ def self.example_code
449
+ [
450
+ 'mobile_center_upload(
451
+ api_token: "...",
452
+ owner_name: "mobile_center_owner",
453
+ app_name: "testing_app",
454
+ apk: "./app-release.apk",
455
+ group: "Testers",
456
+ release_notes: "release notes"
457
+ )',
458
+ 'mobile_center_upload(
459
+ api_token: "...",
460
+ owner_name: "mobile_center_owner",
461
+ app_name: "testing_app",
462
+ apk: "./app-release.ipa",
463
+ group: "Testers",
464
+ dsym: "./app.dSYM.zip",
465
+ release_notes: "release notes"
466
+ )'
467
+ ]
468
+ end
469
+ end
470
+ end
471
+ end
472
+ # rubocop:enable Metrics/ClassLength
@@ -0,0 +1,12 @@
1
+ module Fastlane
2
+ module Helper
3
+ class MobileCenterHelper
4
+ # class methods that you define here become available in your action
5
+ # as `Helper::MobileCenterHelper.your_method`
6
+ #
7
+ def self.show_message
8
+ UI.message("Hello from the mobile_center plugin helper!")
9
+ end
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,5 @@
1
+ module Fastlane
2
+ module MobileCenter
3
+ VERSION = "0.1.0"
4
+ end
5
+ end
metadata ADDED
@@ -0,0 +1,133 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-mobile_center
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Microsoft Corporation
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-05-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pry
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rspec
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rubocop
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: fastlane
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: 2.28.9
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 2.28.9
97
+ description:
98
+ email:
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - LICENSE
104
+ - README.md
105
+ - lib/fastlane/plugin/mobile_center.rb
106
+ - lib/fastlane/plugin/mobile_center/actions/mobile_center_upload_action.rb
107
+ - lib/fastlane/plugin/mobile_center/helper/mobile_center_helper.rb
108
+ - lib/fastlane/plugin/mobile_center/version.rb
109
+ homepage:
110
+ licenses:
111
+ - MIT
112
+ metadata: {}
113
+ post_install_message:
114
+ rdoc_options: []
115
+ require_paths:
116
+ - lib
117
+ required_ruby_version: !ruby/object:Gem::Requirement
118
+ requirements:
119
+ - - ">="
120
+ - !ruby/object:Gem::Version
121
+ version: '0'
122
+ required_rubygems_version: !ruby/object:Gem::Requirement
123
+ requirements:
124
+ - - ">="
125
+ - !ruby/object:Gem::Version
126
+ version: '0'
127
+ requirements: []
128
+ rubyforge_project:
129
+ rubygems_version: 2.6.8
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Fastlane plugin for Mobile Center
133
+ test_files: []