fastlane-plugin-flurry 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: 6726264c683f78322aabc7ba6bf043f992991424
4
+ data.tar.gz: dbde003704f3d7a085bf1e96c773fed7eea20ee2
5
+ SHA512:
6
+ metadata.gz: cd823b9d4062b281ec3768131c0558ec9ab0636da5a09fc7ee1f01391bf7c2e37931f766f6c33c8aed12726106e34d639f6c1537d494b09e97ae01d0cc4dbd89
7
+ data.tar.gz: 017cb8cbc9f5cf6b136c37a78f68a1af87f4174dd7d1577d09ed5e7defedd1fcc144e52bf551521e369cacd3d8c80e49167f1c3f36d98d2ca7f6bc66cecf1c04
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Yahoo Inc.
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,70 @@
1
+ # flurry plugin
2
+
3
+ [![fastlane Plugin Badge](https://rawcdn.githack.com/fastlane/fastlane/master/fastlane/assets/plugin-badge.svg)](https://rubygems.org/gems/fastlane-plugin-flurry)
4
+
5
+ ## Getting Started
6
+
7
+ This project is a [fastlane](https://github.com/fastlane/fastlane) plugin. To get started with `fastlane-plugin-flurry`, add it to your project by running:
8
+
9
+ ```bash
10
+ fastlane add_plugin flurry
11
+ ```
12
+
13
+ ## About flurry
14
+
15
+ This action allows you to upload symbolication files to Flurry.
16
+
17
+ ```ruby
18
+ flurry_upload_dsym(
19
+ api_key: '...',
20
+ auth_token: '...',
21
+ dsym_path: './Example.app.dSYM.zip'
22
+ )
23
+ ```
24
+
25
+ The following environment variables may be used in place of parameters: `FLURRY_API_KEY`, `FLURRY_AUTH_TOKEN`, and `FLURRY_DSYM_PATH`.
26
+
27
+ ## Example Fastfile
28
+ ```
29
+ fastlane_version "1.108.0"
30
+
31
+ default_platform :ios
32
+
33
+ platform :ios do
34
+
35
+ ENV['FLURRY_AUTH_TOKEN'] = '<Put-Token-Here>'
36
+ ENV['FLURRY_API_KEY'] = '<Put-API-Key-Here>' # Use your own API Key Here
37
+
38
+ desc "Build for non-bitcode enabled apps. Includes uploading dSYMs"
39
+ lane :build do
40
+ cert
41
+ sigh
42
+ gym(scheme: "AppName")
43
+ flurry_upload_dsym
44
+ clean_build_artifacts
45
+ end
46
+
47
+ desc "Upload dSYMs for bitcode enabled apps"
48
+ lane :upload_symbols do
49
+ download_dsyms
50
+ flurry_upload_dsym
51
+ clean_build_artifacts
52
+ end
53
+ end
54
+ ```
55
+
56
+ ## Issues and Feedback
57
+
58
+ For any other issues and feedback about this plugin, please submit it to this repository.
59
+
60
+ ## Troubleshooting
61
+
62
+ If you have trouble using plugins, check out the [Plugins Troubleshooting](https://github.com/fastlane/fastlane/blob/master/fastlane/docs/PluginsTroubleshooting.md) doc in the main `fastlane` repo.
63
+
64
+ ## Using `fastlane` Plugins
65
+
66
+ For more information about how the `fastlane` plugin system works, check out the [Plugins documentation](https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Plugins.md).
67
+
68
+ ## About `fastlane`
69
+
70
+ `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).
@@ -0,0 +1,20 @@
1
+ # Created by Akash Duseja 11/16/2016
2
+ # Copyright (c) 2016 Yahoo, Inc.
3
+ # Licensed under the terms of the MIT License. See LICENSE file in the project root.
4
+
5
+ require 'fastlane/plugin/flurry/version'
6
+
7
+ module Fastlane
8
+ module Flurry
9
+ # Return all .rb files inside the "actions" and "helper" directory
10
+ def self.all_classes
11
+ Dir[File.expand_path('**/{actions,helper}/*.rb', File.dirname(__FILE__))]
12
+ end
13
+ end
14
+ end
15
+
16
+ # By default we want to import all available actions and helpers
17
+ # A plugin can contain any number of actions and plugins
18
+ Fastlane::Flurry.all_classes.each do |current|
19
+ require current
20
+ end
@@ -0,0 +1,216 @@
1
+ # Created by Akash Duseja 11/16/2016
2
+ # Copyright (c) 2016 Yahoo, Inc.
3
+ # Licensed under the terms of the MIT License. See LICENSE file in the project root.
4
+
5
+ module Fastlane
6
+ module Actions
7
+ class FlurryUploadDsymAction < Action
8
+
9
+ METADATA_BASE_URL = 'https://crash-metadata.flurry.com/pulse/v1'
10
+ UPLOAD_BASE_URL = 'https://upload.flurry.com/upload/v1'
11
+
12
+ def self.run(params)
13
+ Actions.verify_gem!('rest-client')
14
+ require 'rest-client'
15
+ require 'rubygems/package'
16
+
17
+ # Params - API
18
+ api_key = params[:api_key]
19
+ auth_token = params[:auth_token]
20
+ timeout_in_s = params[:timeout_in_s]
21
+ # Params - dSYM
22
+ dsym_path = params[:dsym_path]
23
+ project_id = find_project(api_key, auth_token)
24
+
25
+ if dsym_path.end_with?('.zip')
26
+ UI.message("Extracting '#{dsym_path}'...")
27
+ dsym_path = unzip_file(dsym_path)
28
+ end
29
+
30
+ tar_zip_file = tar_zip_file(dsym_path)
31
+ upload_id = create_upload(tar_zip_file.size, project_id, auth_token)
32
+ send_to_upload_service(tar_zip_file.path, project_id, upload_id, auth_token)
33
+ check_upload_status(project_id, upload_id, auth_token, timeout_in_s)
34
+ UI.message "Successfully Uploaded the provided dSYMs to Flurry."
35
+ end
36
+
37
+ def self.unzip_file (file)
38
+ dir = Dir.mktmpdir
39
+ Zip::File.open(file) do |zip_file|
40
+ zip_file.each do |f|
41
+ f_path=File.join(dir, f.name)
42
+ FileUtils.mkdir_p(File.dirname(f_path))
43
+ zip_file.extract(f, f_path) unless File.exist?(f_path)
44
+ end
45
+ end
46
+ dir
47
+ end
48
+
49
+ def self.find_project(api_key, auth_token)
50
+ begin
51
+ response = RestClient.get "#{METADATA_BASE_URL}/project?fields[project]=apiKey&filter[project.apiKey]=#{api_key}", get_metadata_headers(auth_token)
52
+ rescue => e
53
+ UI.user_error! "Invalid/Expired Auth Token Provided. Please obtain a new token and try again."
54
+ end
55
+
56
+ json_response_data = JSON.parse(response.body)["data"]
57
+ if json_response_data.count == 0
58
+ UI.user_error! "No project found for the provided API Key. Make sure the provided API key is valid and the user has access to that project."
59
+ end
60
+ return json_response_data[0]["id"]
61
+ end
62
+
63
+ def self.tar_zip_file(dsym_path)
64
+ tar_zip_file = Tempfile.new(['temp','.tar.gz'])
65
+ io = gzip_file(tar_file(dsym_path))
66
+ tar_zip_file.binmode
67
+ tar_zip_file.write io.read
68
+ tar_zip_file.close
69
+ return tar_zip_file
70
+ end
71
+
72
+ def self.tar_file(dsym_path)
73
+ tarfile = StringIO.new("")
74
+ Gem::Package::TarWriter.new(tarfile) do |tar|
75
+ Dir[File.join(dsym_path, "**/*")].each do |file|
76
+ mode = File.stat(file).mode
77
+ relative_file = file.sub /^#{Regexp::escape dsym_path}\/?/, ''
78
+
79
+ if File.directory?(file)
80
+ tar.mkdir relative_file, mode
81
+ else
82
+ tar.add_file relative_file, mode do |tf|
83
+ File.open(file, "rb") { |f| tf.write f.read }
84
+ end
85
+ end
86
+ end
87
+ end
88
+ tarfile.rewind
89
+ return tarfile
90
+ end
91
+
92
+ def self.gzip_file(tar_file)
93
+ gz = StringIO.new("")
94
+ z = Zlib::GzipWriter.new(gz)
95
+ z.write tar_file.string
96
+ z.close
97
+ StringIO.new gz.string
98
+ end
99
+
100
+ def self.create_upload(size, project_id, auth_token)
101
+ payload = "{\"data\": {\"type\": \"upload\", \"attributes\": {\"uploadType\": \"IOS\", \"contentLength\": #{size}}, \"relationships\": {\"project\": {\"data\": {\"id\": #{project_id},\"type\": \"project\"}}}}}"
102
+ response = RestClient.post "#{METADATA_BASE_URL}/project/#{project_id}/uploads", payload, get_metadata_headers(auth_token)
103
+ if response.code != 201
104
+ UI.user_error! "Failed to create Upload with Status Code: #{response.code}"
105
+ end
106
+ jsonResponse = JSON.parse(response.body)
107
+ return jsonResponse["data"]["id"]
108
+ end
109
+
110
+ def self.send_to_upload_service(file_path, project_id, upload_id, auth_token)
111
+ file = File.new(file_path, 'rb')
112
+ file_size = file.size.to_i
113
+ UI.message "Uploading..."
114
+ response = RestClient.post "#{UPLOAD_BASE_URL}/upload/#{project_id}/#{upload_id}", file, get_upload_headers(file_size, auth_token)
115
+ if response.code != 201 && response.code != 202
116
+ UI.user_error! "Failed to send files to upload service with Status Code: #{response.code}"
117
+ end
118
+ end
119
+
120
+ def self.check_upload_status(project_id, upload_id, auth_token, max_duration_seconds)
121
+ time_elapsed = 0
122
+ while time_elapsed < max_duration_seconds.to_i do
123
+ response = RestClient.get "#{METADATA_BASE_URL}/project/#{project_id}/uploads/#{upload_id}?fields[upload]=uploadStatus,failureReason", get_metadata_headers(auth_token)
124
+ json_response = JSON.parse(response.body)
125
+ upload_status = json_response["data"]["attributes"]["uploadStatus"]
126
+ if upload_status == "COMPLETED"
127
+ return
128
+ elsif upload_status == "FAILED"
129
+ reason = json_response["data"]["attributes"]["failureReason"]
130
+ UI.user_error! "Failed to upload the provided dSYMs to Flurry with the following reason: #{reason}"
131
+ end
132
+ sleep 2
133
+ time_elapsed += 2
134
+ end
135
+ UI.user_error! "Timed out after #{time_elapsed} seconds while uploading the provided dSYMs to Flurry"
136
+ end
137
+
138
+ def self.get_metadata_headers(auth_token)
139
+ return {:Authorization => "Bearer #{auth_token}", :accept => 'application/vnd.api+json', :content_type => 'application/vnd.api+json'}
140
+ end
141
+
142
+ def self.get_upload_headers(size, auth_token)
143
+ range_header = 'bytes 0-' + (size - 1).to_s
144
+ return {:content_type => 'application/octet-stream', :Range => range_header, :Authorization => "Bearer #{auth_token}"}
145
+ end
146
+
147
+ #####################################################
148
+ # @!group Documentation
149
+ #####################################################
150
+
151
+ def self.description
152
+ "Upload dSYM symbolication files to Flurry"
153
+ end
154
+
155
+ def self.details
156
+ [
157
+ "This action allows you to upload symbolication files to Flurry.",
158
+ "It's extra useful if you use it to download the latest dSYM files from Apple when you",
159
+ "use Bitcode"
160
+ ].join(" ")
161
+ end
162
+
163
+ def self.available_options
164
+ [
165
+ FastlaneCore::ConfigItem.new(key: :api_key,
166
+ env_name: 'FLURRY_API_KEY',
167
+ description: 'Flurry API Key',
168
+ verify_block: proc do |value|
169
+ UI.user_error!("No API Key for Flurry given, pass using `api_key: 'apiKey'`") if value.to_s.length == 0
170
+ end),
171
+ FastlaneCore::ConfigItem.new(key: :auth_token,
172
+ env_name: 'FLURRY_AUTH_TOKEN',
173
+ description: 'Flurry Auth Token',
174
+ verify_block: proc do |value|
175
+ UI.user_error!("No Auth Token for Flurry given, pass using `auth_token: 'token'`") if value.to_s.length == 0
176
+ end),
177
+ FastlaneCore::ConfigItem.new(key: :dsym_path,
178
+ env_name: 'FLURRY_DSYM_PATH',
179
+ description: 'Path to the DSYM file to upload',
180
+ default_value: Actions.lane_context[SharedValues::DSYM_OUTPUT_PATH],
181
+ verify_block: proc do |value|
182
+ UI.user_error!("Couldn't find file at path '#{File.expand_path(value)}'") unless File.exist?(value)
183
+ UI.user_error!('Symbolication file needs to be dSYM or zip') unless value.end_with?('.dSYM', '.zip')
184
+ end),
185
+ FastlaneCore::ConfigItem.new(key: :timeout_in_s,
186
+ env_name: 'TIMEOUT_IN_S',
187
+ description: 'Upload Timeout in Seconds',
188
+ optional: true,
189
+ default_value: '600')
190
+ ]
191
+ end
192
+
193
+ def self.authors
194
+ ["duseja2"]
195
+ end
196
+
197
+ def self.is_supported?(platform)
198
+ platform == :ios
199
+ end
200
+
201
+ def self.example_code
202
+ [
203
+ 'flurry_upload_dsym(
204
+ api_key: "...",
205
+ auth_token: "...",
206
+ dsym_path: "./App.dSYM.zip"
207
+ )'
208
+ ]
209
+ end
210
+
211
+ def self.category
212
+ :misc
213
+ end
214
+ end
215
+ end
216
+ end
@@ -0,0 +1,16 @@
1
+ # Created by Akash Duseja 11/16/2016
2
+ # Copyright (c) 2016 Yahoo, Inc.
3
+ # Licensed under the terms of the MIT License. See LICENSE file in the project root.
4
+
5
+ module Fastlane
6
+ module Helper
7
+ class FlurryHelper
8
+ # class methods that you define here become available in your action
9
+ # as `Helper::FlurryHelper.your_method`
10
+ #
11
+ def self.show_message
12
+ UI.message("Hello from the flurry plugin helper!")
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,9 @@
1
+ # Created by Akash Duseja 11/16/2016
2
+ # Copyright (c) 2016 Yahoo, Inc.
3
+ # Licensed under the terms of the MIT License. See LICENSE file in the project root.
4
+
5
+ module Fastlane
6
+ module Flurry
7
+ VERSION = "0.1.0"
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: fastlane-plugin-flurry
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Akash Duseja
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-11-16 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: 1.108.0
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: 1.108.0
97
+ description:
98
+ email: duseja2@gmail.com
99
+ executables: []
100
+ extensions: []
101
+ extra_rdoc_files: []
102
+ files:
103
+ - LICENSE
104
+ - README.md
105
+ - lib/fastlane/plugin/flurry.rb
106
+ - lib/fastlane/plugin/flurry/actions/flurry_upload_dsym.rb
107
+ - lib/fastlane/plugin/flurry/helper/flurry_helper.rb
108
+ - lib/fastlane/plugin/flurry/version.rb
109
+ homepage: https://github.com/flurry/fastlane-plugin-flurry
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.5.1
130
+ signing_key:
131
+ specification_version: 4
132
+ summary: Upload dSYM symbolication files to Flurry
133
+ test_files: []
134
+ has_rdoc: