sem 0.1.4 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +17 -0
- data/lib/sem/api/base.rb +7 -5
- data/lib/sem/api/env_vars.rb +12 -10
- data/lib/sem/api/files.rb +11 -9
- data/lib/sem/api/orgs.rb +27 -39
- data/lib/sem/api/projects.rb +27 -18
- data/lib/sem/api/shared_configs.rb +73 -45
- data/lib/sem/api/teams.rb +48 -33
- data/lib/sem/api/traits/associated_with_org.rb +6 -2
- data/lib/sem/api/traits/associated_with_project.rb +29 -0
- data/lib/sem/api/traits/associated_with_shared_config.rb +9 -7
- data/lib/sem/api/traits/associated_with_team.rb +12 -12
- data/lib/sem/api/traits.rb +1 -0
- data/lib/sem/api/users.rb +30 -12
- data/lib/sem/api.rb +0 -1
- data/lib/sem/cli/orgs.rb +11 -28
- data/lib/sem/cli/projects.rb +46 -3
- data/lib/sem/cli/shared_configs.rb +57 -30
- data/lib/sem/cli/teams.rb +101 -45
- data/lib/sem/cli.rb +21 -4
- data/lib/sem/configuration.rb +48 -0
- data/lib/sem/errors.rb +33 -0
- data/lib/sem/pagination.rb +29 -0
- data/lib/sem/srn.rb +42 -0
- data/lib/sem/version.rb +1 -1
- data/lib/sem/views/base.rb +8 -3
- data/lib/sem/views/orgs.rb +9 -0
- data/lib/sem/views/projects.rb +31 -14
- data/lib/sem/views/shared_configs.rb +11 -0
- data/lib/sem/views/teams.rb +68 -16
- data/lib/sem/views/users.rb +5 -7
- data/lib/sem.rb +35 -2
- data/sem.gemspec +4 -3
- metadata +28 -13
- data/lib/sem/api/users_with_permissions.rb +0 -57
- data/lib/sem/credentials.rb +0 -19
- data/lib/sem/views/users_with_permissions.rb +0 -13
data/lib/sem/api/users.rb
CHANGED
@@ -4,22 +4,40 @@ module Sem
|
|
4
4
|
extend Traits::AssociatedWithOrg
|
5
5
|
extend Traits::AssociatedWithTeam
|
6
6
|
|
7
|
-
|
8
|
-
|
7
|
+
class << self
|
8
|
+
def name_to_id(_, name)
|
9
|
+
name
|
10
|
+
end
|
9
11
|
|
10
|
-
|
11
|
-
|
12
|
+
def list
|
13
|
+
org_names = Orgs.list.map { |org| org[:username] }
|
12
14
|
|
13
|
-
|
14
|
-
|
15
|
-
end
|
15
|
+
org_names.pmap { |name| list_for_org(name) }.flatten
|
16
|
+
end
|
16
17
|
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
def info(*args)
|
19
|
+
if args.count == 2
|
20
|
+
org_name, user_name = args
|
21
|
+
users = list_for_org(org_name)
|
22
|
+
else
|
23
|
+
user_name = args.first
|
24
|
+
users = list
|
25
|
+
end
|
26
|
+
|
27
|
+
selected_user = users.find { |user| user[:id] == user_name }
|
28
|
+
|
29
|
+
raise Sem::Errors::ResourceNotFound.new("User", [user_name]) if selected_user.nil?
|
30
|
+
|
31
|
+
selected_user
|
32
|
+
end
|
33
|
+
|
34
|
+
def api
|
35
|
+
client.users
|
36
|
+
end
|
20
37
|
|
21
|
-
|
22
|
-
|
38
|
+
def to_hash(user, _ = nil)
|
39
|
+
{ :id => user.username }
|
40
|
+
end
|
23
41
|
end
|
24
42
|
end
|
25
43
|
end
|
data/lib/sem/api.rb
CHANGED
data/lib/sem/cli/orgs.rb
CHANGED
@@ -8,38 +8,21 @@ class Sem::CLI::Orgs < Dracula
|
|
8
8
|
end
|
9
9
|
|
10
10
|
desc "info", "shows detailed information about an organization"
|
11
|
-
def info(
|
12
|
-
|
11
|
+
def info(org)
|
12
|
+
org_name = Sem::SRN.parse_org(org).first
|
13
13
|
|
14
|
-
Sem::
|
14
|
+
org_instance = Sem::API::Orgs.info(org_name).to_h
|
15
|
+
|
16
|
+
Sem::Views::Orgs.info(org_instance)
|
15
17
|
end
|
16
18
|
|
17
19
|
desc "members", "list members of an organization"
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
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)
|
20
|
+
def members(org)
|
21
|
+
org_name = Sem::SRN.parse_org(org).first
|
22
|
+
|
23
|
+
users = Sem::API::Users.list_for_org(org_name)
|
24
|
+
|
25
|
+
Sem::Views::Users.list(users)
|
43
26
|
end
|
44
27
|
|
45
28
|
end
|
data/lib/sem/cli/projects.rb
CHANGED
@@ -8,10 +8,53 @@ class Sem::CLI::Projects < Dracula
|
|
8
8
|
end
|
9
9
|
|
10
10
|
desc "info", "shows detailed information about a project"
|
11
|
-
def info(
|
12
|
-
|
11
|
+
def info(project)
|
12
|
+
org_name, project_name = Sem::SRN.parse_project(project)
|
13
13
|
|
14
|
-
Sem::
|
14
|
+
project_instance = Sem::API::Projects.info(org_name, project_name).to_h
|
15
|
+
|
16
|
+
Sem::Views::Projects.info(project_instance)
|
17
|
+
end
|
18
|
+
|
19
|
+
class SharedConfigs < Dracula
|
20
|
+
desc "list", "list shared configurations on a project"
|
21
|
+
def list(project)
|
22
|
+
org_name, project_name = Sem::SRN.parse_project(project)
|
23
|
+
|
24
|
+
configs = Sem::API::SharedConfigs.list_for_project(org_name, project_name)
|
25
|
+
|
26
|
+
Sem::Views::SharedConfigs.list(configs)
|
27
|
+
end
|
28
|
+
|
29
|
+
desc "add", "attach a shared configuration to a project"
|
30
|
+
def add(project, shared_config)
|
31
|
+
project_org_name, project_name = Sem::SRN.parse_project(project)
|
32
|
+
shared_config_org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
33
|
+
|
34
|
+
if project_org_name != shared_config_org_name
|
35
|
+
abort Sem::Views::Projects.org_names_not_matching("project", "shared configuration", project, shared_config)
|
36
|
+
end
|
37
|
+
|
38
|
+
Sem::API::SharedConfigs.add_to_project(project_org_name, project_name, shared_config_name)
|
39
|
+
|
40
|
+
puts "Shared Configuration #{project_org_name}/#{shared_config_name} added to the project."
|
41
|
+
end
|
42
|
+
|
43
|
+
desc "remove", "removes a shared configuration from the project"
|
44
|
+
def remove(project, shared_config)
|
45
|
+
project_org_name, project_name = Sem::SRN.parse_project(project)
|
46
|
+
shared_config_org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
47
|
+
|
48
|
+
if project_org_name != shared_config_org_name
|
49
|
+
abort Sem::Views::Projects.org_names_not_matching("project", "shared configuration", project, shared_config)
|
50
|
+
end
|
51
|
+
|
52
|
+
Sem::API::SharedConfigs.remove_from_project(project_org_name, project_name, shared_config_name)
|
53
|
+
|
54
|
+
puts "Shared Configuration #{project_org_name}/#{shared_config_name} removed from the project."
|
55
|
+
end
|
15
56
|
end
|
16
57
|
|
58
|
+
register "shared-configs", "manage shared configurations", SharedConfigs
|
59
|
+
|
17
60
|
end
|
@@ -8,67 +8,89 @@ class Sem::CLI::SharedConfigs < Dracula
|
|
8
8
|
end
|
9
9
|
|
10
10
|
desc "info", "show information about a shared configuration"
|
11
|
-
def info(
|
12
|
-
|
11
|
+
def info(shared_config)
|
12
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
13
13
|
|
14
|
-
Sem::
|
14
|
+
shared_config_instance = Sem::API::SharedConfigs.info(org_name, shared_config_name).to_h
|
15
|
+
|
16
|
+
Sem::Views::SharedConfigs.info(shared_config_instance)
|
15
17
|
end
|
16
18
|
|
17
19
|
desc "create", "create a new shared configuration"
|
18
|
-
def create(
|
19
|
-
org_name, shared_config_name =
|
20
|
+
def create(shared_config)
|
21
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
20
22
|
|
21
|
-
|
23
|
+
shared_config_instance = Sem::API::SharedConfigs.create(org_name, :name => shared_config_name)
|
22
24
|
|
23
|
-
Sem::Views::SharedConfigs.info(
|
25
|
+
Sem::Views::SharedConfigs.info(shared_config_instance)
|
24
26
|
end
|
25
27
|
|
26
28
|
desc "rename", "rename a shared configuration"
|
27
|
-
def rename(
|
28
|
-
|
29
|
+
def rename(old_shared_config, new_shared_config)
|
30
|
+
old_org_name, old_shared_config_name = Sem::SRN.parse_shared_config(old_shared_config)
|
31
|
+
new_org_name, new_shared_config_name = Sem::SRN.parse_shared_config(new_shared_config)
|
32
|
+
|
33
|
+
if old_org_name != new_org_name
|
34
|
+
abort Sem::Views::SharedConfigs.org_names_not_matching("old shared configuration name",
|
35
|
+
"new shared configuration name",
|
36
|
+
old_shared_config,
|
37
|
+
new_shared_config)
|
38
|
+
end
|
29
39
|
|
30
|
-
|
40
|
+
shared_config_instance = Sem::API::SharedConfigs.update(old_org_name,
|
41
|
+
old_shared_config_name,
|
42
|
+
:name => new_shared_config_name)
|
31
43
|
|
32
|
-
Sem::Views::SharedConfigs.info(
|
44
|
+
Sem::Views::SharedConfigs.info(shared_config_instance)
|
33
45
|
end
|
34
46
|
|
35
47
|
desc "delete", "removes a shared configuration from your organization"
|
36
|
-
def delete(
|
37
|
-
Sem::
|
48
|
+
def delete(shared_config)
|
49
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
50
|
+
|
51
|
+
Sem::API::SharedConfigs.delete(org_name, shared_config_name)
|
38
52
|
|
39
|
-
puts "Deleted shared configuration #{
|
53
|
+
puts "Deleted shared configuration #{org_name}/#{shared_config_name}"
|
40
54
|
end
|
41
55
|
|
42
56
|
class Files < Dracula
|
43
57
|
desc "list", "list files in the shared configuration"
|
44
|
-
def list(
|
45
|
-
|
58
|
+
def list(shared_config)
|
59
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
60
|
+
|
61
|
+
files = Sem::API::SharedConfigs.list_files(org_name, shared_config_name)
|
46
62
|
|
47
63
|
Sem::Views::Files.list(files)
|
48
64
|
end
|
49
65
|
|
50
66
|
desc "add", "add a file to the shared configuration"
|
51
67
|
option :file, :aliases => "f", :desc => "File to upload", :required => true
|
52
|
-
def add(
|
68
|
+
def add(shared_config, file)
|
69
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
70
|
+
|
53
71
|
content = File.read(options[:file])
|
54
72
|
|
55
|
-
Sem::API::Files.add_to_shared_config(
|
73
|
+
Sem::API::Files.add_to_shared_config(org_name, shared_config_name, :path => file, :content => content)
|
56
74
|
|
57
|
-
puts "Added #{
|
75
|
+
puts "Added #{file} to #{org_name}/#{shared_config_name}"
|
58
76
|
end
|
59
77
|
|
60
78
|
desc "remove", "remove a file from the shared configuration"
|
61
|
-
def remove(
|
62
|
-
Sem::
|
79
|
+
def remove(shared_config, file)
|
80
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
63
81
|
|
64
|
-
|
82
|
+
Sem::API::Files.remove_from_shared_config(org_name, shared_config_name, file)
|
83
|
+
|
84
|
+
puts "Removed #{file} from #{org_name}/#{shared_config_name}"
|
65
85
|
end
|
66
86
|
end
|
67
87
|
|
68
88
|
class EnvVars < Dracula
|
69
89
|
desc "list", "list environment variables in the shared configuration"
|
70
|
-
def list(
|
71
|
-
|
90
|
+
def list(shared_config)
|
91
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
92
|
+
|
93
|
+
env_vars = Sem::API::SharedConfigs.list_env_vars(org_name, shared_config_name)
|
72
94
|
|
73
95
|
Sem::Views::EnvVars.list(env_vars)
|
74
96
|
end
|
@@ -76,19 +98,24 @@ class Sem::CLI::SharedConfigs < Dracula
|
|
76
98
|
desc "add", "add an environment variable to the shared configuration"
|
77
99
|
option :name, :aliases => "-n", :desc => "Name of the variable", :required => true
|
78
100
|
option :content, :aliases => "-c", :desc => "Content of the variable", :required => true
|
79
|
-
def add(
|
80
|
-
Sem::
|
101
|
+
def add(shared_config)
|
102
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
103
|
+
|
104
|
+
Sem::API::EnvVars.add_to_shared_config(org_name,
|
105
|
+
shared_config_name,
|
81
106
|
:name => options[:name],
|
82
107
|
:content => options[:content])
|
83
108
|
|
84
|
-
puts "Added #{options[:name]} to #{
|
109
|
+
puts "Added #{options[:name]} to #{org_name}/#{shared_config_name}"
|
85
110
|
end
|
86
111
|
|
87
112
|
desc "remove", "remove an environment variable from the shared configuration"
|
88
|
-
def remove(
|
89
|
-
Sem::
|
113
|
+
def remove(shared_config, env_var)
|
114
|
+
org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
115
|
+
|
116
|
+
Sem::API::EnvVars.remove_from_shared_config(org_name, shared_config_name, env_var)
|
90
117
|
|
91
|
-
puts "Removed #{
|
118
|
+
puts "Removed #{env_var} from #{org_name}/#{shared_config_name}"
|
92
119
|
end
|
93
120
|
end
|
94
121
|
|
data/lib/sem/cli/teams.rb
CHANGED
@@ -8,115 +8,171 @@ class Sem::CLI::Teams < Dracula
|
|
8
8
|
end
|
9
9
|
|
10
10
|
desc "info", "show information about a team"
|
11
|
-
def info(
|
12
|
-
|
11
|
+
def info(team)
|
12
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
13
13
|
|
14
|
-
Sem::
|
14
|
+
team_instance = Sem::API::Teams.info(org_name, team_name).to_h
|
15
|
+
|
16
|
+
Sem::Views::Teams.info(team_instance)
|
15
17
|
end
|
16
18
|
|
17
19
|
desc "create", "create a new team"
|
18
20
|
option :permission, :default => "read",
|
19
21
|
:aliases => "-p",
|
20
22
|
:desc => "Permission level of the team in the organization"
|
21
|
-
def create(
|
22
|
-
org_name, team_name =
|
23
|
+
def create(team)
|
24
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
26
|
+
team_instance = Sem::API::Teams.create(org_name,
|
27
|
+
:name => team_name,
|
28
|
+
:permission => options[:permission])
|
27
29
|
|
28
|
-
Sem::Views::Teams.info(
|
30
|
+
Sem::Views::Teams.info(team_instance)
|
29
31
|
end
|
30
32
|
|
31
33
|
desc "rename", "change the name of the team"
|
32
|
-
def rename(
|
33
|
-
|
34
|
+
def rename(old_team, new_team)
|
35
|
+
old_org_name, old_team_name = Sem::SRN.parse_team(old_team)
|
36
|
+
new_org_name, new_team_name = Sem::SRN.parse_team(new_team)
|
37
|
+
|
38
|
+
if old_org_name != new_org_name
|
39
|
+
abort Sem::Views::Teams.org_names_not_matching("old team name", "new team name", old_team, new_team)
|
40
|
+
end
|
34
41
|
|
35
|
-
|
42
|
+
team_instance = Sem::API::Teams.update(old_org_name, old_team_name, :name => new_team_name)
|
36
43
|
|
37
|
-
Sem::Views::Teams.info(
|
44
|
+
Sem::Views::Teams.info(team_instance)
|
38
45
|
end
|
39
46
|
|
40
47
|
desc "set-permission", "set the permission level of the team"
|
41
|
-
def set_permission(
|
42
|
-
|
48
|
+
def set_permission(team, permission)
|
49
|
+
unless ["read", "write", "admin"].include?(permission)
|
50
|
+
abort "Permission \"#{permission}\" doesn't exist.\n" \
|
51
|
+
"Choose one of the following: read, write, admin."
|
52
|
+
end
|
53
|
+
|
54
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
55
|
+
|
56
|
+
team_instance = Sem::API::Teams.update(org_name, team_name, :permission => permission)
|
43
57
|
|
44
|
-
Sem::Views::Teams.info(
|
58
|
+
Sem::Views::Teams.info(team_instance)
|
45
59
|
end
|
46
60
|
|
47
61
|
desc "delete", "removes a team from your organization"
|
48
|
-
def delete(
|
49
|
-
Sem::
|
62
|
+
def delete(team)
|
63
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
50
64
|
|
51
|
-
|
65
|
+
Sem::API::Teams.delete(org_name, team_name)
|
66
|
+
|
67
|
+
puts "Deleted team #{org_name}/#{team_name}"
|
52
68
|
end
|
53
69
|
|
54
70
|
class Members < Dracula
|
55
71
|
desc "list", "lists members of the team"
|
56
|
-
def list(
|
57
|
-
|
72
|
+
def list(team)
|
73
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
74
|
+
|
75
|
+
members = Sem::API::Users.list_for_team(org_name, team_name)
|
58
76
|
|
59
|
-
Sem::Views::
|
77
|
+
Sem::Views::Teams.list_members(team, members)
|
60
78
|
end
|
61
79
|
|
62
80
|
desc "add", "add a user to the team"
|
63
|
-
def add(
|
64
|
-
Sem::
|
81
|
+
def add(team, user)
|
82
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
83
|
+
user_name = Sem::SRN.parse_user(user).first
|
84
|
+
|
85
|
+
Sem::API::Users.add_to_team(org_name, team_name, user_name)
|
65
86
|
|
66
|
-
puts "User #{
|
87
|
+
puts "User #{user_name} added to the team."
|
67
88
|
end
|
68
89
|
|
69
90
|
desc "remove", "removes a user from the team"
|
70
|
-
def remove(
|
71
|
-
Sem::
|
91
|
+
def remove(team, user)
|
92
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
93
|
+
user_name = Sem::SRN.parse_user(user).first
|
72
94
|
|
73
|
-
|
95
|
+
Sem::API::Users.remove_from_team(org_name, team_name, user_name)
|
96
|
+
|
97
|
+
puts "User #{user_name} removed from the team."
|
74
98
|
end
|
75
99
|
end
|
76
100
|
|
77
101
|
class Projects < Dracula
|
78
102
|
desc "list", "lists projects in a team"
|
79
|
-
def list(
|
80
|
-
|
103
|
+
def list(team)
|
104
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
105
|
+
|
106
|
+
projects = Sem::API::Projects.list_for_team(org_name, team_name)
|
81
107
|
|
82
108
|
Sem::Views::Projects.list(projects)
|
83
109
|
end
|
84
110
|
|
85
111
|
desc "add", "add a project to a team"
|
86
|
-
def add(
|
87
|
-
Sem::
|
112
|
+
def add(team, project)
|
113
|
+
team_org_name, team_name = Sem::SRN.parse_team(team)
|
114
|
+
project_org_name, project_name = Sem::SRN.parse_project(project)
|
88
115
|
|
89
|
-
|
116
|
+
if team_org_name != project_org_name
|
117
|
+
abort Sem::Views::Teams.org_names_not_matching("team", "project", team, project)
|
118
|
+
end
|
119
|
+
|
120
|
+
Sem::API::Projects.add_to_team(team_org_name, team_name, project_name)
|
121
|
+
|
122
|
+
puts "Project #{team_org_name}/#{project_name} added to the team."
|
90
123
|
end
|
91
124
|
|
92
125
|
desc "remove", "removes a project from the team"
|
93
|
-
def remove(
|
94
|
-
Sem::
|
126
|
+
def remove(team, project)
|
127
|
+
team_org_name, team_name = Sem::SRN.parse_team(team)
|
128
|
+
project_org_name, project_name = Sem::SRN.parse_project(project)
|
129
|
+
|
130
|
+
if team_org_name != project_org_name
|
131
|
+
abort Sem::Views::Teams.org_names_not_matching("team", "project", team, project)
|
132
|
+
end
|
95
133
|
|
96
|
-
|
134
|
+
Sem::API::Projects.remove_from_team(team_org_name, team_name, project_name)
|
135
|
+
|
136
|
+
puts "Project #{team_org_name}/#{project_name} removed from the team."
|
97
137
|
end
|
98
138
|
end
|
99
139
|
|
100
140
|
class SharedConfigs < Dracula
|
101
141
|
desc "list", "list shared configurations in a team"
|
102
|
-
def list(
|
103
|
-
|
142
|
+
def list(team)
|
143
|
+
org_name, team_name = Sem::SRN.parse_team(team)
|
144
|
+
|
145
|
+
configs = Sem::API::SharedConfigs.list_for_team(org_name, team_name)
|
104
146
|
|
105
147
|
Sem::Views::SharedConfigs.list(configs)
|
106
148
|
end
|
107
149
|
|
108
150
|
desc "add", "add a shared configuration to a team"
|
109
|
-
def add(
|
110
|
-
Sem::
|
151
|
+
def add(team, shared_config)
|
152
|
+
team_org_name, team_name = Sem::SRN.parse_team(team)
|
153
|
+
shared_config_org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
111
154
|
|
112
|
-
|
155
|
+
if team_org_name != shared_config_org_name
|
156
|
+
abort Sem::Views::Teams.org_names_not_matching("team", "shared configuration", team, shared_config)
|
157
|
+
end
|
158
|
+
|
159
|
+
Sem::API::SharedConfigs.add_to_team(team_org_name, team_name, shared_config_name)
|
160
|
+
|
161
|
+
puts "Shared Configuration #{team_org_name}/#{shared_config_name} added to the team."
|
113
162
|
end
|
114
163
|
|
115
|
-
desc "remove", "removes a
|
116
|
-
def remove(
|
117
|
-
Sem::
|
164
|
+
desc "remove", "removes a shared Configuration from the team"
|
165
|
+
def remove(team, shared_config)
|
166
|
+
team_org_name, team_name = Sem::SRN.parse_team(team)
|
167
|
+
shared_config_org_name, shared_config_name = Sem::SRN.parse_shared_config(shared_config)
|
168
|
+
|
169
|
+
if team_org_name != shared_config_org_name
|
170
|
+
abort Sem::Views::Teams.org_names_not_matching("team", "shared configuration", team, shared_config)
|
171
|
+
end
|
172
|
+
|
173
|
+
Sem::API::SharedConfigs.remove_from_team(team_org_name, team_name, shared_config_name)
|
118
174
|
|
119
|
-
puts "Shared Configuration #{shared_config_name} removed from the team."
|
175
|
+
puts "Shared Configuration #{team_org_name}/#{shared_config_name} removed from the team."
|
120
176
|
end
|
121
177
|
end
|
122
178
|
|
data/lib/sem/cli.rb
CHANGED
@@ -7,11 +7,28 @@ module Sem
|
|
7
7
|
require_relative "cli/teams"
|
8
8
|
require_relative "cli/shared_configs"
|
9
9
|
|
10
|
-
desc "login", "
|
11
|
-
|
12
|
-
|
10
|
+
desc "login", "Log in to semaphore from the command line"
|
11
|
+
option :auth_token, :required => true
|
12
|
+
long_desc <<-DESC
|
13
|
+
You can find your auth_token on the bottom of the users settings page https://semaphoreci.com/users/edit.
|
14
|
+
DESC
|
15
|
+
def login
|
16
|
+
auth_token = options[:auth_token]
|
13
17
|
|
14
|
-
|
18
|
+
if Sem::Configuration.valid_auth_token?(auth_token)
|
19
|
+
Sem::Configuration.export_auth_token(auth_token)
|
20
|
+
|
21
|
+
puts "Your credentials have been saved to #{Sem::Configuration::CREDENTIALS_PATH}."
|
22
|
+
else
|
23
|
+
abort "[ERROR] Token is invalid!"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
desc "logout", "Log out from semaphore"
|
28
|
+
def logout
|
29
|
+
Sem::Configuration.delete_auth_token
|
30
|
+
|
31
|
+
puts "Loged out."
|
15
32
|
end
|
16
33
|
|
17
34
|
register "orgs", "manage organizations", Sem::CLI::Orgs
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module Sem
|
2
|
+
class Configuration
|
3
|
+
CREDENTIALS_PATH = File.expand_path("~/.sem/credentials").freeze
|
4
|
+
API_URL_PATH = File.expand_path("~/.sem/api_url").freeze
|
5
|
+
|
6
|
+
DEFAULT_API_URL = "https://api.semaphoreci.com".freeze
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def valid_auth_token?(auth_token)
|
10
|
+
client = SemaphoreClient.new(
|
11
|
+
auth_token,
|
12
|
+
:api_url => api_url,
|
13
|
+
:verbose => (Sem.log_level == Sem::LOG_LEVEL_TRACE)
|
14
|
+
)
|
15
|
+
|
16
|
+
client.orgs.list!
|
17
|
+
|
18
|
+
true
|
19
|
+
rescue SemaphoreClient::Exceptions::RequestFailed
|
20
|
+
false
|
21
|
+
end
|
22
|
+
|
23
|
+
def export_auth_token(auth_token)
|
24
|
+
dirname = File.dirname(CREDENTIALS_PATH)
|
25
|
+
FileUtils.mkdir_p(dirname)
|
26
|
+
|
27
|
+
File.write(CREDENTIALS_PATH, auth_token)
|
28
|
+
File.chmod(0o0600, CREDENTIALS_PATH)
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete_auth_token
|
32
|
+
FileUtils.rm_f(CREDENTIALS_PATH)
|
33
|
+
end
|
34
|
+
|
35
|
+
def auth_token
|
36
|
+
raise Sem::Errors::Auth::NoCredentials unless File.file?(CREDENTIALS_PATH)
|
37
|
+
|
38
|
+
File.read(CREDENTIALS_PATH).strip
|
39
|
+
end
|
40
|
+
|
41
|
+
def api_url
|
42
|
+
return DEFAULT_API_URL unless File.file?(API_URL_PATH)
|
43
|
+
|
44
|
+
File.read(API_URL_PATH).strip
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
data/lib/sem/errors.rb
CHANGED
@@ -1,6 +1,39 @@
|
|
1
1
|
module Sem::Errors
|
2
2
|
Base = Class.new(StandardError)
|
3
3
|
|
4
|
+
InvalidSRN = Class.new(StandardError)
|
5
|
+
|
6
|
+
class ResourceException < Base
|
7
|
+
def initialize(resource, path)
|
8
|
+
@resource = resource
|
9
|
+
@path = path
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
class ResourceNotFound < ResourceException
|
14
|
+
def message
|
15
|
+
"[ERROR] #{@resource} lookup failed\n\n#{@resource} #{@path.join("/")} not found."
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
class ResourceNotCreated < ResourceException
|
20
|
+
def message
|
21
|
+
"[ERROR] #{@resource} creation failed\n\n#{@resource} #{@path.join("/")} not created."
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ResourceNotUpdated < ResourceException
|
26
|
+
def message
|
27
|
+
"[ERROR] #{@resource} update failed\n\n#{@resource} #{@path.join("/")} not updated."
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class ResourceNotDeleted < ResourceException
|
32
|
+
def message
|
33
|
+
"[ERROR] #{@resource} deletion failed\n\n#{@resource} #{@path.join("/")} not deleted."
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
4
37
|
module Auth
|
5
38
|
NoCredentials = Class.new(Sem::Errors::Base)
|
6
39
|
InvalidCredentials = Class.new(Sem::Errors::Base)
|