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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 69ad26460c2a5f0370942054823818fd4628feb0
4
- data.tar.gz: 3d66bfd1e6a4a0fc87ee9e34ac3a27795754774d
3
+ metadata.gz: ccd122f3ce04fc09324bb135463966fd91fe5d90
4
+ data.tar.gz: aff41dee6b2352c2844beb298c8a0ed5268ff5d0
5
5
  SHA512:
6
- metadata.gz: 26889f21ff8805815526af5f70db424d007cf23ffec5b6978b18559a56427d4890d5baa95685545d1d110350b1407786a7a36d92f7306951529ecd13d11c011f
7
- data.tar.gz: 687430ea92a6f952405e5a3a8983d301243bb58bef6fa8c58b2aa9135b20f7ee57bf36d8f8abd92f0536ba7d9928da00e6a91f8d25ecf3fa0f5551aca33cef8d
6
+ metadata.gz: fa93e1e6a31b3f5faf0ea12a32e1178acf2c3fa041105d403b95659b1321d75819b1862f3524fbcd64015f506a6736bf10ab50b82dab69097b85d030f2010448
7
+ data.tar.gz: a59bc4d8e6248700231099d8f36bac604bd7f0bfc6a15817addb1774b2b7b6082e58b7b2c784cb200a58d83785da1dffebc7279d90f77b086a679dc83ddc5d07
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # Semaphore CLI
2
2
 
3
3
  [![Build Status](https://semaphoreci.com/api/v1/renderedtext/cli/branches/master/badge.svg)](https://semaphoreci.com/renderedtext/cli)
4
+ [![Gem Version](https://badge.fury.io/rb/sem.svg)](https://badge.fury.io/rb/sem)
4
5
 
5
6
  ![Semaphore logo](https://d1dkupr86d302v.cloudfront.net/assets/application_bootstrap/layout/semaphore-logo-a6d954e176b6975b511f314a0cc808dc94a8030210077e3a6e904fbe69dc5354.svg)
6
7
 
@@ -10,6 +11,22 @@ The Semaphore CLI is used to manage Semaphore projects from the command line.
10
11
 
11
12
  For more info about Semaphore see <https://www.semaphoreci.com>
12
13
 
14
+ ## Semaphore Resource Name (SRN)
15
+
16
+ SRN is a way of identifying Semaphore resources. This CLI uses SRNs as arguments
17
+ for all actions.
18
+
19
+ Formats for individual resources are the following:
20
+
21
+ - Organization: `organization_name`
22
+ - Team: `organization_name/team_name`
23
+ - Project: `organization_name/project_name`
24
+ - Shared Configuration: `organization_name/shared_configuration_name`
25
+
26
+ ## Using custom API URL
27
+
28
+ Create a file at `~/.sem/api_url` containing only the custom url.
29
+
13
30
  ## Issues
14
31
 
15
32
  For problems directly related to the CLI, [add an issue on GitHub](https://github.com/renderedtext/cli/issues/new).
data/lib/sem/api/base.rb CHANGED
@@ -1,11 +1,13 @@
1
1
  module Sem
2
2
  module API
3
3
  class Base
4
- def self.client
5
- @client ||= begin
6
- auth_token = Sem::Credentials.read
7
-
8
- SemaphoreClient.new(auth_token)
4
+ class << self
5
+ def client
6
+ @client ||= SemaphoreClient.new(
7
+ Sem::Configuration.auth_token,
8
+ :api_url => Sem::Configuration.api_url,
9
+ :verbose => (Sem.log_level == Sem::LOG_LEVEL_TRACE)
10
+ )
9
11
  end
10
12
  end
11
13
  end
@@ -3,17 +3,19 @@ module Sem
3
3
  class EnvVars < Base
4
4
  extend Traits::AssociatedWithSharedConfig
5
5
 
6
- def self.api
7
- client.env_vars
8
- end
6
+ class << self
7
+ def api
8
+ client.env_vars
9
+ end
9
10
 
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
- }
11
+ def to_hash(env_var)
12
+ {
13
+ :id => env_var.id,
14
+ :name => env_var.name,
15
+ :encrypted? => env_var.encrypted,
16
+ :content => env_var.content
17
+ }
18
+ end
17
19
  end
18
20
  end
19
21
  end
data/lib/sem/api/files.rb CHANGED
@@ -3,16 +3,18 @@ module Sem
3
3
  class Files < Base
4
4
  extend Traits::AssociatedWithSharedConfig
5
5
 
6
- def self.api
7
- client.config_files
8
- end
6
+ class << self
7
+ def api
8
+ client.config_files
9
+ end
9
10
 
10
- def self.to_hash(files)
11
- {
12
- :id => files.id,
13
- :name => files.path,
14
- :encrypted? => files.encrypted
15
- }
11
+ def to_hash(file)
12
+ {
13
+ :id => file.id,
14
+ :name => file.path,
15
+ :encrypted? => file.encrypted
16
+ }
17
+ end
16
18
  end
17
19
  end
18
20
  end
data/lib/sem/api/orgs.rb CHANGED
@@ -1,53 +1,41 @@
1
1
  module Sem
2
2
  module API
3
3
  class Orgs < Base
4
- def self.list
5
- orgs = api.list
4
+ class << self
5
+ def list
6
+ orgs = api.list
6
7
 
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
8
+ orgs.map { |org| to_hash(org) }
9
+ end
19
10
 
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
11
+ def info(name)
12
+ org = api.get(name)
28
13
 
29
- admins.map { |admin| Sem::API::Users.to_hash(admin) }
30
- end
14
+ raise Sem::Errors::ResourceNotFound.new("Organization", [name]) if org.nil?
31
15
 
32
- def self.list_owners(org_name)
33
- owners_team = list_teams(org_name).find { |team| team[:name] == "Owners" }
16
+ to_hash(org)
17
+ end
34
18
 
35
- owners = client.users.list_for_team(owners_team[:id])
19
+ def list_teams(name)
20
+ Sem::API::Teams.list_for_org(name)
21
+ end
36
22
 
37
- owners.map { |owner| Sem::API::Users.to_hash(owner) }
38
- end
23
+ def list_users(name)
24
+ Sem::API::Users.list_for_org(name)
25
+ end
39
26
 
40
- def self.api
41
- client.orgs
42
- end
27
+ def api
28
+ client.orgs
29
+ end
43
30
 
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
- }
31
+ def to_hash(org)
32
+ {
33
+ :id => org.id,
34
+ :username => org.username,
35
+ :created_at => org.created_at,
36
+ :updated_at => org.updated_at
37
+ }
38
+ end
51
39
  end
52
40
  end
53
41
  end
@@ -4,29 +4,38 @@ module Sem
4
4
  extend Traits::AssociatedWithOrg
5
5
  extend Traits::AssociatedWithTeam
6
6
 
7
- def self.list
8
- org_names = Orgs.list.map { |org| org[:username] }
7
+ class << self
8
+ def name_to_id(org_name, project_name)
9
+ info(org_name, project_name)[:id]
10
+ end
9
11
 
10
- org_names.map { |name| list_for_org(name) }.flatten
11
- end
12
+ def list
13
+ org_names = Orgs.list.map { |org| org[:username] }
12
14
 
13
- def self.info(path)
14
- org_name, project_name = path.split("/")
15
+ org_names.pmap { |name| list_for_org(name) }.flatten
16
+ end
15
17
 
16
- list_for_org(org_name).find { |project| project[:name] == project_name }
17
- end
18
+ def info(org_name, project_name)
19
+ project = api.list_for_org(org_name, :name => project_name).first
18
20
 
19
- def self.api
20
- client.projects
21
- end
21
+ raise Sem::Errors::ResourceNotFound.new("Project", [org_name, project_name]) if project.nil?
22
+
23
+ to_hash(project, org_name)
24
+ end
25
+
26
+ def api
27
+ client.projects
28
+ end
22
29
 
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
+ def to_hash(project, org)
31
+ {
32
+ :id => project.id,
33
+ :name => project.name,
34
+ :org => org,
35
+ :created_at => project.created_at,
36
+ :updated_at => project.updated_at
37
+ }
38
+ end
30
39
  end
31
40
  end
32
41
  end
@@ -3,71 +3,99 @@ module Sem
3
3
  class SharedConfigs < Base
4
4
  extend Traits::AssociatedWithTeam
5
5
  extend Traits::AssociatedWithOrg
6
+ extend Traits::AssociatedWithProject
6
7
 
7
- def self.list
8
- org_names = Orgs.list.map { |org| org[:username] }
8
+ class << self
9
+ def name_to_id(org_name, shared_config_name)
10
+ info(org_name, shared_config_name)[:id]
11
+ end
9
12
 
10
- org_names.map { |name| list_for_org(name) }.flatten
11
- end
13
+ def list
14
+ org_names = Orgs.list.map { |org| org[:username] }
12
15
 
13
- def self.info(path)
14
- org_name, config_name = path.split("/")
16
+ org_names.pmap { |name| list_for_org(name) }.flatten
17
+ end
15
18
 
16
- list_for_org(org_name).find { |config| config[:name] == config_name }
17
- end
19
+ def info(org_name, shared_config_name)
20
+ selected_shared_config = list_for_org(org_name).find do |shared_config|
21
+ shared_config[:name] == shared_config_name
22
+ end
18
23
 
19
- def self.create(org_name, args)
20
- config = api.create_for_org(org_name, args)
24
+ if selected_shared_config.nil?
25
+ raise Sem::Errors::ResourceNotFound.new("Shared Configuration", [org_name, shared_config_name])
26
+ end
21
27
 
22
- to_hash(config)
23
- end
28
+ selected_shared_config
29
+ end
24
30
 
25
- def self.update(path, args)
26
- shared_config = info(path)
31
+ def create(org_name, args)
32
+ shared_config = api.create_for_org(org_name, args)
27
33
 
28
- shared_config = api.update(shared_config[:id], args)
34
+ if shared_config.nil?
35
+ raise Sem::Errors::ResourceNotCreated.new("Shared Configuration", [org_name, args[:name]])
36
+ end
29
37
 
30
- to_hash(shared_config)
31
- end
38
+ to_hash(shared_config, org_name)
39
+ end
32
40
 
33
- def self.delete(path)
34
- id = info(path)[:id]
41
+ def update(org_name, shared_config_name, args)
42
+ shared_config = info(org_name, shared_config_name)
35
43
 
36
- api.delete(id)
37
- end
44
+ shared_config = api.update(shared_config[:id], args)
38
45
 
39
- def self.list_env_vars(path)
40
- Sem::API::EnvVars.list_for_shared_config(path)
41
- end
46
+ if shared_config.nil?
47
+ raise Sem::Errors::ResourceNotUpdated.new("Shared Configuration", [org_name, shared_config_name])
48
+ end
42
49
 
43
- def self.list_files(path)
44
- Sem::API::Files.list_for_shared_config(path)
45
- end
50
+ to_hash(shared_config, org_name)
51
+ end
46
52
 
47
- def self.api
48
- client.shared_configs
49
- end
53
+ def delete(org_name, shared_config_name)
54
+ shared_config = info(org_name, shared_config_name)
50
55
 
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
56
+ api.delete!(shared_config[:id])
57
+ rescue SemaphoreClient::Exceptions::RequestFailed
58
+ raise Sem::Errors::ResourceNotDeleted.new("Shared Configuration", [org_name, shared_config_name])
59
+ end
60
+
61
+ def list_env_vars(org_name, shared_config_name)
62
+ Sem::API::EnvVars.list_for_shared_config(org_name, shared_config_name)
63
+ end
64
+
65
+ def list_files(org_name, shared_config_name)
66
+ Sem::API::Files.list_for_shared_config(org_name, shared_config_name)
67
+ end
68
+
69
+ def api
70
+ client.shared_configs
71
+ end
72
+
73
+ def to_hash(shared_config, org)
74
+ network_actions = [:config_files_count, :env_vars_count]
75
+
76
+ config_files, env_vars = network_actions.pmap do |action|
77
+ send(action, shared_config.id)
78
+ end
79
+
80
+ {
81
+ :id => shared_config.id,
82
+ :name => shared_config.name,
83
+ :org => org,
84
+ :config_files => config_files,
85
+ :env_vars => env_vars,
86
+ :created_at => shared_config.created_at,
87
+ :updated_at => shared_config.updated_at
88
+ }
89
+ end
61
90
 
62
- class << self
63
91
  private
64
92
 
65
- def config_files_count(config_id)
66
- client.config_files.list_for_shared_config(config_id).to_a.size
93
+ def config_files_count(shared_config_id)
94
+ client.config_files.list_for_shared_config(shared_config_id).to_a.size
67
95
  end
68
96
 
69
- def env_vars_count(config_id)
70
- client.env_vars.list_for_shared_config(config_id).to_a.size
97
+ def env_vars_count(shared_config_id)
98
+ client.env_vars.list_for_shared_config(shared_config_id).to_a.size
71
99
  end
72
100
  end
73
101
  end
data/lib/sem/api/teams.rb CHANGED
@@ -3,51 +3,66 @@ module Sem
3
3
  class Teams < Base
4
4
  extend Traits::AssociatedWithOrg
5
5
 
6
- def self.list
7
- org_names = Sem::API::Orgs.list.map { |org| org[:username] }
6
+ class << self
7
+ def name_to_id(org_name, team_name)
8
+ info(org_name, team_name)[:id]
9
+ end
8
10
 
9
- org_names.map { |name| list_for_org(name) }.flatten
10
- end
11
+ def list
12
+ org_names = Sem::API::Orgs.list.map { |org| org[:username] }
11
13
 
12
- def self.info(path)
13
- org_name, team_name = path.split("/")
14
+ org_names.pmap { |name| list_for_org(name) }.flatten
15
+ end
14
16
 
15
- list_for_org(org_name).find { |team| team[:name] == team_name }
16
- end
17
+ def info(org_name, team_name)
18
+ selected_team = list_for_org(org_name).find { |team| team[:name] == team_name }
17
19
 
18
- def self.create(org_name, args)
19
- team = api.create_for_org(org_name, args)
20
+ raise Sem::Errors::ResourceNotFound.new("Team", [org_name, team_name]) if selected_team.nil?
20
21
 
21
- to_hash(team)
22
- end
22
+ selected_team
23
+ end
23
24
 
24
- def self.update(path, args)
25
- team = info(path)
25
+ def create(org_name, args)
26
+ team = api.create_for_org(org_name, args)
26
27
 
27
- team = api.update(team[:id], args)
28
+ raise Sem::Errors::ResourceNotCreated.new("Team", [org_name, args[:name]]) if team.nil?
28
29
 
29
- to_hash(team)
30
- end
30
+ to_hash(team, org_name)
31
+ end
31
32
 
32
- def self.delete(path)
33
- id = info(path)[:id]
33
+ def update(org_name, team_name, args)
34
+ team = info(org_name, team_name)
34
35
 
35
- api.delete(id)
36
- end
36
+ team = api.update(team[:id], args)
37
37
 
38
- def self.api
39
- client.teams
40
- end
38
+ raise Sem::Errors::ResourceNotUpdated.new("Team", [org_name, team_name]) if team.nil?
39
+
40
+ to_hash(team, org_name)
41
+ end
42
+
43
+ def delete(org_name, team_name)
44
+ team = info(org_name, team_name)
45
+
46
+ api.delete!(team[:id])
47
+ rescue SemaphoreClient::Exceptions::RequestFailed
48
+ raise Sem::Errors::ResourceNotDeleted.new("Team", [org_name, team_name])
49
+ end
50
+
51
+ def api
52
+ client.teams
53
+ end
41
54
 
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
- }
55
+ def to_hash(team, org)
56
+ {
57
+ :id => team.id,
58
+ :name => team.name,
59
+ :org => org,
60
+ :permission => team.permission,
61
+ :members => client.users.list_for_team(team.id).to_a.size.to_s,
62
+ :created_at => team.created_at,
63
+ :updated_at => team.updated_at
64
+ }
65
+ end
51
66
  end
52
67
  end
53
68
  end
@@ -2,10 +2,14 @@ module Sem
2
2
  module API
3
3
  module Traits
4
4
  module AssociatedWithOrg
5
+ PAGES_PER_CALL = 3
6
+
5
7
  def list_for_org(org_name)
6
- instances = api.list_for_org(org_name)
8
+ pages = Sem::Pagination.pages(PAGES_PER_CALL) do |page_index|
9
+ api.list_for_org(org_name, :page => page_index).to_a
10
+ end
7
11
 
8
- instances.map { |instance| to_hash(instance) }
12
+ pages.flatten.pmap { |instance| to_hash(instance, org_name) }
9
13
  end
10
14
  end
11
15
  end
@@ -0,0 +1,29 @@
1
+ module Sem
2
+ module API
3
+ module Traits
4
+ module AssociatedWithProject
5
+ def list_for_project(org_name, project_name)
6
+ project = Projects.info(org_name, project_name)
7
+
8
+ instances = api.list_for_project(project[:id]).to_a
9
+
10
+ instances.map { |instance| to_hash(instance, org_name) }
11
+ end
12
+
13
+ def add_to_project(org_name, project_name, instance_name)
14
+ instance = info(org_name, instance_name)
15
+ project = Projects.info(org_name, project_name)
16
+
17
+ api.attach_to_project(instance[:id], project[:id])
18
+ end
19
+
20
+ def remove_from_project(org_name, project_name, instance_name)
21
+ instance = info(org_name, instance_name)
22
+ project = Projects.info(org_name, project_name)
23
+
24
+ api.detach_from_project(instance[:id], project[:id])
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -2,25 +2,27 @@ module Sem
2
2
  module API
3
3
  module Traits
4
4
  module AssociatedWithSharedConfig
5
- def list_for_shared_config(shared_config_path)
6
- shared_config = SharedConfigs.info(shared_config_path)
5
+ def list_for_shared_config(org_name, shared_config_name)
6
+ shared_config = SharedConfigs.info(org_name, shared_config_name)
7
7
 
8
- instances = api.list_for_shared_config(shared_config[:id])
8
+ instances = api.list_for_shared_config(shared_config[:id]).to_a
9
9
 
10
10
  instances.map { |instance| to_hash(instance) }
11
11
  end
12
12
 
13
- def add_to_shared_config(shared_config_path, params)
14
- shared_config = SharedConfigs.info(shared_config_path)
13
+ def add_to_shared_config(org_name, shared_config_name, params)
14
+ shared_config = SharedConfigs.info(org_name, shared_config_name)
15
15
 
16
16
  api.create_for_shared_config(shared_config[:id], params)
17
17
  end
18
18
 
19
- def remove_from_shared_config(shared_config_path, instance_name)
20
- instances = list_for_shared_config(shared_config_path)
19
+ def remove_from_shared_config(org_name, shared_config_name, instance_name)
20
+ instances = list_for_shared_config(org_name, shared_config_name)
21
21
 
22
22
  selected_instance = instances.find { |instance| instance[:name] == instance_name }
23
23
 
24
+ raise Sem::Errors::ResourceNotFound.new("Resource", [org_name, instance_name]) if selected_instance.nil?
25
+
24
26
  api.delete(selected_instance[:id])
25
27
  end
26
28
  end
@@ -2,26 +2,26 @@ module Sem
2
2
  module API
3
3
  module Traits
4
4
  module AssociatedWithTeam
5
- def list_for_team(team_path)
6
- team = Teams.info(team_path)
5
+ def list_for_team(org_name, team_name)
6
+ team_id = Teams.name_to_id(org_name, team_name)
7
7
 
8
- instances = api.list_for_team(team[:id])
8
+ instances = api.list_for_team(team_id).to_a
9
9
 
10
- instances.map { |instance| to_hash(instance) }
10
+ instances.map { |instance| to_hash(instance, org_name) }
11
11
  end
12
12
 
13
- def add_to_team(team_path, instance_path)
14
- instance = info(instance_path)
15
- team = Teams.info(team_path)
13
+ def add_to_team(org_name, team_name, instance_name)
14
+ instance_id = name_to_id(org_name, instance_name)
15
+ team_id = Teams.name_to_id(org_name, team_name)
16
16
 
17
- api.attach_to_team(instance[:id], team[:id])
17
+ api.attach_to_team(instance_id, team_id)
18
18
  end
19
19
 
20
- def remove_from_team(team_path, instance_path)
21
- instance = info(instance_path)
22
- team = Teams.info(team_path)
20
+ def remove_from_team(org_name, team_name, instance_name)
21
+ instance_id = name_to_id(org_name, instance_name)
22
+ team_id = Teams.name_to_id(org_name, team_name)
23
23
 
24
- api.detach_from_team(instance[:id], team[:id])
24
+ api.detach_from_team(instance_id, team_id)
25
25
  end
26
26
  end
27
27
  end
@@ -4,6 +4,7 @@ module Sem
4
4
  require_relative "traits/associated_with_org"
5
5
  require_relative "traits/associated_with_team"
6
6
  require_relative "traits/associated_with_shared_config"
7
+ require_relative "traits/associated_with_project"
7
8
  end
8
9
  end
9
10
  end