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,888 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "pathname"
|
|
4
|
+
require "dependabot/clients/github_with_retries"
|
|
5
|
+
require "dependabot/clients/gitlab"
|
|
6
|
+
require "dependabot/metadata_finders"
|
|
7
|
+
require "dependabot/pull_request_creator"
|
|
8
|
+
|
|
9
|
+
# rubocop:disable Metrics/ClassLength
|
|
10
|
+
module Dependabot
|
|
11
|
+
class PullRequestCreator
|
|
12
|
+
class MessageBuilder
|
|
13
|
+
ANGULAR_PREFIXES = %w(build chore ci docs feat fix perf refactor style
|
|
14
|
+
test).freeze
|
|
15
|
+
ESLINT_PREFIXES = %w(Breaking Build Chore Docs Fix New Update
|
|
16
|
+
Upgrade).freeze
|
|
17
|
+
GITMOJI_PREFIXES = %w(art zap fire bug ambulance sparkles memo rocket
|
|
18
|
+
lipstick tada white_check_mark lock apple penguin
|
|
19
|
+
checkered_flag robot green_apple bookmark
|
|
20
|
+
rotating_light construction green_heart arrow_down
|
|
21
|
+
arrow_up pushpin construction_worker
|
|
22
|
+
chart_with_upwards_trend recycle heavy_minus_sign
|
|
23
|
+
whale heavy_plus_sign wrench globe_with_meridians
|
|
24
|
+
pencil2 hankey rewind twisted_rightwards_arrows
|
|
25
|
+
package alien truck page_facing_up boom bento
|
|
26
|
+
ok_hand wheelchair bulb beers speech_balloon
|
|
27
|
+
card_file_box loud_sound mute busts_in_silhouette
|
|
28
|
+
children_crossing building_construction iphone
|
|
29
|
+
clown_face egg see_no_evil camera_flash).freeze
|
|
30
|
+
ISSUE_TAG_REGEX =
|
|
31
|
+
/(?<=[\s(\\]|^)(?<tag>(?:\#|GH-)\d+)(?=[^A-z0-9\-]|$)/.freeze
|
|
32
|
+
GITHUB_REF_REGEX = %r{github\.com/[^/\s]+/[^/\s]+/(?:issue|pull)}.freeze
|
|
33
|
+
|
|
34
|
+
attr_reader :source, :dependencies, :files, :credentials,
|
|
35
|
+
:pr_message_footer, :author_details, :vulnerabilities_fixed
|
|
36
|
+
|
|
37
|
+
def initialize(source:, dependencies:, files:, credentials:,
|
|
38
|
+
pr_message_footer: nil, author_details: nil,
|
|
39
|
+
vulnerabilities_fixed: {})
|
|
40
|
+
@dependencies = dependencies
|
|
41
|
+
@files = files
|
|
42
|
+
@source = source
|
|
43
|
+
@credentials = credentials
|
|
44
|
+
@pr_message_footer = pr_message_footer
|
|
45
|
+
@author_details = author_details
|
|
46
|
+
@vulnerabilities_fixed = vulnerabilities_fixed
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def pr_name
|
|
50
|
+
return library_pr_name if library?
|
|
51
|
+
|
|
52
|
+
application_pr_name
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def pr_message
|
|
56
|
+
commit_message_intro + metadata_cascades + prefixed_pr_message_footer
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def commit_message
|
|
60
|
+
message = commit_subject + "\n\n"
|
|
61
|
+
message += commit_message_intro
|
|
62
|
+
message += metadata_links
|
|
63
|
+
message += "\n\n" + signoff_message if signoff_message
|
|
64
|
+
message
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def commit_subject
|
|
70
|
+
subject = pr_name.gsub("⬆️", ":arrow_up:").gsub("🔒", ":lock:")
|
|
71
|
+
return subject unless subject.length > 72
|
|
72
|
+
|
|
73
|
+
subject.split(" from ").first
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def commit_message_intro
|
|
77
|
+
return requirement_commit_message_intro if library?
|
|
78
|
+
|
|
79
|
+
version_commit_message_intro
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def prefixed_pr_message_footer
|
|
83
|
+
return "" unless pr_message_footer
|
|
84
|
+
|
|
85
|
+
"\n\n#{pr_message_footer}"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def signoff_message
|
|
89
|
+
return unless author_details.is_a?(Hash)
|
|
90
|
+
return unless author_details[:name] && author_details[:email]
|
|
91
|
+
|
|
92
|
+
"Signed-off-by: #{author_details[:name]} <#{author_details[:email]}>"
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def library_pr_name
|
|
96
|
+
pr_name = pr_name_prefix
|
|
97
|
+
|
|
98
|
+
pr_name +=
|
|
99
|
+
if dependencies.count == 1
|
|
100
|
+
"#{dependencies.first.display_name} requirement "\
|
|
101
|
+
"from #{old_library_requirement(dependencies.first)} "\
|
|
102
|
+
"to #{new_library_requirement(dependencies.first)}"
|
|
103
|
+
else
|
|
104
|
+
names = dependencies.map(&:name)
|
|
105
|
+
"requirements for #{names[0..-2].join(', ')} and #{names[-1]}"
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
return pr_name if files.first.directory == "/"
|
|
109
|
+
|
|
110
|
+
pr_name + " in #{files.first.directory}"
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# rubocop:disable Metrics/AbcSize
|
|
114
|
+
def application_pr_name
|
|
115
|
+
pr_name = pr_name_prefix
|
|
116
|
+
|
|
117
|
+
pr_name +=
|
|
118
|
+
if dependencies.count == 1
|
|
119
|
+
dependency = dependencies.first
|
|
120
|
+
"#{dependency.display_name} from #{previous_version(dependency)} "\
|
|
121
|
+
"to #{new_version(dependency)}"
|
|
122
|
+
elsif updating_a_property?
|
|
123
|
+
dependency = dependencies.first
|
|
124
|
+
"#{property_name} from #{previous_version(dependency)} "\
|
|
125
|
+
"to #{new_version(dependency)}"
|
|
126
|
+
elsif updating_a_dependency_set?
|
|
127
|
+
dependency = dependencies.first
|
|
128
|
+
"#{dependency_set.fetch(:group)} dependency set "\
|
|
129
|
+
"from #{previous_version(dependency)} "\
|
|
130
|
+
"to #{new_version(dependency)}"
|
|
131
|
+
else
|
|
132
|
+
names = dependencies.map(&:name)
|
|
133
|
+
"#{names[0..-2].join(', ')} and #{names[-1]}"
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
return pr_name if files.first.directory == "/"
|
|
137
|
+
|
|
138
|
+
pr_name + " in #{files.first.directory}"
|
|
139
|
+
end
|
|
140
|
+
# rubocop:enable Metrics/AbcSize
|
|
141
|
+
|
|
142
|
+
def pr_name_prefix
|
|
143
|
+
prefix = commit_prefix.to_s
|
|
144
|
+
prefix += security_prefix if includes_security_fixes?
|
|
145
|
+
prefix + pr_name_first_word
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def commit_prefix
|
|
149
|
+
# If there is a previous Dependabot commit, and it used a known style,
|
|
150
|
+
# use that as our model for subsequent commits
|
|
151
|
+
case last_dependabot_commit_style
|
|
152
|
+
when :gitmoji then "⬆️ "
|
|
153
|
+
when :contentional_prefix then "#{last_dependabot_commit_prefix}: "
|
|
154
|
+
when :contentional_prefix_with_scope
|
|
155
|
+
scope = dependencies.any?(&:production?) ? "deps" : "deps-dev"
|
|
156
|
+
"#{last_dependabot_commit_prefix}(#{scope}): "
|
|
157
|
+
else
|
|
158
|
+
# Otherwise we need to detect the user's preferred style from the
|
|
159
|
+
# existing commits on their repo
|
|
160
|
+
build_commit_prefix_from_previous_commits
|
|
161
|
+
end
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def security_prefix
|
|
165
|
+
return "🔒 " if commit_prefix == "⬆️ "
|
|
166
|
+
|
|
167
|
+
capitalize_first_word? ? "[Security] " : "[security] "
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
def pr_name_first_word
|
|
171
|
+
first_word = library? ? "update " : "bump "
|
|
172
|
+
capitalize_first_word? ? first_word.capitalize : first_word
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
def capitalize_first_word?
|
|
176
|
+
case last_dependabot_commit_style
|
|
177
|
+
when :gitmoji then true
|
|
178
|
+
when :contentional_prefix, :contentional_prefix_with_scope
|
|
179
|
+
last_dependabot_commit_message.match?(/: (\[Security\] )?(B|U)/)
|
|
180
|
+
else
|
|
181
|
+
if using_angular_commit_messages? || using_eslint_commit_messages?
|
|
182
|
+
prefixes = ANGULAR_PREFIXES + ESLINT_PREFIXES
|
|
183
|
+
semantic_msgs = recent_commit_messages.select do |message|
|
|
184
|
+
prefixes.any? { |pre| message.match?(/#{pre}[:(]/i) }
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
return true if semantic_msgs.all? { |m| m.match?(/:\s+\[?[A-Z]/) }
|
|
188
|
+
return false if semantic_msgs.all? { |m| m.match?(/:\s+\[?[a-z]/) }
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
!commit_prefix&.match(/^[a-z]/)
|
|
192
|
+
end
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def build_commit_prefix_from_previous_commits
|
|
196
|
+
if using_angular_commit_messages?
|
|
197
|
+
scope = dependencies.any?(&:production?) ? "deps" : "deps-dev"
|
|
198
|
+
"#{angular_commit_prefix}(#{scope}): "
|
|
199
|
+
elsif using_eslint_commit_messages?
|
|
200
|
+
# https://eslint.org/docs/developer-guide/contributing/pull-requests
|
|
201
|
+
"Upgrade: "
|
|
202
|
+
elsif using_gitmoji_commit_messages?
|
|
203
|
+
"⬆️ "
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def last_dependabot_commit_style
|
|
208
|
+
return unless (msg = last_dependabot_commit_message)
|
|
209
|
+
|
|
210
|
+
return :gitmoji if msg.start_with?("⬆️")
|
|
211
|
+
return :contentional_prefix if msg.match?(/^(chore|build|upgrade):/i)
|
|
212
|
+
return unless msg.match?(/^(chore|build|upgrade)\(/i)
|
|
213
|
+
|
|
214
|
+
:contentional_prefix_with_scope
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
def last_dependabot_commit_prefix
|
|
218
|
+
last_dependabot_commit_message&.split(/[:(]/)&.first
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def requirement_commit_message_intro
|
|
222
|
+
msg = "Updates the requirements on "
|
|
223
|
+
|
|
224
|
+
msg +=
|
|
225
|
+
if dependencies.count == 1
|
|
226
|
+
"#{dependency_links.first} "
|
|
227
|
+
else
|
|
228
|
+
"#{dependency_links[0..-2].join(', ')} and #{dependency_links[-1]} "
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
msg + "to permit the latest version."
|
|
232
|
+
end
|
|
233
|
+
|
|
234
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
|
235
|
+
# rubocop:disable Metrics/PerceivedComplexity
|
|
236
|
+
def version_commit_message_intro
|
|
237
|
+
if dependencies.count > 1 && updating_a_property?
|
|
238
|
+
return multidependency_property_intro
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
if dependencies.count > 1 && updating_a_dependency_set?
|
|
242
|
+
return dependency_set_intro
|
|
243
|
+
end
|
|
244
|
+
|
|
245
|
+
return multidependency_intro if dependencies.count > 1
|
|
246
|
+
|
|
247
|
+
dependency = dependencies.first
|
|
248
|
+
msg = "Bumps #{dependency_links.first} "\
|
|
249
|
+
"from #{previous_version(dependency)} "\
|
|
250
|
+
"to #{new_version(dependency)}."
|
|
251
|
+
|
|
252
|
+
if switching_from_ref_to_release?(dependency)
|
|
253
|
+
msg += " This release includes the previously tagged commit."
|
|
254
|
+
end
|
|
255
|
+
|
|
256
|
+
if vulnerabilities_fixed[dependency.name]&.any?
|
|
257
|
+
msg += " **This update includes security fixes.**"
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
msg
|
|
261
|
+
end
|
|
262
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
|
263
|
+
# rubocop:enable Metrics/PerceivedComplexity
|
|
264
|
+
|
|
265
|
+
def multidependency_property_intro
|
|
266
|
+
dependency = dependencies.first
|
|
267
|
+
|
|
268
|
+
"Bumps `#{property_name}` "\
|
|
269
|
+
"from #{previous_version(dependency)} "\
|
|
270
|
+
"to #{new_version(dependency)}."
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def dependency_set_intro
|
|
274
|
+
dependency = dependencies.first
|
|
275
|
+
|
|
276
|
+
"Bumps `#{dependency_set.fetch(:group)}` "\
|
|
277
|
+
"dependency set from #{previous_version(dependency)} "\
|
|
278
|
+
"to #{new_version(dependency)}."
|
|
279
|
+
end
|
|
280
|
+
|
|
281
|
+
def multidependency_intro
|
|
282
|
+
"Bumps #{dependency_links[0..-2].join(', ')} "\
|
|
283
|
+
"and #{dependency_links[-1]}. These "\
|
|
284
|
+
"dependencies needed to be updated together."
|
|
285
|
+
end
|
|
286
|
+
|
|
287
|
+
def updating_a_property?
|
|
288
|
+
dependencies.first.
|
|
289
|
+
requirements.
|
|
290
|
+
any? { |r| r.dig(:metadata, :property_name) }
|
|
291
|
+
end
|
|
292
|
+
|
|
293
|
+
def updating_a_dependency_set?
|
|
294
|
+
dependencies.first.
|
|
295
|
+
requirements.
|
|
296
|
+
any? { |r| r.dig(:metadata, :dependency_set) }
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
def property_name
|
|
300
|
+
@property_name ||= dependencies.first.requirements.
|
|
301
|
+
find { |r| r.dig(:metadata, :property_name) }&.
|
|
302
|
+
dig(:metadata, :property_name)
|
|
303
|
+
|
|
304
|
+
raise "No property name!" unless @property_name
|
|
305
|
+
|
|
306
|
+
@property_name
|
|
307
|
+
end
|
|
308
|
+
|
|
309
|
+
def dependency_set
|
|
310
|
+
@dependency_set ||= dependencies.first.requirements.
|
|
311
|
+
find { |r| r.dig(:metadata, :dependency_set) }&.
|
|
312
|
+
dig(:metadata, :dependency_set)
|
|
313
|
+
|
|
314
|
+
raise "No dependency set!" unless @dependency_set
|
|
315
|
+
|
|
316
|
+
@dependency_set
|
|
317
|
+
end
|
|
318
|
+
|
|
319
|
+
def dependency_links
|
|
320
|
+
dependencies.map do |dependency|
|
|
321
|
+
if source_url(dependency)
|
|
322
|
+
"[#{dependency.display_name}](#{source_url(dependency)})"
|
|
323
|
+
elsif homepage_url(dependency)
|
|
324
|
+
"[#{dependency.display_name}](#{homepage_url(dependency)})"
|
|
325
|
+
else
|
|
326
|
+
dependency.display_name
|
|
327
|
+
end
|
|
328
|
+
end
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
def metadata_links
|
|
332
|
+
if dependencies.count == 1
|
|
333
|
+
return metadata_links_for_dep(dependencies.first)
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
dependencies.map do |dep|
|
|
337
|
+
"\n\nUpdates `#{dep.display_name}` from #{previous_version(dep)} to "\
|
|
338
|
+
"#{new_version(dep)}"\
|
|
339
|
+
"#{metadata_links_for_dep(dep)}"
|
|
340
|
+
end.join
|
|
341
|
+
end
|
|
342
|
+
|
|
343
|
+
def metadata_links_for_dep(dep)
|
|
344
|
+
msg = ""
|
|
345
|
+
msg += "\n- [Release notes](#{releases_url(dep)})" if releases_url(dep)
|
|
346
|
+
msg += "\n- [Changelog](#{changelog_url(dep)})" if changelog_url(dep)
|
|
347
|
+
msg += "\n- [Upgrade guide](#{upgrade_url(dep)})" if upgrade_url(dep)
|
|
348
|
+
msg += "\n- [Commits](#{commits_url(dep)})" if commits_url(dep)
|
|
349
|
+
msg
|
|
350
|
+
end
|
|
351
|
+
|
|
352
|
+
def metadata_cascades
|
|
353
|
+
if dependencies.count == 1
|
|
354
|
+
return metadata_cascades_for_dep(dependencies.first)
|
|
355
|
+
end
|
|
356
|
+
|
|
357
|
+
dependencies.map do |dep|
|
|
358
|
+
msg = "\n\nUpdates `#{dep.display_name}` from "\
|
|
359
|
+
"#{previous_version(dep)} to #{new_version(dep)}"
|
|
360
|
+
if vulnerabilities_fixed[dep.name]&.any?
|
|
361
|
+
msg += ". **This update includes security fixes.**"
|
|
362
|
+
end
|
|
363
|
+
msg + metadata_cascades_for_dep(dep)
|
|
364
|
+
end.join
|
|
365
|
+
end
|
|
366
|
+
|
|
367
|
+
def metadata_cascades_for_dep(dep)
|
|
368
|
+
msg = ""
|
|
369
|
+
msg += vulnerabilities_cascade(dep)
|
|
370
|
+
msg += release_cascade(dep)
|
|
371
|
+
msg += changelog_cascade(dep)
|
|
372
|
+
msg += upgrade_guide_cascade(dep)
|
|
373
|
+
msg += commits_cascade(dep)
|
|
374
|
+
msg += maintainer_changes_cascade(dep)
|
|
375
|
+
msg += "\n<br />" unless msg == ""
|
|
376
|
+
sanitize_links_and_mentions(msg)
|
|
377
|
+
end
|
|
378
|
+
|
|
379
|
+
def vulnerabilities_cascade(dep)
|
|
380
|
+
fixed_vulns = vulnerabilities_fixed[dep.name]
|
|
381
|
+
return "" unless fixed_vulns&.any?
|
|
382
|
+
|
|
383
|
+
msg = "\n<details>\n<summary>Vulnerabilities fixed</summary>\n\n"
|
|
384
|
+
fixed_vulns.each { |v| msg += serialized_vulnerability_details(v) }
|
|
385
|
+
msg += "</details>"
|
|
386
|
+
sanitize_template_tags(msg)
|
|
387
|
+
end
|
|
388
|
+
|
|
389
|
+
def release_cascade(dep)
|
|
390
|
+
return "" unless releases_text(dep) && releases_url(dep)
|
|
391
|
+
|
|
392
|
+
msg = "\n<details>\n<summary>Release notes</summary>\n\n"
|
|
393
|
+
msg += "*Sourced from [#{dep.display_name}'s releases]"\
|
|
394
|
+
"(#{releases_url(dep)}).*\n\n"
|
|
395
|
+
msg +=
|
|
396
|
+
begin
|
|
397
|
+
release_note_lines = releases_text(dep).split("\n").first(50)
|
|
398
|
+
release_note_lines = release_note_lines.map { |line| "> #{line}\n" }
|
|
399
|
+
if release_note_lines.count == 50
|
|
400
|
+
release_note_lines << truncated_line
|
|
401
|
+
end
|
|
402
|
+
release_note_lines.join
|
|
403
|
+
end
|
|
404
|
+
msg += "</details>"
|
|
405
|
+
msg = link_issues(text: msg, dependency: dep)
|
|
406
|
+
sanitize_template_tags(msg)
|
|
407
|
+
end
|
|
408
|
+
|
|
409
|
+
def changelog_cascade(dep)
|
|
410
|
+
return "" unless changelog_url(dep) && changelog_text(dep)
|
|
411
|
+
|
|
412
|
+
msg = "\n<details>\n<summary>Changelog</summary>\n\n"
|
|
413
|
+
msg += "*Sourced from "\
|
|
414
|
+
"[#{dep.display_name}'s changelog](#{changelog_url(dep)}).*\n\n"
|
|
415
|
+
msg +=
|
|
416
|
+
begin
|
|
417
|
+
changelog_lines = changelog_text(dep).split("\n").first(50)
|
|
418
|
+
changelog_lines = changelog_lines.map { |line| "> #{line}\n" }
|
|
419
|
+
changelog_lines << truncated_line if changelog_lines.count == 50
|
|
420
|
+
changelog_lines.join
|
|
421
|
+
end
|
|
422
|
+
msg += "</details>"
|
|
423
|
+
msg = link_issues(text: msg, dependency: dep)
|
|
424
|
+
msg = fix_relative_links(text: msg, base_url: changelog_url(dep))
|
|
425
|
+
sanitize_template_tags(msg)
|
|
426
|
+
end
|
|
427
|
+
|
|
428
|
+
def upgrade_guide_cascade(dep)
|
|
429
|
+
return "" unless upgrade_url(dep) && upgrade_text(dep)
|
|
430
|
+
|
|
431
|
+
msg = "\n<details>\n<summary>Upgrade guide</summary>\n\n"
|
|
432
|
+
msg += "*Sourced from "\
|
|
433
|
+
"[#{dep.display_name}'s upgrade guide]"\
|
|
434
|
+
"(#{upgrade_url(dep)}).*\n\n"
|
|
435
|
+
msg +=
|
|
436
|
+
begin
|
|
437
|
+
upgrade_lines = upgrade_text(dep).split("\n").first(50)
|
|
438
|
+
upgrade_lines = upgrade_lines.map { |line| "> #{line}\n" }
|
|
439
|
+
upgrade_lines << truncated_line if upgrade_lines.count == 50
|
|
440
|
+
upgrade_lines.join
|
|
441
|
+
end
|
|
442
|
+
msg += "</details>"
|
|
443
|
+
msg = link_issues(text: msg, dependency: dep)
|
|
444
|
+
msg = fix_relative_links(text: msg, base_url: upgrade_url(dep))
|
|
445
|
+
sanitize_template_tags(msg)
|
|
446
|
+
end
|
|
447
|
+
|
|
448
|
+
def commits_cascade(dep)
|
|
449
|
+
return "" unless commits_url(dep) && commits(dep)
|
|
450
|
+
|
|
451
|
+
msg = "\n<details>\n<summary>Commits</summary>\n\n"
|
|
452
|
+
|
|
453
|
+
commits(dep).reverse.first(10).each do |commit|
|
|
454
|
+
title = commit[:message].strip.split("\n").first
|
|
455
|
+
title = title.slice(0..76) + "..." if title && title.length > 80
|
|
456
|
+
sha = commit[:sha][0, 7]
|
|
457
|
+
msg += "- [`#{sha}`](#{commit[:html_url]}) #{title}\n"
|
|
458
|
+
end
|
|
459
|
+
|
|
460
|
+
msg +=
|
|
461
|
+
if commits(dep).count > 10
|
|
462
|
+
"- Additional commits viewable in "\
|
|
463
|
+
"[compare view](#{commits_url(dep)})\n"
|
|
464
|
+
else
|
|
465
|
+
"- See full diff in [compare view](#{commits_url(dep)})\n"
|
|
466
|
+
end
|
|
467
|
+
|
|
468
|
+
msg += "</details>"
|
|
469
|
+
msg = link_issues(text: msg, dependency: dep)
|
|
470
|
+
sanitize_template_tags(msg)
|
|
471
|
+
end
|
|
472
|
+
|
|
473
|
+
def maintainer_changes_cascade(dep)
|
|
474
|
+
return "" unless maintainer_changes(dep)
|
|
475
|
+
|
|
476
|
+
msg = "\n<details>\n<summary>Maintainer changes</summary>\n\n"
|
|
477
|
+
msg += maintainer_changes(dep)
|
|
478
|
+
msg + "\n</details>"
|
|
479
|
+
end
|
|
480
|
+
|
|
481
|
+
def serialized_vulnerability_details(details)
|
|
482
|
+
msg = vulnerability_source_line(details)
|
|
483
|
+
|
|
484
|
+
if details["title"]
|
|
485
|
+
msg += "> **#{details['title'].lines.map(&:strip).join(' ')}**\n"
|
|
486
|
+
end
|
|
487
|
+
|
|
488
|
+
if (description = details["description"])
|
|
489
|
+
description.strip.lines.first(20).each { |line| msg += "> #{line}" }
|
|
490
|
+
msg += truncated_line if description.strip.lines.count > 20
|
|
491
|
+
end
|
|
492
|
+
|
|
493
|
+
msg += "\n" unless msg.end_with?("\n")
|
|
494
|
+
msg += "> \n"
|
|
495
|
+
msg += vulnerability_version_range_lines(details)
|
|
496
|
+
msg + "\n"
|
|
497
|
+
end
|
|
498
|
+
|
|
499
|
+
def vulnerability_source_line(details)
|
|
500
|
+
if details["source_url"] && details["source_name"]
|
|
501
|
+
"*Sourced from [#{details['source_name']}]"\
|
|
502
|
+
"(#{details['source_url']}).*\n\n"
|
|
503
|
+
elsif details["source_name"]
|
|
504
|
+
"*Sourced from #{details['source_name']}.*\n\n"
|
|
505
|
+
else
|
|
506
|
+
""
|
|
507
|
+
end
|
|
508
|
+
end
|
|
509
|
+
|
|
510
|
+
def vulnerability_version_range_lines(details)
|
|
511
|
+
msg = ""
|
|
512
|
+
%w(patched_versions unaffected_versions affected_versions).each do |tp|
|
|
513
|
+
type = tp.split("_").first.capitalize
|
|
514
|
+
next unless details[tp]
|
|
515
|
+
|
|
516
|
+
versions_string = details[tp].any? ? details[tp].join("; ") : "none"
|
|
517
|
+
versions_string = versions_string.gsub(/(?<!\\)~/, '\~')
|
|
518
|
+
msg += "> #{type} versions: #{versions_string}\n"
|
|
519
|
+
end
|
|
520
|
+
msg
|
|
521
|
+
end
|
|
522
|
+
|
|
523
|
+
def truncated_line
|
|
524
|
+
# Tables can spill out of truncated details, so we close them
|
|
525
|
+
"></table> ... (truncated)\n"
|
|
526
|
+
end
|
|
527
|
+
|
|
528
|
+
def releases_url(dependency)
|
|
529
|
+
metadata_finder(dependency).releases_url
|
|
530
|
+
end
|
|
531
|
+
|
|
532
|
+
def releases_text(dependency)
|
|
533
|
+
metadata_finder(dependency).releases_text
|
|
534
|
+
end
|
|
535
|
+
|
|
536
|
+
def changelog_url(dependency)
|
|
537
|
+
metadata_finder(dependency).changelog_url
|
|
538
|
+
end
|
|
539
|
+
|
|
540
|
+
def changelog_text(dependency)
|
|
541
|
+
metadata_finder(dependency).changelog_text
|
|
542
|
+
end
|
|
543
|
+
|
|
544
|
+
def upgrade_url(dependency)
|
|
545
|
+
metadata_finder(dependency).upgrade_guide_url
|
|
546
|
+
end
|
|
547
|
+
|
|
548
|
+
def upgrade_text(dependency)
|
|
549
|
+
metadata_finder(dependency).upgrade_guide_text
|
|
550
|
+
end
|
|
551
|
+
|
|
552
|
+
def commits_url(dependency)
|
|
553
|
+
metadata_finder(dependency).commits_url
|
|
554
|
+
end
|
|
555
|
+
|
|
556
|
+
def commits(dependency)
|
|
557
|
+
metadata_finder(dependency).commits
|
|
558
|
+
end
|
|
559
|
+
|
|
560
|
+
def maintainer_changes(dependency)
|
|
561
|
+
metadata_finder(dependency).maintainer_changes
|
|
562
|
+
end
|
|
563
|
+
|
|
564
|
+
def source_url(dependency)
|
|
565
|
+
metadata_finder(dependency).source_url
|
|
566
|
+
end
|
|
567
|
+
|
|
568
|
+
def homepage_url(dependency)
|
|
569
|
+
metadata_finder(dependency).homepage_url
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def metadata_finder(dependency)
|
|
573
|
+
@metadata_finder ||= {}
|
|
574
|
+
@metadata_finder[dependency.name] ||=
|
|
575
|
+
MetadataFinders.
|
|
576
|
+
for_package_manager(dependency.package_manager).
|
|
577
|
+
new(dependency: dependency, credentials: credentials)
|
|
578
|
+
end
|
|
579
|
+
|
|
580
|
+
def previous_version(dependency)
|
|
581
|
+
if dependency.previous_version.match?(/^[0-9a-f]{40}$/)
|
|
582
|
+
return previous_ref(dependency) if ref_changed?(dependency)
|
|
583
|
+
|
|
584
|
+
"`#{dependency.previous_version[0..6]}`"
|
|
585
|
+
elsif dependency.version == dependency.previous_version &&
|
|
586
|
+
package_manager == "docker"
|
|
587
|
+
digest =
|
|
588
|
+
dependency.previous_requirements.
|
|
589
|
+
map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) }.
|
|
590
|
+
compact.first
|
|
591
|
+
"`#{digest.split(':').last[0..6]}`"
|
|
592
|
+
else
|
|
593
|
+
dependency.previous_version
|
|
594
|
+
end
|
|
595
|
+
end
|
|
596
|
+
|
|
597
|
+
def new_version(dependency)
|
|
598
|
+
if dependency.version.match?(/^[0-9a-f]{40}$/)
|
|
599
|
+
return new_ref(dependency) if ref_changed?(dependency)
|
|
600
|
+
|
|
601
|
+
"`#{dependency.version[0..6]}`"
|
|
602
|
+
elsif dependency.version == dependency.previous_version &&
|
|
603
|
+
package_manager == "docker"
|
|
604
|
+
digest =
|
|
605
|
+
dependency.requirements.
|
|
606
|
+
map { |r| r.dig(:source, "digest") || r.dig(:source, :digest) }.
|
|
607
|
+
compact.first
|
|
608
|
+
"`#{digest.split(':').last[0..6]}`"
|
|
609
|
+
else
|
|
610
|
+
dependency.version
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
|
|
614
|
+
def previous_ref(dependency)
|
|
615
|
+
dependency.previous_requirements.map do |r|
|
|
616
|
+
r.dig(:source, "ref") || r.dig(:source, :ref)
|
|
617
|
+
end.compact.first
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
def new_ref(dependency)
|
|
621
|
+
dependency.requirements.map do |r|
|
|
622
|
+
r.dig(:source, "ref") || r.dig(:source, :ref)
|
|
623
|
+
end.compact.first
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
def old_library_requirement(dependency)
|
|
627
|
+
old_reqs =
|
|
628
|
+
dependency.previous_requirements - dependency.requirements
|
|
629
|
+
|
|
630
|
+
gemspec =
|
|
631
|
+
old_reqs.find { |r| r[:file].match?(%r{^[^/]*\.gemspec$}) }
|
|
632
|
+
return gemspec.fetch(:requirement) if gemspec
|
|
633
|
+
|
|
634
|
+
old_reqs.first.fetch(:requirement)
|
|
635
|
+
end
|
|
636
|
+
|
|
637
|
+
def new_library_requirement(dependency)
|
|
638
|
+
updated_reqs =
|
|
639
|
+
dependency.requirements - dependency.previous_requirements
|
|
640
|
+
|
|
641
|
+
gemspec =
|
|
642
|
+
updated_reqs.find { |r| r[:file].match?(%r{^[^/]*\.gemspec$}) }
|
|
643
|
+
return gemspec.fetch(:requirement) if gemspec
|
|
644
|
+
|
|
645
|
+
updated_reqs.first.fetch(:requirement)
|
|
646
|
+
end
|
|
647
|
+
|
|
648
|
+
def link_issues(text:, dependency:)
|
|
649
|
+
text.gsub(ISSUE_TAG_REGEX) do |mention|
|
|
650
|
+
number = mention.tr("#", "").gsub("GH-", "")
|
|
651
|
+
"[#{mention}](#{source_url(dependency)}/issues/#{number})"
|
|
652
|
+
end
|
|
653
|
+
end
|
|
654
|
+
|
|
655
|
+
def fix_relative_links(text:, base_url:)
|
|
656
|
+
text.gsub(/\[.*?\]\(\..*?\)/) do |link|
|
|
657
|
+
relative_path = link.match(/\((\..*?)\)/).captures.last
|
|
658
|
+
base = base_url.split("://").last.gsub(%r{[^/]*$}, "")
|
|
659
|
+
path = File.join(base, relative_path)
|
|
660
|
+
absolute_path =
|
|
661
|
+
base_url.sub(
|
|
662
|
+
%r{(?<=://).*$},
|
|
663
|
+
Pathname.new(path).cleanpath.to_s
|
|
664
|
+
)
|
|
665
|
+
link.gsub(relative_path, absolute_path)
|
|
666
|
+
end
|
|
667
|
+
end
|
|
668
|
+
|
|
669
|
+
def sanitize_links_and_mentions(text)
|
|
670
|
+
text = text.gsub(%r{(?<![A-Za-z0-9\-])@[A-Za-z0-9\-/]+}) do |mention|
|
|
671
|
+
next mention if mention.include?("/")
|
|
672
|
+
|
|
673
|
+
"[**#{mention.tr('@', '')}**]"\
|
|
674
|
+
"(https://github.com/#{mention.tr('@', '')})"
|
|
675
|
+
end
|
|
676
|
+
|
|
677
|
+
text.gsub(GITHUB_REF_REGEX) do |ref|
|
|
678
|
+
ref.gsub("github.com", "github-redirect.dependabot.com")
|
|
679
|
+
end
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
def sanitize_template_tags(text)
|
|
683
|
+
text.gsub(/\<.*?\>/) do |tag|
|
|
684
|
+
tag_contents = tag.match(/\<(.*?)\>/).captures.first.strip
|
|
685
|
+
|
|
686
|
+
# Unclosed calls to template overflow out of the blockquote block,
|
|
687
|
+
# wrecking the rest of our PRs. Other tags don't share this problem.
|
|
688
|
+
next "\\#{tag}" if tag_contents.start_with?("template")
|
|
689
|
+
|
|
690
|
+
tag
|
|
691
|
+
end
|
|
692
|
+
end
|
|
693
|
+
|
|
694
|
+
def ref_changed?(dependency)
|
|
695
|
+
previous_ref(dependency) && new_ref(dependency) &&
|
|
696
|
+
previous_ref(dependency) != new_ref(dependency)
|
|
697
|
+
end
|
|
698
|
+
|
|
699
|
+
def library?
|
|
700
|
+
filenames = files.map(&:name)
|
|
701
|
+
return true if filenames.any? { |nm| nm.match?(%r{^[^/]*\.gemspec$}) }
|
|
702
|
+
|
|
703
|
+
dependencies.none?(&:appears_in_lockfile?)
|
|
704
|
+
end
|
|
705
|
+
|
|
706
|
+
def switching_from_ref_to_release?(dependency)
|
|
707
|
+
return false unless dependency.previous_version.match?(/^[0-9a-f]{40}$/)
|
|
708
|
+
|
|
709
|
+
Gem::Version.correct?(dependency.version)
|
|
710
|
+
end
|
|
711
|
+
|
|
712
|
+
def includes_security_fixes?
|
|
713
|
+
vulnerabilities_fixed.values.flatten.any?
|
|
714
|
+
end
|
|
715
|
+
|
|
716
|
+
def using_angular_commit_messages?
|
|
717
|
+
return false if recent_commit_messages.none?
|
|
718
|
+
|
|
719
|
+
angular_messages = recent_commit_messages.select do |message|
|
|
720
|
+
ANGULAR_PREFIXES.any? { |pre| message.match?(/#{pre}[:(]/i) }
|
|
721
|
+
end
|
|
722
|
+
|
|
723
|
+
# Definitely not using Angular commits if < 30% match angular commits
|
|
724
|
+
if angular_messages.count.to_f / recent_commit_messages.count < 0.3
|
|
725
|
+
return false
|
|
726
|
+
end
|
|
727
|
+
|
|
728
|
+
eslint_only_pres = ESLINT_PREFIXES.map(&:downcase) - ANGULAR_PREFIXES
|
|
729
|
+
angular_only_pres = ANGULAR_PREFIXES - ESLINT_PREFIXES.map(&:downcase)
|
|
730
|
+
|
|
731
|
+
uses_eslint_only_pres =
|
|
732
|
+
recent_commit_messages.
|
|
733
|
+
any? { |m| eslint_only_pres.any? { |pre| m.match?(/#{pre}[:(]/i) } }
|
|
734
|
+
|
|
735
|
+
uses_angular_only_pres =
|
|
736
|
+
recent_commit_messages.
|
|
737
|
+
any? { |m| angular_only_pres.any? { |pre| m.match?(/#{pre}[:(]/i) } }
|
|
738
|
+
|
|
739
|
+
# If using any angular-only prefixes, return true
|
|
740
|
+
# (i.e., we assume Angular over ESLint when both are present)
|
|
741
|
+
return true if uses_angular_only_pres
|
|
742
|
+
return false if uses_eslint_only_pres
|
|
743
|
+
|
|
744
|
+
true
|
|
745
|
+
end
|
|
746
|
+
|
|
747
|
+
def using_eslint_commit_messages?
|
|
748
|
+
return false if recent_commit_messages.none?
|
|
749
|
+
|
|
750
|
+
semantic_messages = recent_commit_messages.select do |message|
|
|
751
|
+
ESLINT_PREFIXES.any? { |pre| message.start_with?(/#{pre}[:(]/) }
|
|
752
|
+
end
|
|
753
|
+
|
|
754
|
+
semantic_messages.count.to_f / recent_commit_messages.count > 0.3
|
|
755
|
+
end
|
|
756
|
+
|
|
757
|
+
def angular_commit_prefix
|
|
758
|
+
raise "Not using angular commits!" unless using_angular_commit_messages?
|
|
759
|
+
|
|
760
|
+
recent_commits_using_chore =
|
|
761
|
+
recent_commit_messages.
|
|
762
|
+
any? { |msg| msg.start_with?("chore", "Chore") }
|
|
763
|
+
|
|
764
|
+
recent_commits_using_build =
|
|
765
|
+
recent_commit_messages.
|
|
766
|
+
any? { |msg| msg.start_with?("build", "Build") }
|
|
767
|
+
|
|
768
|
+
commit_prefix =
|
|
769
|
+
if recent_commits_using_chore && !recent_commits_using_build
|
|
770
|
+
"chore"
|
|
771
|
+
else
|
|
772
|
+
"build"
|
|
773
|
+
end
|
|
774
|
+
|
|
775
|
+
if capitalize_angular_commit_prefix?
|
|
776
|
+
commit_prefix = commit_prefix.capitalize
|
|
777
|
+
end
|
|
778
|
+
|
|
779
|
+
commit_prefix
|
|
780
|
+
end
|
|
781
|
+
|
|
782
|
+
def capitalize_angular_commit_prefix?
|
|
783
|
+
semantic_messages = recent_commit_messages.select do |message|
|
|
784
|
+
ANGULAR_PREFIXES.any? { |pre| message.match?(/#{pre}[:(]/i) }
|
|
785
|
+
end
|
|
786
|
+
|
|
787
|
+
if semantic_messages.none?
|
|
788
|
+
return last_dependabot_commit_message&.match?(/^A-Z/)
|
|
789
|
+
end
|
|
790
|
+
|
|
791
|
+
capitalized_msgs = semantic_messages.select { |m| m.match?(/^[A-Z]/) }
|
|
792
|
+
capitalized_msgs.count.to_f / semantic_messages.count > 0.5
|
|
793
|
+
end
|
|
794
|
+
|
|
795
|
+
def using_gitmoji_commit_messages?
|
|
796
|
+
return false if recent_commit_messages.none?
|
|
797
|
+
|
|
798
|
+
gitmoji_messages = recent_commit_messages.select do |message|
|
|
799
|
+
GITMOJI_PREFIXES.any? { |pre| message.match?(/:#{pre}:/i) }
|
|
800
|
+
end
|
|
801
|
+
|
|
802
|
+
gitmoji_messages.count.to_f / recent_commit_messages.count > 0.3
|
|
803
|
+
end
|
|
804
|
+
|
|
805
|
+
def recent_commit_messages
|
|
806
|
+
case source.provider
|
|
807
|
+
when "github" then recent_github_commit_messages
|
|
808
|
+
when "gitlab" then recent_gitlab_commit_messages
|
|
809
|
+
else raise "Unsupported provider: #{source.provider}"
|
|
810
|
+
end
|
|
811
|
+
end
|
|
812
|
+
|
|
813
|
+
def recent_github_commit_messages
|
|
814
|
+
@recent_github_commit_messages ||=
|
|
815
|
+
github_client_for_source.commits(source.repo)
|
|
816
|
+
|
|
817
|
+
@recent_github_commit_messages.
|
|
818
|
+
reject { |c| c.author&.type == "Bot" }.
|
|
819
|
+
reject { |c| c.commit&.message&.start_with?("Merge") }.
|
|
820
|
+
map(&:commit).
|
|
821
|
+
map(&:message).
|
|
822
|
+
compact.
|
|
823
|
+
map(&:strip)
|
|
824
|
+
end
|
|
825
|
+
|
|
826
|
+
def recent_gitlab_commit_messages
|
|
827
|
+
@recent_gitlab_commit_messages ||=
|
|
828
|
+
gitlab_client_for_source.commits(source.repo)
|
|
829
|
+
|
|
830
|
+
@recent_gitlab_commit_messages.
|
|
831
|
+
reject { |c| c.author_email == "support@dependabot.com" }.
|
|
832
|
+
reject { |c| c.message&.start_with?("merge !") }.
|
|
833
|
+
map(&:message).
|
|
834
|
+
compact.
|
|
835
|
+
map(&:strip)
|
|
836
|
+
end
|
|
837
|
+
|
|
838
|
+
def last_dependabot_commit_message
|
|
839
|
+
case source.provider
|
|
840
|
+
when "github" then last_github_dependabot_commit_message
|
|
841
|
+
when "gitlab" then last_gitlab_dependabot_commit_message
|
|
842
|
+
else raise "Unsupported provider: #{source.provider}"
|
|
843
|
+
end
|
|
844
|
+
end
|
|
845
|
+
|
|
846
|
+
def last_github_dependabot_commit_message
|
|
847
|
+
@recent_github_commit_messages ||=
|
|
848
|
+
github_client_for_source.commits(source.repo)
|
|
849
|
+
|
|
850
|
+
@recent_github_commit_messages.
|
|
851
|
+
find { |c| c.author&.login == "dependabot[bot]" }&.
|
|
852
|
+
commit&.
|
|
853
|
+
message&.
|
|
854
|
+
strip
|
|
855
|
+
end
|
|
856
|
+
|
|
857
|
+
def last_gitlab_dependabot_commit_message
|
|
858
|
+
@recent_gitlab_commit_messages ||=
|
|
859
|
+
gitlab_client_for_source.commits(source.repo)
|
|
860
|
+
|
|
861
|
+
@recent_gitlab_commit_messages.
|
|
862
|
+
find { |c| c.author_email == "support@dependabot.com" }&.
|
|
863
|
+
message&.
|
|
864
|
+
strip
|
|
865
|
+
end
|
|
866
|
+
|
|
867
|
+
def github_client_for_source
|
|
868
|
+
@github_client_for_source ||=
|
|
869
|
+
Dependabot::Clients::GithubWithRetries.for_source(
|
|
870
|
+
source: source,
|
|
871
|
+
credentials: credentials
|
|
872
|
+
)
|
|
873
|
+
end
|
|
874
|
+
|
|
875
|
+
def gitlab_client_for_source
|
|
876
|
+
@gitlab_client_for_source ||= Dependabot::Clients::Gitlab.for_source(
|
|
877
|
+
source: source,
|
|
878
|
+
credentials: credentials
|
|
879
|
+
)
|
|
880
|
+
end
|
|
881
|
+
|
|
882
|
+
def package_manager
|
|
883
|
+
@package_manager ||= dependencies.first.package_manager
|
|
884
|
+
end
|
|
885
|
+
end
|
|
886
|
+
end
|
|
887
|
+
end
|
|
888
|
+
# rubocop:enable Metrics/ClassLength
|