fastlane-plugin-dependency_check_ios_analyzer 0.3.0 → 1.0.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
  SHA256:
3
- metadata.gz: 0c616a1b00b47f1a1617d2d76d68ed0ec3c852dd7ad98063b7642701938fe1c2
4
- data.tar.gz: dfedd536f98aa734ee7b77e23c728c7159667853a061fcf22f314c2a00f8ef6d
3
+ metadata.gz: 6e345f12b5563a7925a7e3f9f68bec30cba87d77c008549f6894a2f2466933bd
4
+ data.tar.gz: d1c5771351ae90caaf6cde75684fdffdb60a63513f0ea6d6a7464c0a712cd506
5
5
  SHA512:
6
- metadata.gz: e8d13d7abadb6013b7e94d369f7c53e989b362dabe36af1992da3939cbd71b21ddec902e8582de9b72bf4eaeb892fa537d55fce3e130187786dc96a8f2481be6
7
- data.tar.gz: 8310cd0d2fba159280ebf3c52eef846ec99c1b0d2d3ab5c59c4547194478377a269d92f9e0dc99831c4c1ad9466c62581ca5ae0381baf915aed1521dc221bc3d
6
+ metadata.gz: 00d998579a40c7ff824191c74cdbdae8189c3391a9fc081517798967612d714f71470d0480835dae02bc33526d5982202e1591abf517fa79b34c7cb5124266dc
7
+ data.tar.gz: 224c59d4cb97b25fdc1dd22983a921b37eed9267bf2903feffe7bdebe8a3c8533da982345dfff2324ed17143c1e03b3f5ad3c9030c55c7f34f68fca9047bb5a6
data/README.md CHANGED
@@ -4,7 +4,7 @@
4
4
 
5
5
  ## About dependency_check_ios_analyzer
6
6
 
7
- Fastlane wrapper around the [OWASP dependency-check](https://jeremylong.github.io/DependencyCheck) [Swift Package Manager](https://jeremylong.github.io/DependencyCheck/analyzers/swift.html) and [Cocoapods](https://jeremylong.github.io/DependencyCheck/analyzers/cocoapods.html) analyzers 🚀
7
+ Fastlane wrapper around the [OWASP dependency-check](https://jeremylong.github.io/DependencyCheck) iOS analyzers ([Swift Package Manager](https://jeremylong.github.io/DependencyCheck/analyzers/swift.html) and [CocoaPods](https://jeremylong.github.io/DependencyCheck/analyzers/cocoapods.html)).
8
8
 
9
9
  This analyzer is considered experimental. While it may be useful and provide valid results more testing must be completed to ensure that the false negative/false positive rates are acceptable.
10
10
 
@@ -14,18 +14,18 @@ This analyzer is considered experimental. While it may be useful and provide val
14
14
  | ------- |---------------- | ----------- |
15
15
  | `skip_spm_analysis` | Skip analysis of `SPM` dependencies | `false` |
16
16
  | `skip_pods_analysis` | Skip analysis of `CocoaPods` dependencies | `false` |
17
- | `spm_checkouts_path` | Path to Swift Packages, if they are resolved | |
18
- | `pod_file_lock_path` | Path to the `Podfile.lock` file. **Not implemented yet** | |
17
+ | `spm_checkouts_path` | Path to Swift Packages, if resolved | |
18
+ | `pod_file_lock_path` | Path to the `Podfile.lock` file, if exists | |
19
19
  | `project_path` | Path to the directory that contains an Xcode project, workspace or package. Defaults to the `root` | |
20
20
  | `project_name` | The project's name | `DependencyCheck` |
21
- | `output_directory` | The directory in which all reports will be stored | dependency-check |
21
+ | `output_directory` | The directory in which all reports will be stored | `dependency-check` |
22
22
  | `output_types` | Comma separated list of the output types (e.g. `html`, `xml`, `csv`, `json`, `junit`, `sarif`, `all`) | `sarif` |
23
23
  | `cli_version` | Overwrite the version of `DependencyCheck` analyzer | `6.1.6` |
24
24
  | `gpg_key` | Overwrite the GPG key to verify the cryptographic integrity of the requested `cli_version` | |
25
25
  | `verbose` | The file path to write verbose logging information | |
26
- | `fail_on_cvss` | Specifies if the build should be failed if a CVSS score above a specified level is identified. Since the CVSS scores are 0-10, by default the build will never fail | |
27
- | `junit_fail_on_cvss` | Specifies the CVSS score that is considered a failure when generating the junit report | |
28
- | `keep_binary_on_exit` | Keep `DependencyCheck` binary and data on exit | |
26
+ | `fail_on_cvss` | Specifies if the build should be failed if a CVSS score above a specified level is identified. Since the CVSS scores are 0-10, by default the build will never fail | `11` |
27
+ | `junit_fail_on_cvss` | Specifies the CVSS score that is considered a failure when generating the junit report | `0` |
28
+ | `keep_binary_on_exit` | Keep `DependencyCheck` binary and data on exit | `true` |
29
29
 
30
30
  ## Requirements
31
31
 
@@ -43,8 +43,9 @@ $ fastlane add_plugin dependency_check_ios_analyzer
43
43
  ## Usage
44
44
 
45
45
  ```ruby
46
- vulnerabilities_count = dependency_check_ios_analyzer(
47
- output_types: 'HTML, JUNIT',
46
+ dependency_check_ios_analyzer(
47
+ project_name: 'SampleProject',
48
+ output_types: 'html, junit',
48
49
  fail_on_cvss: 7
49
50
  )
50
51
  ```
@@ -1,25 +1,25 @@
1
1
  require 'fastlane_core/ui/ui'
2
2
  require 'fastlane/action'
3
+ require_relative '../helper/configuration_helper'
3
4
  require_relative '../helper/analyzer_helper'
4
- require_relative '../helper/pods_helper'
5
- require_relative '../helper/spm_helper'
6
5
 
7
6
  module Fastlane
8
7
  module Actions
9
8
  class DependencyCheckIosAnalyzerAction < Action
10
9
  def self.run(params)
11
- params[:output_types] = Helper::AnalyzerHelper.parse_output_types(params[:output_types])
12
- bin_path = Helper::AnalyzerHelper.install(params)
13
- @success = Helper::SpmHelper.analize(bin_path: bin_path, params: params)
14
- @vulnerabilities = Helper::AnalyzerHelper.parse_report("#{params[:output_directory]}/SPM/report/*.sarif")
15
- on_exit(params)
10
+ params[:output_types] = Helper::ConfigurationHelper.parse_output_types(params[:output_types])
11
+ bin_path = Helper::ConfigurationHelper.install(params)
12
+
13
+ spm_analysis = Helper::AnalyzerHelper.analize_packages(bin_path: bin_path, params: params)
14
+ pods_analysis = Helper::AnalyzerHelper.analize_pods(bin_path: bin_path, params: params)
15
+
16
+ on_exit(params: params, result: (spm_analysis && pods_analysis))
16
17
  end
17
18
 
18
- def self.on_exit(params)
19
- Helper::AnalyzerHelper.clean_up(params)
20
- say_goodbye = "🦠 There are #{@vulnerabilities} potential vulnerabilities. " \
21
- 'Check out the report for further investigation.'
22
- @success ? UI.important(say_goodbye) : UI.crash!(say_goodbye)
19
+ def self.on_exit(params:, result:)
20
+ Helper::ConfigurationHelper.clean_up(params)
21
+ say_goodbye = '✨ Check out the report for further investigation.'
22
+ result ? UI.important(say_goodbye) : UI.user_error!(say_goodbye)
23
23
  end
24
24
 
25
25
  #####################################################
@@ -27,7 +27,7 @@ module Fastlane
27
27
  #####################################################
28
28
 
29
29
  def self.description
30
- 'Fastlane wrapper around the OWASP dependency-check Swift Package Manager and Cocoapods analyzers.'
30
+ 'Fastlane wrapper around the OWASP dependency-check iOS analyzers (Swift Package Manager and CocoaPods).'
31
31
  end
32
32
 
33
33
  def self.authors
@@ -36,19 +36,14 @@ module Fastlane
36
36
 
37
37
  def self.example_code
38
38
  [
39
- vulnerabilities_count = dependency_check_ios_analyzer(
39
+ dependency_check_ios_analyzer(
40
40
  project_name: 'SampleProject',
41
- skip_pods_analysis: true,
42
41
  output_types: 'html, junit',
43
- fail_on_cvss: 7
42
+ fail_on_cvss: 3
44
43
  )
45
44
  ]
46
45
  end
47
46
 
48
- def self.return_value
49
- @vulnerabilities
50
- end
51
-
52
47
  def self.available_options
53
48
  [
54
49
  FastlaneCore::ConfigItem.new(
@@ -69,14 +64,14 @@ module Fastlane
69
64
  ),
70
65
  FastlaneCore::ConfigItem.new(
71
66
  key: :spm_checkouts_path,
72
- description: 'Path to Swift Packages, if they are resolved',
67
+ description: 'Path to Swift Packages, if resolved',
73
68
  optional: true,
74
69
  is_string: true,
75
70
  type: String
76
71
  ),
77
72
  FastlaneCore::ConfigItem.new(
78
73
  key: :pod_file_lock_path,
79
- description: 'Path to the Podfile.lock file',
74
+ description: 'Path to the Podfile.lock file, if exists',
80
75
  optional: true,
81
76
  is_string: true,
82
77
  type: String
@@ -1,90 +1,111 @@
1
- require 'json'
2
- require 'curb'
3
- require 'zip'
4
-
5
1
  module Fastlane
6
2
  UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
7
3
 
8
4
  module Helper
9
5
  class AnalyzerHelper
10
- def self.install(params)
11
- repo = 'https://github.com/jeremylong/DependencyCheck'
12
- name = 'dependency-check'
13
- version = params[:cli_version] ? params[:cli_version] : '6.1.6'
14
- gpg_key = params[:gpg_key] ? params[:gpg_key] : 'F9514E84AE3708288374BBBE097586CFEA37F9A6'
15
- base_url = "#{repo}/releases/download/v#{version}/#{name}-#{version}-release"
16
- bin_path = "#{params[:output_directory]}/#{name}/bin/#{name}.sh"
17
- zip_path = "#{params[:output_directory]}/#{name}.zip"
18
- asc_path = "#{zip_path}.asc"
19
-
20
- unless File.exist?(bin_path)
21
- FileUtils.mkdir_p(params[:output_directory])
22
-
23
- unless File.exist?(zip_path)
24
- zip_url = "#{base_url}.zip"
25
- UI.message("🚀 Downloading DependencyCheck: #{zip_url}")
26
- curl = Curl.get(zip_url) { |curl| curl.follow_location = true }
27
- File.open(zip_path, 'w+') { |f| f.write(curl.body_str) }
28
- end
29
-
30
- asc_url = "#{base_url}.zip.asc"
31
- UI.message("🚀 Downloading associated GPG signature file: #{asc_url}")
32
- curl = Curl.get(asc_url) { |curl| curl.follow_location = true }
33
- File.open(asc_path, 'w+') { |f| f.write(curl.body_str) }
34
-
35
- verify_cryptographic_integrity(asc_path: asc_path, gpg_key: gpg_key)
36
-
37
- unzip(file: zip_path, params: params)
38
-
39
- FileUtils.rm_rf(zip_path)
40
- FileUtils.rm_rf(asc_path)
41
- end
6
+ def self.analize_packages(bin_path:, params:)
7
+ return true if params[:skip_spm_analysis]
8
+
9
+ path_to_report = "#{params[:output_directory]}/SwiftPackages"
10
+ clean_reports_folder(path_to_report)
11
+ params[:spm_checkouts_path] = resolve_package_dependencies(params)
12
+
13
+ check_dependencies(
14
+ params: params,
15
+ bin_path: bin_path,
16
+ path_to_report: path_to_report,
17
+ destination: params[:spm_checkouts_path]
18
+ )
19
+ end
20
+
21
+ def self.analize_pods(bin_path:, params:)
22
+ return true if params[:skip_pods_analysis]
42
23
 
43
- bin_path
24
+ path_to_report = "#{params[:output_directory]}/CocoaPods"
25
+ clean_reports_folder(path_to_report)
26
+ params[:pod_file_lock_path] = resolve_pods_dependencies(params)
27
+
28
+ check_dependencies(
29
+ params: params,
30
+ bin_path: bin_path,
31
+ path_to_report: path_to_report,
32
+ destination: params[:pod_file_lock_path]
33
+ )
44
34
  end
45
35
 
46
- def self.parse_output_types(output_types)
47
- list = output_types.delete(' ').split(',')
48
- list << 'sarif' unless list.include?('sarif')
49
- report_types = ''
50
- list.each { |output_type| report_types += " --format #{output_type.upcase}" }
36
+ private
51
37
 
52
- UI.message("🎥 Output types: #{list}")
53
- report_types
38
+ def self.clean_reports_folder(path)
39
+ FileUtils.rm_rf(path)
40
+ FileUtils.mkdir_p(path)
54
41
  end
55
42
 
56
- def self.parse_report(report)
57
- if Dir[report].empty?
58
- UI.crash!('Something went wrong. There is no report to analyze. Consider reporting a bug.')
43
+ def self.check_dependencies(params:, bin_path:, path_to_report:, destination:)
44
+ # Specify verbose output
45
+ verbose = params[:verbose] ? " --log #{params[:verbose]}" : ''
46
+
47
+ # Make the script executable
48
+ Actions.sh("chmod 775 #{bin_path}")
49
+
50
+ # Execute dependency-check
51
+ begin
52
+ Actions.sh(
53
+ "#{bin_path}" \
54
+ " --enableExperimental" \
55
+ " --disableBundleAudit" \
56
+ " --prettyPrint" \
57
+ " --project #{params[:project_name]}" \
58
+ " --out #{path_to_report}/report" \
59
+ " --failOnCVSS #{params[:fail_on_cvss]}" \
60
+ " --scan #{destination}" \
61
+ "#{params[:output_types]}" \
62
+ "#{verbose}"
63
+ )
64
+ true
65
+ rescue
66
+ false
59
67
  end
68
+ end
69
+
70
+ def self.parse_the_report(report)
71
+ UI.crash!('There is no report to analyze. Consider reporting a bug.') if Dir[report].empty?
60
72
 
61
73
  JSON.parse(File.read(Dir[report].first))['runs'][0]['results'].size
62
74
  end
63
75
 
64
- def self.clean_up(params)
65
- return if params[:keep_binary_on_exit]
76
+ def self.resolve_package_dependencies(params)
77
+ return params[:spm_checkouts_path] if params[:spm_checkouts_path]
66
78
 
67
- FileUtils.rm_rf("#{params[:output_directory]}/dependency-check")
68
- end
79
+ UI.user_error!("xcodebuild not installed") if `which xcodebuild`.length.zero?
69
80
 
70
- private
81
+ checkouts_path = "#{params[:output_directory]}/SwiftPackages/checkouts"
82
+ checkouts_path = "#{Dir.pwd}/#{checkouts_path}" unless params[:output_directory].include?(Dir.pwd)
71
83
 
72
- def self.unzip(file:, params:)
73
- Zip::File.open(file) do |zip_file|
74
- zip_file.each do |f|
75
- fpath = File.join(params[:output_directory], f.name)
76
- zip_file.extract(f, fpath) unless File.exist?(fpath)
77
- end
84
+ if params[:project_path]
85
+ Actions.sh("cd #{params[:project_path]} && " \
86
+ "set -o pipefail && " \
87
+ "xcodebuild -resolvePackageDependencies -clonedSourcePackagesDirPath #{checkouts_path}")
88
+ else
89
+ Actions.sh("set -o pipefail && " \
90
+ "xcodebuild -resolvePackageDependencies -clonedSourcePackagesDirPath #{checkouts_path}")
78
91
  end
92
+
93
+ UI.message("🎉 SPM checkouts path: #{checkouts_path}")
94
+ checkouts_path
79
95
  end
80
96
 
81
- # https://jeremylong.github.io/DependencyCheck/dependency-check-cli/
82
- def self.verify_cryptographic_integrity(asc_path:, gpg_key:)
83
- UI.message("🕵️ Verifying the cryptographic integrity")
84
- # Import the GPG key used to sign all DependencyCheck releases
85
- Actions.sh("gpg --keyserver hkp://keys.gnupg.net --recv-keys #{gpg_key}")
86
- # Verify the cryptographic integrity
87
- Actions.sh("gpg --verify #{asc_path}")
97
+ def self.resolve_pods_dependencies(params)
98
+ return params[:pod_file_lock_path] if params[:pod_file_lock_path]
99
+
100
+ UI.user_error!("pod not installed") if `which pod`.length.zero?
101
+
102
+ if params[:project_path]
103
+ Actions.sh("cd #{params[:project_path]} && set -o pipefail && pod install")
104
+ else
105
+ Actions.sh("set -o pipefail && pod install")
106
+ end
107
+
108
+ params[:project_path] ? "#{params[:project_path]}/Podfile.lock" : 'Podfile.lock'
88
109
  end
89
110
  end
90
111
  end
@@ -0,0 +1,83 @@
1
+ require 'json'
2
+ require 'curb'
3
+ require 'zip'
4
+
5
+ module Fastlane
6
+ UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
7
+
8
+ module Helper
9
+ class ConfigurationHelper
10
+ def self.install(params)
11
+ repo = 'https://github.com/jeremylong/DependencyCheck'
12
+ name = 'dependency-check'
13
+ version = params[:cli_version] ? params[:cli_version] : '6.1.6'
14
+ gpg_key = params[:gpg_key] ? params[:gpg_key] : 'F9514E84AE3708288374BBBE097586CFEA37F9A6'
15
+ base_url = "#{repo}/releases/download/v#{version}/#{name}-#{version}-release"
16
+ bin_path = "#{params[:output_directory]}/#{name}/bin/#{name}.sh"
17
+ zip_path = "#{params[:output_directory]}/#{name}.zip"
18
+ asc_path = "#{zip_path}.asc"
19
+
20
+ unless File.exist?(bin_path)
21
+ FileUtils.mkdir_p(params[:output_directory])
22
+
23
+ unless File.exist?(zip_path)
24
+ zip_url = "#{base_url}.zip"
25
+ UI.message("🚀 Downloading DependencyCheck: #{zip_url}")
26
+ curl = Curl.get(zip_url) { |curl| curl.follow_location = true }
27
+ File.open(zip_path, 'w+') { |f| f.write(curl.body_str) }
28
+ end
29
+
30
+ asc_url = "#{base_url}.zip.asc"
31
+ UI.message("🚀 Downloading associated GPG signature file: #{asc_url}")
32
+ curl = Curl.get(asc_url) { |curl| curl.follow_location = true }
33
+ File.open(asc_path, 'w+') { |f| f.write(curl.body_str) }
34
+
35
+ verify_cryptographic_integrity(asc_path: asc_path, gpg_key: gpg_key)
36
+
37
+ unzip(file: zip_path, params: params)
38
+
39
+ FileUtils.rm_rf(zip_path)
40
+ FileUtils.rm_rf(asc_path)
41
+ end
42
+
43
+ bin_path
44
+ end
45
+
46
+ def self.parse_output_types(output_types)
47
+ list = output_types.delete(' ').split(',')
48
+ list << 'sarif' unless output_types =~ (/(sarif|all)/)
49
+ report_types = ''
50
+ list.each { |output_type| report_types += " --format #{output_type.upcase}" }
51
+
52
+ UI.message("🎥 Output types: #{list}")
53
+ report_types
54
+ end
55
+
56
+ def self.clean_up(params)
57
+ return if params[:keep_binary_on_exit]
58
+
59
+ FileUtils.rm_rf("#{params[:output_directory]}/dependency-check")
60
+ end
61
+
62
+ private
63
+
64
+ def self.unzip(file:, params:)
65
+ Zip::File.open(file) do |zip_file|
66
+ zip_file.each do |f|
67
+ fpath = File.join(params[:output_directory], f.name)
68
+ zip_file.extract(f, fpath) unless File.exist?(fpath)
69
+ end
70
+ end
71
+ end
72
+
73
+ # https://jeremylong.github.io/DependencyCheck/dependency-check-cli/
74
+ def self.verify_cryptographic_integrity(asc_path:, gpg_key:)
75
+ UI.message("🕵️ Verifying the cryptographic integrity")
76
+ # Import the GPG key used to sign all DependencyCheck releases
77
+ Actions.sh("gpg --keyserver hkp://keys.gnupg.net --recv-keys #{gpg_key}")
78
+ # Verify the cryptographic integrity
79
+ Actions.sh("gpg --verify #{asc_path}")
80
+ end
81
+ end
82
+ end
83
+ end
@@ -1,5 +1,5 @@
1
1
  module Fastlane
2
2
  module DependencyCheckIosAnalyzer
3
- VERSION = '0.3.0'
3
+ VERSION = '1.0.0'
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: fastlane-plugin-dependency_check_ios_analyzer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.0
4
+ version: 1.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexey Alter-Pesotskiy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-01 00:00:00.000000000 Z
11
+ date: 2021-05-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: curb
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - ">="
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: cocoapods
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: pry
43
57
  requirement: !ruby/object:Gem::Requirement
@@ -189,8 +203,7 @@ files:
189
203
  - lib/fastlane/plugin/dependency_check_ios_analyzer.rb
190
204
  - lib/fastlane/plugin/dependency_check_ios_analyzer/actions/dependency_check_ios_analyzer_action.rb
191
205
  - lib/fastlane/plugin/dependency_check_ios_analyzer/helper/analyzer_helper.rb
192
- - lib/fastlane/plugin/dependency_check_ios_analyzer/helper/pods_helper.rb
193
- - lib/fastlane/plugin/dependency_check_ios_analyzer/helper/spm_helper.rb
206
+ - lib/fastlane/plugin/dependency_check_ios_analyzer/helper/configuration_helper.rb
194
207
  - lib/fastlane/plugin/dependency_check_ios_analyzer/version.rb
195
208
  homepage: https://github.com/alteral/fastlane-plugin-dependency_check_ios_analyzer
196
209
  licenses:
@@ -214,6 +227,6 @@ requirements: []
214
227
  rubygems_version: 3.0.3
215
228
  signing_key:
216
229
  specification_version: 4
217
- summary: Fastlane wrapper around the OWASP dependency-check Swift Package Manager
218
- and Cocoapods analyzers.
230
+ summary: Fastlane wrapper around the OWASP dependency-check iOS analyzers (Swift Package
231
+ Manager and CocoaPods).
219
232
  test_files: []
@@ -1,27 +0,0 @@
1
- module Fastlane
2
- UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
3
-
4
- module Helper
5
- class PodsHelper
6
- def self.analize(params)
7
- if params[:skip_pods_analysis]
8
- UI.important("⚡ Cocoapods dependencies will NOT be analyzed.")
9
- return 0
10
- end
11
-
12
- 0 # FIXME: https://github.com/alteral/fastlane-plugin-dependency_check_ios_analyzer/issues/3
13
- end
14
-
15
- private
16
-
17
- def self.verify(params)
18
- report = "#{params[:output_directory]}/Cocoapods/*.sarif"
19
- if Dir[report].empty?
20
- UI.crash!('Something went wrong. There is no report to analyze. Consider reporting a bug.')
21
- end
22
-
23
- JSON.parse(File.read(Dir[report].first))
24
- end
25
- end
26
- end
27
- end
@@ -1,67 +0,0 @@
1
- module Fastlane
2
- UI = FastlaneCore::UI unless Fastlane.const_defined?("UI")
3
-
4
- module Helper
5
- class SpmHelper
6
- def self.analize(bin_path:, params:)
7
- if params[:skip_spm_analysis]
8
- UI.important("⚡ SPM dependencies will NOT be analyzed.")
9
- return 0
10
- end
11
-
12
- # Verify xcodebuild
13
- UI.user_error!("xcodebuild not installed") if `which xcodebuild`.length.zero?
14
-
15
- # Specify verbose output
16
- verbose = params[:verbose] ? " --log #{params[:verbose]}" : ''
17
-
18
- # Resolve package ddependencies
19
- checkouts_path = resolve_package_dependencies(params)
20
-
21
- # Make the script executable
22
- Actions.sh("chmod 775 #{bin_path}")
23
-
24
- # Execute DependencyCheck
25
- begin
26
- Actions.sh(
27
- "#{bin_path}" \
28
- " --enableExperimental" \
29
- " --disableBundleAudit" \
30
- " --prettyPrint" \
31
- " --project #{params[:project_name]}" \
32
- " --out #{params[:output_directory]}/SPM/report" \
33
- " --failOnCVSS #{params[:fail_on_cvss]}" \
34
- " --scan #{checkouts_path}" \
35
- "#{params[:output_types]}" \
36
- "#{verbose}"
37
- )
38
- rescue
39
- return false
40
- end
41
-
42
- true
43
- end
44
-
45
- private
46
-
47
- def self.resolve_package_dependencies(params)
48
- return params[:spm_checkouts_path] if params[:spm_checkouts_path]
49
-
50
- checkouts_path = "#{params[:output_directory]}/SPM/SourcePackages"
51
- checkouts_path = "#{Dir.pwd}/#{checkouts_path}" unless params[:output_directory].include?(Dir.pwd)
52
-
53
- if params[:project_path]
54
- Actions.sh("cd #{params[:project_path]} && " \
55
- "set -o pipefail && " \
56
- "xcodebuild -resolvePackageDependencies -clonedSourcePackagesDirPath #{checkouts_path}")
57
- else
58
- Actions.sh("set -o pipefail && " \
59
- "xcodebuild -resolvePackageDependencies -clonedSourcePackagesDirPath #{checkouts_path}")
60
- end
61
-
62
- UI.message("🎉 SPM checkouts path: #{checkouts_path}")
63
- checkouts_path
64
- end
65
- end
66
- end
67
- end