dependabot-nuget 0.322.2 → 0.325.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.
Files changed (80) hide show
  1. checksums.yaml +4 -4
  2. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Program.cs +0 -4
  3. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/AnalyzeWorker.cs +1 -31
  4. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyFinder.cs +0 -3
  5. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/DependencyInfo.cs +1 -0
  6. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Analyze/VersionFinder.cs +64 -10
  7. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Clone/CloneWorker.cs +1 -1
  8. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/DependencySolver/MSBuildDependencySolver.cs +10 -4
  9. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/DiscoveryWorker.cs +4 -4
  10. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/PackagesConfigDiscovery.cs +2 -2
  11. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Discover/SdkProjectDiscovery.cs +31 -41
  12. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/ExperimentsManager.cs +3 -6
  13. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Cooldown.cs +83 -0
  14. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ApiModel/Job.cs +2 -1
  15. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/ModifiedFilesTracker.cs +9 -1
  16. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/PullRequestBodyGenerator/DetailedPullRequestBodyGenerator.cs +6 -0
  17. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/RunWorker.cs +8 -1
  18. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/CreateSecurityUpdatePullRequestHandler.cs +1 -1
  19. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/GroupUpdateAllVersionsHandler.cs +79 -67
  20. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshGroupUpdatePullRequestHandler.cs +1 -1
  21. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshSecurityUpdatePullRequestHandler.cs +1 -1
  22. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Run/UpdateHandlers/RefreshVersionUpdatePullRequestHandler.cs +1 -1
  23. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/FileWriterWorker.cs +10 -7
  24. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/FileWriters/XmlFileWriter.cs +245 -125
  25. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/LockFileUpdater.cs +4 -11
  26. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/PackageReferenceUpdater.cs +4 -5
  27. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Updater/UpdaterWorker.cs +1 -1
  28. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/DependencyConflictResolver.cs +2 -2
  29. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/MSBuildHelper.cs +14 -31
  30. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/NuGetHelper.cs +3 -5
  31. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/ProcessExtensions.cs +12 -13
  32. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core/Utilities/XmlExtensions.cs +3 -3
  33. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/AnalyzeWorkerTests.cs +78 -2
  34. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Analyze/VersionFinderTests.cs +126 -3
  35. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Clone/CloneWorkerTests.cs +14 -0
  36. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/DependencySolver/MSBuildDependencySolverTests.cs +1 -2
  37. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTestBase.cs +2 -2
  38. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.Project.cs +1 -2
  39. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/DiscoveryWorkerTests.cs +0 -6
  40. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Discover/SdkProjectDiscoveryTests.cs +2 -3
  41. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/MockNuGetPackage.cs +1 -2
  42. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/ApiModel/CooldownTests.cs +99 -0
  43. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/MiscellaneousTests.cs +168 -4
  44. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/PullRequestBodyGenerator/DetailedPullRequestBodyGeneratorTests.cs +71 -0
  45. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/SerializationTests.cs +71 -0
  46. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Run/UpdateHandlers/GroupUpdateAllVersionsHandlerTests.cs +70 -39
  47. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/FileWriterWorkerTests.cs +43 -30
  48. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/FileWriters/XmlFileWriterTests.cs +76 -3
  49. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Update/PackageReferenceUpdaterTests.cs +0 -2
  50. data/helpers/lib/NuGetUpdater/NuGetUpdater.Core.Test/Utilities/MSBuildHelperTests.cs +11 -27
  51. data/lib/dependabot/nuget.rb +3 -11
  52. metadata +8 -54
  53. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/AnalyzeCommand.cs +0 -49
  54. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/DiscoverCommand.cs +0 -60
  55. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/FrameworkCheckCommand.cs +0 -35
  56. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli/Commands/UpdateCommand.cs +0 -58
  57. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Analyze.cs +0 -380
  58. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Discover.cs +0 -557
  59. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.FrameworkCheck.cs +0 -37
  60. data/helpers/lib/NuGetUpdater/NuGetUpdater.Cli.Test/EntryPointTests.Update.cs +0 -226
  61. data/lib/dependabot/nuget/analysis/analysis_json_reader.rb +0 -65
  62. data/lib/dependabot/nuget/analysis/dependency_analysis.rb +0 -66
  63. data/lib/dependabot/nuget/cache_manager.rb +0 -29
  64. data/lib/dependabot/nuget/discovery/dependency_details.rb +0 -102
  65. data/lib/dependabot/nuget/discovery/dependency_file_discovery.rb +0 -122
  66. data/lib/dependabot/nuget/discovery/discovery_json_reader.rb +0 -266
  67. data/lib/dependabot/nuget/discovery/evaluation_details.rb +0 -63
  68. data/lib/dependabot/nuget/discovery/project_discovery.rb +0 -104
  69. data/lib/dependabot/nuget/discovery/property_details.rb +0 -43
  70. data/lib/dependabot/nuget/discovery/workspace_discovery.rb +0 -61
  71. data/lib/dependabot/nuget/file_fetcher.rb +0 -46
  72. data/lib/dependabot/nuget/file_parser.rb +0 -153
  73. data/lib/dependabot/nuget/file_updater.rb +0 -256
  74. data/lib/dependabot/nuget/language.rb +0 -98
  75. data/lib/dependabot/nuget/metadata_finder.rb +0 -197
  76. data/lib/dependabot/nuget/native_helpers.rb +0 -364
  77. data/lib/dependabot/nuget/nuget_config_credential_helpers.rb +0 -88
  78. data/lib/dependabot/nuget/package_manager.rb +0 -51
  79. data/lib/dependabot/nuget/update_checker/requirements_updater.rb +0 -105
  80. data/lib/dependabot/nuget/update_checker.rb +0 -210
@@ -1,197 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require "nokogiri"
5
- require "sorbet-runtime"
6
- require "dependabot/metadata_finders"
7
- require "dependabot/metadata_finders/base"
8
- require "dependabot/registry_client"
9
-
10
- module Dependabot
11
- module Nuget
12
- class MetadataFinder < Dependabot::MetadataFinders::Base
13
- extend T::Sig
14
-
15
- sig do
16
- override
17
- .params(
18
- dependency: Dependabot::Dependency,
19
- credentials: T::Array[Dependabot::Credential]
20
- )
21
- .void
22
- end
23
- def initialize(dependency:, credentials:)
24
- @dependency_nuspec_file = T.let(nil, T.nilable(Nokogiri::XML::Document))
25
-
26
- super
27
- end
28
-
29
- private
30
-
31
- sig { override.returns(T.nilable(Dependabot::Source)) }
32
- def look_up_source
33
- return Source.from_url(dependency_source_url) if dependency_source_url
34
-
35
- if dependency_nuspec_file
36
- src_repo = look_up_source_in_nuspec(T.must(dependency_nuspec_file))
37
- return src_repo if src_repo
38
- end
39
-
40
- # Fallback to getting source from the search result's projectUrl or licenseUrl.
41
- # GitHub Packages doesn't support getting the `.nuspec`, switch to getting
42
- # that instead once it is supported.
43
- src_repo_from_project
44
- rescue StandardError
45
- # At this point in the process the PR is ready to be posted, we tried to gather commit
46
- # and release notes, but have encountered an exception. So let's eat it since it's
47
- # better to have a PR with no info than error out.
48
- nil
49
- end
50
-
51
- sig { returns(T.nilable(Dependabot::Source)) }
52
- def src_repo_from_project
53
- source = dependency.requirements.find { |r| r.fetch(:source) }&.fetch(:source)
54
- return unless source
55
-
56
- # Query the service index e.g. https://nuget.pkg.github.com/ORG/index.json
57
- response = Dependabot::RegistryClient.get(
58
- url: source.fetch(:url),
59
- headers: { **auth_header, "Accept" => "application/json" }
60
- )
61
- return unless response.status == 200
62
-
63
- # Extract the query url e.g. https://nuget.pkg.github.com/ORG/query
64
- search_base = extract_search_url(response.body)
65
- return unless search_base
66
-
67
- response = Dependabot::RegistryClient.get(
68
- url: search_base + "?q=#{dependency.name.downcase}&prerelease=true&semVerLevel=2.0.0",
69
- headers: { **auth_header, "Accept" => "application/json" }
70
- )
71
- return unless response.status == 200
72
-
73
- # Find a projectUrl or licenseUrl that look like a source URL
74
- extract_source_repo(response.body)
75
- rescue JSON::ParserError
76
- # Ignored, this is expected for some registries that don't handle these request.
77
- end
78
-
79
- sig { params(body: String).returns(T.nilable(String)) }
80
- def extract_search_url(body)
81
- JSON.parse(body)
82
- .fetch("resources", [])
83
- .find { |r| r.fetch("@type") == "SearchQueryService" }
84
- &.fetch("@id")
85
- end
86
-
87
- sig { params(body: String).returns(T.nilable(Dependabot::Source)) }
88
- def extract_source_repo(body)
89
- JSON.parse(body).fetch("data", []).each do |search_result|
90
- next unless search_result["id"].casecmp(dependency.name).zero?
91
-
92
- if search_result.key?("projectUrl")
93
- source = Source.from_url(search_result.fetch("projectUrl"))
94
- return source if source
95
- end
96
- if search_result.key?("licenseUrl")
97
- source = Source.from_url(search_result.fetch("licenseUrl"))
98
- return source if source
99
- end
100
- end
101
- # failed to find a source URL
102
- nil
103
- end
104
-
105
- sig { params(nuspec: Nokogiri::XML::Document).returns(T.nilable(Dependabot::Source)) }
106
- def look_up_source_in_nuspec(nuspec)
107
- potential_source_urls = [
108
- nuspec.at_css("package > metadata > repository")
109
- &.attribute("url")&.value,
110
- nuspec.at_css("package > metadata > repository > url")&.content,
111
- nuspec.at_css("package > metadata > projectUrl")&.content,
112
- nuspec.at_css("package > metadata > licenseUrl")&.content
113
- ].compact
114
-
115
- source_url = potential_source_urls.find { |url| Source.from_url(url) }
116
- source_url ||= source_from_anywhere_in_nuspec(nuspec)
117
-
118
- Source.from_url(source_url)
119
- end
120
-
121
- sig { params(nuspec: Nokogiri::XML::Document).returns(T.nilable(String)) }
122
- def source_from_anywhere_in_nuspec(nuspec)
123
- github_urls = []
124
- nuspec.to_s.force_encoding(Encoding::UTF_8)
125
- .scan(Source::SOURCE_REGEX) do
126
- github_urls << Regexp.last_match.to_s
127
- end
128
-
129
- github_urls.find do |url|
130
- repo = T.must(Source.from_url(url)).repo
131
- repo.downcase.end_with?(dependency.name.downcase)
132
- end
133
- end
134
-
135
- sig { returns(T.nilable(Nokogiri::XML::Document)) }
136
- def dependency_nuspec_file
137
- return @dependency_nuspec_file unless @dependency_nuspec_file.nil?
138
-
139
- return if dependency_nuspec_url.nil?
140
-
141
- response = Dependabot::RegistryClient.get(
142
- url: T.must(dependency_nuspec_url),
143
- headers: auth_header
144
- )
145
-
146
- @dependency_nuspec_file = Nokogiri::XML(response.body)
147
- end
148
-
149
- sig { returns(T.nilable(String)) }
150
- def dependency_nuspec_url
151
- source = dependency.requirements
152
- .find { |r| r.fetch(:source) }&.fetch(:source)
153
-
154
- source.fetch(:nuspec_url) if source&.key?(:nuspec_url)
155
- end
156
-
157
- sig { returns(T.nilable(String)) }
158
- def dependency_source_url
159
- source = dependency.requirements
160
- .find { |r| r.fetch(:source) }&.fetch(:source)
161
-
162
- return unless source
163
- return source.fetch(:source_url) if source.key?(:source_url)
164
-
165
- source.fetch("source_url")
166
- end
167
-
168
- # rubocop:disable Metrics/PerceivedComplexity
169
- sig { returns(T::Hash[String, String]) }
170
- def auth_header
171
- source = dependency.requirements
172
- .find { |r| r.fetch(:source) }&.fetch(:source)
173
- url = source&.fetch(:url, nil) || source&.fetch("url")
174
-
175
- token = credentials
176
- .select { |cred| cred["type"] == "nuget_feed" }
177
- .find { |cred| cred["url"] == url }
178
- &.fetch("token", nil)
179
-
180
- return {} unless token
181
-
182
- if token.include?(":")
183
- encoded_token = Base64.encode64(token).delete("\n")
184
- { "Authorization" => "Basic #{encoded_token}" }
185
- elsif Base64.decode64(token).ascii_only? &&
186
- Base64.decode64(token).include?(":")
187
- { "Authorization" => "Basic #{token.delete("\n")}" }
188
- else
189
- { "Authorization" => "Bearer #{token}" }
190
- end
191
- end
192
- # rubocop:enable Metrics/PerceivedComplexity
193
- end
194
- end
195
- end
196
-
197
- Dependabot::MetadataFinders.register("nuget", Dependabot::Nuget::MetadataFinder)
@@ -1,364 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "shellwords"
5
- require "sorbet-runtime"
6
-
7
- require_relative "nuget_config_credential_helpers"
8
-
9
- module Dependabot
10
- module Nuget
11
- module NativeHelpers
12
- extend T::Sig
13
-
14
- sig { returns(String) }
15
- def self.job_id
16
- ENV.fetch("DEPENDABOT_JOB_ID")
17
- end
18
-
19
- sig { returns(String) }
20
- def self.native_helpers_root
21
- helpers_root = ENV.fetch("DEPENDABOT_NATIVE_HELPERS_PATH", nil)
22
- return File.join(helpers_root, "nuget") unless helpers_root.nil?
23
-
24
- File.expand_path("../../../helpers", __dir__)
25
- end
26
-
27
- sig { params(project_tfms: T::Array[String], package_tfms: T::Array[String]).returns(T::Boolean) }
28
- def self.run_nuget_framework_check(project_tfms, package_tfms)
29
- exe_path = File.join(native_helpers_root, "NuGetUpdater", "NuGetUpdater.Cli")
30
- command_parts = [
31
- exe_path,
32
- "framework-check",
33
- "--project-tfms",
34
- *project_tfms,
35
- "--package-tfms",
36
- *package_tfms
37
- ]
38
- command = Shellwords.join(command_parts)
39
-
40
- fingerprint = [
41
- exe_path,
42
- "framework-check",
43
- "--project-tfms",
44
- "<project-tfms>",
45
- "--package-tfms",
46
- "<package-tfms>"
47
- ].join(" ")
48
-
49
- puts "running NuGet updater:\n" + command
50
-
51
- output = SharedHelpers.run_shell_command(command, allow_unsafe_shell_command: true, fingerprint: fingerprint)
52
- puts output
53
-
54
- # Exit code == 0 means that all project frameworks are compatible
55
- true
56
- rescue Dependabot::SharedHelpers::HelperSubprocessFailed
57
- # Exit code != 0 means that not all project frameworks are compatible
58
- false
59
- end
60
-
61
- sig do
62
- params(
63
- job_path: String,
64
- repo_root: String,
65
- workspace_path: String,
66
- output_path: String
67
- ).returns([String, String])
68
- end
69
- def self.get_nuget_discover_tool_command(job_path:, repo_root:, workspace_path:, output_path:)
70
- exe_path = File.join(native_helpers_root, "NuGetUpdater", "NuGetUpdater.Cli")
71
- command_parts = [
72
- exe_path,
73
- "discover",
74
- "--job-id",
75
- job_id,
76
- "--job-path",
77
- job_path,
78
- "--repo-root",
79
- repo_root,
80
- "--workspace",
81
- workspace_path,
82
- "--output",
83
- output_path
84
- ].compact
85
-
86
- command = Shellwords.join(command_parts)
87
-
88
- fingerprint = [
89
- exe_path,
90
- "discover",
91
- "--job-id",
92
- "<job-id>",
93
- "--job-path",
94
- "<job-path>",
95
- "--repo-root",
96
- "<repo-root>",
97
- "--workspace",
98
- "<path-to-workspace>",
99
- "--output",
100
- "<path-to-output>"
101
- ].compact.join(" ")
102
-
103
- [command, fingerprint]
104
- end
105
-
106
- sig do
107
- params(
108
- job_path: String,
109
- repo_root: String,
110
- workspace_path: String,
111
- output_path: String,
112
- credentials: T::Array[Dependabot::Credential]
113
- ).void
114
- end
115
- def self.run_nuget_discover_tool(job_path:, repo_root:, workspace_path:, output_path:, credentials:)
116
- (command, fingerprint) = get_nuget_discover_tool_command(job_path: job_path,
117
- repo_root: repo_root,
118
- workspace_path: workspace_path,
119
- output_path: output_path)
120
-
121
- puts "running NuGet discovery:\n" + command
122
-
123
- NuGetConfigCredentialHelpers.patch_nuget_config_for_action(credentials) do
124
- output = SharedHelpers.run_shell_command(command, allow_unsafe_shell_command: true, fingerprint: fingerprint)
125
- puts output
126
- end
127
- end
128
-
129
- sig do
130
- params(job_path: String, repo_root: String, discovery_file_path: String, dependency_file_path: String,
131
- analysis_folder_path: String).returns([String, String])
132
- end
133
- def self.get_nuget_analyze_tool_command(job_path:, repo_root:, discovery_file_path:, dependency_file_path:,
134
- analysis_folder_path:)
135
- exe_path = File.join(native_helpers_root, "NuGetUpdater", "NuGetUpdater.Cli")
136
- command_parts = [
137
- exe_path,
138
- "analyze",
139
- "--job-id",
140
- job_id,
141
- "--job-path",
142
- job_path,
143
- "--repo-root",
144
- repo_root,
145
- "--discovery-file-path",
146
- discovery_file_path,
147
- "--dependency-file-path",
148
- dependency_file_path,
149
- "--analysis-folder-path",
150
- analysis_folder_path
151
- ].compact
152
-
153
- command = Shellwords.join(command_parts)
154
-
155
- fingerprint = [
156
- exe_path,
157
- "analyze",
158
- "--job-id",
159
- "<job-id>",
160
- "--job-path",
161
- "<job-path>",
162
- "--discovery-file-path",
163
- "<discovery-file-path>",
164
- "--dependency-file-path",
165
- "<dependency-file-path>",
166
- "--analysis-folder-path",
167
- "<analysis_folder_path>"
168
- ].compact.join(" ")
169
-
170
- [command, fingerprint]
171
- end
172
-
173
- sig do
174
- params(
175
- job_path: String, repo_root: String, discovery_file_path: String, dependency_file_path: String,
176
- analysis_folder_path: String, credentials: T::Array[Dependabot::Credential]
177
- ).void
178
- end
179
- def self.run_nuget_analyze_tool(job_path:, repo_root:, discovery_file_path:, dependency_file_path:,
180
- analysis_folder_path:, credentials:)
181
- (command, fingerprint) = get_nuget_analyze_tool_command(job_path: job_path,
182
- repo_root: repo_root,
183
- discovery_file_path: discovery_file_path,
184
- dependency_file_path: dependency_file_path,
185
- analysis_folder_path: analysis_folder_path)
186
-
187
- puts "running NuGet analyze:\n" + command
188
-
189
- NuGetConfigCredentialHelpers.patch_nuget_config_for_action(credentials) do
190
- output = SharedHelpers.run_shell_command(command, allow_unsafe_shell_command: true, fingerprint: fingerprint)
191
- puts output
192
- end
193
- end
194
-
195
- # rubocop:disable Metrics/MethodLength
196
- sig do
197
- params(job_path: String, repo_root: String, proj_path: String, dependency: Dependency,
198
- is_transitive: T::Boolean, result_output_path: String).returns([String, String])
199
- end
200
- def self.get_nuget_updater_tool_command(job_path:, repo_root:, proj_path:, dependency:, is_transitive:,
201
- result_output_path:)
202
- exe_path = File.join(native_helpers_root, "NuGetUpdater", "NuGetUpdater.Cli")
203
- command_parts = [
204
- exe_path,
205
- "update",
206
- "--job-id",
207
- job_id,
208
- "--job-path",
209
- job_path,
210
- "--repo-root",
211
- repo_root,
212
- "--solution-or-project",
213
- proj_path,
214
- "--dependency",
215
- dependency.name,
216
- "--new-version",
217
- dependency.version,
218
- "--previous-version",
219
- dependency.previous_version,
220
- is_transitive ? "--transitive" : nil,
221
- "--result-output-path",
222
- result_output_path
223
- ].compact
224
-
225
- command = Shellwords.join(command_parts)
226
-
227
- fingerprint = [
228
- exe_path,
229
- "update",
230
- "--job-id",
231
- "<job-id>",
232
- "--job-path",
233
- "<job-path>",
234
- "--repo-root",
235
- "<repo-root>",
236
- "--solution-or-project",
237
- "<path-to-solution-or-project>",
238
- "--dependency",
239
- "<dependency-name>",
240
- "--new-version",
241
- "<new-version>",
242
- "--previous-version",
243
- "<previous-version>",
244
- is_transitive ? "--transitive" : nil,
245
- "--result-output-path",
246
- "<result-output-path>"
247
- ].compact.join(" ")
248
-
249
- [command, fingerprint]
250
- end
251
- # rubocop:enable Metrics/MethodLength
252
-
253
- sig { returns(String) }
254
- def self.update_result_file_path
255
- File.join(Dir.tmpdir, "update-result.json")
256
- end
257
-
258
- sig do
259
- params(
260
- job_path: String,
261
- repo_root: String,
262
- proj_path: String,
263
- dependency: Dependency,
264
- is_transitive: T::Boolean,
265
- credentials: T::Array[Dependabot::Credential]
266
- ).void
267
- end
268
- def self.run_nuget_updater_tool(job_path:, repo_root:, proj_path:, dependency:, is_transitive:, credentials:)
269
- (command, fingerprint) = get_nuget_updater_tool_command(job_path: job_path, repo_root: repo_root,
270
- proj_path: proj_path, dependency: dependency,
271
- is_transitive: is_transitive,
272
- result_output_path: update_result_file_path)
273
-
274
- puts "running NuGet updater:\n" + command
275
-
276
- NuGetConfigCredentialHelpers.patch_nuget_config_for_action(credentials) do
277
- output = SharedHelpers.run_shell_command(command,
278
- allow_unsafe_shell_command: true,
279
- fingerprint: fingerprint)
280
- puts output
281
-
282
- result_contents = File.read(update_result_file_path)
283
- Dependabot.logger.info("update result: #{result_contents}")
284
- result_json = T.let(JSON.parse(result_contents), T::Hash[String, T.untyped])
285
- ensure_no_errors(result_json)
286
- end
287
- end
288
-
289
- sig { void }
290
- def self.normalize_file_names
291
- # environment variables are required and the following will generate an actionable error message if they're not
292
- _dependabot_repo_contents_path = ENV.fetch("DEPENDABOT_REPO_CONTENTS_PATH")
293
-
294
- # this environment variable is directly used
295
- dependabot_home = ENV.fetch("DEPENDABOT_HOME")
296
-
297
- command = [
298
- "pwsh",
299
- "#{dependabot_home}/dependabot-updater/bin/normalize-file-names.ps1"
300
- ].join(" ")
301
- output = SharedHelpers.run_shell_command(command)
302
- puts output
303
- end
304
-
305
- sig { void }
306
- def self.install_dotnet_sdks
307
- return unless Dependabot::Experiments.enabled?(:nuget_install_dotnet_sdks)
308
-
309
- # environment variables are required and the following will generate an actionable error message if they're not
310
- _dependabot_job_path = ENV.fetch("DEPENDABOT_JOB_PATH")
311
- _dependabot_repo_contents_path = ENV.fetch("DEPENDABOT_REPO_CONTENTS_PATH")
312
- _dotnet_install_script_path = ENV.fetch("DOTNET_INSTALL_SCRIPT_PATH")
313
- _dotnet_install_dir = ENV.fetch("DOTNET_INSTALL_DIR")
314
-
315
- # this environment variable is directly used
316
- dependabot_home = ENV.fetch("DEPENDABOT_HOME")
317
-
318
- command = [
319
- "pwsh",
320
- "#{dependabot_home}/dependabot-updater/bin/install-sdks.ps1"
321
- ].join(" ")
322
- output = SharedHelpers.run_shell_command(command)
323
- puts output
324
- end
325
-
326
- # rubocop:disable Metrics/AbcSize
327
- sig { params(json: T::Hash[String, T.untyped]).void }
328
- def self.ensure_no_errors(json)
329
- error = T.let(json.fetch("Error", nil), T.nilable(T::Hash[String, T.untyped]))
330
- return if error.nil?
331
-
332
- error_type = T.let(error.fetch("error-type"), String)
333
- error_details = T.let(error.fetch("error-details", {}), T::Hash[String, T.untyped])
334
-
335
- case error_type
336
- when "dependency_file_not_found"
337
- file_path = T.let(error_details.fetch("file-path"), String)
338
- message = T.let(error_details.fetch("message", nil), T.nilable(String))
339
- raise DependencyFileNotFound.new(file_path, message)
340
- when "dependency_file_not_parseable"
341
- file_path = T.let(error_details.fetch("file-path"), String)
342
- message = T.let(error_details.fetch("message", nil), T.nilable(String))
343
- raise DependencyFileNotParseable.new(file_path, message)
344
- when "dependency_not_found"
345
- source = T.let(error_details.fetch("source"), String)
346
- raise DependencyNotFound, source
347
- when "illformed_requirement"
348
- raise BadRequirementError, T.let(error_details.fetch("message"), String)
349
- when "private_source_authentication_failure"
350
- raise PrivateSourceAuthenticationFailure, T.let(error_details.fetch("source"), String)
351
- when "private_source_bad_response"
352
- raise PrivateSourceBadResponse, T.let(error_details.fetch("source"), String)
353
- when "update_not_possible"
354
- raise UpdateNotPossible, T.let(error_details.fetch("dependencies"), T::Array[String])
355
- when "unknown_error"
356
- raise DependabotError, error_details.to_json
357
- else
358
- raise "Unexpected error type from native tool: #{error_type}: #{error_details}"
359
- end
360
- end
361
- # rubocop:enable Metrics/AbcSize
362
- end
363
- end
364
- end
@@ -1,88 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "sorbet-runtime"
5
-
6
- module Dependabot
7
- module Nuget
8
- module NuGetConfigCredentialHelpers
9
- extend T::Sig
10
-
11
- sig { returns(String) }
12
- def self.user_nuget_config_path
13
- home_directory = Dir.home
14
- File.join(home_directory, ".nuget", "NuGet", "NuGet.Config")
15
- end
16
-
17
- sig { returns(String) }
18
- def self.temporary_nuget_config_path
19
- user_nuget_config_path + "_ORIGINAL"
20
- end
21
-
22
- sig { params(credentials: T::Array[Dependabot::Credential]).void }
23
- def self.add_credentials_to_nuget_config(credentials)
24
- return unless File.exist?(user_nuget_config_path)
25
-
26
- nuget_credentials = credentials.select { |cred| cred["type"] == "nuget_feed" }
27
- return if nuget_credentials.empty?
28
-
29
- File.rename(user_nuget_config_path, temporary_nuget_config_path)
30
-
31
- package_sources = [" <add key=\"nuget.org\" value=\"https://api.nuget.org/v3/index.json\" />"]
32
- package_source_credentials = []
33
- nuget_credentials.each_with_index do |c, i|
34
- source_name = "nuget_source_#{i + 1}"
35
- package_sources << " <add key=\"#{source_name}\" value=\"#{c['url']}\" />"
36
- next unless c["token"]
37
-
38
- package_source_credentials << " <#{source_name}>"
39
- package_source_credentials << " <add key=\"Username\" value=\"user\" />"
40
- package_source_credentials << " <add key=\"ClearTextPassword\" value=\"#{c['token']}\" />"
41
- package_source_credentials << " </#{source_name}>"
42
- end
43
-
44
- nuget_config = <<~NUGET_XML
45
- <?xml version="1.0" encoding="utf-8"?>
46
- <configuration>
47
- <packageSources>
48
- #{package_sources.join("\n")}
49
- </packageSources>
50
- <packageSourceCredentials>
51
- #{package_source_credentials.join("\n")}
52
- </packageSourceCredentials>
53
- </configuration>
54
- NUGET_XML
55
- File.write(user_nuget_config_path, nuget_config)
56
- end
57
-
58
- sig { void }
59
- def self.restore_user_nuget_config
60
- return unless File.exist?(temporary_nuget_config_path)
61
-
62
- File.delete(user_nuget_config_path)
63
- File.rename(temporary_nuget_config_path, user_nuget_config_path)
64
- end
65
-
66
- sig { params(credentials: T::Array[Dependabot::Credential], _block: T.proc.void).void }
67
- def self.patch_nuget_config_for_action(credentials, &_block)
68
- add_credentials_to_nuget_config(credentials)
69
- begin
70
- yield
71
- rescue DependabotError
72
- # forward these
73
- raise
74
- rescue StandardError => e
75
- log_message =
76
- <<~LOG_MESSAGE
77
- Block argument of NuGetConfigCredentialHelpers::patch_nuget_config_for_action causes an exception #{e}:
78
- #{e.message}
79
- LOG_MESSAGE
80
- Dependabot.logger.error(log_message)
81
- puts log_message
82
- ensure
83
- restore_user_nuget_config
84
- end
85
- end
86
- end
87
- end
88
- end
@@ -1,51 +0,0 @@
1
- # typed: strong
2
- # frozen_string_literal: true
3
-
4
- require "sorbet-runtime"
5
- require "dependabot/nuget/version"
6
- require "dependabot/ecosystem"
7
- require "dependabot/nuget/requirement"
8
-
9
- module Dependabot
10
- module Nuget
11
- ECOSYSTEM = "dotnet"
12
-
13
- SUPPORTED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
14
-
15
- DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
16
-
17
- class NugetPackageManager < Dependabot::Ecosystem::VersionManager
18
- extend T::Sig
19
-
20
- NAME = "nuget"
21
-
22
- SUPPORTED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
23
-
24
- DEPRECATED_VERSIONS = T.let([].freeze, T::Array[Dependabot::Version])
25
-
26
- sig do
27
- params(
28
- raw_version: T.nilable(String)
29
- ).void
30
- end
31
- def initialize(raw_version)
32
- super(
33
- name: NAME,
34
- version: Version.new(raw_version),
35
- deprecated_versions: DEPRECATED_VERSIONS,
36
- supported_versions: SUPPORTED_VERSIONS
37
- )
38
- end
39
-
40
- sig { override.returns(T::Boolean) }
41
- def deprecated?
42
- false
43
- end
44
-
45
- sig { override.returns(T::Boolean) }
46
- def unsupported?
47
- false
48
- end
49
- end
50
- end
51
- end