maintainers 0.1.2 → 0.2.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 +4 -4
- data/CHANGELOG +10 -1
- data/MAINTAINERS +2 -1
- data/MAINTAINERS-example +1 -0
- data/MAINTAINERS-unmaintained_example +2 -1
- data/lib/maintainers/cli.rb +54 -18
- data/lib/maintainers/runner.rb +110 -3
- data/lib/maintainers/version.rb +1 -1
- data/maintainers.gemspec +1 -0
- metadata +16 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 637a6814e58b1d5692780afee0338f597a9e334f
|
4
|
+
data.tar.gz: 310211fbde7e866fc7ca8e0843705fe1449e083d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 5bff305dcea9ef041947ab5c2fd7de7e2a4082498d258cc9d4ed2e12de22feca265870ad1f142948d77c009abbd628ed056e2af0ffb50de77b0009f43f380ddb
|
7
|
+
data.tar.gz: ff073623557c64dd1c115f43e6f25213f3b77798bdefd2726392b56d832a65d136d607bbc99d236dfcd3e9cafcc0fdb7562984c7b43ac47d514aec90ced3cc21
|
data/CHANGELOG
CHANGED
@@ -6,6 +6,14 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
6
6
|
|
7
7
|
## [Unreleased]
|
8
8
|
|
9
|
+
## [0.2.0] - 2016-09-05
|
10
|
+
### Added
|
11
|
+
- Add a 'validate' subcommand
|
12
|
+
- Add a 'list' subcommand
|
13
|
+
- Add a 'report' subcommand
|
14
|
+
- Add half-decent usage
|
15
|
+
- Add an optional 'file_format' field referring back to this repo
|
16
|
+
|
9
17
|
## [0.1.2] - 2016-09-02
|
10
18
|
### Fixed
|
11
19
|
- Fixed (for realz) schema file reference
|
@@ -19,6 +27,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
|
|
19
27
|
### Added
|
20
28
|
- Initial support for a json format for MAINTAINERS
|
21
29
|
|
22
|
-
[Unreleased]: https://github.com/puppetlabs/maintainers/compare/0.
|
30
|
+
[Unreleased]: https://github.com/puppetlabs/maintainers/compare/0.2.0...HEAD
|
31
|
+
[0.2.0]: https://github.com/puppetlabs/maintainers/compare/0.1.2...0.2.0
|
23
32
|
[0.1.2]: https://github.com/puppetlabs/maintainers/compare/0.1.1...0.1.2
|
24
33
|
[0.1.1]: https://github.com/puppetlabs/maintainers/compare/0.1.0...0.1.1
|
data/MAINTAINERS
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"version": 1,
|
3
|
+
"file_format": "This MAINTAINERS file format is described at https://github.com/puppetlabs/maintainers",
|
3
4
|
"issues": "https://github.com/puppetlabs/maintainers/issues",
|
4
5
|
"people": [
|
5
6
|
{
|
@@ -8,4 +9,4 @@
|
|
8
9
|
"name": "Kylo Ginsberg"
|
9
10
|
}
|
10
11
|
]
|
11
|
-
}
|
12
|
+
}
|
data/MAINTAINERS-example
CHANGED
data/lib/maintainers/cli.rb
CHANGED
@@ -13,20 +13,57 @@ module Maintainers
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def usage
|
16
|
-
|
16
|
+
usage = <<USAGE
|
17
|
+
usage: maintainers <command> [<args>]
|
18
|
+
|
19
|
+
See below for subcommands. All operate on a file called 'MAINTAINERS'
|
20
|
+
in the current working directory, except for 'report' which looks for
|
21
|
+
that file throughout a github organization.
|
22
|
+
|
23
|
+
create --issues <issues text> [--unmaintained]
|
24
|
+
|
25
|
+
Creates a MAINTAINERS file scaffold (but with no people yet).
|
26
|
+
- An 'issues' string is required - typically this is the
|
27
|
+
URL at which to file issues, but knock yourself out.
|
28
|
+
- An 'unmaintained' flag is optional - this make explicit
|
29
|
+
that a repo is not maintained.
|
30
|
+
|
31
|
+
add --github <github id> [--email <email address] [--name <street name>]
|
32
|
+
|
33
|
+
Add a maintainer to the MAINTAINERS file. This can also be used to update
|
34
|
+
a maintainer (e.g. adding an 'email' or 'name'): if the specified 'github' id
|
35
|
+
is already in the MAINTAINERS file, the new fields will be merged with
|
36
|
+
the exiting ones.
|
37
|
+
- A 'github' id is required.
|
38
|
+
- An 'email' address is optional.
|
39
|
+
- A 'name' is optional.
|
40
|
+
|
41
|
+
remove --github <github id>
|
42
|
+
|
43
|
+
Remove a maintainer from the MAINTAINERS file.
|
44
|
+
- A 'github' id is required.
|
45
|
+
|
46
|
+
list
|
47
|
+
|
48
|
+
List the maintainers in a tabular form.
|
49
|
+
|
50
|
+
validate
|
51
|
+
|
52
|
+
Validate that the MAINTAINERS file can be read. This can
|
53
|
+
be useful if you hand-edit the file but want to double-check
|
54
|
+
that it is still machine readable.
|
55
|
+
|
56
|
+
report
|
57
|
+
|
58
|
+
Report on maintainers throughout a github organization.
|
59
|
+
Note: for the report to include private repos, generate a github
|
60
|
+
token with full control of private repositories, and then
|
61
|
+
set the environment variable GITHUB_TOKEN to that token.
|
62
|
+
USAGE
|
63
|
+
puts usage
|
17
64
|
exit 1
|
18
65
|
end
|
19
66
|
|
20
|
-
SUBCOMMANDS_WE_LOVE = [
|
21
|
-
"create",
|
22
|
-
"add",
|
23
|
-
"remove",
|
24
|
-
"list",
|
25
|
-
"report",
|
26
|
-
"help",
|
27
|
-
"--help",
|
28
|
-
]
|
29
|
-
|
30
67
|
# @return [Hash] Return an options hash
|
31
68
|
def parse(args)
|
32
69
|
|
@@ -54,19 +91,18 @@ module Maintainers
|
|
54
91
|
end,
|
55
92
|
'list' => OptionParser.new do |opts|
|
56
93
|
end,
|
94
|
+
'validate' => OptionParser.new do |opts|
|
95
|
+
end,
|
96
|
+
'report' => OptionParser.new do |opts|
|
97
|
+
end,
|
57
98
|
}
|
58
99
|
|
59
|
-
if args.count == 0
|
60
|
-
$stderr.puts "Give me some args please"
|
61
|
-
usage
|
62
|
-
end
|
100
|
+
usage if args.count == 0
|
63
101
|
|
64
102
|
subcommand = args.shift
|
65
103
|
options[:subcommand] = subcommand
|
66
104
|
|
67
|
-
unless subcommands.keys.include? subcommand
|
68
|
-
usage
|
69
|
-
end
|
105
|
+
usage unless subcommands.keys.include? subcommand
|
70
106
|
|
71
107
|
subcommands[subcommand].order!
|
72
108
|
|
data/lib/maintainers/runner.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
|
4
4
|
require 'json'
|
5
5
|
require 'json-schema'
|
6
|
+
require 'octokit'
|
6
7
|
|
7
8
|
module Maintainers
|
8
9
|
# Runner entry point
|
@@ -12,6 +13,9 @@ module Maintainers
|
|
12
13
|
|
13
14
|
# for now just assume it's always MAINTAINERS
|
14
15
|
options[:filename] ||= 'MAINTAINERS'
|
16
|
+
|
17
|
+
# for now just assume it's always puppetlabs
|
18
|
+
options[:org] ||= 'puppetlabs'
|
15
19
|
end
|
16
20
|
|
17
21
|
# Run, Lola, Run
|
@@ -24,6 +28,12 @@ module Maintainers
|
|
24
28
|
add(@options)
|
25
29
|
when 'remove'
|
26
30
|
remove(@options)
|
31
|
+
when 'list'
|
32
|
+
list(@options)
|
33
|
+
when 'validate'
|
34
|
+
validate(@options)
|
35
|
+
when 'report'
|
36
|
+
report(@options)
|
27
37
|
end
|
28
38
|
end
|
29
39
|
|
@@ -35,14 +45,19 @@ module Maintainers
|
|
35
45
|
JSON.parse(File.read(schema_path))
|
36
46
|
end
|
37
47
|
|
38
|
-
def
|
39
|
-
|
48
|
+
def validate_json(maintainers, quiet = false)
|
49
|
+
begin
|
50
|
+
JSON::Validator.validate!(maintainers_schema, maintainers)
|
51
|
+
rescue JSON::Schema::ValidationError => e
|
52
|
+
puts e unless quiet
|
53
|
+
false
|
54
|
+
end
|
40
55
|
end
|
41
56
|
|
42
57
|
def write_file(filename, maintainers)
|
43
58
|
maintainers_json = JSON.pretty_generate(maintainers)
|
44
59
|
|
45
|
-
if !
|
60
|
+
if !validate_json(maintainers_json)
|
46
61
|
$stderr.puts "Invalid maintainers string!"
|
47
62
|
exit 1
|
48
63
|
end
|
@@ -60,6 +75,7 @@ module Maintainers
|
|
60
75
|
# minimum content for a maintainers file
|
61
76
|
maintainers = {}
|
62
77
|
maintainers["version"] = 1
|
78
|
+
maintainers["file_format"] = "This MAINTAINERS file format is described at https://github.com/puppetlabs/maintainers"
|
63
79
|
maintainers["issues"] = options[:issues]
|
64
80
|
maintainers["people"] = []
|
65
81
|
|
@@ -106,5 +122,96 @@ module Maintainers
|
|
106
122
|
|
107
123
|
write_file(filename, maintainers)
|
108
124
|
end
|
125
|
+
|
126
|
+
def list(options)
|
127
|
+
filename = options[:filename]
|
128
|
+
if !File.exist?(filename)
|
129
|
+
$stderr.puts "No #{filename} file exists yet. You can use the 'create' subcommand to create one."
|
130
|
+
exit 1
|
131
|
+
end
|
132
|
+
|
133
|
+
maintainers_json = File.read(filename)
|
134
|
+
validate_json(maintainers_json)
|
135
|
+
maintainers = JSON.load(maintainers_json)
|
136
|
+
|
137
|
+
maintainers['people'].each { |p|
|
138
|
+
puts "%-16s %-20s %s" % [ p['github'], p['name'], p['email'] ]
|
139
|
+
}
|
140
|
+
end
|
141
|
+
|
142
|
+
def validate(options)
|
143
|
+
filename = options[:filename]
|
144
|
+
if !File.exist?(filename)
|
145
|
+
$stderr.puts "No #{filename} file exists yet. You can use the 'create' subcommand to create one."
|
146
|
+
exit 1
|
147
|
+
end
|
148
|
+
|
149
|
+
if validate_json(File.read(filename))
|
150
|
+
puts "#{filename} looks good"
|
151
|
+
else
|
152
|
+
puts "There's something wrong with #{filename}"
|
153
|
+
exit 1
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
def report(options)
|
158
|
+
puts "Ok, hang tight, this may take a while as I query github ..."
|
159
|
+
client = Octokit::Client.new(:access_token => ENV['GITHUB_TOKEN'], :auto_paginate => true)
|
160
|
+
|
161
|
+
repos = client.org_repos(options[:org])
|
162
|
+
|
163
|
+
puts "Found a total of #{repos.count} #{options[:org]} repos"
|
164
|
+
|
165
|
+
# For now hardwire some arbitrary filters to help narrow down the
|
166
|
+
# number of repos reported on (and thus github API calls):
|
167
|
+
# - ignore repos with < 5 forks
|
168
|
+
# - ignore repos on a blocklist
|
169
|
+
# There are pretty arbitrary lines, so could be parameterized (or dropped).
|
170
|
+
|
171
|
+
lightly_forked_repos, repos = repos.partition { |repo| repo.forks < 5 }
|
172
|
+
|
173
|
+
blocklist = [
|
174
|
+
'puppetlabs-modules',
|
175
|
+
'courseware',
|
176
|
+
'courseware-virtual',
|
177
|
+
'showoff',
|
178
|
+
'education-builds',
|
179
|
+
'robby3',
|
180
|
+
'pltraining-classroom',
|
181
|
+
'pltraining-bootstrap',
|
182
|
+
'sfdc_reporting',
|
183
|
+
'tse-control-repo',
|
184
|
+
'puppet-quest-guide',
|
185
|
+
'courseware-lvm',
|
186
|
+
]
|
187
|
+
|
188
|
+
blocklisted_repos, repos = repos.partition { |repo| blocklist.include? repo.name }
|
189
|
+
|
190
|
+
no_maintainers_file_repos, repos = repos.partition { |repo|
|
191
|
+
begin
|
192
|
+
contents = client.contents("#{options[:org]}/#{repo.name}", :path => 'MAINTAINERS')
|
193
|
+
rescue Octokit::NotFound
|
194
|
+
end
|
195
|
+
|
196
|
+
contents.nil?
|
197
|
+
}
|
198
|
+
|
199
|
+
unrecognized_maintainers_file_repos, repos = repos.partition { |repo|
|
200
|
+
contents = client.contents("#{options[:org]}/#{repo.name}", :path => 'MAINTAINERS')
|
201
|
+
# the file content is base64 encoded with some '\n's sprinkled in.
|
202
|
+
# the split.join maneuver below strips out those '\n' sprinkles.
|
203
|
+
maintainers = Base64.decode64(contents[:content].split.join)
|
204
|
+
|
205
|
+
!validate_json(maintainers, true)
|
206
|
+
}
|
207
|
+
|
208
|
+
puts "Skipped #{lightly_forked_repos.count} repos with fewer than 5 forks" if lightly_forked_repos
|
209
|
+
puts "Skipped #{blocklisted_repos.count} repos on a blocklist" if blocklisted_repos
|
210
|
+
puts "Skipped #{no_maintainers_file_repos.count} without a MAINTAINERS file" if no_maintainers_file_repos
|
211
|
+
puts "Skipped #{unrecognized_maintainers_file_repos.count} with a MAINTAINERS file in a different format" if unrecognized_maintainers_file_repos
|
212
|
+
puts "Found #{repos.count} repos with MAINTAINERS files"
|
213
|
+
|
214
|
+
end
|
215
|
+
|
109
216
|
end
|
110
217
|
end
|
data/lib/maintainers/version.rb
CHANGED
data/maintainers.gemspec
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: maintainers
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Puppet, Inc
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-09-
|
11
|
+
date: 2016-09-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -66,6 +66,20 @@ dependencies:
|
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
68
|
version: '9.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: octokit
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '4.3'
|
76
|
+
type: :runtime
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '4.3'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: json-schema
|
71
85
|
requirement: !ruby/object:Gem::Requirement
|