Skip to content

Commit 591a979

Browse files
committed
docker: add metadata finding support for org.opencontainers.image.version and org.opencontainers.image.revision
1 parent 24f1357 commit 591a979

File tree

2 files changed

+104
-7
lines changed

2 files changed

+104
-7
lines changed

docker/lib/dependabot/docker/metadata_finder.rb

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,70 @@ def look_up_source
1818
return if dependency.requirements.empty?
1919

2020
new_source = dependency.requirements.first&.fetch(:source)
21-
return unless new_source && new_source[:registry] && new_source[:tag]
21+
return unless new_source && new_source[:registry] && (new_source[:tag] || new_source[:digest])
2222

23-
image_ref = "#{new_source[:registry]}/#{dependency.name}:#{new_source[:tag]}"
24-
image_details_output = SharedHelpers.run_shell_command("regctl image inspect #{image_ref}")
25-
image_details = JSON.parse(image_details_output)
26-
image_source = image_details.dig("config", "Labels", "org.opencontainers.image.source")
23+
details = image_details(new_source)
24+
image_source = details.dig("config", "Labels", "org.opencontainers.image.source")
2725
return unless image_source
2826

29-
Dependabot::Source.from_url(image_source)
27+
return Dependabot::Source.from_url(image_source) if new_source[:tag]
28+
29+
build_source_from_image_version(image_source, details)
3030
rescue StandardError => e
3131
Dependabot.logger.warn("Error looking up Docker source: #{e.message}")
3232
nil
3333
end
34+
35+
sig do
36+
params(
37+
source: T::Hash[Symbol, T.untyped]
38+
).returns(
39+
T::Hash[String, T.untyped]
40+
)
41+
end
42+
def image_details(source)
43+
registry = source[:registry]
44+
tag = source[:tag]
45+
digest = source[:digest]
46+
47+
image_ref =
48+
# If both tag and digest are present, use the digest as docker ignores the tag when a digest is present
49+
if digest
50+
"#{registry}/#{dependency.name}@sha256:#{digest}"
51+
else
52+
"#{registry}/#{dependency.name}:#{tag}"
53+
end
54+
55+
Dependabot.logger.info("Fetching image details for #{image_ref}")
56+
output = SharedHelpers.run_shell_command("regctl image inspect #{image_ref}")
57+
JSON.parse(output)
58+
end
59+
60+
sig do
61+
params(
62+
image_source: String,
63+
details: T::Hash[String, T.untyped]
64+
).returns(T.nilable(Dependabot::Source))
65+
end
66+
def build_source_from_image_version(image_source, details)
67+
image_version = details.dig("config", "Labels", "org.opencontainers.image.version")
68+
revision = details.dig("config", "Labels", "org.opencontainers.image.revision")
69+
70+
return unless image_version&.start_with?("v") || revision
71+
72+
parsed_source = Dependabot::Source.from_url(image_source)
73+
return unless parsed_source
74+
75+
Dependabot.logger.info "Building source with branch '#{image_version}' and commit '#{revision}'"
76+
77+
Dependabot::Source.new(
78+
provider: parsed_source.provider,
79+
repo: parsed_source.repo,
80+
directory: parsed_source.directory,
81+
branch: image_version,
82+
commit: revision
83+
)
84+
end
3485
end
3586
end
3687
end

docker/spec/dependabot/docker/metadata_finder_spec.rb

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,53 @@
7373
requirement: nil,
7474
groups: [],
7575
source: { registry: "ghcr.io",
76-
digest: "sha256:389a5a9a5457ed237b05d623ddc31a42fa97811051dcd02d7ca4ad46bd3edd3e" }
76+
digest: "389a5a9a5457ed237b05d623ddc31a42fa97811051dcd02d7ca4ad46bd3edd3e" }
77+
}],
78+
package_manager: "docker"
79+
)
80+
end
81+
82+
it "doesn't find the repository" do
83+
expect(finder.source_url).to be_nil
84+
end
85+
end
86+
87+
context "with a docker image without a tag but with org.opencontainers.image.version populated" do
88+
let(:dependency) do
89+
Dependabot::Dependency.new(
90+
name: "regclient/regctl",
91+
version: "",
92+
requirements: [{
93+
file: "Dockerfile",
94+
requirement: nil,
95+
groups: [],
96+
source: { registry: "ghcr.io",
97+
digest: "a734f285c0962e46557bff24489fa0b0521455733f72d9eb30c4f7a5027aeed6" }
98+
}],
99+
package_manager: "docker"
100+
)
101+
end
102+
103+
it "finds the repository" do
104+
expect(finder.source_url).to eq "https://github.com/regclient/regclient"
105+
expect(finder.send(:source).branch).to eq "v0.11.1"
106+
expect(finder.send(:source).commit).to eq "bf3bcfc47173b49ee8000d1d3a1ac15036e83cf0"
107+
end
108+
end
109+
110+
context "with a docker image without a tag but without a proper tag format or revision" do
111+
# The image used here has org.opencontainers.image.version set to "24.04"
112+
# which refers to the Ubuntu version rather than a tag
113+
let(:dependency) do
114+
Dependabot::Dependency.new(
115+
name: "maven",
116+
version: "",
117+
requirements: [{
118+
file: "Dockerfile",
119+
requirement: nil,
120+
groups: [],
121+
source: { registry: "docker.io",
122+
digest: "800a33a4cb190082c47abcd57944c852e1dece834f92c0aef65bea6336c52a72" }
77123
}],
78124
package_manager: "docker"
79125
)

0 commit comments

Comments
 (0)