github_changelog_generator 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/bin/github_changelog_generator +5 -0
- data/lib/github_changelog_generator.rb +205 -0
- data/lib/github_changelog_generator/parser.rb +55 -0
- metadata +75 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: f85f1c07a9a8a62875a705a096a6defec31a8e39
|
4
|
+
data.tar.gz: 0f32a943be2acba4387df7016ac10654b1f6976e
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7d10d9c8610a5ce8a27156b6c14f483965c9e4273724a989bc8af1cb6df3e3044a7af50799b2cc92ce82ad281171e6460effc887e204b47ef1f7410a60e1db71
|
7
|
+
data.tar.gz: c804a7f77d45628fe26087db70bc5694af73033c287bac402e28b69be606c82a56a37fe94063960da7636367704152700032c766b0deb531581b567e7708df07
|
@@ -0,0 +1,205 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'github_api'
|
4
|
+
require 'json'
|
5
|
+
require 'httparty'
|
6
|
+
require_relative 'github_changelog_generator/parser'
|
7
|
+
|
8
|
+
|
9
|
+
class ChangelogGenerator
|
10
|
+
|
11
|
+
attr_accessor :options, :all_tags
|
12
|
+
|
13
|
+
def initialize()
|
14
|
+
|
15
|
+
@options = Parser.parse_options
|
16
|
+
if @options[:token]
|
17
|
+
@github = Github.new oauth_token: @options[:token]
|
18
|
+
else
|
19
|
+
@github = Github.new
|
20
|
+
end
|
21
|
+
@all_tags = self.get_all_tags
|
22
|
+
@pull_requests = self.get_all_closed_pull_requests
|
23
|
+
|
24
|
+
@tag_times_hash = {}
|
25
|
+
end
|
26
|
+
|
27
|
+
def print_json(json)
|
28
|
+
puts JSON.pretty_generate(json)
|
29
|
+
end
|
30
|
+
|
31
|
+
def exec_command(cmd)
|
32
|
+
exec_cmd = "cd #{$project_path} && #{cmd}"
|
33
|
+
%x[#{exec_cmd}]
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
def get_all_closed_pull_requests
|
38
|
+
|
39
|
+
|
40
|
+
issues = @github.pull_requests.list @options[:user], @options[:project], :state => 'closed'
|
41
|
+
json = issues.body
|
42
|
+
|
43
|
+
if @options[:verbose]
|
44
|
+
puts 'Receive all pull requests'
|
45
|
+
end
|
46
|
+
|
47
|
+
json
|
48
|
+
|
49
|
+
end
|
50
|
+
|
51
|
+
def compund_changelog
|
52
|
+
if @options[:verbose]
|
53
|
+
puts 'Generating changelog:'
|
54
|
+
end
|
55
|
+
|
56
|
+
log = "# Changelog\n\n"
|
57
|
+
|
58
|
+
if @options[:last]
|
59
|
+
log += self.generate_log_between_tags(self.all_tags[0], self.all_tags[1])
|
60
|
+
elsif @options[:tag1] && @options[:tag2]
|
61
|
+
|
62
|
+
tag1 = @options[:tag1]
|
63
|
+
tag2 = @options[:tag2]
|
64
|
+
tags_strings = []
|
65
|
+
self.all_tags.each { |x| tags_strings.push(x['name'])}
|
66
|
+
|
67
|
+
if tags_strings.include?(tag1)
|
68
|
+
if tags_strings.include?(tag2)
|
69
|
+
hash = Hash[tags_strings.map.with_index.to_a]
|
70
|
+
index1 = hash[tag1]
|
71
|
+
index2 = hash[tag2]
|
72
|
+
log += self.generate_log_between_tags(self.all_tags[index1], self.all_tags[index2])
|
73
|
+
else
|
74
|
+
puts "Can't find tag #{tag2} -> exit"
|
75
|
+
exit
|
76
|
+
end
|
77
|
+
else
|
78
|
+
puts "Can't find tag #{tag1} -> exit"
|
79
|
+
exit
|
80
|
+
end
|
81
|
+
else
|
82
|
+
log += self.generate_log_for_all_tags
|
83
|
+
end
|
84
|
+
|
85
|
+
|
86
|
+
if @options[:verbose]
|
87
|
+
puts log
|
88
|
+
end
|
89
|
+
|
90
|
+
output_filename = "#{@options[:project]}_changelog.md"
|
91
|
+
File.open(output_filename, 'w') { |file| file.write(log) }
|
92
|
+
|
93
|
+
puts "Done! Generated log placed in #{output_filename}"
|
94
|
+
|
95
|
+
end
|
96
|
+
|
97
|
+
def generate_log_for_all_tags
|
98
|
+
log = ''
|
99
|
+
for index in 1 ... self.all_tags.size
|
100
|
+
log += self.generate_log_between_tags(self.all_tags[index-1], self.all_tags[index])
|
101
|
+
end
|
102
|
+
|
103
|
+
log
|
104
|
+
end
|
105
|
+
|
106
|
+
def is_megred(number)
|
107
|
+
@github.pull_requests.merged? @options[:user], @options[:project], number
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_all_merged_pull_requests
|
111
|
+
json = self.get_all_closed_pull_requests
|
112
|
+
puts 'Check if the requests is merged... (it can take a while)'
|
113
|
+
|
114
|
+
json.delete_if { |req|
|
115
|
+
merged = self.is_megred(req[:number])
|
116
|
+
if @options[:verbose]
|
117
|
+
puts "##{req[:number]} #{merged ? 'merged' : 'not merged'}"
|
118
|
+
end
|
119
|
+
!merged
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
def get_all_tags
|
124
|
+
|
125
|
+
url = "https://api.github.com/repos/#{@options[:user]}/#{@options[:project]}/tags"
|
126
|
+
|
127
|
+
if @options[:verbose]
|
128
|
+
puts "Receive tags for repo #{url}"
|
129
|
+
end
|
130
|
+
|
131
|
+
response = HTTParty.get(url,
|
132
|
+
:headers => {'Authorization' => 'token 8587bb22f6bf125454768a4a19dbcc774ea68d48',
|
133
|
+
'User-Agent' => 'Changelog-Generator'})
|
134
|
+
|
135
|
+
json_parse = JSON.parse(response.body)
|
136
|
+
|
137
|
+
if @options[:verbose]
|
138
|
+
puts "Found #{json_parse.count} tags"
|
139
|
+
end
|
140
|
+
|
141
|
+
json_parse
|
142
|
+
end
|
143
|
+
|
144
|
+
def generate_log_between_tags(since_tag, till_tag)
|
145
|
+
since_tag_time = self.get_time_of_tag(since_tag)
|
146
|
+
till_tag_time = self.get_time_of_tag(till_tag)
|
147
|
+
|
148
|
+
# if we mix up tags order - lits fix it!
|
149
|
+
if since_tag_time > till_tag_time
|
150
|
+
since_tag, till_tag = till_tag, since_tag
|
151
|
+
since_tag_time, till_tag_time = till_tag_time, since_tag_time
|
152
|
+
end
|
153
|
+
|
154
|
+
till_tag_name = till_tag['name']
|
155
|
+
|
156
|
+
pull_requests = Array.new(@pull_requests)
|
157
|
+
|
158
|
+
pull_requests.delete_if { |req|
|
159
|
+
t = Time.parse(req[:closed_at]).utc
|
160
|
+
true_classor_false_class = t > since_tag_time
|
161
|
+
classor_false_class = t < till_tag_time
|
162
|
+
|
163
|
+
in_range = (true_classor_false_class) && (classor_false_class)
|
164
|
+
!in_range
|
165
|
+
}
|
166
|
+
|
167
|
+
self.create_log(pull_requests, till_tag_name, till_tag_time)
|
168
|
+
end
|
169
|
+
|
170
|
+
def create_log(pull_requests, tag_name, tag_time)
|
171
|
+
|
172
|
+
trimmed_tag = tag_name.tr('v', '')
|
173
|
+
log = "## [#{trimmed_tag}] (https://github.com/#{@options[:user]}/#{@options[:project]}/tree/#{tag_name})\n"
|
174
|
+
|
175
|
+
time_string = tag_time.strftime @options[:format]
|
176
|
+
log += "#### #{time_string}\n"
|
177
|
+
|
178
|
+
pull_requests.each { |dict|
|
179
|
+
merge = "#{dict[:title]} [\\##{dict[:number]}](https://github.com/#{@options[:user]}/#{@options[:project]}/pull/#{dict[:number]})\n\n"
|
180
|
+
log += "- #{merge}"
|
181
|
+
}
|
182
|
+
log
|
183
|
+
end
|
184
|
+
|
185
|
+
def get_time_of_tag(prev_tag)
|
186
|
+
|
187
|
+
if @tag_times_hash[prev_tag['name']]
|
188
|
+
return @tag_times_hash[prev_tag['name']]
|
189
|
+
end
|
190
|
+
|
191
|
+
if @options[:verbose]
|
192
|
+
puts "Get time for tag #{prev_tag['name']}"
|
193
|
+
end
|
194
|
+
|
195
|
+
github_git_data_commits_get = @github.git_data.commits.get @options[:user], @options[:project], prev_tag['commit']['sha']
|
196
|
+
time_string = github_git_data_commits_get['committer']['date']
|
197
|
+
Time.parse(time_string)
|
198
|
+
@tag_times_hash[prev_tag['name']] = Time.parse(time_string)
|
199
|
+
end
|
200
|
+
|
201
|
+
end
|
202
|
+
|
203
|
+
if __FILE__ == $0
|
204
|
+
ChangelogGenerator.new.compund_changelog
|
205
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
class Parser
|
5
|
+
def self.parse_options
|
6
|
+
options = {:tag1 => nil, :tag2 => nil, :format => '%d/%m/%y'}
|
7
|
+
|
8
|
+
parser = OptionParser.new { |opts|
|
9
|
+
opts.banner = 'Usage: changelog_generator.rb -u user_name -p project_name [-t 16-digit-GitHubToken] [options]'
|
10
|
+
opts.on('-u', '--user [USER]', 'your username on GitHub') do |last|
|
11
|
+
options[:user] = last
|
12
|
+
end
|
13
|
+
opts.on('-p', '--project [PROJECT]', 'name of project on GitHub') do |last|
|
14
|
+
options[:project] = last
|
15
|
+
end
|
16
|
+
opts.on('-t', '--token [TOKEN]', 'To make more than 50 requests this app required your OAuth token for GitHub. You can generate it on https://github.com/settings/applications') do |last|
|
17
|
+
options[:token] = last
|
18
|
+
end
|
19
|
+
opts.on('-h', '--help', 'Displays Help') do
|
20
|
+
puts opts
|
21
|
+
exit
|
22
|
+
end
|
23
|
+
opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
|
24
|
+
options[:verbose] = v
|
25
|
+
end
|
26
|
+
opts.on('-l', '--last-changes', 'generate log between last 2 tags') do |last|
|
27
|
+
options[:last] = last
|
28
|
+
end
|
29
|
+
opts.on('-f', '--date-format [FORMAT]', 'date format. default is %d/%m/%y') do |last|
|
30
|
+
options[:format] = last
|
31
|
+
end
|
32
|
+
}
|
33
|
+
|
34
|
+
parser.parse!
|
35
|
+
|
36
|
+
#udefined case with 1 parameter:
|
37
|
+
if ARGV[0] && !ARGV[1]
|
38
|
+
puts parser.banner
|
39
|
+
exit
|
40
|
+
end
|
41
|
+
|
42
|
+
if !options[:user] || !options[:project]
|
43
|
+
puts parser.banner
|
44
|
+
exit
|
45
|
+
end
|
46
|
+
|
47
|
+
if ARGV[1]
|
48
|
+
options[:tag1] = ARGV[0]
|
49
|
+
options[:tag2] = ARGV[1]
|
50
|
+
|
51
|
+
end
|
52
|
+
|
53
|
+
options
|
54
|
+
end
|
55
|
+
end
|
metadata
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: github_changelog_generator
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Petr Korolev
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2014-10-10 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: httparty
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0.6'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0.6'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: github_api
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0.12'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0.12'
|
41
|
+
description: Script, that automatically generate change-log from your tags and pull-requests
|
42
|
+
email: sky4winder+github_changelog_generator@gmail.com
|
43
|
+
executables:
|
44
|
+
- github_changelog_generator
|
45
|
+
extensions: []
|
46
|
+
extra_rdoc_files: []
|
47
|
+
files:
|
48
|
+
- bin/github_changelog_generator
|
49
|
+
- lib/github_changelog_generator.rb
|
50
|
+
- lib/github_changelog_generator/parser.rb
|
51
|
+
homepage: https://github.com/skywinder/Github-Changelog-Generator
|
52
|
+
licenses:
|
53
|
+
- MIT
|
54
|
+
metadata: {}
|
55
|
+
post_install_message:
|
56
|
+
rdoc_options: []
|
57
|
+
require_paths:
|
58
|
+
- lib
|
59
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: '0'
|
64
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
requirements: []
|
70
|
+
rubyforge_project:
|
71
|
+
rubygems_version: 2.2.2
|
72
|
+
signing_key:
|
73
|
+
specification_version: 4
|
74
|
+
summary: Script, that automatically generate change-log from your tags and pull-requests.
|
75
|
+
test_files: []
|