gerd 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 +3 -0
- data/.travis.yml +3 -0
- data/Gemfile +3 -0
- data/Gemfile.lock +115 -0
- data/Guardfile +43 -0
- data/README.md +83 -0
- data/Rakefile +11 -0
- data/bin/gerd +4 -0
- data/gerd.gemspec +33 -0
- data/lib/gerd.rb +6 -0
- data/lib/gerd/audit/audit.rb +79 -0
- data/lib/gerd/audit/builders.rb +0 -0
- data/lib/gerd/cli.rb +74 -0
- data/lib/gerd/exceptions.rb +16 -0
- data/lib/gerd/formatters.rb +39 -0
- data/lib/gerd/github_client.rb +35 -0
- data/lib/gerd/inspections/actions/change_repo_privacy.rb +16 -0
- data/lib/gerd/inspections/actions/create_repo.rb +26 -0
- data/lib/gerd/inspections/actions/create_team.rb +31 -0
- data/lib/gerd/inspections/actions/delete_repo.rb +29 -0
- data/lib/gerd/inspections/actions/delete_team.rb +19 -0
- data/lib/gerd/inspections/actions/update_name_action.rb +19 -0
- data/lib/gerd/inspections/diff.rb +17 -0
- data/lib/gerd/inspections/diffs/organisation.rb +89 -0
- data/lib/gerd/inspections/diffs/repositories.rb +94 -0
- data/lib/gerd/invoke.rb +18 -0
- data/lib/gerd/model/members.rb +0 -0
- data/lib/gerd/model/model.rb +95 -0
- data/lib/gerd/model/organisation.rb +0 -0
- data/lib/gerd/model/repositories.rb +0 -0
- data/lib/gerd/model/teams.rb +0 -0
- data/lib/gerd/validation/organisations/apply.rb +0 -0
- data/lib/gerd/validation/organisations/diff.rb +0 -0
- data/lib/gerd/validation/organisations/introspect.rb +0 -0
- data/lib/gerd/validators.rb +55 -0
- data/lib/gerd/version.rb +4 -0
- data/local.sh +10 -0
- data/spec/model_spec.rb +149 -0
- data/spec/organisation_spec.rb +76 -0
- data/spec/repositories_spec.rb +223 -0
- data/spec/spec_helper.rb +6 -0
- metadata +246 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module Gerd
|
4
|
+
module Formatters
|
5
|
+
|
6
|
+
def self.find_formatter(file)
|
7
|
+
return Gerd::Formatters::Stdout.new unless file
|
8
|
+
return Gerd::Formatters::FileFormatter.new(file)
|
9
|
+
end
|
10
|
+
|
11
|
+
class Stdout
|
12
|
+
|
13
|
+
def print(hash, options = {})
|
14
|
+
puts JSON.pretty_generate(hash)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
class FileFormatter
|
20
|
+
|
21
|
+
def initialize(file)
|
22
|
+
@file = file
|
23
|
+
end
|
24
|
+
|
25
|
+
def print(hash, options = {})
|
26
|
+
|
27
|
+
if(File.exists?(@file))
|
28
|
+
puts "The file #{@file} already exists. Use -o or --overwrite" unless options[:overwrite]
|
29
|
+
return unless options[:overwrite]
|
30
|
+
end
|
31
|
+
output_file = File.new(@file, "w")
|
32
|
+
content = JSON.pretty_generate(hash)
|
33
|
+
output_file.write(content)
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
39
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
require 'octokit'
|
2
|
+
require 'octokit/repository'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Gerd
|
6
|
+
class GHClient
|
7
|
+
|
8
|
+
def self.create(explicit_token)
|
9
|
+
Octokit.auto_paginate = true
|
10
|
+
token = explicit_token
|
11
|
+
token = ENV['GERD_TOKEN'] unless token
|
12
|
+
token = from_local unless token
|
13
|
+
token = from_global unless token
|
14
|
+
client = token ? Octokit::Client.new(:access_token => token) : client = Octokit::Client.new
|
15
|
+
client
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.from_local()
|
19
|
+
file = File.join(Dir.pwd, ".gerd")
|
20
|
+
return unless File.exist?(file)
|
21
|
+
local_file = File.read(file)
|
22
|
+
grim_conf = JSON.parse(local_file)
|
23
|
+
grim_conf['token']
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.from_global()
|
27
|
+
file = File.join(ENV['HOME'], ".gerd")
|
28
|
+
return unless File.exist?(file)
|
29
|
+
global_file = File.read(file)
|
30
|
+
grim_conf = JSON.parse(global_file)
|
31
|
+
grim_conf['token']
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Gerd
|
2
|
+
module Inspections
|
3
|
+
module Actions
|
4
|
+
|
5
|
+
class CreateRepo
|
6
|
+
|
7
|
+
def initialize(repo_to_create, org, privacy = false)
|
8
|
+
@org = org
|
9
|
+
@repo = repo_to_create
|
10
|
+
@privacy = privacy
|
11
|
+
end
|
12
|
+
|
13
|
+
def invoke(client, options = {})
|
14
|
+
puts "Creating #{@org}/#{@repo}"
|
15
|
+
opts = {
|
16
|
+
:organization => @org,
|
17
|
+
:private => @privacy
|
18
|
+
}
|
19
|
+
res = client.create_repo(@repo, { :organization => @org })
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
module Gerd
|
2
|
+
module Inspections
|
3
|
+
module Actions
|
4
|
+
|
5
|
+
class CreateTeam
|
6
|
+
|
7
|
+
def initialize(team_name, organisation, team_opts)
|
8
|
+
@team_name = team_name
|
9
|
+
@org = organisation
|
10
|
+
@opts = team_opts
|
11
|
+
end
|
12
|
+
|
13
|
+
def invoke(client, options = {})
|
14
|
+
team_name = @team_name
|
15
|
+
description = @opts['description']
|
16
|
+
privacy = @opts['privacy']
|
17
|
+
repos = []
|
18
|
+
repos = @opts['repos'].collect { | repo | "#{@org}/#{repo}" } unless !@opts.has_key?('repos')
|
19
|
+
opts = {
|
20
|
+
:name => team_name,
|
21
|
+
:repo_names => repos,
|
22
|
+
:permission => 'admin'
|
23
|
+
}
|
24
|
+
client.create_team(@org, opts)
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Gerd
|
2
|
+
module Inspections
|
3
|
+
module Actions
|
4
|
+
|
5
|
+
class DeleteRepo
|
6
|
+
|
7
|
+
def initialize(repo_to_delete, organisation)
|
8
|
+
@org = organisation
|
9
|
+
@repo = repo_to_delete
|
10
|
+
end
|
11
|
+
|
12
|
+
def invoke(client, options = {})
|
13
|
+
if !options[:delete]
|
14
|
+
puts "You must explicitly use the --delete option to delete repos"
|
15
|
+
return
|
16
|
+
end
|
17
|
+
opts = {
|
18
|
+
:organization => @org
|
19
|
+
}
|
20
|
+
repo_name = "#{@org}/#{@repo}"
|
21
|
+
puts "Deleting #{repo_name}"
|
22
|
+
client.delete_repository(repo_name, opts)
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require 'gerd/inspections/actions/update_name_action'
|
2
|
+
require 'gerd/inspections/actions/create_team'
|
3
|
+
require 'gerd/inspections/actions/delete_team'
|
4
|
+
|
5
|
+
module Gerd
|
6
|
+
module Inspections
|
7
|
+
|
8
|
+
module Organisation
|
9
|
+
|
10
|
+
def self.inspect_organisations(expected, actual)
|
11
|
+
if expected.organisation == actual.organisation
|
12
|
+
return Gerd::Inspections::Organisation::Diff.new(true, "Organisations match")
|
13
|
+
else
|
14
|
+
action = Gerd::Inspections::Organisation::Actions::UpdateName.new(expected, actual)
|
15
|
+
return Gerd::Inspections::Organisation::Diff.new(
|
16
|
+
false, "Expected #{expected.organisation} but found #{actual.organisation}",
|
17
|
+
[action]
|
18
|
+
)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def self.inspect_teams(expected, actual)
|
23
|
+
diffs = []
|
24
|
+
|
25
|
+
diffs << inspect_expected_teams_exist(expected, actual)
|
26
|
+
|
27
|
+
diffs << inspect_no_extra_teams_exist(expected, actual)
|
28
|
+
|
29
|
+
diffs.flatten
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.inspect_expected_teams_exist(expected, actual)
|
33
|
+
|
34
|
+
diffs = []
|
35
|
+
|
36
|
+
expected_teams = expected.teams
|
37
|
+
actual_teams = actual.teams
|
38
|
+
|
39
|
+
expected_teams.keys.each do | expected_team |
|
40
|
+
if !actual_teams.keys.include? expected_team
|
41
|
+
team_to_create = expected_teams[expected_team]
|
42
|
+
action = Gerd::Inspections::Actions::CreateTeam.new(expected_team, expected.organisation, team_to_create)
|
43
|
+
diffs << Gerd::Inspections::Diff.new(false, "I expected to see team #{expected_team} but did not", [action])
|
44
|
+
end
|
45
|
+
|
46
|
+
end
|
47
|
+
|
48
|
+
diffs.flatten
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.inspect_no_extra_teams_exist(expected, actual)
|
53
|
+
|
54
|
+
diffs = []
|
55
|
+
|
56
|
+
expected_teams = expected.teams
|
57
|
+
actual_teams = actual.teams
|
58
|
+
|
59
|
+
actual_teams.keys.each do | team |
|
60
|
+
|
61
|
+
if !expected_teams.keys.include? team
|
62
|
+
|
63
|
+
action = Gerd::Inspections::Actions::DeleteTeam.new(actual_teams[team])
|
64
|
+
diffs << Gerd::Inspections::Diff.new(false, "I did not expect to see team #{team} but saw it anyway", [action])
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
diffs
|
70
|
+
|
71
|
+
end
|
72
|
+
|
73
|
+
class Diff
|
74
|
+
|
75
|
+
attr_accessor :passed, :message, :actions
|
76
|
+
|
77
|
+
def initialize(state, message, actions = [])
|
78
|
+
@passed = state
|
79
|
+
@message = message
|
80
|
+
@actions = actions
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
|
87
|
+
end
|
88
|
+
|
89
|
+
end
|
@@ -0,0 +1,94 @@
|
|
1
|
+
require 'gerd/inspections/diff'
|
2
|
+
require 'gerd/inspections/actions/create_repo'
|
3
|
+
require 'gerd/inspections/actions/delete_repo'
|
4
|
+
require 'gerd/inspections/actions/change_repo_privacy'
|
5
|
+
|
6
|
+
module Gerd
|
7
|
+
module Inspections
|
8
|
+
|
9
|
+
module Repositories
|
10
|
+
|
11
|
+
def self.inspect_repositories(expected, actual)
|
12
|
+
|
13
|
+
diffs = []
|
14
|
+
|
15
|
+
diffs << inspect_required_repos_exist(expected, actual)
|
16
|
+
|
17
|
+
diffs << inspect_no_extra_repos_exist(expected, actual)
|
18
|
+
|
19
|
+
diffs << inspect_repo_privacy(expected, actual)
|
20
|
+
|
21
|
+
diffs.flatten
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.inspect_required_repos_exist(expected, actual)
|
26
|
+
|
27
|
+
diffs = []
|
28
|
+
|
29
|
+
expected_repos = expected.repositories
|
30
|
+
actual_repos= actual.repositories
|
31
|
+
|
32
|
+
expected_repos.keys.each do | expected_repo |
|
33
|
+
if !actual_repos.keys.include? expected_repo
|
34
|
+
repo_to_create = expected_repos[expected_repo]
|
35
|
+
privacy = repo_to_create['privacy']
|
36
|
+
action = Gerd::Inspections::Actions::CreateRepo.new(expected_repo, expected.organisation, privacy)
|
37
|
+
diffs << Gerd::Inspections::Diff.new(false, "I expected to see repository #{expected_repo} but did not", [action])
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
diffs
|
43
|
+
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.inspect_no_extra_repos_exist(expected, actual)
|
47
|
+
|
48
|
+
diffs = []
|
49
|
+
|
50
|
+
expected_repos = expected.repositories
|
51
|
+
actual_repos= actual.repositories
|
52
|
+
|
53
|
+
actual_repos.keys.each do | repo |
|
54
|
+
|
55
|
+
if !expected_repos.keys.include? repo
|
56
|
+
action = Gerd::Inspections::Actions::DeleteRepo.new(repo, expected.organisation)
|
57
|
+
diffs << Gerd::Inspections::Diff.new(false, "I did not expect to see repository #{repo} but saw it anyway", [action])
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
diffs
|
63
|
+
|
64
|
+
end
|
65
|
+
|
66
|
+
def self.inspect_repo_privacy(expected, actual)
|
67
|
+
|
68
|
+
diffs = []
|
69
|
+
|
70
|
+
expected_repos = expected.repositories
|
71
|
+
actual_repos= actual.repositories
|
72
|
+
|
73
|
+
expected_repos.each do | repo_name, expected_repo |
|
74
|
+
actual_repo = actual_repos[repo_name]
|
75
|
+
next if !actual_repo
|
76
|
+
if expected_repo['private'] == true && actual_repo['private'] == false
|
77
|
+
action = Gerd::Inspections::Actions::ChangeRepoPrivacy.new(actual_repo, true)
|
78
|
+
diffs << Gerd::Inspections::Diff.new(false, "I expected repo #{repo_name} to be private, but it is not", [action])
|
79
|
+
end
|
80
|
+
if expected_repo['private'] == false && actual_repo['private'] == true
|
81
|
+
action = Gerd::Inspections::Actions::ChangeRepoPrivacy.new(actual_repo, false)
|
82
|
+
diffs << Gerd::Inspections::Diff.new(false, "I did not expect repo #{repo_name} to be private, but it is", [action])
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
diffs
|
87
|
+
|
88
|
+
end
|
89
|
+
|
90
|
+
end
|
91
|
+
|
92
|
+
end
|
93
|
+
|
94
|
+
end
|