diff --git a/Gemfile b/Gemfile index 92c4aea..7149f8b 100644 --- a/Gemfile +++ b/Gemfile @@ -16,6 +16,7 @@ end group :test do gem "vcr" + gem "multi_json" gem "webmock" gem "coveralls", "~>0.8", require: false gem "simplecov", "~>0.10", require: false diff --git a/lib/github_changelog_generator.rb b/lib/github_changelog_generator.rb index c6a47a8..7b4637e 100755 --- a/lib/github_changelog_generator.rb +++ b/lib/github_changelog_generator.rb @@ -1,7 +1,6 @@ #!/usr/bin/env ruby # frozen_string_literal: true -require "github_api" require "octokit" require 'faraday-http-cache' require "logger" diff --git a/lib/github_changelog_generator/array.rb b/lib/github_changelog_generator/array.rb index 83fcfcd..752e2df 100644 --- a/lib/github_changelog_generator/array.rb +++ b/lib/github_changelog_generator/array.rb @@ -1,13 +1,13 @@ class Array def stringify_keys_deep! new_ar = [] - self.each do |value| + each do |value| new_value = value - if value.is_a? Hash or value.is_a? Array + if value.is_a?(Hash) || value.is_a?(Array) new_value = value.stringify_keys_deep! end new_ar << new_value end new_ar end -end \ No newline at end of file +end diff --git a/lib/github_changelog_generator/fetcher.rb b/lib/github_changelog_generator/fetcher.rb deleted file mode 100644 index 1f425dc..0000000 --- a/lib/github_changelog_generator/fetcher.rb +++ /dev/null @@ -1,226 +0,0 @@ -# frozen_string_literal: true -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 - MAX_SIMULTANEOUS_REQUESTS = 25 - CHANGELOG_GITHUB_TOKEN = "CHANGELOG_GITHUB_TOKEN" - GH_RATE_LIMIT_EXCEEDED_MSG = "Warning: Can't finish operation: GitHub API rate limit exceeded, change log may be " \ - "missing some issues. You can limit the number of issues fetched using the `--max-issues NUM` argument." - NO_TOKEN_PROVIDED = "Warning: No token provided (-t option) and variable $CHANGELOG_GITHUB_TOKEN was not found. " \ - "This script can make only 50 requests to GitHub API per hour without token!" - - 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? - - @github = check_github_response { Github.new @github_options } - 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) - - Helper.log.warn NO_TOKEN_PROVIDED unless env_var - - env_var - end - - # Fetch all tags from repo - # @return [Array] array of tags - def get_all_tags - print "Fetching tags...\r" if @options[:verbose] - - check_github_response { github_fetch_tags } - end - - # This is wrapper with rescue block - # @return [Object] returns exactly the same, what you put in the block, but wrap it with begin-rescue block - def check_github_response - begin - value = yield - rescue Github::Error::Unauthorized => e - Helper.log.error e.response_message - abort "Error: wrong GitHub token" - rescue Github::Error::Forbidden => e - Helper.log.warn e.response_message - Helper.log.warn GH_RATE_LIMIT_EXCEEDED_MSG - end - value - end - - # Fill input array with tags - # @return [Array] array of tags in repo - def github_fetch_tags - tags = [] - 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_in_same_line("Fetching tags... #{page_i}/#{count_pages * PER_PAGE_NUMBER}") - tags.concat(page) unless page.nil? - end - print_empty_line - - if tags.empty? - Helper.log.warn "Warning: Can't find any tags in repo.\ -Make sure, that you push tags to remote repo via 'git push --tags'" - else - Helper.log.info "Found #{tags.count} tags" - end - 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, pull-requests) - def fetch_closed_issues_and_pr - print "Fetching closed issues...\r" if @options[:verbose] - 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_in_same_line("Fetching issues... #{page_i}/#{count_pages * PER_PAGE_NUMBER}") - issues.concat(page) - break if @options[:max_issues] && issues.length >= @options[:max_issues] - end - print_empty_line - Helper.log.info "Received issues: #{issues.count}" - - rescue Github::Error::Forbidden => e - Helper.log.warn e.error_messages.map { |m| m[:message] }.join(", ") - Helper.log.warn GH_RATE_LIMIT_EXCEEDED_MSG - end - - # separate arrays of issues and pull requests: - issues.partition do |x| - x[:pull_request].nil? - end - end - - # Fetch all pull requests. We need them to detect :merged_at parameter - # @return [Array] all pull requests - def fetch_closed_pull_requests - pull_requests = [] - begin - response = if @options[:release_branch].nil? - @github.pull_requests.list @options[:user], - @options[:project], - state: "closed" - else - @github.pull_requests.list @options[:user], - @options[:project], - state: "closed", - base: @options[:release_branch] - end - page_i = 0 - count_pages = response.count_pages - response.each_page do |page| - page_i += PER_PAGE_NUMBER - log_string = "Fetching merged dates... #{page_i}/#{count_pages * PER_PAGE_NUMBER}" - print_in_same_line(log_string) - pull_requests.concat(page) - end - print_empty_line - rescue Github::Error::Forbidden => e - Helper.log.warn e.error_messages.map { |m| m[:message] }.join(", ") - Helper.log.warn GH_RATE_LIMIT_EXCEEDED_MSG - end - - Helper.log.info "Fetching merged dates: #{pull_requests.count}" - pull_requests - end - - # Print specified line on the same string - # @param [String] log_string - def print_in_same_line(log_string) - print log_string + "\r" - end - - # Print long line with spaces on same line to clear prev message - def print_empty_line - print_in_same_line(" ") - end - - # Fetch event for all issues and add them to events - # @param [Array] issues - # @return [Void] - def fetch_events_async(issues) - i = 0 - threads = [] - issues.each_slice(MAX_SIMULTANEOUS_REQUESTS) do |issues_slice| - issues_slice.each do |issue| - threads << Thread.new do - begin - response = @github.issues.events.list user: @options[:user], - repo: @options[:project], - issue_number: issue["number"] - issue['events'] = [] - response.each_page do |page| - issue['events'].concat(page) - end - rescue Github::Error::Forbidden => e - Helper.log.warn e.error_messages.map { |m| m[:message] }.join(", ") - Helper.log.warn GH_RATE_LIMIT_EXCEEDED_MSG - end - print_in_same_line("Fetching events for issues and PR: #{i + 1}/#{issues.count}") - i += 1 - end - end - threads.each(&:join) - threads = [] - end - - # to clear line from prev print - print_empty_line - - Helper.log.info "Fetching events for issues and PR: #{i}" - end - - # Fetch tag time from repo - # - # @param [Hash] tag - # @return [Time] time of specified tag - def fetch_date_of_tag(tag) - begin - commit_data = @github.git_data.commits.get @options[:user], - @options[:project], - tag["commit"]["sha"] - rescue Github::Error::Forbidden => e - Helper.log.warn e.error_messages.map { |m| m[:message] }.join(", ") - Helper.log.warn GH_RATE_LIMIT_EXCEEDED_MSG - end - time_string = commit_data["committer"]["date"] - Time.parse(time_string) - end - - # Fetch commit for specified event - # @return [Hash] - def fetch_commit(event) - @github.git_data.commits.get @options[:user], @options[:project], event['commit_id'] - end - end -end diff --git a/lib/github_changelog_generator/generator/generator.rb b/lib/github_changelog_generator/generator/generator.rb index 49a3a5b..8f25617 100644 --- a/lib/github_changelog_generator/generator/generator.rb +++ b/lib/github_changelog_generator/generator/generator.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require_relative "../fetcher" require_relative "../octo_fetcher" require_relative "generator_generation" require_relative "generator_fetcher" @@ -107,13 +106,13 @@ module GitHubChangelogGenerator issues.each do |dict| added = false - dict['labels'].each do |label| - if @options[:bug_labels].include? label['name'] + 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'] + if @options[:enhancement_labels].include? label["name"] enhancement_a.push dict added = true next @@ -124,13 +123,13 @@ module GitHubChangelogGenerator added_pull_requests = [] pull_requests.each do |pr| - pr['labels'].each do |label| - if @options[:bug_labels].include? label['name'] + pr["labels"].each do |label| + if @options[:bug_labels].include? label["name"] bugs_a.push pr added_pull_requests.push pr next end - if @options[:enhancement_labels].include? label['name'] + if @options[:enhancement_labels].include? label["name"] enhancement_a.push pr added_pull_requests.push pr next diff --git a/lib/github_changelog_generator/generator/generator_fetcher.rb b/lib/github_changelog_generator/generator/generator_fetcher.rb index bf3dc3a..51d6859 100644 --- a/lib/github_changelog_generator/generator/generator_fetcher.rb +++ b/lib/github_changelog_generator/generator/generator_fetcher.rb @@ -50,12 +50,12 @@ module GitHubChangelogGenerator # Fill :actual_date parameter of specified issue by closed date of the commit, if it was closed by commit. # @param [Hash] issue def find_closed_date_by_commit(issue) - unless issue['events'].nil? + 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" + 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 + issue["events"].reverse!.each do |event| + if event["event"].eql? compare_string set_date_from_event(event, issue) break end @@ -69,16 +69,17 @@ module GitHubChangelogGenerator # @param [Hash] event # @param [Hash] issue def set_date_from_event(event, issue) - if event['commit_id'].nil? - issue['actual_date'] = issue['closed_at'] + if event["commit_id"].nil? + issue["actual_date"] = issue["closed_at"] else begin commit = @fetcher.fetch_commit(event) - issue['actual_date'] = commit['commit']['author']['date'] + issue["actual_date"] = commit["commit"]["author"]["date"] + # issue['actual_date'] = commit['author']['date'] rescue puts "Warning: Can't fetch commit #{event['commit_id']}. It is probably referenced from another repo." - issue['actual_date'] = issue['closed_at'] + issue["actual_date"] = issue["closed_at"] end end end diff --git a/lib/github_changelog_generator/generator/generator_generation.rb b/lib/github_changelog_generator/generator/generator_generation.rb index a139a55..5e78e45 100644 --- a/lib/github_changelog_generator/generator/generator_generation.rb +++ b/lib/github_changelog_generator/generator/generator_generation.rb @@ -119,9 +119,8 @@ module GitHubChangelogGenerator # # @return [Array] filtered issues and pull requests 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) + 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"] @@ -167,7 +166,7 @@ module GitHubChangelogGenerator # @param [Hash] issue Fetched issue from GitHub # @return [String] Markdown-formatted single issue def get_string_for_issue(issue) - encapsulated_title = encapsulate_string issue['title'] + encapsulated_title = encapsulate_string issue["title"] title_with_number = "#{encapsulated_title} [\\##{issue['number']}](#{issue['html_url']})" issue_line_with_user(title_with_number, issue) @@ -178,13 +177,13 @@ module GitHubChangelogGenerator def issue_line_with_user(line, issue) return line if !@options[:author] || issue.pull_request.nil? - user = issue['user'] + user = issue["user"] return "#{line} ({Null user})" unless user if @options[:usernames_as_github_logins] - "#{line} (@#{user['login']})" + "#{line} (@#{user["login"]})" else - "#{line} ([#{user['login']}](#{user['html_url']}))" + "#{line} ([#{user["login"]}](#{user["html_url"]}))" end end end diff --git a/lib/github_changelog_generator/generator/generator_processor.rb b/lib/github_changelog_generator/generator/generator_processor.rb index 61c4a4f..e863f82 100644 --- a/lib/github_changelog_generator/generator/generator_processor.rb +++ b/lib/github_changelog_generator/generator/generator_processor.rb @@ -8,7 +8,7 @@ module GitHubChangelogGenerator return issues if !@options[:exclude_labels] || @options[:exclude_labels].empty? issues.reject do |issue| - labels = issue['labels'].map{|l| l['name'] } + labels = issue["labels"].map { |l| l["name"] } (labels & @options[:exclude_labels]).any? end end @@ -32,18 +32,18 @@ module GitHubChangelogGenerator # @return [Array] issues with milestone #tag_name def find_issues_to_add(all_issues, tag_name) all_issues.select do |issue| - if issue['milestone'].nil? + 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'] + tag["name"] == issue["milestone"]["title"] end if milestone_is_tag.nil? false else - issue['milestone']['title'] == tag_name + issue["milestone"]["title"] == tag_name end end end @@ -53,11 +53,11 @@ module GitHubChangelogGenerator def remove_issues_in_milestones(filtered_issues) filtered_issues.select! do |issue| # leave issues without milestones - if issue['milestone'].nil? + if issue["milestone"].nil? true else # check, that this milestone in tag list: - @filtered_tags.find { |tag| tag['name'] == issue['milestone']['title'] }.nil? + @filtered_tags.find { |tag| tag["name"] == issue["milestone"]["title"] }.nil? end end end @@ -68,7 +68,7 @@ module GitHubChangelogGenerator # @param [String] older_tag all issues before this tag date will be excluded. May be nil, if it's first tag # @param [String] newer_tag all issue after this tag will be excluded. May be nil for unreleased section # @return [Array] filtered issues - def delete_by_time(issues, hash_key = 'actual_date', older_tag = nil, newer_tag = nil) + 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? @@ -123,7 +123,7 @@ module GitHubChangelogGenerator def filter_wo_labels(issues) if @options[:add_issues_wo_labels] issues_wo_labels = issues.select do |issue| - !issue['labels'].map{|l| l['name'] }.any? + !issue["labels"].map { |l| l["name"] }.any? end return issues_wo_labels end @@ -135,7 +135,7 @@ module GitHubChangelogGenerator issues else issues.select do |issue| - labels = issue['labels'].map { |l| l['name'] } & @options[:include_labels] + labels = issue["labels"].map { |l| l["name"] } & @options[:include_labels] labels.any? end end @@ -179,16 +179,16 @@ module GitHubChangelogGenerator pull_requests.each do |pr| fetched_pr = closed_pull_requests.find do |fpr| - fpr['number'] == pr['number'] + fpr["number"] == pr["number"] end if fetched_pr - pr['merged_at'] = fetched_pr['merged_at'] + pr["merged_at"] = fetched_pr["merged_at"] closed_pull_requests.delete(fetched_pr) end end pull_requests.select! do |pr| - !pr['merged_at'].nil? + !pr["merged_at"].nil? end pull_requests diff --git a/lib/github_changelog_generator/generator/generator_tags.rb b/lib/github_changelog_generator/generator/generator_tags.rb index c8dfc1c..5b5d963 100644 --- a/lib/github_changelog_generator/generator/generator_tags.rb +++ b/lib/github_changelog_generator/generator/generator_tags.rb @@ -80,8 +80,8 @@ module GitHubChangelogGenerator 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 } + if all_tags.map { |t| t["name"] }.include? tag + idx = all_tags.index { |t| t["name"] == tag } filtered_tags = if idx > 0 all_tags[0..idx - 1] else @@ -100,8 +100,8 @@ module GitHubChangelogGenerator filtered_tags = all_tags tag = @options[:due_tag] if tag - if all_tags.any? && all_tags.map(&:name).include?(tag) - idx = all_tags.index { |t| t.name == tag } + if all_tags.any? && all_tags.map { |t| t["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] @@ -121,11 +121,11 @@ module GitHubChangelogGenerator filtered_tags = all_tags if @options[:between_tags] @options[:between_tags].each do |tag| - unless all_tags.map(&:name).include? tag + unless all_tags.map { |t| t["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 } + filtered_tags = all_tags.select { |tag| @options[:between_tags].include? tag["name"] } end filtered_tags end @@ -158,18 +158,18 @@ module GitHubChangelogGenerator def filter_tags_with_regex(all_tags, regex) warn_if_nonmatching_regex(all_tags) - all_tags.reject { |tag| regex =~ tag.name } + all_tags.reject { |tag| regex =~ tag["name"] } end def filter_exact_tags(all_tags) @options[:exclude_tags].each do |tag| warn_if_tag_not_found(all_tags, tag) end - all_tags.reject { |tag| @options[:exclude_tags].include? tag.name } + all_tags.reject { |tag| @options[:exclude_tags].include? tag["name"] } end def warn_if_nonmatching_regex(all_tags) - unless all_tags.map(&:name).any? { |t| @options[:exclude_tags] =~ t } + unless all_tags.map { |t| t["name"] }.any? { |t| @options[:exclude_tags] =~ t } Helper.log.warn "Warning: unable to reject any tag, using regex "\ "#{@options[:exclude_tags].inspect} in --exclude-tags "\ "option." @@ -177,7 +177,7 @@ module GitHubChangelogGenerator end def warn_if_tag_not_found(all_tags, tag) - unless all_tags.map(&:name).include? tag + unless all_tags.map { |t| t["name"] }.include? tag Helper.log.warn "Warning: can't find tag #{tag}, specified with --exclude-tags option." end end diff --git a/lib/github_changelog_generator/hash.rb b/lib/github_changelog_generator/hash.rb index e66e7ad..3a7349e 100644 --- a/lib/github_changelog_generator/hash.rb +++ b/lib/github_changelog_generator/hash.rb @@ -2,14 +2,14 @@ class Hash def stringify_keys_deep! new_hash = {} keys.each do |k| - ks = k.respond_to?(:to_s) ? k.to_s : k - if values_at(k).first.kind_of? Hash or values_at(k).first.kind_of? Array - new_hash[ks] = values_at(k).first.send(:stringify_keys_deep!) - else - new_hash[ks] = values_at(k).first - end + ks = k.respond_to?(:to_s) ? k.to_s : k + new_hash[ks] = if values_at(k).first.is_a?(Hash) || values_at(k).first.is_a?(Array) + values_at(k).first.send(:stringify_keys_deep!) + else + values_at(k).first + end end new_hash end -end \ No newline at end of file +end diff --git a/lib/github_changelog_generator/octo_fetcher.rb b/lib/github_changelog_generator/octo_fetcher.rb index 4549c59..37f848c 100644 --- a/lib/github_changelog_generator/octo_fetcher.rb +++ b/lib/github_changelog_generator/octo_fetcher.rb @@ -28,7 +28,7 @@ module GitHubChangelogGenerator @github_token = fetch_github_token - @request_options = { :per_page => PER_PAGE_NUMBER } + @request_options = { per_page: PER_PAGE_NUMBER } @github_options = {} @github_options[:access_token] = @github_token unless @github_token.nil? @github_options[:api_endpoint] = @options[:github_endpoint] unless @options[:github_endpoint].nil? @@ -63,7 +63,6 @@ module GitHubChangelogGenerator check_github_response { github_fetch_tags } end - # Returns the number of pages for a API call # # @return [Integer] number of pages for this API call in total @@ -75,23 +74,22 @@ module GitHubChangelogGenerator last_response = client.last_response - if last_pg = last_response.rels[:last] - parse_url_for_vars(last_pg.href)['page'].to_i + if (last_pg = last_response.rels[:last]) + parse_url_for_vars(last_pg.href)["page"].to_i else 1 end end - # Fill input array with tags # # @return [Array ] array of tags in repo def github_fetch_tags tags = [] page_i = 0 - count_pages = calculate_pages(@client, 'tags', {}) + count_pages = calculate_pages(@client, "tags", {}) - iterate_pages(@client, 'tags', {}) do |new_tags| + iterate_pages(@client, "tags", {}) do |new_tags| page_i += PER_PAGE_NUMBER print_in_same_line("Fetching tags... #{page_i}/#{count_pages * PER_PAGE_NUMBER}") tags.concat(new_tags) @@ -105,7 +103,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow Helper.log.info "Found #{tags.count} tags" end # tags are a Sawyer::Resource. Convert to hash - tags = tags.map{|h| h.to_hash.stringify_keys_deep! } + tags = tags.map { |h| h.to_hash.stringify_keys_deep! } tags end @@ -117,16 +115,16 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow print "Fetching closed issues...\r" if @options[:verbose] issues = [] options = { - :state => "closed", - :filter => "all", - :labels => nil, + state: "closed", + filter: "all", + labels: nil } options[:since] = @since unless @since.nil? page_i = 0 - count_pages = calculate_pages(@client, 'issues', options) + count_pages = calculate_pages(@client, "issues", options) - iterate_pages(@client, 'issues', options) do |new_issues| + iterate_pages(@client, "issues", options) do |new_issues| page_i += PER_PAGE_NUMBER print_in_same_line("Fetching issues... #{page_i}/#{count_pages * PER_PAGE_NUMBER}") issues.concat(new_issues) @@ -135,11 +133,11 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow print_empty_line Helper.log.info "Received issues: #{issues.count}" - issues = issues.map{|h| h.to_hash.stringify_keys_deep! } + issues = issues.map { |h| h.to_hash.stringify_keys_deep! } # separate arrays of issues and pull requests: issues.partition do |x| - x['pull_request'].nil? + x["pull_request"].nil? end end @@ -148,17 +146,17 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow # @return [Array ] all pull requests def fetch_closed_pull_requests pull_requests = [] - options = { :state => 'closed' } + options = { state: "closed" } - if !@options[:release_branch].nil? + unless @options[:release_branch].nil? options[:base] = @options[:release_branch] end page_i = 0 - count_pages = calculate_pages(@client, 'pull_requests', options) + count_pages = calculate_pages(@client, "pull_requests", options) - iterate_pages(@client, 'pull_requests', options) do |new_pr| - page_i += PER_PAGE_NUMBER + iterate_pages(@client, "pull_requests", options) do |new_pr| + page_i += PER_PAGE_NUMBER log_string = "Fetching merged dates... #{page_i}/#{count_pages * PER_PAGE_NUMBER}" print_in_same_line(log_string) pull_requests.concat(new_pr) @@ -166,7 +164,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow print_empty_line Helper.log.info "Pull Request count: #{pull_requests.count}" - pull_requests = pull_requests.map{|h| h.to_hash.stringify_keys_deep! } + pull_requests = pull_requests.map { |h| h.to_hash.stringify_keys_deep! } pull_requests end @@ -181,11 +179,11 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow issues.each_slice(MAX_THREAD_NUMBER) do |issues_slice| issues_slice.each do |issue| threads << Thread.new do - issue['events'] = [] - iterate_pages(@client, 'issue_events', issue['number'], {}) do |new_event| - issue['events'].concat(new_event) + issue["events"] = [] + iterate_pages(@client, "issue_events", issue["number"], {}) do |new_event| + issue["events"].concat(new_event) end - issue['events'] = issue['events'].map{|h| h.to_hash.stringify_keys_deep! } + issue["events"] = issue["events"].map { |h| h.to_hash.stringify_keys_deep! } print_in_same_line("Fetching events for issues and PR: #{i + 1}/#{issues.count}") i += 1 end @@ -205,10 +203,10 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow # @param [Hash] tag # @return [Time] time of specified tag def fetch_date_of_tag(tag) - commit_data = check_github_response { @client.commit(user_project, tag['commit']['sha']) } + commit_data = check_github_response { @client.commit(user_project, tag["commit"]["sha"]) } commit_data = commit_data.to_hash.stringify_keys_deep! - commit_data['commit']['committer']['date'] + commit_data["commit"]["committer"]["date"] end # Fetch commit for specified event @@ -216,8 +214,9 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow # @return [Hash] def fetch_commit(event) check_github_response do - commit = @client.commit(user_project, event['commit_id']) + commit = @client.commit(user_project, event["commit_id"]) commit = commit.to_hash.stringify_keys_deep! + commit end end @@ -229,7 +228,7 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow # @param [Octokit::Client] client # @param [String] method (eg. 'tags') # @return [Integer] total number of pages - def iterate_pages(client, method, *args, &block) + def iterate_pages(client, method, *args) if args.size == 1 && args.first.is_a?(Hash) request_options = args.delete_at(0) elsif args.size > 1 && args.last.is_a?(Hash) @@ -247,8 +246,8 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow yield last_response.data - while !(next_one = last_response.rels[:next]).nil? - pages +=1 + until (next_one = last_response.rels[:next]).nil? + pages += 1 last_response = check_github_response { next_one.get } yield last_response.data @@ -307,12 +306,11 @@ Make sure, that you push tags to remote repo via 'git push --tags'".yellow # @param [String] uri eg. https://api.github.com/repositories/43914960/tags?page=37&foo=1 # @return [Hash] of all GET variables. eg. { 'page' => 37, 'foo' => 1 } def parse_url_for_vars(uri) - URI(uri).query.split("&").inject({}) do |params, get_var| - k,v = get_var.split("=") + URI(uri).query.split("&").each_with_object({}) do |params, get_var| + k, v = get_var.split("=") params[k] = v params end end - end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 004b65c..a0cacdd 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -38,16 +38,15 @@ end require "github_changelog_generator" require "github_changelog_generator/task" - VCR.configure do |c| c.allow_http_connections_when_no_cassette = true - c.cassette_library_dir = 'spec/vcr' + c.cassette_library_dir = "spec/vcr" c.ignore_localhost = true c.default_cassette_options = { - :record => :new_episodes, - :serialize_with => :json, - :preserve_exact_body_bytes => true, - :decode_compressed_response => true, + record: :new_episodes, + serialize_with: :json, + preserve_exact_body_bytes: true, + decode_compressed_response: true } c.hook_into :webmock, :faraday @@ -74,6 +73,4 @@ RSpec.configure do |config| Kernel.srand config.seed config.extend VCR::RSpec::Macros - end - diff --git a/spec/unit/fetcher_spec.rb b/spec/unit/fetcher_spec.rb deleted file mode 100644 index 5c5e970..0000000 --- a/spec/unit/fetcher_spec.rb +++ /dev/null @@ -1,231 +0,0 @@ -# frozen_string_literal: true -VALID_TOKEN = "0123456789abcdef" -INVALID_TOKEN = "0000000000000000" - -describe GitHubChangelogGenerator::Fetcher do - let(:options) do - { - :user => "skywinder", - :project => "changelog_test", - } - end - - let(:fetcher) { GitHubChangelogGenerator::Fetcher.new(options) } - - - describe "#fetch_github_token" do - token = GitHubChangelogGenerator::Fetcher::CHANGELOG_GITHUB_TOKEN - context "when token in ENV exist" do - before { stub_const("ENV", ENV.to_hash.merge(token => VALID_TOKEN)) } - subject { fetcher.fetch_github_token } - it { is_expected.to eq(VALID_TOKEN) } - end - - context "when token in ENV is nil" do - before { stub_const("ENV", ENV.to_hash.merge(token => nil)) } - subject { fetcher.fetch_github_token } - it { is_expected.to be_nil } - end - - context "when token in options and ENV is nil" do - let(:options) { { :token => VALID_TOKEN } } - - before do - stub_const("ENV", ENV.to_hash.merge(token => nil)) - end - - subject { fetcher.fetch_github_token } - it { is_expected.to eq(VALID_TOKEN) } - end - - context "when token in options and ENV specified" do - let(:options) { { :token => VALID_TOKEN } } - - before do - stub_const("ENV", ENV.to_hash.merge(token => "no_matter_what")) - end - - subject { fetcher.fetch_github_token } - it { is_expected.to eq(VALID_TOKEN) } - end - end - - describe "#get_all_tags" do - context "when github_fetch_tags returns tags" do - it "returns tags" do - mock_tags = ['tag'] - allow(fetcher).to receive(:github_fetch_tags).and_return(mock_tags) - expect(fetcher.get_all_tags).to eq(mock_tags) - end - end - end - - describe "#github_fetch_tags" do - context "when wrong token provided" do - use_vcr_cassette - - let(:options) do - { - :user => "skywinder", - :project => "changelog_test", - :token => INVALID_TOKEN - } - end - - it "should raise Unauthorized error" do - expect { fetcher.github_fetch_tags }.to raise_error Github::Error::Unauthorized - end - end - - context "when API call is valid" do - use_vcr_cassette - - it "should return tags" do - expected_tags = [{"name"=>"v0.0.3", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3", "commit"=>{"sha"=>"a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90"}}, {"name"=>"v0.0.2", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.2", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.2", "commit"=>{"sha"=>"9b35bb13dcd15b68e7bcbf10cde5eb937a54f710", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/9b35bb13dcd15b68e7bcbf10cde5eb937a54f710"}}, {"name"=>"v0.0.1", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.1", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.1", "commit"=>{"sha"=>"4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d"}}, {"name"=>"0.0.4", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/0.0.4", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/0.0.4", "commit"=>{"sha"=>"ece0c3ab7142b21064b885061c55ede00ef6ce94", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/ece0c3ab7142b21064b885061c55ede00ef6ce94"}}] - - expect(fetcher.github_fetch_tags).to eq(expected_tags) - end - end - end - - - describe "#fetch_closed_issues_and_pr" do - context "when API call is valid" do - use_vcr_cassette - - - it "returns issues" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr - expect(issues.size).to eq(7) - expect(pull_requests.size).to eq(14) - end - - it "returns issue with proper key/values" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr - expected_issue = {"url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14", "repository_url"=>"https://api.github.com/repos/skywinder/changelog_test", "labels_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}", "comments_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/comments", "events_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/events", "html_url"=>"https://github.com/skywinder/changelog_test/issues/14", "id"=>95419412, "number"=>14, "title"=>"Issue closed from commit from PR", "user"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "labels"=>[], "state"=>"closed", "locked"=>false, "assignee"=>nil, "milestone"=>nil, "comments"=>0, "created_at"=>"2015-07-16T12:06:08Z", "updated_at"=>"2015-07-16T12:21:42Z", "closed_at"=>"2015-07-16T12:21:42Z", "body"=>""} - expect(issues.first).to eq(expected_issue) - end - - it "returns pull request with proper key/values" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr - expected_pr = {"url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21", "repository_url"=>"https://api.github.com/repos/skywinder/changelog_test", "labels_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21/labels{/name}", "comments_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21/comments", "events_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21/events", "html_url"=>"https://github.com/skywinder/changelog_test/pull/21", "id"=>124925759, "number"=>21, "title"=>"Merged br (should appear in change log with #20)", "user"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "labels"=>[], "state"=>"closed", "locked"=>false, "assignee"=>nil, "milestone"=>nil, "comments"=>0, "created_at"=>"2016-01-05T09:24:08Z", "updated_at"=>"2016-01-05T09:26:53Z", "closed_at"=>"2016-01-05T09:24:27Z", "pull_request"=>{"url"=>"https://api.github.com/repos/skywinder/changelog_test/pulls/21", "html_url"=>"https://github.com/skywinder/changelog_test/pull/21", "diff_url"=>"https://github.com/skywinder/changelog_test/pull/21.diff", "patch_url"=>"https://github.com/skywinder/changelog_test/pull/21.patch"}, "body"=>"to test https://github.com/skywinder/github-changelog-generator/pull/305\r\nshould appear in change log with #20"} - expect(pull_requests.first).to eq(expected_pr) - end - - - it "returns issues with labels" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr - expected = [[], [], ["Bug"], [], ["enhancement"], ["some label"], []] - expect(issues.map{|i| i.labels.map(&:name) }).to eq(expected) - end - - it "returns pull_requests with labels" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr - expected = [[], [], [], [], [], ["enhancement"], [], [], ["invalid"], [], [], [], [], ["invalid"]] - expect(pull_requests.map{|i| i.labels.map(&:name) }).to eq(expected) - end - end - end - - describe "#fetch_closed_pull_requests" do - context "when API call is valid" do - use_vcr_cassette - - it "returns pull requests" do - pull_requests = fetcher.fetch_closed_pull_requests - expect(pull_requests.size).to eq(14) - end - - it "returns correct pull request keys" do - pull_requests = fetcher.fetch_closed_pull_requests - - pr = pull_requests.first - expect(pr.keys).to eq(["url", "id", "html_url", "diff_url", "patch_url", "issue_url", "number", "state", "locked", "title", "user", "body", "created_at", "updated_at", "closed_at", "merged_at", "merge_commit_sha", "assignee", "milestone", "commits_url", "review_comments_url", "review_comment_url", "comments_url", "statuses_url", "head", "base", "_links"]) - end - end - end - - - describe "#fetch_events_async" do - context "when API call is valid" do - use_vcr_cassette - - it "populates issues" do - issues = [{"url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14", "repository_url"=>"https://api.github.com/repos/skywinder/changelog_test", "labels_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}", "comments_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/comments", "events_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/events", "html_url"=>"https://github.com/skywinder/changelog_test/issues/14", "id"=>95419412, "number"=>14, "title"=>"Issue closed from commit from PR", "user"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "labels"=>[], "state"=>"closed", "locked"=>false, "assignee"=>nil, "milestone"=>nil, "comments"=>0, "created_at"=>"2015-07-16T12:06:08Z", "updated_at"=>"2015-07-16T12:21:42Z", "closed_at"=>"2015-07-16T12:21:42Z", "body"=>""}] - - # Check that they are blank to begin with - expect(issues.first['events']).to be_nil - - fetcher.fetch_events_async(issues) - issue_events = issues.first['events'] - - expected_events = [{"id"=>357462189, "url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189", "actor"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "event"=>"referenced", "commit_id"=>"decfe840d1a1b86e0c28700de5362d3365a29555", "commit_url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", "created_at"=>"2015-07-16T12:21:16Z"}, {"id"=>357462542, "url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/events/357462542", "actor"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "event"=>"closed", "commit_id"=>"decfe840d1a1b86e0c28700de5362d3365a29555", "commit_url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", "created_at"=>"2015-07-16T12:21:42Z"}] - expect(issue_events).to eq(expected_events) - end - - end - end - - - describe "#fetch_date_of_tag" do - context "when API call is valid" do - use_vcr_cassette - - it "returns date" do - tag = {"name"=>"v0.0.3", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3", "commit"=>{"sha"=>"a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90"}} - dt = fetcher.fetch_date_of_tag(tag) - expect(dt).to eq(Time.parse("2015-03-04 19:01:48 UTC")) - end - - end - end - - - describe "#fetch_commit" do - context "when API call is valid" do - use_vcr_cassette - - it "returns commit" do - event = {"id"=>357462189, "url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189", "actor"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "event"=>"referenced", "commit_id"=>"decfe840d1a1b86e0c28700de5362d3365a29555", "commit_url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", "created_at"=>"2015-07-16T12:21:16Z"} - commit = fetcher.fetch_commit(event) - - expectations = [ - ["sha", "decfe840d1a1b86e0c28700de5362d3365a29555"], - ["url", - "https://api.github.com/repos/skywinder/changelog_test/git/commits/decfe840d1a1b86e0c28700de5362d3365a29555"], - ["html_url", - "https://github.com/skywinder/changelog_test/commit/decfe840d1a1b86e0c28700de5362d3365a29555"], - ["author", - {"name"=>"Petr Korolev", - "email"=>"sky4winder@gmail.com", - "date"=>"2015-07-16T12:11:01Z"}], - ["committer", - {"name"=>"Petr Korolev", - "email"=>"sky4winder@gmail.com", - "date"=>"2015-07-16T12:11:01Z"}], - ["tree", - {"sha"=>"0699c15258a7c2b2e157051fe19851d4f705cac8", - "url"=> - "https://api.github.com/repos/skywinder/changelog_test/git/trees/0699c15258a7c2b2e157051fe19851d4f705cac8"}], - ["message", "fix #14"], - ["parents", - [{"sha"=>"7ec095e5e3caceacedabf44d0b9b10da17c92e51", - "url"=> - "https://api.github.com/repos/skywinder/changelog_test/git/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51", - "html_url"=> - "https://github.com/skywinder/changelog_test/commit/7ec095e5e3caceacedabf44d0b9b10da17c92e51"}] - ] - ] - - expectations.each do |property, val| - expect(commit.send(property)).to eq(val) - end - - end - - end - end - - - -end diff --git a/spec/unit/generator/generator_processor_spec.rb b/spec/unit/generator/generator_processor_spec.rb index f814569..b6f26ab 100644 --- a/spec/unit/generator/generator_processor_spec.rb +++ b/spec/unit/generator/generator_processor_spec.rb @@ -2,10 +2,10 @@ module GitHubChangelogGenerator describe Generator do context "#exclude_issues_by_labels" do - let(:label) { { 'name' => "BAD" } } - let(:issue) { { 'labels' => [label] } } - let(:good_label) { { 'name' => "GOOD" } } - let(:good_issue) { { 'labels' => [good_label] } } + let(:label) { { "name" => "BAD" } } + let(:issue) { { "labels" => [label] } } + let(:good_label) { { "name" => "GOOD" } } + let(:good_issue) { { "labels" => [good_label] } } let(:issues) { [issue, good_issue] } subject(:generator) { described_class.new(exclude_labels: %w(BAD BOO)) } diff --git a/spec/unit/generator/generator_tags_spec.rb b/spec/unit/generator/generator_tags_spec.rb index 86cdf70..0a1a083 100644 --- a/spec/unit/generator/generator_tags_spec.rb +++ b/spec/unit/generator/generator_tags_spec.rb @@ -1,12 +1,12 @@ # frozen_string_literal: true describe GitHubChangelogGenerator::Generator do - def tag_mash_with_name(tag) - Hashie::Mash.new.tap { |mash_tag| mash_tag.name = tag } + def tag_with_name(tag) + {}.tap { |mash_tag| mash_tag["name"] = tag } end - def tags_mash_from_strings(tags_strings) + def tags_from_strings(tags_strings) tags_strings.map do |tag| - tag_mash_with_name(tag) + tag_with_name(tag) end end @@ -17,20 +17,20 @@ describe GitHubChangelogGenerator::Generator do end subject do - @generator.get_filtered_tags(tags_mash_from_strings(%w(1 2 3))) + @generator.get_filtered_tags(tags_from_strings(%w(1 2 3))) end it { is_expected.to be_a(Array) } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) } end context "when between_tags same as input array" do before do @generator = GitHubChangelogGenerator::Generator.new(between_tags: %w(1 2 3)) end subject do - @generator.get_filtered_tags(tags_mash_from_strings(%w(1 2 3))) + @generator.get_filtered_tags(tags_from_strings(%w(1 2 3))) end it { is_expected.to be_a(Array) } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) } end context "when between_tags filled with correct values" do @@ -38,10 +38,10 @@ describe GitHubChangelogGenerator::Generator do @generator = GitHubChangelogGenerator::Generator.new(between_tags: %w(1 2)) end subject do - @generator.get_filtered_tags(tags_mash_from_strings(%w(1 2 3))) + @generator.get_filtered_tags(tags_from_strings(%w(1 2 3))) end it { is_expected.to be_a(Array) } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2))) } end context "when between_tags filled with invalid values" do @@ -50,133 +50,133 @@ describe GitHubChangelogGenerator::Generator do end subject do - @generator.get_filtered_tags(tags_mash_from_strings(%w(1 2 3))) + @generator.get_filtered_tags(tags_from_strings(%w(1 2 3))) end it { is_expected.to be_a(Array) } - it { is_expected.to match_array(tags_mash_from_strings(%w(1))) } + it { is_expected.to match_array(tags_from_strings(%w(1))) } end end describe "#get_filtered_tags" do subject do - generator.get_filtered_tags(tags_mash_from_strings(%w(1 2 3 4 5))) + generator.get_filtered_tags(tags_from_strings(%w(1 2 3 4 5))) end context "with excluded and between tags" do let(:generator) { GitHubChangelogGenerator::Generator.new(between_tags: %w(1 2 3), exclude_tags: %w(2)) } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 3))) } end end describe "#filter_excluded_tags" do - subject { generator.filter_excluded_tags(tags_mash_from_strings(%w(1 2 3))) } + subject { generator.filter_excluded_tags(tags_from_strings(%w(1 2 3))) } context "with matching string" do let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: %w(3)) } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2))) } end context "with non-matching string" do let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: %w(invalid tags)) } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) } end context "with matching regex" do let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: /[23]/) } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1))) } + it { is_expected.to match_array(tags_from_strings(%w(1))) } end context "with non-matching regex" do let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags: /[abc]/) } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) } end end describe "#filter_excluded_tags_regex" do - subject { generator.filter_excluded_tags(tags_mash_from_strings(%w(1 2 3))) } + subject { generator.filter_excluded_tags(tags_from_strings(%w(1 2 3))) } context "with matching regex" do let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags_regex: "[23]") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1))) } + it { is_expected.to match_array(tags_from_strings(%w(1))) } end context "with non-matching regex" do let(:generator) { GitHubChangelogGenerator::Generator.new(exclude_tags_regex: "[45]") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) } end end describe "#filter_since_tag" do context "with filled array" do - subject { generator.filter_since_tag(tags_mash_from_strings(%w(1 2 3))) } + subject { generator.filter_since_tag(tags_from_strings(%w(1 2 3))) } context "with valid since tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "2") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1))) } + it { is_expected.to match_array(tags_from_strings(%w(1))) } end context "with invalid since tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "Invalid tag") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) } end end context "with empty array" do - subject { generator.filter_since_tag(tags_mash_from_strings(%w())) } + subject { generator.filter_since_tag(tags_from_strings(%w())) } context "with valid since tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "2") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w())) } + it { is_expected.to match_array(tags_from_strings(%w())) } end context "with invalid since tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(since_tag: "Invalid tag") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w())) } + it { is_expected.to match_array(tags_from_strings(%w())) } end end end describe "#filter_due_tag" do context "with filled array" do - subject { generator.filter_due_tag(tags_mash_from_strings(%w(1 2 3))) } + subject { generator.filter_due_tag(tags_from_strings(%w(1 2 3))) } context "with valid due tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "2") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(3))) } + it { is_expected.to match_array(tags_from_strings(%w(3))) } end context "with invalid due tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "Invalid tag") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w(1 2 3))) } + it { is_expected.to match_array(tags_from_strings(%w(1 2 3))) } end end context "with empty array" do - subject { generator.filter_due_tag(tags_mash_from_strings(%w())) } + subject { generator.filter_due_tag(tags_from_strings(%w())) } context "with valid due tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "2") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w())) } + it { is_expected.to match_array(tags_from_strings(%w())) } end context "with invalid due tag" do let(:generator) { GitHubChangelogGenerator::Generator.new(due_tag: "Invalid tag") } it { is_expected.to be_a Array } - it { is_expected.to match_array(tags_mash_from_strings(%w())) } + it { is_expected.to match_array(tags_from_strings(%w())) } end end end @@ -191,7 +191,7 @@ describe GitHubChangelogGenerator::Generator do end context "fetch already filled tag" do before { @generator.instance_variable_set :@tag_times_hash, "valid_tag" => current_time } - subject { @generator.get_time_of_tag tag_mash_with_name("valid_tag") } + subject { @generator.get_time_of_tag tag_with_name("valid_tag") } it { is_expected.to be_a_kind_of(Time) } it { is_expected.to eq(current_time) } end @@ -202,7 +202,7 @@ describe GitHubChangelogGenerator::Generator do @generator.instance_variable_set :@fetcher, mock end subject do - of_tag = @generator.get_time_of_tag(tag_mash_with_name("valid_tag")) + of_tag = @generator.get_time_of_tag(tag_with_name("valid_tag")) of_tag end it { is_expected.to be_a_kind_of(Time) } @@ -229,13 +229,13 @@ describe GitHubChangelogGenerator::Generator do @generator.sort_tags_by_date(tags) end context "sort unsorted tags" do - let(:tags) { tags_mash_from_strings %w(valid_tag1 valid_tag2 valid_tag3) } + let(:tags) { tags_from_strings %w(valid_tag1 valid_tag2 valid_tag3) } it { is_expected.to be_a_kind_of(Array) } it { is_expected.to match_array(tags.reverse!) } end context "sort sorted tags" do - let(:tags) { tags_mash_from_strings %w(valid_tag3 valid_tag2 valid_tag1) } + let(:tags) { tags_from_strings %w(valid_tag3 valid_tag2 valid_tag1) } it { is_expected.to be_a_kind_of(Array) } it { is_expected.to match_array(tags) } diff --git a/spec/unit/octo_fetcher_spec.rb b/spec/unit/octo_fetcher_spec.rb index 0460e95..7bbfea7 100644 --- a/spec/unit/octo_fetcher_spec.rb +++ b/spec/unit/octo_fetcher_spec.rb @@ -4,14 +4,13 @@ INVALID_TOKEN = "0000000000000000" describe GitHubChangelogGenerator::OctoFetcher do let(:options) do { - :user => "skywinder", - :project => "changelog_test", + user: "skywinder", + project: "changelog_test" } end let(:fetcher) { GitHubChangelogGenerator::OctoFetcher.new(options) } - describe "#fetch_github_token" do token = GitHubChangelogGenerator::OctoFetcher::CHANGELOG_GITHUB_TOKEN context "when token in ENV exist" do @@ -27,7 +26,7 @@ describe GitHubChangelogGenerator::OctoFetcher do end context "when token in options and ENV is nil" do - let(:options) { { :token => VALID_TOKEN } } + let(:options) { { token: VALID_TOKEN } } before do stub_const("ENV", ENV.to_hash.merge(token => nil)) @@ -38,7 +37,7 @@ describe GitHubChangelogGenerator::OctoFetcher do end context "when token in options and ENV specified" do - let(:options) { { :token => VALID_TOKEN } } + let(:options) { { token: VALID_TOKEN } } before do stub_const("ENV", ENV.to_hash.merge(token => "no_matter_what")) @@ -52,7 +51,7 @@ describe GitHubChangelogGenerator::OctoFetcher do describe "#get_all_tags" do context "when github_fetch_tags returns tags" do it "returns tags" do - mock_tags = ['tag'] + mock_tags = ["tag"] allow(fetcher).to receive(:github_fetch_tags).and_return(mock_tags) expect(fetcher.get_all_tags).to eq(mock_tags) end @@ -65,9 +64,9 @@ describe GitHubChangelogGenerator::OctoFetcher do let(:options) do { - :user => "skywinder", - :project => "changelog_test", - :token => INVALID_TOKEN + user: "skywinder", + project: "changelog_test", + token: INVALID_TOKEN } end @@ -80,7 +79,42 @@ describe GitHubChangelogGenerator::OctoFetcher do use_vcr_cassette it "should return tags" do - expected_tags = [{"name"=>"v0.0.3", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3", "commit"=>{"sha"=>"a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90"}}, {"name"=>"v0.0.2", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.2", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.2", "commit"=>{"sha"=>"9b35bb13dcd15b68e7bcbf10cde5eb937a54f710", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/9b35bb13dcd15b68e7bcbf10cde5eb937a54f710"}}, {"name"=>"v0.0.1", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.1", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.1", "commit"=>{"sha"=>"4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d"}}, {"name"=>"0.0.4", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/0.0.4", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/0.0.4", "commit"=>{"sha"=>"ece0c3ab7142b21064b885061c55ede00ef6ce94", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/ece0c3ab7142b21064b885061c55ede00ef6ce94"}}] + expected_tags = [{ "name" => "v0.0.3", + "zipball_url" => + "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3", + "tarball_url" => + "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3", + "commit" => + { "sha" => "a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90", + "url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90" } }, + { "name" => "v0.0.2", + "zipball_url" => + "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.2", + "tarball_url" => + "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.2", + "commit" => + { "sha" => "9b35bb13dcd15b68e7bcbf10cde5eb937a54f710", + "url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/9b35bb13dcd15b68e7bcbf10cde5eb937a54f710" } }, + { "name" => "v0.0.1", + "zipball_url" => + "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.1", + "tarball_url" => + "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.1", + "commit" => + { "sha" => "4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d", + "url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/4c2d6d1ed58bdb24b870dcb5d9f2ceed0283d69d" } }, + { "name" => "0.0.4", + "zipball_url" => + "https://api.github.com/repos/skywinder/changelog_test/zipball/0.0.4", + "tarball_url" => + "https://api.github.com/repos/skywinder/changelog_test/tarball/0.0.4", + "commit" => + { "sha" => "ece0c3ab7142b21064b885061c55ede00ef6ce94", + "url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/ece0c3ab7142b21064b885061c55ede00ef6ce94" } }] expect(fetcher.github_fetch_tags).to eq(expected_tags) end @@ -92,12 +126,10 @@ describe GitHubChangelogGenerator::OctoFetcher do end end - describe "#fetch_closed_issues_and_pr" do context "when API call is valid" do use_vcr_cassette - it "returns issues" do issues, pull_requests = fetcher.fetch_closed_issues_and_pr expect(issues.size).to eq(7) @@ -105,42 +137,127 @@ describe GitHubChangelogGenerator::OctoFetcher do end it "returns issue with proper key/values" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr - expected_issue = {"url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14", "repository_url"=>"https://api.github.com/repos/skywinder/changelog_test", "labels_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}", "comments_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/comments", "events_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/events", "html_url"=>"https://github.com/skywinder/changelog_test/issues/14", "id"=>95419412, "number"=>14, "title"=>"Issue closed from commit from PR", "user"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "labels"=>[], "state"=>"closed", "locked"=>false, "assignee"=>nil, "milestone"=>nil, "comments"=>0, "created_at"=>"2015-07-16T12:06:08Z", "updated_at"=>"2015-07-16T12:21:42Z", "closed_at"=>"2015-07-16T12:21:42Z", "body"=>""} + issues, _pull_requests = fetcher.fetch_closed_issues_and_pr + expected_issue = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14", + "repository_url" => "https://api.github.com/repos/skywinder/changelog_test", + "labels_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}", + "comments_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/14/comments", + "events_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/14/events", + "html_url" => "https://github.com/skywinder/changelog_test/issues/14", + "id" => 95_419_412, + "number" => 14, + "title" => "Issue closed from commit from PR", + "user" => + { "login" => "skywinder", + "id" => 3_356_474, + "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", + "gravatar_id" => "", + "url" => "https://api.github.com/users/skywinder", + "html_url" => "https://github.com/skywinder", + "followers_url" => "https://api.github.com/users/skywinder/followers", + "following_url" => + "https://api.github.com/users/skywinder/following{/other_user}", + "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", + "starred_url" => + "https://api.github.com/users/skywinder/starred{/owner}{/repo}", + "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", + "organizations_url" => "https://api.github.com/users/skywinder/orgs", + "repos_url" => "https://api.github.com/users/skywinder/repos", + "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", + "received_events_url" => + "https://api.github.com/users/skywinder/received_events", + "type" => "User", + "site_admin" => false }, + "labels" => [], + "state" => "closed", + "locked" => false, + "assignee" => nil, + "milestone" => nil, + "comments" => 0, + "created_at" => "2015-07-16T12:06:08Z", + "updated_at" => "2015-07-16T12:21:42Z", + "closed_at" => "2015-07-16T12:21:42Z", + "body" => "" } # Convert times to Time - expected_issue.each_pair do |k,v| - if v =~ /^2015-/ - expected_issue[k] = Time.parse(v) - end + expected_issue.each_pair do |k, v| + expected_issue[k] = Time.parse(v) if v =~ /^2015-/ end expect(issues.first).to eq(expected_issue) end it "returns pull request with proper key/values" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr - expected_pr = {"url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21", "repository_url"=>"https://api.github.com/repos/skywinder/changelog_test", "labels_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21/labels{/name}", "comments_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21/comments", "events_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/21/events", "html_url"=>"https://github.com/skywinder/changelog_test/pull/21", "id"=>124925759, "number"=>21, "title"=>"Merged br (should appear in change log with #20)", "user"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "labels"=>[], "state"=>"closed", "locked"=>false, "assignee"=>nil, "milestone"=>nil, "comments"=>0, "created_at"=>"2016-01-05T09:24:08Z", "updated_at"=>"2016-01-05T09:26:53Z", "closed_at"=>"2016-01-05T09:24:27Z", "pull_request"=>{"url"=>"https://api.github.com/repos/skywinder/changelog_test/pulls/21", "html_url"=>"https://github.com/skywinder/changelog_test/pull/21", "diff_url"=>"https://github.com/skywinder/changelog_test/pull/21.diff", "patch_url"=>"https://github.com/skywinder/changelog_test/pull/21.patch"}, "body"=>"to test https://github.com/skywinder/github-changelog-generator/pull/305\r\nshould appear in change log with #20"} + _issues, pull_requests = fetcher.fetch_closed_issues_and_pr + expected_pr = { "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/21", + "repository_url" => "https://api.github.com/repos/skywinder/changelog_test", + "labels_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/21/labels{/name}", + "comments_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/21/comments", + "events_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/21/events", + "html_url" => "https://github.com/skywinder/changelog_test/pull/21", + "id" => 124_925_759, + "number" => 21, + "title" => "Merged br (should appear in change log with #20)", + "user" => + { "login" => "skywinder", + "id" => 3_356_474, + "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", + "gravatar_id" => "", + "url" => "https://api.github.com/users/skywinder", + "html_url" => "https://github.com/skywinder", + "followers_url" => "https://api.github.com/users/skywinder/followers", + "following_url" => + "https://api.github.com/users/skywinder/following{/other_user}", + "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", + "starred_url" => + "https://api.github.com/users/skywinder/starred{/owner}{/repo}", + "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", + "organizations_url" => "https://api.github.com/users/skywinder/orgs", + "repos_url" => "https://api.github.com/users/skywinder/repos", + "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", + "received_events_url" => + "https://api.github.com/users/skywinder/received_events", + "type" => "User", + "site_admin" => false }, + "labels" => [], + "state" => "closed", + "locked" => false, + "assignee" => nil, + "milestone" => nil, + "comments" => 0, + "created_at" => "2016-01-05T09:24:08Z", + "updated_at" => "2016-01-05T09:26:53Z", + "closed_at" => "2016-01-05T09:24:27Z", + "pull_request" => + { "url" => "https://api.github.com/repos/skywinder/changelog_test/pulls/21", + "html_url" => "https://github.com/skywinder/changelog_test/pull/21", + "diff_url" => "https://github.com/skywinder/changelog_test/pull/21.diff", + "patch_url" => "https://github.com/skywinder/changelog_test/pull/21.patch" }, + "body" => + "to test https://github.com/skywinder/github-changelog-generator/pull/305\r\nshould appear in change log with #20" } # Convert times to Time - expected_pr.each_pair do |k,v| - if v =~ /^2016-01/ - expected_pr[k] = Time.parse(v) - end + expected_pr.each_pair do |k, v| + expected_pr[k] = Time.parse(v) if v =~ /^2016-01/ end expect(pull_requests.first).to eq(expected_pr) end - it "returns issues with labels" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr + issues, _pull_requests = fetcher.fetch_closed_issues_and_pr expected = [[], [], ["Bug"], [], ["enhancement"], ["some label"], []] - expect(issues.map{|i| i['labels'].map{|l| l['name']} }).to eq(expected) + expect(issues.map { |i| i["labels"].map { |l| l["name"] } }).to eq(expected) end it "returns pull_requests with labels" do - issues, pull_requests = fetcher.fetch_closed_issues_and_pr + _issues, pull_requests = fetcher.fetch_closed_issues_and_pr expected = [[], [], [], [], [], ["enhancement"], [], [], ["invalid"], [], [], [], [], ["invalid"]] - expect(pull_requests.map{|i| i['labels'].map{|l| l['name']} }).to eq(expected) + expect(pull_requests.map { |i| i["labels"].map { |l| l["name"] } }).to eq(expected) end end end @@ -158,93 +275,222 @@ describe GitHubChangelogGenerator::OctoFetcher do pull_requests = fetcher.fetch_closed_pull_requests pr = pull_requests.first - expect(pr.keys).to eq(["url", "id", "html_url", "diff_url", "patch_url", "issue_url", "number", "state", "locked", "title", "user", "body", "created_at", "updated_at", "closed_at", "merged_at", "merge_commit_sha", "assignee", "milestone", "commits_url", "review_comments_url", "review_comment_url", "comments_url", "statuses_url", "head", "base", "_links"]) + expect(pr.keys).to eq(%w(url id html_url diff_url patch_url issue_url number state locked title user body created_at updated_at closed_at merged_at merge_commit_sha assignee milestone commits_url review_comments_url review_comment_url comments_url statuses_url head base _links)) end end end - describe "#fetch_events_async" do context "when API call is valid" do use_vcr_cassette it "populates issues" do - issues = [{"url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14", "repository_url"=>"https://api.github.com/repos/skywinder/changelog_test", "labels_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}", "comments_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/comments", "events_url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/14/events", "html_url"=>"https://github.com/skywinder/changelog_test/issues/14", "id"=>95419412, "number"=>14, "title"=>"Issue closed from commit from PR", "user"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "labels"=>[], "state"=>"closed", "locked"=>false, "assignee"=>nil, "milestone"=>nil, "comments"=>0, "created_at"=>"2015-07-16T12:06:08Z", "updated_at"=>"2015-07-16T12:21:42Z", "closed_at"=>"2015-07-16T12:21:42Z", "body"=>""}] + issues = [{ "url" => "https://api.github.com/repos/skywinder/changelog_test/issues/14", + "repository_url" => "https://api.github.com/repos/skywinder/changelog_test", + "labels_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/14/labels{/name}", + "comments_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/14/comments", + "events_url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/14/events", + "html_url" => "https://github.com/skywinder/changelog_test/issues/14", + "id" => 95_419_412, + "number" => 14, + "title" => "Issue closed from commit from PR", + "user" => + { "login" => "skywinder", + "id" => 3_356_474, + "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", + "gravatar_id" => "", + "url" => "https://api.github.com/users/skywinder", + "html_url" => "https://github.com/skywinder", + "followers_url" => "https://api.github.com/users/skywinder/followers", + "following_url" => + "https://api.github.com/users/skywinder/following{/other_user}", + "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", + "starred_url" => + "https://api.github.com/users/skywinder/starred{/owner}{/repo}", + "subscriptions_url" => + "https://api.github.com/users/skywinder/subscriptions", + "organizations_url" => "https://api.github.com/users/skywinder/orgs", + "repos_url" => "https://api.github.com/users/skywinder/repos", + "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", + "received_events_url" => + "https://api.github.com/users/skywinder/received_events", + "type" => "User", + "site_admin" => false }, + "labels" => [], + "state" => "closed", + "locked" => false, + "assignee" => nil, + "milestone" => nil, + "comments" => 0, + "created_at" => "2015-07-16T12:06:08Z", + "updated_at" => "2015-07-16T12:21:42Z", + "closed_at" => "2015-07-16T12:21:42Z", + "body" => "" }] # Check that they are blank to begin with - expect(issues.first['events']).to be_nil + expect(issues.first["events"]).to be_nil fetcher.fetch_events_async(issues) - issue_events = issues.first['events'] + issue_events = issues.first["events"] - expected_events = [{"id"=>357462189, "url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189", "actor"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "event"=>"referenced", "commit_id"=>"decfe840d1a1b86e0c28700de5362d3365a29555", "commit_url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", "created_at"=>"2015-07-16T12:21:16Z"}, {"id"=>357462542, "url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/events/357462542", "actor"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "event"=>"closed", "commit_id"=>"decfe840d1a1b86e0c28700de5362d3365a29555", "commit_url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", "created_at"=>"2015-07-16T12:21:42Z"}] + expected_events = [{ "id" => 357_462_189, + "url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189", + "actor" => + { "login" => "skywinder", + "id" => 3_356_474, + "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", + "gravatar_id" => "", + "url" => "https://api.github.com/users/skywinder", + "html_url" => "https://github.com/skywinder", + "followers_url" => "https://api.github.com/users/skywinder/followers", + "following_url" => + "https://api.github.com/users/skywinder/following{/other_user}", + "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", + "starred_url" => + "https://api.github.com/users/skywinder/starred{/owner}{/repo}", + "subscriptions_url" => + "https://api.github.com/users/skywinder/subscriptions", + "organizations_url" => "https://api.github.com/users/skywinder/orgs", + "repos_url" => "https://api.github.com/users/skywinder/repos", + "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", + "received_events_url" => + "https://api.github.com/users/skywinder/received_events", + "type" => "User", + "site_admin" => false }, + "event" => "referenced", + "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555", + "commit_url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", + "created_at" => "2015-07-16T12:21:16Z" }, + { "id" => 357_462_542, + "url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462542", + "actor" => + { "login" => "skywinder", + "id" => 3_356_474, + "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", + "gravatar_id" => "", + "url" => "https://api.github.com/users/skywinder", + "html_url" => "https://github.com/skywinder", + "followers_url" => "https://api.github.com/users/skywinder/followers", + "following_url" => + "https://api.github.com/users/skywinder/following{/other_user}", + "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", + "starred_url" => + "https://api.github.com/users/skywinder/starred{/owner}{/repo}", + "subscriptions_url" => + "https://api.github.com/users/skywinder/subscriptions", + "organizations_url" => "https://api.github.com/users/skywinder/orgs", + "repos_url" => "https://api.github.com/users/skywinder/repos", + "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", + "received_events_url" => + "https://api.github.com/users/skywinder/received_events", + "type" => "User", + "site_admin" => false }, + "event" => "closed", + "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555", + "commit_url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", + "created_at" => "2015-07-16T12:21:42Z" }] # Convert times to Time expected_events.map! do |event| event.each_pair do |k, v| - if v =~ /^201[56]-/ - event[k] = Time.parse(v) - end + event[k] = Time.parse(v) if v =~ /^201[56]-/ end end expect(issue_events).to eq(expected_events) end - end end - describe "#fetch_date_of_tag" do context "when API call is valid" do use_vcr_cassette it "returns date" do - tag = {"name"=>"v0.0.3", "zipball_url"=>"https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3", "tarball_url"=>"https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3", "commit"=>{"sha"=>"a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90", "url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90"}} + tag = { "name" => "v0.0.3", + "zipball_url" => + "https://api.github.com/repos/skywinder/changelog_test/zipball/v0.0.3", + "tarball_url" => + "https://api.github.com/repos/skywinder/changelog_test/tarball/v0.0.3", + "commit" => + { "sha" => "a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90", + "url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/a0cba2b1a1ea9011ab07ee1ac140ba5a5eb8bd90" } } + dt = fetcher.fetch_date_of_tag(tag) expect(dt).to eq(Time.parse("2015-03-04 19:01:48 UTC")) end - end end - describe "#fetch_commit" do context "when API call is valid" do use_vcr_cassette it "returns commit" do - event = {"id"=>357462189, "url"=>"https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189", "actor"=>{"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}, "event"=>"referenced", "commit_id"=>"decfe840d1a1b86e0c28700de5362d3365a29555", "commit_url"=>"https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", "created_at"=>"2015-07-16T12:21:16Z"} + event = { "id" => 357_462_189, + "url" => + "https://api.github.com/repos/skywinder/changelog_test/issues/events/357462189", + "actor" => + { "login" => "skywinder", + "id" => 3_356_474, + "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", + "gravatar_id" => "", + "url" => "https://api.github.com/users/skywinder", + "html_url" => "https://github.com/skywinder", + "followers_url" => "https://api.github.com/users/skywinder/followers", + "following_url" => + "https://api.github.com/users/skywinder/following{/other_user}", + "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", + "starred_url" => + "https://api.github.com/users/skywinder/starred{/owner}{/repo}", + "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", + "organizations_url" => "https://api.github.com/users/skywinder/orgs", + "repos_url" => "https://api.github.com/users/skywinder/repos", + "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", + "received_events_url" => + "https://api.github.com/users/skywinder/received_events", + "type" => "User", + "site_admin" => false }, + "event" => "referenced", + "commit_id" => "decfe840d1a1b86e0c28700de5362d3365a29555", + "commit_url" => + "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555", + "created_at" => "2015-07-16T12:21:16Z" } commit = fetcher.fetch_commit(event) expectations = [ - ["sha", "decfe840d1a1b86e0c28700de5362d3365a29555"], + %w(sha decfe840d1a1b86e0c28700de5362d3365a29555), ["url", "https://api.github.com/repos/skywinder/changelog_test/commits/decfe840d1a1b86e0c28700de5362d3365a29555"], # OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/decfe840d1a1b86e0c28700de5362d3365a29555"], ["html_url", "https://github.com/skywinder/changelog_test/commit/decfe840d1a1b86e0c28700de5362d3365a29555"], ["author", - {"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}], + { "login" => "skywinder", "id" => 3_356_474, "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id" => "", "url" => "https://api.github.com/users/skywinder", "html_url" => "https://github.com/skywinder", "followers_url" => "https://api.github.com/users/skywinder/followers", "following_url" => "https://api.github.com/users/skywinder/following{/other_user}", "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url" => "https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", "organizations_url" => "https://api.github.com/users/skywinder/orgs", "repos_url" => "https://api.github.com/users/skywinder/repos", "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", "received_events_url" => "https://api.github.com/users/skywinder/received_events", "type" => "User", "site_admin" => false }], ["committer", - {"login"=>"skywinder", "id"=>3356474, "avatar_url"=>"https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id"=>"", "url"=>"https://api.github.com/users/skywinder", "html_url"=>"https://github.com/skywinder", "followers_url"=>"https://api.github.com/users/skywinder/followers", "following_url"=>"https://api.github.com/users/skywinder/following{/other_user}", "gists_url"=>"https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url"=>"https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url"=>"https://api.github.com/users/skywinder/subscriptions", "organizations_url"=>"https://api.github.com/users/skywinder/orgs", "repos_url"=>"https://api.github.com/users/skywinder/repos", "events_url"=>"https://api.github.com/users/skywinder/events{/privacy}", "received_events_url"=>"https://api.github.com/users/skywinder/received_events", "type"=>"User", "site_admin"=>false}], + { "login" => "skywinder", "id" => 3_356_474, "avatar_url" => "https://avatars.githubusercontent.com/u/3356474?v=3", "gravatar_id" => "", "url" => "https://api.github.com/users/skywinder", "html_url" => "https://github.com/skywinder", "followers_url" => "https://api.github.com/users/skywinder/followers", "following_url" => "https://api.github.com/users/skywinder/following{/other_user}", "gists_url" => "https://api.github.com/users/skywinder/gists{/gist_id}", "starred_url" => "https://api.github.com/users/skywinder/starred{/owner}{/repo}", "subscriptions_url" => "https://api.github.com/users/skywinder/subscriptions", "organizations_url" => "https://api.github.com/users/skywinder/orgs", "repos_url" => "https://api.github.com/users/skywinder/repos", "events_url" => "https://api.github.com/users/skywinder/events{/privacy}", "received_events_url" => "https://api.github.com/users/skywinder/received_events", "type" => "User", "site_admin" => false }], ["parents", - [{"sha"=>"7ec095e5e3caceacedabf44d0b9b10da17c92e51", - "url"=> + [{ "sha" => "7ec095e5e3caceacedabf44d0b9b10da17c92e51", + "url" => "https://api.github.com/repos/skywinder/changelog_test/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51", - # OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51", - "html_url"=> - "https://github.com/skywinder/changelog_test/commit/7ec095e5e3caceacedabf44d0b9b10da17c92e51"}] + # OLD API: "https://api.github.com/repos/skywinder/changelog_test/git/commits/7ec095e5e3caceacedabf44d0b9b10da17c92e51", + "html_url" => + "https://github.com/skywinder/changelog_test/commit/7ec095e5e3caceacedabf44d0b9b10da17c92e51" }] ] ] expectations.each do |property, val| expect(commit[property]).to eq(val) end - end - end end - end