github_changelog_generator 1.15.0 → 1.16.3
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/README.md +32 -54
- data/Rakefile +1 -1
- data/lib/github_changelog_generator/argv_parser.rb +225 -0
- data/lib/github_changelog_generator/generator/entry.rb +10 -10
- data/lib/github_changelog_generator/generator/generator.rb +41 -19
- data/lib/github_changelog_generator/generator/generator_fetcher.rb +5 -9
- data/lib/github_changelog_generator/generator/generator_processor.rb +23 -20
- data/lib/github_changelog_generator/generator/generator_tags.rb +15 -9
- data/lib/github_changelog_generator/generator/section.rb +27 -7
- data/lib/github_changelog_generator/helper.rb +1 -1
- data/lib/github_changelog_generator/octo_fetcher.rb +190 -126
- data/lib/github_changelog_generator/options.rb +4 -0
- data/lib/github_changelog_generator/parser.rb +70 -248
- data/lib/github_changelog_generator/parser_file.rb +29 -14
- data/lib/github_changelog_generator/reader.rb +2 -2
- data/lib/github_changelog_generator/ssl_certs/cacert.pem +851 -1680
- data/lib/github_changelog_generator/task.rb +3 -2
- data/lib/github_changelog_generator/version.rb +1 -1
- data/man/git-generate-changelog.1 +46 -34
- data/man/git-generate-changelog.1.html +39 -31
- data/man/git-generate-changelog.html +19 -19
- data/man/git-generate-changelog.md +39 -31
- data/spec/files/config_example +5 -0
- data/spec/spec_helper.rb +1 -1
- data/spec/unit/generator/entry_spec.rb +37 -31
- data/spec/unit/generator/generator_processor_spec.rb +99 -44
- data/spec/unit/generator/generator_spec.rb +47 -0
- data/spec/unit/generator/generator_tags_spec.rb +46 -3
- data/spec/unit/generator/section_spec.rb +34 -0
- data/spec/unit/octo_fetcher_spec.rb +45 -2
- data/spec/unit/parser_spec.rb +50 -0
- metadata +45 -9
| @@ -2,8 +2,6 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            module GitHubChangelogGenerator
         | 
| 4 4 | 
             
              class Generator
         | 
| 5 | 
            -
                MAX_THREAD_NUMBER = 25
         | 
| 6 | 
            -
             | 
| 7 5 | 
             
                # Fetch event for issues and pull requests
         | 
| 8 6 | 
             
                # @return [Array] array of fetched issues
         | 
| 9 7 | 
             
                def fetch_events_for_issues_and_pr
         | 
| @@ -64,7 +62,7 @@ module GitHubChangelogGenerator | |
| 64 62 | 
             
                # @param [Array] prs The PRs to associate.
         | 
| 65 63 | 
             
                # @return [Array] PRs without their merge_commit_sha in a tag.
         | 
| 66 64 | 
             
                def associate_tagged_prs(tags, prs, total)
         | 
| 67 | 
            -
                  @fetcher. | 
| 65 | 
            +
                  @fetcher.fetch_tag_shas(tags)
         | 
| 68 66 |  | 
| 69 67 | 
             
                  i = 0
         | 
| 70 68 | 
             
                  prs.reject do |pr|
         | 
| @@ -106,7 +104,7 @@ module GitHubChangelogGenerator | |
| 106 104 | 
             
                    i = total - prs_left.count
         | 
| 107 105 | 
             
                    prs_left.reject do |pr|
         | 
| 108 106 | 
             
                      found = false
         | 
| 109 | 
            -
                      if pr["events"] && (event = pr["events"].find { |e| e["event"] == "merged" }) && sha_in_release_branch(event["commit_id"])
         | 
| 107 | 
            +
                      if pr["events"] && (event = pr["events"].find { |e| e["event"] == "merged" }) && sha_in_release_branch?(event["commit_id"])
         | 
| 110 108 | 
             
                        found = true
         | 
| 111 109 | 
             
                        i += 1
         | 
| 112 110 | 
             
                        print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
         | 
| @@ -139,7 +137,7 @@ module GitHubChangelogGenerator | |
| 139 137 | 
             
                        pr["first_occurring_tag"] = oldest_tag["name"]
         | 
| 140 138 | 
             
                        found = true
         | 
| 141 139 | 
             
                        i += 1
         | 
| 142 | 
            -
                      elsif sha_in_release_branch(rebased_sha)
         | 
| 140 | 
            +
                      elsif sha_in_release_branch?(rebased_sha)
         | 
| 143 141 | 
             
                        found = true
         | 
| 144 142 | 
             
                        i += 1
         | 
| 145 143 | 
             
                      else
         | 
| @@ -197,11 +195,9 @@ module GitHubChangelogGenerator | |
| 197 195 | 
             
                #
         | 
| 198 196 | 
             
                # @param [String] sha SHA to check.
         | 
| 199 197 | 
             
                # @return [Boolean] True if SHA is in the branch git history.
         | 
| 200 | 
            -
                def sha_in_release_branch(sha)
         | 
| 198 | 
            +
                def sha_in_release_branch?(sha)
         | 
| 201 199 | 
             
                  branch = @options[:release_branch] || @fetcher.default_branch
         | 
| 202 | 
            -
                   | 
| 203 | 
            -
                  shas_in_branch = commits_in_branch["commits"].collect { |commit| commit["sha"] }
         | 
| 204 | 
            -
                  shas_in_branch.include?(sha)
         | 
| 200 | 
            +
                  @fetcher.commits_in_branch(branch).include?(sha)
         | 
| 205 201 | 
             
                end
         | 
| 206 202 | 
             
              end
         | 
| 207 203 | 
             
            end
         | 
| @@ -69,6 +69,9 @@ module GitHubChangelogGenerator | |
| 69 69 | 
             
                    # leave issues without milestones
         | 
| 70 70 | 
             
                    if issue["milestone"].nil?
         | 
| 71 71 | 
             
                      true
         | 
| 72 | 
            +
                    # remove issues of open milestones if option is set
         | 
| 73 | 
            +
                    elsif issue["milestone"]["state"] == "open"
         | 
| 74 | 
            +
                      @options[:issues_of_open_milestones]
         | 
| 72 75 | 
             
                    else
         | 
| 73 76 | 
             
                      # check, that this milestone in tag list:
         | 
| 74 77 | 
             
                      @filtered_tags.find { |tag| tag["name"] == issue["milestone"]["title"] }.nil?
         | 
| @@ -130,21 +133,19 @@ module GitHubChangelogGenerator | |
| 130 133 | 
             
                end
         | 
| 131 134 |  | 
| 132 135 | 
             
                def tag_older_new_tag?(newer_tag_time, time)
         | 
| 133 | 
            -
                   | 
| 134 | 
            -
             | 
| 135 | 
            -
             | 
| 136 | 
            -
             | 
| 137 | 
            -
             | 
| 138 | 
            -
                  tag_in_range_new
         | 
| 136 | 
            +
                  if newer_tag_time.nil?
         | 
| 137 | 
            +
                    true
         | 
| 138 | 
            +
                  else
         | 
| 139 | 
            +
                    time <= newer_tag_time
         | 
| 140 | 
            +
                  end
         | 
| 139 141 | 
             
                end
         | 
| 140 142 |  | 
| 141 143 | 
             
                def tag_newer_old_tag?(older_tag_time, time)
         | 
| 142 | 
            -
                   | 
| 143 | 
            -
             | 
| 144 | 
            -
             | 
| 145 | 
            -
             | 
| 146 | 
            -
             | 
| 147 | 
            -
                  tag_in_range_old
         | 
| 144 | 
            +
                  if older_tag_time.nil?
         | 
| 145 | 
            +
                    true
         | 
| 146 | 
            +
                  else
         | 
| 147 | 
            +
                    time > older_tag_time
         | 
| 148 | 
            +
                  end
         | 
| 148 149 | 
             
                end
         | 
| 149 150 |  | 
| 150 151 | 
             
                # Include issues with labels, specified in :include_labels
         | 
| @@ -152,22 +153,24 @@ module GitHubChangelogGenerator | |
| 152 153 | 
             
                # @return [Array] filtered array of issues
         | 
| 153 154 | 
             
                def include_issues_by_labels(issues)
         | 
| 154 155 | 
             
                  filtered_issues = filter_by_include_labels(issues)
         | 
| 155 | 
            -
                   | 
| 156 | 
            -
                  filtered_issues
         | 
| 156 | 
            +
                  filter_wo_labels(filtered_issues)
         | 
| 157 157 | 
             
                end
         | 
| 158 158 |  | 
| 159 | 
            -
                # @param [Array]  | 
| 159 | 
            +
                # @param [Array] items Issues & PRs to filter when without labels
         | 
| 160 160 | 
             
                # @return [Array] Issues & PRs without labels or empty array if
         | 
| 161 161 | 
             
                #                 add_issues_wo_labels or add_pr_wo_labels are false
         | 
| 162 | 
            -
                def filter_wo_labels( | 
| 163 | 
            -
                  if  | 
| 164 | 
            -
                     | 
| 165 | 
            -
                   | 
| 166 | 
            -
                     | 
| 162 | 
            +
                def filter_wo_labels(items)
         | 
| 163 | 
            +
                  if items.any? && items.first.key?("pull_request")
         | 
| 164 | 
            +
                    return items if options[:add_pr_wo_labels]
         | 
| 165 | 
            +
                  elsif options[:add_issues_wo_labels]
         | 
| 166 | 
            +
                    return items
         | 
| 167 167 | 
             
                  end
         | 
| 168 | 
            +
                  # The default is to filter items without labels
         | 
| 169 | 
            +
                  items.select { |item| item["labels"].map { |l| l["name"] }.any? }
         | 
| 168 170 | 
             
                end
         | 
| 169 171 |  | 
| 170 172 | 
             
                # @todo Document this
         | 
| 173 | 
            +
                # @param [Object] issues
         | 
| 171 174 | 
             
                def filter_by_include_labels(issues)
         | 
| 172 175 | 
             
                  if options[:include_labels].nil?
         | 
| 173 176 | 
             
                    issues
         | 
| @@ -11,15 +11,10 @@ module GitHubChangelogGenerator | |
| 11 11 | 
             
                  fetch_tags_dates(all_tags) # Creates a Hash @tag_times_hash
         | 
| 12 12 | 
             
                  all_sorted_tags = sort_tags_by_date(all_tags)
         | 
| 13 13 |  | 
| 14 | 
            -
                  @sorted_tags   =  | 
| 14 | 
            +
                  @sorted_tags   = filter_included_tags(all_sorted_tags)
         | 
| 15 | 
            +
                  @sorted_tags   = filter_excluded_tags(@sorted_tags)
         | 
| 15 16 | 
             
                  @filtered_tags = get_filtered_tags(@sorted_tags)
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                  # Because we need to properly create compare links, we need a sorted list
         | 
| 18 | 
            -
                  # of all filtered tags (including the excluded ones). We'll exclude those
         | 
| 19 | 
            -
                  # tags from section headers inside the mapping function.
         | 
| 20 | 
            -
                  section_tags = get_filtered_tags(all_sorted_tags)
         | 
| 21 | 
            -
             | 
| 22 | 
            -
                  @tag_section_mapping = build_tag_section_mapping(section_tags, @filtered_tags)
         | 
| 17 | 
            +
                  @tag_section_mapping = build_tag_section_mapping(@filtered_tags, @filtered_tags)
         | 
| 23 18 |  | 
| 24 19 | 
             
                  @filtered_tags
         | 
| 25 20 | 
             
                end
         | 
| @@ -83,7 +78,7 @@ module GitHubChangelogGenerator | |
| 83 78 | 
             
                # @return [Array] link, name and time of the tag
         | 
| 84 79 | 
             
                def detect_link_tag_time(newer_tag)
         | 
| 85 80 | 
             
                  # if tag is nil - set current time
         | 
| 86 | 
            -
                  newer_tag_time = newer_tag.nil? ? Time.new : get_time_of_tag(newer_tag)
         | 
| 81 | 
            +
                  newer_tag_time = newer_tag.nil? ? Time.new.getutc : get_time_of_tag(newer_tag)
         | 
| 87 82 |  | 
| 88 83 | 
             
                  # if it's future release tag - set this value
         | 
| 89 84 | 
             
                  if newer_tag.nil? && options[:future_release]
         | 
| @@ -161,6 +156,17 @@ module GitHubChangelogGenerator | |
| 161 156 | 
             
                  filtered_tags
         | 
| 162 157 | 
             
                end
         | 
| 163 158 |  | 
| 159 | 
            +
                # @param [Array] all_tags all tags
         | 
| 160 | 
            +
                # @return [Array] filtered tags according to :include_tags_regex option
         | 
| 161 | 
            +
                def filter_included_tags(all_tags)
         | 
| 162 | 
            +
                  if options[:include_tags_regex]
         | 
| 163 | 
            +
                    regex = Regexp.new(options[:include_tags_regex])
         | 
| 164 | 
            +
                    all_tags.select { |tag| regex =~ tag["name"] }
         | 
| 165 | 
            +
                  else
         | 
| 166 | 
            +
                    all_tags
         | 
| 167 | 
            +
                  end
         | 
| 168 | 
            +
                end
         | 
| 169 | 
            +
             | 
| 164 170 | 
             
                # @param [Array] all_tags all tags
         | 
| 165 171 | 
             
                # @return [Array] filtered tags according :exclude_tags or :exclude_tags_regex option
         | 
| 166 172 | 
             
                def filter_excluded_tags(all_tags)
         | 
| @@ -7,7 +7,23 @@ module GitHubChangelogGenerator | |
| 7 7 | 
             
              #
         | 
| 8 8 | 
             
              # @see GitHubChangelogGenerator::Entry
         | 
| 9 9 | 
             
              class Section
         | 
| 10 | 
            -
                 | 
| 10 | 
            +
                # @return [String]
         | 
| 11 | 
            +
                attr_accessor :name
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                # @return [String] a merge prefix, or an issue prefix
         | 
| 14 | 
            +
                attr_reader :prefix
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                # @return [Array<Hash>]
         | 
| 17 | 
            +
                attr_reader :issues
         | 
| 18 | 
            +
             | 
| 19 | 
            +
                # @return [Array<String>]
         | 
| 20 | 
            +
                attr_reader :labels
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                # @return [Boolean]
         | 
| 23 | 
            +
                attr_reader :body_only
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                # @return [Options]
         | 
| 26 | 
            +
                attr_reader :options
         | 
| 11 27 |  | 
| 12 28 | 
             
                def initialize(opts = {})
         | 
| 13 29 | 
             
                  @name = opts[:name]
         | 
| @@ -16,11 +32,12 @@ module GitHubChangelogGenerator | |
| 16 32 | 
             
                  @issues = opts[:issues] || []
         | 
| 17 33 | 
             
                  @options = opts[:options] || Options.new({})
         | 
| 18 34 | 
             
                  @body_only = opts[:body_only] || false
         | 
| 35 | 
            +
                  @entry = Entry.new(options)
         | 
| 19 36 | 
             
                end
         | 
| 20 37 |  | 
| 21 38 | 
             
                # Returns the content of a section.
         | 
| 22 39 | 
             
                #
         | 
| 23 | 
            -
                # @return [String]  | 
| 40 | 
            +
                # @return [String] Generated section content
         | 
| 24 41 | 
             
                def generate_content
         | 
| 25 42 | 
             
                  content = ""
         | 
| 26 43 |  | 
| @@ -49,7 +66,7 @@ module GitHubChangelogGenerator | |
| 49 66 | 
             
                  encapsulated_title = encapsulate_string issue["title"]
         | 
| 50 67 |  | 
| 51 68 | 
             
                  title_with_number = "#{encapsulated_title} [\\##{issue['number']}](#{issue['html_url']})"
         | 
| 52 | 
            -
                  title_with_number = "#{title_with_number}#{line_labels_for(issue)}" if @options[:issue_line_labels].present?
         | 
| 69 | 
            +
                  title_with_number = "#{title_with_number}#{@entry.line_labels_for(issue)}" if @options[:issue_line_labels].present?
         | 
| 53 70 | 
             
                  line = issue_line_with_user(title_with_number, issue)
         | 
| 54 71 | 
             
                  issue_line_with_body(line, issue)
         | 
| 55 72 | 
             
                end
         | 
| @@ -60,16 +77,16 @@ module GitHubChangelogGenerator | |
| 60 77 |  | 
| 61 78 | 
             
                  # get issue body till first line break
         | 
| 62 79 | 
             
                  body_paragraph = body_till_first_break(issue["body"])
         | 
| 63 | 
            -
                  # remove spaces from  | 
| 80 | 
            +
                  # remove spaces from beginning of the string
         | 
| 64 81 | 
             
                  body_paragraph.rstrip!
         | 
| 65 82 | 
             
                  # encapsulate to md
         | 
| 66 | 
            -
                  encapsulated_body = "\ | 
| 83 | 
            +
                  encapsulated_body = "  \n#{encapsulate_string(body_paragraph)}"
         | 
| 67 84 |  | 
| 68 85 | 
             
                  "**#{line}** #{encapsulated_body}"
         | 
| 69 86 | 
             
                end
         | 
| 70 87 |  | 
| 71 88 | 
             
                def body_till_first_break(body)
         | 
| 72 | 
            -
                  body.split(/\n | 
| 89 | 
            +
                  body.split(/\n/, 2).first
         | 
| 73 90 | 
             
                end
         | 
| 74 91 |  | 
| 75 92 | 
             
                def issue_line_with_user(line, issue)
         | 
| @@ -95,7 +112,10 @@ module GitHubChangelogGenerator | |
| 95 112 | 
             
                  string = string.gsub('\\', '\\\\')
         | 
| 96 113 |  | 
| 97 114 | 
             
                  ENCAPSULATED_CHARACTERS.each do |char|
         | 
| 98 | 
            -
                     | 
| 115 | 
            +
                    # Only replace char with escaped version if it isn't inside backticks (markdown inline code).
         | 
| 116 | 
            +
                    # This relies on each opening '`' being closed (ie an even number in total).
         | 
| 117 | 
            +
                    # A char is *outside* backticks if there is an even number of backticks following it.
         | 
| 118 | 
            +
                    string = string.gsub(%r{#{Regexp.escape(char)}(?=([^`]*`[^`]*`)*[^`]*$)}, "\\#{char}")
         | 
| 99 119 | 
             
                  end
         | 
| 100 120 |  | 
| 101 121 | 
             
                  string
         | 
| @@ -14,7 +14,7 @@ module GitHubChangelogGenerator | |
| 14 14 | 
             
                @log ||= if test?
         | 
| 15 15 | 
             
                           Logger.new(nil) # don't show any logs when running tests
         | 
| 16 16 | 
             
                         else
         | 
| 17 | 
            -
                           Logger.new( | 
| 17 | 
            +
                           Logger.new($stdout)
         | 
| 18 18 | 
             
                         end
         | 
| 19 19 | 
             
                @log.formatter = proc do |severity, _datetime, _progname, msg|
         | 
| 20 20 | 
             
                  string = "#{msg}\n"
         | 
| @@ -2,6 +2,12 @@ | |
| 2 2 |  | 
| 3 3 | 
             
            require "tmpdir"
         | 
| 4 4 | 
             
            require "retriable"
         | 
| 5 | 
            +
            require "set"
         | 
| 6 | 
            +
            require "async"
         | 
| 7 | 
            +
            require "async/barrier"
         | 
| 8 | 
            +
            require "async/semaphore"
         | 
| 9 | 
            +
            require "async/http/faraday"
         | 
| 10 | 
            +
             | 
| 5 11 | 
             
            module GitHubChangelogGenerator
         | 
| 6 12 | 
             
              # A Fetcher responsible for all requests to GitHub and all basic manipulation with related data
         | 
| 7 13 | 
             
              # (such as filtering, validating, e.t.c)
         | 
| @@ -9,14 +15,14 @@ module GitHubChangelogGenerator | |
| 9 15 | 
             
              # Example:
         | 
| 10 16 | 
             
              # fetcher = GitHubChangelogGenerator::OctoFetcher.new(options)
         | 
| 11 17 | 
             
              class OctoFetcher
         | 
| 12 | 
            -
                PER_PAGE_NUMBER | 
| 13 | 
            -
                 | 
| 18 | 
            +
                PER_PAGE_NUMBER = 100
         | 
| 19 | 
            +
                MAXIMUM_CONNECTIONS = 50
         | 
| 14 20 | 
             
                MAX_FORBIDDEN_RETRIES = 100
         | 
| 15 21 | 
             
                CHANGELOG_GITHUB_TOKEN = "CHANGELOG_GITHUB_TOKEN"
         | 
| 16 22 | 
             
                GH_RATE_LIMIT_EXCEEDED_MSG = "Warning: Can't finish operation: GitHub API rate limit exceeded, changelog may be " \
         | 
| 17 23 | 
             
                "missing some issues. You can limit the number of issues fetched using the `--max-issues NUM` argument."
         | 
| 18 24 | 
             
                NO_TOKEN_PROVIDED = "Warning: No token provided (-t option) and variable $CHANGELOG_GITHUB_TOKEN was not found. " \
         | 
| 19 | 
            -
                "This script can make only 50 requests to GitHub API per hour without token!"
         | 
| 25 | 
            +
                "This script can make only 50 requests to GitHub API per hour without a token!"
         | 
| 20 26 |  | 
| 21 27 | 
             
                # @param options [Hash] Options passed in
         | 
| 22 28 | 
             
                # @option options [String] :user GitHub username
         | 
| @@ -31,47 +37,58 @@ module GitHubChangelogGenerator | |
| 31 37 | 
             
                  @project      = @options[:project]
         | 
| 32 38 | 
             
                  @since        = @options[:since]
         | 
| 33 39 | 
             
                  @http_cache   = @options[:http_cache]
         | 
| 34 | 
            -
                  @cache_file   = nil
         | 
| 35 | 
            -
                  @cache_log    = nil
         | 
| 36 40 | 
             
                  @commits      = []
         | 
| 37 | 
            -
                  @ | 
| 38 | 
            -
                   | 
| 39 | 
            -
                   | 
| 40 | 
            -
                  @ | 
| 41 | 
            +
                  @branches     = nil
         | 
| 42 | 
            +
                  @graph        = nil
         | 
| 43 | 
            +
                  @client = nil
         | 
| 44 | 
            +
                  @commits_in_tag_cache = {}
         | 
| 45 | 
            +
                end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                def middleware
         | 
| 48 | 
            +
                  Faraday::RackBuilder.new do |builder|
         | 
| 49 | 
            +
                    if @http_cache
         | 
| 50 | 
            +
                      cache_file = @options.fetch(:cache_file) { File.join(Dir.tmpdir, "github-changelog-http-cache") }
         | 
| 51 | 
            +
                      cache_log  = @options.fetch(:cache_log) { File.join(Dir.tmpdir, "github-changelog-logger.log") }
         | 
| 52 | 
            +
             | 
| 53 | 
            +
                      builder.use(
         | 
| 54 | 
            +
                        Faraday::HttpCache,
         | 
| 55 | 
            +
                        serializer: Marshal,
         | 
| 56 | 
            +
                        store: ActiveSupport::Cache::FileStore.new(cache_file),
         | 
| 57 | 
            +
                        logger: Logger.new(cache_log),
         | 
| 58 | 
            +
                        shared_cache: false
         | 
| 59 | 
            +
                      )
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                    builder.use Octokit::Response::RaiseError
         | 
| 63 | 
            +
                    builder.adapter :async_http
         | 
| 64 | 
            +
                  end
         | 
| 41 65 | 
             
                end
         | 
| 42 66 |  | 
| 43 | 
            -
                def  | 
| 44 | 
            -
                   | 
| 67 | 
            +
                def connection_options
         | 
| 68 | 
            +
                  ca_file = @options[:ssl_ca_file] || ENV["SSL_CA_FILE"] || File.expand_path("ssl_certs/cacert.pem", __dir__)
         | 
| 45 69 |  | 
| 46 | 
            -
                   | 
| 47 | 
            -
                  @cache_log  = @options.fetch(:cache_log) { File.join(Dir.tmpdir, "github-changelog-logger.log") }
         | 
| 48 | 
            -
                  init_cache
         | 
| 70 | 
            +
                  Octokit.connection_options.merge({ ssl: { ca_file: ca_file } })
         | 
| 49 71 | 
             
                end
         | 
| 50 72 |  | 
| 51 | 
            -
                def  | 
| 52 | 
            -
                   | 
| 53 | 
            -
             | 
| 54 | 
            -
             | 
| 55 | 
            -
                   | 
| 56 | 
            -
                  result[:api_endpoint] = endpoint if endpoint
         | 
| 57 | 
            -
                  result
         | 
| 58 | 
            -
                end
         | 
| 73 | 
            +
                def client_options
         | 
| 74 | 
            +
                  options = {
         | 
| 75 | 
            +
                    middleware: middleware,
         | 
| 76 | 
            +
                    connection_options: connection_options
         | 
| 77 | 
            +
                  }
         | 
| 59 78 |  | 
| 60 | 
            -
             | 
| 61 | 
            -
             | 
| 62 | 
            -
                   | 
| 63 | 
            -
                end
         | 
| 79 | 
            +
                  if (github_token = fetch_github_token)
         | 
| 80 | 
            +
                    options[:access_token] = github_token
         | 
| 81 | 
            +
                  end
         | 
| 64 82 |  | 
| 65 | 
            -
             | 
| 66 | 
            -
             | 
| 67 | 
            -
                    builder.use(Faraday::HttpCache, serializer: Marshal,
         | 
| 68 | 
            -
                                                    store: ActiveSupport::Cache::FileStore.new(@cache_file),
         | 
| 69 | 
            -
                                                    logger: Logger.new(@cache_log),
         | 
| 70 | 
            -
                                                    shared_cache: false)
         | 
| 71 | 
            -
                    builder.use Octokit::Response::RaiseError
         | 
| 72 | 
            -
                    builder.adapter Faraday.default_adapter
         | 
| 73 | 
            -
                    # builder.response :logger
         | 
| 83 | 
            +
                  if (endpoint = @options[:github_endpoint])
         | 
| 84 | 
            +
                    options[:api_endpoint] = endpoint
         | 
| 74 85 | 
             
                  end
         | 
| 86 | 
            +
             | 
| 87 | 
            +
                  options
         | 
| 88 | 
            +
                end
         | 
| 89 | 
            +
             | 
| 90 | 
            +
                def client
         | 
| 91 | 
            +
                  @client ||= Octokit::Client.new(client_options)
         | 
| 75 92 | 
             
                end
         | 
| 76 93 |  | 
| 77 94 | 
             
                DEFAULT_REQUEST_OPTIONS = { per_page: PER_PAGE_NUMBER }
         | 
| @@ -88,6 +105,9 @@ module GitHubChangelogGenerator | |
| 88 105 | 
             
                # Returns the number of pages for a API call
         | 
| 89 106 | 
             
                #
         | 
| 90 107 | 
             
                # @return [Integer] number of pages for this API call in total
         | 
| 108 | 
            +
                # @param [Object] request_options
         | 
| 109 | 
            +
                # @param [Object] method
         | 
| 110 | 
            +
                # @param [Object] client
         | 
| 91 111 | 
             
                def calculate_pages(client, method, request_options)
         | 
| 92 112 | 
             
                  # Makes the first API call so that we can call last_response
         | 
| 93 113 | 
             
                  check_github_response do
         | 
| @@ -107,11 +127,11 @@ module GitHubChangelogGenerator | |
| 107 127 | 
             
                #
         | 
| 108 128 | 
             
                # @return [Array <Hash>] array of tags in repo
         | 
| 109 129 | 
             
                def github_fetch_tags
         | 
| 110 | 
            -
                  tags | 
| 111 | 
            -
                  page_i | 
| 112 | 
            -
                  count_pages = calculate_pages( | 
| 130 | 
            +
                  tags = []
         | 
| 131 | 
            +
                  page_i = 0
         | 
| 132 | 
            +
                  count_pages = calculate_pages(client, "tags", {})
         | 
| 113 133 |  | 
| 114 | 
            -
                  iterate_pages( | 
| 134 | 
            +
                  iterate_pages(client, "tags") do |new_tags|
         | 
| 115 135 | 
             
                    page_i += PER_PAGE_NUMBER
         | 
| 116 136 | 
             
                    print_in_same_line("Fetching tags... #{page_i}/#{count_pages * PER_PAGE_NUMBER}")
         | 
| 117 137 | 
             
                    tags.concat(new_tags)
         | 
| @@ -142,9 +162,9 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 142 162 | 
             
                  print "Fetching closed issues...\r" if @options[:verbose]
         | 
| 143 163 | 
             
                  issues = []
         | 
| 144 164 | 
             
                  page_i = 0
         | 
| 145 | 
            -
                  count_pages = calculate_pages( | 
| 165 | 
            +
                  count_pages = calculate_pages(client, "issues", closed_pr_options)
         | 
| 146 166 |  | 
| 147 | 
            -
                  iterate_pages( | 
| 167 | 
            +
                  iterate_pages(client, "issues", **closed_pr_options) do |new_issues|
         | 
| 148 168 | 
             
                    page_i += PER_PAGE_NUMBER
         | 
| 149 169 | 
             
                    print_in_same_line("Fetching issues... #{page_i}/#{count_pages * PER_PAGE_NUMBER}")
         | 
| 150 170 | 
             
                    issues.concat(new_issues)
         | 
| @@ -165,10 +185,10 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 165 185 | 
             
                  pull_requests = []
         | 
| 166 186 | 
             
                  options = { state: "closed" }
         | 
| 167 187 |  | 
| 168 | 
            -
                  page_i | 
| 169 | 
            -
                  count_pages = calculate_pages( | 
| 188 | 
            +
                  page_i = 0
         | 
| 189 | 
            +
                  count_pages = calculate_pages(client, "pull_requests", options)
         | 
| 170 190 |  | 
| 171 | 
            -
                  iterate_pages( | 
| 191 | 
            +
                  iterate_pages(client, "pull_requests", **options) do |new_pr|
         | 
| 172 192 | 
             
                    page_i += PER_PAGE_NUMBER
         | 
| 173 193 | 
             
                    log_string = "Fetching merged dates... #{page_i}/#{count_pages * PER_PAGE_NUMBER}"
         | 
| 174 194 | 
             
                    print_in_same_line(log_string)
         | 
| @@ -185,14 +205,20 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 185 205 | 
             
                # @param [Array] issues
         | 
| 186 206 | 
             
                # @return [Void]
         | 
| 187 207 | 
             
                def fetch_events_async(issues)
         | 
| 188 | 
            -
                  i | 
| 189 | 
            -
                   | 
| 208 | 
            +
                  i = 0
         | 
| 209 | 
            +
                  # Add accept option explicitly for disabling the warning of preview API.
         | 
| 210 | 
            +
                  preview = { accept: Octokit::Preview::PREVIEW_TYPES[:project_card_events] }
         | 
| 211 | 
            +
             | 
| 212 | 
            +
                  barrier = Async::Barrier.new
         | 
| 213 | 
            +
                  semaphore = Async::Semaphore.new(MAXIMUM_CONNECTIONS, parent: barrier)
         | 
| 214 | 
            +
             | 
| 215 | 
            +
                  Sync do
         | 
| 216 | 
            +
                    client = self.client
         | 
| 190 217 |  | 
| 191 | 
            -
             | 
| 192 | 
            -
             | 
| 193 | 
            -
                      threads << Thread.new do
         | 
| 218 | 
            +
                    issues.each do |issue|
         | 
| 219 | 
            +
                      semaphore.async do
         | 
| 194 220 | 
             
                        issue["events"] = []
         | 
| 195 | 
            -
                        iterate_pages( | 
| 221 | 
            +
                        iterate_pages(client, "issue_events", issue["number"], **preview) do |new_event|
         | 
| 196 222 | 
             
                          issue["events"].concat(new_event)
         | 
| 197 223 | 
             
                        end
         | 
| 198 224 | 
             
                        issue["events"] = issue["events"].map { |event| stringify_keys_deep(event.to_hash) }
         | 
| @@ -200,12 +226,12 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 200 226 | 
             
                        i += 1
         | 
| 201 227 | 
             
                      end
         | 
| 202 228 | 
             
                    end
         | 
| 203 | 
            -
                    threads.each(&:join)
         | 
| 204 | 
            -
                    threads = []
         | 
| 205 | 
            -
                  end
         | 
| 206 229 |  | 
| 207 | 
            -
             | 
| 208 | 
            -
             | 
| 230 | 
            +
                    barrier.wait
         | 
| 231 | 
            +
             | 
| 232 | 
            +
                    # to clear line from prev print
         | 
| 233 | 
            +
                    print_empty_line
         | 
| 234 | 
            +
                  end
         | 
| 209 235 |  | 
| 210 236 | 
             
                  Helper.log.info "Fetching events for issues and PR: #{i}"
         | 
| 211 237 | 
             
                end
         | 
| @@ -215,21 +241,25 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 215 241 | 
             
                # @param [Array] prs The array of PRs.
         | 
| 216 242 | 
             
                # @return [Void] No return; PRs are updated in-place.
         | 
| 217 243 | 
             
                def fetch_comments_async(prs)
         | 
| 218 | 
            -
                   | 
| 244 | 
            +
                  barrier = Async::Barrier.new
         | 
| 245 | 
            +
                  semaphore = Async::Semaphore.new(MAXIMUM_CONNECTIONS, parent: barrier)
         | 
| 219 246 |  | 
| 220 | 
            -
                   | 
| 221 | 
            -
                     | 
| 222 | 
            -
             | 
| 247 | 
            +
                  Sync do
         | 
| 248 | 
            +
                    client = self.client
         | 
| 249 | 
            +
             | 
| 250 | 
            +
                    prs.each do |pr|
         | 
| 251 | 
            +
                      semaphore.async do
         | 
| 223 252 | 
             
                        pr["comments"] = []
         | 
| 224 | 
            -
                        iterate_pages( | 
| 253 | 
            +
                        iterate_pages(client, "issue_comments", pr["number"]) do |new_comment|
         | 
| 225 254 | 
             
                          pr["comments"].concat(new_comment)
         | 
| 226 255 | 
             
                        end
         | 
| 227 256 | 
             
                        pr["comments"] = pr["comments"].map { |comment| stringify_keys_deep(comment.to_hash) }
         | 
| 228 257 | 
             
                      end
         | 
| 229 258 | 
             
                    end
         | 
| 230 | 
            -
             | 
| 231 | 
            -
                     | 
| 259 | 
            +
             | 
| 260 | 
            +
                    barrier.wait
         | 
| 232 261 | 
             
                  end
         | 
| 262 | 
            +
             | 
| 233 263 | 
             
                  nil
         | 
| 234 264 | 
             
                end
         | 
| 235 265 |  | 
| @@ -245,21 +275,6 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 245 275 | 
             
                  commit_data["commit"]["committer"]["date"]
         | 
| 246 276 | 
             
                end
         | 
| 247 277 |  | 
| 248 | 
            -
                # Fetch and cache comparison between two github refs
         | 
| 249 | 
            -
                #
         | 
| 250 | 
            -
                # @param [String] older The older sha/tag/branch.
         | 
| 251 | 
            -
                # @param [String] newer The newer sha/tag/branch.
         | 
| 252 | 
            -
                # @return [Hash] Github api response for comparison.
         | 
| 253 | 
            -
                def fetch_compare(older, newer)
         | 
| 254 | 
            -
                  unless @compares["#{older}...#{newer}"]
         | 
| 255 | 
            -
                    compare_data = check_github_response { @client.compare(user_project, older, newer || "HEAD") }
         | 
| 256 | 
            -
                    raise StandardError, "Sha #{older} and sha #{newer} are not related; please file a github-changelog-generator issues and describe how to replicate this issue." if compare_data["status"] == "diverged"
         | 
| 257 | 
            -
             | 
| 258 | 
            -
                    @compares["#{older}...#{newer}"] = stringify_keys_deep(compare_data.to_hash)
         | 
| 259 | 
            -
                  end
         | 
| 260 | 
            -
                  @compares["#{older}...#{newer}"]
         | 
| 261 | 
            -
                end
         | 
| 262 | 
            -
             | 
| 263 278 | 
             
                # Fetch commit for specified event
         | 
| 264 279 | 
             
                #
         | 
| 265 280 | 
             
                # @param [String] commit_id the SHA of a commit to fetch
         | 
| @@ -271,9 +286,11 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 271 286 | 
             
                  if found
         | 
| 272 287 | 
             
                    stringify_keys_deep(found.to_hash)
         | 
| 273 288 | 
             
                  else
         | 
| 289 | 
            +
                    client = self.client
         | 
| 290 | 
            +
             | 
| 274 291 | 
             
                    # cache miss; don't add to @commits because unsure of order.
         | 
| 275 292 | 
             
                    check_github_response do
         | 
| 276 | 
            -
                      commit =  | 
| 293 | 
            +
                      commit = client.commit(user_project, commit_id)
         | 
| 277 294 | 
             
                      commit = stringify_keys_deep(commit.to_hash)
         | 
| 278 295 | 
             
                      commit
         | 
| 279 296 | 
             
                    end
         | 
| @@ -285,8 +302,25 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 285 302 | 
             
                # @return [Array] Commits in a repo.
         | 
| 286 303 | 
             
                def commits
         | 
| 287 304 | 
             
                  if @commits.empty?
         | 
| 288 | 
            -
                     | 
| 289 | 
            -
                       | 
| 305 | 
            +
                    Sync do
         | 
| 306 | 
            +
                      barrier = Async::Barrier.new
         | 
| 307 | 
            +
                      semaphore = Async::Semaphore.new(MAXIMUM_CONNECTIONS, parent: barrier)
         | 
| 308 | 
            +
             | 
| 309 | 
            +
                      if (since_commit = @options[:since_commit])
         | 
| 310 | 
            +
                        iterate_pages(client, "commits_since", since_commit, parent: semaphore) do |new_commits|
         | 
| 311 | 
            +
                          @commits.concat(new_commits)
         | 
| 312 | 
            +
                        end
         | 
| 313 | 
            +
                      else
         | 
| 314 | 
            +
                        iterate_pages(client, "commits", parent: semaphore) do |new_commits|
         | 
| 315 | 
            +
                          @commits.concat(new_commits)
         | 
| 316 | 
            +
                        end
         | 
| 317 | 
            +
                      end
         | 
| 318 | 
            +
             | 
| 319 | 
            +
                      barrier.wait
         | 
| 320 | 
            +
             | 
| 321 | 
            +
                      @commits.sort! do |b, a|
         | 
| 322 | 
            +
                        a[:commit][:author][:date] <=> b[:commit][:author][:date]
         | 
| 323 | 
            +
                      end
         | 
| 290 324 | 
             
                    end
         | 
| 291 325 | 
             
                  end
         | 
| 292 326 | 
             
                  @commits
         | 
| @@ -301,42 +335,63 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 301 335 |  | 
| 302 336 | 
             
                # @return [String] Default branch of the repo
         | 
| 303 337 | 
             
                def default_branch
         | 
| 304 | 
            -
                  @default_branch ||=  | 
| 338 | 
            +
                  @default_branch ||= client.repository(user_project)[:default_branch]
         | 
| 339 | 
            +
                end
         | 
| 340 | 
            +
             | 
| 341 | 
            +
                # @param [String] name
         | 
| 342 | 
            +
                # @return [Array<String>]
         | 
| 343 | 
            +
                def commits_in_branch(name)
         | 
| 344 | 
            +
                  @branches ||= client.branches(user_project).map { |branch| [branch[:name], branch] }.to_h
         | 
| 345 | 
            +
             | 
| 346 | 
            +
                  if (branch = @branches[name])
         | 
| 347 | 
            +
                    commits_in_tag(branch[:commit][:sha])
         | 
| 348 | 
            +
                  else
         | 
| 349 | 
            +
                    []
         | 
| 350 | 
            +
                  end
         | 
| 305 351 | 
             
                end
         | 
| 306 352 |  | 
| 307 353 | 
             
                # Fetch all SHAs occurring in or before a given tag and add them to
         | 
| 308 354 | 
             
                # "shas_in_tag"
         | 
| 309 355 | 
             
                #
         | 
| 310 356 | 
             
                # @param [Array] tags The array of tags.
         | 
| 311 | 
            -
                # @return  | 
| 312 | 
            -
                def  | 
| 313 | 
            -
                   | 
| 314 | 
            -
                   | 
| 315 | 
            -
             | 
| 316 | 
            -
             | 
| 317 | 
            -
             | 
| 318 | 
            -
             | 
| 319 | 
            -
             | 
| 320 | 
            -
             | 
| 321 | 
            -
             | 
| 322 | 
            -
             | 
| 323 | 
            -
             | 
| 324 | 
            -
             | 
| 357 | 
            +
                # @return void
         | 
| 358 | 
            +
                def fetch_tag_shas(tags)
         | 
| 359 | 
            +
                  # Reverse the tags array to gain max benefit from the @commits_in_tag_cache
         | 
| 360 | 
            +
                  tags.reverse_each do |tag|
         | 
| 361 | 
            +
                    tag["shas_in_tag"] = commits_in_tag(tag["commit"]["sha"])
         | 
| 362 | 
            +
                  end
         | 
| 363 | 
            +
                end
         | 
| 364 | 
            +
             | 
| 365 | 
            +
                private
         | 
| 366 | 
            +
             | 
| 367 | 
            +
                # @param [Set] shas
         | 
| 368 | 
            +
                # @param [Object] sha
         | 
| 369 | 
            +
                def commits_in_tag(sha, shas = Set.new)
         | 
| 370 | 
            +
                  # Reduce multiple runs for the same tag
         | 
| 371 | 
            +
                  return @commits_in_tag_cache[sha] if @commits_in_tag_cache.key?(sha)
         | 
| 372 | 
            +
             | 
| 373 | 
            +
                  @graph ||= commits.map { |commit| [commit[:sha], commit] }.to_h
         | 
| 374 | 
            +
                  return shas unless (current = @graph[sha])
         | 
| 375 | 
            +
             | 
| 376 | 
            +
                  queue = [current]
         | 
| 377 | 
            +
                  while queue.any?
         | 
| 378 | 
            +
                    commit = queue.shift
         | 
| 379 | 
            +
                    # If we've already processed this sha, just grab it's parents from the cache
         | 
| 380 | 
            +
                    if @commits_in_tag_cache.key?(commit[:sha])
         | 
| 381 | 
            +
                      shas.merge(@commits_in_tag_cache[commit[:sha]])
         | 
| 382 | 
            +
                    else
         | 
| 383 | 
            +
                      shas.add(commit[:sha])
         | 
| 384 | 
            +
                      commit[:parents].each do |p|
         | 
| 385 | 
            +
                        queue.push(@graph[p[:sha]]) unless shas.include?(p[:sha])
         | 
| 325 386 | 
             
                      end
         | 
| 326 387 | 
             
                    end
         | 
| 327 | 
            -
                    threads.each(&:join)
         | 
| 328 | 
            -
                    threads = []
         | 
| 329 388 | 
             
                  end
         | 
| 330 389 |  | 
| 331 | 
            -
                   | 
| 332 | 
            -
                   | 
| 333 | 
            -
             | 
| 334 | 
            -
                  Helper.log.info "Fetching SHAs for tags: #{i}"
         | 
| 335 | 
            -
                  nil
         | 
| 390 | 
            +
                  @commits_in_tag_cache[sha] = shas
         | 
| 391 | 
            +
                  shas
         | 
| 336 392 | 
             
                end
         | 
| 337 393 |  | 
| 338 | 
            -
                 | 
| 339 | 
            -
             | 
| 394 | 
            +
                # @param [Object] indata
         | 
| 340 395 | 
             
                def stringify_keys_deep(indata)
         | 
| 341 396 | 
             
                  case indata
         | 
| 342 397 | 
             
                  when Array
         | 
| @@ -360,43 +415,49 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 360 415 | 
             
                #
         | 
| 361 416 | 
             
                # @param [Octokit::Client] client
         | 
| 362 417 | 
             
                # @param [String] method (eg. 'tags')
         | 
| 418 | 
            +
                # @param [Array] arguments
         | 
| 419 | 
            +
                # @param [Async::Semaphore] parent
         | 
| 363 420 | 
             
                #
         | 
| 364 421 | 
             
                # @yield [Sawyer::Resource] An OctoKit-provided response (which can be empty)
         | 
| 365 422 | 
             
                #
         | 
| 366 423 | 
             
                # @return [void]
         | 
| 367 | 
            -
                 | 
| 368 | 
            -
             | 
| 424 | 
            +
                # @param [Hash] options
         | 
| 425 | 
            +
                def iterate_pages(client, method, *arguments, parent: nil, **options)
         | 
| 426 | 
            +
                  options = DEFAULT_REQUEST_OPTIONS.merge(options)
         | 
| 369 427 |  | 
| 370 | 
            -
                  check_github_response { client.send(method, user_project, * | 
| 428 | 
            +
                  check_github_response { client.send(method, user_project, *arguments, **options) }
         | 
| 371 429 | 
             
                  last_response = client.last_response.tap do |response|
         | 
| 372 430 | 
             
                    raise(MovedPermanentlyError, response.data[:url]) if response.status == 301
         | 
| 373 431 | 
             
                  end
         | 
| 374 432 |  | 
| 375 433 | 
             
                  yield(last_response.data)
         | 
| 376 434 |  | 
| 377 | 
            -
                   | 
| 378 | 
            -
                     | 
| 379 | 
            -
                     | 
| 380 | 
            -
             | 
| 381 | 
            -
             | 
| 382 | 
            -
             | 
| 383 | 
            -
             | 
| 384 | 
            -
             | 
| 385 | 
            -
                     | 
| 386 | 
            -
             | 
| 387 | 
            -
             | 
| 388 | 
            -
             | 
| 389 | 
            -
             | 
| 435 | 
            +
                  if parent.nil?
         | 
| 436 | 
            +
                    # The snail visits one leaf at a time:
         | 
| 437 | 
            +
                    until (next_one = last_response.rels[:next]).nil?
         | 
| 438 | 
            +
                      last_response = check_github_response { next_one.get }
         | 
| 439 | 
            +
                      yield(last_response.data)
         | 
| 440 | 
            +
                    end
         | 
| 441 | 
            +
                  elsif (last = last_response.rels[:last])
         | 
| 442 | 
            +
                    # OR we bring out the gatling gun:
         | 
| 443 | 
            +
                    parameters = querystring_as_hash(last.href)
         | 
| 444 | 
            +
                    last_page = Integer(parameters["page"])
         | 
| 445 | 
            +
             | 
| 446 | 
            +
                    (2..last_page).each do |page|
         | 
| 447 | 
            +
                      parent.async do
         | 
| 448 | 
            +
                        data = check_github_response { client.send(method, user_project, *arguments, page: page, **options) }
         | 
| 449 | 
            +
                        yield data
         | 
| 450 | 
            +
                      end
         | 
| 451 | 
            +
                    end
         | 
| 390 452 | 
             
                  end
         | 
| 391 453 | 
             
                end
         | 
| 392 454 |  | 
| 393 455 | 
             
                # This is wrapper with rescue block
         | 
| 394 456 | 
             
                #
         | 
| 395 457 | 
             
                # @return [Object] returns exactly the same, what you put in the block, but wrap it with begin-rescue block
         | 
| 396 | 
            -
                 | 
| 397 | 
            -
             | 
| 398 | 
            -
             | 
| 399 | 
            -
                  end
         | 
| 458 | 
            +
                # @param [Proc] block
         | 
| 459 | 
            +
                def check_github_response(&block)
         | 
| 460 | 
            +
                  Retriable.retriable(retry_options, &block)
         | 
| 400 461 | 
             
                rescue MovedPermanentlyError => e
         | 
| 401 462 | 
             
                  fail_with_message(e, "The repository has moved, update your configuration")
         | 
| 402 463 | 
             
                rescue Octokit::Forbidden => e
         | 
| @@ -406,6 +467,8 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 406 467 | 
             
                end
         | 
| 407 468 |  | 
| 408 469 | 
             
                # Presents the exception, and the aborts with the message.
         | 
| 470 | 
            +
                # @param [Object] message
         | 
| 471 | 
            +
                # @param [Object] error
         | 
| 409 472 | 
             
                def fail_with_message(error, message)
         | 
| 410 473 | 
             
                  Helper.log.error("#{error.class}: #{error.message}")
         | 
| 411 474 | 
             
                  sys_abort(message)
         | 
| @@ -432,10 +495,11 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 432 495 | 
             
                    Helper.log.warn("RETRY - #{exception.class}: '#{exception.message}'")
         | 
| 433 496 | 
             
                    Helper.log.warn("#{try} tries in #{elapsed_time} seconds and #{next_interval} seconds until the next try")
         | 
| 434 497 | 
             
                    Helper.log.warn GH_RATE_LIMIT_EXCEEDED_MSG
         | 
| 435 | 
            -
                    Helper.log.warn | 
| 498 | 
            +
                    Helper.log.warn(client.rate_limit)
         | 
| 436 499 | 
             
                  end
         | 
| 437 500 | 
             
                end
         | 
| 438 501 |  | 
| 502 | 
            +
                # @param [Object] msg
         | 
| 439 503 | 
             
                def sys_abort(msg)
         | 
| 440 504 | 
             
                  abort(msg)
         | 
| 441 505 | 
             
                end
         | 
| @@ -444,7 +508,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'" | |
| 444 508 | 
             
                #
         | 
| 445 509 | 
             
                # @param [String] log_string
         | 
| 446 510 | 
             
                def print_in_same_line(log_string)
         | 
| 447 | 
            -
                  print log_string | 
| 511 | 
            +
                  print "#{log_string}\r"
         | 
| 448 512 | 
             
                end
         | 
| 449 513 |  | 
| 450 514 | 
             
                # Print long line with spaces on same line to clear prev message
         |