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 +4 -4
- data/bin/changelogerator +74 -0
- data/lib/changelogerator.rb +93 -62
- metadata +10 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8b7471810cc9cef7c45a8e3e299797131a6535eb3719160b27911f622ed9edc3
|
4
|
+
data.tar.gz: 7ba7b175da8540b9faefba07510736f484380ae698aa910480c69de4647220c5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c1b900314ed34b4b90de73ad40ebc946aa4e60f40fc3ed9801ad840088739b654452fbe226cf9233bcb881cec2bc7e742c431554cbb2b81209decc769bb2acf9
|
7
|
+
data.tar.gz: b413918b6710e7504f7ac1c750a1bdd1c00788f744c3168e25ff0ba85e1b6c13d985d368b3e50da8d872f047c3e072f6a656dbbda69e0e5a3749d2fe973ce02e
|
data/bin/changelogerator
ADDED
@@ -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
|
data/lib/changelogerator.rb
CHANGED
@@ -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 (
|
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 :
|
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
|
-
|
85
|
-
|
86
|
-
@changes.map
|
87
|
-
|
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
|
-
|
94
|
-
nil
|
91
|
+
compute_global_meta
|
95
92
|
end
|
96
93
|
|
97
94
|
def add(change)
|
98
|
-
|
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
|
-
|
109
|
-
|
110
|
-
|
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
|
-
|
113
|
-
change[
|
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
|
156
|
+
commits = @gh.compare(@repo, from, to).commits
|
157
|
+
commits.map do |c|
|
128
158
|
title = c.commit.message.split("\n\n").first
|
129
|
-
|
159
|
+
regex = /.*#([0-9]+).*$/
|
160
|
+
next unless title =~ regex
|
130
161
|
|
131
|
-
title.gsub(
|
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.
|
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:
|
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:
|
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: '
|
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.
|
71
|
+
rubygems_version: 3.2.22
|
68
72
|
signing_key:
|
69
73
|
specification_version: 4
|
70
74
|
summary: Changelog generation/management
|