gerd 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|