github_changelog_generator 1.15.0.pre.rc → 1.16.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (66) hide show
  1. checksums.yaml +5 -5
  2. data/LICENSE +1 -1
  3. data/README.md +134 -81
  4. data/Rakefile +1 -1
  5. data/bin/git-generate-changelog +1 -1
  6. data/lib/github_changelog_generator.rb +10 -6
  7. data/lib/github_changelog_generator/argv_parser.rb +224 -0
  8. data/lib/github_changelog_generator/generator/entry.rb +218 -0
  9. data/lib/github_changelog_generator/generator/generator.rb +120 -121
  10. data/lib/github_changelog_generator/generator/generator_fetcher.rb +138 -23
  11. data/lib/github_changelog_generator/generator/generator_processor.rb +60 -27
  12. data/lib/github_changelog_generator/generator/generator_tags.rb +25 -21
  13. data/lib/github_changelog_generator/generator/section.rb +124 -0
  14. data/lib/github_changelog_generator/helper.rb +1 -1
  15. data/lib/github_changelog_generator/octo_fetcher.rb +250 -96
  16. data/lib/github_changelog_generator/options.rb +39 -4
  17. data/lib/github_changelog_generator/parser.rb +70 -209
  18. data/lib/github_changelog_generator/parser_file.rb +35 -16
  19. data/lib/github_changelog_generator/reader.rb +2 -2
  20. data/lib/github_changelog_generator/ssl_certs/cacert.pem +851 -1680
  21. data/lib/github_changelog_generator/task.rb +4 -4
  22. data/lib/github_changelog_generator/version.rb +1 -1
  23. data/man/git-generate-changelog.1 +160 -74
  24. data/man/git-generate-changelog.1.html +159 -95
  25. data/man/git-generate-changelog.html +36 -24
  26. data/man/git-generate-changelog.md +156 -93
  27. data/spec/files/config_example +5 -0
  28. data/spec/files/github-changelog-generator.md +114 -114
  29. data/spec/{install-gem-in-bundler.gemfile → install_gem_in_bundler.gemfile} +2 -0
  30. data/spec/spec_helper.rb +2 -6
  31. data/spec/unit/generator/entry_spec.rb +766 -0
  32. data/spec/unit/generator/generator_processor_spec.rb +103 -41
  33. data/spec/unit/generator/generator_spec.rb +47 -0
  34. data/spec/unit/generator/generator_tags_spec.rb +51 -24
  35. data/spec/unit/generator/section_spec.rb +34 -0
  36. data/spec/unit/octo_fetcher_spec.rb +247 -197
  37. data/spec/unit/options_spec.rb +24 -0
  38. data/spec/unit/parse_file_spec.rb +2 -2
  39. data/spec/unit/parser_spec.rb +50 -0
  40. data/spec/unit/reader_spec.rb +4 -4
  41. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits/when_API_is_valid/returns_commits.json +1 -0
  42. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_commits_before/when_API_is_valid/returns_commits.json +1 -1
  43. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid.json +1 -1
  44. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issue_with_proper_key/values.json +1 -1
  45. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues.json +1 -1
  46. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_issues_with_labels.json +1 -1
  47. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_request_with_proper_key/values.json +1 -1
  48. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_issues_and_pr/when_API_call_is_valid/returns_pull_requests_with_labels.json +1 -1
  49. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid.json +1 -1
  50. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_correct_pull_request_keys.json +1 -1
  51. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_closed_pull_requests/when_API_call_is_valid/returns_pull_requests.json +1 -1
  52. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid.json +1 -1
  53. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_commit/when_API_call_is_valid/returns_commit.json +1 -1
  54. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid.json +1 -1
  55. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_date_of_tag/when_API_call_is_valid/returns_date.json +1 -1
  56. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid.json +1 -1
  57. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_fetch_events_async/when_API_call_is_valid/populates_issues.json +1 -1
  58. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid.json +1 -1
  59. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags.json +1 -1
  60. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_API_call_is_valid/should_return_tags_count.json +1 -1
  61. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided.json +1 -1
  62. data/spec/vcr/GitHubChangelogGenerator_OctoFetcher/_github_fetch_tags/when_wrong_token_provided/should_raise_Unauthorized_error.json +1 -1
  63. metadata +56 -20
  64. data/bin/ghclgen +0 -5
  65. data/lib/github_changelog_generator/generator/generator_generation.rb +0 -181
  66. data/spec/unit/generator/generator_generation_spec.rb +0 -73
@@ -2,14 +2,10 @@
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
10
- if options[:verbose]
11
- print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r"
12
- end
8
+ print "Fetching events for issues and PR: 0/#{@issues.count + @pull_requests.count}\r" if options[:verbose]
13
9
 
14
10
  # Async fetching events:
15
11
  @fetcher.fetch_events_async(@issues + @pull_requests)
@@ -18,34 +14,141 @@ module GitHubChangelogGenerator
18
14
  # Async fetching of all tags dates
19
15
  def fetch_tags_dates(tags)
20
16
  print "Fetching tag dates...\r" if options[:verbose]
21
- # Async fetching tags:
22
- threads = []
23
17
  i = 0
24
- all = tags.count
25
18
  tags.each do |tag|
26
- print " \r"
27
- threads << Thread.new do
28
- get_time_of_tag(tag)
29
- print "Fetching tags dates: #{i + 1}/#{all}\r" if options[:verbose]
30
- i += 1
31
- end
19
+ get_time_of_tag(tag)
20
+ i += 1
32
21
  end
33
- threads.each(&:join)
34
- puts "Fetching tags dates: #{i}" if options[:verbose]
22
+ puts "Fetching tags dates: #{i}/#{tags.count}" if options[:verbose]
35
23
  end
36
24
 
37
25
  # Find correct closed dates, if issues was closed by commits
38
26
  def detect_actual_closed_dates(issues)
39
27
  print "Fetching closed dates for issues...\r" if options[:verbose]
40
28
 
41
- issues.each_slice(MAX_THREAD_NUMBER) do |issues_slice|
42
- threads = []
43
- issues_slice.each do |issue|
44
- threads << Thread.new { find_closed_date_by_commit(issue) }
29
+ i = 0
30
+ issues.each do |issue|
31
+ find_closed_date_by_commit(issue)
32
+ i += 1
33
+ end
34
+ puts "Fetching closed dates for issues: #{i}/#{issues.count}" if options[:verbose]
35
+ end
36
+
37
+ # Adds a key "first_occurring_tag" to each PR with a value of the oldest
38
+ # tag that a PR's merge commit occurs in in the git history. This should
39
+ # indicate the release of each PR by git's history regardless of dates and
40
+ # divergent branches.
41
+ #
42
+ # @param [Array] tags The tags sorted by time, newest to oldest.
43
+ # @param [Array] prs The PRs to discover the tags of.
44
+ # @return [Nil] No return; PRs are updated in-place.
45
+ def add_first_occurring_tag_to_prs(tags, prs)
46
+ total = prs.count
47
+
48
+ prs_left = associate_tagged_prs(tags, prs, total)
49
+ prs_left = associate_release_branch_prs(prs_left, total)
50
+ prs_left = associate_rebase_comment_prs(tags, prs_left, total) if prs_left.any?
51
+ # PRs in prs_left will be untagged, not in release branch, and not
52
+ # rebased. They should not be included in the changelog as they probably
53
+ # have been merged to a branch other than the release branch.
54
+ @pull_requests -= prs_left
55
+ Helper.log.info "Associating PRs with tags: #{total}/#{total}"
56
+ end
57
+
58
+ # Associate merged PRs by the merge SHA contained in each tag. If the
59
+ # merge_commit_sha is not found in any tag's history, skip association.
60
+ #
61
+ # @param [Array] tags The tags sorted by time, newest to oldest.
62
+ # @param [Array] prs The PRs to associate.
63
+ # @return [Array] PRs without their merge_commit_sha in a tag.
64
+ def associate_tagged_prs(tags, prs, total)
65
+ @fetcher.fetch_tag_shas(tags)
66
+
67
+ i = 0
68
+ prs.reject do |pr|
69
+ found = false
70
+ # XXX Wish I could use merge_commit_sha, but gcg doesn't currently
71
+ # fetch that. See
72
+ # https://developer.github.com/v3/pulls/#get-a-single-pull-request vs.
73
+ # https://developer.github.com/v3/pulls/#list-pull-requests
74
+ if pr["events"] && (event = pr["events"].find { |e| e["event"] == "merged" })
75
+ # Iterate tags.reverse (oldest to newest) to find first tag of each PR.
76
+ if (oldest_tag = tags.reverse.find { |tag| tag["shas_in_tag"].include?(event["commit_id"]) })
77
+ pr["first_occurring_tag"] = oldest_tag["name"]
78
+ found = true
79
+ i += 1
80
+ print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
81
+ end
82
+ else
83
+ # Either there were no events or no merged event. Github's api can be
84
+ # weird like that apparently. Check for a rebased comment before erroring.
85
+ no_events_pr = associate_rebase_comment_prs(tags, [pr], total)
86
+ raise StandardError, "No merge sha found for PR #{pr['number']} via the GitHub API" unless no_events_pr.empty?
87
+
88
+ found = true
89
+ i += 1
90
+ print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
45
91
  end
46
- threads.each(&:join)
92
+ found
93
+ end
94
+ end
95
+
96
+ # Associate merged PRs by the HEAD of the release branch. If no
97
+ # --release-branch was specified, then the github default branch is used.
98
+ #
99
+ # @param [Array] prs_left PRs not associated with any tag.
100
+ # @param [Integer] total The total number of PRs to associate; used for verbose printing.
101
+ # @return [Array] PRs without their merge_commit_sha in the branch.
102
+ def associate_release_branch_prs(prs_left, total)
103
+ if prs_left.any?
104
+ i = total - prs_left.count
105
+ prs_left.reject do |pr|
106
+ found = false
107
+ if pr["events"] && (event = pr["events"].find { |e| e["event"] == "merged" }) && sha_in_release_branch?(event["commit_id"])
108
+ found = true
109
+ i += 1
110
+ print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
111
+ end
112
+ found
113
+ end
114
+ else
115
+ prs_left
116
+ end
117
+ end
118
+
119
+ # Associate merged PRs by the SHA detected in github comments of the form
120
+ # "rebased commit: <sha>". For use when the merge_commit_sha is not in the
121
+ # actual git history due to rebase.
122
+ #
123
+ # @param [Array] tags The tags sorted by time, newest to oldest.
124
+ # @param [Array] prs_left The PRs not yet associated with any tag or branch.
125
+ # @return [Array] PRs without rebase comments.
126
+ def associate_rebase_comment_prs(tags, prs_left, total)
127
+ i = total - prs_left.count
128
+ # Any remaining PRs were not found in the list of tags by their merge
129
+ # commit and not found in any specified release branch. Fallback to
130
+ # rebased commit comment.
131
+ @fetcher.fetch_comments_async(prs_left)
132
+ prs_left.reject do |pr|
133
+ found = false
134
+ if pr["comments"] && (rebased_comment = pr["comments"].reverse.find { |c| c["body"].match(%r{rebased commit: ([0-9a-f]{40})}i) })
135
+ rebased_sha = rebased_comment["body"].match(%r{rebased commit: ([0-9a-f]{40})}i)[1]
136
+ if (oldest_tag = tags.reverse.find { |tag| tag["shas_in_tag"].include?(rebased_sha) })
137
+ pr["first_occurring_tag"] = oldest_tag["name"]
138
+ found = true
139
+ i += 1
140
+ elsif sha_in_release_branch?(rebased_sha)
141
+ found = true
142
+ i += 1
143
+ else
144
+ raise StandardError, "PR #{pr['number']} has a rebased SHA comment but that SHA was not found in the release branch or any tags"
145
+ end
146
+ print("Associating PRs with tags: #{i}/#{total}\r") if @options[:verbose]
147
+ else
148
+ puts "Warning: PR #{pr['number']} merge commit was not found in the release branch or tagged git history and no rebased SHA comment was found"
149
+ end
150
+ found
47
151
  end
48
- puts "Fetching closed dates for issues: Done!" if options[:verbose]
49
152
  end
50
153
 
51
154
  # Fill :actual_date parameter of specified issue by closed date of the commit, if it was closed by commit.
@@ -74,7 +177,7 @@ module GitHubChangelogGenerator
74
177
  issue["actual_date"] = issue["closed_at"]
75
178
  else
76
179
  begin
77
- commit = @fetcher.fetch_commit(event)
180
+ commit = @fetcher.fetch_commit(event["commit_id"])
78
181
  issue["actual_date"] = commit["commit"]["author"]["date"]
79
182
 
80
183
  # issue['actual_date'] = commit['author']['date']
@@ -84,5 +187,17 @@ module GitHubChangelogGenerator
84
187
  end
85
188
  end
86
189
  end
190
+
191
+ private
192
+
193
+ # Detect if a sha occurs in the --release-branch. Uses the github repo
194
+ # default branch if not specified.
195
+ #
196
+ # @param [String] sha SHA to check.
197
+ # @return [Boolean] True if SHA is in the branch git history.
198
+ def sha_in_release_branch?(sha)
199
+ branch = @options[:release_branch] || @fetcher.default_branch
200
+ @fetcher.commits_in_branch(branch).include?(sha)
201
+ end
87
202
  end
88
203
  end
@@ -2,7 +2,7 @@
2
2
 
3
3
  module GitHubChangelogGenerator
4
4
  class Generator
5
- # delete all labels with labels from options[:exclude_labels] array
5
+ # delete all issues with labels from options[:exclude_labels] array
6
6
  # @param [Array] issues
7
7
  # @return [Array] filtered array
8
8
  def exclude_issues_by_labels(issues)
@@ -14,6 +14,19 @@ module GitHubChangelogGenerator
14
14
  end
15
15
  end
16
16
 
17
+ # Only include issues without labels if options[:add_issues_wo_labels]
18
+ # @param [Array] issues
19
+ # @return [Array] filtered array
20
+ def exclude_issues_without_labels(issues)
21
+ return issues if issues.empty?
22
+ return issues if issues.first.key?("pull_request") && options[:add_pr_wo_labels]
23
+ return issues if !issues.first.key?("pull_request") && options[:add_issues_wo_labels]
24
+
25
+ issues.reject do |issue|
26
+ issue["labels"].empty?
27
+ end
28
+ end
29
+
17
30
  # @return [Array] filtered issues accourding milestone
18
31
  def filter_by_milestone(filtered_issues, tag_name, all_issues)
19
32
  remove_issues_in_milestones(filtered_issues)
@@ -56,6 +69,9 @@ module GitHubChangelogGenerator
56
69
  # leave issues without milestones
57
70
  if issue["milestone"].nil?
58
71
  true
72
+ # remove issues of open milestones if option is set
73
+ elsif issue["milestone"]["state"] == "open"
74
+ @options[:issues_of_open_milestones]
59
75
  else
60
76
  # check, that this milestone in tag list:
61
77
  @filtered_tags.find { |tag| tag["name"] == issue["milestone"]["title"] }.nil?
@@ -63,11 +79,22 @@ module GitHubChangelogGenerator
63
79
  end
64
80
  end
65
81
 
82
+ # Method filter issues, that belong only specified tag range
83
+ #
84
+ # @param [Array] issues issues to filter
85
+ # @param [Hash, Nil] newer_tag Tag to find PRs of. May be nil for unreleased section
86
+ # @return [Array] filtered issues
87
+ def filter_by_tag(issues, newer_tag = nil)
88
+ issues.select do |issue|
89
+ issue["first_occurring_tag"] == (newer_tag.nil? ? nil : newer_tag["name"])
90
+ end
91
+ end
92
+
66
93
  # Method filter issues, that belong only specified tag range
67
94
  # @param [Array] issues issues to filter
68
95
  # @param [Symbol] hash_key key of date value default is :actual_date
69
- # @param [String] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag
70
- # @param [String] newer_tag all issue after this tag will be excluded. May be nil for unreleased section
96
+ # @param [Hash, Nil] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag
97
+ # @param [Hash, Nil] newer_tag all issue after this tag will be excluded. May be nil for unreleased section
71
98
  # @return [Array] filtered issues
72
99
  def delete_by_time(issues, hash_key = "actual_date", older_tag = nil, newer_tag = nil)
73
100
  # in case if not tags specified - return unchanged array
@@ -97,28 +124,28 @@ module GitHubChangelogGenerator
97
124
 
98
125
  def ensure_older_tag(older_tag, newer_tag)
99
126
  return older_tag if older_tag
127
+
100
128
  idx = sorted_tags.index { |t| t["name"] == newer_tag["name"] }
101
129
  # skip if we are already at the oldest element
102
130
  return if idx == sorted_tags.size - 1
131
+
103
132
  sorted_tags[idx - 1]
104
133
  end
105
134
 
106
135
  def tag_older_new_tag?(newer_tag_time, time)
107
- tag_in_range_new = if newer_tag_time.nil?
108
- true
109
- else
110
- time <= newer_tag_time
111
- end
112
- tag_in_range_new
136
+ if newer_tag_time.nil?
137
+ true
138
+ else
139
+ time <= newer_tag_time
140
+ end
113
141
  end
114
142
 
115
- def tag_newer_old_tag?(older_tag_time, t)
116
- tag_in_range_old = if older_tag_time.nil?
117
- true
118
- else
119
- t > older_tag_time
120
- end
121
- tag_in_range_old
143
+ def tag_newer_old_tag?(older_tag_time, time)
144
+ if older_tag_time.nil?
145
+ true
146
+ else
147
+ time > older_tag_time
148
+ end
122
149
  end
123
150
 
124
151
  # Include issues with labels, specified in :include_labels
@@ -126,37 +153,43 @@ module GitHubChangelogGenerator
126
153
  # @return [Array] filtered array of issues
127
154
  def include_issues_by_labels(issues)
128
155
  filtered_issues = filter_by_include_labels(issues)
129
- filtered_issues = filter_wo_labels(filtered_issues)
130
- filtered_issues
156
+ filter_wo_labels(filtered_issues)
131
157
  end
132
158
 
133
- # @return [Array] issues without labels or empty array if add_issues_wo_labels is false
134
- def filter_wo_labels(issues)
135
- if options[:add_issues_wo_labels]
136
- issues
137
- else
138
- issues.select { |issue| issue["labels"].map { |l| l["name"] }.any? }
159
+ # @param [Array] items Issues & PRs to filter when without labels
160
+ # @return [Array] Issues & PRs without labels or empty array if
161
+ # add_issues_wo_labels or add_pr_wo_labels are false
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
139
167
  end
168
+ # The default is to filter items without labels
169
+ items.select { |item| item["labels"].map { |l| l["name"] }.any? }
140
170
  end
141
171
 
172
+ # @todo Document this
173
+ # @param [Object] issues
142
174
  def filter_by_include_labels(issues)
143
175
  if options[:include_labels].nil?
144
176
  issues
145
177
  else
146
178
  issues.select do |issue|
147
179
  labels = issue["labels"].map { |l| l["name"] } & options[:include_labels]
148
- labels.any?
180
+ labels.any? || issue["labels"].empty?
149
181
  end
150
182
  end
151
183
  end
152
184
 
153
185
  # General filtered function
154
186
  #
155
- # @param [Array] all_issues
187
+ # @param [Array] all_issues PRs or issues
156
188
  # @return [Array] filtered issues
157
189
  def filter_array_by_labels(all_issues)
158
190
  filtered_issues = include_issues_by_labels(all_issues)
159
- exclude_issues_by_labels(filtered_issues)
191
+ filtered_issues = exclude_issues_by_labels(filtered_issues)
192
+ exclude_issues_without_labels(filtered_issues)
160
193
  end
161
194
 
162
195
  # Filter issues according labels
@@ -4,22 +4,17 @@ module GitHubChangelogGenerator
4
4
  class Generator
5
5
  # fetch, filter tags, fetch dates and sort them in time order
6
6
  def fetch_and_filter_tags
7
- detect_since_tag
8
- detect_due_tag
7
+ since_tag
8
+ due_tag
9
9
 
10
10
  all_tags = @fetcher.get_all_tags
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 = filter_excluded_tags(all_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
@@ -35,7 +30,7 @@ module GitHubChangelogGenerator
35
30
  tag = section_tags[i]
36
31
 
37
32
  # Don't create section header for the "since" tag
38
- next if @since_tag && tag["name"] == @since_tag
33
+ next if since_tag && tag["name"] == since_tag
39
34
 
40
35
  # Don't create a section header for the first tag in between_tags
41
36
  next if options[:between_tags] && tag == section_tags.last
@@ -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]
@@ -98,11 +93,11 @@ module GitHubChangelogGenerator
98
93
  end
99
94
 
100
95
  # @return [Object] try to find newest tag using #Reader and :base option if specified otherwise returns nil
101
- def detect_since_tag
96
+ def since_tag
102
97
  @since_tag ||= options.fetch(:since_tag) { version_of_first_item }
103
98
  end
104
99
 
105
- def detect_due_tag
100
+ def due_tag
106
101
  @due_tag ||= options.fetch(:due_tag, nil)
107
102
  end
108
103
 
@@ -125,7 +120,7 @@ module GitHubChangelogGenerator
125
120
  # @return [Array] filtered tags according :since_tag option
126
121
  def filter_since_tag(all_tags)
127
122
  filtered_tags = all_tags
128
- tag = detect_since_tag
123
+ tag = since_tag
129
124
  if tag
130
125
  if all_tags.map { |t| t["name"] }.include? tag
131
126
  idx = all_tags.index { |t| t["name"] == tag }
@@ -135,7 +130,7 @@ module GitHubChangelogGenerator
135
130
  []
136
131
  end
137
132
  else
138
- Helper.log.warn "Warning: can't find tag #{tag}, specified with --since-tag option."
133
+ raise ChangelogGeneratorError, "Error: can't find tag #{tag}, specified with --since-tag option."
139
134
  end
140
135
  end
141
136
  filtered_tags
@@ -145,7 +140,7 @@ module GitHubChangelogGenerator
145
140
  # @return [Array] filtered tags according :due_tag option
146
141
  def filter_due_tag(all_tags)
147
142
  filtered_tags = all_tags
148
- tag = detect_due_tag
143
+ tag = due_tag
149
144
  if tag
150
145
  if all_tags.any? && all_tags.map { |t| t["name"] }.include?(tag)
151
146
  idx = all_tags.index { |t| t["name"] == tag }
@@ -155,12 +150,23 @@ module GitHubChangelogGenerator
155
150
  []
156
151
  end
157
152
  else
158
- Helper.log.warn "Warning: can't find tag #{tag}, specified with --due-tag option."
153
+ raise ChangelogGeneratorError, "Error: can't find tag #{tag}, specified with --due-tag option."
159
154
  end
160
155
  end
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)
@@ -208,9 +214,7 @@ module GitHubChangelogGenerator
208
214
  end
209
215
 
210
216
  def warn_if_tag_not_found(all_tags, tag)
211
- unless all_tags.map { |t| t["name"] }.include?(tag)
212
- Helper.log.warn "Warning: can't find tag #{tag}, specified with --exclude-tags option."
213
- end
217
+ Helper.log.warn("Warning: can't find tag #{tag}, specified with --exclude-tags option.") unless all_tags.map { |t| t["name"] }.include?(tag)
214
218
  end
215
219
  end
216
220
  end