sem 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/.rspec +2 -0
  4. data/.rubocop.yml +103 -0
  5. data/Gemfile +6 -0
  6. data/README.md +27 -0
  7. data/Rakefile +10 -0
  8. data/bin/console +14 -0
  9. data/bin/setup +8 -0
  10. data/exe/sem +5 -0
  11. data/guides.md +168 -0
  12. data/ids.md +74 -0
  13. data/lib/sem.rb +53 -0
  14. data/lib/sem/api.rb +14 -0
  15. data/lib/sem/api/base.rb +17 -0
  16. data/lib/sem/api/env_vars.rb +20 -0
  17. data/lib/sem/api/files.rb +19 -0
  18. data/lib/sem/api/orgs.rb +54 -0
  19. data/lib/sem/api/projects.rb +33 -0
  20. data/lib/sem/api/shared_configs.rb +75 -0
  21. data/lib/sem/api/teams.rb +54 -0
  22. data/lib/sem/api/traits.rb +9 -0
  23. data/lib/sem/api/traits/associated_with_org.rb +13 -0
  24. data/lib/sem/api/traits/associated_with_shared_config.rb +29 -0
  25. data/lib/sem/api/traits/associated_with_team.rb +29 -0
  26. data/lib/sem/api/users.rb +26 -0
  27. data/lib/sem/api/users_with_permissions.rb +53 -0
  28. data/lib/sem/cli.rb +20 -0
  29. data/lib/sem/cli/orgs.rb +45 -0
  30. data/lib/sem/cli/projects.rb +17 -0
  31. data/lib/sem/cli/shared_configs.rb +97 -0
  32. data/lib/sem/cli/teams.rb +126 -0
  33. data/lib/sem/errors.rb +8 -0
  34. data/lib/sem/version.rb +3 -0
  35. data/lib/sem/views.rb +7 -0
  36. data/lib/sem/views/base.rb +7 -0
  37. data/lib/sem/views/env_vars.rb +13 -0
  38. data/lib/sem/views/files.rb +13 -0
  39. data/lib/sem/views/orgs.rb +22 -0
  40. data/lib/sem/views/projects.rb +22 -0
  41. data/lib/sem/views/shared_configs.rb +24 -0
  42. data/lib/sem/views/teams.rb +24 -0
  43. data/lib/sem/views/users.rb +13 -0
  44. data/lib/sem/views/users_with_permissions.rb +13 -0
  45. data/sem.gemspec +33 -0
  46. metadata +201 -0
data/lib/sem.rb ADDED
@@ -0,0 +1,53 @@
1
+ require "sem/version"
2
+ require "dracula"
3
+ require "semaphore_client"
4
+
5
+ module Sem
6
+ require "sem/errors"
7
+ require "sem/cli"
8
+ require "sem/api"
9
+ require "sem/views"
10
+
11
+ # Returns exit status as a number.
12
+ def self.start(args)
13
+ Sem::CLI.start(args)
14
+
15
+ 0
16
+ rescue Sem::Errors::Auth::NoCredentials
17
+ on_no_credentials
18
+
19
+ 1
20
+ rescue Sem::Errors::Auth::InvalidCredentials
21
+ on_invalid_credentials
22
+
23
+ 1
24
+ rescue StandardError => e
25
+ on_unhandled_error(e)
26
+
27
+ 1
28
+ end
29
+
30
+ private_class_method def self.on_no_credentials
31
+ puts "[ERROR] You are not logged in."
32
+ puts ""
33
+ puts "Log in with '#{Sem::CLI.program_name} login --auth-token <token>'"
34
+ end
35
+
36
+ private_class_method def self.on_invalid_credentials
37
+ puts "[ERROR] Your credentials are invalid."
38
+ puts ""
39
+ puts "Log in with '#{Sem::CLI.program_name} login --auth-token <token>'"
40
+ end
41
+
42
+ private_class_method def self.on_unhandled_error(exception)
43
+ puts "[PANIC] Unhandled error."
44
+ puts ""
45
+ puts "Well, this is emberassing. An unknown error was detected."
46
+ puts ""
47
+ puts "Backtrace: "
48
+ puts exception.backtrace
49
+ puts ""
50
+ puts "Please report this issue to https://semaphoreci.com/support."
51
+ end
52
+
53
+ end
data/lib/sem/api.rb ADDED
@@ -0,0 +1,14 @@
1
+ module Sem
2
+ module API
3
+ require_relative "api/traits"
4
+ require_relative "api/base"
5
+ require_relative "api/users_with_permissions"
6
+ require_relative "api/orgs"
7
+ require_relative "api/users"
8
+ require_relative "api/projects"
9
+ require_relative "api/env_vars"
10
+ require_relative "api/files"
11
+ require_relative "api/shared_configs"
12
+ require_relative "api/teams"
13
+ end
14
+ end
@@ -0,0 +1,17 @@
1
+ module Sem
2
+ module API
3
+ class Base
4
+ CREDENTIALS_PATH = "~/.sem/credentials".freeze
5
+
6
+ def self.client
7
+ @client ||= begin
8
+ path = File.expand_path(CREDENTIALS_PATH)
9
+
10
+ auth_token = File.read(path).delete("\n")
11
+
12
+ SemaphoreClient.new(auth_token)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,20 @@
1
+ module Sem
2
+ module API
3
+ class EnvVars < Base
4
+ extend Traits::AssociatedWithSharedConfig
5
+
6
+ def self.api
7
+ client.env_vars
8
+ end
9
+
10
+ def self.to_hash(env_var)
11
+ {
12
+ :id => env_var.id,
13
+ :name => env_var.name,
14
+ :encrypted? => env_var.encrypted,
15
+ :content => env_var.content
16
+ }
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,19 @@
1
+ module Sem
2
+ module API
3
+ class Files < Base
4
+ extend Traits::AssociatedWithSharedConfig
5
+
6
+ def self.api
7
+ client.config_files
8
+ end
9
+
10
+ def self.to_hash(files)
11
+ {
12
+ :id => files.id,
13
+ :name => files.path,
14
+ :encrypted? => files.encrypted
15
+ }
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,54 @@
1
+ module Sem
2
+ module API
3
+ class Orgs < Base
4
+ def self.list
5
+ orgs = api.list
6
+
7
+ orgs.map { |org| to_hash(org) }
8
+ end
9
+
10
+ def self.info(name)
11
+ org = api.get(name)
12
+
13
+ to_hash(org)
14
+ end
15
+
16
+ def self.list_teams(org_name)
17
+ Sem::API::Teams.list_for_org(org_name)
18
+ end
19
+
20
+ def self.list_users(org_name)
21
+ Sem::API::Users.list_for_org(org_name)
22
+ end
23
+
24
+ def self.list_admins(org_name)
25
+ admin_teams = list_teams(org_name).select { |team| team[:permission] == "admin" }
26
+
27
+ admins = admin_teams.map { |team| client.users.list_for_team(team[:id]) }.flatten
28
+
29
+ admins.map { |admin| Sem::API::Users.to_hash(admin) }
30
+ end
31
+
32
+ def self.list_owners(org_name)
33
+ owners_team = list_teams(org_name).find { |team| team[:name] == "Owners" }
34
+
35
+ owners = client.users.list_for_team(owners_team[:id])
36
+
37
+ owners.map { |owner| Sem::API::Users.to_hash(owner) }
38
+ end
39
+
40
+ def self.api
41
+ client.orgs
42
+ end
43
+
44
+ def self.to_hash(org)
45
+ {
46
+ :id => org.id,
47
+ :username => org.username,
48
+ :created_at => org.created_at,
49
+ :updated_at => org.updated_at
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,33 @@
1
+ module Sem
2
+ module API
3
+ class Projects < Base
4
+ extend Traits::AssociatedWithOrg
5
+ extend Traits::AssociatedWithTeam
6
+
7
+ def self.list
8
+ org_names = Orgs.list.map { |org| org[:username] }
9
+
10
+ org_names.map { |name| list_for_org(name) }.flatten
11
+ end
12
+
13
+ def self.info(path)
14
+ org_name, project_name = path.split("/")
15
+
16
+ list_for_org(org_name).find { |project| project[:name] == project_name }
17
+ end
18
+
19
+ def self.api
20
+ client.projects
21
+ end
22
+
23
+ def self.to_hash(project)
24
+ {
25
+ :id => project.id,
26
+ :name => project.name,
27
+ :created_at => project.created_at,
28
+ :updated_at => project.updated_at
29
+ }
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,75 @@
1
+ module Sem
2
+ module API
3
+ class SharedConfigs < Base
4
+ extend Traits::AssociatedWithTeam
5
+ extend Traits::AssociatedWithOrg
6
+
7
+ def self.list
8
+ org_names = Orgs.list.map { |org| org[:username] }
9
+
10
+ org_names.map { |name| list_for_org(name) }.flatten
11
+ end
12
+
13
+ def self.info(path)
14
+ org_name, config_name = path.split("/")
15
+
16
+ list_for_org(org_name).find { |config| config[:name] == config_name }
17
+ end
18
+
19
+ def self.create(org_name, args)
20
+ config = api.create_for_org(org_name, args)
21
+
22
+ to_hash(config)
23
+ end
24
+
25
+ def self.update(path, args)
26
+ shared_config = info(path)
27
+
28
+ shared_config = api.update(shared_config[:id], args)
29
+
30
+ to_hash(shared_config)
31
+ end
32
+
33
+ def self.delete(path)
34
+ id = info(path)[:id]
35
+
36
+ api.delete(id)
37
+ end
38
+
39
+ def self.list_env_vars(path)
40
+ Sem::API::EnvVars.list_for_shared_config(path)
41
+ end
42
+
43
+ def self.list_files(path)
44
+ Sem::API::Files.list_for_shared_config(path)
45
+ end
46
+
47
+ def self.api
48
+ client.shared_configs
49
+ end
50
+
51
+ def self.to_hash(config)
52
+ {
53
+ :id => config.id,
54
+ :name => config.name,
55
+ :config_files => config_files_count(config.id),
56
+ :env_vars => env_vars_count(config.id),
57
+ :created_at => config.created_at,
58
+ :updated_at => config.updated_at
59
+ }
60
+ end
61
+
62
+ class << self
63
+ private
64
+
65
+ def config_files_count(config_id)
66
+ client.config_files.list_for_shared_config(config_id).to_a.size
67
+ end
68
+
69
+ def env_vars_count(config_id)
70
+ client.env_vars.list_for_shared_config(config_id).to_a.size
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,54 @@
1
+ module Sem
2
+ module API
3
+ class Teams < Base
4
+ extend Traits::AssociatedWithOrg
5
+
6
+ def self.list
7
+ org_names = Sem::API::Orgs.list.map { |org| org[:username] }
8
+
9
+ org_names.map { |name| list_for_org(name) }.flatten
10
+ end
11
+
12
+ def self.info(path)
13
+ org_name, team_name = path.split("/")
14
+
15
+ list_for_org(org_name).find { |team| team[:name] == team_name }
16
+ end
17
+
18
+ def self.create(org_name, args)
19
+ team = api.create_for_org(org_name, args)
20
+
21
+ to_hash(team)
22
+ end
23
+
24
+ def self.update(path, args)
25
+ team = info(path)
26
+
27
+ team = api.update(team[:id], args)
28
+
29
+ to_hash(team)
30
+ end
31
+
32
+ def self.delete(path)
33
+ id = info(path)[:id]
34
+
35
+ api.delete(id)
36
+ end
37
+
38
+ def self.api
39
+ client.teams
40
+ end
41
+
42
+ def self.to_hash(team)
43
+ {
44
+ :id => team.id,
45
+ :name => team.name,
46
+ :permission => team.permission,
47
+ :members => client.users.list_for_team(team.id).count.to_s,
48
+ :created_at => team.created_at,
49
+ :updated_at => team.updated_at
50
+ }
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,9 @@
1
+ module Sem
2
+ module API
3
+ module Traits
4
+ require_relative "traits/associated_with_org"
5
+ require_relative "traits/associated_with_team"
6
+ require_relative "traits/associated_with_shared_config"
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ module Sem
2
+ module API
3
+ module Traits
4
+ module AssociatedWithOrg
5
+ def list_for_org(org_name)
6
+ instances = api.list_for_org(org_name)
7
+
8
+ instances.map { |instance| to_hash(instance) }
9
+ end
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ module Sem
2
+ module API
3
+ module Traits
4
+ module AssociatedWithSharedConfig
5
+ def list_for_shared_config(shared_config_path)
6
+ shared_config = SharedConfigs.info(shared_config_path)
7
+
8
+ instances = api.list_for_shared_config(shared_config[:id])
9
+
10
+ instances.map { |instance| to_hash(instance) }
11
+ end
12
+
13
+ def add_to_shared_config(shared_config_path, params)
14
+ shared_config = SharedConfigs.info(shared_config_path)
15
+
16
+ api.create_for_shared_config(shared_config[:id], params)
17
+ end
18
+
19
+ def remove_from_shared_config(shared_config_path, instance_name)
20
+ instances = list_for_shared_config(shared_config_path)
21
+
22
+ selected_instance = instances.find { |instance| instance[:name] == instance_name }
23
+
24
+ api.delete(selected_instance[:id])
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,29 @@
1
+ module Sem
2
+ module API
3
+ module Traits
4
+ module AssociatedWithTeam
5
+ def list_for_team(team_path)
6
+ team = Teams.info(team_path)
7
+
8
+ instances = api.list_for_team(team[:id])
9
+
10
+ instances.map { |instance| to_hash(instance) }
11
+ end
12
+
13
+ def add_to_team(team_path, instance_path)
14
+ instance = info(instance_path)
15
+ team = Teams.info(team_path)
16
+
17
+ api.attach_to_team(instance[:id], team[:id])
18
+ end
19
+
20
+ def remove_from_team(team_path, instance_path)
21
+ instance = info(instance_path)
22
+ team = Teams.info(team_path)
23
+
24
+ api.detach_from_team(instance[:id], team[:id])
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ module Sem
2
+ module API
3
+ class Users < Base
4
+ extend Traits::AssociatedWithOrg
5
+ extend Traits::AssociatedWithTeam
6
+
7
+ def self.list
8
+ org_names = Orgs.list.map { |org| org[:username] }
9
+
10
+ org_names.map { |name| list_for_org(name) }.flatten
11
+ end
12
+
13
+ def self.info(name)
14
+ list.find { |user| user[:id] == name }
15
+ end
16
+
17
+ def self.api
18
+ client.users
19
+ end
20
+
21
+ def self.to_hash(user)
22
+ { :id => user.username }
23
+ end
24
+ end
25
+ end
26
+ end