dependabot-common 0.236.0 → 0.237.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
 - data/lib/dependabot/clients/azure.rb +3 -3
 - data/lib/dependabot/config/file.rb +17 -6
 - data/lib/dependabot/config/update_config.rb +23 -5
 - data/lib/dependabot/dependency_file.rb +84 -14
 - data/lib/dependabot/dependency_group.rb +29 -5
 - data/lib/dependabot/errors.rb +101 -13
 - data/lib/dependabot/file_fetchers/base.rb +227 -93
 - data/lib/dependabot/metadata_finders/base/changelog_finder.rb +13 -6
 - data/lib/dependabot/pull_request_creator/github.rb +11 -8
 - data/lib/dependabot/pull_request_creator/message.rb +21 -2
 - data/lib/dependabot/pull_request_creator/message_builder/link_and_mention_sanitizer.rb +37 -16
 - data/lib/dependabot/pull_request_creator/message_builder/metadata_presenter.rb +4 -2
 - data/lib/dependabot/pull_request_creator/pr_name_prefixer.rb +10 -4
 - data/lib/dependabot/shared_helpers.rb +117 -33
 - data/lib/dependabot/simple_instrumentor.rb +22 -3
 - data/lib/dependabot/source.rb +65 -17
 - data/lib/dependabot/update_checkers/version_filters.rb +12 -1
 - data/lib/dependabot/utils.rb +21 -2
 - data/lib/dependabot/workspace/base.rb +42 -7
 - data/lib/dependabot/workspace/change_attempt.rb +31 -3
 - data/lib/dependabot/workspace/git.rb +34 -4
 - data/lib/dependabot/workspace.rb +16 -2
 - data/lib/dependabot.rb +1 -1
 - metadata +23 -9
 
| 
         @@ -1,7 +1,8 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # typed:  
     | 
| 
      
 1 
     | 
    
         
            +
            # typed: true
         
     | 
| 
       2 
2 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            require "excon"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "sorbet-runtime"
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            require "dependabot/clients/github_with_retries"
         
     | 
| 
       7 
8 
     | 
    
         
             
            require "dependabot/clients/gitlab_with_retries"
         
     | 
| 
         @@ -12,6 +13,8 @@ module Dependabot 
     | 
|
| 
       12 
13 
     | 
    
         
             
              module MetadataFinders
         
     | 
| 
       13 
14 
     | 
    
         
             
                class Base
         
     | 
| 
       14 
15 
     | 
    
         
             
                  class ChangelogFinder
         
     | 
| 
      
 16 
     | 
    
         
            +
                    extend T::Sig
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
       15 
18 
     | 
    
         
             
                    require_relative "changelog_pruner"
         
     | 
| 
       16 
19 
     | 
    
         
             
                    require_relative "commits_finder"
         
     | 
| 
       17 
20 
     | 
    
         | 
| 
         @@ -86,9 +89,9 @@ module Dependabot 
     | 
|
| 
       86 
89 
     | 
    
         
             
                      suggested_source = Source.from_url(suggested_changelog_url)
         
     | 
| 
       87 
90 
     | 
    
         
             
                      return unless suggested_source&.provider == "github"
         
     | 
| 
       88 
91 
     | 
    
         | 
| 
       89 
     | 
    
         
            -
                      opts = { path: suggested_source 
     | 
| 
      
 92 
     | 
    
         
            +
                      opts = { path: suggested_source&.directory, ref: suggested_source&.branch }.compact
         
     | 
| 
       90 
93 
     | 
    
         
             
                      suggested_source_client = github_client_for_source(suggested_source)
         
     | 
| 
       91 
     | 
    
         
            -
                      tmp_files = suggested_source_client.contents(suggested_source 
     | 
| 
      
 94 
     | 
    
         
            +
                      tmp_files = suggested_source_client.contents(suggested_source&.repo, opts)
         
     | 
| 
       92 
95 
     | 
    
         | 
| 
       93 
96 
     | 
    
         
             
                      filename = suggested_changelog_url.split("/").last.split("#").first
         
     | 
| 
       94 
97 
     | 
    
         
             
                      @changelog_from_suggested_url =
         
     | 
| 
         @@ -128,7 +131,10 @@ module Dependabot 
     | 
|
| 
       128 
131 
     | 
    
         
             
                        file = candidates.first if candidates.one?
         
     | 
| 
       129 
132 
     | 
    
         
             
                        file ||=
         
     | 
| 
       130 
133 
     | 
    
         
             
                          candidates.find do |f|
         
     | 
| 
       131 
     | 
    
         
            -
                             
     | 
| 
      
 134 
     | 
    
         
            +
                            if fetch_file_text(f).nil?
         
     | 
| 
      
 135 
     | 
    
         
            +
                              candidates -= [f]
         
     | 
| 
      
 136 
     | 
    
         
            +
                              next
         
     | 
| 
      
 137 
     | 
    
         
            +
                            end
         
     | 
| 
       132 
138 
     | 
    
         
             
                            pruner = ChangelogPruner.new(
         
     | 
| 
       133 
139 
     | 
    
         
             
                              dependency: dependency,
         
     | 
| 
       134 
140 
     | 
    
         
             
                              changelog_text: fetch_file_text(f)
         
     | 
| 
         @@ -159,11 +165,12 @@ module Dependabot 
     | 
|
| 
       159 
165 
     | 
    
         
             
                      fetch_file_text(changelog)
         
     | 
| 
       160 
166 
     | 
    
         
             
                    end
         
     | 
| 
       161 
167 
     | 
    
         | 
| 
      
 168 
     | 
    
         
            +
                    sig { params(file: T.untyped).returns(T.nilable(String)) }
         
     | 
| 
       162 
169 
     | 
    
         
             
                    def fetch_file_text(file)
         
     | 
| 
       163 
170 
     | 
    
         
             
                      @file_text ||= {}
         
     | 
| 
       164 
171 
     | 
    
         | 
| 
       165 
172 
     | 
    
         
             
                      unless @file_text.key?(file.download_url)
         
     | 
| 
       166 
     | 
    
         
            -
                        file_source = Source.from_url(file.html_url)
         
     | 
| 
      
 173 
     | 
    
         
            +
                        file_source = T.must(Source.from_url(file.html_url))
         
     | 
| 
       167 
174 
     | 
    
         
             
                        @file_text[file.download_url] =
         
     | 
| 
       168 
175 
     | 
    
         
             
                          case file_source.provider
         
     | 
| 
       169 
176 
     | 
    
         
             
                          when "github" then fetch_github_file(file_source, file)
         
     | 
| 
         @@ -171,7 +178,7 @@ module Dependabot 
     | 
|
| 
       171 
178 
     | 
    
         
             
                          when "bitbucket" then fetch_bitbucket_file(file)
         
     | 
| 
       172 
179 
     | 
    
         
             
                          when "azure" then fetch_azure_file(file)
         
     | 
| 
       173 
180 
     | 
    
         
             
                          when "codecommit" then nil # TODO: git file from codecommit
         
     | 
| 
       174 
     | 
    
         
            -
                          else raise "Unsupported provider '#{provider}'"
         
     | 
| 
      
 181 
     | 
    
         
            +
                          else raise "Unsupported provider '#{file_source.provider}'"
         
     | 
| 
       175 
182 
     | 
    
         
             
                          end
         
     | 
| 
       176 
183 
     | 
    
         
             
                      end
         
     | 
| 
       177 
184 
     | 
    
         | 
| 
         @@ -1,8 +1,9 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # typed:  
     | 
| 
      
 1 
     | 
    
         
            +
            # typed: true
         
     | 
| 
       2 
2 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            require "octokit"
         
     | 
| 
       5 
5 
     | 
    
         
             
            require "securerandom"
         
     | 
| 
      
 6 
     | 
    
         
            +
            require "sorbet-runtime"
         
     | 
| 
       6 
7 
     | 
    
         
             
            require "dependabot/clients/github_with_retries"
         
     | 
| 
       7 
8 
     | 
    
         
             
            require "dependabot/pull_request_creator"
         
     | 
| 
       8 
9 
     | 
    
         
             
            require "dependabot/pull_request_creator/commit_signer"
         
     | 
| 
         @@ -10,6 +11,8 @@ module Dependabot 
     | 
|
| 
       10 
11 
     | 
    
         
             
              class PullRequestCreator
         
     | 
| 
       11 
12 
     | 
    
         
             
                # rubocop:disable Metrics/ClassLength
         
     | 
| 
       12 
13 
     | 
    
         
             
                class Github
         
     | 
| 
      
 14 
     | 
    
         
            +
                  extend T::Sig
         
     | 
| 
      
 15 
     | 
    
         
            +
             
     | 
| 
       13 
16 
     | 
    
         
             
                  # GitHub limits PR descriptions to a max of 65,536 characters:
         
     | 
| 
       14 
17 
     | 
    
         
             
                  # https://github.com/orgs/community/discussions/27190#discussioncomment-3726017
         
     | 
| 
       15 
18 
     | 
    
         
             
                  PR_DESCRIPTION_MAX_LENGTH = 65_535 # 0 based count
         
     | 
| 
         @@ -65,11 +68,11 @@ module Dependabot 
     | 
|
| 
       65 
68 
     | 
    
         
             
                  def branch_exists?(name)
         
     | 
| 
       66 
69 
     | 
    
         
             
                    git_metadata_fetcher.ref_names.include?(name)
         
     | 
| 
       67 
70 
     | 
    
         
             
                  rescue Dependabot::GitDependenciesNotReachable => e
         
     | 
| 
       68 
     | 
    
         
            -
                    raise e.cause if e.cause&.message&.include?("is disabled")
         
     | 
| 
       69 
     | 
    
         
            -
                    raise e.cause if e.cause.is_a?(Octokit::Unauthorized)
         
     | 
| 
      
 71 
     | 
    
         
            +
                    raise T.must(e.cause) if e.cause&.message&.include?("is disabled")
         
     | 
| 
      
 72 
     | 
    
         
            +
                    raise T.must(e.cause) if e.cause.is_a?(Octokit::Unauthorized)
         
     | 
| 
       70 
73 
     | 
    
         
             
                    raise(RepoNotFound, source.url) unless repo_exists?
         
     | 
| 
       71 
74 
     | 
    
         | 
| 
       72 
     | 
    
         
            -
                    retrying ||= false
         
     | 
| 
      
 75 
     | 
    
         
            +
                    retrying ||= T.let(false, T::Boolean)
         
     | 
| 
       73 
76 
     | 
    
         | 
| 
       74 
77 
     | 
    
         
             
                    msg = "Unexpected git error!\n\n#{e.cause&.class}: #{e.cause&.message}"
         
     | 
| 
       75 
78 
     | 
    
         
             
                    raise msg if retrying
         
     | 
| 
         @@ -249,14 +252,14 @@ module Dependabot 
     | 
|
| 
       249 
252 
     | 
    
         
             
                    rescue Octokit::UnprocessableEntity => e
         
     | 
| 
       250 
253 
     | 
    
         
             
                      raise if e.message.match?(/Reference already exists/i)
         
     | 
| 
       251 
254 
     | 
    
         | 
| 
       252 
     | 
    
         
            -
                      retrying_branch_creation ||= false
         
     | 
| 
      
 255 
     | 
    
         
            +
                      retrying_branch_creation ||= T.let(false, T::Boolean)
         
     | 
| 
       253 
256 
     | 
    
         
             
                      raise if retrying_branch_creation
         
     | 
| 
       254 
257 
     | 
    
         | 
| 
       255 
258 
     | 
    
         
             
                      retrying_branch_creation = true
         
     | 
| 
       256 
259 
     | 
    
         | 
| 
       257 
260 
     | 
    
         
             
                      # Branch creation will fail if a branch called `dependabot` already
         
     | 
| 
       258 
261 
     | 
    
         
             
                      # exists, since git won't be able to create a dir with the same name
         
     | 
| 
       259 
     | 
    
         
            -
                      ref = "refs/heads/#{SecureRandom.hex[0..3] + branch_name}"
         
     | 
| 
      
 262 
     | 
    
         
            +
                      ref = "refs/heads/#{T.must(SecureRandom.hex[0..3]) + branch_name}"
         
     | 
| 
       260 
263 
     | 
    
         
             
                      retry
         
     | 
| 
       261 
264 
     | 
    
         
             
                    end
         
     | 
| 
       262 
265 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -320,7 +323,7 @@ module Dependabot 
     | 
|
| 
       320 
323 
     | 
    
         
             
                        "`@#{reviewers.first}`"
         
     | 
| 
       321 
324 
     | 
    
         
             
                      else
         
     | 
| 
       322 
325 
     | 
    
         
             
                        names = reviewers.map { |rv| "`@#{rv}`" }
         
     | 
| 
       323 
     | 
    
         
            -
                        "#{names[0..-2].join(', ')} and #{names[-1]}"
         
     | 
| 
      
 326 
     | 
    
         
            +
                        "#{T.must(names[0..-2]).join(', ')} and #{names[-1]}"
         
     | 
| 
       324 
327 
     | 
    
         
             
                      end
         
     | 
| 
       325 
328 
     | 
    
         | 
| 
       326 
329 
     | 
    
         
             
                    msg = "Dependabot tried to add #{reviewers_string} as "
         
     | 
| 
         @@ -371,7 +374,7 @@ module Dependabot 
     | 
|
| 
       371 
374 
     | 
    
         
             
                    # Sometimes PR creation fails with no details (presumably because the
         
     | 
| 
       372 
375 
     | 
    
         
             
                    # details are internal). It doesn't hurt to retry in these cases, in
         
     | 
| 
       373 
376 
     | 
    
         
             
                    # case the cause is a race.
         
     | 
| 
       374 
     | 
    
         
            -
                    retrying_pr_creation ||= false
         
     | 
| 
      
 377 
     | 
    
         
            +
                    retrying_pr_creation ||= T.let(false, T::Boolean)
         
     | 
| 
       375 
378 
     | 
    
         
             
                    raise if retrying_pr_creation
         
     | 
| 
       376 
379 
     | 
    
         | 
| 
       377 
380 
     | 
    
         
             
                    retrying_pr_creation = true
         
     | 
| 
         @@ -1,12 +1,31 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # typed:  
     | 
| 
      
 1 
     | 
    
         
            +
            # typed: strong
         
     | 
| 
       2 
2 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
            require "sorbet-runtime"
         
     | 
| 
      
 5 
     | 
    
         
            +
             
     | 
| 
       4 
6 
     | 
    
         
             
            module Dependabot
         
     | 
| 
       5 
7 
     | 
    
         
             
              class PullRequestCreator
         
     | 
| 
       6 
8 
     | 
    
         
             
                # Message is a static alternative to MessageBuilder
         
     | 
| 
       7 
9 
     | 
    
         
             
                class Message
         
     | 
| 
       8 
     | 
    
         
            -
                   
     | 
| 
      
 10 
     | 
    
         
            +
                  extend T::Sig
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                  sig { returns(T.nilable(String)) }
         
     | 
| 
      
 13 
     | 
    
         
            +
                  attr_reader :commit_message
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                  sig { returns(T.nilable(String)) }
         
     | 
| 
      
 16 
     | 
    
         
            +
                  attr_reader :pr_name
         
     | 
| 
       9 
17 
     | 
    
         | 
| 
      
 18 
     | 
    
         
            +
                  sig { returns(T.nilable(String)) }
         
     | 
| 
      
 19 
     | 
    
         
            +
                  attr_reader :pr_message
         
     | 
| 
      
 20 
     | 
    
         
            +
             
     | 
| 
      
 21 
     | 
    
         
            +
                  sig do
         
     | 
| 
      
 22 
     | 
    
         
            +
                    params(
         
     | 
| 
      
 23 
     | 
    
         
            +
                      commit_message: T.nilable(String),
         
     | 
| 
      
 24 
     | 
    
         
            +
                      pr_name: T.nilable(String),
         
     | 
| 
      
 25 
     | 
    
         
            +
                      pr_message: T.nilable(String)
         
     | 
| 
      
 26 
     | 
    
         
            +
                    )
         
     | 
| 
      
 27 
     | 
    
         
            +
                      .void
         
     | 
| 
      
 28 
     | 
    
         
            +
                  end
         
     | 
| 
       10 
29 
     | 
    
         
             
                  def initialize(commit_message: nil, pr_name: nil, pr_message: nil)
         
     | 
| 
       11 
30 
     | 
    
         
             
                    @commit_message = commit_message
         
     | 
| 
       12 
31 
     | 
    
         
             
                    @pr_name = pr_name
         
     | 
| 
         @@ -1,7 +1,8 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # typed:  
     | 
| 
      
 1 
     | 
    
         
            +
            # typed: strong
         
     | 
| 
       2 
2 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
       4 
4 
     | 
    
         
             
            require "commonmarker"
         
     | 
| 
      
 5 
     | 
    
         
            +
            require "sorbet-runtime"
         
     | 
| 
       5 
6 
     | 
    
         
             
            require "strscan"
         
     | 
| 
       6 
7 
     | 
    
         
             
            require "dependabot/pull_request_creator/message_builder"
         
     | 
| 
       7 
8 
     | 
    
         | 
| 
         @@ -9,6 +10,8 @@ module Dependabot 
     | 
|
| 
       9 
10 
     | 
    
         
             
              class PullRequestCreator
         
     | 
| 
       10 
11 
     | 
    
         
             
                class MessageBuilder
         
     | 
| 
       11 
12 
     | 
    
         
             
                  class LinkAndMentionSanitizer
         
     | 
| 
      
 13 
     | 
    
         
            +
                    extend T::Sig
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
       12 
15 
     | 
    
         
             
                    GITHUB_USERNAME = /[a-z0-9]+(-[a-z0-9]+)*/i
         
     | 
| 
       13 
16 
     | 
    
         
             
                    GITHUB_REF_REGEX = %r{
         
     | 
| 
       14 
17 
     | 
    
         
             
                      (?:https?://)?
         
     | 
| 
         @@ -22,19 +25,24 @@ module Dependabot 
     | 
|
| 
       22 
25 
     | 
    
         
             
                    TEAM_MENTION_REGEX = %r{(?<![A-Za-z0-9`~])@(?<org>#{GITHUB_USERNAME})/(?<team>#{GITHUB_USERNAME})/?}
         
     | 
| 
       23 
26 
     | 
    
         
             
                    # End of string
         
     | 
| 
       24 
27 
     | 
    
         
             
                    EOS_REGEX = /\z/
         
     | 
| 
       25 
     | 
    
         
            -
                    COMMONMARKER_OPTIONS =  
     | 
| 
       26 
     | 
    
         
            -
                      GITHUB_PRE_LANG FULL_INFO_STRING
         
     | 
| 
       27 
     | 
    
         
            -
             
     | 
| 
       28 
     | 
    
         
            -
                     
     | 
| 
       29 
     | 
    
         
            -
             
     | 
| 
       30 
     | 
    
         
            -
             
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
      
 28 
     | 
    
         
            +
                    COMMONMARKER_OPTIONS = T.let(
         
     | 
| 
      
 29 
     | 
    
         
            +
                      %i(GITHUB_PRE_LANG FULL_INFO_STRING).freeze,
         
     | 
| 
      
 30 
     | 
    
         
            +
                      T::Array[Symbol]
         
     | 
| 
      
 31 
     | 
    
         
            +
                    )
         
     | 
| 
      
 32 
     | 
    
         
            +
                    COMMONMARKER_EXTENSIONS = T.let(
         
     | 
| 
      
 33 
     | 
    
         
            +
                      %i(table tasklist strikethrough autolink tagfilter).freeze,
         
     | 
| 
      
 34 
     | 
    
         
            +
                      T::Array[Symbol]
         
     | 
| 
      
 35 
     | 
    
         
            +
                    )
         
     | 
| 
      
 36 
     | 
    
         
            +
             
     | 
| 
      
 37 
     | 
    
         
            +
                    sig { returns(T.nilable(String)) }
         
     | 
| 
       32 
38 
     | 
    
         
             
                    attr_reader :github_redirection_service
         
     | 
| 
       33 
39 
     | 
    
         | 
| 
      
 40 
     | 
    
         
            +
                    sig { params(github_redirection_service: T.nilable(String)).void }
         
     | 
| 
       34 
41 
     | 
    
         
             
                    def initialize(github_redirection_service:)
         
     | 
| 
       35 
42 
     | 
    
         
             
                      @github_redirection_service = github_redirection_service
         
     | 
| 
       36 
43 
     | 
    
         
             
                    end
         
     | 
| 
       37 
44 
     | 
    
         | 
| 
      
 45 
     | 
    
         
            +
                    sig { params(text: String, unsafe: T::Boolean, format_html: T::Boolean).returns(String) }
         
     | 
| 
       38 
46 
     | 
    
         
             
                    def sanitize_links_and_mentions(text:, unsafe: false, format_html: true)
         
     | 
| 
       39 
47 
     | 
    
         
             
                      doc = CommonMarker.render_doc(
         
     | 
| 
       40 
48 
     | 
    
         
             
                        text, :LIBERAL_HTML_TAG, COMMONMARKER_EXTENSIONS
         
     | 
| 
         @@ -53,6 +61,7 @@ module Dependabot 
     | 
|
| 
       53 
61 
     | 
    
         | 
| 
       54 
62 
     | 
    
         
             
                    private
         
     | 
| 
       55 
63 
     | 
    
         | 
| 
      
 64 
     | 
    
         
            +
                    sig { params(doc: CommonMarker::Node).void }
         
     | 
| 
       56 
65 
     | 
    
         
             
                    def sanitize_mentions(doc)
         
     | 
| 
       57 
66 
     | 
    
         
             
                      doc.walk do |node|
         
     | 
| 
       58 
67 
     | 
    
         
             
                        if node.type == :text &&
         
     | 
| 
         @@ -77,6 +86,7 @@ module Dependabot 
     | 
|
| 
       77 
86 
     | 
    
         
             
                    # This is because there are ecosystems that have packages that follow the same pattern
         
     | 
| 
       78 
87 
     | 
    
         
             
                    # (e.g. @angular/angular-cli), and we don't want to create an invalid link, since
         
     | 
| 
       79 
88 
     | 
    
         
             
                    # team mentions link to `https://github.com/org/:organization_name/teams/:team_name`.
         
     | 
| 
      
 89 
     | 
    
         
            +
                    sig { params(doc: CommonMarker::Node).void }
         
     | 
| 
       80 
90 
     | 
    
         
             
                    def sanitize_team_mentions(doc)
         
     | 
| 
       81 
91 
     | 
    
         
             
                      doc.walk do |node|
         
     | 
| 
       82 
92 
     | 
    
         
             
                        if node.type == :text &&
         
     | 
| 
         @@ -92,6 +102,7 @@ module Dependabot 
     | 
|
| 
       92 
102 
     | 
    
         
             
                      end
         
     | 
| 
       93 
103 
     | 
    
         
             
                    end
         
     | 
| 
       94 
104 
     | 
    
         | 
| 
      
 105 
     | 
    
         
            +
                    sig { params(doc: CommonMarker::Node).void }
         
     | 
| 
       95 
106 
     | 
    
         
             
                    def sanitize_links(doc)
         
     | 
| 
       96 
107 
     | 
    
         
             
                      doc.walk do |node|
         
     | 
| 
       97 
108 
     | 
    
         
             
                        if node.type == :link && node.url.match?(GITHUB_REF_REGEX)
         
     | 
| 
         @@ -101,7 +112,7 @@ module Dependabot 
     | 
|
| 
       101 
112 
     | 
    
         
             
                              next
         
     | 
| 
       102 
113 
     | 
    
         
             
                            end
         
     | 
| 
       103 
114 
     | 
    
         | 
| 
       104 
     | 
    
         
            -
                            last_match = subnode.string_content.match(GITHUB_REF_REGEX)
         
     | 
| 
      
 115 
     | 
    
         
            +
                            last_match = T.must(subnode.string_content.match(GITHUB_REF_REGEX))
         
     | 
| 
       105 
116 
     | 
    
         
             
                            number = last_match.named_captures.fetch("number")
         
     | 
| 
       106 
117 
     | 
    
         
             
                            repo = last_match.named_captures.fetch("repo")
         
     | 
| 
       107 
118 
     | 
    
         
             
                            subnode.string_content = "#{repo}##{number}"
         
     | 
| 
         @@ -115,6 +126,7 @@ module Dependabot 
     | 
|
| 
       115 
126 
     | 
    
         
             
                      end
         
     | 
| 
       116 
127 
     | 
    
         
             
                    end
         
     | 
| 
       117 
128 
     | 
    
         | 
| 
      
 129 
     | 
    
         
            +
                    sig { params(doc: CommonMarker::Node).void }
         
     | 
| 
       118 
130 
     | 
    
         
             
                    def sanitize_nwo_text(doc)
         
     | 
| 
       119 
131 
     | 
    
         
             
                      doc.walk do |node|
         
     | 
| 
       120 
132 
     | 
    
         
             
                        if node.type == :text &&
         
     | 
| 
         @@ -125,8 +137,9 @@ module Dependabot 
     | 
|
| 
       125 
137 
     | 
    
         
             
                      end
         
     | 
| 
       126 
138 
     | 
    
         
             
                    end
         
     | 
| 
       127 
139 
     | 
    
         | 
| 
      
 140 
     | 
    
         
            +
                    sig { params(node: CommonMarker::Node).void }
         
     | 
| 
       128 
141 
     | 
    
         
             
                    def replace_nwo_node(node)
         
     | 
| 
       129 
     | 
    
         
            -
                      match = node.string_content.match(GITHUB_NWO_REGEX)
         
     | 
| 
      
 142 
     | 
    
         
            +
                      match = T.must(node.string_content.match(GITHUB_NWO_REGEX))
         
     | 
| 
       130 
143 
     | 
    
         
             
                      repo = match.named_captures.fetch("repo")
         
     | 
| 
       131 
144 
     | 
    
         
             
                      number = match.named_captures.fetch("number")
         
     | 
| 
       132 
145 
     | 
    
         
             
                      new_node = build_nwo_text_node("#{repo}##{number}")
         
     | 
| 
         @@ -134,22 +147,24 @@ module Dependabot 
     | 
|
| 
       134 
147 
     | 
    
         
             
                      node.delete
         
     | 
| 
       135 
148 
     | 
    
         
             
                    end
         
     | 
| 
       136 
149 
     | 
    
         | 
| 
      
 150 
     | 
    
         
            +
                    sig { params(text: String).returns(String) }
         
     | 
| 
       137 
151 
     | 
    
         
             
                    def replace_github_host(text)
         
     | 
| 
       138 
     | 
    
         
            -
                      return text if !github_redirection_service.nil? && text.include?(github_redirection_service)
         
     | 
| 
      
 152 
     | 
    
         
            +
                      return text if !github_redirection_service.nil? && text.include?(T.must(github_redirection_service))
         
     | 
| 
       139 
153 
     | 
    
         | 
| 
       140 
154 
     | 
    
         
             
                      text.gsub(
         
     | 
| 
       141 
155 
     | 
    
         
             
                        /(www\.)?github.com/, github_redirection_service || "github.com"
         
     | 
| 
       142 
156 
     | 
    
         
             
                      )
         
     | 
| 
       143 
157 
     | 
    
         
             
                    end
         
     | 
| 
       144 
158 
     | 
    
         | 
| 
      
 159 
     | 
    
         
            +
                    sig { params(text: String).returns(T::Array[CommonMarker::Node]) }
         
     | 
| 
       145 
160 
     | 
    
         
             
                    def build_mention_nodes(text)
         
     | 
| 
       146 
     | 
    
         
            -
                      nodes = []
         
     | 
| 
      
 161 
     | 
    
         
            +
                      nodes = T.let([], T::Array[CommonMarker::Node])
         
     | 
| 
       147 
162 
     | 
    
         
             
                      scan = StringScanner.new(text)
         
     | 
| 
       148 
163 
     | 
    
         | 
| 
       149 
164 
     | 
    
         
             
                      until scan.eos?
         
     | 
| 
       150 
165 
     | 
    
         
             
                        line = scan.scan_until(MENTION_REGEX) ||
         
     | 
| 
       151 
166 
     | 
    
         
             
                               scan.scan_until(EOS_REGEX)
         
     | 
| 
       152 
     | 
    
         
            -
                        line_match = line.match(MENTION_REGEX)
         
     | 
| 
      
 167 
     | 
    
         
            +
                        line_match = T.must(line).match(MENTION_REGEX)
         
     | 
| 
       153 
168 
     | 
    
         
             
                        mention = line_match&.to_s
         
     | 
| 
       154 
169 
     | 
    
         
             
                        text_node = CommonMarker::Node.new(:text)
         
     | 
| 
       155 
170 
     | 
    
         | 
| 
         @@ -168,14 +183,15 @@ module Dependabot 
     | 
|
| 
       168 
183 
     | 
    
         
             
                      nodes
         
     | 
| 
       169 
184 
     | 
    
         
             
                    end
         
     | 
| 
       170 
185 
     | 
    
         | 
| 
      
 186 
     | 
    
         
            +
                    sig { params(text: String).returns(T::Array[CommonMarker::Node]) }
         
     | 
| 
       171 
187 
     | 
    
         
             
                    def build_team_mention_nodes(text)
         
     | 
| 
       172 
     | 
    
         
            -
                      nodes = []
         
     | 
| 
      
 188 
     | 
    
         
            +
                      nodes = T.let([], T::Array[CommonMarker::Node])
         
     | 
| 
       173 
189 
     | 
    
         | 
| 
       174 
190 
     | 
    
         
             
                      scan = StringScanner.new(text)
         
     | 
| 
       175 
191 
     | 
    
         
             
                      until scan.eos?
         
     | 
| 
       176 
192 
     | 
    
         
             
                        line = scan.scan_until(TEAM_MENTION_REGEX) ||
         
     | 
| 
       177 
193 
     | 
    
         
             
                               scan.scan_until(EOS_REGEX)
         
     | 
| 
       178 
     | 
    
         
            -
                        line_match = line.match(TEAM_MENTION_REGEX)
         
     | 
| 
      
 194 
     | 
    
         
            +
                        line_match = T.must(line).match(TEAM_MENTION_REGEX)
         
     | 
| 
       179 
195 
     | 
    
         
             
                        mention = line_match&.to_s
         
     | 
| 
       180 
196 
     | 
    
         
             
                        text_node = CommonMarker::Node.new(:text)
         
     | 
| 
       181 
197 
     | 
    
         | 
| 
         @@ -192,18 +208,21 @@ module Dependabot 
     | 
|
| 
       192 
208 
     | 
    
         
             
                      nodes
         
     | 
| 
       193 
209 
     | 
    
         
             
                    end
         
     | 
| 
       194 
210 
     | 
    
         | 
| 
      
 211 
     | 
    
         
            +
                    sig { params(text: String).returns(T::Array[CommonMarker::Node]) }
         
     | 
| 
       195 
212 
     | 
    
         
             
                    def build_mention_link_text_nodes(text)
         
     | 
| 
       196 
213 
     | 
    
         
             
                      code_node = CommonMarker::Node.new(:code)
         
     | 
| 
       197 
214 
     | 
    
         
             
                      code_node.string_content = insert_zero_width_space_in_mention(text)
         
     | 
| 
       198 
215 
     | 
    
         
             
                      [code_node]
         
     | 
| 
       199 
216 
     | 
    
         
             
                    end
         
     | 
| 
       200 
217 
     | 
    
         | 
| 
      
 218 
     | 
    
         
            +
                    sig { params(text: String).returns(CommonMarker::Node) }
         
     | 
| 
       201 
219 
     | 
    
         
             
                    def build_nwo_text_node(text)
         
     | 
| 
       202 
220 
     | 
    
         
             
                      code_node = CommonMarker::Node.new(:code)
         
     | 
| 
       203 
221 
     | 
    
         
             
                      code_node.string_content = text
         
     | 
| 
       204 
222 
     | 
    
         
             
                      code_node
         
     | 
| 
       205 
223 
     | 
    
         
             
                    end
         
     | 
| 
       206 
224 
     | 
    
         | 
| 
      
 225 
     | 
    
         
            +
                    sig { params(url: String, text: String).returns(CommonMarker::Node) }
         
     | 
| 
       207 
226 
     | 
    
         
             
                    def create_link_node(url, text)
         
     | 
| 
       208 
227 
     | 
    
         
             
                      link_node = CommonMarker::Node.new(:link)
         
     | 
| 
       209 
228 
     | 
    
         
             
                      code_node = CommonMarker::Node.new(:code)
         
     | 
| 
         @@ -217,12 +236,14 @@ module Dependabot 
     | 
|
| 
       217 
236 
     | 
    
         
             
                    # email replies on dependabot pull requests triggering notifications to
         
     | 
| 
       218 
237 
     | 
    
         
             
                    # users who've been mentioned in changelogs etc. PR email replies parse
         
     | 
| 
       219 
238 
     | 
    
         
             
                    # the content of the pull request body in plain text.
         
     | 
| 
      
 239 
     | 
    
         
            +
                    sig { params(mention: String).returns(String) }
         
     | 
| 
       220 
240 
     | 
    
         
             
                    def insert_zero_width_space_in_mention(mention)
         
     | 
| 
       221 
241 
     | 
    
         
             
                      mention.sub("@", "@\u200B").encode("utf-8")
         
     | 
| 
       222 
242 
     | 
    
         
             
                    end
         
     | 
| 
       223 
243 
     | 
    
         | 
| 
      
 244 
     | 
    
         
            +
                    sig { params(node: CommonMarker::Node).returns(T::Boolean) }
         
     | 
| 
       224 
245 
     | 
    
         
             
                    def parent_node_link?(node)
         
     | 
| 
       225 
     | 
    
         
            -
                      node.type == :link || (node.parent && parent_node_link?(node.parent))
         
     | 
| 
      
 246 
     | 
    
         
            +
                      node.type == :link || (!node.parent.nil? && parent_node_link?(T.must(node.parent)))
         
     | 
| 
       226 
247 
     | 
    
         
             
                    end
         
     | 
| 
       227 
248 
     | 
    
         
             
                  end
         
     | 
| 
       228 
249 
     | 
    
         
             
                end
         
     | 
| 
         @@ -1,12 +1,14 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            # typed:  
     | 
| 
      
 1 
     | 
    
         
            +
            # typed: true
         
     | 
| 
       2 
2 
     | 
    
         
             
            # frozen_string_literal: true
         
     | 
| 
       3 
3 
     | 
    
         | 
| 
      
 4 
     | 
    
         
            +
            require "sorbet-runtime"
         
     | 
| 
       4 
5 
     | 
    
         
             
            require "dependabot/pull_request_creator/message_builder"
         
     | 
| 
       5 
6 
     | 
    
         | 
| 
       6 
7 
     | 
    
         
             
            module Dependabot
         
     | 
| 
       7 
8 
     | 
    
         
             
              class PullRequestCreator
         
     | 
| 
       8 
9 
     | 
    
         
             
                class MessageBuilder
         
     | 
| 
       9 
10 
     | 
    
         
             
                  class MetadataPresenter
         
     | 
| 
      
 11 
     | 
    
         
            +
                    extend T::Sig
         
     | 
| 
       10 
12 
     | 
    
         
             
                    extend Forwardable
         
     | 
| 
       11 
13 
     | 
    
         | 
| 
       12 
14 
     | 
    
         
             
                    attr_reader :dependency, :source, :metadata_finder,
         
     | 
| 
         @@ -192,7 +194,7 @@ module Dependabot 
     | 
|
| 
       192 
194 
     | 
    
         
             
                        unaffected_versions
         
     | 
| 
       193 
195 
     | 
    
         
             
                        affected_versions
         
     | 
| 
       194 
196 
     | 
    
         
             
                      ).each do |tp|
         
     | 
| 
       195 
     | 
    
         
            -
                        type = tp.split("_").first.capitalize
         
     | 
| 
      
 197 
     | 
    
         
            +
                        type = T.must(tp.split("_").first).capitalize
         
     | 
| 
       196 
198 
     | 
    
         
             
                        next unless details[tp]
         
     | 
| 
       197 
199 
     | 
    
         | 
| 
       198 
200 
     | 
    
         
             
                        versions_string = details[tp].any? ? details[tp].join("; ") : "none"
         
     | 
| 
         @@ -132,7 +132,7 @@ module Dependabot 
     | 
|
| 
       132 
132 
     | 
    
         
             
                    case last_dependabot_commit_style
         
     | 
| 
       133 
133 
     | 
    
         
             
                    when :gitmoji then true
         
     | 
| 
       134 
134 
     | 
    
         
             
                    when :conventional_prefix, :conventional_prefix_with_scope
         
     | 
| 
       135 
     | 
    
         
            -
                       
     | 
| 
      
 135 
     | 
    
         
            +
                      last_dependabot_commit_title.match?(/: (\[[Ss]ecurity\] )?(B|U)/)
         
     | 
| 
       136 
136 
     | 
    
         
             
                    else raise "Unknown commit style #{last_dependabot_commit_style}"
         
     | 
| 
       137 
137 
     | 
    
         
             
                    end
         
     | 
| 
       138 
138 
     | 
    
         
             
                  end
         
     | 
| 
         @@ -152,7 +152,7 @@ module Dependabot 
     | 
|
| 
       152 
152 
     | 
    
         
             
                  end
         
     | 
| 
       153 
153 
     | 
    
         | 
| 
       154 
154 
     | 
    
         
             
                  def last_dependabot_commit_style
         
     | 
| 
       155 
     | 
    
         
            -
                    return unless (msg =  
     | 
| 
      
 155 
     | 
    
         
            +
                    return unless (msg = last_dependabot_commit_title)
         
     | 
| 
       156 
156 
     | 
    
         | 
| 
       157 
157 
     | 
    
         
             
                    return :gitmoji if msg.start_with?("⬆️")
         
     | 
| 
       158 
158 
     | 
    
         
             
                    return :conventional_prefix if msg.match?(/\A(chore|build|upgrade):/i)
         
     | 
| 
         @@ -162,7 +162,7 @@ module Dependabot 
     | 
|
| 
       162 
162 
     | 
    
         
             
                  end
         
     | 
| 
       163 
163 
     | 
    
         | 
| 
       164 
164 
     | 
    
         
             
                  def last_dependabot_commit_prefix
         
     | 
| 
       165 
     | 
    
         
            -
                     
     | 
| 
      
 165 
     | 
    
         
            +
                    last_dependabot_commit_title&.split(/[:(]/)&.first
         
     | 
| 
       166 
166 
     | 
    
         
             
                  end
         
     | 
| 
       167 
167 
     | 
    
         | 
| 
       168 
168 
     | 
    
         
             
                  # rubocop:disable Metrics/PerceivedComplexity
         
     | 
| 
         @@ -245,7 +245,7 @@ module Dependabot 
     | 
|
| 
       245 
245 
     | 
    
         
             
                      ANGULAR_PREFIXES.any? { |pre| message.match?(/#{pre}[:(]/i) }
         
     | 
| 
       246 
246 
     | 
    
         
             
                    end
         
     | 
| 
       247 
247 
     | 
    
         | 
| 
       248 
     | 
    
         
            -
                    return  
     | 
| 
      
 248 
     | 
    
         
            +
                    return last_dependabot_commit_title&.start_with?(/[A-Z]/) if semantic_messages.none?
         
     | 
| 
       249 
249 
     | 
    
         | 
| 
       250 
250 
     | 
    
         
             
                    capitalized_msgs = semantic_messages
         
     | 
| 
       251 
251 
     | 
    
         
             
                                       .select { |m| m.start_with?(/[A-Z]/) }
         
     | 
| 
         @@ -329,6 +329,12 @@ module Dependabot 
     | 
|
| 
       329 
329 
     | 
    
         
             
                                                      .map(&:strip)
         
     | 
| 
       330 
330 
     | 
    
         
             
                  end
         
     | 
| 
       331 
331 
     | 
    
         | 
| 
      
 332 
     | 
    
         
            +
                  def last_dependabot_commit_title
         
     | 
| 
      
 333 
     | 
    
         
            +
                    return @last_dependabot_commit_title if defined?(@last_dependabot_commit_title)
         
     | 
| 
      
 334 
     | 
    
         
            +
             
     | 
| 
      
 335 
     | 
    
         
            +
                    @last_dependabot_commit_title = last_dependabot_commit_message&.split("\n")&.first
         
     | 
| 
      
 336 
     | 
    
         
            +
                  end
         
     | 
| 
      
 337 
     | 
    
         
            +
             
     | 
| 
       332 
338 
     | 
    
         
             
                  def last_dependabot_commit_message
         
     | 
| 
       333 
339 
     | 
    
         
             
                    @last_dependabot_commit_message ||=
         
     | 
| 
       334 
340 
     | 
    
         
             
                      case source.provider
         
     |