changelogerator 0.0.14 → 0.9.1

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: 15c0df34a0b84def4982a8245b7d2fea66d52092941ecfcf761b5c55173670d8
4
- data.tar.gz: c196735034e5aedbbff42ef8b8d822c434baed96c518ad6bedc8f6f61f864fbd
3
+ metadata.gz: 8b7471810cc9cef7c45a8e3e299797131a6535eb3719160b27911f622ed9edc3
4
+ data.tar.gz: 7ba7b175da8540b9faefba07510736f484380ae698aa910480c69de4647220c5
5
5
  SHA512:
6
- metadata.gz: bb8aaaa63b3cea0adc294b6f02a8a21cffdd7dc52e9ef0c3cf4ee46ea06e30535229c8b9a738b03369fb8b87775169c29c4bf46580b97ceba786483849711ded
7
- data.tar.gz: 35952f39e680721b3405aed8d7ce30947c6fc92e41d86942a6fc580a3d856af4ee8682aa8d6b56f7a9d903693346ecfd71e086f59fd7f360730a89a1aba15504
6
+ metadata.gz: c1b900314ed34b4b90de73ad40ebc946aa4e60f40fc3ed9801ad840088739b654452fbe226cf9233bcb881cec2bc7e742c431554cbb2b81209decc769bb2acf9
7
+ data.tar.gz: b413918b6710e7504f7ac1c750a1bdd1c00788f744c3168e25ff0ba85e1b6c13d985d368b3e50da8d872f047c3e072f6a656dbbda69e0e5a3749d2fe973ce02e
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # frozen_string_literal: true
4
+
5
+ require 'optparse'
6
+ require_relative '../lib/changelogerator'
7
+ require 'logger'
8
+
9
+ @options = {
10
+ from: nil,
11
+ to: nil
12
+ }
13
+
14
+ logger = Logger.new($stdout)
15
+ logger.level = Logger::WARN
16
+ logger.debug('Starting')
17
+
18
+ OptionParser.new do |opts|
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.
23
+
24
+ Usage:
25
+ changelogerator <repo> [options]'
26
+
27
+ opts.on('-v', '--[no-]verbose', 'Run verbosely') do |v|
28
+ @options[:verbose] = v
29
+ end
30
+
31
+ opts.on('-fFROM', '--from=FROM', 'From Ref.') do |f|
32
+ @options[:from] = f
33
+ end
34
+
35
+ opts.on('-tTO', '--to=TO', 'To Ref.') do |t|
36
+ @options[:to] = t
37
+ end
38
+
39
+ opts.on('-p', '--[no-]prefix', 'Add (or not) a prefix for the repo') do |p|
40
+ @options[:prefix] = p
41
+ end
42
+
43
+ opts.on('-h', '--help', 'Prints this help') do
44
+ puts opts
45
+ exit
46
+ end
47
+ end.parse!
48
+
49
+ @options[:repo] = ARGV[0]
50
+
51
+ def validate
52
+ raise "Missing value for the 'repo' field" unless @options[:repo]
53
+ raise "Missing value for the 'from' field" unless @options[:from]
54
+ raise "Missing value for the 'to' field" unless @options[:to]
55
+
56
+ true
57
+ end
58
+
59
+ exit 1 unless validate
60
+
61
+ logger.debug('Validation passed')
62
+ logger.debug(format(' - repo: %s', @options[:repo]))
63
+ logger.debug(format(' - from: %s', @options[:from]))
64
+ logger.debug(format(' - to: %s', @options[:to]))
65
+
66
+ cl = Changelog.new(
67
+ @options[:repo],
68
+ @options[:from],
69
+ @options[:to],
70
+ token: ENV['GITHUB_TOKEN'],
71
+ prefix: @options[:prefix]
72
+ )
73
+
74
+ puts cl.to_json
@@ -3,52 +3,15 @@
3
3
  # A small wrapper class for more easily generating and manipulating Github/Git
4
4
  # changelogs. Given two different git objects (sha, tag, whatever), it will
5
5
  # find all PRs that made up that diff and store them as a list. Also allows
6
- # for filtering by label, and the importance of that change (priorities), based
6
+ # for filtering by label, and the importance of that change (labels), based
7
7
  # on how we classify the importance of PRs in the paritytech/polkadot project.
8
- # Probably not tremendously useful to other projects.
9
8
  class Changelog
10
9
  require 'octokit'
11
10
  require 'git_diff_parser'
11
+ require 'json'
12
12
 
13
- attr_accessor :changes
14
- attr_reader :priority
15
-
16
- @priorities = [
17
- {
18
- priority: 1,
19
- label: 'C1-low 📌',
20
- text: 'Upgrade priority: **Low** (upgrade at your convenience)'
21
- },
22
- {
23
- priority: 3,
24
- label: 'C3-medium 📣',
25
- text: 'Upgrade priority: **Medium** (timely upgrade recommended)'
26
- },
27
- {
28
- priority: 7,
29
- label: 'C7-high ❗️',
30
- text: 'Upgrade priority:❗ **HIGH** ❗ Please upgrade your node as soon as possible'
31
- },
32
- {
33
- priority: 9,
34
- label: 'C9-critical ‼️',
35
- text: 'Upgrade priority: ❗❗ **URGENT** ❗❗ PLEASE UPGRADE IMMEDIATELY'
36
- }
37
- ]
38
-
39
- class << self
40
- attr_reader :priorities
41
- end
42
-
43
- # Return highest priority from an array of changes (NOT the actual Changelog
44
- # object)
45
- def self.highest_priority_for_changes(changes)
46
- @priorities.find do |p|
47
- p[:priority] == changes.map do |change|
48
- change[:priority][:priority]
49
- end.max
50
- end
51
- end
13
+ attr_accessor :repository, :changes, :meta
14
+ attr_reader :label
52
15
 
53
16
  def self.changes_with_label(changes, label)
54
17
  changes.select do |change|
@@ -56,6 +19,32 @@ class Changelog
56
19
  end
57
20
  end
58
21
 
22
+ # Go through all changes and compute some
23
+ # aggregated values
24
+ def compute_global_meta
25
+ @meta = {}
26
+
27
+ @changes.each do |change|
28
+ # here we remove some of the fields to reduce (considerably) the size
29
+ # of the json output
30
+ change.head = nil
31
+ change.base = nil
32
+ change._links = nil
33
+
34
+ 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
42
+ end
43
+ end
44
+ end
45
+
46
+ # Return the list of all the files in the changeset
47
+ # that also in the given path
59
48
  def self.changes_files_in_paths?(change, paths)
60
49
  changed_files = GitDiffParser.parse(Octokit.get(change.diff_url)).files
61
50
  paths = [paths] unless paths.is_a? Array
@@ -65,6 +54,18 @@ class Changelog
65
54
  nil
66
55
  end
67
56
 
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
+
68
69
  ## End of class methods
69
70
 
70
71
  # github_repo: 'paritytech/polkadot'
@@ -76,44 +77,72 @@ class Changelog
76
77
  # prefix: whether or not to prefix PR numbers with their repo in the changelog
77
78
  def initialize(github_repo, from, to, token: '', prefix: nil)
78
79
  @repo = github_repo
79
- @priorities = self.class.priorities
80
80
  @gh = Octokit::Client.new(
81
81
  access_token: token
82
82
  )
83
+ @repository = @gh.repository(@repo)
83
84
  @prefix = prefix
84
- @changes = prs_from_ids(pr_ids_from_git_diff(from, to)).map(&:to_hash)
85
- # add priority to each change
86
- @changes.map { |c| apply_priority_to_change(c) }
87
- end
88
-
89
- def changes_with_label(label)
90
- self.class.changes_with_label(@changes, label)
91
- end
85
+ ids = pr_ids_from_git_diff(from, to)
86
+ @changes = prs_from_ids(ids)
87
+ @changes.map do |c|
88
+ compute_change_meta(c)
89
+ end
92
90
 
93
- def runtime_changes?
94
- nil
91
+ compute_global_meta
95
92
  end
96
93
 
97
94
  def add(change)
98
- changes.prepend(prettify_title(apply_priority_to_change(change)))
95
+ compute_change_meta(change)
96
+ prettify_title(change)
97
+ changes.prepend(change)
98
+ @meta = compute_global_meta
99
99
  end
100
100
 
101
+ # Add a pull request from id
101
102
  def add_from_id(id)
102
103
  pull = @gh.pull_request(@repo, id)
103
104
  add pull
104
105
  end
105
106
 
107
+ def to_json(*_args)
108
+ opts = {
109
+ array_nl: "\n",
110
+ object_nl: "\n",
111
+ indent: ' ',
112
+ space_before: ' ',
113
+ space: ' '
114
+ }
115
+ obj = @changes
116
+
117
+ commits = {
118
+ meta: @meta,
119
+ repository: @repository.to_h,
120
+ changes: obj.map(&:to_h)
121
+ }
122
+
123
+ JSON.fast_generate(commits, opts)
124
+ end
125
+
106
126
  private
107
127
 
108
- def apply_priority_to_change(change)
109
- @priorities.each do |p|
110
- change[:priority] = p if change[:labels].any? { |l| l[:name] == p[:label] }
128
+ # Compute and attach metadata about one change
129
+ def compute_change_meta(change)
130
+ meta = {}
131
+
132
+ change.labels.each do |label|
133
+ letter, number, text = self.class.get_label_code(label.name)
134
+ next unless letter && number
135
+
136
+ meta[letter] = {
137
+ value: number.to_i,
138
+ text: text
139
+ }
111
140
  end
112
- # Failsafe: add lowest priority if none detected
113
- change[:priority] ||= @priorities[0]
114
- change
141
+
142
+ change['meta'] = meta
115
143
  end
116
144
 
145
+ # Prepend the repo if @prefix is true
117
146
  def prettify_title(pull)
118
147
  pull[:pretty_title] = if @prefix
119
148
  "#{pull[:title]} (#{@repo}##{pull[:number]})"
@@ -124,11 +153,13 @@ class Changelog
124
153
  end
125
154
 
126
155
  def pr_ids_from_git_diff(from, to)
127
- @gh.compare(@repo, from, to).commits.map do |c|
156
+ commits = @gh.compare(@repo, from, to).commits
157
+ commits.map do |c|
128
158
  title = c.commit.message.split("\n\n").first
129
- next unless title =~ /\(#[0-9]+\)$/
159
+ regex = /.*#([0-9]+).*$/
160
+ next unless title =~ regex
130
161
 
131
- title.gsub(/.*#([0-9]+)\)$/, '\1')
162
+ title.gsub(regex, '\1')
132
163
  end.compact.map(&:to_i)
133
164
  end
134
165
 
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.0.14
4
+ version: 0.9.1
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: 2020-10-01 00:00:00.000000000 Z
12
+ date: 2021-11-11 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: git_diff_parser
@@ -38,12 +39,15 @@ 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
- executables: []
45
+ executables:
46
+ - changelogerator
44
47
  extensions: []
45
48
  extra_rdoc_files: []
46
49
  files:
50
+ - bin/changelogerator
47
51
  - lib/changelogerator.rb
48
52
  homepage: https://github.com/s3krit/changelogerator
49
53
  licenses:
@@ -57,14 +61,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
57
61
  requirements:
58
62
  - - ">="
59
63
  - !ruby/object:Gem::Version
60
- version: '0'
64
+ version: '2.7'
61
65
  required_rubygems_version: !ruby/object:Gem::Requirement
62
66
  requirements:
63
67
  - - ">="
64
68
  - !ruby/object:Gem::Version
65
69
  version: '0'
66
70
  requirements: []
67
- rubygems_version: 3.1.2
71
+ rubygems_version: 3.2.22
68
72
  signing_key:
69
73
  specification_version: 4
70
74
  summary: Changelog generation/management