Class: GitHubChangelogGenerator::Generator

Inherits:
Object
  • Object
show all
Defined in:
lib/github_changelog_generator/generator/generator.rb,
lib/github_changelog_generator/generator/generator_tags.rb,
lib/github_changelog_generator/generator/generator_fetcher.rb,
lib/github_changelog_generator/generator/generator_processor.rb,
lib/github_changelog_generator/generator/generator_generation.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(options = nil) ⇒ Generator

A Generator responsible for all logic, related with change log generation from ready-to-parse issues

Example:

generator = GitHubChangelogGenerator::Generator.new
content = generator.compound_changelog

20
21
22
23
24
# File 'lib/github_changelog_generator/generator/generator.rb', line 20

def initialize(options = nil)
  @options = options || {}
  @tag_times_hash = {}
  @fetcher = GitHubChangelogGenerator::Fetcher.new @options
end

Instance Attribute Details

#filtered_tagsObject

Returns the value of attribute filtered_tags


13
14
15
# File 'lib/github_changelog_generator/generator/generator.rb', line 13

def filtered_tags
  @filtered_tags
end

#githubObject

Returns the value of attribute github


13
14
15
# File 'lib/github_changelog_generator/generator/generator.rb', line 13

def github
  @github
end

#optionsObject

Returns the value of attribute options


13
14
15
# File 'lib/github_changelog_generator/generator/generator.rb', line 13

def options
  @options
end

Instance Method Details

#compound_changelogString

Main function to start change log generation

Returns:

  • (String)

    Generated change log file


6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 6

def compound_changelog
  fetch_and_filter_tags
  sort_tags_by_date(@filtered_tags)
  fetch_issues_and_pr

  log = ""
  log += @options[:frontmatter] if @options[:frontmatter]
  log += "#{@options[:header]}\n\n"

  log += if @options[:unreleased_only]
           generate_log_between_tags(filtered_tags[0], nil)
         else
           generate_log_for_all_tags
         end

  log += File.read(@options[:base]) if File.file?(@options[:base])

  log += "\n\n\\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*"
  @log = log
end

#create_log_for_tag(pull_requests, issues, newer_tag, older_tag_name = nil) ⇒ String

Generates log for section with header and body

Parameters:

  • pull_requests (Array)

    List or PR's in new section

  • issues (Array)

    List of issues in new section

  • newer_tag (String)

    Name of the newer tag. Could be nil for `Unreleased` section

  • older_tag_name (String) (defaults to: nil)

    Older tag, used for the links. Could be nil for last tag.

Returns:

  • (String)

    Ready and parsed section


59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
# File 'lib/github_changelog_generator/generator/generator.rb', line 59

def create_log_for_tag(pull_requests, issues, newer_tag, older_tag_name = nil)
  newer_tag_link, newer_tag_name, newer_tag_time = detect_link_tag_time(newer_tag)

  github_site = options[:github_site] || "https://github.com"
  project_url = "#{github_site}/#{@options[:user]}/#{@options[:project]}"

  log = generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url)

  if @options[:issues]
    # Generate issues:
    log += issues_to_log(issues, pull_requests)
  end

  if @options[:pulls]
    # Generate pull requests:
    log += generate_sub_section(pull_requests, @options[:merge_prefix])
  end

  log
end

#delete_by_time(issues, hash_key = :actual_date, older_tag = nil, newer_tag = nil) ⇒ Array

Method filter issues, that belong only specified tag range

Parameters:

  • issues (Array)

    issues to filter

  • hash_key (Symbol) (defaults to: :actual_date)

    key of date value default is :actual_date

  • older_tag (String) (defaults to: nil)

    all issues before this tag date will be excluded. May be nil, if it's first tag

  • newer_tag (String) (defaults to: nil)

    all issue after this tag will be excluded. May be nil for unreleased section

Returns:

  • (Array)

    filtered issues


70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 70

def delete_by_time(issues, hash_key = :actual_date, older_tag = nil, newer_tag = nil)
  # in case if not tags specified - return unchanged array
  return issues if older_tag.nil? && newer_tag.nil?

  newer_tag_time = newer_tag && get_time_of_tag(newer_tag)
  older_tag_time = older_tag && get_time_of_tag(older_tag)

  issues.select do |issue|
    if issue[hash_key]
      time = Time.parse(issue[hash_key]).utc

      tag_in_range_old = tag_newer_old_tag?(older_tag_time, time)

      tag_in_range_new = tag_older_new_tag?(newer_tag_time, time)

      tag_in_range = tag_in_range_old && tag_in_range_new

      tag_in_range
    else
      false
    end
  end
end

#detect_actual_closed_dates(issues) ⇒ Object

Find correct closed dates, if issues was closed by commits


34
35
36
37
38
39
40
41
42
43
44
45
46
# File 'lib/github_changelog_generator/generator/generator_fetcher.rb', line 34

def detect_actual_closed_dates(issues)
  print "Fetching closed dates for issues...\r" if @options[:verbose]

  max_thread_number = 50
  issues.each_slice(max_thread_number) do |issues_slice|
    threads = []
    issues_slice.each do |issue|
      threads << Thread.new { find_closed_date_by_commit(issue) }
    end
    threads.each(&:join)
  end
  puts "Fetching closed dates for issues: Done!" if @options[:verbose]
end

Detect link, name and time for specified tag.

Parameters:

  • newer_tag (Hash)

    newer tag. Can be nil, if it's Unreleased section.

Returns:

  • (Array)

    link, name and time of the tag


39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 39

def detect_link_tag_time(newer_tag)
  # if tag is nil - set current time
  newer_tag_time = newer_tag.nil? ? Time.new : get_time_of_tag(newer_tag)

  # if it's future release tag - set this value
  if newer_tag.nil? && @options[:future_release]
    newer_tag_name = @options[:future_release]
    newer_tag_link = @options[:future_release]
  else
    # put unreleased label if there is no name for the tag
    newer_tag_name = newer_tag.nil? ? @options[:unreleased_label] : newer_tag["name"]
    newer_tag_link = newer_tag.nil? ? "HEAD" : newer_tag_name
  end
  [newer_tag_link, newer_tag_name, newer_tag_time]
end

#detect_since_tagObject

Returns try to find newest tag using #Reader and :base option if specified otherwise returns nil

Returns:

  • (Object)

    try to find newest tag using #Reader and :base option if specified otherwise returns nil


56
57
58
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 56

def detect_since_tag
  @since_tag ||= @options.fetch(:since_tag) { version_of_first_item }
end

#encapsulate_string(string) ⇒ String

Encapsulate characters to make markdown look as expected.

Parameters:

  • string (String)

Returns:

  • (String)

    encapsulated input string


41
42
43
44
45
46
47
48
49
50
# File 'lib/github_changelog_generator/generator/generator.rb', line 41

def encapsulate_string(string)
  string.gsub! '\\', '\\\\'

  encpas_chars = %w(< > * _ \( \) [ ] #)
  encpas_chars.each do |char|
    string.gsub! char, "\\#{char}"
  end

  string
end

#exclude_issues_by_labels(issues) ⇒ Array

delete all labels with labels from @options array

Parameters:

  • issues (Array)

Returns:

  • (Array)

    filtered array


6
7
8
9
10
11
12
13
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 6

def exclude_issues_by_labels(issues)
  return issues if !@options[:exclude_labels] || @options[:exclude_labels].empty?

  issues.reject do |issue|
    labels = issue.labels.map(&:name)
    (labels & @options[:exclude_labels]).any?
  end
end

#fetch_and_filter_tagsObject

fetch, filter tags, fetch dates and sort them in time order


4
5
6
7
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 4

def fetch_and_filter_tags
  @filtered_tags = get_filtered_tags(@fetcher.get_all_tags)
  fetch_tags_dates
end

#fetch_events_for_issues_and_prArray

Fetch event for issues and pull requests

Returns:

  • (Array)

    array of fetched issues


5
6
7
8
9
10
11
12
# File 'lib/github_changelog_generator/generator/generator_fetcher.rb', line 5

def fetch_events_for_issues_and_pr
  if @options[:verbose]
    print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r"
  end

  # Async fetching events:
  @fetcher.fetch_events_async(@issues + @pull_requests)
end

#fetch_issues_and_prObject


26
27
28
29
30
31
32
33
34
35
# File 'lib/github_changelog_generator/generator/generator.rb', line 26

def fetch_issues_and_pr
  issues, pull_requests = @fetcher.fetch_closed_issues_and_pr

  @pull_requests = @options[:pulls] ? get_filtered_pull_requests(pull_requests) : []

  @issues = @options[:issues] ? get_filtered_issues(issues) : []

  fetch_events_for_issues_and_pr
  detect_actual_closed_dates(@issues + @pull_requests)
end

#fetch_tags_datesObject

Async fetching of all tags dates


15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/github_changelog_generator/generator/generator_fetcher.rb', line 15

def fetch_tags_dates
  print "Fetching tag dates...\r" if @options[:verbose]
  # Async fetching tags:
  threads = []
  i = 0
  all = @filtered_tags.count
  @filtered_tags.each do |tag|
    print "                                 \r"
    threads << Thread.new do
      get_time_of_tag(tag)
      print "Fetching tags dates: #{i + 1}/#{all}\r" if @options[:verbose]
      i += 1
    end
  end
  threads.each(&:join)
  puts "Fetching tags dates: #{i}" if @options[:verbose]
end

#filter_array_by_labels(all_issues) ⇒ Array

General filtered function

Parameters:

  • all_issues (Array)

Returns:

  • (Array)

    filtered issues


144
145
146
147
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 144

def filter_array_by_labels(all_issues)
  filtered_issues = include_issues_by_labels(all_issues)
  exclude_issues_by_labels(filtered_issues)
end

#filter_between_tags(all_tags) ⇒ Array

Returns filtered tags according :between_tags option

Parameters:

  • all_tags (Array)

    all tags

Returns:

  • (Array)

    filtered tags according :between_tags option


119
120
121
122
123
124
125
126
127
128
129
130
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 119

def filter_between_tags(all_tags)
  filtered_tags = all_tags
  if @options[:between_tags]
    @options[:between_tags].each do |tag|
      unless all_tags.map(&:name).include? tag
        Helper.log.warn "Warning: can't find tag #{tag}, specified with --between-tags option."
      end
    end
    filtered_tags = all_tags.select { |tag| @options[:between_tags].include? tag.name }
  end
  filtered_tags
end

#filter_by_include_labels(issues) ⇒ Object


132
133
134
135
136
137
138
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 132

def filter_by_include_labels(issues)
  filtered_issues = @options[:include_labels].nil? ? issues : issues.select do |issue|
    labels = issue.labels.map(&:name) & @options[:include_labels]
    labels.any?
  end
  filtered_issues
end

#filter_by_milestone(filtered_issues, tag_name, all_issues) ⇒ Array

Returns filtered issues accourding milestone

Returns:

  • (Array)

    filtered issues accourding milestone


16
17
18
19
20
21
22
23
24
25
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 16

def filter_by_milestone(filtered_issues, tag_name, all_issues)
  remove_issues_in_milestones(filtered_issues)
  unless tag_name.nil?
    # add missed issues (according milestones)
    issues_to_add = find_issues_to_add(all_issues, tag_name)

    filtered_issues |= issues_to_add
  end
  filtered_issues
end

#filter_due_tag(all_tags) ⇒ Array

Returns filtered tags according :due_tag option

Parameters:

  • all_tags (Array)

    all tags

Returns:

  • (Array)

    filtered tags according :due_tag option


98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 98

def filter_due_tag(all_tags)
  filtered_tags = all_tags
  tag = @options[:due_tag]
  if tag
    if (all_tags.count > 0) && (all_tags.map(&:name).include? tag)
      idx = all_tags.index { |t| t.name == tag }
      last_index = all_tags.count - 1
      filtered_tags = if idx > 0 && idx < last_index
                        all_tags[idx + 1..last_index]
                      else
                        []
                      end
    else
      Helper.log.warn "Warning: can't find tag #{tag}, specified with --due-tag option."
    end
  end
  filtered_tags
end

#filter_excluded_tags(all_tags) ⇒ Array

Returns filtered tags according :exclude_tags or :exclude_tags_regex option

Parameters:

  • all_tags (Array)

    all tags

Returns:

  • (Array)

    filtered tags according :exclude_tags or :exclude_tags_regex option


134
135
136
137
138
139
140
141
142
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 134

def filter_excluded_tags(all_tags)
  if @options[:exclude_tags]
    apply_exclude_tags(all_tags)
  elsif @options[:exclude_tags_regex]
    apply_exclude_tags_regex(all_tags)
  else
    all_tags
  end
end

#filter_issues_for_tags(newer_tag, older_tag) ⇒ Array

Apply all filters to issues and pull requests

Returns:

  • (Array)

    filtered issues and pull requests


120
121
122
123
124
125
126
127
128
129
130
131
132
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 120

def filter_issues_for_tags(newer_tag, older_tag)
  filtered_pull_requests = delete_by_time(@pull_requests, :actual_date, older_tag, newer_tag)
  filtered_issues = delete_by_time(@issues, :actual_date, older_tag, newer_tag)

  newer_tag_name = newer_tag.nil? ? nil : newer_tag["name"]

  if @options[:filter_issues_by_milestone]
    # delete excess irrelevant issues (according milestones). Issue #22.
    filtered_issues = filter_by_milestone(filtered_issues, newer_tag_name, @issues)
    filtered_pull_requests = filter_by_milestone(filtered_pull_requests, newer_tag_name, @pull_requests)
  end
  [filtered_issues, filtered_pull_requests]
end

#filter_merged_pull_requests(pull_requests) ⇒ Object

This method filter only merged PR and fetch missing required attributes for pull requests :merged_at - is a date, when issue PR was merged. More correct to use merged date, rather than closed date.


172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 172

def filter_merged_pull_requests(pull_requests)
  print "Fetching merged dates...\r" if @options[:verbose]
  closed_pull_requests = @fetcher.fetch_closed_pull_requests

  pull_requests.each do |pr|
    fetched_pr = closed_pull_requests.find do |fpr|
      fpr.number == pr.number
    end
    if fetched_pr
      pr[:merged_at] = fetched_pr[:merged_at]
      closed_pull_requests.delete(fetched_pr)
    end
  end

  pull_requests.select! do |pr|
    !pr[:merged_at].nil?
  end

  pull_requests
end

#filter_since_tag(all_tags) ⇒ Array

Returns filtered tags according :since_tag option

Parameters:

  • all_tags (Array)

    all tags

Returns:

  • (Array)

    filtered tags according :since_tag option


78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 78

def filter_since_tag(all_tags)
  filtered_tags = all_tags
  tag = detect_since_tag
  if tag
    if all_tags.map(&:name).include? tag
      idx = all_tags.index { |t| t.name == tag }
      filtered_tags = if idx > 0
                        all_tags[0..idx - 1]
                      else
                        []
                      end
    else
      Helper.log.warn "Warning: can't find tag #{tag}, specified with --since-tag option."
    end
  end
  filtered_tags
end

#filter_wo_labels(issues) ⇒ Array

Returns issues without labels or empty array if add_issues_wo_labels is false

Returns:

  • (Array)

    issues without labels or empty array if add_issues_wo_labels is false


122
123
124
125
126
127
128
129
130
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 122

def filter_wo_labels(issues)
  if @options[:add_issues_wo_labels]
    issues_wo_labels = issues.select do |issue|
      !issue.labels.map(&:name).any?
    end
    return issues_wo_labels
  end
  []
end

#find_closed_date_by_commit(issue) ⇒ Object

Fill :actual_date parameter of specified issue by closed date of the commit, if it was closed by commit.

Parameters:

  • issue (Hash)

50
51
52
53
54
55
56
57
58
59
60
61
62
63
# File 'lib/github_changelog_generator/generator/generator_fetcher.rb', line 50

def find_closed_date_by_commit(issue)
  unless issue[:events].nil?
    # if it's PR -> then find "merged event", in case of usual issue -> fond closed date
    compare_string = issue[:merged_at].nil? ? "closed" : "merged"
    # reverse! - to find latest closed event. (event goes in date order)
    issue[:events].reverse!.each do |event|
      if event[:event].eql? compare_string
        set_date_from_event(event, issue)
        break
      end
    end
  end
  # TODO: assert issues, that remain without 'actual_date' hash for some reason.
end

#find_issues_to_add(all_issues, tag_name) ⇒ Array

Add all issues, that should be in that tag, according milestone

Parameters:

  • all_issues (Array)
  • tag_name (String)

Returns:

  • (Array)

    issues with milestone #tag_name


32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 32

def find_issues_to_add(all_issues, tag_name)
  all_issues.select do |issue|
    if issue.milestone.nil?
      false
    else
      # check, that this milestone in tag list:
      milestone_is_tag = @filtered_tags.find do |tag|
        tag.name == issue.milestone.title
      end

      if milestone_is_tag.nil?
        false
      else
        issue.milestone.title == tag_name
      end
    end
  end
end

#generate_for_2_tags(log) ⇒ String

Returns temp method should be removed soon

Returns:

  • (String)

    temp method should be removed soon


28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 28

def generate_for_2_tags(log)
  tag1 = @options[:tag1]
  tag2 = @options[:tag2]
  tags_strings = []
  filtered_tags.each { |x| tags_strings.push(x["name"]) }

  if tags_strings.include?(tag1)
    if tags_strings.include?(tag2)
      to_a = tags_strings.map.with_index.to_a
      hash = Hash[to_a]
      index1 = hash[tag1]
      index2 = hash[tag2]
      log += generate_log_between_tags(all_tags[index1], all_tags[index2])
    else
      raise ChangelogGeneratorError, "Can't find tag #{tag2} -> exit".red
    end
  else
    raise ChangelogGeneratorError, "Can't find tag #{tag1} -> exit".red
  end
  log
end

#generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_link, project_url) ⇒ String

It generate one header for section with specific parameters.

Parameters:

  • newer_tag_name (String)
    • name of newer tag

  • newer_tag_link (String)
    • used for links. Could be same as #newer_tag_name or some specific value, like HEAD

  • newer_tag_time (Time)
    • time, when newer tag created

  • older_tag_link (String)
    • tag name, used for links.

  • project_url (String)
    • url for current project.

Returns:

  • (String)
    • Generate one ready-to-add section.


75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 75

def generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_link, project_url)
  log = ""

  # Generate date string:
  time_string = newer_tag_time.strftime @options[:date_format]

  # Generate tag name and link
  release_url = if @options[:release_url]
                  format(@options[:release_url], newer_tag_link)
                else
                  "#{project_url}/tree/#{newer_tag_link}"
                end
  log += if newer_tag_name.equal? @options[:unreleased_label]
           "## [#{newer_tag_name}](#{release_url})\n\n"
         else
           "## [#{newer_tag_name}](#{release_url}) (#{time_string})\n"
         end

  if @options[:compare_link] && older_tag_link
    # Generate compare link
    log += "[Full Changelog](#{project_url}/compare/#{older_tag_link}...#{newer_tag_link})\n\n"
  end

  log
end

#generate_log_between_tags(older_tag, newer_tag) ⇒ Object

Generate log only between 2 specified tags

Parameters:

  • older_tag (String)

    all issues before this tag date will be excluded. May be nil, if it's first tag

  • newer_tag (String)

    all issue after this tag will be excluded. May be nil for unreleased section


104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 104

def generate_log_between_tags(older_tag, newer_tag)
  filtered_issues, filtered_pull_requests = filter_issues_for_tags(newer_tag, older_tag)

  older_tag_name = older_tag.nil? ? detect_since_tag : older_tag["name"]

  if newer_tag.nil? && filtered_issues.empty? && filtered_pull_requests.empty?
    # do not generate empty unreleased section
    return ""
  end

  create_log_for_tag(filtered_pull_requests, filtered_issues, newer_tag, older_tag_name)
end

#generate_log_for_all_tagsString

The full cycle of generation for whole project

Returns:

  • (String)

    The complete change log


136
137
138
139
140
141
142
143
144
145
146
147
148
149
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 136

def generate_log_for_all_tags
  puts "Generating log..." if @options[:verbose]

  log = generate_unreleased_section

  (1...filtered_tags.size).each do |index|
    log += generate_log_between_tags(filtered_tags[index], filtered_tags[index - 1])
  end
  if @filtered_tags.count != 0
    log += generate_log_between_tags(nil, filtered_tags.last)
  end

  log
end

#generate_sub_section(issues, prefix) ⇒ String

Returns Generate ready-to-go sub-section

Parameters:

  • issues (Array)

    List of issues on sub-section

  • prefix (String)

    Nae of sub-section

Returns:

  • (String)

    Generate ready-to-go sub-section


53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 53

def generate_sub_section(issues, prefix)
  log = ""

  if issues.any?
    log += "#{prefix}\n\n" unless options[:simple_list]
    issues.each do |issue|
      merge_string = get_string_for_issue(issue)
      log += "- #{merge_string}\n"
    end
    log += "\n"
  end
  log
end

#generate_unreleased_sectionObject


151
152
153
154
155
156
157
158
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 151

def generate_unreleased_section
  log = ""
  if @options[:unreleased]
    unreleased_log = generate_log_between_tags(filtered_tags[0], nil)
    log += unreleased_log if unreleased_log
  end
  log
end

#get_filtered_issues(issues) ⇒ Array

Filter issues according labels

Returns:

  • (Array)

    Filtered issues


151
152
153
154
155
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 151

def get_filtered_issues(issues)
  issues = filter_array_by_labels(issues)
  puts "Filtered issues: #{issues.count}" if @options[:verbose]
  issues
end

#get_filtered_pull_requests(pull_requests) ⇒ Array

This method fetches missing params for PR and filter them by specified options It include add all PR's with labels from @options array And exclude all from :exclude_labels array.

Returns:

  • (Array)

    filtered PR's


161
162
163
164
165
166
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 161

def get_filtered_pull_requests(pull_requests)
  pull_requests = filter_array_by_labels(pull_requests)
  pull_requests = filter_merged_pull_requests(pull_requests)
  puts "Filtered pull requests: #{pull_requests.count}" if @options[:verbose]
  pull_requests
end

#get_filtered_tags(all_tags) ⇒ Array

Return tags after filtering tags in lists provided by option: –between-tags & –exclude-tags

Returns:

  • (Array)

70
71
72
73
74
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 70

def get_filtered_tags(all_tags)
  filtered_tags = filter_since_tag(all_tags)
  filtered_tags = filter_between_tags(filtered_tags)
  filter_excluded_tags(filtered_tags)
end

#get_string_for_issue(issue) ⇒ String

Parse issue and generate single line formatted issue line.

Example output:

Parameters:

  • issue (Hash)

    Fetched issue from GitHub

Returns:

  • (String)

    Markdown-formatted single issue


167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
# File 'lib/github_changelog_generator/generator/generator_generation.rb', line 167

def get_string_for_issue(issue)
  encapsulated_title = encapsulate_string issue[:title]

  title_with_number = "#{encapsulated_title} [\\##{issue[:number]}](#{issue.html_url})"

  unless issue.pull_request.nil?
    if @options[:author]
      title_with_number += if issue.user.nil?
                             " ({Null user})"
                           else
                             " ([#{issue.user.login}](#{issue.user.html_url}))"
                           end
    end
  end
  title_with_number
end

#get_time_of_tag(tag_name) ⇒ Time

Try to find tag date in local hash. Otherwise fFetch tag time and put it to local hash file.

Parameters:

  • tag_name (Hash)

    name of the tag

Returns:

  • (Time)

    time of specified tag

Raises:


21
22
23
24
25
26
27
28
29
30
31
32
33
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 21

def get_time_of_tag(tag_name)
  raise ChangelogGeneratorError, "tag_name is nil".red if tag_name.nil?

  name_of_tag = tag_name["name"]
  time_for_name = @tag_times_hash[name_of_tag]
  if !time_for_name.nil?
    time_for_name
  else
    time_string = @fetcher.fetch_date_of_tag tag_name
    @tag_times_hash[name_of_tag] = time_string
    time_string
  end
end

#include_issues_by_labels(issues) ⇒ Array

Include issues with labels, specified in :include_labels

Parameters:

  • issues (Array)

    to filter

Returns:

  • (Array)

    filtered array of issues


115
116
117
118
119
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 115

def include_issues_by_labels(issues)
  filtered_issues = filter_by_include_labels(issues)
  filtered_issues |= filter_wo_labels(issues)
  filtered_issues
end

#issues_to_log(issues, pull_requests) ⇒ String

Generate ready-to-paste log from list of issues and pull requests.

Parameters:

  • issues (Array)
  • pull_requests (Array)

Returns:

  • (String)

    generated log for issues


85
86
87
88
89
90
91
92
93
# File 'lib/github_changelog_generator/generator/generator.rb', line 85

def issues_to_log(issues, pull_requests)
  log = ""
  bugs_a, enhancement_a, issues_a = parse_by_sections(issues, pull_requests)

  log += generate_sub_section(enhancement_a, @options[:enhancement_prefix])
  log += generate_sub_section(bugs_a, @options[:bug_prefix])
  log += generate_sub_section(issues_a, @options[:issue_prefix])
  log
end

#parse_by_sections(issues, pull_requests) ⇒ Array

This method sort issues by types (bugs, features, or just closed issues) by labels

Parameters:

  • issues (Array)
  • pull_requests (Array)

Returns:

  • (Array)

    tuple of filtered arrays: (Bugs, Enhancements Issues)


101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
# File 'lib/github_changelog_generator/generator/generator.rb', line 101

def parse_by_sections(issues, pull_requests)
  issues_a = []
  enhancement_a = []
  bugs_a = []

  issues.each do |dict|
    added = false
    dict.labels.each do |label|
      if @options[:bug_labels].include? label.name
        bugs_a.push dict
        added = true
        next
      end
      if @options[:enhancement_labels].include? label.name
        enhancement_a.push dict
        added = true
        next
      end
    end
    issues_a.push dict unless added
  end

  added_pull_requests = []
  pull_requests.each do |dict|
    dict.labels.each do |label|
      if @options[:bug_labels].include? label.name
        bugs_a.push dict
        added_pull_requests.push dict
        next
      end
      if @options[:enhancement_labels].include? label.name
        enhancement_a.push dict
        added_pull_requests.push dict
        next
      end
    end
  end
  added_pull_requests.each { |p| pull_requests.delete(p) }

  [bugs_a, enhancement_a, issues_a]
end

#remove_issues_in_milestones(filtered_issues) ⇒ Array

Returns array with removed issues, that contain milestones with same name as a tag

Returns:

  • (Array)

    array with removed issues, that contain milestones with same name as a tag


52
53
54
55
56
57
58
59
60
61
62
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 52

def remove_issues_in_milestones(filtered_issues)
  filtered_issues.select! do |issue|
    # leave issues without milestones
    if issue.milestone.nil?
      true
    else
      # check, that this milestone in tag list:
      @filtered_tags.find { |tag| tag.name == issue.milestone.title }.nil?
    end
  end
end

#set_date_from_event(event, issue) ⇒ Object

Set closed date from this issue

Parameters:

  • event (Hash)
  • issue (Hash)

69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'lib/github_changelog_generator/generator/generator_fetcher.rb', line 69

def set_date_from_event(event, issue)
  if event[:commit_id].nil?
    issue[:actual_date] = issue[:closed_at]
  else
    begin
      commit = @fetcher.fetch_commit(event)
      issue[:actual_date] = commit[:author][:date]
    rescue
      puts "Warning: Can't fetch commit #{event[:commit_id]}. It is probably referenced from another repo.".yellow
      issue[:actual_date] = issue[:closed_at]
    end
  end
end

#sort_tags_by_date(tags) ⇒ Object

Sort all tags by date


10
11
12
13
14
15
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 10

def sort_tags_by_date(tags)
  puts "Sorting tags..." if @options[:verbose]
  tags.sort_by! do |x|
    get_time_of_tag(x)
  end.reverse!
end

#tag_newer_old_tag?(older_tag_time, t) ⇒ Boolean

Returns:

  • (Boolean)

103
104
105
106
107
108
109
110
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 103

def tag_newer_old_tag?(older_tag_time, t)
  tag_in_range_old = if older_tag_time.nil?
                       true
                     else
                       t > older_tag_time
                     end
  tag_in_range_old
end

#tag_older_new_tag?(newer_tag_time, time) ⇒ Boolean

Returns:

  • (Boolean)

94
95
96
97
98
99
100
101
# File 'lib/github_changelog_generator/generator/generator_processor.rb', line 94

def tag_older_new_tag?(newer_tag_time, time)
  tag_in_range_new = if newer_tag_time.nil?
                       true
                     else
                       time <= newer_tag_time
                     end
  tag_in_range_new
end

#version_of_first_itemObject


60
61
62
63
64
65
# File 'lib/github_changelog_generator/generator/generator_tags.rb', line 60

def version_of_first_item
  return unless File.file?(@options[:base].to_s)

  sections = GitHubChangelogGenerator::Reader.new.read(@options[:base])
  sections.first["version"] if sections && sections.any?
end