dependabot-core 0.76.1
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 +7 -0
- data/CHANGELOG.md +6408 -0
- data/LICENSE +37 -0
- data/README.md +115 -0
- data/helpers/elixir/bin/check_update.exs +92 -0
- data/helpers/elixir/bin/do_update.exs +39 -0
- data/helpers/elixir/bin/parse_deps.exs +103 -0
- data/helpers/elixir/bin/run.exs +76 -0
- data/helpers/elixir/mix.exs +21 -0
- data/helpers/elixir/mix.lock +3 -0
- data/helpers/go/Makefile +9 -0
- data/helpers/go/go.mod +9 -0
- data/helpers/go/go.sum +5 -0
- data/helpers/go/importresolver/main.go +34 -0
- data/helpers/go/main.go +77 -0
- data/helpers/go/updatechecker/main.go +107 -0
- data/helpers/go/updater/go.mod +3 -0
- data/helpers/go/updater/go.sum +2 -0
- data/helpers/go/updater/helpers.go +57 -0
- data/helpers/go/updater/main.go +48 -0
- data/helpers/npm/.agignore +1 -0
- data/helpers/npm/.envrc +2 -0
- data/helpers/npm/.eslintrc +14 -0
- data/helpers/npm/.nvimrc +7 -0
- data/helpers/npm/bin/run.js +34 -0
- data/helpers/npm/lib/helpers.js +25 -0
- data/helpers/npm/lib/peer-dependency-checker.js +102 -0
- data/helpers/npm/lib/subdependency-updater.js +48 -0
- data/helpers/npm/lib/updater.js +95 -0
- data/helpers/npm/package.json +17 -0
- data/helpers/npm/test/fixtures/npm-left-pad.json +1 -0
- data/helpers/npm/test/fixtures/updater/original/package-lock.json +16 -0
- data/helpers/npm/test/fixtures/updater/original/package.json +9 -0
- data/helpers/npm/test/fixtures/updater/updated/package-lock.json +16 -0
- data/helpers/npm/test/helpers.js +7 -0
- data/helpers/npm/test/updater.test.js +50 -0
- data/helpers/npm/yarn.lock +6120 -0
- data/helpers/php/.php_cs +34 -0
- data/helpers/php/bin/run.php +57 -0
- data/helpers/php/composer.json +14 -0
- data/helpers/php/composer.lock +1521 -0
- data/helpers/php/composer.phar +0 -0
- data/helpers/php/setup.sh +4 -0
- data/helpers/php/src/DependabotInstallationManager.php +61 -0
- data/helpers/php/src/DependabotPluginManager.php +23 -0
- data/helpers/php/src/ExceptionIO.php +25 -0
- data/helpers/php/src/Hasher.php +21 -0
- data/helpers/php/src/UpdateChecker.php +123 -0
- data/helpers/php/src/Updater.php +97 -0
- data/helpers/python/lib/__init__.py +0 -0
- data/helpers/python/lib/hasher.py +23 -0
- data/helpers/python/lib/parser.py +130 -0
- data/helpers/python/requirements.txt +9 -0
- data/helpers/python/run.py +18 -0
- data/helpers/test/run.rb +15 -0
- data/helpers/utils/git-credential-store-immutable +10 -0
- data/helpers/yarn/.agignore +1 -0
- data/helpers/yarn/.envrc +2 -0
- data/helpers/yarn/.eslintrc +14 -0
- data/helpers/yarn/.nvimrc +7 -0
- data/helpers/yarn/bin/run.js +36 -0
- data/helpers/yarn/lib/fix-duplicates.js +53 -0
- data/helpers/yarn/lib/helpers.js +5 -0
- data/helpers/yarn/lib/lockfile-parser.js +21 -0
- data/helpers/yarn/lib/peer-dependency-checker.js +130 -0
- data/helpers/yarn/lib/replace-lockfile-declaration.js +45 -0
- data/helpers/yarn/lib/subdependency-updater.js +69 -0
- data/helpers/yarn/lib/updater.js +254 -0
- data/helpers/yarn/package.json +17 -0
- data/helpers/yarn/test/fixtures/updater/original/package.json +6 -0
- data/helpers/yarn/test/fixtures/updater/original/yarn.lock +11 -0
- data/helpers/yarn/test/fixtures/updater/updated/yarn.lock +12 -0
- data/helpers/yarn/test/fixtures/updater/with-version-comments/package.json +5 -0
- data/helpers/yarn/test/fixtures/updater/with-version-comments/yarn.lock +13 -0
- data/helpers/yarn/test/fixtures/yarnpkg-is-positive.json +1 -0
- data/helpers/yarn/test/fixtures/yarnpkg-left-pad.json +1 -0
- data/helpers/yarn/test/helpers.js +7 -0
- data/helpers/yarn/test/updater.test.js +93 -0
- data/helpers/yarn/yarn.lock +4912 -0
- data/lib/bundler_definition_bundler_version_patch.rb +15 -0
- data/lib/bundler_definition_ruby_version_patch.rb +14 -0
- data/lib/bundler_git_source_patch.rb +27 -0
- data/lib/dependabot.rb +4 -0
- data/lib/dependabot/clients/bitbucket.rb +101 -0
- data/lib/dependabot/clients/github_with_retries.rb +117 -0
- data/lib/dependabot/clients/gitlab.rb +72 -0
- data/lib/dependabot/dependency.rb +118 -0
- data/lib/dependabot/dependency_file.rb +54 -0
- data/lib/dependabot/errors.rb +179 -0
- data/lib/dependabot/file_fetchers.rb +48 -0
- data/lib/dependabot/file_fetchers/README.md +65 -0
- data/lib/dependabot/file_fetchers/base.rb +302 -0
- data/lib/dependabot/file_fetchers/docker/docker.rb +40 -0
- data/lib/dependabot/file_fetchers/dotnet/nuget.rb +215 -0
- data/lib/dependabot/file_fetchers/dotnet/nuget/import_paths_finder.rb +51 -0
- data/lib/dependabot/file_fetchers/dotnet/nuget/sln_project_paths_finder.rb +55 -0
- data/lib/dependabot/file_fetchers/elixir/hex.rb +78 -0
- data/lib/dependabot/file_fetchers/elm/elm_package.rb +52 -0
- data/lib/dependabot/file_fetchers/git/submodules.rb +73 -0
- data/lib/dependabot/file_fetchers/go/dep.rb +69 -0
- data/lib/dependabot/file_fetchers/go/modules.rb +64 -0
- data/lib/dependabot/file_fetchers/java/gradle.rb +56 -0
- data/lib/dependabot/file_fetchers/java/gradle/settings_file_parser.rb +66 -0
- data/lib/dependabot/file_fetchers/java/maven.rb +127 -0
- data/lib/dependabot/file_fetchers/java_script/npm_and_yarn.rb +330 -0
- data/lib/dependabot/file_fetchers/java_script/npm_and_yarn/path_dependency_builder.rb +107 -0
- data/lib/dependabot/file_fetchers/php/composer.rb +131 -0
- data/lib/dependabot/file_fetchers/python/pip.rb +305 -0
- data/lib/dependabot/file_fetchers/ruby/bundler.rb +185 -0
- data/lib/dependabot/file_fetchers/ruby/bundler/child_gemfile_finder.rb +70 -0
- data/lib/dependabot/file_fetchers/ruby/bundler/path_gemspec_finder.rb +114 -0
- data/lib/dependabot/file_fetchers/ruby/bundler/require_relative_finder.rb +67 -0
- data/lib/dependabot/file_fetchers/rust/cargo.rb +240 -0
- data/lib/dependabot/file_parsers.rb +48 -0
- data/lib/dependabot/file_parsers/README.md +45 -0
- data/lib/dependabot/file_parsers/base.rb +31 -0
- data/lib/dependabot/file_parsers/base/dependency_set.rb +77 -0
- data/lib/dependabot/file_parsers/docker/docker.rb +164 -0
- data/lib/dependabot/file_parsers/dotnet/nuget.rb +85 -0
- data/lib/dependabot/file_parsers/dotnet/nuget/packages_config_parser.rb +65 -0
- data/lib/dependabot/file_parsers/dotnet/nuget/project_file_parser.rb +156 -0
- data/lib/dependabot/file_parsers/dotnet/nuget/property_value_finder.rb +131 -0
- data/lib/dependabot/file_parsers/elixir/hex.rb +134 -0
- data/lib/dependabot/file_parsers/elm/elm_package.rb +136 -0
- data/lib/dependabot/file_parsers/git/submodules.rb +69 -0
- data/lib/dependabot/file_parsers/go/dep.rb +163 -0
- data/lib/dependabot/file_parsers/go/modules.rb +34 -0
- data/lib/dependabot/file_parsers/go/modules/go_mod_parser.rb +134 -0
- data/lib/dependabot/file_parsers/java/gradle.rb +236 -0
- data/lib/dependabot/file_parsers/java/gradle/property_value_finder.rb +90 -0
- data/lib/dependabot/file_parsers/java/gradle/repositories_finder.rb +145 -0
- data/lib/dependabot/file_parsers/java/maven.rb +252 -0
- data/lib/dependabot/file_parsers/java/maven/property_value_finder.rb +166 -0
- data/lib/dependabot/file_parsers/java/maven/repositories_finder.rb +188 -0
- data/lib/dependabot/file_parsers/java_script/npm_and_yarn.rb +394 -0
- data/lib/dependabot/file_parsers/php/composer.rb +177 -0
- data/lib/dependabot/file_parsers/python/pip.rb +223 -0
- data/lib/dependabot/file_parsers/python/pip/pipfile_files_parser.rb +154 -0
- data/lib/dependabot/file_parsers/python/pip/poetry_files_parser.rb +141 -0
- data/lib/dependabot/file_parsers/python/pip/setup_file_parser.rb +160 -0
- data/lib/dependabot/file_parsers/ruby/bundler.rb +295 -0
- data/lib/dependabot/file_parsers/ruby/bundler/file_preparer.rb +85 -0
- data/lib/dependabot/file_parsers/ruby/bundler/gemfile_checker.rb +48 -0
- data/lib/dependabot/file_parsers/rust/cargo.rb +213 -0
- data/lib/dependabot/file_updaters.rb +48 -0
- data/lib/dependabot/file_updaters/README.md +58 -0
- data/lib/dependabot/file_updaters/base.rb +52 -0
- data/lib/dependabot/file_updaters/docker/docker.rb +133 -0
- data/lib/dependabot/file_updaters/dotnet/nuget.rb +151 -0
- data/lib/dependabot/file_updaters/dotnet/nuget/packages_config_declaration_finder.rb +69 -0
- data/lib/dependabot/file_updaters/dotnet/nuget/project_file_declaration_finder.rb +78 -0
- data/lib/dependabot/file_updaters/dotnet/nuget/property_value_updater.rb +64 -0
- data/lib/dependabot/file_updaters/elixir/hex.rb +71 -0
- data/lib/dependabot/file_updaters/elixir/hex/lockfile_updater.rb +147 -0
- data/lib/dependabot/file_updaters/elixir/hex/mixfile_git_pin_updater.rb +53 -0
- data/lib/dependabot/file_updaters/elixir/hex/mixfile_requirement_updater.rb +74 -0
- data/lib/dependabot/file_updaters/elixir/hex/mixfile_sanitizer.rb +28 -0
- data/lib/dependabot/file_updaters/elixir/hex/mixfile_updater.rb +98 -0
- data/lib/dependabot/file_updaters/elm/elm_package.rb +79 -0
- data/lib/dependabot/file_updaters/elm/elm_package/elm_json_updater.rb +69 -0
- data/lib/dependabot/file_updaters/elm/elm_package/elm_package_updater.rb +69 -0
- data/lib/dependabot/file_updaters/git/submodules.rb +38 -0
- data/lib/dependabot/file_updaters/go/dep.rb +77 -0
- data/lib/dependabot/file_updaters/go/dep/lockfile_updater.rb +219 -0
- data/lib/dependabot/file_updaters/go/dep/manifest_updater.rb +155 -0
- data/lib/dependabot/file_updaters/go/modules.rb +71 -0
- data/lib/dependabot/file_updaters/go/modules/go_mod_updater.rb +81 -0
- data/lib/dependabot/file_updaters/java/gradle.rb +176 -0
- data/lib/dependabot/file_updaters/java/gradle/dependency_set_updater.rb +66 -0
- data/lib/dependabot/file_updaters/java/gradle/property_value_updater.rb +58 -0
- data/lib/dependabot/file_updaters/java/maven.rb +155 -0
- data/lib/dependabot/file_updaters/java/maven/declaration_finder.rb +132 -0
- data/lib/dependabot/file_updaters/java/maven/property_value_updater.rb +61 -0
- data/lib/dependabot/file_updaters/java_script/npm_and_yarn.rb +159 -0
- data/lib/dependabot/file_updaters/java_script/npm_and_yarn/npm_lockfile_updater.rb +532 -0
- data/lib/dependabot/file_updaters/java_script/npm_and_yarn/npmrc_builder.rb +191 -0
- data/lib/dependabot/file_updaters/java_script/npm_and_yarn/package_json_preparer.rb +91 -0
- data/lib/dependabot/file_updaters/java_script/npm_and_yarn/package_json_updater.rb +220 -0
- data/lib/dependabot/file_updaters/java_script/npm_and_yarn/yarn_lockfile_updater.rb +475 -0
- data/lib/dependabot/file_updaters/php/composer.rb +78 -0
- data/lib/dependabot/file_updaters/php/composer/lockfile_updater.rb +264 -0
- data/lib/dependabot/file_updaters/php/composer/manifest_updater.rb +70 -0
- data/lib/dependabot/file_updaters/python/pip.rb +147 -0
- data/lib/dependabot/file_updaters/python/pip/pip_compile_file_updater.rb +363 -0
- data/lib/dependabot/file_updaters/python/pip/pipfile_file_updater.rb +397 -0
- data/lib/dependabot/file_updaters/python/pip/pipfile_preparer.rb +125 -0
- data/lib/dependabot/file_updaters/python/pip/poetry_file_updater.rb +289 -0
- data/lib/dependabot/file_updaters/python/pip/pyproject_preparer.rb +105 -0
- data/lib/dependabot/file_updaters/python/pip/requirement_file_updater.rb +166 -0
- data/lib/dependabot/file_updaters/python/pip/requirement_replacer.rb +95 -0
- data/lib/dependabot/file_updaters/python/pip/setup_file_sanitizer.rb +91 -0
- data/lib/dependabot/file_updaters/ruby/bundler.rb +121 -0
- data/lib/dependabot/file_updaters/ruby/bundler/gemfile_updater.rb +116 -0
- data/lib/dependabot/file_updaters/ruby/bundler/gemspec_dependency_name_finder.rb +52 -0
- data/lib/dependabot/file_updaters/ruby/bundler/gemspec_sanitizer.rb +298 -0
- data/lib/dependabot/file_updaters/ruby/bundler/gemspec_updater.rb +64 -0
- data/lib/dependabot/file_updaters/ruby/bundler/git_pin_replacer.rb +80 -0
- data/lib/dependabot/file_updaters/ruby/bundler/git_source_remover.rb +102 -0
- data/lib/dependabot/file_updaters/ruby/bundler/lockfile_updater.rb +384 -0
- data/lib/dependabot/file_updaters/ruby/bundler/requirement_replacer.rb +188 -0
- data/lib/dependabot/file_updaters/rust/cargo.rb +83 -0
- data/lib/dependabot/file_updaters/rust/cargo/lockfile_updater.rb +251 -0
- data/lib/dependabot/file_updaters/rust/cargo/manifest_updater.rb +162 -0
- data/lib/dependabot/git_commit_checker.rb +412 -0
- data/lib/dependabot/metadata_finders.rb +46 -0
- data/lib/dependabot/metadata_finders/README.md +53 -0
- data/lib/dependabot/metadata_finders/base.rb +117 -0
- data/lib/dependabot/metadata_finders/base/changelog_finder.rb +317 -0
- data/lib/dependabot/metadata_finders/base/changelog_pruner.rb +177 -0
- data/lib/dependabot/metadata_finders/base/commits_finder.rb +217 -0
- data/lib/dependabot/metadata_finders/base/release_finder.rb +251 -0
- data/lib/dependabot/metadata_finders/docker/docker.rb +18 -0
- data/lib/dependabot/metadata_finders/dotnet/nuget.rb +116 -0
- data/lib/dependabot/metadata_finders/elixir/hex.rb +69 -0
- data/lib/dependabot/metadata_finders/elm/elm_package.rb +22 -0
- data/lib/dependabot/metadata_finders/git/submodules.rb +20 -0
- data/lib/dependabot/metadata_finders/go/dep.rb +56 -0
- data/lib/dependabot/metadata_finders/java/maven.rb +173 -0
- data/lib/dependabot/metadata_finders/java_script/npm_and_yarn.rb +215 -0
- data/lib/dependabot/metadata_finders/php/composer.rb +66 -0
- data/lib/dependabot/metadata_finders/python/pip.rb +120 -0
- data/lib/dependabot/metadata_finders/ruby/bundler.rb +150 -0
- data/lib/dependabot/metadata_finders/rust/cargo.rb +64 -0
- data/lib/dependabot/pull_request_creator.rb +151 -0
- data/lib/dependabot/pull_request_creator/branch_namer.rb +170 -0
- data/lib/dependabot/pull_request_creator/commit_signer.rb +63 -0
- data/lib/dependabot/pull_request_creator/github.rb +233 -0
- data/lib/dependabot/pull_request_creator/gitlab.rb +122 -0
- data/lib/dependabot/pull_request_creator/labeler.rb +361 -0
- data/lib/dependabot/pull_request_creator/message_builder.rb +888 -0
- data/lib/dependabot/pull_request_updater.rb +43 -0
- data/lib/dependabot/pull_request_updater/github.rb +151 -0
- data/lib/dependabot/shared_helpers.rb +201 -0
- data/lib/dependabot/source.rb +120 -0
- data/lib/dependabot/update_checkers.rb +48 -0
- data/lib/dependabot/update_checkers/README.md +67 -0
- data/lib/dependabot/update_checkers/base.rb +220 -0
- data/lib/dependabot/update_checkers/docker/docker.rb +290 -0
- data/lib/dependabot/update_checkers/dotnet/nuget.rb +127 -0
- data/lib/dependabot/update_checkers/dotnet/nuget/property_updater.rb +97 -0
- data/lib/dependabot/update_checkers/dotnet/nuget/repository_finder.rb +232 -0
- data/lib/dependabot/update_checkers/dotnet/nuget/requirements_updater.rb +81 -0
- data/lib/dependabot/update_checkers/dotnet/nuget/version_finder.rb +231 -0
- data/lib/dependabot/update_checkers/elixir/hex.rb +274 -0
- data/lib/dependabot/update_checkers/elixir/hex/file_preparer.rb +193 -0
- data/lib/dependabot/update_checkers/elixir/hex/requirements_updater.rb +177 -0
- data/lib/dependabot/update_checkers/elixir/hex/version_resolver.rb +175 -0
- data/lib/dependabot/update_checkers/elm/elm_package.rb +126 -0
- data/lib/dependabot/update_checkers/elm/elm_package/cli_parser.rb +33 -0
- data/lib/dependabot/update_checkers/elm/elm_package/elm_18_version_resolver.rb +234 -0
- data/lib/dependabot/update_checkers/elm/elm_package/elm_19_version_resolver.rb +198 -0
- data/lib/dependabot/update_checkers/elm/elm_package/requirements_updater.rb +75 -0
- data/lib/dependabot/update_checkers/git/submodules.rb +52 -0
- data/lib/dependabot/update_checkers/go/dep.rb +311 -0
- data/lib/dependabot/update_checkers/go/dep/file_preparer.rb +221 -0
- data/lib/dependabot/update_checkers/go/dep/latest_version_finder.rb +169 -0
- data/lib/dependabot/update_checkers/go/dep/requirements_updater.rb +223 -0
- data/lib/dependabot/update_checkers/go/dep/version_resolver.rb +164 -0
- data/lib/dependabot/update_checkers/go/modules.rb +112 -0
- data/lib/dependabot/update_checkers/java/gradle.rb +148 -0
- data/lib/dependabot/update_checkers/java/gradle/multi_dependency_updater.rb +105 -0
- data/lib/dependabot/update_checkers/java/gradle/version_finder.rb +183 -0
- data/lib/dependabot/update_checkers/java/maven.rb +159 -0
- data/lib/dependabot/update_checkers/java/maven/property_updater.rb +127 -0
- data/lib/dependabot/update_checkers/java/maven/requirements_updater.rb +92 -0
- data/lib/dependabot/update_checkers/java/maven/version_finder.rb +225 -0
- data/lib/dependabot/update_checkers/java_script/npm_and_yarn.rb +280 -0
- data/lib/dependabot/update_checkers/java_script/npm_and_yarn/latest_version_finder.rb +342 -0
- data/lib/dependabot/update_checkers/java_script/npm_and_yarn/library_detector.rb +69 -0
- data/lib/dependabot/update_checkers/java_script/npm_and_yarn/registry_finder.rb +226 -0
- data/lib/dependabot/update_checkers/java_script/npm_and_yarn/requirements_updater.rb +197 -0
- data/lib/dependabot/update_checkers/java_script/npm_and_yarn/subdependency_version_resolver.rb +228 -0
- data/lib/dependabot/update_checkers/java_script/npm_and_yarn/version_resolver.rb +452 -0
- data/lib/dependabot/update_checkers/php/composer.rb +165 -0
- data/lib/dependabot/update_checkers/php/composer/requirements_updater.rb +243 -0
- data/lib/dependabot/update_checkers/php/composer/version_resolver.rb +203 -0
- data/lib/dependabot/update_checkers/python/pip.rb +227 -0
- data/lib/dependabot/update_checkers/python/pip/latest_version_finder.rb +252 -0
- data/lib/dependabot/update_checkers/python/pip/pip_compile_version_resolver.rb +380 -0
- data/lib/dependabot/update_checkers/python/pip/pipfile_version_resolver.rb +559 -0
- data/lib/dependabot/update_checkers/python/pip/poetry_version_resolver.rb +300 -0
- data/lib/dependabot/update_checkers/python/pip/requirements_updater.rb +367 -0
- data/lib/dependabot/update_checkers/ruby/bundler.rb +324 -0
- data/lib/dependabot/update_checkers/ruby/bundler/file_preparer.rb +278 -0
- data/lib/dependabot/update_checkers/ruby/bundler/force_updater.rb +261 -0
- data/lib/dependabot/update_checkers/ruby/bundler/latest_version_finder.rb +169 -0
- data/lib/dependabot/update_checkers/ruby/bundler/requirements_updater.rb +264 -0
- data/lib/dependabot/update_checkers/ruby/bundler/ruby_requirement_setter.rb +115 -0
- data/lib/dependabot/update_checkers/ruby/bundler/shared_bundler_helpers.rb +243 -0
- data/lib/dependabot/update_checkers/ruby/bundler/version_resolver.rb +255 -0
- data/lib/dependabot/update_checkers/rust/cargo.rb +282 -0
- data/lib/dependabot/update_checkers/rust/cargo/file_preparer.rb +202 -0
- data/lib/dependabot/update_checkers/rust/cargo/requirements_updater.rb +175 -0
- data/lib/dependabot/update_checkers/rust/cargo/version_resolver.rb +242 -0
- data/lib/dependabot/utils.rb +84 -0
- data/lib/dependabot/utils/docker/credentials_finder.rb +65 -0
- data/lib/dependabot/utils/dotnet/requirement.rb +90 -0
- data/lib/dependabot/utils/dotnet/version.rb +22 -0
- data/lib/dependabot/utils/elixir/requirement.rb +53 -0
- data/lib/dependabot/utils/elixir/version.rb +59 -0
- data/lib/dependabot/utils/elm/requirement.rb +92 -0
- data/lib/dependabot/utils/elm/version.rb +19 -0
- data/lib/dependabot/utils/go/path_converter.rb +74 -0
- data/lib/dependabot/utils/go/requirement.rb +152 -0
- data/lib/dependabot/utils/go/shared_helper.rb +20 -0
- data/lib/dependabot/utils/go/version.rb +40 -0
- data/lib/dependabot/utils/java/requirement.rb +110 -0
- data/lib/dependabot/utils/java/version.rb +179 -0
- data/lib/dependabot/utils/java_script/requirement.rb +117 -0
- data/lib/dependabot/utils/java_script/version.rb +30 -0
- data/lib/dependabot/utils/php/requirement.rb +97 -0
- data/lib/dependabot/utils/php/version.rb +22 -0
- data/lib/dependabot/utils/python/requirement.rb +130 -0
- data/lib/dependabot/utils/python/version.rb +88 -0
- data/lib/dependabot/utils/ruby/requirement.rb +26 -0
- data/lib/dependabot/utils/rust/requirement.rb +108 -0
- data/lib/dependabot/utils/rust/version.rb +32 -0
- data/lib/dependabot/version.rb +5 -0
- data/lib/python_requirement_parser.rb +33 -0
- data/lib/python_versions.rb +21 -0
- metadata +641 -0
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "dependabot/update_checkers/ruby/bundler"
|
|
4
|
+
require "dependabot/update_checkers/python/pip"
|
|
5
|
+
require "dependabot/update_checkers/java_script/npm_and_yarn"
|
|
6
|
+
require "dependabot/update_checkers/java/maven"
|
|
7
|
+
require "dependabot/update_checkers/java/gradle"
|
|
8
|
+
require "dependabot/update_checkers/php/composer"
|
|
9
|
+
require "dependabot/update_checkers/git/submodules"
|
|
10
|
+
require "dependabot/update_checkers/docker/docker"
|
|
11
|
+
require "dependabot/update_checkers/elixir/hex"
|
|
12
|
+
require "dependabot/update_checkers/rust/cargo"
|
|
13
|
+
require "dependabot/update_checkers/dotnet/nuget"
|
|
14
|
+
require "dependabot/update_checkers/go/dep"
|
|
15
|
+
require "dependabot/update_checkers/go/modules"
|
|
16
|
+
require "dependabot/update_checkers/elm/elm_package"
|
|
17
|
+
|
|
18
|
+
module Dependabot
|
|
19
|
+
module UpdateCheckers
|
|
20
|
+
@update_checkers = {
|
|
21
|
+
"bundler" => UpdateCheckers::Ruby::Bundler,
|
|
22
|
+
"npm_and_yarn" => UpdateCheckers::JavaScript::NpmAndYarn,
|
|
23
|
+
"maven" => UpdateCheckers::Java::Maven,
|
|
24
|
+
"gradle" => UpdateCheckers::Java::Gradle,
|
|
25
|
+
"pip" => UpdateCheckers::Python::Pip,
|
|
26
|
+
"composer" => UpdateCheckers::Php::Composer,
|
|
27
|
+
"submodules" => UpdateCheckers::Git::Submodules,
|
|
28
|
+
"docker" => UpdateCheckers::Docker::Docker,
|
|
29
|
+
"hex" => UpdateCheckers::Elixir::Hex,
|
|
30
|
+
"cargo" => UpdateCheckers::Rust::Cargo,
|
|
31
|
+
"nuget" => UpdateCheckers::Dotnet::Nuget,
|
|
32
|
+
"dep" => UpdateCheckers::Go::Dep,
|
|
33
|
+
"go_modules" => UpdateCheckers::Go::Modules,
|
|
34
|
+
"elm-package" => UpdateCheckers::Elm::ElmPackage
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def self.for_package_manager(package_manager)
|
|
38
|
+
update_checker = @update_checkers[package_manager]
|
|
39
|
+
return update_checker if update_checker
|
|
40
|
+
|
|
41
|
+
raise "Unsupported package_manager #{package_manager}"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.register(package_manager, update_checker)
|
|
45
|
+
@update_checkers[package_manager] = update_checker
|
|
46
|
+
end
|
|
47
|
+
end
|
|
48
|
+
end
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
# Update checkers
|
|
2
|
+
|
|
3
|
+
Update checkers check whether a given dependency is up-to-date. If it isn't,
|
|
4
|
+
they augment it with details of the version to update to.
|
|
5
|
+
|
|
6
|
+
There is a `Dependabot::UpdateCheckers` class for each language Dependabot
|
|
7
|
+
supports.
|
|
8
|
+
|
|
9
|
+
## Public API
|
|
10
|
+
|
|
11
|
+
Each `Dependabot::UpdateCheckers` class implements the following methods:
|
|
12
|
+
|
|
13
|
+
| Method | Description |
|
|
14
|
+
|------------------------------|-----------------------------------------------------------------------------------------------|
|
|
15
|
+
| `#up_to_date?` | Returns a boolean for whether the dependency this instance was created with is currently at the latest version. |
|
|
16
|
+
| `#can_update?` | Returns a boolean for whether the dependency this instance was created with needs updating. This will be true if the dependency and/or its requirements can be updated to support a newer version whilst keeping the dependency files it came from resolvable. |
|
|
17
|
+
| `#updated_dependencies` | Returns an array of updated `Dependabot::Dependency` instance with updated `version` and `requirements` attributes. The previous valuse are stored on the instance as `previous_version` and `previous_requirements`. |
|
|
18
|
+
| `#latest_version` | See the "Writing an update checker" section. |
|
|
19
|
+
| `#latest_resolvable_version` | See the "Writing an update checker" section. |
|
|
20
|
+
| `#updated_requirements` | See the "Writing an update checker" section. |
|
|
21
|
+
|
|
22
|
+
An integration might look as follows:
|
|
23
|
+
|
|
24
|
+
```ruby
|
|
25
|
+
require 'dependabot/update_checkers'
|
|
26
|
+
|
|
27
|
+
dependency = dependencies.first
|
|
28
|
+
|
|
29
|
+
update_checker_class = Dependabot::UpdateCheckers::Ruby::Bundler
|
|
30
|
+
update_checker = update_checker_class.new(
|
|
31
|
+
dependency: dependency,
|
|
32
|
+
dependency_files: files,
|
|
33
|
+
credentials: [{
|
|
34
|
+
"type" => "git_source",
|
|
35
|
+
"host" => "github.com",
|
|
36
|
+
"username" => "x-access-token",
|
|
37
|
+
"password" => "token"
|
|
38
|
+
}]
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
puts "Update needed for #{dependency.name}? "\
|
|
42
|
+
"#{update_checker.can_update?(requirements_to_update: :own)}"
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
## Writing an update checker for a new language
|
|
46
|
+
|
|
47
|
+
All new update checkers should inherit from `Dependabot::UpdateCheckers::Base` and
|
|
48
|
+
implement the following methods:
|
|
49
|
+
|
|
50
|
+
| Method | Description |
|
|
51
|
+
|------------------------------|-----------------------------------------------------------------------------------------------|
|
|
52
|
+
| `#latest_version` | The latest version of the dependency, ignoring resolvability. This is used to short-circuit update checking when the dependency is already at the latest version (since checking resolvability is typically slow). |
|
|
53
|
+
| `#latest_resolvable_version` | The latest version of the dependency that will still allow the full dependency set to resolve. |
|
|
54
|
+
| `#latest_resolvable_version_with_no_unlock` | The latest version of the dependency that satisfies the dependency's current version constraints and will still allow the full dependency set to resolve. |
|
|
55
|
+
| `#updated_requirements` | An updated set of requirements for the dependency that should replace the existing requirements in the manifest file. Use by the file updater class when updating the manifest file. |
|
|
56
|
+
| `#latest_version_resolvable_with_full_unlock?` | A boolean for whether the latest version can be resolved if all other dependencies are unlocked in the manifest file. Can be set to always return `false` if multi-dependency updates aren't yet supported. |
|
|
57
|
+
| `#updated_dependencies_after_full_unlock` | And updated set of dependencies after a full unlock and update has taken place. Not required if `latest_version_resolvable_with_full_unlock?` always returns false. |
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
To ensure the above are implemented, you should include
|
|
61
|
+
`it_behaves_like "a dependency update checker"` in your specs for the new update
|
|
62
|
+
checker.
|
|
63
|
+
|
|
64
|
+
Writing update checkers generally gets tricky when resolvability has to
|
|
65
|
+
be taken into account. It is almost always easiest to do so in the language your
|
|
66
|
+
update checker relates to, so you may wish to shell out to that language. See
|
|
67
|
+
`UpdateCheckers::Php::Composer` for an example of how to do so.
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "json"
|
|
4
|
+
require "dependabot/utils"
|
|
5
|
+
|
|
6
|
+
module Dependabot
|
|
7
|
+
module UpdateCheckers
|
|
8
|
+
class Base
|
|
9
|
+
attr_reader :dependency, :dependency_files, :credentials,
|
|
10
|
+
:ignored_versions, :requirements_update_strategy
|
|
11
|
+
|
|
12
|
+
def initialize(dependency:, dependency_files:, credentials:,
|
|
13
|
+
ignored_versions: [], requirements_update_strategy: nil)
|
|
14
|
+
@dependency = dependency
|
|
15
|
+
@dependency_files = dependency_files
|
|
16
|
+
@credentials = credentials
|
|
17
|
+
@requirements_update_strategy = requirements_update_strategy
|
|
18
|
+
@ignored_versions = ignored_versions
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def up_to_date?
|
|
22
|
+
if dependency.appears_in_lockfile?
|
|
23
|
+
version_up_to_date?
|
|
24
|
+
else
|
|
25
|
+
requirements_up_to_date?
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def can_update?(requirements_to_unlock:)
|
|
30
|
+
if dependency.appears_in_lockfile?
|
|
31
|
+
version_can_update?(requirements_to_unlock: requirements_to_unlock)
|
|
32
|
+
else
|
|
33
|
+
# TODO: Handle full unlock updates for dependencies without a lockfile
|
|
34
|
+
return false if requirements_to_unlock == :none
|
|
35
|
+
|
|
36
|
+
requirements_can_update?
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def updated_dependencies(requirements_to_unlock:)
|
|
41
|
+
unless can_update?(requirements_to_unlock: requirements_to_unlock)
|
|
42
|
+
return []
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
case requirements_to_unlock&.to_sym
|
|
46
|
+
when :none then [updated_dependency_without_unlock]
|
|
47
|
+
when :own then [updated_dependency_with_own_req_unlock]
|
|
48
|
+
when :all then updated_dependencies_after_full_unlock
|
|
49
|
+
else raise "Unknown unlock level '#{requirements_to_unlock}'"
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def latest_version
|
|
54
|
+
raise NotImplementedError
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def latest_resolvable_version
|
|
58
|
+
raise NotImplementedError
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def latest_resolvable_version_with_no_unlock
|
|
62
|
+
raise NotImplementedError
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def updated_requirements
|
|
66
|
+
raise NotImplementedError
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def version_class
|
|
70
|
+
Utils.version_class_for_package_manager(dependency.package_manager)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def requirement_class
|
|
74
|
+
Utils.requirement_class_for_package_manager(dependency.package_manager)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
# For some langauges, the manifest file may be constructed such that
|
|
78
|
+
# Dependabot has no way to update it (e.g., if it fetches its versions
|
|
79
|
+
# from a web API). This method is overridden in those cases.
|
|
80
|
+
def requirements_unlocked_or_can_be?
|
|
81
|
+
true
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
private
|
|
85
|
+
|
|
86
|
+
def latest_version_resolvable_with_full_unlock?
|
|
87
|
+
raise NotImplementedError
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def updated_dependency_without_unlock
|
|
91
|
+
Dependency.new(
|
|
92
|
+
name: dependency.name,
|
|
93
|
+
version: latest_resolvable_version_with_no_unlock.to_s,
|
|
94
|
+
requirements: dependency.requirements,
|
|
95
|
+
previous_version: dependency.version,
|
|
96
|
+
previous_requirements: dependency.requirements,
|
|
97
|
+
package_manager: dependency.package_manager
|
|
98
|
+
)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def updated_dependency_with_own_req_unlock
|
|
102
|
+
Dependency.new(
|
|
103
|
+
name: dependency.name,
|
|
104
|
+
version: latest_resolvable_version.to_s,
|
|
105
|
+
requirements: updated_requirements,
|
|
106
|
+
previous_version: dependency.version,
|
|
107
|
+
previous_requirements: dependency.requirements,
|
|
108
|
+
package_manager: dependency.package_manager
|
|
109
|
+
)
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def updated_dependencies_after_full_unlock
|
|
113
|
+
raise NotImplementedError
|
|
114
|
+
end
|
|
115
|
+
|
|
116
|
+
def version_up_to_date?
|
|
117
|
+
return sha1_version_up_to_date? if existing_version_is_sha?
|
|
118
|
+
|
|
119
|
+
numeric_version_up_to_date?
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def version_can_update?(requirements_to_unlock:)
|
|
123
|
+
if existing_version_is_sha?
|
|
124
|
+
return sha1_version_can_update?(
|
|
125
|
+
requirements_to_unlock: requirements_to_unlock
|
|
126
|
+
)
|
|
127
|
+
end
|
|
128
|
+
|
|
129
|
+
numeric_version_can_update?(
|
|
130
|
+
requirements_to_unlock: requirements_to_unlock
|
|
131
|
+
)
|
|
132
|
+
end
|
|
133
|
+
|
|
134
|
+
def existing_version_is_sha?
|
|
135
|
+
return false if version_class.correct?(dependency.version)
|
|
136
|
+
|
|
137
|
+
dependency.version.match?(/^[0-9a-f]{6,}$/)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def sha1_version_up_to_date?
|
|
141
|
+
latest_version&.to_s&.start_with?(dependency.version)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def sha1_version_can_update?(requirements_to_unlock:)
|
|
145
|
+
return false if sha1_version_up_to_date?
|
|
146
|
+
|
|
147
|
+
# All we can do with SHA-1 hashes is check for presence and equality
|
|
148
|
+
case requirements_to_unlock&.to_sym
|
|
149
|
+
when :none
|
|
150
|
+
new_version = latest_resolvable_version_with_no_unlock
|
|
151
|
+
new_version && !new_version.to_s.start_with?(dependency.version)
|
|
152
|
+
when :own
|
|
153
|
+
new_version = latest_resolvable_version
|
|
154
|
+
new_version && !new_version.to_s.start_with?(dependency.version)
|
|
155
|
+
when :all
|
|
156
|
+
latest_version_resolvable_with_full_unlock?
|
|
157
|
+
else raise "Unknown unlock level '#{requirements_to_unlock}'"
|
|
158
|
+
end
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
def numeric_version_up_to_date?
|
|
162
|
+
return false unless latest_version
|
|
163
|
+
|
|
164
|
+
# If a lockfile isn't out of date and the package has switched to a git
|
|
165
|
+
# source then we'll get a numeric version switching to a git SHA. In
|
|
166
|
+
# this case we treat the verison as up-to-date so that it's ignored.
|
|
167
|
+
return true if latest_version.to_s.match?(/^[0-9a-f]{40}$/)
|
|
168
|
+
|
|
169
|
+
latest_version <= version_class.new(dependency.version)
|
|
170
|
+
end
|
|
171
|
+
|
|
172
|
+
def numeric_version_can_update?(requirements_to_unlock:)
|
|
173
|
+
return false if numeric_version_up_to_date?
|
|
174
|
+
|
|
175
|
+
case requirements_to_unlock&.to_sym
|
|
176
|
+
when :none
|
|
177
|
+
new_version = latest_resolvable_version_with_no_unlock
|
|
178
|
+
new_version && new_version > version_class.new(dependency.version)
|
|
179
|
+
when :own
|
|
180
|
+
new_version = latest_resolvable_version
|
|
181
|
+
new_version && new_version > version_class.new(dependency.version)
|
|
182
|
+
when :all
|
|
183
|
+
latest_version_resolvable_with_full_unlock?
|
|
184
|
+
else raise "Unknown unlock level '#{requirements_to_unlock}'"
|
|
185
|
+
end
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
def requirements_up_to_date?
|
|
189
|
+
return true if (updated_requirements - dependency.requirements).none?
|
|
190
|
+
return false unless latest_version
|
|
191
|
+
return false unless version_class.correct?(latest_version.to_s)
|
|
192
|
+
return false unless version_from_requirements
|
|
193
|
+
|
|
194
|
+
version_from_requirements >= version_class.new(latest_version.to_s)
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
def version_from_requirements
|
|
198
|
+
@version_from_requirements ||=
|
|
199
|
+
dependency.requirements.map { |r| r.fetch(:requirement) }.compact.
|
|
200
|
+
flat_map { |req_str| requirement_class.requirements_array(req_str) }.
|
|
201
|
+
flat_map(&:requirements).
|
|
202
|
+
reject { |req_array| req_array.first.start_with?("<") }.
|
|
203
|
+
map(&:last).
|
|
204
|
+
max
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def requirements_can_update?
|
|
208
|
+
changed_reqs = updated_requirements - dependency.requirements
|
|
209
|
+
|
|
210
|
+
return false if changed_reqs.none?
|
|
211
|
+
|
|
212
|
+
changed_reqs.none? { |r| r[:requirement] == :unfixable }
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
def ignore_reqs
|
|
216
|
+
ignored_versions.map { |req| requirement_class.new(req.split(",")) }
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
end
|
|
@@ -0,0 +1,290 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "docker_registry2"
|
|
4
|
+
|
|
5
|
+
require "dependabot/update_checkers/base"
|
|
6
|
+
require "dependabot/errors"
|
|
7
|
+
require "dependabot/utils/docker/credentials_finder"
|
|
8
|
+
|
|
9
|
+
module Dependabot
|
|
10
|
+
module UpdateCheckers
|
|
11
|
+
module Docker
|
|
12
|
+
class Docker < Dependabot::UpdateCheckers::Base
|
|
13
|
+
VERSION_REGEX = /(?<version>[0-9]+(?:\.[a-zA-Z0-9]+)*)/.freeze
|
|
14
|
+
VERSION_WITH_SUFFIX =
|
|
15
|
+
/^#{VERSION_REGEX}(?<affix>-[a-z0-9.\-]+)?$/.freeze
|
|
16
|
+
VERSION_WITH_PREFIX =
|
|
17
|
+
/^(?<affix>[a-z0-9.\-]+-)?#{VERSION_REGEX}$/.freeze
|
|
18
|
+
NAME_WITH_VERSION =
|
|
19
|
+
/#{VERSION_WITH_PREFIX}|#{VERSION_WITH_SUFFIX}/.freeze
|
|
20
|
+
|
|
21
|
+
def latest_version
|
|
22
|
+
@latest_version ||= fetch_latest_version
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def latest_resolvable_version
|
|
26
|
+
# Resolvability isn't an issue for Docker containers.
|
|
27
|
+
latest_version
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def latest_resolvable_version_with_no_unlock
|
|
31
|
+
# No concept of "unlocking" for Docker containers
|
|
32
|
+
dependency.version
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def updated_requirements
|
|
36
|
+
dependency.requirements.map do |req|
|
|
37
|
+
updated_source = req.fetch(:source).dup
|
|
38
|
+
updated_source[:digest] = updated_digest if req[:source][:digest]
|
|
39
|
+
updated_source[:tag] = latest_version if req[:source][:tag]
|
|
40
|
+
|
|
41
|
+
req.merge(source: updated_source)
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
private
|
|
46
|
+
|
|
47
|
+
def latest_version_resolvable_with_full_unlock?
|
|
48
|
+
# Full unlock checks aren't relevant for Dockerfiles
|
|
49
|
+
false
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def updated_dependencies_after_full_unlock
|
|
53
|
+
raise NotImplementedError
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def version_can_update?(*)
|
|
57
|
+
!version_up_to_date?
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def version_up_to_date?
|
|
61
|
+
# If the tag isn't up-to-date then we can definitely update
|
|
62
|
+
return false if version_tag_up_to_date? == false
|
|
63
|
+
|
|
64
|
+
# Otherwise, if the Dockerfile specifies a digest check that that is
|
|
65
|
+
# up-to-date
|
|
66
|
+
digest_up_to_date?
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def version_tag_up_to_date?
|
|
70
|
+
return unless dependency.version.match?(NAME_WITH_VERSION)
|
|
71
|
+
|
|
72
|
+
old_v = numeric_version_from(dependency.version)
|
|
73
|
+
latest_v = numeric_version_from(latest_version)
|
|
74
|
+
|
|
75
|
+
return true if version_class.new(latest_v) <= version_class.new(old_v)
|
|
76
|
+
|
|
77
|
+
# Check the precision of the potentially higher tag is the same as the
|
|
78
|
+
# one it would replace. In the event that it's not the same, check the
|
|
79
|
+
# digests are also unequal. Avoids 'updating' ruby-2 -> ruby-2.5.1
|
|
80
|
+
return false if old_v.split(".").count == latest_v.split(".").count
|
|
81
|
+
|
|
82
|
+
digest_of(dependency.version) == digest_of(latest_version)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def digest_up_to_date?
|
|
86
|
+
dependency.requirements.all? do |req|
|
|
87
|
+
next true unless req.fetch(:source)[:digest]
|
|
88
|
+
|
|
89
|
+
req.fetch(:source).fetch(:digest) == digest_of(dependency.version)
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
# Note: It's important that this *always* returns a version (even if
|
|
94
|
+
# it's the existing one) as it is what we later check the digest of.
|
|
95
|
+
def fetch_latest_version
|
|
96
|
+
unless dependency.version.match?(NAME_WITH_VERSION)
|
|
97
|
+
return dependency.version
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# Prune out any downgrade tags before checking for pre-releases
|
|
101
|
+
# (which requires a call to the registry for each tag, so can be slow)
|
|
102
|
+
candidate_tags = comparable_tags_from_registry
|
|
103
|
+
non_downgrade_tags = remove_version_downgrades(candidate_tags)
|
|
104
|
+
candidate_tags = non_downgrade_tags if non_downgrade_tags.any?
|
|
105
|
+
|
|
106
|
+
wants_prerelease = prerelease?(dependency.version)
|
|
107
|
+
candidate_tags =
|
|
108
|
+
candidate_tags.
|
|
109
|
+
reject { |tag| prerelease?(tag) && !wants_prerelease }.
|
|
110
|
+
reject do |tag|
|
|
111
|
+
version = version_class.new(numeric_version_from(tag))
|
|
112
|
+
ignore_reqs.any? { |r| r.satisfied_by?(version) }
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
latest_tag =
|
|
116
|
+
candidate_tags.
|
|
117
|
+
max_by { |tag| version_class.new(numeric_version_from(tag)) }
|
|
118
|
+
|
|
119
|
+
latest_tag || dependency.version
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
def comparable_tags_from_registry
|
|
123
|
+
original_affix = affix_of(dependency.version)
|
|
124
|
+
|
|
125
|
+
tags_from_registry.
|
|
126
|
+
select { |tag| tag.match?(NAME_WITH_VERSION) }.
|
|
127
|
+
select { |tag| affix_of(tag) == original_affix }.
|
|
128
|
+
reject { |tag| commit_sha_suffix?(tag) }
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
def remove_version_downgrades(candidate_tags)
|
|
132
|
+
candidate_tags.select do |tag|
|
|
133
|
+
version_class.new(numeric_version_from(tag)) >=
|
|
134
|
+
version_class.new(numeric_version_from(dependency.version))
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
def commit_sha_suffix?(tag)
|
|
139
|
+
# Some people suffix their versions with commit SHAs. Dependabot
|
|
140
|
+
# can't order on those but will try to, so instead we should exclude
|
|
141
|
+
# them (unless there's a `latest` version pushed to the registry, in
|
|
142
|
+
# which case we'll use that to find the latest version)
|
|
143
|
+
return false unless tag.match?(/(^|\-)[0-9a-f]{7,}$/)
|
|
144
|
+
|
|
145
|
+
!tag.match?(/(^|\-)20[0-1]\d{5}$/)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def version_of_latest_tag
|
|
149
|
+
return unless latest_digest
|
|
150
|
+
|
|
151
|
+
tags_from_registry.
|
|
152
|
+
select { |tag| canonical_version?(tag) }.
|
|
153
|
+
select { |t| digest_of(t) == latest_digest }.
|
|
154
|
+
map { |t| version_class.new(numeric_version_from(t)) }.
|
|
155
|
+
max
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
def canonical_version?(tag)
|
|
159
|
+
return false unless numeric_version_from(tag)
|
|
160
|
+
return true if tag == numeric_version_from(tag)
|
|
161
|
+
|
|
162
|
+
# .NET tags are suffixed with -sdk. There may be other cases we need
|
|
163
|
+
# to consider in future, too.
|
|
164
|
+
tag == numeric_version_from(tag) + "-sdk"
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
def updated_digest
|
|
168
|
+
@updated_digest ||=
|
|
169
|
+
begin
|
|
170
|
+
docker_registry_client.digest(docker_repo_name, latest_version)
|
|
171
|
+
rescue RestClient::Exceptions::Timeout
|
|
172
|
+
attempt ||= 1
|
|
173
|
+
attempt += 1
|
|
174
|
+
raise if attempt > 3
|
|
175
|
+
|
|
176
|
+
retry
|
|
177
|
+
end
|
|
178
|
+
rescue DockerRegistry2::RegistryAuthenticationException,
|
|
179
|
+
RestClient::Forbidden
|
|
180
|
+
raise PrivateSourceAuthenticationFailure, registry_hostname
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def tags_from_registry
|
|
184
|
+
@tags_from_registry ||=
|
|
185
|
+
begin
|
|
186
|
+
docker_registry_client.tags(docker_repo_name).fetch("tags")
|
|
187
|
+
rescue RestClient::Exceptions::Timeout
|
|
188
|
+
attempt ||= 1
|
|
189
|
+
attempt += 1
|
|
190
|
+
raise if attempt > 3
|
|
191
|
+
|
|
192
|
+
retry
|
|
193
|
+
end
|
|
194
|
+
rescue DockerRegistry2::RegistryAuthenticationException,
|
|
195
|
+
RestClient::Forbidden
|
|
196
|
+
raise PrivateSourceAuthenticationFailure, registry_hostname
|
|
197
|
+
end
|
|
198
|
+
|
|
199
|
+
def latest_digest
|
|
200
|
+
return unless tags_from_registry.include?("latest")
|
|
201
|
+
|
|
202
|
+
digest_of("latest")
|
|
203
|
+
end
|
|
204
|
+
|
|
205
|
+
def digest_of(tag)
|
|
206
|
+
@digests ||= {}
|
|
207
|
+
return @digests[tag] if @digests.key?(tag)
|
|
208
|
+
|
|
209
|
+
@digests[tag] =
|
|
210
|
+
begin
|
|
211
|
+
docker_registry_client.digest(docker_repo_name, tag)
|
|
212
|
+
rescue *transient_docker_errors => e
|
|
213
|
+
attempt ||= 1
|
|
214
|
+
attempt += 1
|
|
215
|
+
return if attempt > 3 && e.is_a?(DockerRegistry2::NotFound)
|
|
216
|
+
raise if attempt > 3
|
|
217
|
+
|
|
218
|
+
retry
|
|
219
|
+
end
|
|
220
|
+
end
|
|
221
|
+
|
|
222
|
+
def transient_docker_errors
|
|
223
|
+
[RestClient::Exceptions::Timeout, DockerRegistry2::NotFound]
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
def affix_of(tag)
|
|
227
|
+
tag.match(NAME_WITH_VERSION).named_captures.fetch("affix")
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
def prerelease?(tag)
|
|
231
|
+
return true if numeric_version_from(tag).match?(/[a-zA-Z]/)
|
|
232
|
+
|
|
233
|
+
# If we're dealing with a numeric version we can compare it against
|
|
234
|
+
# the digest for the `latest` tag.
|
|
235
|
+
return false unless numeric_version_from(tag)
|
|
236
|
+
return false unless latest_digest
|
|
237
|
+
return false unless version_of_latest_tag
|
|
238
|
+
|
|
239
|
+
version_class.new(numeric_version_from(tag)) > version_of_latest_tag
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def numeric_version_from(tag)
|
|
243
|
+
return unless tag.match?(NAME_WITH_VERSION)
|
|
244
|
+
|
|
245
|
+
tag.match(NAME_WITH_VERSION).named_captures.fetch("version")
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def registry_hostname
|
|
249
|
+
dependency.requirements.first[:source][:registry] ||
|
|
250
|
+
"registry.hub.docker.com"
|
|
251
|
+
end
|
|
252
|
+
|
|
253
|
+
def using_dockerhub?
|
|
254
|
+
registry_hostname == "registry.hub.docker.com"
|
|
255
|
+
end
|
|
256
|
+
|
|
257
|
+
def registry_credentials
|
|
258
|
+
credentials_finder.credentials_for_registry(registry_hostname)
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def credentials_finder
|
|
262
|
+
@credentials_finder ||=
|
|
263
|
+
Utils::Docker::CredentialsFinder.new(credentials)
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def docker_repo_name
|
|
267
|
+
return dependency.name unless using_dockerhub?
|
|
268
|
+
return dependency.name unless dependency.name.split("/").count < 2
|
|
269
|
+
|
|
270
|
+
"library/#{dependency.name}"
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def docker_registry_client
|
|
274
|
+
@docker_registry_client ||=
|
|
275
|
+
DockerRegistry2::Registry.new(
|
|
276
|
+
"https://#{registry_hostname}",
|
|
277
|
+
user: registry_credentials&.fetch("username"),
|
|
278
|
+
password: registry_credentials&.fetch("password")
|
|
279
|
+
)
|
|
280
|
+
end
|
|
281
|
+
|
|
282
|
+
def ignore_reqs
|
|
283
|
+
# Note: we use Gem::Requirement here because ignore conditions will
|
|
284
|
+
# be passed as Ruby ranges
|
|
285
|
+
ignored_versions.map { |req| Gem::Requirement.new(req.split(",")) }
|
|
286
|
+
end
|
|
287
|
+
end
|
|
288
|
+
end
|
|
289
|
+
end
|
|
290
|
+
end
|