changelogerator 0.9.0 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b292e9657833099e9623ee12bc856d1212fe047a0fc3da90ef7192ab305c2f6d
4
- data.tar.gz: 24fab3a02631ae80b4ab8b810b8aee5b9fd9340280bfce389247dfb19d215ef6
3
+ metadata.gz: a765967f91e3865aebe4990566bd73cdd310fde94ceade67ca4523486712752c
4
+ data.tar.gz: 722f348d22b0a44270a6289f1bcf9b48ecb4b5197e6b6f61eddd552058572ea5
5
5
  SHA512:
6
- metadata.gz: 28564cd68a1ebd4d4917e8f43339551a144edac68fa242ce1b3248e0f123e9835040d8c267e51755bfb0a3e09a26fb22214605ace98212b9bdc573b54c0265a0
7
- data.tar.gz: b9c23322c65362bdee0f6535982d4c349bde39092f99457901bebe48d5ba9d77e5484faab552ed81a5f786976024dc68f600eeaa85a34a578a50df6ec560f7dd
6
+ metadata.gz: 8331c26720ae5168575df385006c13d06dcf592b0250d97bd9d846d8f3cb697a5b82ddbf198fe180422d6e54dc5b05b0cba5a193c16cfc75bcf1849179d553ac
7
+ data.tar.gz: 9e7b6297c51b47965b103d5ba378a0cdbed04d1fe9cfa7f9190ed79f3d98a538945144bb75ffa78ddf1d71e276dd156f9fd455efb6ab08023e0daf0e7401ac1a
data/bin/changelogerator CHANGED
@@ -16,12 +16,13 @@ logger.level = Logger::WARN
16
16
  logger.debug('Starting')
17
17
 
18
18
  OptionParser.new do |opts|
19
- opts.banner = "
20
- Changelogerator helps you generate a template friendly context made of the changes
21
- between 2 references on your Github project.
19
+ opts.banner = 'Changelogerator
20
+
21
+ This utility helps generate a template friendly context made
22
+ of the changes between 2 references on your Github project.
22
23
 
23
24
  Usage:
24
- changelogerator <repo> [options]"
25
+ changelogerator <repo> [options]'
25
26
 
26
27
  opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
27
28
  @options[:verbose] = v
@@ -43,6 +44,13 @@ OptionParser.new do |opts|
43
44
  puts opts
44
45
  exit
45
46
  end
47
+
48
+ opts.on('-V', '--version', 'Show the version') do
49
+ gemspec = "#{__dir__}/../changelogerator.gemspec"
50
+ gem = Gem::Specification.load(gemspec)
51
+ puts format('%<n>s v%<v>s', { v: gem.version, n: gem.name })
52
+ exit
53
+ end
46
54
  end.parse!
47
55
 
48
56
  @options[:repo] = ARGV[0]
data/lib/change.rb ADDED
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'label'
4
+
5
+ ### A class describe one change that can potentially have several labels
6
+ class Change
7
+ attr_reader :labels
8
+
9
+ def initialize(labels)
10
+ # Below we test if we got the full data from Octokit or
11
+ # only some fake data (label names only) from our tests.
12
+ @labels = labels.map do |label|
13
+ if label.respond_to?(:name)
14
+ from_octokit(label)
15
+ else
16
+ from_str(label)
17
+ end
18
+ end
19
+
20
+ @extra = {}
21
+ end
22
+
23
+ def []=(key, value)
24
+ @extra[key] = value
25
+ end
26
+
27
+ def meta
28
+ @extra['meta']
29
+ end
30
+
31
+ private
32
+
33
+ def from_octokit(label)
34
+ Label.new(label.name)
35
+ end
36
+
37
+ def from_str(label_name)
38
+ Label.new(label_name)
39
+ end
40
+ end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'pry'
3
+ require 'label'
4
+ require 'change'
4
5
 
5
6
  # A small wrapper class for more easily generating and manipulating Github/Git
6
7
  # changelogs. Given two different git objects (sha, tag, whatever), it will
@@ -34,13 +35,19 @@ class Changelog
34
35
  change._links = nil
35
36
 
36
37
  change[:meta].each_key do |meta_key|
37
- current = change[:meta][meta_key]
38
-
39
- meta[meta_key] = {} unless meta[meta_key]
40
- meta[meta_key][:min] = current[:value] if !meta[meta_key][:min] || current[:value] < meta[meta_key][:min]
41
- meta[meta_key][:max] = current[:value] if !meta[meta_key][:max] || current[:value] > meta[meta_key][:max]
42
- meta[meta_key][:count] = 0 unless meta[meta_key][:count]
43
- meta[meta_key][:count] += 1
38
+ aggregate = change[:meta][meta_key]['agg']
39
+
40
+ if meta[meta_key]
41
+ meta[meta_key][:min] = aggregate['min'] if aggregate['min'] < meta[meta_key][:min]
42
+ meta[meta_key][:max] = aggregate['max'] if aggregate['max'] > meta[meta_key][:max]
43
+ meta[meta_key][:count] += aggregate['count']
44
+ else
45
+ meta[meta_key] = {
46
+ min: aggregate['min'],
47
+ max: aggregate['max'],
48
+ count: aggregate['count']
49
+ }
50
+ end
44
51
  end
45
52
  end
46
53
  end
@@ -56,18 +63,6 @@ class Changelog
56
63
  nil
57
64
  end
58
65
 
59
- # Return the label code for a change
60
- # if the label name matches the expected pattern.
61
- # nil otherwise.
62
- def self.get_label_code(name)
63
- m = match = name.match(/^([a-z])(\d+)-(.*)$/i)
64
- if m
65
- letter, number, text = match.captures
66
- return [letter, number, text]
67
- end
68
- nil
69
- end
70
-
71
66
  ## End of class methods
72
67
 
73
68
  # github_repo: 'paritytech/polkadot'
@@ -84,16 +79,18 @@ class Changelog
84
79
  )
85
80
  @repository = @gh.repository(@repo)
86
81
  @prefix = prefix
87
- @changes = prs_from_ids(pr_ids_from_git_diff(from, to))
82
+ ids = pr_ids_from_git_diff(from, to)
83
+ # The following takes very long time
84
+ @changes = prs_from_ids(ids)
88
85
  @changes.map do |c|
89
- compute_change_meta(c)
86
+ self.class.compute_change_meta(c)
90
87
  end
91
88
 
92
89
  compute_global_meta
93
90
  end
94
91
 
95
92
  def add(change)
96
- compute_change_meta(change)
93
+ self.class.compute_change_meta(change)
97
94
  prettify_title(change)
98
95
  changes.prepend(change)
99
96
  @meta = compute_global_meta
@@ -124,25 +121,41 @@ class Changelog
124
121
  JSON.fast_generate(commits, opts)
125
122
  end
126
123
 
127
- private
128
-
129
124
  # Compute and attach metadata about one change
130
- def compute_change_meta(change)
125
+ def self.compute_change_meta(change)
131
126
  meta = {}
132
127
 
133
- change.labels.each do |label|
134
- letter, number, text = self.class.get_label_code(label.name)
135
- next unless letter && number
128
+ change.labels.each do |lbl|
129
+ label = Label.new(lbl.name)
130
+
131
+ next unless label
132
+
133
+ if meta.key?(label.letter)
134
+ aggregate = meta[label.letter]['agg']
135
+ aggregate['max'] = label.number if label.number > aggregate['max']
136
+ aggregate['min'] = label.number if label.number < aggregate['min']
137
+ aggregate['count'] += 1
138
+ else
139
+ meta[label.letter] = {
140
+ 'agg' => {
141
+ 'count' => 1,
142
+ 'max' => label.number,
143
+ 'min' => label.number
144
+ }
145
+ }
146
+ end
136
147
 
137
- meta[letter] = {
138
- value: number.to_i,
139
- text: text
148
+ meta[label.letter]["#{label.letter}#{label.number}"] = {
149
+ 'value' => label.number,
150
+ 'text' => label.description
140
151
  }
141
152
  end
142
153
 
143
154
  change['meta'] = meta
144
155
  end
145
156
 
157
+ private
158
+
146
159
  # Prepend the repo if @prefix is true
147
160
  def prettify_title(pull)
148
161
  pull[:pretty_title] = if @prefix
@@ -154,14 +167,17 @@ class Changelog
154
167
  end
155
168
 
156
169
  def pr_ids_from_git_diff(from, to)
157
- @gh.compare(@repo, from, to).commits.map do |c|
170
+ commits = @gh.compare(@repo, from, to).commits
171
+ commits.map do |c|
158
172
  title = c.commit.message.split("\n\n").first
159
- next unless title =~ /\(#[0-9]+\)$/
173
+ regex = /.*#([0-9]+).*$/
174
+ next unless title =~ regex
160
175
 
161
- title.gsub(/.*#([0-9]+)\)$/, '\1')
176
+ title.gsub(regex, '\1')
162
177
  end.compact.map(&:to_i)
163
178
  end
164
179
 
180
+ # TODO: See if we can make this quicker
165
181
  def prs_from_ids(ids)
166
182
  batch_size = 100
167
183
  prs = []
data/lib/label.rb ADDED
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ ### Label = Letter + Number [+ Description]
4
+ class Label
5
+ attr_accessor :letter, :number, :description
6
+
7
+ # Return the label letter for a change if the label name matches the expected pattern.
8
+ # nil otherwise.
9
+ def parse(label)
10
+ m = match = label.match(/^([a-z])(\d+)\s*-?\s*(.*)$/i)
11
+ return nil unless m
12
+
13
+ letter, digits, text = match.captures
14
+ number = digits.to_i
15
+ [letter, number, text]
16
+ end
17
+
18
+ def initialize(input)
19
+ raise InvalidInput, 'Invalid, it must be a non-empty string' unless input
20
+
21
+ p = parse(input)
22
+ raise InvalidLabel, format('Invalid label "%<input>s"', { input: input }) unless p
23
+
24
+ @letter = p[0].upcase
25
+ @number = p[1]
26
+ @description = p[2] unless p[2].empty?
27
+ end
28
+
29
+ ### Implemented for compatibility reasons
30
+ def name
31
+ to_str
32
+ end
33
+
34
+ def to_str
35
+ format('%<l>s%<n>d - %<d>s', { l: @letter, n: @number, d: @description })
36
+ end
37
+ end
38
+
39
+ class InvalidLabel < StandardError; end
40
+
41
+ class InvalidInput < StandardError; end
metadata CHANGED
@@ -1,14 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: changelogerator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.0
4
+ version: 0.10.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Pugh
8
+ - Wilfried Kopp
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2021-11-09 00:00:00.000000000 Z
12
+ date: 2023-02-15 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: git_diff_parser
@@ -38,7 +39,8 @@ dependencies:
38
39
  - - "~>"
39
40
  - !ruby/object:Gem::Version
40
41
  version: '4'
41
- description: Simple helper class for paritytech/polkadot changelogs
42
+ description: A utility to fetch the data required to generate a changelog based on
43
+ change in Github and formatted labels.
42
44
  email:
43
45
  executables:
44
46
  - changelogerator
@@ -46,11 +48,14 @@ extensions: []
46
48
  extra_rdoc_files: []
47
49
  files:
48
50
  - bin/changelogerator
51
+ - lib/change.rb
49
52
  - lib/changelogerator.rb
53
+ - lib/label.rb
50
54
  homepage: https://github.com/s3krit/changelogerator
51
55
  licenses:
52
56
  - AGPL-3.0
53
- metadata: {}
57
+ metadata:
58
+ rubygems_mfa_required: 'true'
54
59
  post_install_message:
55
60
  rdoc_options: []
56
61
  require_paths:
@@ -66,7 +71,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
66
71
  - !ruby/object:Gem::Version
67
72
  version: '0'
68
73
  requirements: []
69
- rubygems_version: 3.2.22
74
+ rubygems_version: 3.2.33
70
75
  signing_key:
71
76
  specification_version: 4
72
77
  summary: Changelog generation/management