maintainers 0.1.2 → 0.2.0

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
  SHA1:
3
- metadata.gz: 9a242cfe2e2085d761f6fd899e539b342ae8ab65
4
- data.tar.gz: 2b3d13830eecdd5b0e33cb6d2381ed68ba3131f8
3
+ metadata.gz: 637a6814e58b1d5692780afee0338f597a9e334f
4
+ data.tar.gz: 310211fbde7e866fc7ca8e0843705fe1449e083d
5
5
  SHA512:
6
- metadata.gz: 33040a6040571e954c8e0ebc1b724cdf864a32bd5b6796f428fe46e5b7b75f9fa8559448c1881466de3f7148e1a3a0745dde4ac62ffd547dc88e8fa2c06ffe70
7
- data.tar.gz: 1cb1627cd7a50e59c5c2d4d3957a12224c107ae0d5638aa931eebf62fe07d1cae3c47991922c172d0e0d54e093bb4165e171bba438532e43422c38ea43f05f3b
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.1.2...HEAD
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
@@ -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
+ }
@@ -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/graceland/issues",
4
5
  "people": [
5
6
  {
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "version": 1,
3
+ "file_format": "This MAINTAINERS file format is described at https://github.com/puppetlabs/maintainers",
3
4
  "maintained": false,
4
- "issues": "https://github.com/graceland/issues",
5
+ "issues": "This repo is not maintained",
5
6
  "people": []
6
7
  }
@@ -13,20 +13,57 @@ module Maintainers
13
13
  end
14
14
 
15
15
  def usage
16
- puts "Imagine a usage statement here"
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
 
@@ -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 validate(maintainers)
39
- JSON::Validator.validate(maintainers_schema, maintainers)
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 !validate(maintainers_json)
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
@@ -1,3 +1,3 @@
1
1
  module Maintainers
2
- VERSION = "0.1.2"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -21,5 +21,6 @@ Gem::Specification.new do |spec|
21
21
  spec.add_development_dependency "rspec", "~> 3.0"
22
22
  spec.add_development_dependency "byebug", "~> 9.0"
23
23
 
24
+ spec.add_runtime_dependency 'octokit', '~> 4.3'
24
25
  spec.add_runtime_dependency 'json-schema', '~> 2.6'
25
26
  end
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.1.2
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-02 00:00:00.000000000 Z
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