fastlane-plugin-tpa 1.1.0 → 2.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +77 -6
- data/lib/fastlane/plugin/tpa/actions/tpa_action.rb +75 -72
- data/lib/fastlane/plugin/tpa/actions/upload_symbols_to_tpa_action.rb +164 -0
- data/lib/fastlane/plugin/tpa/helper/tpa_helper.rb +35 -5
- data/lib/fastlane/plugin/tpa/helper/upload_symbols_to_tpa_helper.rb +19 -0
- data/lib/fastlane/plugin/tpa/version.rb +1 -1
- metadata +80 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dcab66aba351a3916310f07514693588c77e6a4a
|
4
|
+
data.tar.gz: dfb508eeeec3829882097a6de72f3867cbe1cc22
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ed04e58274dc2a572adbd940749e12ff05b11a4757cb81256bec02ff95fe2aaf4ea7cdcf8092ea51cfcf3cb772ebf23eff259d4343ac186b7f2bbf6cb913dd0d
|
7
|
+
data.tar.gz: 3f6321eb3cea622ed35e9ee8d9cdc1f52e60c9b21b437d79e4ce1d62bba3f509f170a6759d8a57158ece903e7b13e75a44de0916428eac2618de36b8d319ec70
|
data/LICENSE
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
The MIT License (MIT)
|
2
2
|
|
3
|
-
Copyright (c)
|
3
|
+
Copyright (c) 2017 Morten Bøgh <morten@justabeech.com>
|
4
4
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
data/README.md
CHANGED
@@ -1,7 +1,19 @@
|
|
1
|
-
|
1
|
+
<p align="center">
|
2
|
+
<img src="docs/tpa_logo.png" />
|
3
|
+
</p>
|
2
4
|
|
5
|
+
# TPA plugin
|
3
6
|
[![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-tpa)
|
4
7
|
|
8
|
+
TPA gives you advanced user behaviour analytics, app distribution, crash analytics and more.
|
9
|
+
|
10
|
+
<p align="center">
|
11
|
+
<a href="#getting-started">Getting Started</a> |
|
12
|
+
<a href="#overview">Overview</a> |
|
13
|
+
<a href="#issues-and-feedback">Issues and Feedback</a> |
|
14
|
+
<a href="#license">License</a>
|
15
|
+
</p>
|
16
|
+
|
5
17
|
## Getting Started
|
6
18
|
|
7
19
|
This project is a [fastlane](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-tpa`, add it to your project by running:
|
@@ -10,18 +22,73 @@ This project is a [fastlane](https://github.com/fastlane/fastlane) plugin. To ge
|
|
10
22
|
fastlane add_plugin tpa
|
11
23
|
```
|
12
24
|
|
13
|
-
##
|
25
|
+
## Overview
|
26
|
+
|
27
|
+
This plugin makes interacting with TPA easy by providing you actions to upload `.ipa`, `.apk` and `.dSYM` files directly to TPA.
|
28
|
+
|
29
|
+
In particular, this plugin provides the following two actions:
|
30
|
+
|
31
|
+
- [`tpa`](#tpa): uploads either an iOS `.ipa` app together with its corresponding `dSYM` to TPA. It is also capable of uploading an Android `.apk` app to TPA.
|
32
|
+
- [`upload_symbols_to_tpa`](#upload_symbols_to_tpa): Uploads only dSYM files to TPA
|
33
|
+
|
34
|
+
### tpa
|
35
|
+
|
36
|
+
Use the `tpa` action in order to upload an app to TPA. A common building lane would look something like the following:
|
37
|
+
|
38
|
+
```ruby
|
39
|
+
desc 'Builds a beta version of the app and uploads it to TPA'
|
40
|
+
lane :beta do
|
41
|
+
build_app # Builds the app
|
42
|
+
tpa # Uploads the app and dSYM files to TPA
|
43
|
+
end
|
44
|
+
```
|
45
|
+
|
46
|
+
### upload_symbols_to_tpa
|
47
|
+
|
48
|
+
If you have bitcode enabled in your iOS app, then you will need to download the `dSYM` files from App Store Connect and upload them to TPA so that the crash reports can be symbolicated. In order to help with this process, then you can make use of the `upload_symbols_to_tpa` action.
|
49
|
+
|
50
|
+
This action should be part of the [`download_dsyms`](https://docs.fastlane.tools/actions/download_dsyms/) action which is part of Fastlane.
|
51
|
+
|
52
|
+
We recommend setting up a CI server which runs on a regular basis (for example once every night) to refresh the `dSYM` files. Such a lane could look like the following:
|
53
|
+
|
54
|
+
```ruby
|
55
|
+
desc 'Downloads the dSYM files from App Store Connect and uploads them to TPA'
|
56
|
+
lane :refresh_dsym do
|
57
|
+
download_dsyms # Download dSYM files from App Store Connect
|
58
|
+
upload_symbols_to_tpa # Upload them to TPA
|
59
|
+
clean_build_artifacts # Delete the local dSYM files
|
60
|
+
end
|
61
|
+
```
|
62
|
+
|
63
|
+
Instead of downloading all the dSYM files, then an alternative lane could look like the following:
|
64
|
+
|
65
|
+
```ruby
|
66
|
+
desc 'Downloads the dSYM files from App Store Connect and uploads them to TPA'
|
67
|
+
lane :refresh_dsym do
|
68
|
+
download_dsyms(version: 'latest') # Download dSYM files from App Store Connect
|
69
|
+
upload_symbols_to_tpa # Upload them to TPA
|
70
|
+
clean_build_artifacts # Delete the local dSYM files
|
71
|
+
end
|
72
|
+
```
|
73
|
+
|
74
|
+
## Available for `tpa.io` Domains
|
75
|
+
If you are using a managed version of TPA (for example `{your-subdomain.tpa.io}`, then feel free to use the latest version of this plugin. In your `Pluginfile` it should simply be written:
|
14
76
|
|
15
|
-
|
77
|
+
```ruby
|
78
|
+
gem 'fastlane-plugin-tpa'
|
79
|
+
```
|
80
|
+
|
81
|
+
If you do not have a `tpa.io` domain, you will need to use version 1.x.x of this plugin. You can install version 1.x.x by specifying the following in your `Pluginfile`:
|
82
|
+
|
83
|
+
```ruby
|
84
|
+
gem 'fastlane-plugin-tpa', '~>1.0'
|
85
|
+
```
|
16
86
|
|
17
|
-
**Note to author:** Add a more detailed description about this plugin here. If your plugin contains multiple actions, make sure to mention them here.
|
18
87
|
|
19
88
|
## Example
|
20
89
|
|
21
90
|
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`.
|
22
91
|
|
23
|
-
**Note to author:** Please set up a sample project to make it easy for users to explore what your plugin does. Provide everything that is necessary to try out the plugin in this project (including a sample Xcode/Android project if necessary)
|
24
|
-
|
25
92
|
## Run tests for this plugin
|
26
93
|
|
27
94
|
To run both the tests, and code style validation, run
|
@@ -50,3 +117,7 @@ For more information about how the `fastlane` plugin system works, check out the
|
|
50
117
|
## About `fastlane`
|
51
118
|
|
52
119
|
`fastlane` is the easiest way to automate building and releasing your iOS and Android apps. To learn more, check out [fastlane.tools](https://fastlane.tools).
|
120
|
+
|
121
|
+
## License
|
122
|
+
|
123
|
+
MIT
|
@@ -2,52 +2,27 @@ module Fastlane
|
|
2
2
|
module Actions
|
3
3
|
class TpaAction < Action
|
4
4
|
def self.run(params)
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
UI.
|
5
|
+
require 'rest_client'
|
6
|
+
|
7
|
+
upload_url = upload_url(params)
|
8
|
+
headers = headers(params)
|
9
|
+
body = body(params)
|
10
|
+
|
11
|
+
UI.message("Going to upload app to TPA")
|
12
|
+
UI.success("This might take a few minutes. Please don't interrupt the script.")
|
13
|
+
|
14
|
+
# Starts the upload
|
15
|
+
begin
|
16
|
+
RestClient.post(upload_url, body, headers)
|
17
|
+
rescue RestClient::ExceptionWithResponse => ex
|
18
|
+
handle_exception_response(ex)
|
19
|
+
rescue => ex
|
20
|
+
UI.crash!("Something went wrong while uploading your app to TPA: #{ex}")
|
21
21
|
else
|
22
|
-
UI.
|
22
|
+
UI.success("🎉 Your app has successfully been uploaded to TPA 🎉")
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
-
def self.upload_options(params)
|
27
|
-
app_file = app_file(params)
|
28
|
-
|
29
|
-
options = []
|
30
|
-
options << "-F app=@\"#{app_file}\""
|
31
|
-
|
32
|
-
if params[:mapping]
|
33
|
-
options << "-F mapping=@\"#{params[:mapping]}\""
|
34
|
-
end
|
35
|
-
|
36
|
-
options << "-F publish=#{params[:publish]}"
|
37
|
-
|
38
|
-
if params[:notes]
|
39
|
-
options << "-F notes=#{params[:notes]}"
|
40
|
-
end
|
41
|
-
|
42
|
-
if params[:progress_bar]
|
43
|
-
options << "--progress-bar"
|
44
|
-
end
|
45
|
-
|
46
|
-
options << "-F force=#{params[:force]}"
|
47
|
-
|
48
|
-
options
|
49
|
-
end
|
50
|
-
|
51
26
|
def self.app_file(params)
|
52
27
|
app_file = [
|
53
28
|
params[:ipa],
|
@@ -62,14 +37,35 @@ module Fastlane
|
|
62
37
|
end
|
63
38
|
|
64
39
|
def self.upload_url(params)
|
65
|
-
params[:
|
40
|
+
"#{params[:base_url]}/rest/api/v2/projects/#{params[:api_uuid]}/apps/versions/app/"
|
66
41
|
end
|
67
42
|
|
68
|
-
def self.
|
69
|
-
|
70
|
-
"
|
71
|
-
|
72
|
-
|
43
|
+
def self.headers(params)
|
44
|
+
{
|
45
|
+
:"X-API-Key" => params[:api_key]
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.body(params)
|
50
|
+
{
|
51
|
+
app: File.new(app_file(params), 'rb'),
|
52
|
+
mapping: params[:mapping],
|
53
|
+
notes: params[:notes],
|
54
|
+
publish: params[:publish],
|
55
|
+
force: params[:force]
|
56
|
+
}
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.handle_exception_response(ex)
|
60
|
+
if Fastlane::Helper::TpaHelper.valid_json?(ex.response)
|
61
|
+
res = JSON.parse(ex.response)
|
62
|
+
if res.key?("detail")
|
63
|
+
UI.crash!("Something went wrong while uploading your app to TPA: #{res['detail']}")
|
64
|
+
else
|
65
|
+
UI.crash!("Something went wrong while uploading your app to TPA: #{res}")
|
66
|
+
end
|
67
|
+
else
|
68
|
+
UI.crash!("Something went wrong while uploading your app to TPA: #{ex.response}")
|
73
69
|
end
|
74
70
|
end
|
75
71
|
|
@@ -78,12 +74,20 @@ module Fastlane
|
|
78
74
|
#####################################################
|
79
75
|
|
80
76
|
def self.description
|
81
|
-
"Upload builds to The Perfect App (
|
77
|
+
"Upload app builds to The Perfect App (tpa.io)"
|
82
78
|
end
|
83
79
|
|
84
|
-
|
85
|
-
def self.available_options
|
80
|
+
def self.details
|
86
81
|
[
|
82
|
+
"This plugin helps you to easily setup a CI/CD integration with The Perfect App. Simply",
|
83
|
+
"install this plugin and add the `tpa` command to your normal building lane. This will guide",
|
84
|
+
"you through the necessary parameters to use this plugin, which we recommend setting up as",
|
85
|
+
" as environmental to automate the whole process."
|
86
|
+
].join(" ")
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.available_options
|
90
|
+
Fastlane::Helper::TpaHelper.shared_available_options + [
|
87
91
|
FastlaneCore::ConfigItem.new(key: :ipa,
|
88
92
|
env_name: "FL_TPA_IPA",
|
89
93
|
description: "Path to your IPA file. Optional if you use the `gym` or `xcodebuild` action",
|
@@ -116,12 +120,6 @@ module Fastlane
|
|
116
120
|
verify_block: proc do |value|
|
117
121
|
# validation is done in the action
|
118
122
|
end),
|
119
|
-
FastlaneCore::ConfigItem.new(key: :upload_url,
|
120
|
-
env_name: "FL_TPA_UPLOAD_URL",
|
121
|
-
description: "TPA Upload URL",
|
122
|
-
verify_block: proc do |value|
|
123
|
-
UI.user_error!("Please pass your TPA Upload URL using `ENV['FL_TPA_UPLOAD_URL'] = 'value'`") unless value
|
124
|
-
end),
|
125
123
|
FastlaneCore::ConfigItem.new(key: :publish,
|
126
124
|
env_name: "FL_TPA_PUBLISH",
|
127
125
|
description: "Publish build upon upload",
|
@@ -135,29 +133,34 @@ module Fastlane
|
|
135
133
|
FastlaneCore::ConfigItem.new(key: :notes,
|
136
134
|
env_name: "FL_TPA_NOTES",
|
137
135
|
description: "Release notes",
|
138
|
-
optional: true),
|
139
|
-
FastlaneCore::ConfigItem.new(key: :verbose,
|
140
|
-
env_name: "FL_TPA_VERBOSE",
|
141
|
-
description: "Detailed output",
|
142
|
-
is_string: false,
|
143
|
-
default_value: false,
|
144
|
-
optional: true),
|
145
|
-
FastlaneCore::ConfigItem.new(key: :progress_bar,
|
146
|
-
env_name: "FL_TPA_PROGRESS_BAR",
|
147
|
-
description: "Show progress bar of upload",
|
148
|
-
is_string: false,
|
149
|
-
default_value: true,
|
150
136
|
optional: true)
|
151
137
|
]
|
152
138
|
end
|
153
|
-
|
139
|
+
|
140
|
+
def self.output
|
141
|
+
nil
|
142
|
+
end
|
143
|
+
|
144
|
+
def self.return_value
|
145
|
+
nil
|
146
|
+
end
|
154
147
|
|
155
148
|
def self.authors
|
156
|
-
["mbogh"]
|
149
|
+
["mbogh", "Stefan Veis Pennerup"]
|
157
150
|
end
|
158
151
|
|
159
152
|
def self.is_supported?(platform)
|
160
|
-
[:ios, :android].include?
|
153
|
+
[:ios, :android].include?(platform)
|
154
|
+
end
|
155
|
+
|
156
|
+
def self.example_code
|
157
|
+
[
|
158
|
+
'tpa'
|
159
|
+
]
|
160
|
+
end
|
161
|
+
|
162
|
+
def self.category
|
163
|
+
:beta
|
161
164
|
end
|
162
165
|
end
|
163
166
|
end
|
@@ -0,0 +1,164 @@
|
|
1
|
+
require 'fastlane/action'
|
2
|
+
require_relative '../helper/upload_symbols_to_tpa_helper'
|
3
|
+
|
4
|
+
module Fastlane
|
5
|
+
module Actions
|
6
|
+
class UploadSymbolsToTpaAction < Action
|
7
|
+
def self.run(params)
|
8
|
+
require 'digest/md5'
|
9
|
+
require 'rest_client'
|
10
|
+
|
11
|
+
# Params - dSYM
|
12
|
+
dsym_paths = []
|
13
|
+
dsym_paths << params[:dsym_path] if params[:dsym_path]
|
14
|
+
dsym_paths += Actions.lane_context[SharedValues::DSYM_PATHS] if Actions.lane_context[SharedValues::DSYM_PATHS]
|
15
|
+
|
16
|
+
if dsym_paths.count.zero?
|
17
|
+
UI.error("Couldn't find any dSYMs, please pass them using the dsym_path option")
|
18
|
+
return nil
|
19
|
+
end
|
20
|
+
|
21
|
+
# Get rid of duplicate dSYMs (which might occur when both passed and detected)
|
22
|
+
dsym_paths = dsym_paths.collect { |a| File.expand_path(a) }
|
23
|
+
dsym_paths.uniq!
|
24
|
+
|
25
|
+
# Fetches a list of dSYM files already uploaded to TPA
|
26
|
+
known_dsyms = download_known_dsyms(params)
|
27
|
+
|
28
|
+
# Handles each dSYM file
|
29
|
+
dsym_paths.each do |current_path|
|
30
|
+
if should_upload_dsym(params, known_dsyms, current_path)
|
31
|
+
upload_dsym(params, current_path)
|
32
|
+
else
|
33
|
+
UI.message("Already uploaded: '#{current_path}'")
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
UI.success("Successfully uploaded dSYM files to TPA 🎉")
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.download_known_dsyms(params)
|
41
|
+
UI.message("Downloading list of dSYMs already uploaded to TPA...")
|
42
|
+
|
43
|
+
url = "#{params[:base_url]}/rest/api/v2/projects/#{params[:api_uuid]}/apps/#{params[:app_identifier]}/symbols/"
|
44
|
+
|
45
|
+
begin
|
46
|
+
res = RestClient.get(url, { :"X-API-Key" => params[:api_key] })
|
47
|
+
result = JSON.parse(res.body)
|
48
|
+
rescue => ex
|
49
|
+
raise ex
|
50
|
+
end
|
51
|
+
return result
|
52
|
+
end
|
53
|
+
|
54
|
+
# Checks whether the given dsym path already exists in the list of known_dsyms
|
55
|
+
def self.should_upload_dsym(params, known_dsyms, path)
|
56
|
+
meta_data = Helper::UploadSymbolsToTpaHelper.parse_meta_data(path)
|
57
|
+
|
58
|
+
# Constructs the dictionary to compare
|
59
|
+
dict = {
|
60
|
+
'filename' => File.basename(path),
|
61
|
+
'version_number' => meta_data[:build],
|
62
|
+
'version_string' => meta_data[:version],
|
63
|
+
'hash' => Digest::MD5.hexdigest(File.read(path))
|
64
|
+
}
|
65
|
+
|
66
|
+
has_already_been_uploaded = known_dsyms.include?(dict)
|
67
|
+
return !has_already_been_uploaded
|
68
|
+
end
|
69
|
+
|
70
|
+
# Uploads the given dsym path to TPA
|
71
|
+
def self.upload_dsym(params, path)
|
72
|
+
UI.message("Uploading '#{path}'...")
|
73
|
+
|
74
|
+
begin
|
75
|
+
meta_data = Helper::UploadSymbolsToTpaHelper.parse_meta_data(path)
|
76
|
+
|
77
|
+
# Double checks that the app_identifier is as intended
|
78
|
+
unless meta_data[:app_identifier] == params[:app_identifier]
|
79
|
+
raise "App identifier of dSYM path does not match app identifier specified in Fastfile"
|
80
|
+
end
|
81
|
+
|
82
|
+
# Constructs the url
|
83
|
+
url = "#{params[:base_url]}/rest/api/v2/projects/#{params[:api_uuid]}/apps/#{meta_data[:app_identifier]}/versions/#{meta_data[:build]}/symbols/"
|
84
|
+
|
85
|
+
# Uploads the dSYM to TPA
|
86
|
+
RestClient.post(url, { version_string: meta_data[:version], mapping: File.new(path, 'rb') }, { :"X-API-Key" => params[:api_key] })
|
87
|
+
rescue => ex
|
88
|
+
UI.error(ex.to_s) # it fails, however we don't want to fail everything just for this
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
#####################################################
|
93
|
+
# @!group Documentation
|
94
|
+
#####################################################
|
95
|
+
|
96
|
+
def self.description
|
97
|
+
"Upload dsym files downloaded from App Store Connect directly to TPA"
|
98
|
+
end
|
99
|
+
|
100
|
+
def self.details
|
101
|
+
[
|
102
|
+
"If your app uses Bitcode, then the final dSYM files are not generated upon compile time.",
|
103
|
+
"Instead you have to go to App Store Connect and download the dSYM files after Apple has",
|
104
|
+
"processed your app. Afterwards you need to upload these files to TPA in order to allow",
|
105
|
+
"for symbolication of the crash reports. You can use this plugin to streamline and",
|
106
|
+
"automate this whole process."
|
107
|
+
].join(" ")
|
108
|
+
end
|
109
|
+
|
110
|
+
def self.available_options
|
111
|
+
Fastlane::Helper::TpaHelper.shared_available_options + [
|
112
|
+
FastlaneCore::ConfigItem.new(key: :dsym_path,
|
113
|
+
env_name: "FL_UPLOAD_SYMBOLS_TO_TPA_DSYM_PATH",
|
114
|
+
description: "Path to the dSYM zip file to upload",
|
115
|
+
default_value: ENV[SharedValues::DSYM_OUTPUT_PATH.to_s] || (Dir["./**/*.dSYM.zip"]).sort_by { |f| File.mtime(f) }.last,
|
116
|
+
default_value_dynamic: true,
|
117
|
+
optional: true,
|
118
|
+
verify_block: proc do |value|
|
119
|
+
UI.user_error!("Couldn't find file at path '#{File.expand_path(value)}'") unless File.exist?(value)
|
120
|
+
UI.user_error!("Symbolication file needs to be zip") unless value.end_with?(".zip")
|
121
|
+
end),
|
122
|
+
FastlaneCore::ConfigItem.new(key: :app_identifier,
|
123
|
+
short_option: "-a",
|
124
|
+
env_name: "FL_TPA_APP_IDENTIFIER",
|
125
|
+
description: "The bundle identifier of your app",
|
126
|
+
optional: false,
|
127
|
+
code_gen_sensitive: true,
|
128
|
+
default_value: CredentialsManager::AppfileConfig.try_fetch_value(:app_identifier),
|
129
|
+
default_value_dynamic: true)
|
130
|
+
]
|
131
|
+
end
|
132
|
+
|
133
|
+
def self.output
|
134
|
+
nil
|
135
|
+
end
|
136
|
+
|
137
|
+
def self.return_value
|
138
|
+
nil
|
139
|
+
end
|
140
|
+
|
141
|
+
def self.authors
|
142
|
+
["Stefan Veis Pennerup"]
|
143
|
+
end
|
144
|
+
|
145
|
+
def self.is_supported?(platform)
|
146
|
+
[:ios, :tvos].include?(platform)
|
147
|
+
end
|
148
|
+
|
149
|
+
def self.example_code
|
150
|
+
[
|
151
|
+
'upload_symbols_to_tpa(dsym_path: "./App.dSYM.zip")',
|
152
|
+
'download_dsyms # Download dSYM files from App Store Connect
|
153
|
+
upload_symbols_to_tpa # Upload them to TPA
|
154
|
+
clean_build_artifacts # Delete the local dSYM files
|
155
|
+
'
|
156
|
+
]
|
157
|
+
end
|
158
|
+
|
159
|
+
def self.category
|
160
|
+
:misc
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
@@ -1,11 +1,41 @@
|
|
1
1
|
module Fastlane
|
2
2
|
module Helper
|
3
3
|
class TpaHelper
|
4
|
-
#
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
4
|
+
# Specifies a list of ConfigItems that all the actions have as available options
|
5
|
+
def self.shared_available_options
|
6
|
+
[
|
7
|
+
FastlaneCore::ConfigItem.new(key: :base_url,
|
8
|
+
env_name: "FL_TPA_BASE_URL",
|
9
|
+
description: "The Base URL for your TPA",
|
10
|
+
optional: false,
|
11
|
+
verify_block: proc do |value|
|
12
|
+
UI.user_error!("The Base URL cannot be empty") if value.to_s.length.zero?
|
13
|
+
UI.user_error!("Please specify a Base URL beginning with https://") unless value.start_with?("https://")
|
14
|
+
UI.user_error!("Please specify a Base URL which ends with .tpa.io") unless value.end_with?(".tpa.io", ".tpa.io/")
|
15
|
+
end),
|
16
|
+
FastlaneCore::ConfigItem.new(key: :api_uuid,
|
17
|
+
env_name: "FL_TPA_API_UUID",
|
18
|
+
description: "The API UUID of your TPA project",
|
19
|
+
optional: false,
|
20
|
+
verify_block: proc do |value|
|
21
|
+
UI.user_error!("The API UUID cannot be empty") if value.to_s.length.zero?
|
22
|
+
end),
|
23
|
+
FastlaneCore::ConfigItem.new(key: :api_key,
|
24
|
+
env_name: "FL_TPA_API_KEY",
|
25
|
+
description: "Your API key to access the TPA REST API",
|
26
|
+
optional: false,
|
27
|
+
verify_block: proc do |value|
|
28
|
+
UI.user_error!("The API key cannot be empty") if value.to_s.length.zero?
|
29
|
+
end)
|
30
|
+
]
|
31
|
+
end
|
32
|
+
|
33
|
+
# Returns true if the given parameter can be parsed to a JSON object, false otherwise
|
34
|
+
def self.valid_json?(json)
|
35
|
+
JSON.parse(json)
|
36
|
+
return true
|
37
|
+
rescue JSON::ParserError => _
|
38
|
+
return false
|
9
39
|
end
|
10
40
|
end
|
11
41
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'fastlane_core/ui/ui'
|
2
|
+
|
3
|
+
module Fastlane
|
4
|
+
UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
|
5
|
+
|
6
|
+
module Helper
|
7
|
+
class UploadSymbolsToTpaHelper
|
8
|
+
# Extracts the app identifier, version and build number from the dSYM path
|
9
|
+
def self.parse_meta_data(path)
|
10
|
+
# Extracts the app_identifier, version and build number from the path
|
11
|
+
match_groups = File.basename(path).match("^(?<app_identifier>.+)-(?<version>.+)-(?<build>.+).dSYM.zip$")
|
12
|
+
if match_groups.nil?
|
13
|
+
raise "Failed to extract app identifier, version and build number from the #{path}"
|
14
|
+
end
|
15
|
+
return match_groups
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,43 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: fastlane-plugin-tpa
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
7
|
+
- The Perfect App
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-08-03 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rest-client
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: 2.0.2
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: 2.0.2
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: webmock
|
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'
|
13
41
|
- !ruby/object:Gem::Dependency
|
14
42
|
name: pry
|
15
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -52,6 +80,20 @@ dependencies:
|
|
52
80
|
- - ">="
|
53
81
|
- !ruby/object:Gem::Version
|
54
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rspec_junit_formatter
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
55
97
|
- !ruby/object:Gem::Dependency
|
56
98
|
name: rake
|
57
99
|
requirement: !ruby/object:Gem::Requirement
|
@@ -68,6 +110,34 @@ dependencies:
|
|
68
110
|
version: '0'
|
69
111
|
- !ruby/object:Gem::Dependency
|
70
112
|
name: rubocop
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - '='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: 0.49.1
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - '='
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: 0.49.1
|
125
|
+
- !ruby/object:Gem::Dependency
|
126
|
+
name: rubocop-require_tools
|
127
|
+
requirement: !ruby/object:Gem::Requirement
|
128
|
+
requirements:
|
129
|
+
- - ">="
|
130
|
+
- !ruby/object:Gem::Version
|
131
|
+
version: '0'
|
132
|
+
type: :development
|
133
|
+
prerelease: false
|
134
|
+
version_requirements: !ruby/object:Gem::Requirement
|
135
|
+
requirements:
|
136
|
+
- - ">="
|
137
|
+
- !ruby/object:Gem::Version
|
138
|
+
version: '0'
|
139
|
+
- !ruby/object:Gem::Dependency
|
140
|
+
name: simplecov
|
71
141
|
requirement: !ruby/object:Gem::Requirement
|
72
142
|
requirements:
|
73
143
|
- - ">="
|
@@ -86,16 +156,16 @@ dependencies:
|
|
86
156
|
requirements:
|
87
157
|
- - ">="
|
88
158
|
- !ruby/object:Gem::Version
|
89
|
-
version:
|
159
|
+
version: 2.100.1
|
90
160
|
type: :development
|
91
161
|
prerelease: false
|
92
162
|
version_requirements: !ruby/object:Gem::Requirement
|
93
163
|
requirements:
|
94
164
|
- - ">="
|
95
165
|
- !ruby/object:Gem::Version
|
96
|
-
version:
|
166
|
+
version: 2.100.1
|
97
167
|
description:
|
98
|
-
email:
|
168
|
+
email: support@theperfectapp.com
|
99
169
|
executables: []
|
100
170
|
extensions: []
|
101
171
|
extra_rdoc_files: []
|
@@ -104,9 +174,11 @@ files:
|
|
104
174
|
- README.md
|
105
175
|
- lib/fastlane/plugin/tpa.rb
|
106
176
|
- lib/fastlane/plugin/tpa/actions/tpa_action.rb
|
177
|
+
- lib/fastlane/plugin/tpa/actions/upload_symbols_to_tpa_action.rb
|
107
178
|
- lib/fastlane/plugin/tpa/helper/tpa_helper.rb
|
179
|
+
- lib/fastlane/plugin/tpa/helper/upload_symbols_to_tpa_helper.rb
|
108
180
|
- lib/fastlane/plugin/tpa/version.rb
|
109
|
-
homepage: https://github.com/
|
181
|
+
homepage: https://github.com/ThePerfectApp/fastlane-plugin-tpa
|
110
182
|
licenses:
|
111
183
|
- MIT
|
112
184
|
metadata: {}
|
@@ -126,7 +198,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
126
198
|
version: '0'
|
127
199
|
requirements: []
|
128
200
|
rubyforge_project:
|
129
|
-
rubygems_version: 2.
|
201
|
+
rubygems_version: 2.5.1
|
130
202
|
signing_key:
|
131
203
|
specification_version: 4
|
132
204
|
summary: TPA gives you advanced user behaviour analytics, app distribution, crash
|