changelogerator 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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