dependabot-docker 0.388.0 → 0.389.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3aa2fc6d14725482321a9c09dd3304b393aec6271208da0437803b15806f5821
4
- data.tar.gz: '0785c238b7814483f797a6d31642deb80748a718b386be4f188dc32886d7b6c5'
3
+ metadata.gz: acc9b9fe679bfe9320ba49b341428d06c1e8c8ee3a32fe8ee9b2c58e3255088d
4
+ data.tar.gz: 750a5ecbaf42000e3aee5b91cf0e6563918c1e97f5bfd67c000a73cad2266d59
5
5
  SHA512:
6
- metadata.gz: 92c9e9149fc669a82485b6186646811e0c46820481f9c0160a1386a7e912def7f6b6873e376ec4176d930f2e1f483f9e3e52930cea2bf6d27927f0048e81743c
7
- data.tar.gz: a451bc5070ef987e560032f7761cb8a29d349947cb4dc9e4988a9954fd3e554538f56cde67347ab23a5feb6fb2a6da6e7633eba9a4072a8d063689dcd95b03e9
6
+ metadata.gz: 42c3c509647b68dd51fb9854e8d799d1d7c698fa2d6e2b7534e4d71d958572e0d4e44616d2d201032ad746a862e3471f5cd7e293713a1b94f3afb1922e0e27ba
7
+ data.tar.gz: e23963530ca9eedab7de6ffcfa2ecff538a502784d308c8b305645eb60e23ce4b2ce2328ce4c747daadd8a4730879f1e9c62b5aa46e028aebecb35b6439899cc
@@ -80,6 +80,14 @@ module Dependabot
80
80
  # so we cap the attempts to avoid rate limiting or excessive latency.
81
81
  MAX_PLATFORM_VALIDATION_ATTEMPTS = T.let(5, Integer)
82
82
 
83
+ # Page size used when listing tags from a registry. Without an explicit page
84
+ # size, registries such as Docker Hub try to return every tag in a single
85
+ # response, which times out (HTTP 504) for images with very large tag counts
86
+ # (e.g. hexpm/elixir has ~1M tags). Requesting a bounded page keeps each
87
+ # request fast; the client then follows the registry's pagination links to
88
+ # collect the remaining tags.
89
+ TAGS_PAGE_SIZE = T.let(100, Integer)
90
+
83
91
  DockerSource = T.type_alias do
84
92
  T::Hash[Symbol, T.nilable(String)]
85
93
  end
@@ -491,6 +499,7 @@ module Dependabot
491
499
  )
492
500
  rescue *transient_docker_errors,
493
501
  DockerRegistry2::RegistryAuthenticationException,
502
+ DockerRegistry2::RegistryAuthorizationException,
494
503
  RestClient::Forbidden,
495
504
  RestClient::TooManyRequests => e
496
505
  Dependabot.logger.warn(
@@ -700,30 +709,28 @@ module Dependabot
700
709
  sig { returns(T::Array[Dependabot::Docker::Tag]) }
701
710
  def tags_from_registry
702
711
  @tags_from_registry ||= T.let(
703
- begin
704
- client = docker_registry_client
705
-
706
- client.tags(docker_repo_name, auto_paginate: true).fetch("tags").map { |name| Tag.new(name) }
707
- rescue *transient_docker_errors
708
- attempt ||= 1
709
- attempt += 1
710
- raise if attempt > 3
711
-
712
- retry
713
- end,
712
+ fetch_tags_from_registry,
714
713
  T.nilable(T::Array[Dependabot::Docker::Tag])
715
714
  )
716
715
  rescue DockerRegistry2::RegistryAuthenticationException,
716
+ DockerRegistry2::RegistryAuthorizationException,
717
717
  RestClient::Forbidden
718
718
  raise PrivateSourceAuthenticationFailure, registry_hostname
719
719
  rescue RestClient::Exceptions::OpenTimeout,
720
- RestClient::Exceptions::ReadTimeout
720
+ RestClient::Exceptions::ReadTimeout,
721
+ DockerRegistry2::RegistryUnknownException
721
722
  raise if using_dockerhub?
722
723
 
723
724
  raise PrivateSourceTimedOut, T.must(registry_hostname)
724
725
  rescue RestClient::ServerBrokeConnection,
725
726
  RestClient::TooManyRequests
726
727
  raise PrivateSourceBadResponse, registry_hostname
728
+ rescue DockerRegistry2::RegistryHTTPException => e
729
+ # The registry returned an HTTP error status (e.g. a 504 when Docker Hub
730
+ # can't enumerate an image's tags). Surface a generic RegistryError with
731
+ # the status rather than a private-source error, since the registry may
732
+ # well be public (e.g. Docker Hub).
733
+ raise_registry_error(e)
727
734
  rescue JSON::ParserError => e
728
735
  if e.message.include?("unexpected token")
729
736
  raise DependencyFileNotResolvable, "Error while accessing docker image at #{registry_hostname}"
@@ -732,6 +739,52 @@ module Dependabot
732
739
  raise
733
740
  end
734
741
 
742
+ # Registries such as Docker Hub time out (HTTP 504) when asked to return the
743
+ # full tag list for images with very large tag counts (e.g. hexpm/elixir has
744
+ # ~1M tags). Request the list without a page size first — a single efficient
745
+ # call for the common case — and fall back to a paginated request when the
746
+ # registry can't return everything at once.
747
+ sig { params(page_size: T.nilable(Integer)).returns(T::Array[Dependabot::Docker::Tag]) }
748
+ def fetch_tags_from_registry(page_size: nil)
749
+ client = docker_registry_client
750
+ response =
751
+ if page_size
752
+ client.tags(docker_repo_name, page_size, "", false, auto_paginate: true)
753
+ else
754
+ client.tags(docker_repo_name, auto_paginate: true)
755
+ end
756
+ response.fetch("tags").map { |name| Tag.new(name) }
757
+ rescue *transient_docker_errors
758
+ attempt ||= 1
759
+ attempt += 1
760
+ raise if attempt > 3
761
+
762
+ retry
763
+ rescue DockerRegistry2::RegistryHTTPException => e
764
+ raise if page_size || registry_http_status(e) == 429
765
+
766
+ fetch_tags_from_registry(page_size: TAGS_PAGE_SIZE)
767
+ end
768
+
769
+ # docker_registry2 1.19.0 only exposes the status in the exception message.
770
+ sig { params(error: DockerRegistry2::RegistryHTTPException).returns(Integer) }
771
+ def registry_http_status(error)
772
+ if error.respond_to?(:status)
773
+ status = error.method(:status).call
774
+ return status if status.is_a?(Integer)
775
+ end
776
+
777
+ status = error.message[/status (\d+)/, 1]
778
+ return status.to_i if status
779
+
780
+ raise error
781
+ end
782
+
783
+ sig { params(error: DockerRegistry2::RegistryHTTPException).returns(T.noreturn) }
784
+ def raise_registry_error(error)
785
+ raise RegistryError.new(registry_http_status(error), error.message)
786
+ end
787
+
735
788
  sig { returns(T.nilable(String)) }
736
789
  def latest_digest
737
790
  return unless tags_from_registry.map(&:name).include?("latest")
@@ -757,7 +810,10 @@ module Dependabot
757
810
  raise PrivateSourceBadResponse, registry_hostname if attempt > 3
758
811
 
759
812
  retry
813
+ rescue DockerRegistry2::RegistryHTTPException => e
814
+ raise_registry_error(e)
760
815
  rescue DockerRegistry2::RegistryAuthenticationException,
816
+ DockerRegistry2::RegistryAuthorizationException,
761
817
  RestClient::Forbidden
762
818
  raise PrivateSourceAuthenticationFailure, registry_hostname
763
819
  rescue RestClient::ServerBrokeConnection,
@@ -777,6 +833,7 @@ module Dependabot
777
833
  RestClient::ServiceUnavailable,
778
834
  RestClient::InternalServerError,
779
835
  RestClient::BadGateway,
836
+ DockerRegistry2::RegistryUnknownException,
780
837
  DockerRegistry2::NotFound
781
838
  ]
782
839
  end
@@ -1120,6 +1177,7 @@ module Dependabot
1120
1177
  config_created_timestamps[tag_name] = created
1121
1178
  created
1122
1179
  rescue *transient_docker_errors, DockerRegistry2::RegistryAuthenticationException,
1180
+ DockerRegistry2::RegistryAuthorizationException,
1123
1181
  RestClient::Forbidden, JSON::ParserError => e
1124
1182
  Dependabot.logger.info(
1125
1183
  "Failed to fetch config created timestamp for #{docker_repo_name}:#{tag_name}: #{e.message}"
@@ -1417,6 +1475,7 @@ module Dependabot
1417
1475
  platform_digests_cache[tag_name] = digests
1418
1476
  digests
1419
1477
  rescue *transient_docker_errors, DockerRegistry2::RegistryAuthenticationException,
1478
+ DockerRegistry2::RegistryAuthorizationException,
1420
1479
  RestClient::Forbidden, RestClient::TooManyRequests, JSON::ParserError => e
1421
1480
  Dependabot.logger.info(
1422
1481
  "Failed to fetch platform digests for #{docker_repo_name}:#{tag_name}: #{e.message}"
@@ -1460,6 +1519,7 @@ module Dependabot
1460
1519
  manifest_platforms_cache[tag_name] = platforms
1461
1520
  platforms
1462
1521
  rescue *transient_docker_errors, DockerRegistry2::RegistryAuthenticationException,
1522
+ DockerRegistry2::RegistryAuthorizationException,
1463
1523
  RestClient::Forbidden, JSON::ParserError => e
1464
1524
  Dependabot.logger.info(
1465
1525
  "Failed to fetch manifest platforms for #{docker_repo_name}:#{tag_name}: #{e.message}"
@@ -1524,6 +1584,7 @@ module Dependabot
1524
1584
  platform_timestamps_cache[tag_name] = timestamps
1525
1585
  timestamps
1526
1586
  rescue *transient_docker_errors, DockerRegistry2::RegistryAuthenticationException,
1587
+ DockerRegistry2::RegistryAuthorizationException,
1527
1588
  RestClient::Forbidden, JSON::ParserError => e
1528
1589
  Dependabot.logger.info(
1529
1590
  "Failed to fetch platform timestamps for #{docker_repo_name}:#{tag_name}: #{e.message}"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dependabot-docker
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.388.0
4
+ version: 0.389.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dependabot
@@ -15,14 +15,14 @@ dependencies:
15
15
  requirements:
16
16
  - - '='
17
17
  - !ruby/object:Gem::Version
18
- version: 0.388.0
18
+ version: 0.389.0
19
19
  type: :runtime
20
20
  prerelease: false
21
21
  version_requirements: !ruby/object:Gem::Requirement
22
22
  requirements:
23
23
  - - '='
24
24
  - !ruby/object:Gem::Version
25
- version: 0.388.0
25
+ version: 0.389.0
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: debug
28
28
  requirement: !ruby/object:Gem::Requirement
@@ -266,7 +266,7 @@ licenses:
266
266
  - MIT
267
267
  metadata:
268
268
  bug_tracker_uri: https://github.com/dependabot/dependabot-core/issues
269
- changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.388.0
269
+ changelog_uri: https://github.com/dependabot/dependabot-core/releases/tag/v0.389.0
270
270
  rdoc_options: []
271
271
  require_paths:
272
272
  - lib