cocoapods-bugsnag 2.2.0 → 2.3.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
- SHA1:
3
- metadata.gz: 482f70c66ea52e9633b644d594c1c8ef9bdddbe5
4
- data.tar.gz: f4a0810109c18cf8edd07bcbda48d2d84ec37d9b
2
+ SHA256:
3
+ metadata.gz: 9bd7a73528694640aa6a5d4029fcf1cdbef07d71a0da73ab2b859272e491a8ca
4
+ data.tar.gz: 2c00d5eea8c273f5d30b2683cb04fb0bc446f17bdf2b2f6f3e6a0233bda6bb9d
5
5
  SHA512:
6
- metadata.gz: 17a00ed6b43c406eba7390a722cf06930b32780c030efc2218b4d856a8a71981994fbc3925c87d4185b1ff988c7a2631c6445e1f45328e725b71dfa69a11e5ad
7
- data.tar.gz: 8432e08a32cf59006b02fbe56fc846221544aaea895eea9c5eb3ae76d6e9d7a01dd3dd0c729028ef2b5899f8c25cbc276914ffca24bea94a34d722587d9c4e57
6
+ metadata.gz: '042861a83266e07106633d6b236fe5e3ac5271d2bacfd73bf2eb43e50388e81b7e371a7df0ee2bce2a3762f139629ef7a37a2beaa77b8cf73af2120dea75466e'
7
+ data.tar.gz: 9708b8a7b945b3e99c18df3d5768d1369f0353e83d1266fcf92b90dc2626b258140b55c58bde738fb040f1d1f4121d8fbcdbc9b906ca45c97e96d8ad5d4ecf4b
data/CHANGELOG.md CHANGED
@@ -1,5 +1,27 @@
1
1
  # Changelog
2
2
 
3
+ ## 2.3.0 (13 Sept 2022)
4
+
5
+ ### Enhancements
6
+
7
+ * The Xcode build phase is now compatible with Xcode 14's `ENABLE_USER_SCRIPT_SANDBOXING` build setting.
8
+ This requires all dSYM files to be specified in the build phase's "Input Files" list.
9
+ | [#28](https://github.com/bugsnag/cocoapods-bugsnag/pull/28)
10
+
11
+ ## 2.2.2 (17 May 2022)
12
+
13
+ ### Enhancements
14
+
15
+ * Uploading can now be skipped by setting `DISABLE_COCOAPODS_BUGSNAG=YES` via Xcode's Build Settings, `xcconfig` or `xcodebuild`.
16
+ | [#25](https://github.com/bugsnag/cocoapods-bugsnag/pull/25)
17
+
18
+ ## 2.2.1 (20 Nov 2020)
19
+
20
+ ### Bug fixes
21
+
22
+ * The Xcode build phase now specifies its dependencies for improved reliability with Xcode's new build system.
23
+ | [#20](https://github.com/bugsnag/cocoapods-bugsnag/pull/20)
24
+
3
25
  ## 2.2.0 (30 Sept 2020)
4
26
 
5
27
  ### Enhancements
data/README.md CHANGED
@@ -40,9 +40,11 @@ pod install
40
40
  Once added, uploading your dSYM files to Bugsnag will occur automatically.
41
41
 
42
42
  By default, your Bugsnag API key will either be read from the `BUGSNAG_API_KEY`
43
- environment variable or from the `:bugsnag:apiKey` (or `BugsnagAPIKey`) value in your
44
- `Info.plist`. Alternatively edit the script in the new "Upload Bugsnag dSYM" build
45
- phase in Xcode.
43
+ environment variable (add an Xcode build setting with this name to set it) or
44
+ from the `:bugsnag:apiKey` (or `BugsnagAPIKey`) value in your `Info.plist`.
45
+
46
+ Uploading can be disabled by setting `DISABLE_COCOAPODS_BUGSNAG=YES` in Xcode's
47
+ Build Settings or an `xcconfig` file, or as an argument to `xcodebuild`.
46
48
 
47
49
  ## Support
48
50
 
@@ -50,3 +52,7 @@ phase in Xcode.
50
52
  * [Search open and closed issues](https://github.com/bugsnag/cocoapods-bugsnag/issues?utf8=✓&q=is%3Aissue)
51
53
  for similar problems
52
54
  * [Open an issue](https://github.com/bugsnag/cocoapods-bugsnag/issues/new)
55
+
56
+ ## License
57
+
58
+ This module is free software released under the MIT License. See [LICENSE.txt](./LICENSE.txt) for details.
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |spec|
2
2
  spec.name = "cocoapods-bugsnag"
3
- spec.version = "2.2.0"
3
+ spec.version = "2.3.0"
4
4
  spec.homepage = "https://bugsnag.com"
5
5
  spec.description = "Configures the dSYM upload phase of your project when integrated with bugsnag."
6
6
  spec.summary = "To get meaningful stacktraces from your crashes, the Bugsnag service needs your dSYM file for your build. This plugin adds an upload phase to your project where needed."
@@ -12,11 +12,13 @@ Gem::Specification.new do |spec|
12
12
  "cocoapods-bugsnag.gemspec"
13
13
  ]
14
14
  spec.extra_rdoc_files = [ "README.md", "CHANGELOG.md" ]
15
- spec.test_files = [ "spec/cocoapods_bugsnag_spec.rb" ]
15
+ spec.test_files = [
16
+ "spec/cocoapods_bugsnag_spec.rb",
17
+ "spec/spec_helper.rb"
18
+ ]
16
19
  spec.require_paths = [ "lib" ]
17
20
  spec.license = "MIT"
18
21
 
19
22
  spec.add_dependency "cocoapods", "~> 1.0"
20
23
  spec.add_development_dependency "rake", ">= 12.3.3"
21
- spec.add_development_dependency "bacon", "~> 1.0"
22
24
  end
@@ -2,38 +2,55 @@ module Pod
2
2
  class Installer::UserProjectIntegrator::TargetIntegrator
3
3
 
4
4
  BUGSNAG_PHASE_NAME = "Upload Bugsnag dSYM"
5
+ BUGSNAG_PHASE_INPUT_PATHS = [
6
+ "${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}",
7
+ "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}"]
8
+ BUGSNAG_PHASE_SHELL_PATH = "/usr/bin/env ruby"
5
9
  BUGSNAG_PHASE_SCRIPT = <<'RUBY'
6
- api_key = nil # Insert your key here to use it directly from this script
7
-
8
- # Attempt to get the API key from an environment variable
9
- unless api_key
10
- api_key = ENV["BUGSNAG_API_KEY"]
11
-
12
- # If not present, attempt to lookup the value from the Info.plist
13
- unless api_key
14
- info_plist_path = "#{ENV["BUILT_PRODUCTS_DIR"]}/#{ENV["INFOPLIST_PATH"]}"
15
- plist_buddy_response = `/usr/libexec/PlistBuddy -c "print :bugsnag:apiKey" "#{info_plist_path}"`
16
- plist_buddy_response = `/usr/libexec/PlistBuddy -c "print :BugsnagAPIKey" "#{info_plist_path}"` if !$?.success?
17
- api_key = plist_buddy_response if $?.success?
18
- end
10
+ # Set DISABLE_COCOAPODS_BUGSNAG=YES via Xcode's Build Settings, xcconfig or xcodebuild to skip upload
11
+ if ENV['DISABLE_COCOAPODS_BUGSNAG'] == 'YES'
12
+ puts 'Skipping dSYM upload'
13
+ return
19
14
  end
20
15
 
21
- fail("No Bugsnag API key detected - add your key to your Info.plist, BUGSNAG_API_KEY environment variable or this Run Script phase") unless api_key
16
+ # Attempt to get the API key from an environment variable (or Xcode build setting)
17
+ api_key = ENV["BUGSNAG_API_KEY"]
22
18
 
23
- fork do
24
- Process.setsid
25
- STDIN.reopen("/dev/null")
26
- STDOUT.reopen("/dev/null", "a")
27
- STDERR.reopen("/dev/null", "a")
19
+ # If not present, attempt to lookup the value from the Info.plist
20
+ unless api_key
21
+ info_plist_path = "#{ENV["BUILT_PRODUCTS_DIR"]}/#{ENV["INFOPLIST_PATH"]}"
22
+ plist_buddy_response = `/usr/libexec/PlistBuddy -c "print :bugsnag:apiKey" "#{info_plist_path}"`
23
+ plist_buddy_response = `/usr/libexec/PlistBuddy -c "print :BugsnagAPIKey" "#{info_plist_path}"` if !$?.success?
24
+ api_key = plist_buddy_response if $?.success?
25
+ end
28
26
 
29
- require 'shellwords'
27
+ fail("No Bugsnag API key detected - add your key to your Info.plist or BUGSNAG_API_KEY environment variable") unless api_key
30
28
 
31
- Dir["#{ENV["DWARF_DSYM_FOLDER_PATH"]}/*/Contents/Resources/DWARF/*"].each do |dsym|
32
- curl_command = "curl --http1.1 -F dsym=@#{Shellwords.escape(dsym)} -F projectRoot=#{Shellwords.escape(ENV["PROJECT_DIR"])} "
33
- curl_command += "-F apiKey=#{Shellwords.escape(api_key)} "
34
- curl_command += "https://upload.bugsnag.com/"
35
- system(curl_command)
29
+ if ENV['ENABLE_USER_SCRIPT_SANDBOXING'] == 'YES'
30
+ count = ENV['SCRIPT_INPUT_FILE_COUNT'].to_i
31
+ abort 'error: dSYMs must be specified as build phase "Input Files" because ENABLE_USER_SCRIPT_SANDBOXING is enabled' unless count > 0
32
+ dsyms = []
33
+ for i in 0 .. count - 1
34
+ file = ENV["SCRIPT_INPUT_FILE_#{i}"]
35
+ next if file.end_with? '.plist'
36
+ if File.exist? file
37
+ dsyms.append file
38
+ else
39
+ abort "error: cannot read #{file}" unless ENV['DEBUG_INFORMATION_FORMAT'] != 'dwarf-with-dsym'
40
+ end
36
41
  end
42
+ else
43
+ dsyms = Dir["#{ENV['DWARF_DSYM_FOLDER_PATH']}/*/Contents/Resources/DWARF/*"]
44
+ end
45
+
46
+ dsyms.each do |dsym|
47
+ Process.detach Process.spawn('/usr/bin/curl', '--http1.1',
48
+ '-F', "apiKey=#{api_key}",
49
+ '-F', "dsym=@#{dsym}",
50
+ '-F', "projectRoot=#{ENV['PROJECT_DIR']}",
51
+ 'https://upload.bugsnag.com/',
52
+ %i[err out] => :close
53
+ )
37
54
  end
38
55
  RUBY
39
56
 
@@ -41,43 +58,54 @@ RUBY
41
58
  def integrate!
42
59
  integrate_without_bugsnag!
43
60
  return unless should_add_build_phase?
44
- return if bugsnag_native_targets.empty?
61
+
45
62
  UI.section("Integrating with Bugsnag") do
46
63
  add_bugsnag_upload_script_phase
47
64
  user_project.save
48
65
  end
49
- UI.puts "Added 'Upload Bugsnag dSYM' build phase"
50
66
  end
51
67
 
52
-
53
68
  def add_bugsnag_upload_script_phase
54
- bugsnag_native_targets.each do |native_target|
69
+ native_targets.each do |native_target|
55
70
  phase = native_target.shell_script_build_phases.select do |bp|
56
71
  bp.name == BUGSNAG_PHASE_NAME
57
- end.first || native_target.new_shell_script_build_phase(BUGSNAG_PHASE_NAME)
72
+ end.first || add_shell_script_build_phase(native_target, BUGSNAG_PHASE_NAME)
58
73
 
59
- phase.shell_path = "/usr/bin/env ruby"
74
+ phase.input_paths = dsym_phase_input_paths(phase)
75
+ phase.shell_path = BUGSNAG_PHASE_SHELL_PATH
60
76
  phase.shell_script = BUGSNAG_PHASE_SCRIPT
61
77
  phase.show_env_vars_in_log = '0'
62
78
  end
63
79
  end
64
80
 
81
+ def add_shell_script_build_phase(native_target, name)
82
+ UI.puts "Adding '#{name}' build phase to '#{native_target.name}'"
83
+ native_target.new_shell_script_build_phase(name)
84
+ end
85
+
86
+ def dsym_phase_input_paths(phase)
87
+ (phase.input_paths + BUGSNAG_PHASE_INPUT_PATHS + target.framework_dsym_paths).uniq
88
+ end
89
+
65
90
  def should_add_build_phase?
66
91
  has_bugsnag_dep = target.target_definition.dependencies.any? do |dep|
67
- dep.name.include?('Bugsnag')
92
+ dep.name.match?(/bugsnag/i)
68
93
  end
69
94
  uses_bugsnag_plugin = target.target_definition.podfile.plugins.key?('cocoapods-bugsnag')
70
95
  return has_bugsnag_dep && uses_bugsnag_plugin
71
96
  end
97
+ end
98
+ end
72
99
 
73
- def bugsnag_native_targets
74
- @bugsnag_native_targets ||=(
75
- native_targets.reject do |native_target|
76
- native_target.shell_script_build_phases.any? do |bp|
77
- bp.name == BUGSNAG_PHASE_NAME && bp.shell_script == BUGSNAG_PHASE_SCRIPT
78
- end
79
- end
80
- )
100
+ module Pod
101
+ class AggregateTarget
102
+ def framework_dsym_paths
103
+ return [] unless includes_frameworks?
104
+
105
+ framework_paths_by_config['Release'].map do |framework|
106
+ name = File.basename(framework.source_path, '.framework')
107
+ "#{framework.source_path}.dSYM/Contents/Resources/DWARF/#{name}"
108
+ end
81
109
  end
82
110
  end
83
111
  end
@@ -1,3 +1,128 @@
1
- require 'bacon'
1
+ # frozen_string_literal: true
2
2
 
3
+ require 'cocoapods'
4
+ require 'cocoapods_bugsnag'
5
+ require 'tmpdir'
3
6
 
7
+ # rubocop:disable Lint/MissingCopEnableDirective, Metrics/BlockLength
8
+
9
+ RSpec.describe 'cocoapods-bugsnag' do
10
+ context 'with a user project' do
11
+ around(:each) do |t|
12
+ Dir.chdir(Dir.mktmpdir) { t.run }
13
+ end
14
+
15
+ let(:config) { Pod::Config.instance }
16
+
17
+ before do
18
+ user_project = Xcodeproj::Project.new('App.xcodeproj')
19
+ Pod::Generator::AppTargetHelper.add_app_target(user_project, :osx, '10.11')
20
+ user_project.save
21
+
22
+ CLAide::Command::PluginManager.load_plugins('cocoapods')
23
+ end
24
+
25
+ it 'adds a build phase if included in Podfile' do
26
+ File.write 'Podfile', <<~RUBY
27
+ use_frameworks!
28
+ plugin 'cocoapods-bugsnag'
29
+ target 'App' do
30
+ pod 'AFNetworking'
31
+ pod 'Bugsnag'
32
+ end
33
+ RUBY
34
+
35
+ installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
36
+ installer.install!
37
+
38
+ expect(Pod::UI.output).to include "Adding 'Upload Bugsnag dSYM' build phase to 'App'"
39
+
40
+ expect(installer.aggregate_targets.flat_map(&:user_targets)).to all(satisfy do |target|
41
+ upload_phase = target.shell_script_build_phases.find { |bp| bp.name == 'Upload Bugsnag dSYM' }
42
+ expect(upload_phase.shell_path).to eq '/usr/bin/env ruby'
43
+ expect(upload_phase.shell_script).to include 'BUGSNAG_API_KEY'
44
+ expect(upload_phase.shell_script).to include 'SCRIPT_INPUT_FILE_COUNT'
45
+ expect(upload_phase.show_env_vars_in_log).to eq '0'
46
+ expect(upload_phase.input_paths).to eq %w[
47
+ ${BUILT_PRODUCTS_DIR}/${INFOPLIST_PATH}
48
+ ${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}
49
+ ${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework.dSYM/Contents/Resources/DWARF/AFNetworking
50
+ ${BUILT_PRODUCTS_DIR}/Bugsnag/Bugsnag.framework.dSYM/Contents/Resources/DWARF/Bugsnag
51
+ ]
52
+ end)
53
+ end
54
+
55
+ it 'does not remove existing input phases' do
56
+ File.write 'Podfile', <<~RUBY
57
+ use_frameworks!
58
+ plugin 'cocoapods-bugsnag'
59
+ target 'App' do
60
+ pod 'AFNetworking'
61
+ pod 'Bugsnag'
62
+ end
63
+ RUBY
64
+
65
+ installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
66
+ installer.install!
67
+
68
+ expect(Pod::UI.output).to include "Adding 'Upload Bugsnag dSYM' build phase to 'App'"
69
+ Pod::UI.output = ''.dup
70
+
71
+ File.write 'Podfile', <<~RUBY
72
+ use_frameworks!
73
+ plugin 'cocoapods-bugsnag'
74
+ target 'App' do
75
+ # AFNetworking now omitted
76
+ pod 'Bugsnag'
77
+ end
78
+ RUBY
79
+
80
+ installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
81
+ installer.install!
82
+
83
+ expect(Pod::UI.output).not_to include "Adding 'Upload Bugsnag dSYM' build phase to 'App'"
84
+
85
+ expect(installer.aggregate_targets.flat_map(&:user_targets)).to all(satisfy do |target|
86
+ upload_phase = target.shell_script_build_phases.find { |bp| bp.name == 'Upload Bugsnag dSYM' }
87
+ expect(upload_phase.input_paths).to include(
88
+ '${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework.dSYM/Contents/Resources/DWARF/AFNetworking'
89
+ )
90
+ end)
91
+ end
92
+
93
+ it 'does nothing if Bugsnag is not a dependency' do
94
+ File.write 'Podfile', <<~RUBY
95
+ plugin 'cocoapods-bugsnag'
96
+ target 'App'
97
+ RUBY
98
+
99
+ installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
100
+ installer.install!
101
+
102
+ expect(Pod::UI.output).not_to include "Adding 'Upload Bugsnag dSYM' build phase to 'App'"
103
+
104
+ expect(installer.aggregate_targets.flat_map(&:user_targets)).to all(satisfy do |target|
105
+ upload_phase = target.shell_script_build_phases.find { |bp| bp.name == 'Upload Bugsnag dSYM' }
106
+ expect(upload_phase).to be_nil
107
+ end)
108
+ end
109
+
110
+ it 'does nothing if not added as a plugin' do
111
+ File.write 'Podfile', <<~RUBY
112
+ target 'App' do
113
+ pod 'Bugsnag'
114
+ end
115
+ RUBY
116
+
117
+ installer = Pod::Installer.new(config.sandbox, config.podfile, config.lockfile)
118
+ installer.install!
119
+
120
+ expect(Pod::UI.output).not_to include "Adding 'Upload Bugsnag dSYM' build phase to 'App'"
121
+
122
+ expect(installer.aggregate_targets.flat_map(&:user_targets)).to all(satisfy do |target|
123
+ upload_phase = target.shell_script_build_phases.find { |bp| bp.name == 'Upload Bugsnag dSYM' }
124
+ expect(upload_phase).to be_nil
125
+ end)
126
+ end
127
+ end
128
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'cocoapods'
4
+
5
+ module Pod
6
+ # Disable the wrapping so the output is deterministic in the tests.
7
+ #
8
+ UI.disable_wrap = true
9
+
10
+ # Redirects the messages to an internal store.
11
+ #
12
+ module UI
13
+ class << self
14
+ attr_accessor :output, :warnings, :next_input
15
+
16
+ def puts(message = '')
17
+ @output << "#{message}\n"
18
+ end
19
+
20
+ def warn(message = '', _actions = [])
21
+ @warnings << "#{message}\n"
22
+ end
23
+
24
+ def print(message)
25
+ @output << message
26
+ end
27
+
28
+ alias gets next_input
29
+
30
+ def print_warnings; end
31
+ end
32
+ end
33
+ end
34
+
35
+ RSpec.configure do |config|
36
+ config.before(:each) do
37
+ Pod::UI.output = ''.dup
38
+ Pod::UI.warnings = ''.dup
39
+ Pod::UI.next_input = ''.dup
40
+ Pod::Config.instance = nil
41
+ end
42
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cocoapods-bugsnag
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0
4
+ version: 2.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Delisa Mason
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-09-30 00:00:00.000000000 Z
11
+ date: 2022-09-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: cocoapods
@@ -38,20 +38,6 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: 12.3.3
41
- - !ruby/object:Gem::Dependency
42
- name: bacon
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '1.0'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '1.0'
55
41
  description: Configures the dSYM upload phase of your project when integrated with
56
42
  bugsnag.
57
43
  email:
@@ -68,11 +54,12 @@ files:
68
54
  - lib/cocoapods_bugsnag.rb
69
55
  - lib/cocoapods_plugin.rb
70
56
  - spec/cocoapods_bugsnag_spec.rb
57
+ - spec/spec_helper.rb
71
58
  homepage: https://bugsnag.com
72
59
  licenses:
73
60
  - MIT
74
61
  metadata: {}
75
- post_install_message:
62
+ post_install_message:
76
63
  rdoc_options: []
77
64
  require_paths:
78
65
  - lib
@@ -87,12 +74,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
87
74
  - !ruby/object:Gem::Version
88
75
  version: '0'
89
76
  requirements: []
90
- rubyforge_project:
91
- rubygems_version: 2.6.14
92
- signing_key:
77
+ rubygems_version: 3.0.3.1
78
+ signing_key:
93
79
  specification_version: 4
94
80
  summary: To get meaningful stacktraces from your crashes, the Bugsnag service needs
95
81
  your dSYM file for your build. This plugin adds an upload phase to your project
96
82
  where needed.
97
83
  test_files:
98
84
  - spec/cocoapods_bugsnag_spec.rb
85
+ - spec/spec_helper.rb