sem 0.1.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 +14 -0
- data/.rspec +2 -0
- data/.rubocop.yml +103 -0
- data/Gemfile +6 -0
- data/README.md +27 -0
- data/Rakefile +10 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/exe/sem +5 -0
- data/guides.md +168 -0
- data/ids.md +74 -0
- data/lib/sem.rb +53 -0
- data/lib/sem/api.rb +14 -0
- data/lib/sem/api/base.rb +17 -0
- data/lib/sem/api/env_vars.rb +20 -0
- data/lib/sem/api/files.rb +19 -0
- data/lib/sem/api/orgs.rb +54 -0
- data/lib/sem/api/projects.rb +33 -0
- data/lib/sem/api/shared_configs.rb +75 -0
- data/lib/sem/api/teams.rb +54 -0
- data/lib/sem/api/traits.rb +9 -0
- data/lib/sem/api/traits/associated_with_org.rb +13 -0
- data/lib/sem/api/traits/associated_with_shared_config.rb +29 -0
- data/lib/sem/api/traits/associated_with_team.rb +29 -0
- data/lib/sem/api/users.rb +26 -0
- data/lib/sem/api/users_with_permissions.rb +53 -0
- data/lib/sem/cli.rb +20 -0
- data/lib/sem/cli/orgs.rb +45 -0
- data/lib/sem/cli/projects.rb +17 -0
- data/lib/sem/cli/shared_configs.rb +97 -0
- data/lib/sem/cli/teams.rb +126 -0
- data/lib/sem/errors.rb +8 -0
- data/lib/sem/version.rb +3 -0
- data/lib/sem/views.rb +7 -0
- data/lib/sem/views/base.rb +7 -0
- data/lib/sem/views/env_vars.rb +13 -0
- data/lib/sem/views/files.rb +13 -0
- data/lib/sem/views/orgs.rb +22 -0
- data/lib/sem/views/projects.rb +22 -0
- data/lib/sem/views/shared_configs.rb +24 -0
- data/lib/sem/views/teams.rb +24 -0
- data/lib/sem/views/users.rb +13 -0
- data/lib/sem/views/users_with_permissions.rb +13 -0
- data/sem.gemspec +33 -0
- metadata +201 -0
@@ -0,0 +1,53 @@
|
|
1
|
+
module Sem
|
2
|
+
module API
|
3
|
+
class UsersWithPermissions < Base
|
4
|
+
class << self
|
5
|
+
LEVELS = { "owner" => 3, "admin" => 2, "write" => 1, "read" => 0 }.freeze
|
6
|
+
|
7
|
+
def list_owners_for_org(org_name)
|
8
|
+
Sem::API::Orgs.list_owners(org_name).map { |user| user.merge(:permission => "owner") }
|
9
|
+
end
|
10
|
+
|
11
|
+
def list_admins_for_org(org_name)
|
12
|
+
Sem::API::Orgs.list_admins(org_name).map { |user| user.merge(:permission => "admin") }
|
13
|
+
end
|
14
|
+
|
15
|
+
def list_for_org(org_name)
|
16
|
+
all_teams = client.teams.list_for_org(org_name)
|
17
|
+
|
18
|
+
team_groups = teams_by_permission(all_teams)
|
19
|
+
|
20
|
+
user_groups = users_for_team_groups(team_groups)
|
21
|
+
|
22
|
+
user_groups.reduce({}) { |acc, teams| acc.merge(teams) }.values
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def teams_by_permission(all_teams)
|
28
|
+
groups = all_teams.group_by(&:permission)
|
29
|
+
|
30
|
+
groups.sort_by { |permission, _| LEVELS[permission] }.to_h.values
|
31
|
+
end
|
32
|
+
|
33
|
+
def users_for_team_groups(groups)
|
34
|
+
groups.map { |teams| users_for_teams(teams) }.flatten
|
35
|
+
end
|
36
|
+
|
37
|
+
def users_for_teams(teams)
|
38
|
+
teams.map { |team| users_for_team(team) }.flatten.uniq
|
39
|
+
end
|
40
|
+
|
41
|
+
def users_for_team(team)
|
42
|
+
users = client.users.list_for_team(team.id)
|
43
|
+
|
44
|
+
users.map { |user| [user.username, transform_user(user, team)] }.to_h
|
45
|
+
end
|
46
|
+
|
47
|
+
def transform_user(user, team)
|
48
|
+
Users.to_hash(user).merge(:permission => team.permission)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
data/lib/sem/cli.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
module Sem
|
2
|
+
class CLI < Dracula
|
3
|
+
program_name "sem"
|
4
|
+
|
5
|
+
require_relative "cli/orgs"
|
6
|
+
require_relative "cli/projects"
|
7
|
+
require_relative "cli/teams"
|
8
|
+
require_relative "cli/shared_configs"
|
9
|
+
|
10
|
+
desc "login", "log in to semaphore from the command line"
|
11
|
+
def login
|
12
|
+
puts "NOT IMPLEMENTED"
|
13
|
+
end
|
14
|
+
|
15
|
+
register "orgs", "manage organizations", Sem::CLI::Orgs
|
16
|
+
register "teams", "manage teams and team membership", Sem::CLI::Teams
|
17
|
+
register "shared-configs", "manage shared configurations", Sem::CLI::SharedConfigs
|
18
|
+
register "projects", "manage projects", Sem::CLI::Projects
|
19
|
+
end
|
20
|
+
end
|
data/lib/sem/cli/orgs.rb
ADDED
@@ -0,0 +1,45 @@
|
|
1
|
+
class Sem::CLI::Orgs < Dracula
|
2
|
+
|
3
|
+
desc "list", "list organizations"
|
4
|
+
def list
|
5
|
+
orgs = Sem::API::Orgs.list
|
6
|
+
|
7
|
+
Sem::Views::Orgs.list(orgs)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "info", "shows detailed information about an organization"
|
11
|
+
def info(org_name)
|
12
|
+
org = Sem::API::Orgs.info(org_name)
|
13
|
+
|
14
|
+
Sem::Views::Orgs.info(org)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "members", "list members of an organization"
|
18
|
+
option :with_2fa,
|
19
|
+
:default => false,
|
20
|
+
:type => :boolean,
|
21
|
+
:desc => "list members that have two factor authentication enabled"
|
22
|
+
option :admins,
|
23
|
+
:default => false,
|
24
|
+
:type => :boolean,
|
25
|
+
:desc => "list only admins in the organization"
|
26
|
+
option :owners,
|
27
|
+
:default => false,
|
28
|
+
:type => :boolean,
|
29
|
+
:desc => "list only owners in the organization"
|
30
|
+
def members(org_name)
|
31
|
+
raise "Not Implemented" if options[:with_2fa]
|
32
|
+
|
33
|
+
users =
|
34
|
+
if options[:owners]
|
35
|
+
Sem::API::UsersWithPermissions.list_owners_for_org(org_name)
|
36
|
+
elsif options[:admins]
|
37
|
+
Sem::API::UsersWithPermissions.list_admins_for_org(org_name)
|
38
|
+
else
|
39
|
+
Sem::API::UsersWithPermissions.list_for_org(org_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
Sem::Views::UsersWithPermissions.list(users)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Sem::CLI::Projects < Dracula
|
2
|
+
|
3
|
+
desc "list", "list projects"
|
4
|
+
def list
|
5
|
+
projects = Sem::API::Projects.list
|
6
|
+
|
7
|
+
Sem::Views::Projects.list(projects)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "info", "shows detailed information about a project"
|
11
|
+
def info(project_path)
|
12
|
+
project = Sem::API::Projects.info(project_path)
|
13
|
+
|
14
|
+
Sem::Views::Projects.info(project)
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
class Sem::CLI::SharedConfigs < Dracula
|
2
|
+
|
3
|
+
desc "list", "list shared cofigurations"
|
4
|
+
def list
|
5
|
+
shared_configs = Sem::API::SharedConfigs.list
|
6
|
+
|
7
|
+
Sem::Views::SharedConfigs.list(shared_configs)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "info", "show information about a shared configuration"
|
11
|
+
def info(path)
|
12
|
+
shared_config = Sem::API::SharedConfigs.info(path)
|
13
|
+
|
14
|
+
Sem::Views::SharedConfigs.info(shared_config)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "create", "create a new shared configuration"
|
18
|
+
def create(path)
|
19
|
+
org_name, shared_config_name = path.split("/")
|
20
|
+
|
21
|
+
shared_config = Sem::API::SharedConfigs.create(org_name, :name => shared_config_name)
|
22
|
+
|
23
|
+
Sem::Views::SharedConfigs.info(shared_config)
|
24
|
+
end
|
25
|
+
|
26
|
+
desc "rename", "rename a shared configuration"
|
27
|
+
def rename(old_path, new_path)
|
28
|
+
_, name = new_path.split("/")
|
29
|
+
|
30
|
+
shared_config = Sem::API::SharedConfigs.update(old_path, :name => name)
|
31
|
+
|
32
|
+
Sem::Views::SharedConfigs.info(shared_config)
|
33
|
+
end
|
34
|
+
|
35
|
+
desc "delete", "removes a shared configuration from your organization"
|
36
|
+
def delete(path)
|
37
|
+
Sem::API::SharedConfigs.delete(path)
|
38
|
+
|
39
|
+
puts "Deleted shared configuration #{path}"
|
40
|
+
end
|
41
|
+
|
42
|
+
class Files < Dracula
|
43
|
+
desc "list", "list files in the shared configuration"
|
44
|
+
def list(shared_config_path)
|
45
|
+
files = Sem::API::SharedConfigs.list_files(shared_config_path)
|
46
|
+
|
47
|
+
Sem::Views::Files.list(files)
|
48
|
+
end
|
49
|
+
|
50
|
+
desc "add", "add a file to the shared configuration"
|
51
|
+
option :file, :aliases => "f", :desc => "File to upload", :required => true
|
52
|
+
def add(shared_config_path, file_name)
|
53
|
+
content = File.read(options[:file])
|
54
|
+
|
55
|
+
Sem::API::Files.add_to_shared_config(shared_config_path, :path => file_name, :content => content)
|
56
|
+
|
57
|
+
puts "Added #{file_name} to #{shared_config_path}"
|
58
|
+
end
|
59
|
+
|
60
|
+
desc "remove", "remove a file from the shared configuration"
|
61
|
+
def remove(shared_config_path, file_name)
|
62
|
+
Sem::API::Files.remove_from_shared_config(shared_config_path, file_name)
|
63
|
+
|
64
|
+
puts "Removed #{file_name} from #{shared_config_path}"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
class EnvVars < Dracula
|
69
|
+
desc "list", "list environment variables in the shared configuration"
|
70
|
+
def list(shared_config_path)
|
71
|
+
env_vars = Sem::API::SharedConfigs.list_env_vars(shared_config_path)
|
72
|
+
|
73
|
+
Sem::Views::EnvVars.list(env_vars)
|
74
|
+
end
|
75
|
+
|
76
|
+
desc "add", "add an environment variable to the shared configuration"
|
77
|
+
option :name, :aliases => "-n", :desc => "Name of the variable", :required => true
|
78
|
+
option :content, :aliases => "-c", :desc => "Content of the variable", :required => true
|
79
|
+
def add(shared_config_path)
|
80
|
+
Sem::API::EnvVars.add_to_shared_config(shared_config_path,
|
81
|
+
:name => options[:name],
|
82
|
+
:content => options[:content])
|
83
|
+
|
84
|
+
puts "Added #{options[:name]} to #{shared_config_path}"
|
85
|
+
end
|
86
|
+
|
87
|
+
desc "remove", "remove an environment variable from the shared configuration"
|
88
|
+
def remove(shared_config_path, env_var_name)
|
89
|
+
Sem::API::EnvVars.remove_from_shared_config(shared_config_path, env_var_name)
|
90
|
+
|
91
|
+
puts "Removed #{env_var_name} from #{shared_config_path}"
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
register "files", "manage files", Files
|
96
|
+
register "env-vars", "manage environment variables", EnvVars
|
97
|
+
end
|
@@ -0,0 +1,126 @@
|
|
1
|
+
class Sem::CLI::Teams < Dracula
|
2
|
+
|
3
|
+
desc "list", "list teams"
|
4
|
+
def list
|
5
|
+
teams = Sem::API::Teams.list
|
6
|
+
|
7
|
+
Sem::Views::Teams.list(teams)
|
8
|
+
end
|
9
|
+
|
10
|
+
desc "info", "show information about a team"
|
11
|
+
def info(name)
|
12
|
+
team = Sem::API::Teams.info(name)
|
13
|
+
|
14
|
+
Sem::Views::Teams.info(team)
|
15
|
+
end
|
16
|
+
|
17
|
+
desc "create", "create a new team"
|
18
|
+
option :permission, :default => "read",
|
19
|
+
:aliases => "-p",
|
20
|
+
:desc => "Permission level of the team in the organization"
|
21
|
+
def create(name)
|
22
|
+
org_name, team_name = name.split("/")
|
23
|
+
|
24
|
+
team = Sem::API::Teams.create(org_name,
|
25
|
+
:name => team_name,
|
26
|
+
:permission => options[:permission])
|
27
|
+
|
28
|
+
Sem::Views::Teams.info(team)
|
29
|
+
end
|
30
|
+
|
31
|
+
desc "rename", "change the name of the team"
|
32
|
+
def rename(old_name, new_name)
|
33
|
+
_, name = new_name.split("/")
|
34
|
+
|
35
|
+
team = Sem::API::Teams.update(old_name, :name => name)
|
36
|
+
|
37
|
+
Sem::Views::Teams.info(team)
|
38
|
+
end
|
39
|
+
|
40
|
+
desc "set-permission", "set the permission level of the team"
|
41
|
+
def set_permission(team_name, permission)
|
42
|
+
team = Sem::API::Teams.update(team_name, :permission => permission)
|
43
|
+
|
44
|
+
Sem::Views::Teams.info(team)
|
45
|
+
end
|
46
|
+
|
47
|
+
desc "delete", "removes a team from your organization"
|
48
|
+
def delete(name)
|
49
|
+
Sem::API::Teams.delete(name)
|
50
|
+
|
51
|
+
puts "Deleted team #{name}"
|
52
|
+
end
|
53
|
+
|
54
|
+
class Members < Dracula
|
55
|
+
desc "list", "lists members of the team"
|
56
|
+
def list(team_name)
|
57
|
+
members = Sem::API::Users.list_for_team(team_name)
|
58
|
+
|
59
|
+
Sem::Views::Users.list(members)
|
60
|
+
end
|
61
|
+
|
62
|
+
desc "add", "add a user to the team"
|
63
|
+
def add(team_name, username)
|
64
|
+
Sem::API::Users.add_to_team(team_name, username)
|
65
|
+
|
66
|
+
puts "User #{username} added to the team."
|
67
|
+
end
|
68
|
+
|
69
|
+
desc "remove", "removes a user from the team"
|
70
|
+
def remove(team_name, username)
|
71
|
+
Sem::API::Users.remove_from_team(team_name, username)
|
72
|
+
|
73
|
+
puts "User #{username} removed from the team."
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
77
|
+
class Projects < Dracula
|
78
|
+
desc "list", "lists projects in a team"
|
79
|
+
def list(team_name)
|
80
|
+
projects = Sem::API::Projects.list_for_team(team_name)
|
81
|
+
|
82
|
+
Sem::Views::Projects.list(projects)
|
83
|
+
end
|
84
|
+
|
85
|
+
desc "add", "add a project to a team"
|
86
|
+
def add(team_name, project_name)
|
87
|
+
Sem::API::Projects.add_to_team(team_name, project_name)
|
88
|
+
|
89
|
+
puts "Project #{project_name} added to the team."
|
90
|
+
end
|
91
|
+
|
92
|
+
desc "remove", "removes a project from the team"
|
93
|
+
def remove(team_name, project_name)
|
94
|
+
Sem::API::Projects.remove_from_team(team_name, project_name)
|
95
|
+
|
96
|
+
puts "Project #{project_name} removed from the team."
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
class SharedConfigs < Dracula
|
101
|
+
desc "list", "list shared configurations in a team"
|
102
|
+
def list(team_name)
|
103
|
+
configs = Sem::API::SharedConfigs.list_for_team(team_name)
|
104
|
+
|
105
|
+
Sem::Views::SharedConfigs.list(configs)
|
106
|
+
end
|
107
|
+
|
108
|
+
desc "add", "add a shared configuration to a team"
|
109
|
+
def add(team_name, shared_config_name)
|
110
|
+
Sem::API::SharedConfigs.add_to_team(team_name, shared_config_name)
|
111
|
+
|
112
|
+
puts "Shared Configuration #{shared_config_name} added to the team."
|
113
|
+
end
|
114
|
+
|
115
|
+
desc "remove", "removes a project from the team"
|
116
|
+
def remove(team_name, shared_config_name)
|
117
|
+
Sem::API::SharedConfigs.remove_from_team(team_name, shared_config_name)
|
118
|
+
|
119
|
+
puts "Shared Configuration #{shared_config_name} removed from the team."
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
register "members", "manage team members", Members
|
124
|
+
register "projects", "manage team members", Projects
|
125
|
+
register "shared-configs", "manage shared configurations", SharedConfigs
|
126
|
+
end
|
data/lib/sem/errors.rb
ADDED
data/lib/sem/version.rb
ADDED
data/lib/sem/views.rb
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
class Sem::Views::EnvVars < Sem::Views::Base
|
2
|
+
|
3
|
+
def self.list(env_vars)
|
4
|
+
header = ["ID", "NAME", "ENCRYPTED?", "CONTENT"]
|
5
|
+
|
6
|
+
body = env_vars.map do |env_var|
|
7
|
+
[env_var[:id], env_var[:name], env_var[:encrypted?], env_var[:content]]
|
8
|
+
end
|
9
|
+
|
10
|
+
print_table([header, *body])
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Sem::Views::Orgs < Sem::Views::Base
|
2
|
+
|
3
|
+
def self.list(orgs)
|
4
|
+
header = ["ID", "NAME"]
|
5
|
+
|
6
|
+
body = orgs.map do |org|
|
7
|
+
[org[:id], org[:username]]
|
8
|
+
end
|
9
|
+
|
10
|
+
print_table [header, *body]
|
11
|
+
end
|
12
|
+
|
13
|
+
def self.info(org)
|
14
|
+
print_table [
|
15
|
+
["ID", org[:id]],
|
16
|
+
["Name", org[:username]],
|
17
|
+
["Created", org[:created_at]],
|
18
|
+
["Updated", org[:updated_at]]
|
19
|
+
]
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|