fastlane-plugin-bugsnag 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5d3998cc286232a7f3d2ec963ed35420f020015e
4
- data.tar.gz: 57a410de55d97ed5d19ea6ce08c36ddf7520b2d0
3
+ metadata.gz: 624e98774c63f32ddf2857f3367aa6dba7af23e9
4
+ data.tar.gz: 763cac39d2c3adca9932f82c36560bd43780b5ca
5
5
  SHA512:
6
- metadata.gz: 4d43547635bd11fea2b6cfa290e6aff090f921d920fa831e94f7db8f6d0a2014e8c1c39a1021a0f01e24040179a3ba2482a895c3cd8100d81ef4c30db1951730
7
- data.tar.gz: cf8084b78c671410580d4a42f5ff5e35c91e658c51cd0edc9dd0df092bd9810871d279a7cbccc6a9da7a9cb320c5083da8309ddd77c1bb1c1cdfdaab679edae5
6
+ metadata.gz: bd3209ca6bfd1d2490d381f3826a0fd8b9887a35a77c7898db4e97657e6c470d6fb59dfb51616369fc8d1a16835cde124146f5fd5adc7496b1d9a0e2eed647e4
7
+ data.tar.gz: 39983da8947d6edf0cc60abd71bd1b1394afe9d41bed80e24b15f58b5ad772bcb5301109b9ceed6637d9147fad570659fc2771d3289a995beb058030a29f7c0f
data/bugsnag-dsym-upload CHANGED
@@ -77,6 +77,9 @@ while [[ $# -gt 0 ]]; do
77
77
  esac
78
78
  done
79
79
 
80
+ # Set IFS to ensure that file paths with spaces in get processed correctly
81
+ IFS=$'\n'
82
+
80
83
  if [[ ! -z $symbol_maps ]]; then
81
84
  if [[ ! -d $symbol_maps ]]; then
82
85
  exit_with_usage "Bitcode symbol map parameter is not a directory"
@@ -100,9 +103,6 @@ if [[ ! -d $dsym_dir ]]; then
100
103
  fi
101
104
  fi
102
105
 
103
- # Set IFS to ensure that file paths with spaces in get processed correctly
104
- IFS=$'\n'
105
-
106
106
  log_verbose "Uploading files to $upload_server"
107
107
  success_count=0
108
108
  fail_count=0
@@ -0,0 +1,300 @@
1
+ require "xmlsimple"
2
+ require "json"
3
+
4
+ module Fastlane
5
+ module Actions
6
+ class SendBuildToBugsnagAction < Action
7
+
8
+ BUILD_TOOL = "bugsnag-fastlane-plugin"
9
+
10
+ def self.run(params)
11
+ payload = {buildTool: BUILD_TOOL, sourceControl: {}}
12
+ if lane_context[:PLATFORM_NAME] == :android
13
+ payload.merge!(options_from_android_manifest(params[:config_file])) if params[:config_file]
14
+ else
15
+ payload.merge!(options_from_info_plist(params[:config_file])) if params[:config_file]
16
+ end
17
+ payload.delete(:config_file)
18
+
19
+ # Overwrite automated options with configured if set
20
+ payload[:apiKey] = params[:api_key] unless params[:api_key].nil?
21
+ payload[:appVersion] = params[:app_version] unless params[:app_version].nil?
22
+ payload[:releaseStage] = params[:release_stage] unless params[:release_stage].nil?
23
+ payload[:appVersionCode] = params[:android_version_code] unless params[:android_version_code].nil?
24
+ payload[:appBundleVersion] = params[:ios_bundle_version] unless params[:ios_bundle_version].nil?
25
+ payload[:builderName] = params[:builder]
26
+
27
+ payload[:sourceControl][:revision] = params[:revision] if params[:revision]
28
+ payload[:sourceControl][:repository] = params[:repository] if params[:repository]
29
+
30
+ payload.reject! {|k,v| v == nil || (v.is_a?(Hash) && v.empty?)}
31
+
32
+ if payload[:apiKey].nil? || !payload[:apiKey].is_a?(String)
33
+ UI.user_error! missing_api_key_message(params)
34
+ end
35
+ if payload[:appVersion].nil?
36
+ UI.user_error! missing_api_key_message(params)
37
+ end
38
+ send_notification(params[:endpoint], ::JSON.dump(payload))
39
+ end
40
+
41
+ def self.missing_api_key_message(params)
42
+ message = "A Bugsnag API key is required to release a build. "
43
+ if lane_context[:PLATFORM_NAME] == :android
44
+ if params[:config_file]
45
+ message << "Set com.bugsnag.android.API_KEY in your AndroidManifest.xml to detect API key automatically."
46
+ else
47
+ message << "Set the config_file option with the path to your AndroidManifest.xml and set com.bugsnag.android.API_KEY in it to detect API key automatically."
48
+ end
49
+ else
50
+ if params[:config_file]
51
+ message << "Set BugsnagAPIKey in your Info.plist file to detect API key automatically."
52
+ else
53
+ message << "Set the config_file option with the path to your Info.plist and set BugsnagAPIKey in it to detect API key automatically."
54
+ end
55
+ end
56
+ message
57
+ end
58
+
59
+ def self.missing_app_version_message(params)
60
+ message = "An app version must be specified release a build."
61
+ if lane_context[:PLATFORM_NAME] == :android
62
+ if params[:config_file]
63
+ message << "Set com.bugsnag.android.APP_VERSION in your AndroidManifest.xml to detect this value automatically."
64
+ else
65
+ message << "Set the config_file option with the path to your AndroidManifest.xml and set com.bugsnag.android.APP_VERSION in it to detect this value automatically."
66
+ end
67
+ else
68
+ if params[:config_file]
69
+ message << "Set the app_version option with your app version or set config_file to update the path to your Info.plist"
70
+ else
71
+ message << "Set the config_file option with the path to your Info.plist"
72
+ end
73
+ end
74
+ message
75
+ end
76
+
77
+ def self.description
78
+ "Notifies Bugsnag of a build"
79
+ end
80
+
81
+ def self.authors
82
+ ["cawllec"]
83
+ end
84
+
85
+ def self.example_code
86
+ ['send_build_to_bugsnag']
87
+ end
88
+
89
+ def self.category
90
+ :building
91
+ end
92
+
93
+ def self.return_value
94
+ nil
95
+ end
96
+
97
+ def self.details
98
+ "Notifies Bugsnag of a new build being released including app version and source control details"
99
+ end
100
+
101
+ def self.is_supported?(platform)
102
+ [:ios, :mac, :android].include?(platform)
103
+ end
104
+
105
+ def self.available_options
106
+ options = load_default_values
107
+ [
108
+ FastlaneCore::ConfigItem.new(key: :config_file,
109
+ description: "AndroidManifest.xml/Info.plist location",
110
+ optional: true,
111
+ default_value: options[:config_file]),
112
+ FastlaneCore::ConfigItem.new(key: :api_key,
113
+ description: "Bugsnag API Key",
114
+ optional: true,
115
+ default_value: options[:apiKey]),
116
+ FastlaneCore::ConfigItem.new(key: :app_version,
117
+ description: "App version being built",
118
+ optional: true,
119
+ default_value: options[:appVersion]),
120
+ FastlaneCore::ConfigItem.new(key: :android_version_code,
121
+ description: "Android app version code",
122
+ optional: true,
123
+ default_value: options[:appVersionCode]),
124
+ FastlaneCore::ConfigItem.new(key: :ios_bundle_version,
125
+ description: "iOS/macOS/tvOS bundle version",
126
+ optional: true,
127
+ default_value: options[:appBundleVersion]),
128
+ FastlaneCore::ConfigItem.new(key: :release_stage,
129
+ description: "Release stage being built, i.e. staging, production",
130
+ optional: true,
131
+ default_value: options[:releaseStage] || "production"),
132
+ FastlaneCore::ConfigItem.new(key: :builder,
133
+ description: "The name of the entity triggering the build",
134
+ optional: true,
135
+ default_value: `whoami`.chomp),
136
+ FastlaneCore::ConfigItem.new(key: :repository,
137
+ description: "The source control repository URL for this application",
138
+ optional: true,
139
+ default_value: options[:repository]),
140
+ FastlaneCore::ConfigItem.new(key: :revision,
141
+ description: "The source control revision id",
142
+ optional: true,
143
+ default_value: options[:revision]),
144
+ FastlaneCore::ConfigItem.new(key: :endpoint,
145
+ description: "Bugsnag deployment endpoint",
146
+ optional: true,
147
+ default_value: "https://build.bugsnag.com")
148
+ ]
149
+ end
150
+
151
+ private
152
+
153
+ def self.load_default_values
154
+ options = {releaseStage: "production", user: `whoami`.chomp}
155
+ if file_path = default_android_manifest_path
156
+ options.merge!(options_from_android_manifest(file_path))
157
+ build_gradle_path = Dir.glob("app/build.gradle").first
158
+ build_gradle_path ||= Dir.glob("build.gradle")
159
+ options.merge!(options_from_build_gradle(build_gradle_path)) if build_gradle_path
160
+ elsif file_path = default_info_plist_path
161
+ options.merge!(options_from_info_plist(file_path))
162
+ end
163
+ if git_opts = git_remote_options
164
+ options.merge!(git_opts)
165
+ end
166
+ options
167
+ end
168
+
169
+ def self.default_android_manifest_path
170
+ Dir.glob("./{app,}/src/main/AndroidManifest.xml").first
171
+ end
172
+
173
+ def self.default_info_plist_path
174
+ Dir.glob("./*/Info.plist").first
175
+ end
176
+
177
+ def self.options_from_info_plist file_path
178
+ plist_getter = Fastlane::Actions::GetInfoPlistValueAction
179
+ {
180
+ apiKey: plist_getter.run(path: file_path, key: "BugsnagAPIKey"),
181
+ appVersion: plist_getter.run(path: file_path, key: "CFBundleShortVersionString"),
182
+ appBundleVersion: plist_getter.run(path: file_path, key: "CFBundleVersion"),
183
+ config_file: file_path,
184
+ }
185
+ end
186
+
187
+ def self.options_from_android_manifest file_path
188
+ options = {}
189
+ begin
190
+ meta_data = parse_android_manifest_options(XmlSimple.xml_in(file_path))
191
+
192
+ options[:apiKey] = meta_data["com.bugsnag.android.API_KEY"]
193
+ options[:appVersion] = meta_data["com.bugsnag.android.APP_VERSION"]
194
+ options[:releaseStage] = meta_data["com.bugsnag.android.RELEASE_STAGE"]
195
+ rescue ArgumentError
196
+ nil
197
+ end
198
+ options[:config_file] = file_path
199
+ options
200
+ end
201
+
202
+ def self.options_from_build_gradle file_path
203
+ options = {}
204
+ begin
205
+ content = File.read(file_path)
206
+ if content =~ /versionCode (\d+)/
207
+ options[:appVersionCode] = $1
208
+ end
209
+ if content =~ /versionName \W(.*)\W[\s]*\n/
210
+ options[:appVersion] = $1
211
+ end
212
+ rescue
213
+ end
214
+ options
215
+ end
216
+
217
+ def self.git_remote_options
218
+ require "git"
219
+ begin
220
+ repo = Git.open(Dir.pwd)
221
+ origin = repo.remotes.detect {|r| r.name == "origin"}
222
+ origin = repo.remotes.first unless origin
223
+ if origin
224
+ return {
225
+ repository: origin.url,
226
+ revision: repo.revparse("HEAD"),
227
+ }
228
+ end
229
+ rescue
230
+ end
231
+ nil
232
+ end
233
+
234
+ def self.parse_android_manifest_options config_hash
235
+ map_meta_data(get_meta_data(config_hash))
236
+ end
237
+
238
+ def self.get_meta_data(object, output = [])
239
+ if object.is_a?(Array)
240
+ object.each do |item|
241
+ output = get_meta_data(item, output)
242
+ end
243
+ elsif object.is_a?(Hash)
244
+ object.each do |key, value|
245
+ if key === "meta-data"
246
+ output << value
247
+ elsif value.is_a?(Array) || value.is_a?(Hash)
248
+ output = get_meta_data(value, output)
249
+ end
250
+ end
251
+ end
252
+ output.flatten
253
+ end
254
+
255
+ def self.map_meta_data(meta_data)
256
+ output = {}
257
+ meta_data.each do |hash|
258
+ output[hash["android:name"]] = hash["android:value"]
259
+ end
260
+ output
261
+ end
262
+
263
+ def self.parse_response_body(response)
264
+ begin
265
+ JSON.load(response.body)
266
+ rescue => e
267
+ UI.user_error! "Failed to notify Bugsnag of a new build: #{e}"
268
+ end
269
+ end
270
+
271
+ def self.send_notification(url, body)
272
+ require "net/http"
273
+ uri = URI.parse(url)
274
+ http = Net::HTTP.new(uri.host, uri.port)
275
+ http.read_timeout = 15
276
+ http.open_timeout = 15
277
+
278
+ http.use_ssl = uri.scheme == "https"
279
+
280
+ uri.path == "" ? "/" : uri.path
281
+ request = Net::HTTP::Post.new(uri, {"Content-Type" => "application/json"})
282
+ request.body = body
283
+ begin
284
+ response = http.request(request)
285
+ rescue => e
286
+ UI.user_error! "Failed to notify Bugsnag of a new build: #{e}"
287
+ end
288
+ if response.code != "200"
289
+ body = parse_response_body(response)
290
+ if body and body.has_key? "errors"
291
+ errors = body["errors"].map {|error| "\n * #{error}"}.join
292
+ UI.user_error! "The following errors occurred while notifying Bugsnag:#{errors}.\n\nPlease update your lane config and retry."
293
+ else
294
+ UI.user_error! "Failed to notify Bugsnag of a new build. Please retry. HTTP status code: #{response.code}"
295
+ end
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module Bugsnag
3
- VERSION = "1.1.0"
3
+ VERSION = "1.2.0"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,15 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-bugsnag
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delisa Mason
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-05-09 00:00:00.000000000 Z
11
+ date: 2018-01-11 00:00:00.000000000 Z
12
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: xml-simple
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
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: git
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
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
@@ -103,6 +131,7 @@ files:
103
131
  - LICENSE.txt
104
132
  - bugsnag-dsym-upload
105
133
  - lib/fastlane/plugin/bugsnag.rb
134
+ - lib/fastlane/plugin/bugsnag/actions/send_build_to_bugsnag.rb
106
135
  - lib/fastlane/plugin/bugsnag/actions/upload_symbols_to_bugsnag.rb
107
136
  - lib/fastlane/plugin/bugsnag/version.rb
108
137
  - spec/bugsnag_upload_dsym_action_spec.rb