@@ -18,19 +18,73 @@ 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 ( "Looking up Docker source #{ 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+ # Sometimes the versions are not tags (e.g., "24.04")
70+ # We only want to build a source if the version looks like a tag (starts with "v")
71+ is_tag = image_version &.start_with? ( "v" )
72+
73+ return unless is_tag || revision
74+
75+ parsed_source = Dependabot ::Source . from_url ( image_source )
76+ return unless parsed_source
77+
78+ Dependabot . logger . info "Building source with branch '#{ image_version } ' and commit '#{ revision } '"
79+
80+ Dependabot ::Source . new (
81+ provider : parsed_source . provider ,
82+ repo : parsed_source . repo ,
83+ directory : parsed_source . directory ,
84+ branch : image_version ,
85+ commit : revision
86+ )
87+ end
3488 end
3589 end
3690end
0 commit comments