Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for updating dependencies in target files #6913

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions maven/lib/dependabot/maven/file_fetcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def fetch_files
fetched_files << pom
fetched_files += child_poms
fetched_files += relative_path_parents(fetched_files)
fetched_files += targetfiles
fetched_files << extensions if extensions
fetched_files.uniq
end
Expand All @@ -47,6 +48,14 @@ def pom
def extensions
@extensions ||= T.let(fetch_file_if_present(".mvn/extensions.xml"), T.nilable(Dependabot::DependencyFile))
end

sig { returns(T::Array[DependencyFile]) }
def targetfiles
@targetfiles ||= T.let(
repo_contents(raise_errors: false).
select { |f| f.type == "file" && f.name.end_with?(".target") }.
map { |f| fetch_file_from_host(f.name) })
end

sig { returns(T::Array[DependencyFile]) }
def child_poms
Expand Down
29 changes: 29 additions & 0 deletions maven/lib/dependabot/maven/file_parser.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,14 @@ class FileParser < Dependabot::FileParsers::Base
# - Any dependencies (incl. those in dependencyManagement or plugins)
# - Any plugins (incl. those in pluginManagement)
# - Any extensions
# - Any eclipse-target with a location of type Maven
DEPENDENCY_SELECTOR = "project > parent, " \
"dependencies > dependency, " \
"extensions > extension, " \
"annotationProcessorPaths > path"
PLUGIN_SELECTOR = "plugins > plugin"
EXTENSION_SELECTOR = "extensions > extension"
TARGET_SELECTOR = "target > locations > location[type='Maven'] > dependencies > dependency"
PLUGIN_ARTIFACT_ITEMS_SELECTOR = "plugins > plugin > executions > execution > " \
"configuration > artifactItems > artifactItem"

Expand All @@ -43,6 +45,7 @@ def parse
dependency_set = DependencySet.new
pomfiles.each { |pom| dependency_set += pomfile_dependencies(pom) }
extensionfiles.each { |extension| dependency_set += extensionfile_dependencies(extension) }
targetfiles.each { |target| dependency_set += targetfile_dependencies(target) }
dependency_set.dependencies
end

Expand Down Expand Up @@ -122,6 +125,26 @@ def extensionfile_dependencies(extension)
dependency_set
end

sig { params(target: Dependabot::DependencyFile).returns(DependencySet) }
def targetfile_dependencies(target)
dependency_set = DependencySet.new

errors = []
doc = Nokogiri::XML(target.content)
doc.remove_namespaces!

doc.css(TARGET_SELECTOR).each do |dependency_node|
dep = dependency_from_dependency_node(target, dependency_node)
dependency_set << dep if dep
rescue DependencyFileNotEvaluatable => e
errors << e
end

raise errors.first if errors.any? && dependency_set.dependencies.none?

dependency_set
end

sig do
params(pom: Dependabot::DependencyFile,
dependency_node: Nokogiri::XML::Element).returns(T.nilable(Dependabot::Dependency))
Expand Down Expand Up @@ -365,6 +388,12 @@ def extensionfiles
)
end

sig { returns(T::Array[Dependabot::DependencyFile]) }
def targetfiles
@targetfiles ||=
dependency_files.select { |f| f.name.end_with?(".target") }
end

sig { returns(T::Array[String]) }
def internal_dependency_names
@internal_dependency_names ||= T.let(
Expand Down
18 changes: 18 additions & 0 deletions maven/spec/dependabot/maven/file_fetcher_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@
directory: directory
)
end

let(:file_fetcher_instance) do
described_class.new(source: source, credentials: credentials, repo_contents_path: nil)

before do
allow(file_fetcher_instance).to receive(:commit).and_return("sha")
Expand Down Expand Up @@ -79,6 +82,21 @@
it { is_expected.to be(false) }
end
end

before do
allow(file_fetcher_instance).to receive(:commit).and_return("sha")

stub_request(:get, File.join(url, ".mvn?ref=sha")).
with(headers: { "Authorization" => "token token" }).
to_return(
status: 404
)
stub_request(:get, /.*\?ref=sha/).
with(headers: { "Authorization" => "token token" }).
to_return(
status: 404
)
end

context "with a basic pom" do
before do
Expand Down
27 changes: 27 additions & 0 deletions maven/spec/dependabot/maven/file_parser_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,33 @@
end
end

context "with target-file" do
let(:files) { [targetfile, pom] }
let(:targetfile) do
Dependabot::DependencyFile.new(name: "releng/myproject.target", content: targetfile_body)
end
let(:targetfile_body) { fixture("target-files", "example.target") }

describe "the sole dependency" do
subject(:dependency) { dependencies[3] }

it "has the right details" do
expect(dependency).to be_a(Dependabot::Dependency)
expect(dependency.name).to eq("commons-io:commons-io")
expect(dependency.version).to eq("2.11.0")
expect(dependency.requirements).to eq(
[{
requirement: "2.11.0",
file: "releng/myproject.target",
groups: [],
source: nil,
metadata: { packaging_type: "jar" }
}]
)
end
end
end

context "with rogue whitespace" do
let(:pom_body) { fixture("poms", "whitespace.xml") }

Expand Down
18 changes: 18 additions & 0 deletions maven/spec/fixtures/target-files/example.target
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde version="3.8"?>
<target name="example">
<locations>
<location path="/tmp/dummy/" type="Directory"/>
<location includeDependencyDepth="none" includeSource="true" label="An old version of commons-io" missingManifest="error" type="Maven">
<dependencies>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
<type>jar</type>
</dependency>
</dependencies>
</location>
<location path="${eclipse_home}" type="Profile"/>
</locations>
</target>
Loading