fastlane-plugin-bugsnag 1.1.0 → 1.2.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 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