mkghrepo 0.0.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 +7 -0
- data/.gitignore +18 -0
- data/.ruby-version +1 -0
- data/Gemfile +4 -0
- data/README.md +32 -0
- data/Rakefile +1 -0
- data/bin/mkghrepo +20 -0
- data/lib/mkghrepo/cli.rb +184 -0
- data/lib/mkghrepo/repo.rb +42 -0
- data/lib/mkghrepo/version.rb +5 -0
- data/lib/mkghrepo.rb +4 -0
- data/mkghrepo.gemspec +28 -0
- metadata +126 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 61e3ebd4a68bfd47ba4e22e662fd79cd7bc2924b
|
4
|
+
data.tar.gz: 28333abba470929e76d353b0f2c466535b9a65f2
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: ceb2dd85a69cbab50aea37804b2e9bba17505f905765dc9da980e92a5bd55968707c1f6b67db2e6c88e61ecad3378ea5ba53c8bedf46994c208db1cb6c3b17ad
|
7
|
+
data.tar.gz: aa9ef45714c0ba23c6d3dc49b39808f870145773116b91fe0c59588579e6fe0acf27a2e72ba78d71f726a3f5ea216561bcf8e229cd64d145191763a110e78dfe
|
data/.gitignore
ADDED
data/.ruby-version
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
2.1.4
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
# Mkghrepo
|
2
|
+
Quick and dirty tool to mass create repositories on Github.
|
3
|
+
|
4
|
+
To install: `gem install mkghrepo`
|
5
|
+
|
6
|
+
Help:
|
7
|
+
|
8
|
+
```
|
9
|
+
Usage: mkghrepo [options] [<filename>]
|
10
|
+
|
11
|
+
Repository options:
|
12
|
+
-p, --private make the repository private
|
13
|
+
-t, --create-team creates a team called "<foo>-write", default is false
|
14
|
+
--token sets github token, defaults from GITHUB_TOKEN
|
15
|
+
|
16
|
+
Other options:
|
17
|
+
-h, --help print this help
|
18
|
+
-v, --version print the version
|
19
|
+
```
|
20
|
+
|
21
|
+
`mkghrepo` accepts one repository per line as input, either stored in a file or passed through STDIN, the formats supported are:
|
22
|
+
|
23
|
+
`<org>/<repo> [<user1> <user2> ... <userN>]`
|
24
|
+
|
25
|
+
or
|
26
|
+
|
27
|
+
`<repo>`
|
28
|
+
|
29
|
+
If users are listed and the `-t` flag has been specified in the run, a team called `<repo>-write` will be created and those users added to it. The users must already be part of the organization or they will be skipped (a warning will be displayed).
|
30
|
+
|
31
|
+
## Troubleshooting
|
32
|
+
By default, debug events are not logged, to see them, set `MKGHREPO_LOG` to `DEBUG` in your shell environment.
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
data/bin/mkghrepo
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'mkghrepo'
|
3
|
+
|
4
|
+
# Instantiate new cli object.
|
5
|
+
cli = Mkghrepo::CLI.new
|
6
|
+
|
7
|
+
# Parse CLI options.
|
8
|
+
opts = cli.parse_options
|
9
|
+
|
10
|
+
# Log into Github and get a client
|
11
|
+
client = Mkghrepo::Repo.new(opts[:token])
|
12
|
+
|
13
|
+
# Main entrypoint into the actual program.
|
14
|
+
if opts.arguments.length < 1
|
15
|
+
# If no file arguments, start processing standard input.
|
16
|
+
cli.process_stdin(client, opts)
|
17
|
+
else
|
18
|
+
# If file argument is present, take the first one and parse it.
|
19
|
+
cli.process_file(opts.arguments[0], client, opts)
|
20
|
+
end
|
data/lib/mkghrepo/cli.rb
ADDED
@@ -0,0 +1,184 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'logger'
|
3
|
+
require 'slop'
|
4
|
+
|
5
|
+
module Mkghrepo
|
6
|
+
# CLI Class takes care of all the plubing related to the CLI commands and
|
7
|
+
# option parsing, consuming other classes to operate against Github Repos.
|
8
|
+
#
|
9
|
+
# Disabling ClassLength cop due to parse_options inflating the line numbers.
|
10
|
+
class CLI # rubocop:disable Metrics/ClassLength
|
11
|
+
def setup_logging(level)
|
12
|
+
start = Time.now
|
13
|
+
@logger = Logger.new(STDOUT)
|
14
|
+
@logger.level = level
|
15
|
+
@logger.datetime_format = '%Y-%m-%d %H:%M:%S'
|
16
|
+
@logger.formatter = proc do |severity, _datetime, _progname, msg|
|
17
|
+
now = Time.now
|
18
|
+
"[#{severity}][#{(now - start).round}] #{msg}\n"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def initialize
|
23
|
+
if ENV['MKGHREPO_LOG'].nil?
|
24
|
+
setup_logging(Logger::INFO)
|
25
|
+
else
|
26
|
+
setup_logging(Logger.const_get(ENV['MKGHREPO_LOG'].upcase))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
# Parse CLI options with 'slop', disabling the MethodLength cop for this
|
31
|
+
# particular method as we can't really make it shorter.
|
32
|
+
def parse_options # rubocop:disable Metrics/MethodLength
|
33
|
+
opts = Slop.parse do |o|
|
34
|
+
o.banner = 'Usage: mkghrepo [options] <filename>'
|
35
|
+
o.separator ''
|
36
|
+
o.separator 'Repository options:'
|
37
|
+
o.bool '-p',
|
38
|
+
'--private',
|
39
|
+
'make the repository private',
|
40
|
+
default: false
|
41
|
+
o.bool '-t',
|
42
|
+
'--create-team',
|
43
|
+
'creates a team called "<foo>-write", default is false',
|
44
|
+
default: false
|
45
|
+
o.string '--token',
|
46
|
+
'sets github token, defaults from GITHUB_TOKEN',
|
47
|
+
default: ENV['GITHUB_TOKEN']
|
48
|
+
o.separator ''
|
49
|
+
o.separator 'Other options:'
|
50
|
+
o.bool '-h', '--help', 'print this help'
|
51
|
+
o.on '-v', '--version', 'print the version' do
|
52
|
+
puts VERSION
|
53
|
+
exit
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
input_sanitization(opts)
|
58
|
+
|
59
|
+
opts
|
60
|
+
end
|
61
|
+
|
62
|
+
def input_sanitization(opts)
|
63
|
+
@logger.debug("Options: #{opts.to_hash} Arguments: #{opts.arguments}")
|
64
|
+
|
65
|
+
# if help is required, just print it and exit
|
66
|
+
if opts.help?
|
67
|
+
puts opts
|
68
|
+
exit
|
69
|
+
end
|
70
|
+
|
71
|
+
return unless opts[:token].nil?
|
72
|
+
|
73
|
+
# Fail if token is not available
|
74
|
+
@logger.fatal('Token is required')
|
75
|
+
puts opts
|
76
|
+
exit 1
|
77
|
+
end
|
78
|
+
|
79
|
+
def process_file(file, client, opts)
|
80
|
+
# We received one or more file arguments, let's open up the first one and
|
81
|
+
# start reading it.
|
82
|
+
@logger.debug("Opening #{file} for parsing...")
|
83
|
+
unless File.exist?(file)
|
84
|
+
# File not found, no point in continuing
|
85
|
+
@logger.fatal("File #{file} not found")
|
86
|
+
exit 1
|
87
|
+
end
|
88
|
+
File.open(file, 'r') do |f|
|
89
|
+
f.each_line do |a|
|
90
|
+
# Treat each line as a separate repo
|
91
|
+
process_lines(a, client, opts[:private], opts[:create_team])
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def process_stdin(client, opts)
|
97
|
+
# We have no file arguments, start reading from STDIN and treat every line
|
98
|
+
# as a separate repo.
|
99
|
+
@logger.warn('No file arguments, reading from stdin...')
|
100
|
+
begin
|
101
|
+
STDIN.read.split("\n").each do |a|
|
102
|
+
# Treat each line as a separate repo
|
103
|
+
process_lines(a, client, opts[:private], opts[:create_team])
|
104
|
+
end
|
105
|
+
rescue Interrupt
|
106
|
+
# Trap a CTRL+C event and exit gracefully
|
107
|
+
@logger.warn('Exiting...')
|
108
|
+
exit 130
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
def process_lines(line, client, private, create_team)
|
113
|
+
# Split the line using space as delimiter, format is:
|
114
|
+
# <org>/<repo> <user1> <user2> ... <userN>
|
115
|
+
# or
|
116
|
+
# <repo>
|
117
|
+
@logger.debug("processing #{line.strip}")
|
118
|
+
matches = line.split(' ')
|
119
|
+
repo = matches[0]
|
120
|
+
create_repo(client, repo, private)
|
121
|
+
|
122
|
+
# If no users are specified or create_team was not enabled
|
123
|
+
return if matches.length < 2 || create_team == false
|
124
|
+
# create team and whatever
|
125
|
+
if repo.include? '/'
|
126
|
+
process_team(client, repo, matches[1..matches.count])
|
127
|
+
else
|
128
|
+
@logger.warn("Not creating Team for #{repo}, only orgs support teams")
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def process_team(client, repo, users)
|
133
|
+
team = create_team(client, repo)
|
134
|
+
users.each do |user|
|
135
|
+
add_user_to_team(client, user, team.id)
|
136
|
+
end
|
137
|
+
end
|
138
|
+
|
139
|
+
def parse_error(object, e)
|
140
|
+
case
|
141
|
+
when !e.errors.first[:message].nil?
|
142
|
+
# Print a human readable error and carry on.
|
143
|
+
@logger.error("Can't process #{object}: #{e.errors.first[:message]}")
|
144
|
+
when e.errors.length > 0
|
145
|
+
# Can't find a human readable error, just dump the error hash and be
|
146
|
+
# done with it.
|
147
|
+
@logger.error("Can't process #{object}: #{e.errors}")
|
148
|
+
else
|
149
|
+
# Apparently some errors are not correctly formatted so we just dump
|
150
|
+
# the whole ugly message to screen.
|
151
|
+
@logger.error("Can't process #{object}: #{e.message}")
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def create_repo(client, repo, private)
|
156
|
+
@logger.debug("Creating repo named: #{repo}")
|
157
|
+
client.create_repo(repo, private)
|
158
|
+
rescue Octokit::Error => e
|
159
|
+
parse_error(repo, e)
|
160
|
+
else
|
161
|
+
@logger.info("Succesfully created repository: #{repo}")
|
162
|
+
end
|
163
|
+
|
164
|
+
def create_team(client, repo)
|
165
|
+
team_name = repo.rpartition('/').last + '-write'
|
166
|
+
@logger.debug("Creating team named: #{team_name}")
|
167
|
+
team = client.create_team(repo, team_name, 'push')
|
168
|
+
rescue Octokit::Error => e
|
169
|
+
parse_error(team_name, e)
|
170
|
+
else
|
171
|
+
@logger.info("Succesfully created team '#{team_name}' for: #{repo}")
|
172
|
+
team
|
173
|
+
end
|
174
|
+
|
175
|
+
def add_user_to_team(client, user, team_id)
|
176
|
+
@logger.debug("Adding user #{user} to team id: #{team_id}")
|
177
|
+
client.add_user_to_team(user, team_id)
|
178
|
+
rescue Octokit::Error => e
|
179
|
+
parse_error(user, e)
|
180
|
+
else
|
181
|
+
@logger.info("Succesfully added user '#{user}' on team id: #{team_id}")
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
require 'octokit'
|
3
|
+
|
4
|
+
module Mkghrepo
|
5
|
+
# Repo provides an interface to github repos
|
6
|
+
class Repo
|
7
|
+
def initialize(token)
|
8
|
+
# stack = Faraday::RackBuilder.new do |builder|
|
9
|
+
# builder.response :logger
|
10
|
+
# builder.use Octokit::Response::RaiseError
|
11
|
+
# builder.adapter Faraday.default_adapter
|
12
|
+
# end
|
13
|
+
# Octokit.middleware = stack
|
14
|
+
@client = Octokit::Client.new(access_token: token)
|
15
|
+
end
|
16
|
+
|
17
|
+
def create_repo(repo, private = false)
|
18
|
+
if repo.include? '/'
|
19
|
+
organization = repo.rpartition('/').first
|
20
|
+
repo = repo.rpartition('/').last
|
21
|
+
@client.create_repository(repo,
|
22
|
+
private: private,
|
23
|
+
organization: organization)
|
24
|
+
else
|
25
|
+
@client.create_repository(repo,
|
26
|
+
private: private)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_team(repo, team_name, permissions)
|
31
|
+
organization = repo.rpartition('/').first
|
32
|
+
@client.create_team(organization,
|
33
|
+
name: team_name,
|
34
|
+
repo_names: [repo],
|
35
|
+
permission: permissions)
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_user_to_team(user, team_id)
|
39
|
+
@client.add_team_member(team_id, user)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/mkghrepo.rb
ADDED
data/mkghrepo.gemspec
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'mkghrepo/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'mkghrepo'
|
8
|
+
spec.version = Mkghrepo::VERSION
|
9
|
+
spec.executables << 'mkghrepo'
|
10
|
+
spec.authors = ['Fabio Rapposelli']
|
11
|
+
spec.email = ['fabio@rapposelli.org']
|
12
|
+
spec.description = 'mkghrepo is a tool to facilitate mass repository creation'
|
13
|
+
spec.summary = 'mkghrepo is a tool to facilitate mass repository creation'
|
14
|
+
spec.homepage = 'https://github.com/frapposelli/mkghrepo'
|
15
|
+
spec.license = 'APL2'
|
16
|
+
|
17
|
+
spec.files = `git ls-files`.split($RS)
|
18
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
+
spec.require_paths = ['lib']
|
21
|
+
|
22
|
+
spec.add_runtime_dependency 'octokit', '~> 4.0'
|
23
|
+
spec.add_runtime_dependency 'slop', '~> 4.0'
|
24
|
+
|
25
|
+
spec.add_development_dependency 'bundler', '~> 1.10'
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rubocop'
|
28
|
+
end
|
metadata
ADDED
@@ -0,0 +1,126 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: mkghrepo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Fabio Rapposelli
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2015-12-14 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: octokit
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '4.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '4.0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: slop
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - "~>"
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '4.0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - "~>"
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '4.0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.10'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.10'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rubocop
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
description: mkghrepo is a tool to facilitate mass repository creation
|
84
|
+
email:
|
85
|
+
- fabio@rapposelli.org
|
86
|
+
executables:
|
87
|
+
- mkghrepo
|
88
|
+
extensions: []
|
89
|
+
extra_rdoc_files: []
|
90
|
+
files:
|
91
|
+
- ".gitignore"
|
92
|
+
- ".ruby-version"
|
93
|
+
- Gemfile
|
94
|
+
- README.md
|
95
|
+
- Rakefile
|
96
|
+
- bin/mkghrepo
|
97
|
+
- lib/mkghrepo.rb
|
98
|
+
- lib/mkghrepo/cli.rb
|
99
|
+
- lib/mkghrepo/repo.rb
|
100
|
+
- lib/mkghrepo/version.rb
|
101
|
+
- mkghrepo.gemspec
|
102
|
+
homepage: https://github.com/frapposelli/mkghrepo
|
103
|
+
licenses:
|
104
|
+
- APL2
|
105
|
+
metadata: {}
|
106
|
+
post_install_message:
|
107
|
+
rdoc_options: []
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
version: '0'
|
115
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
|
+
requirements:
|
117
|
+
- - ">="
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
version: '0'
|
120
|
+
requirements: []
|
121
|
+
rubyforge_project:
|
122
|
+
rubygems_version: 2.2.2
|
123
|
+
signing_key:
|
124
|
+
specification_version: 4
|
125
|
+
summary: mkghrepo is a tool to facilitate mass repository creation
|
126
|
+
test_files: []
|