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!
Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.
Alternative Proxies: