diff --git a/.gitignore b/.gitignore index a64bd1285..e69de29bb 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +0,0 @@ -constants.rb -*.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 000000000..e9842e488 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,23 @@ +# Changelog + +## [0.3.0] (https://github.com/skywinder/Github-Changelog-Generator/tree/0.3.0) +#### 07/11/14 +- Fix parsing date of pull request [\#3](https://github.com/skywinder/Github-Changelog-Generator/pull/3) + +- *Fixed bug:* Last tag not appeared in changelog [\#5](https://github.com/skywinder/Github-Changelog-Generator/issues/5) + +- *Fixed issue:* Implement option to specify output filename [\#4](https://github.com/skywinder/Github-Changelog-Generator/issues/4) + +## [0.1.0] (https://github.com/skywinder/Github-Changelog-Generator/tree/0.1.0) +#### 07/11/14 +- Add changelog generation for last tag [\#2](https://github.com/skywinder/Github-Changelog-Generator/pull/2) + +- Add option (-o --output) to specify name of the output file. [\#1](https://github.com/skywinder/Github-Changelog-Generator/pull/1) + +## [0.0.2] (https://github.com/skywinder/Github-Changelog-Generator/tree/0.0.2) +#### 06/11/14 +## [0.0.1] (https://github.com/skywinder/Github-Changelog-Generator/tree/0.0.1) +#### 06/11/14 + + +**This file was generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)* \ No newline at end of file diff --git a/README.md b/README.md index 9c5cbce0a..eed0ef8c8 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ See `github_changelog_generator --help` for detailed usage. -v, --[no-]verbose Run verbosely -l, --last-changes Generate log between only last 2 tags -f, --date-format [FORMAT] Date format. Default is %d/%m/%y - -o, --output [FORMAT] Output file. Default is CHANGELOG.md + -o, --output [NAME] Output file. Default is CHANGELOG.md ## Examples: ### This changelog: [ActionSheetPicker-3.0/CHANGELOG.md](https://github.com/skywinder/ActionSheetPicker-3.0/blob/master/CHANGELOG.md) diff --git a/github_changelog_generator.gemspec b/github_changelog_generator.gemspec index 1e067fc58..d02969b79 100644 --- a/github_changelog_generator.gemspec +++ b/github_changelog_generator.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |s| s.name = "github_changelog_generator" - s.version = "0.0.2" + s.version = "1.0.0" s.default_executable = "github_changelog_generator" s.required_ruby_version = '>= 1.9.3' diff --git a/lib/github_changelog_generator.rb b/lib/github_changelog_generator.rb index ec41d919a..4afae76c7 100755 --- a/lib/github_changelog_generator.rb +++ b/lib/github_changelog_generator.rb @@ -8,7 +8,7 @@ class ChangelogGenerator - attr_accessor :options, :all_tags + attr_accessor :options, :all_tags, :github def initialize() @@ -20,6 +20,7 @@ def initialize() end @all_tags = self.get_all_tags @pull_requests = self.get_all_closed_pull_requests + @issues = self.get_all_issues @tag_times_hash = {} end @@ -35,17 +36,14 @@ def exec_command(cmd) def get_all_closed_pull_requests - - - issues = @github.pull_requests.list @options[:user], @options[:project], :state => 'closed' - json = issues.body + request = @github.pull_requests.list @options[:user], @options[:project], :state => 'closed' + pull_requests = request.body if @options[:verbose] puts 'Receive all pull requests' end - json - + pull_requests end def compund_changelog @@ -87,7 +85,7 @@ def compund_changelog puts log end - log += "\n\n*This file was generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*" + log += "\n\n**This file was generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*" output_filename = "#{@options[:output]}" File.open(output_filename, 'w') { |file| file.write(log) } @@ -111,19 +109,6 @@ def is_megred(number) @github.pull_requests.merged? @options[:user], @options[:project], number end - def get_all_merged_pull_requests - json = self.get_all_closed_pull_requests - puts 'Check if the requests is merged... (it can take a while)' - - json.delete_if { |req| - merged = self.is_megred(req[:number]) - if @options[:verbose] - puts "##{req[:number]} #{merged ? 'merged' : 'not merged'}" - end - !merged - } - end - def get_all_tags url = "https://api.github.com/repos/#{@options[:user]}/#{@options[:project]}/tags" @@ -133,7 +118,7 @@ def get_all_tags end response = HTTParty.get(url, - :headers => {'Authorization' => 'token 8587bb22f6bf125454768a4a19dbcc774ea68d48', + :headers => {'Authorization' => "token #{@options[:token]}", 'User-Agent' => 'Changelog-Generator'}) json_parse = JSON.parse(response.body) @@ -160,15 +145,37 @@ def generate_log_between_tags(since_tag, till_tag) pull_requests = Array.new(@pull_requests) pull_requests.delete_if { |req| - t = Time.parse(req[:merged_at]).utc - tag_is_later_since = t > since_tag_time - tag_is_before_till = t <= till_tag_time + if req[:merged_at] + t = Time.parse(req[:merged_at]).utc + tag_is_later_since = t > since_tag_time + tag_is_before_till = t <= till_tag_time + + in_range = (tag_is_later_since) && (tag_is_before_till) + !in_range + else + true + end - in_range = (tag_is_later_since) && (tag_is_before_till) - !in_range } - self.create_log(pull_requests, till_tag_name, till_tag_time) + issues = Array.new(@issues) + + issues.delete_if{ |issue| + if issue[:closed_at] + t = Time.parse(issue[:closed_at]).utc + tag_is_later_since = t > since_tag_time + tag_is_before_till = t <= till_tag_time + + in_range = (tag_is_later_since) && (tag_is_before_till) + !in_range + else + true + end + + } + + self.create_log(pull_requests, issues, till_tag_name, till_tag_time) + end def generate_log_before_tag(tag) @@ -178,26 +185,81 @@ def generate_log_before_tag(tag) pull_requests = Array.new(@pull_requests) pull_requests.delete_if { |req| - t = Time.parse(req[:closed_at]).utc - t > tag_time + if req[:merged_at] + t = Time.parse(req[:merged_at]).utc + t > tag_time + else + true + end + + } + + issues = Array.new(@issues) + + issues.delete_if{ |issue| + if issue[:closed_at] + t = Time.parse(issue[:closed_at]).utc + t > tag_time + else + true + end } - self.create_log(pull_requests, tag_name, tag_time) + self.create_log(pull_requests, issues, tag_name, tag_time) end - def create_log(pull_requests, tag_name, tag_time) + def create_log(pull_requests, issues, tag_name, tag_time) + # Generate tag name and link trimmed_tag = tag_name.tr('v', '') log = "## [#{trimmed_tag}] (https://github.com/#{@options[:user]}/#{@options[:project]}/tree/#{tag_name})\n" + #Generate date string: time_string = tag_time.strftime @options[:format] log += "#### #{time_string}\n" - pull_requests.each { |dict| - merge = "#{dict[:title]} [\\##{dict[:number]}](https://github.com/#{@options[:user]}/#{@options[:project]}/pull/#{dict[:number]})\n\n" - log += "- #{merge}" - } + if @options[:pulls] + # Generate pull requests: + if pull_requests + pull_requests.each { |dict| + merge = "#{dict[:title]} [\\##{dict[:number]}](https://github.com/#{@options[:user]}/#{@options[:project]}/pull/#{dict[:number]})\n\n" + log += "- #{merge}" + } + end + end + + if @options[:issues] + # Generate issues: + if issues + issues.each { |dict| + is_bug = false + is_enhancement = false + dict.labels.each { |label| + if label.name == 'bug' + is_bug = true + end + if label.name == 'enhancement' + is_enhancement = true + end + } + + intro = 'Closed issue' + if is_bug + intro = 'Fixed bug' + end + + if is_enhancement + intro = 'Implemented enhancement' + end + + merge = "*#{intro}:* #{dict[:title]} [\\##{dict[:number]}](https://github.com/#{@options[:user]}/#{@options[:project]}/issues/#{dict[:number]})\n\n" + log += "- #{merge}" + } + end + + end + log end @@ -217,8 +279,23 @@ def get_time_of_tag(prev_tag) @tag_times_hash[prev_tag['name']] = Time.parse(time_string) end + def get_all_issues + all_issues = [] + @options[:labels].each { |label| + issues = @github.issues.list user: @options[:user], repo: @options[:project], state: 'closed', filter: 'all', labels: label + all_issues = all_issues.concat(issues.body) + } + if @options[:verbose] + puts "Receive all closed issues with labels #{@options[:labels]}: #{all_issues.count} issues" + end + + all_issues + + end + end if __FILE__ == $0 - ChangelogGenerator.new.compund_changelog + changelog_generator = ChangelogGenerator.new + changelog_generator.compund_changelog end \ No newline at end of file diff --git a/lib/github_changelog_generator/parser.rb b/lib/github_changelog_generator/parser.rb index 0dc882a0d..8a6fa20b4 100644 --- a/lib/github_changelog_generator/parser.rb +++ b/lib/github_changelog_generator/parser.rb @@ -3,7 +3,7 @@ class Parser def self.parse_options - options = {:tag1 => nil, :tag2 => nil, :format => '%d/%m/%y', :output => 'CHANGELOG.md'} + options = {:tag1 => nil, :tag2 => nil, :format => '%d/%m/%y', :output => 'CHANGELOG.md', :labels => %w(bug enhancement), :pulls => true, :issues => true } parser = OptionParser.new { |opts| opts.banner = 'Usage: changelog_generator --user username --project project_name [options]' @@ -23,15 +23,24 @@ def self.parse_options opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v| options[:verbose] = v end - opts.on('-l', '--last-changes', 'Generate log between only last 2 tags') do |last| + opts.on('--[no-]issues', 'Include closed issues to changelog. Default is true') do |v| + options[:issues] = v + end + opts.on('--[no-]pull-requests', 'Include pull-requests to changelog. Default is true') do |v| + options[:pulls] = v + end + opts.on('-l', '--last-changes', 'Generate log between last 2 tags only') do |last| options[:last] = last end opts.on('-f', '--date-format [FORMAT]', 'Date format. Default is %d/%m/%y') do |last| options[:format] = last end - opts.on('-o', '--output [FORMAT]', 'Output file. Default is CHANGELOG.md') do |last| + opts.on('-o', '--output [NAME]', 'Output file. Default is CHANGELOG.md') do |last| options[:output] = last end + opts.on('--labels x,y,z', Array, 'List of labels. Issues with that labels will be included to changelog. Default is \'bug,enhancement\'') do |list| + options[:labels] = list + end } parser.parse!