github_changelog_generator 1.13.2 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/lib/github_changelog_generator.rb +6 -1
- data/lib/github_changelog_generator/generator/generator.rb +28 -28
- data/lib/github_changelog_generator/generator/generator_fetcher.rb +23 -20
- data/lib/github_changelog_generator/generator/generator_generation.rb +40 -53
- data/lib/github_changelog_generator/generator/generator_processor.rb +32 -22
- data/lib/github_changelog_generator/generator/generator_tags.rb +77 -46
- data/lib/github_changelog_generator/octo_fetcher.rb +363 -0
- data/lib/github_changelog_generator/options.rb +92 -0
- data/lib/github_changelog_generator/parser.rb +21 -5
- data/lib/github_changelog_generator/parser_file.rb +2 -2
- data/lib/github_changelog_generator/version.rb +1 -1
- data/man/git-generate-changelog.1 +44 -2
- data/man/git-generate-changelog.1.html +290 -0
- data/man/git-generate-changelog.md +29 -1
- data/spec/spec_helper.rb +21 -0
- data/spec/unit/generator/generator_processor_spec.rb +4 -4
- data/spec/unit/generator/generator_tags_spec.rb +43 -40
- data/spec/unit/octo_fetcher_spec.rb +528 -0
- data/spec/unit/options_spec.rb +42 -0
- data/spec/unit/reader_spec.rb +0 -4
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_request_with_proper_key/values.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided.json +1 -0
- data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided/should_raise_Unauthorized_error.json +1 -0
- metadata +97 -12
- data/lib/CHANGELOG.md +0 -58
- data/lib/github_changelog_generator/fetcher.rb +0 -226
- data/spec/unit/fetcher_spec.rb +0 -60
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28ce5bfbf45c423de7b0e00662def73cb31dab48
|
4
|
+
data.tar.gz: 0f0ce064c6c069ce90d0186f308be3bdfce966cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a855f3b32548927042e54979e40e296999636c0a2e7fbfb6c3bb5ab228ae013803a15219361b540eb7aa1bac677e0c85ac340de57a8168e8311e29d054aa5947
|
7
|
+
data.tar.gz: 4c8412f7522e7941ce4255a2b246c975013cf2fe99534fe716d275e28ce5fe668f00586e42a3605806b900673e71c112a0ae756888131d82b0dd5c113daf4b33
|
data/README.md
CHANGED
@@ -228,7 +228,7 @@ If you're seeing this warning, please do the following:
|
|
228
228
|
|
229
229
|
- ***My Ruby version is very old, can I use this?***
|
230
230
|
|
231
|
-
When your Ruby is old, and you don't want to upgrade, and
|
231
|
+
When your Ruby is old, and you don't want to upgrade, and you want to
|
232
232
|
control which libraries you use, you can use Bundler.
|
233
233
|
|
234
234
|
In a Gemfile, perhaps in a non-deployed `:development` group, add this
|
@@ -1,11 +1,16 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
# frozen_string_literal: true
|
3
3
|
|
4
|
-
require "
|
4
|
+
require "octokit"
|
5
|
+
require "faraday-http-cache"
|
6
|
+
require "logger"
|
7
|
+
require "active_support"
|
5
8
|
require "json"
|
9
|
+
require "multi_json"
|
6
10
|
require "benchmark"
|
7
11
|
|
8
12
|
require_relative "github_changelog_generator/helper"
|
13
|
+
require_relative "github_changelog_generator/options"
|
9
14
|
require_relative "github_changelog_generator/parser"
|
10
15
|
require_relative "github_changelog_generator/parser_file"
|
11
16
|
require_relative "github_changelog_generator/generator/generator"
|
@@ -1,5 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
require_relative "../
|
2
|
+
require_relative "../octo_fetcher"
|
3
3
|
require_relative "generator_generation"
|
4
4
|
require_relative "generator_fetcher"
|
5
5
|
require_relative "generator_processor"
|
@@ -11,25 +11,25 @@ module GitHubChangelogGenerator
|
|
11
11
|
end
|
12
12
|
|
13
13
|
class Generator
|
14
|
-
attr_accessor :options, :filtered_tags, :github
|
14
|
+
attr_accessor :options, :filtered_tags, :github, :tag_section_mapping, :sorted_tags
|
15
15
|
|
16
16
|
# A Generator responsible for all logic, related with change log generation from ready-to-parse issues
|
17
17
|
#
|
18
18
|
# Example:
|
19
19
|
# generator = GitHubChangelogGenerator::Generator.new
|
20
20
|
# content = generator.compound_changelog
|
21
|
-
def initialize(options =
|
22
|
-
@options
|
21
|
+
def initialize(options = {})
|
22
|
+
@options = options
|
23
23
|
@tag_times_hash = {}
|
24
|
-
@fetcher
|
24
|
+
@fetcher = GitHubChangelogGenerator::OctoFetcher.new(options)
|
25
25
|
end
|
26
26
|
|
27
27
|
def fetch_issues_and_pr
|
28
28
|
issues, pull_requests = @fetcher.fetch_closed_issues_and_pr
|
29
29
|
|
30
|
-
@pull_requests =
|
30
|
+
@pull_requests = options[:pulls] ? get_filtered_pull_requests(pull_requests) : []
|
31
31
|
|
32
|
-
@issues =
|
32
|
+
@issues = options[:issues] ? get_filtered_issues(issues) : []
|
33
33
|
|
34
34
|
fetch_events_for_issues_and_pr
|
35
35
|
detect_actual_closed_dates(@issues + @pull_requests)
|
@@ -61,18 +61,18 @@ module GitHubChangelogGenerator
|
|
61
61
|
newer_tag_link, newer_tag_name, newer_tag_time = detect_link_tag_time(newer_tag)
|
62
62
|
|
63
63
|
github_site = options[:github_site] || "https://github.com"
|
64
|
-
project_url = "#{github_site}/#{
|
64
|
+
project_url = "#{github_site}/#{options[:user]}/#{options[:project]}"
|
65
65
|
|
66
66
|
log = generate_header(newer_tag_name, newer_tag_link, newer_tag_time, older_tag_name, project_url)
|
67
67
|
|
68
|
-
if
|
68
|
+
if options[:issues]
|
69
69
|
# Generate issues:
|
70
70
|
log += issues_to_log(issues, pull_requests)
|
71
71
|
end
|
72
72
|
|
73
|
-
if
|
73
|
+
if options[:pulls]
|
74
74
|
# Generate pull requests:
|
75
|
-
log += generate_sub_section(pull_requests,
|
75
|
+
log += generate_sub_section(pull_requests, options[:merge_prefix])
|
76
76
|
end
|
77
77
|
|
78
78
|
log
|
@@ -87,9 +87,9 @@ module GitHubChangelogGenerator
|
|
87
87
|
log = ""
|
88
88
|
bugs_a, enhancement_a, issues_a = parse_by_sections(issues, pull_requests)
|
89
89
|
|
90
|
-
log += generate_sub_section(enhancement_a,
|
91
|
-
log += generate_sub_section(bugs_a,
|
92
|
-
log += generate_sub_section(issues_a,
|
90
|
+
log += generate_sub_section(enhancement_a, options[:enhancement_prefix])
|
91
|
+
log += generate_sub_section(bugs_a, options[:bug_prefix])
|
92
|
+
log += generate_sub_section(issues_a, options[:issue_prefix])
|
93
93
|
log
|
94
94
|
end
|
95
95
|
|
@@ -106,32 +106,32 @@ module GitHubChangelogGenerator
|
|
106
106
|
|
107
107
|
issues.each do |dict|
|
108
108
|
added = false
|
109
|
-
dict
|
110
|
-
if
|
111
|
-
bugs_a.push
|
109
|
+
dict["labels"].each do |label|
|
110
|
+
if options[:bug_labels].include?(label["name"])
|
111
|
+
bugs_a.push(dict)
|
112
112
|
added = true
|
113
113
|
next
|
114
114
|
end
|
115
|
-
if
|
116
|
-
enhancement_a.push
|
115
|
+
if options[:enhancement_labels].include?(label["name"])
|
116
|
+
enhancement_a.push(dict)
|
117
117
|
added = true
|
118
118
|
next
|
119
119
|
end
|
120
120
|
end
|
121
|
-
issues_a.push
|
121
|
+
issues_a.push(dict) unless added
|
122
122
|
end
|
123
123
|
|
124
124
|
added_pull_requests = []
|
125
|
-
pull_requests.each do |
|
126
|
-
|
127
|
-
if
|
128
|
-
bugs_a.push
|
129
|
-
added_pull_requests.push
|
125
|
+
pull_requests.each do |pr|
|
126
|
+
pr["labels"].each do |label|
|
127
|
+
if options[:bug_labels].include?(label["name"])
|
128
|
+
bugs_a.push(pr)
|
129
|
+
added_pull_requests.push(pr)
|
130
130
|
next
|
131
131
|
end
|
132
|
-
if
|
133
|
-
enhancement_a.push
|
134
|
-
added_pull_requests.push
|
132
|
+
if options[:enhancement_labels].include?(label["name"])
|
133
|
+
enhancement_a.push(pr)
|
134
|
+
added_pull_requests.push(pr)
|
135
135
|
next
|
136
136
|
end
|
137
137
|
end
|
@@ -1,10 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module GitHubChangelogGenerator
|
3
3
|
class Generator
|
4
|
+
MAX_THREAD_NUMBER = 25
|
5
|
+
|
4
6
|
# Fetch event for issues and pull requests
|
5
7
|
# @return [Array] array of fetched issues
|
6
8
|
def fetch_events_for_issues_and_pr
|
7
|
-
if
|
9
|
+
if options[:verbose]
|
8
10
|
print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r"
|
9
11
|
end
|
10
12
|
|
@@ -13,48 +15,47 @@ module GitHubChangelogGenerator
|
|
13
15
|
end
|
14
16
|
|
15
17
|
# Async fetching of all tags dates
|
16
|
-
def fetch_tags_dates
|
17
|
-
print "Fetching tag dates...\r" if
|
18
|
+
def fetch_tags_dates(tags)
|
19
|
+
print "Fetching tag dates...\r" if options[:verbose]
|
18
20
|
# Async fetching tags:
|
19
21
|
threads = []
|
20
22
|
i = 0
|
21
|
-
all =
|
22
|
-
|
23
|
+
all = tags.count
|
24
|
+
tags.each do |tag|
|
23
25
|
print " \r"
|
24
26
|
threads << Thread.new do
|
25
27
|
get_time_of_tag(tag)
|
26
|
-
print "Fetching tags dates: #{i + 1}/#{all}\r" if
|
28
|
+
print "Fetching tags dates: #{i + 1}/#{all}\r" if options[:verbose]
|
27
29
|
i += 1
|
28
30
|
end
|
29
31
|
end
|
30
32
|
threads.each(&:join)
|
31
|
-
puts "Fetching tags dates: #{i}" if
|
33
|
+
puts "Fetching tags dates: #{i}" if options[:verbose]
|
32
34
|
end
|
33
35
|
|
34
36
|
# Find correct closed dates, if issues was closed by commits
|
35
37
|
def detect_actual_closed_dates(issues)
|
36
|
-
print "Fetching closed dates for issues...\r" if
|
38
|
+
print "Fetching closed dates for issues...\r" if options[:verbose]
|
37
39
|
|
38
|
-
|
39
|
-
issues.each_slice(max_thread_number) do |issues_slice|
|
40
|
+
issues.each_slice(MAX_THREAD_NUMBER) do |issues_slice|
|
40
41
|
threads = []
|
41
42
|
issues_slice.each do |issue|
|
42
43
|
threads << Thread.new { find_closed_date_by_commit(issue) }
|
43
44
|
end
|
44
45
|
threads.each(&:join)
|
45
46
|
end
|
46
|
-
puts "Fetching closed dates for issues: Done!" if
|
47
|
+
puts "Fetching closed dates for issues: Done!" if options[:verbose]
|
47
48
|
end
|
48
49
|
|
49
50
|
# Fill :actual_date parameter of specified issue by closed date of the commit, if it was closed by commit.
|
50
51
|
# @param [Hash] issue
|
51
52
|
def find_closed_date_by_commit(issue)
|
52
|
-
unless issue[
|
53
|
+
unless issue["events"].nil?
|
53
54
|
# if it's PR -> then find "merged event", in case of usual issue -> fond closed date
|
54
|
-
compare_string = issue[
|
55
|
+
compare_string = issue["merged_at"].nil? ? "closed" : "merged"
|
55
56
|
# reverse! - to find latest closed event. (event goes in date order)
|
56
|
-
issue[
|
57
|
-
if event[
|
57
|
+
issue["events"].reverse!.each do |event|
|
58
|
+
if event["event"].eql? compare_string
|
58
59
|
set_date_from_event(event, issue)
|
59
60
|
break
|
60
61
|
end
|
@@ -68,15 +69,17 @@ module GitHubChangelogGenerator
|
|
68
69
|
# @param [Hash] event
|
69
70
|
# @param [Hash] issue
|
70
71
|
def set_date_from_event(event, issue)
|
71
|
-
if event[
|
72
|
-
issue[
|
72
|
+
if event["commit_id"].nil?
|
73
|
+
issue["actual_date"] = issue["closed_at"]
|
73
74
|
else
|
74
75
|
begin
|
75
76
|
commit = @fetcher.fetch_commit(event)
|
76
|
-
issue[
|
77
|
+
issue["actual_date"] = commit["commit"]["author"]["date"]
|
78
|
+
|
79
|
+
# issue['actual_date'] = commit['author']['date']
|
77
80
|
rescue
|
78
|
-
puts "Warning: Can't fetch commit #{event[
|
79
|
-
issue[
|
81
|
+
puts "Warning: Can't fetch commit #{event['commit_id']}. It is probably referenced from another repo."
|
82
|
+
issue["actual_date"] = issue["closed_at"]
|
80
83
|
end
|
81
84
|
end
|
82
85
|
end
|
@@ -6,50 +6,26 @@ module GitHubChangelogGenerator
|
|
6
6
|
# @return [String] Generated change log file
|
7
7
|
def compound_changelog
|
8
8
|
fetch_and_filter_tags
|
9
|
-
sort_tags_by_date(@filtered_tags)
|
10
9
|
fetch_issues_and_pr
|
11
10
|
|
12
11
|
log = ""
|
13
|
-
log +=
|
14
|
-
log += "#{
|
12
|
+
log += options[:frontmatter] if options[:frontmatter]
|
13
|
+
log += "#{options[:header]}\n\n"
|
15
14
|
|
16
|
-
log += if
|
15
|
+
log += if options[:unreleased_only]
|
17
16
|
generate_log_between_tags(filtered_tags[0], nil)
|
18
17
|
else
|
19
18
|
generate_log_for_all_tags
|
20
19
|
end
|
21
20
|
|
22
|
-
log += File.read(
|
21
|
+
log += File.read(options[:base]) if File.file?(options[:base])
|
23
22
|
|
24
23
|
log += "\n\n\\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*"
|
25
24
|
@log = log
|
26
25
|
end
|
27
26
|
|
28
|
-
# @return [String] temp method should be removed soon
|
29
|
-
def generate_for_2_tags(log)
|
30
|
-
tag1 = @options[:tag1]
|
31
|
-
tag2 = @options[:tag2]
|
32
|
-
tags_strings = []
|
33
|
-
filtered_tags.each { |x| tags_strings.push(x["name"]) }
|
34
|
-
|
35
|
-
if tags_strings.include?(tag1)
|
36
|
-
if tags_strings.include?(tag2)
|
37
|
-
to_a = tags_strings.map.with_index.to_a
|
38
|
-
hash = Hash[to_a]
|
39
|
-
index1 = hash[tag1]
|
40
|
-
index2 = hash[tag2]
|
41
|
-
log += generate_log_between_tags(all_tags[index1], all_tags[index2])
|
42
|
-
else
|
43
|
-
raise ChangelogGeneratorError, "Can't find tag #{tag2} -> exit"
|
44
|
-
end
|
45
|
-
else
|
46
|
-
raise ChangelogGeneratorError, "Can't find tag #{tag1} -> exit"
|
47
|
-
end
|
48
|
-
log
|
49
|
-
end
|
50
|
-
|
51
27
|
# @param [Array] issues List of issues on sub-section
|
52
|
-
# @param [String] prefix
|
28
|
+
# @param [String] prefix Name of sub-section
|
53
29
|
# @return [String] Generate ready-to-go sub-section
|
54
30
|
def generate_sub_section(issues, prefix)
|
55
31
|
log = ""
|
@@ -77,21 +53,21 @@ module GitHubChangelogGenerator
|
|
77
53
|
log = ""
|
78
54
|
|
79
55
|
# Generate date string:
|
80
|
-
time_string = newer_tag_time.strftime
|
56
|
+
time_string = newer_tag_time.strftime(options[:date_format])
|
81
57
|
|
82
58
|
# Generate tag name and link
|
83
|
-
release_url = if
|
84
|
-
format(
|
59
|
+
release_url = if options[:release_url]
|
60
|
+
format(options[:release_url], newer_tag_link)
|
85
61
|
else
|
86
62
|
"#{project_url}/tree/#{newer_tag_link}"
|
87
63
|
end
|
88
|
-
log += if newer_tag_name.equal?
|
64
|
+
log += if newer_tag_name.equal?(options[:unreleased_label])
|
89
65
|
"## [#{newer_tag_name}](#{release_url})\n\n"
|
90
66
|
else
|
91
67
|
"## [#{newer_tag_name}](#{release_url}) (#{time_string})\n"
|
92
68
|
end
|
93
69
|
|
94
|
-
if
|
70
|
+
if options[:compare_link] && older_tag_link
|
95
71
|
# Generate compare link
|
96
72
|
log += "[Full Changelog](#{project_url}/compare/#{older_tag_link}...#{newer_tag_link})\n\n"
|
97
73
|
end
|
@@ -119,12 +95,12 @@ module GitHubChangelogGenerator
|
|
119
95
|
#
|
120
96
|
# @return [Array] filtered issues and pull requests
|
121
97
|
def filter_issues_for_tags(newer_tag, older_tag)
|
122
|
-
filtered_pull_requests = delete_by_time(@pull_requests,
|
123
|
-
filtered_issues
|
98
|
+
filtered_pull_requests = delete_by_time(@pull_requests, "actual_date", older_tag, newer_tag)
|
99
|
+
filtered_issues = delete_by_time(@issues, "actual_date", older_tag, newer_tag)
|
124
100
|
|
125
101
|
newer_tag_name = newer_tag.nil? ? nil : newer_tag["name"]
|
126
102
|
|
127
|
-
if
|
103
|
+
if options[:filter_issues_by_milestone]
|
128
104
|
# delete excess irrelevant issues (according milestones). Issue #22.
|
129
105
|
filtered_issues = filter_by_milestone(filtered_issues, newer_tag_name, @issues)
|
130
106
|
filtered_pull_requests = filter_by_milestone(filtered_pull_requests, newer_tag_name, @pull_requests)
|
@@ -135,15 +111,13 @@ module GitHubChangelogGenerator
|
|
135
111
|
# The full cycle of generation for whole project
|
136
112
|
# @return [String] The complete change log
|
137
113
|
def generate_log_for_all_tags
|
138
|
-
puts "Generating log..." if
|
114
|
+
puts "Generating log..." if options[:verbose]
|
139
115
|
|
140
116
|
log = generate_unreleased_section
|
141
117
|
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
if filtered_tags.any?
|
146
|
-
log += generate_log_between_tags(nil, filtered_tags.last)
|
118
|
+
@tag_section_mapping.each_pair do |_tag_section, left_right_tags|
|
119
|
+
older_tag, newer_tag = left_right_tags
|
120
|
+
log += generate_log_between_tags(older_tag, newer_tag)
|
147
121
|
end
|
148
122
|
|
149
123
|
log
|
@@ -151,9 +125,10 @@ module GitHubChangelogGenerator
|
|
151
125
|
|
152
126
|
def generate_unreleased_section
|
153
127
|
log = ""
|
154
|
-
if
|
155
|
-
|
156
|
-
|
128
|
+
if options[:unreleased]
|
129
|
+
start_tag = filtered_tags[0] || sorted_tags.last
|
130
|
+
unreleased_log = generate_log_between_tags(start_tag, nil)
|
131
|
+
log += unreleased_log if unreleased_log
|
157
132
|
end
|
158
133
|
log
|
159
134
|
end
|
@@ -166,24 +141,36 @@ module GitHubChangelogGenerator
|
|
166
141
|
# @param [Hash] issue Fetched issue from GitHub
|
167
142
|
# @return [String] Markdown-formatted single issue
|
168
143
|
def get_string_for_issue(issue)
|
169
|
-
encapsulated_title = encapsulate_string issue[
|
144
|
+
encapsulated_title = encapsulate_string issue["title"]
|
170
145
|
|
171
|
-
title_with_number = "#{encapsulated_title} [\\##{issue[
|
146
|
+
title_with_number = "#{encapsulated_title} [\\##{issue['number']}](#{issue['html_url']})"
|
147
|
+
if options[:issue_line_labels].present?
|
148
|
+
title_with_number = "#{title_with_number}#{line_labels_for(issue)}"
|
149
|
+
end
|
172
150
|
issue_line_with_user(title_with_number, issue)
|
173
151
|
end
|
174
152
|
|
175
153
|
private
|
176
154
|
|
155
|
+
def line_labels_for(issue)
|
156
|
+
labels = if options[:issue_line_labels] == ["ALL"]
|
157
|
+
issue["labels"]
|
158
|
+
else
|
159
|
+
issue["labels"].select { |label| options[:issue_line_labels].include?(label["name"]) }
|
160
|
+
end
|
161
|
+
labels.map { |label| " \[[#{label['name']}](#{label['url'].sub('api.github.com/repos', 'github.com')})\]" }.join("")
|
162
|
+
end
|
163
|
+
|
177
164
|
def issue_line_with_user(line, issue)
|
178
|
-
return line if
|
165
|
+
return line if !options[:author] || issue["pull_request"].nil?
|
179
166
|
|
180
|
-
user = issue
|
167
|
+
user = issue["user"]
|
181
168
|
return "#{line} ({Null user})" unless user
|
182
169
|
|
183
|
-
if
|
184
|
-
"#{line} (@#{user
|
170
|
+
if options[:usernames_as_github_logins]
|
171
|
+
"#{line} (@#{user['login']})"
|
185
172
|
else
|
186
|
-
"#{line} ([#{user
|
173
|
+
"#{line} ([#{user['login']}](#{user['html_url']}))"
|
187
174
|
end
|
188
175
|
end
|
189
176
|
end
|
@@ -1,15 +1,15 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
module GitHubChangelogGenerator
|
3
3
|
class Generator
|
4
|
-
# delete all labels with labels from
|
4
|
+
# delete all labels with labels from options[:exclude_labels] array
|
5
5
|
# @param [Array] issues
|
6
6
|
# @return [Array] filtered array
|
7
7
|
def exclude_issues_by_labels(issues)
|
8
|
-
return issues if
|
8
|
+
return issues if !options[:exclude_labels] || options[:exclude_labels].empty?
|
9
9
|
|
10
10
|
issues.reject do |issue|
|
11
|
-
labels = issue
|
12
|
-
(labels &
|
11
|
+
labels = issue["labels"].map { |l| l["name"] }
|
12
|
+
(labels & options[:exclude_labels]).any?
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
@@ -32,18 +32,18 @@ module GitHubChangelogGenerator
|
|
32
32
|
# @return [Array] issues with milestone #tag_name
|
33
33
|
def find_issues_to_add(all_issues, tag_name)
|
34
34
|
all_issues.select do |issue|
|
35
|
-
if issue
|
35
|
+
if issue["milestone"].nil?
|
36
36
|
false
|
37
37
|
else
|
38
38
|
# check, that this milestone in tag list:
|
39
39
|
milestone_is_tag = @filtered_tags.find do |tag|
|
40
|
-
tag
|
40
|
+
tag["name"] == issue["milestone"]["title"]
|
41
41
|
end
|
42
42
|
|
43
43
|
if milestone_is_tag.nil?
|
44
44
|
false
|
45
45
|
else
|
46
|
-
issue
|
46
|
+
issue["milestone"]["title"] == tag_name
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
@@ -53,11 +53,11 @@ module GitHubChangelogGenerator
|
|
53
53
|
def remove_issues_in_milestones(filtered_issues)
|
54
54
|
filtered_issues.select! do |issue|
|
55
55
|
# leave issues without milestones
|
56
|
-
if issue
|
56
|
+
if issue["milestone"].nil?
|
57
57
|
true
|
58
58
|
else
|
59
59
|
# check, that this milestone in tag list:
|
60
|
-
@filtered_tags.find { |tag| tag
|
60
|
+
@filtered_tags.find { |tag| tag["name"] == issue["milestone"]["title"] }.nil?
|
61
61
|
end
|
62
62
|
end
|
63
63
|
end
|
@@ -68,16 +68,18 @@ module GitHubChangelogGenerator
|
|
68
68
|
# @param [String] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag
|
69
69
|
# @param [String] newer_tag all issue after this tag will be excluded. May be nil for unreleased section
|
70
70
|
# @return [Array] filtered issues
|
71
|
-
def delete_by_time(issues, hash_key =
|
71
|
+
def delete_by_time(issues, hash_key = "actual_date", older_tag = nil, newer_tag = nil)
|
72
72
|
# in case if not tags specified - return unchanged array
|
73
73
|
return issues if older_tag.nil? && newer_tag.nil?
|
74
74
|
|
75
|
+
older_tag = ensure_older_tag(older_tag, newer_tag)
|
76
|
+
|
75
77
|
newer_tag_time = newer_tag && get_time_of_tag(newer_tag)
|
76
78
|
older_tag_time = older_tag && get_time_of_tag(older_tag)
|
77
79
|
|
78
80
|
issues.select do |issue|
|
79
81
|
if issue[hash_key]
|
80
|
-
time = Time.parse(issue[hash_key]).utc
|
82
|
+
time = Time.parse(issue[hash_key].to_s).utc
|
81
83
|
|
82
84
|
tag_in_range_old = tag_newer_old_tag?(older_tag_time, time)
|
83
85
|
|
@@ -92,6 +94,14 @@ module GitHubChangelogGenerator
|
|
92
94
|
end
|
93
95
|
end
|
94
96
|
|
97
|
+
def ensure_older_tag(older_tag, newer_tag)
|
98
|
+
return older_tag if older_tag
|
99
|
+
idx = sorted_tags.index { |t| t["name"] == newer_tag["name"] }
|
100
|
+
# skip if we are already at the oldest element
|
101
|
+
return if idx == sorted_tags.size - 1
|
102
|
+
sorted_tags[idx - 1]
|
103
|
+
end
|
104
|
+
|
95
105
|
def tag_older_new_tag?(newer_tag_time, time)
|
96
106
|
tag_in_range_new = if newer_tag_time.nil?
|
97
107
|
true
|
@@ -121,9 +131,9 @@ module GitHubChangelogGenerator
|
|
121
131
|
|
122
132
|
# @return [Array] issues without labels or empty array if add_issues_wo_labels is false
|
123
133
|
def filter_wo_labels(issues)
|
124
|
-
if
|
134
|
+
if options[:add_issues_wo_labels]
|
125
135
|
issues_wo_labels = issues.select do |issue|
|
126
|
-
!issue
|
136
|
+
!issue["labels"].map { |l| l["name"] }.any?
|
127
137
|
end
|
128
138
|
return issues_wo_labels
|
129
139
|
end
|
@@ -131,11 +141,11 @@ module GitHubChangelogGenerator
|
|
131
141
|
end
|
132
142
|
|
133
143
|
def filter_by_include_labels(issues)
|
134
|
-
if
|
144
|
+
if options[:include_labels].nil?
|
135
145
|
issues
|
136
146
|
else
|
137
147
|
issues.select do |issue|
|
138
|
-
labels = issue
|
148
|
+
labels = issue["labels"].map { |l| l["name"] } & options[:include_labels]
|
139
149
|
labels.any?
|
140
150
|
end
|
141
151
|
end
|
@@ -154,18 +164,18 @@ module GitHubChangelogGenerator
|
|
154
164
|
# @return [Array] Filtered issues
|
155
165
|
def get_filtered_issues(issues)
|
156
166
|
issues = filter_array_by_labels(issues)
|
157
|
-
puts "Filtered issues: #{issues.count}" if
|
167
|
+
puts "Filtered issues: #{issues.count}" if options[:verbose]
|
158
168
|
issues
|
159
169
|
end
|
160
170
|
|
161
171
|
# This method fetches missing params for PR and filter them by specified options
|
162
|
-
# It include add all PR's with labels from
|
172
|
+
# It include add all PR's with labels from options[:include_labels] array
|
163
173
|
# And exclude all from :exclude_labels array.
|
164
174
|
# @return [Array] filtered PR's
|
165
175
|
def get_filtered_pull_requests(pull_requests)
|
166
176
|
pull_requests = filter_array_by_labels(pull_requests)
|
167
177
|
pull_requests = filter_merged_pull_requests(pull_requests)
|
168
|
-
puts "Filtered pull requests: #{pull_requests.count}" if
|
178
|
+
puts "Filtered pull requests: #{pull_requests.count}" if options[:verbose]
|
169
179
|
pull_requests
|
170
180
|
end
|
171
181
|
|
@@ -174,21 +184,21 @@ module GitHubChangelogGenerator
|
|
174
184
|
# :merged_at - is a date, when issue PR was merged.
|
175
185
|
# More correct to use merged date, rather than closed date.
|
176
186
|
def filter_merged_pull_requests(pull_requests)
|
177
|
-
print "Fetching merged dates...\r" if
|
187
|
+
print "Fetching merged dates...\r" if options[:verbose]
|
178
188
|
closed_pull_requests = @fetcher.fetch_closed_pull_requests
|
179
189
|
|
180
190
|
pull_requests.each do |pr|
|
181
191
|
fetched_pr = closed_pull_requests.find do |fpr|
|
182
|
-
fpr
|
192
|
+
fpr["number"] == pr["number"]
|
183
193
|
end
|
184
194
|
if fetched_pr
|
185
|
-
pr[
|
195
|
+
pr["merged_at"] = fetched_pr["merged_at"]
|
186
196
|
closed_pull_requests.delete(fetched_pr)
|
187
197
|
end
|
188
198
|
end
|
189
199
|
|
190
200
|
pull_requests.select! do |pr|
|
191
|
-
!pr[
|
201
|
+
!pr["merged_at"].nil?
|
192
202
|
end
|
193
203
|
|
194
204
|
pull_requests
|