168 lines
5.4 KiB
Ruby
168 lines
5.4 KiB
Ruby
module GitHubChangelogGenerator
|
|
# A Fetcher responsible for all requests to GitHub and all basic manipulation with related data (such as filtering, validating, e.t.c)
|
|
#
|
|
# Example:
|
|
# fetcher = GitHubChangelogGenerator::Fetcher.new options
|
|
class Fetcher
|
|
PER_PAGE_NUMBER = 30
|
|
GH_RATE_LIMIT_EXCEEDED_MSG = "Warning: GitHub API rate limit (5000 per hour) exceeded, change log may be " \
|
|
"missing some issues. You can limit the number of issues fetched using the `--max-issues NUM` argument."
|
|
|
|
def initialize(options = {})
|
|
@options = options
|
|
|
|
@user = @options[:user]
|
|
@project = @options[:project]
|
|
@github_token = fetch_github_token
|
|
|
|
github_options = {per_page: PER_PAGE_NUMBER}
|
|
github_options[:oauth_token] = @github_token unless @github_token.nil?
|
|
github_options[:endpoint] = options[:github_endpoint] unless options[:github_endpoint].nil?
|
|
github_options[:site] = options[:github_endpoint] unless options[:github_site].nil?
|
|
|
|
begin
|
|
@github = Github.new github_options
|
|
rescue
|
|
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
|
|
end
|
|
end
|
|
|
|
# Returns GitHub token. First try to use variable, provided by --token option, otherwise try to fetch it from CHANGELOG_GITHUB_TOKEN env variable.
|
|
#
|
|
# @return [String]
|
|
def fetch_github_token
|
|
env_var = @options[:token] ? @options[:token] : (ENV.fetch "CHANGELOG_GITHUB_TOKEN", nil)
|
|
|
|
unless env_var
|
|
puts "Warning: No token provided (-t option) and variable $CHANGELOG_GITHUB_TOKEN was not found.".yellow
|
|
puts "This script can make only 50 requests to GitHub API per hour without token!".yellow
|
|
end
|
|
|
|
env_var
|
|
end
|
|
|
|
# Fetch all tags from repo
|
|
# @return [Array] array of tags
|
|
def get_all_tags
|
|
if @options[:verbose]
|
|
print "Fetching tags...\r"
|
|
end
|
|
|
|
tags = []
|
|
|
|
begin
|
|
response = @github.repos.tags @options[:user], @options[:project]
|
|
page_i = 0
|
|
count_pages = response.count_pages
|
|
response.each_page do |page|
|
|
page_i += PER_PAGE_NUMBER
|
|
print "Fetching tags... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
|
|
tags.concat(page)
|
|
end
|
|
print " \r"
|
|
|
|
if tags.count == 0
|
|
puts "Warning: Can't find any tags in repo. Make sure, that you push tags to remote repo via 'git push --tags'".yellow
|
|
elsif @options[:verbose]
|
|
puts "Found #{tags.count} tags"
|
|
end
|
|
|
|
rescue
|
|
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
|
|
end
|
|
|
|
tags
|
|
end
|
|
|
|
# Return tags after filtering tags in lists provided by option: --between-tags & --exclude-tags
|
|
#
|
|
# @return [Array]
|
|
def get_filtered_tags
|
|
all_tags = get_all_tags
|
|
filtered_tags = []
|
|
if @options[:between_tags]
|
|
@options[:between_tags].each do |tag|
|
|
unless all_tags.include? tag
|
|
puts "Warning: can't find tag #{tag}, specified with --between-tags option.".yellow
|
|
end
|
|
end
|
|
filtered_tags = all_tags.select { |tag| @options[:between_tags].include? tag }
|
|
end
|
|
filtered_tags
|
|
end
|
|
|
|
# This method fetch all closed issues and separate them to pull requests and pure issues
|
|
# (pull request is kind of issue in term of GitHub)
|
|
# @return [Tuple] with issues and pull requests
|
|
def fetch_issues_and_pull_requests
|
|
if @options[:verbose]
|
|
print "Fetching closed issues...\r"
|
|
end
|
|
issues = []
|
|
|
|
begin
|
|
response = @github.issues.list user: @options[:user], repo: @options[:project], state: "closed", filter: "all", labels: nil
|
|
page_i = 0
|
|
count_pages = response.count_pages
|
|
response.each_page do |page|
|
|
page_i += PER_PAGE_NUMBER
|
|
print "Fetching issues... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
|
|
issues.concat(page)
|
|
break if @options[:max_issues] && issues.length >= @options[:max_issues]
|
|
end
|
|
rescue
|
|
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
|
|
end
|
|
|
|
print " \r"
|
|
|
|
if @options[:verbose]
|
|
puts "Received issues: #{issues.count}"
|
|
end
|
|
|
|
# remove pull request from issues:
|
|
issues.partition { |x|
|
|
x[:pull_request].nil?
|
|
}
|
|
end
|
|
|
|
|
|
# This method fetch missing required attributes for pull requests
|
|
# :merged_at - is a date, when issue PR was merged.
|
|
# More correct to use this date, not closed date.
|
|
def fetch_merged_at_pull_requests
|
|
if @options[:verbose]
|
|
print "Fetching merged dates...\r"
|
|
end
|
|
pull_requests = []
|
|
begin
|
|
response = @github.pull_requests.list @options[:user], @options[:project], state: "closed"
|
|
page_i = 0
|
|
response.each_page do |page|
|
|
page_i += PER_PAGE_NUMBER
|
|
count_pages = response.count_pages
|
|
print "Fetching merged dates... #{page_i}/#{count_pages * PER_PAGE_NUMBER}\r"
|
|
pull_requests.concat(page)
|
|
end
|
|
rescue
|
|
puts GH_RATE_LIMIT_EXCEEDED_MSG.yellow
|
|
end
|
|
|
|
print " \r"
|
|
|
|
@pull_requests.each { |pr|
|
|
fetched_pr = pull_requests.find { |fpr|
|
|
fpr.number == pr.number
|
|
}
|
|
pr[:merged_at] = fetched_pr[:merged_at]
|
|
pull_requests.delete(fetched_pr)
|
|
}
|
|
|
|
if @options[:verbose]
|
|
puts "Fetching merged dates: Done!"
|
|
end
|
|
end
|
|
|
|
end
|
|
end
|