changelogerator 0.9.1 → 0.10.1

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: 8b7471810cc9cef7c45a8e3e299797131a6535eb3719160b27911f622ed9edc3
4
- data.tar.gz: 7ba7b175da8540b9faefba07510736f484380ae698aa910480c69de4647220c5
3
+ metadata.gz: cf5410924ba8561481f9ce9130a067d35ce76d42c7b78d002df2059c5b644c6a
4
+ data.tar.gz: 8567d1755cfa533951d8fdc9567535dd05ca764659c38ee78e21a59783248b79
5
5
  SHA512:
6
- metadata.gz: c1b900314ed34b4b90de73ad40ebc946aa4e60f40fc3ed9801ad840088739b654452fbe226cf9233bcb881cec2bc7e742c431554cbb2b81209decc769bb2acf9
7
- data.tar.gz: b413918b6710e7504f7ac1c750a1bdd1c00788f744c3168e25ff0ba85e1b6c13d985d368b3e50da8d872f047c3e072f6a656dbbda69e0e5a3749d2fe973ce02e
6
+ metadata.gz: a10fa4370f7fac47801c47896d3a6367f07fd4855c91b032de7798adad612cf164f19a72f0acd9f3185e3944c64236077548d93689116b96ef8c60969b832892
7
+ data.tar.gz: 4e72e0a82a7231804f6cb99280b12dadef9b210abca249287882fb80ae01ad3b21fbde3c1e1df2c2dd00ef76c9b7e2209c1f061eb6f6dd2aaecc894bbeae6fa7
data/bin/changelogerator CHANGED
@@ -44,6 +44,13 @@ of the changes between 2 references on your Github project.
44
44
  puts opts
45
45
  exit
46
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
47
54
  end.parse!
48
55
 
49
56
  @options[:repo] = ARGV[0]
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'rake'
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = 'changelogerator'
7
+ s.version = '0.10.1'
8
+ s.summary = 'Changelog generation/management'
9
+ s.authors = ['Martin Pugh', 'Wilfried Kopp']
10
+ s.files = FileList['lib/**/*.rb', 'bin/changelogerator', 'changelogerator.gemspec']
11
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
12
+ s.executables = s.files.grep(%r{^bin/}) { |f| File.basename(f) }
13
+ s.description = 'A utility to fetch the data required to generate a changelog based on change in Github and formatted labels.'
14
+ s.require_paths = ['lib']
15
+ s.license = 'AGPL-3.0'
16
+ s.homepage = 'https://github.com/s3krit/changelogerator'
17
+ s.add_runtime_dependency 'git_diff_parser', '~> 3'
18
+ s.add_runtime_dependency 'octokit', '~> 4'
19
+ s.required_ruby_version = '>= 2.7'
20
+ s.metadata = { 'rubygems_mfa_required' => 'true' }
21
+ end
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,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'label'
4
+ require 'change'
5
+
3
6
  # A small wrapper class for more easily generating and manipulating Github/Git
4
7
  # changelogs. Given two different git objects (sha, tag, whatever), it will
5
8
  # find all PRs that made up that diff and store them as a list. Also allows
@@ -32,13 +35,19 @@ class Changelog
32
35
  change._links = nil
33
36
 
34
37
  change[:meta].each_key do |meta_key|
35
- current = change[:meta][meta_key]
36
-
37
- meta[meta_key] = {} unless meta[meta_key]
38
- meta[meta_key][:min] = current[:value] if !meta[meta_key][:min] || current[:value] < meta[meta_key][:min]
39
- meta[meta_key][:max] = current[:value] if !meta[meta_key][:max] || current[:value] > meta[meta_key][:max]
40
- meta[meta_key][:count] = 0 unless meta[meta_key][:count]
41
- 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
42
51
  end
43
52
  end
44
53
  end
@@ -54,18 +63,6 @@ class Changelog
54
63
  nil
55
64
  end
56
65
 
57
- # Return the label code for a change
58
- # if the label name matches the expected pattern.
59
- # nil otherwise.
60
- def self.get_label_code(name)
61
- m = match = name.match(/^([a-z])(\d+)-(.*)$/i)
62
- if m
63
- letter, number, text = match.captures
64
- return [letter, number, text]
65
- end
66
- nil
67
- end
68
-
69
66
  ## End of class methods
70
67
 
71
68
  # github_repo: 'paritytech/polkadot'
@@ -83,16 +80,17 @@ class Changelog
83
80
  @repository = @gh.repository(@repo)
84
81
  @prefix = prefix
85
82
  ids = pr_ids_from_git_diff(from, to)
83
+ # The following takes very long time
86
84
  @changes = prs_from_ids(ids)
87
85
  @changes.map do |c|
88
- compute_change_meta(c)
86
+ self.class.compute_change_meta(c)
89
87
  end
90
88
 
91
89
  compute_global_meta
92
90
  end
93
91
 
94
92
  def add(change)
95
- compute_change_meta(change)
93
+ self.class.compute_change_meta(change)
96
94
  prettify_title(change)
97
95
  changes.prepend(change)
98
96
  @meta = compute_global_meta
@@ -123,25 +121,41 @@ class Changelog
123
121
  JSON.fast_generate(commits, opts)
124
122
  end
125
123
 
126
- private
127
-
128
124
  # Compute and attach metadata about one change
129
- def compute_change_meta(change)
125
+ def self.compute_change_meta(change)
130
126
  meta = {}
131
127
 
132
- change.labels.each do |label|
133
- letter, number, text = self.class.get_label_code(label.name)
134
- 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
135
147
 
136
- meta[letter] = {
137
- value: number.to_i,
138
- text: text
148
+ meta[label.letter]["#{label.letter}#{label.number}"] = {
149
+ 'value' => label.number,
150
+ 'text' => label.description
139
151
  }
140
152
  end
141
153
 
142
154
  change['meta'] = meta
143
155
  end
144
156
 
157
+ private
158
+
145
159
  # Prepend the repo if @prefix is true
146
160
  def prettify_title(pull)
147
161
  pull[:pretty_title] = if @prefix
@@ -163,6 +177,7 @@ class Changelog
163
177
  end.compact.map(&:to_i)
164
178
  end
165
179
 
180
+ # TODO: See if we can make this quicker
166
181
  def prs_from_ids(ids)
167
182
  batch_size = 100
168
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,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: changelogerator
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.1
4
+ version: 0.10.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Martin Pugh
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2021-11-11 00:00:00.000000000 Z
12
+ date: 2023-02-15 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: git_diff_parser
@@ -48,11 +48,15 @@ extensions: []
48
48
  extra_rdoc_files: []
49
49
  files:
50
50
  - bin/changelogerator
51
+ - changelogerator.gemspec
52
+ - lib/change.rb
51
53
  - lib/changelogerator.rb
54
+ - lib/label.rb
52
55
  homepage: https://github.com/s3krit/changelogerator
53
56
  licenses:
54
57
  - AGPL-3.0
55
- metadata: {}
58
+ metadata:
59
+ rubygems_mfa_required: 'true'
56
60
  post_install_message:
57
61
  rdoc_options: []
58
62
  require_paths:
@@ -68,7 +72,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
68
72
  - !ruby/object:Gem::Version
69
73
  version: '0'
70
74
  requirements: []
71
- rubygems_version: 3.2.22
75
+ rubygems_version: 3.4.6
72
76
  signing_key:
73
77
  specification_version: 4
74
78
  summary: Changelog generation/management