semaph 0.2.0 → 0.3.0

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.
Files changed (31) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/Gemfile.lock +1 -1
  4. data/README.md +81 -11
  5. data/lib/semaph/api.rb +37 -4
  6. data/lib/semaph/commands/reload_command.rb +5 -4
  7. data/lib/semaph/commands/rerun_workflow_command.rb +18 -0
  8. data/lib/semaph/commands/stop_workflow_command.rb +18 -0
  9. data/lib/semaph/model/job.rb +43 -1
  10. data/lib/semaph/model/job_collection.rb +17 -4
  11. data/lib/semaph/model/pipeline.rb +27 -1
  12. data/lib/semaph/model/pipeline_collection.rb +0 -1
  13. data/lib/semaph/model/project.rb +1 -1
  14. data/lib/semaph/model/project_collection.rb +0 -1
  15. data/lib/semaph/model/workflow.rb +11 -1
  16. data/lib/semaph/model/workflow_collection.rb +0 -1
  17. data/lib/semaph/shells/organisation/organisation_shell.rb +13 -9
  18. data/lib/semaph/shells/organisation/projects_list_command.rb +1 -0
  19. data/lib/semaph/shells/organisations/organisations_shell.rb +5 -1
  20. data/lib/semaph/shells/pipeline/jobs_list_command.rb +3 -15
  21. data/lib/semaph/shells/pipeline/jobs_logs_command.rb +30 -0
  22. data/lib/semaph/shells/pipeline/jobs_poll_command.rb +37 -0
  23. data/lib/semaph/shells/pipeline/pipeline_shell.rb +80 -7
  24. data/lib/semaph/shells/project/project_shell.rb +31 -18
  25. data/lib/semaph/shells/project/workflows_list_command.rb +1 -0
  26. data/lib/semaph/shells/project/workflows_select_command.rb +10 -3
  27. data/lib/semaph/shells/workflow/pipelines_list_command.rb +2 -1
  28. data/lib/semaph/shells/workflow/pipelines_select_command.rb +9 -3
  29. data/lib/semaph/shells/workflow/workflow_shell.rb +44 -13
  30. data/lib/semaph/version.rb +1 -1
  31. metadata +6 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b22217dbedbfa234279e494e23d64af812563e6fa8d57e2e2b14f185b3fbe52c
4
- data.tar.gz: 36c3a0944ef6408730c18b2f147f734616300023792e9e82b0c5ebc0956bab05
3
+ metadata.gz: 13271774cf750f1f8eedc2d48de45ceeaa164af2593581cac85fc73e6c371d95
4
+ data.tar.gz: 3afba979f087aba88acbeeb3a09e46261fda8ba3afae3cf1690ced82d687d420
5
5
  SHA512:
6
- metadata.gz: 4fdda4999337920b39947b2c2fe09ea2cf62830998f948fed2d835dd74f5436172276dace4d59f0e493f14381aae349aaa0aafaa123b5f452ab4ed6a1fba0db0
7
- data.tar.gz: c5f969a3450d98f8a9b7a9eeb66d134856558e0376259070206ad0a8e76d4e3c38e6a12e3b27312aa272a48cc08af50288e99b443983ffc1d374d5401f82eb85
6
+ metadata.gz: a00c84f6e8e357e0a99f921e316b8a36f8c5cf78a8d9befb33f2e8e25f733801024392401b4329d8faf20a690dace3c7b2fe48a1f31bb71dfa4c25f41987156b
7
+ data.tar.gz: 8c904c17ba321fb240c4bdc1fa8ecb1beac95d6688da8632dd6e7e26446c2c16bd52bca36757eccc389cb06b64d3e1af4fc874ce817d706d632e28eaad2b56b5
data/.gitignore CHANGED
@@ -1,4 +1,5 @@
1
1
  .DS_Store
2
+ *.log
2
3
 
3
4
  /.bundle/
4
5
  /.yardoc
@@ -7,4 +8,4 @@
7
8
  /doc/
8
9
  /pkg/
9
10
  /spec/reports/
10
- /tmp/
11
+ /tmp/
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- semaph (0.1.0)
4
+ semaph (0.3.0)
5
5
  faraday
6
6
  rainbow
7
7
  shell_shock
data/README.md CHANGED
@@ -1,28 +1,98 @@
1
1
  # Semaph
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/semaph`. To experiment with that code, run `bin/console` for an interactive prompt.
3
+ This is command line shell for interacting with [semaphoreci 2.0](http://docs.semaphoreci.com/).
4
+
5
+ It complements the [sem](https://docs.semaphoreci.com/reference/sem-command-line-tool/) tool with some
6
+ overlap in responsibilities.
4
7
 
5
- TODO: Delete this and the text above, and describe your gem
6
8
 
7
9
  ## Installation
8
10
 
9
- Add this line to your application's Gemfile:
11
+ gem install semaph
12
+
13
+ ## Usage
14
+
15
+ To set up authentication to semaphoreci, you can just follow the instructions to install and setup
16
+ [sem](https://docs.semaphoreci.com/reference/sem-command-line-tool/). This will result
17
+ in your authentication details being written to `~/.sem.yaml`.
10
18
 
11
- ```ruby
12
- gem 'semaph'
19
+ You should see something like the following in this file:
20
+
21
+ ```yaml
22
+ active-context: foo_semaphoreci_com
23
+ contexts:
24
+ foo_semaphoreci_com:
25
+ auth:
26
+ token: qwerty
27
+ host: foo.semaphoreci.com
13
28
  ```
14
29
 
15
- And then execute:
30
+ Now you can run `semaph` and will be presented with a prompt like one of the following:
16
31
 
17
- $ bundle install
32
+ 🏗 >
18
33
 
19
- Or install it yourself as:
34
+ or
20
35
 
21
- $ gem install semaph
36
+ 🏗 foo.semaphoreci.com >
22
37
 
23
- ## Usage
38
+ This is the first of a series of nested shells. Each shell represents a different context
39
+ and has different commands available. To see the commands available, execute `help` and
40
+ to see the details of a particular command, execute `help <command name>`. Once you are
41
+ familar with the commands for each context, you can type the first couple of characters
42
+ and then hit tab to complete the rest. For some commands you can also tab complete the
43
+ parameters. Once you enter a shell, return to the previous shell or exit `semaph`, you can
44
+ press ctrl-d.
45
+
46
+ ### organisations shell
47
+
48
+ 🏗 >
49
+
50
+ You will only see this shell if you have multiple sets of credentials in your `~/.sem.yml` file.
51
+
52
+ From this shell, you can `list-organisations` you are authenticated to and `select-organisation`
53
+ to enter a shell for that organisation.
54
+
55
+ ### organisation shell
56
+
57
+ 🏗 foo.semaphoreci.com >
58
+
59
+ If you have only one set of credentials in `~/.sem.yml` then this will be the initial shell.
60
+
61
+ From here you can `list-projects` and then `select-project` to enter a shell for that project.
62
+
63
+ If new projects have been added/removed while you are using this shell, you can `reload-projects`.
64
+
65
+ ### project shell
66
+
67
+ 🏗 foo.semaphoreci.com my-app >
68
+
69
+ From this shell, you will mostly be interested in `list-workflows <branch>` (where 'branch' is any
70
+ substring of the git branch you want to see workflows for) and then `select-workflow <index>`
71
+ (where 'index' is the number displayed for each workflow `list-workflows` - tab completion on uuids
72
+ seemed a bad idea) to enter a shell for that specific workflow.
73
+
74
+ You can also `open-github` (opens a web browser for the github project associated with the project), `open-project`
75
+ (opens the semaphoreci project in a browser) and `reload-workflows` (to see any new/changed workflows).
76
+
77
+ ### workflow shell
78
+
79
+ 🏗 foo.semaphoreci.com my-app workflowuuid >
80
+
81
+ From this shell, you can `list-pipelines` for the selected workflow. These are the builds usually starting
82
+ from `semaphore.yml` plus any promotion pipelines that might be executed. You can `select-pipeline` to monitor
83
+ what's happening with the pipeline.
84
+
85
+ You can also `open-github-branch`, `open-github-commit` to see the branch/commit in a browser and
86
+ `open-workflow`, `open-branch` to see the semaphore branch/workflow in a browser and `reload-pipelines` to see
87
+ any changes that have happened in semaphore.
88
+
89
+ ### pipeline shell
90
+
91
+ 🏗 foo.semaphoreci.com my-app workflowuuid semaphore.yml >
92
+
93
+ From this shell, you can `list-jobs` and `reload-jobs`.
24
94
 
25
- TODO: Write usage instructions here
95
+ Jobs are displayed with a flattened view of blocks and jobs for compactness.
26
96
 
27
97
  ## Development
28
98
 
@@ -4,12 +4,14 @@ require "json"
4
4
  module Semaph
5
5
  # Refer to https://docs.semaphoreci.com/reference/api-v1alpha/
6
6
  class Api
7
- attr_reader :host
7
+ attr_reader :host, :name
8
8
 
9
9
  def initialize(token, host)
10
10
  @token = token
11
11
  @host = host
12
- @base = "https://#{host}/api/v1alpha"
12
+ @name = host.split(".").first
13
+ @host_url = "https://#{host}"
14
+ @base = "#{@host_url}/api/v1alpha"
13
15
  end
14
16
 
15
17
  def projects
@@ -20,6 +22,18 @@ module Semaph
20
22
  get "plumber-workflows", { project_id: project_id }
21
23
  end
22
24
 
25
+ def workflow(workflow_id)
26
+ get "plumber-workflows/#{workflow_id}"
27
+ end
28
+
29
+ def stop_workflow(workflow_id)
30
+ post "plumber-workflows/#{workflow_id}/terminate"
31
+ end
32
+
33
+ def rerun_workflow(workflow_id)
34
+ post "plumber-workflows/#{workflow_id}/reschedule?request_token=#{workflow_id}"
35
+ end
36
+
23
37
  def pipelines(options)
24
38
  get "pipelines", options
25
39
  end
@@ -32,13 +46,32 @@ module Semaph
32
46
  get "jobs/#{id}"
33
47
  end
34
48
 
49
+ def job_log(id)
50
+ get_raw "jobs/#{id}/plain_logs.json"
51
+ end
52
+
35
53
  private
36
54
 
55
+ def get_raw(path, params = {})
56
+ url = "#{@host_url}/#{path}"
57
+ puts url if ENV["SEMAPH_DEBUG"]
58
+ response = Faraday.get(url, params, { "Authorization" => "Token #{@token}" })
59
+ check_response(response, url)
60
+ end
61
+
37
62
  def get(path, params = {})
38
63
  url = "#{@base}/#{path}"
39
64
  puts url if ENV["SEMAPH_DEBUG"]
40
65
  response = Faraday.get(url, params, headers)
41
- check_response(response, url).tap do |hash|
66
+ JSON.parse(check_response(response, url)).tap do |hash|
67
+ pp hash if ENV["SEMAPH_DEBUG"]
68
+ end
69
+ end
70
+
71
+ def post(path, params = {})
72
+ url = "#{@base}/#{path}"
73
+ response = Faraday.post(url, params.to_json, headers)
74
+ JSON.parse(check_response(response, url)).tap do |hash|
42
75
  pp hash if ENV["SEMAPH_DEBUG"]
43
76
  end
44
77
  end
@@ -52,7 +85,7 @@ module Semaph
52
85
  end
53
86
 
54
87
  def check_response(response, url)
55
- return JSON.parse(response.body) if response.status == 200
88
+ return response.body if response.status == 200
56
89
 
57
90
  puts "http response #{response.status} received for #{url}:\n#{response.body}"
58
91
  exit 1
@@ -3,13 +3,14 @@ module Semaph
3
3
  class ReloadCommand
4
4
  attr_reader :help
5
5
 
6
- def initialize(entity, help)
7
- @entity = entity
8
- @help = help
6
+ def initialize
7
+ @help = "reload all code"
9
8
  end
10
9
 
11
10
  def execute(_whatever)
12
- @entity.reload
11
+ Dir["lib/**/*.rb"].each do |path|
12
+ load path
13
+ end
13
14
  end
14
15
  end
15
16
  end
@@ -0,0 +1,18 @@
1
+ require "semaph/shells/workflow/workflow_shell"
2
+
3
+ module Semaph
4
+ module Commands
5
+ class RerunWorkflowCommand
6
+ attr_reader :help
7
+
8
+ def initialize(workflow)
9
+ @workflow = workflow
10
+ @help = "rerun workflow"
11
+ end
12
+
13
+ def execute(_whatever)
14
+ ::Semaph::Shells::Workflow::WorkflowShell.new(@workflow.rerun).push
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,18 @@
1
+ require "semaph/shells/workflow/workflow_shell"
2
+
3
+ module Semaph
4
+ module Commands
5
+ class StopWorkflowCommand
6
+ attr_reader :help
7
+
8
+ def initialize(workflow)
9
+ @workflow = workflow
10
+ @help = "stop workflow"
11
+ end
12
+
13
+ def execute(_whatever)
14
+ @workflow.stop
15
+ end
16
+ end
17
+ end
18
+ end
@@ -20,6 +20,49 @@ module Semaph
20
20
  assign_from_block(raw_block)
21
21
  end
22
22
 
23
+ def log
24
+ pipeline.workflow.project.client.job_log(id)
25
+ end
26
+
27
+ def description
28
+ [
29
+ block_icon,
30
+ @block_name,
31
+ job_icon,
32
+ @name,
33
+ ].compact.join(" ")
34
+ end
35
+
36
+ # block_state can be waiting/running/done
37
+ # block_result can be passed/failed/canceled/stopped
38
+ def block_icon
39
+ return "🟠" if @block_state == "waiting"
40
+
41
+ return "🔵" if @block_state == "running"
42
+
43
+ return "⚪" if @block_result == "canceled"
44
+
45
+ return "⛔" if @block_result == "stopped"
46
+
47
+ return "🟢" if @block_result == "passed"
48
+
49
+ "🔴"
50
+ end
51
+
52
+ # status can be FINISHED/RUNNING
53
+ # result can be PASSED/FAILED/STOPPED
54
+ def job_icon
55
+ return nil unless @status
56
+
57
+ return "🔵" unless @status == "FINISHED"
58
+
59
+ return "⛔" if @result == "STOPPED"
60
+
61
+ return "🟢" if @result == "PASSED"
62
+
63
+ "🔴"
64
+ end
65
+
23
66
  private
24
67
 
25
68
  def assign_from_job(raw)
@@ -37,4 +80,3 @@ module Semaph
37
80
  end
38
81
  end
39
82
  end
40
-
@@ -7,7 +7,6 @@ module Semaph
7
7
 
8
8
  def initialize(pipeline)
9
9
  @pipeline = pipeline
10
- reload
11
10
  end
12
11
 
13
12
  def reload
@@ -16,6 +15,14 @@ module Semaph
16
15
  @all = build_jobs(project.client.pipeline(@pipeline.id))
17
16
  end
18
17
 
18
+ def incomplete
19
+ @all.reject { |job| job.status == "FINISHED" }
20
+ end
21
+
22
+ def failed
23
+ @all.select { |job| job.result == "FAILED" }
24
+ end
25
+
19
26
  private
20
27
 
21
28
  def build_jobs(content)
@@ -23,12 +30,18 @@ module Semaph
23
30
  blocks = content.delete("blocks")
24
31
  blocks.each do |block|
25
32
  jobs = block.delete("jobs").sort_by { |job| job["index"] }
26
- jobs.each do |job|
27
- result << Job.new(@pipeline, block, job)
28
- end
33
+ append_jobs(result, block, jobs)
29
34
  end
30
35
  result
31
36
  end
37
+
38
+ def append_jobs(result, block, jobs)
39
+ if jobs.count.positive?
40
+ jobs.each { |job| result << Job.new(@pipeline, block, job) }
41
+ else
42
+ result << Job.new(@pipeline, block, {})
43
+ end
44
+ end
32
45
  end
33
46
  end
34
47
  end
@@ -12,10 +12,36 @@ module Semaph
12
12
  @yaml = raw["yaml_file_name"]
13
13
  @state = raw["state"]
14
14
  @result = raw["result"]
15
+ %w[created done pending queuing running stopping].each do |name|
16
+ extract_time(name)
17
+ end
15
18
  end
16
19
 
17
20
  def job_collection
18
- JobCollection.new(self)
21
+ @job_collection ||= JobCollection.new(self)
22
+ end
23
+
24
+ def description
25
+ "#{icon} #{yaml}"
26
+ end
27
+
28
+ def icon
29
+ return "🔵" unless @state == "DONE"
30
+
31
+ return "⛔" if @result == "STOPPED"
32
+
33
+ return "🟢" if @result == "PASSED"
34
+
35
+ "🔴"
36
+ end
37
+
38
+ private
39
+
40
+ def extract_time(name)
41
+ key = "#{name}_at"
42
+ return if raw[key]["seconds"].zero?
43
+
44
+ instance_variable_set("@#{key}", Time.at(raw[key]["seconds"]))
19
45
  end
20
46
  end
21
47
  end
@@ -7,7 +7,6 @@ module Semaph
7
7
 
8
8
  def initialize(workflow)
9
9
  @workflow = workflow
10
- reload
11
10
  end
12
11
 
13
12
  def reload
@@ -27,7 +27,7 @@ module Semaph
27
27
  end
28
28
 
29
29
  def workflow_collection
30
- WorkflowCollection.new(self)
30
+ @workflow_collection ||= WorkflowCollection.new(self)
31
31
  end
32
32
  end
33
33
  end
@@ -7,7 +7,6 @@ module Semaph
7
7
 
8
8
  def initialize(client)
9
9
  @client = client
10
- reload
11
10
  end
12
11
 
13
12
  def reload
@@ -17,7 +17,17 @@ module Semaph
17
17
  end
18
18
 
19
19
  def pipeline_collection
20
- PipelineCollection.new(self)
20
+ @pipeline_collection ||= PipelineCollection.new(self)
21
+ end
22
+
23
+ def rerun
24
+ rerun_response = project.client.rerun_workflow(@id)
25
+ workflow_response = project.client.workflow(rerun_response["wf_id"])
26
+ Workflow.new(project, workflow_response["workflow"])
27
+ end
28
+
29
+ def stop
30
+ project.client.stop_workflow(@id)
21
31
  end
22
32
  end
23
33
  end
@@ -7,7 +7,6 @@ module Semaph
7
7
 
8
8
  def initialize(project)
9
9
  @project = project
10
- reload
11
10
  end
12
11
 
13
12
  def reload
@@ -12,16 +12,20 @@ module Semaph
12
12
  include ShellShock::Context
13
13
 
14
14
  def initialize(organisation)
15
- host = organisation["host"]
16
- @prompt = "🏗 #{host} > "
17
- client = ::Semaph::Api.new(organisation["auth"]["token"], host)
18
- project_collection = ::Semaph::Model::ProjectCollection.new(client)
19
- add_command ProjectsListCommand.new(project_collection), "list-projects"
15
+ @client = ::Semaph::Api.new(organisation["auth"]["token"], organisation["host"])
16
+ @prompt = "🏗 #{@client.name} > "
17
+ add_commands
18
+ @project_list_command.execute("")
19
+ end
20
+
21
+ private
22
+
23
+ def add_commands
24
+ project_collection = ::Semaph::Model::ProjectCollection.new(@client)
25
+ @project_list_command = ProjectsListCommand.new(project_collection)
26
+ add_command @project_list_command, "list-projects"
20
27
  add_command ProjectsSelectCommand.new(project_collection), "select-project"
21
- add_command(
22
- ::Semaph::Commands::ReloadCommand.new(project_collection, "reload projects"),
23
- "reload-projects",
24
- )
28
+ add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
25
29
  end
26
30
  end
27
31
  end
@@ -10,6 +10,7 @@ module Semaph
10
10
  end
11
11
 
12
12
  def execute(_whatever)
13
+ @project_collection.reload
13
14
  @project_collection.all.each do |project|
14
15
  puts project.name
15
16
  end
@@ -1,3 +1,4 @@
1
+ require "semaph/commands/reload_command"
1
2
  require "semaph/shells/organisations/organisations_list_command"
2
3
  require "semaph/shells/organisations/organisations_select_command"
3
4
  require "shell_shock/context"
@@ -11,8 +12,11 @@ module Semaph
11
12
  def initialize(organisations)
12
13
  @organisations = organisations
13
14
  @prompt = "🏗 > "
14
- add_command OrganisationsListCommand.new(organisations), "list-organisations"
15
+ organisations_list_command = OrganisationsListCommand.new(organisations)
16
+ add_command organisations_list_command, "list-organisations"
15
17
  add_command OrganisationsSelectCommand.new(organisations), "select-organisation"
18
+ add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
19
+ organisations_list_command.execute("")
16
20
  end
17
21
  end
18
22
  end
@@ -10,23 +10,11 @@ module Semaph
10
10
  end
11
11
 
12
12
  def execute(_whatever)
13
- @job_collection.all.each do |job|
14
- puts description(job)
13
+ @job_collection.reload
14
+ @job_collection.all.each_with_index do |job, index|
15
+ puts "#{index + 1} #{job.description}"
15
16
  end
16
17
  end
17
-
18
- private
19
-
20
- def description(job)
21
- [
22
- job.block_name,
23
- job.block_state,
24
- job.block_result,
25
- job.name,
26
- job.status,
27
- job.result,
28
- ].join(" ")
29
- end
30
18
  end
31
19
  end
32
20
  end
@@ -0,0 +1,30 @@
1
+ module Semaph
2
+ module Shells
3
+ module Pipeline
4
+ class JobsLogsCommand
5
+ attr_reader :usage, :help
6
+
7
+ def initialize(job_collection)
8
+ @job_collection = job_collection
9
+ @usage = "<job index>"
10
+ @help = "retrieve log for job"
11
+ end
12
+
13
+ def execute(index_string)
14
+ index = index_string.to_i - 1
15
+
16
+ job = @job_collection.all[index]
17
+
18
+ unless job
19
+ puts "There is no job at position #{index}"
20
+ return
21
+ end
22
+
23
+ filename = "#{job.id}.log"
24
+ File.open(filename, "w") { |file| file.puts job.log } unless File.exist?(filename)
25
+ system("less #{filename}")
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,37 @@
1
+ module Semaph
2
+ module Shells
3
+ module Pipeline
4
+ class JobsPollCommand
5
+ attr_reader :usage, :help
6
+
7
+ def initialize(job_collection)
8
+ @job_collection = job_collection
9
+ @help = "poll jobs"
10
+ @can_notify = !`which terminal-notifier`.chomp.empty?
11
+ end
12
+
13
+ def execute(_whatever)
14
+ incomplete_jobs = @job_collection.incomplete
15
+ while incomplete_jobs.count.positive?
16
+ puts "#{incomplete_jobs.count} incomplete jobs remaining:"
17
+ incomplete_jobs.each { |job| puts job.description }
18
+ failed_jobs = @job_collection.failed
19
+ if failed_jobs.count.positive?
20
+ puts "Some jobs have already failed:"
21
+ failed_jobs.each { |job| puts job.description }
22
+ `terminal-notifier -group semaph -message "#{failed_jobs.count} jobs have failed" -title "Job failures"` if @can_notify
23
+ return
24
+ end
25
+ sleep 20
26
+ @job_collection.reload
27
+ incomplete_jobs = @job_collection.incomplete
28
+ end
29
+ @job_collection.all.each_with_index do |job, index|
30
+ puts "#{index + 1} #{job.description}"
31
+ end
32
+ `terminal-notifier -group semaph -message "All jobs have completed" -title "Workflow completed"` if @can_notify
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -1,23 +1,96 @@
1
+ require "semaph/commands/reload_command"
2
+ require "semaph/commands/rerun_workflow_command"
1
3
  require "semaph/shells/pipeline/jobs_list_command"
4
+ require "semaph/shells/pipeline/jobs_logs_command"
5
+ require "semaph/shells/pipeline/jobs_poll_command"
2
6
  require "shell_shock/context"
3
7
 
4
8
  module Semaph
5
9
  module Shells
6
10
  module Pipeline
7
11
  class PipelineShell
12
+ attr_reader :pipeline
13
+
8
14
  include ShellShock::Context
9
15
 
10
16
  def initialize(pipeline)
11
17
  @pipeline = pipeline
12
- workflow = pipeline.workflow
13
- project = workflow.project
14
- @prompt = "🏗 #{project.client.host} #{project.name} #{workflow.id} #{pipeline.yaml} > "
15
- job_collection = pipeline.job_collection
18
+ @prompt = "🏗 #{project.client.name} #{project.name} #{workflow.id} #{pipeline.yaml} > "
19
+ add_commands
20
+ @jobs_list_command.execute("")
21
+ end
22
+
23
+ private
24
+
25
+ def project
26
+ workflow.project
27
+ end
28
+
29
+ def workflow
30
+ pipeline.workflow
31
+ end
32
+
33
+ def job_collection
34
+ pipeline.job_collection
35
+ end
36
+
37
+ def add_commands
38
+ @jobs_list_command = JobsListCommand.new(job_collection)
39
+ add_command @jobs_list_command, "list-jobs"
40
+ add_command JobsPollCommand.new(job_collection), "poll-jobs"
41
+ add_command JobsLogsCommand.new(job_collection), "jobs-logs"
42
+ add_command ::Semaph::Commands::RerunWorkflowCommand.new(workflow), "rerun"
43
+ add_open_branch_command
44
+ add_open_workflow_command
45
+ add_github_commands
46
+ add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
47
+ end
48
+
49
+ def add_open_workflow_command
50
+ add_command(
51
+ ::Semaph::Commands::VisitUrlCommand.new(
52
+ "https://#{project.client.host}/workflows/#{workflow.id}",
53
+ "browse to workflow",
54
+ ),
55
+ "open-workflow",
56
+ )
57
+ end
58
+
59
+ def add_open_branch_command
60
+ add_command(
61
+ ::Semaph::Commands::VisitUrlCommand.new(
62
+ "https://#{project.client.host}/branches/#{workflow.branch_id}",
63
+ "browse to branch in semaphore",
64
+ ),
65
+ "open-branch",
66
+ )
67
+ end
68
+
69
+ def add_github_commands
70
+ return unless workflow.project.github_url
71
+
72
+ add_github_branch
73
+ add_github_commit
74
+ end
75
+
76
+ def add_github_branch
77
+ add_command(
78
+ ::Semaph::Commands::VisitUrlCommand.new(
79
+ "#{workflow.project.github_url}/tree/#{workflow.branch}",
80
+ "browse to the branch in github",
81
+ ),
82
+ "open-github-branch",
83
+ )
84
+ end
85
+
86
+ def add_github_commit
16
87
  add_command(
17
- ::Semaph::Commands::ReloadCommand.new(job_collection, "reload jobs"),
18
- "reload-jobs",
88
+ ::Semaph::Commands::VisitUrlCommand.new(
89
+ "#{workflow.project.github_url}/commit/#{workflow.sha}",
90
+ "browse to the commit in github",
91
+ ),
92
+ "open-github-commit",
19
93
  )
20
- add_command JobsListCommand.new(job_collection), "list-jobs"
21
94
  end
22
95
  end
23
96
  end
@@ -1,5 +1,5 @@
1
- require "semaph/commands/visit_url_command"
2
1
  require "semaph/commands/reload_command"
2
+ require "semaph/commands/visit_url_command"
3
3
  require "semaph/shells/project/workflows_list_command"
4
4
  require "semaph/shells/project/workflows_select_command"
5
5
  require "shell_shock/context"
@@ -8,30 +8,33 @@ module Semaph
8
8
  module Shells
9
9
  module Project
10
10
  class ProjectShell
11
+ attr_reader :project
12
+
11
13
  include ShellShock::Context
12
14
 
13
15
  def initialize(project)
14
- @prompt = "🏗 #{project.client.host} #{project.name} > "
15
- workflow_collection = project.workflow_collection
16
- add_github_command(project)
17
- add_command(
18
- ::Semaph::Commands::ReloadCommand.new(workflow_collection, "reload workflows"),
19
- "reload-workflows",
20
- )
21
- add_command(
22
- ::Semaph::Commands::VisitUrlCommand.new(
23
- "https://#{project.client.host}/projects/#{project.name}",
24
- "browse to project",
25
- ),
26
- "open-project",
27
- )
28
- add_command WorkflowsListCommand.new(workflow_collection), "list-workflows"
29
- add_command WorkflowsSelectCommand.new(workflow_collection), "select-workflow"
16
+ @project = project
17
+ @prompt = "🏗 #{project.client.name} #{project.name} > "
18
+ add_commands
19
+ @workflows_list_command.execute("")
30
20
  end
31
21
 
32
22
  private
33
23
 
34
- def add_github_command(project)
24
+ def workflow_collection
25
+ project.workflow_collection
26
+ end
27
+
28
+ def add_commands
29
+ add_github_command
30
+ add_open_project_command
31
+ @workflows_list_command = WorkflowsListCommand.new(workflow_collection)
32
+ add_command @workflows_list_command, "list-workflows"
33
+ add_command WorkflowsSelectCommand.new(workflow_collection), "select-workflow"
34
+ add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
35
+ end
36
+
37
+ def add_github_command
35
38
  return unless project.github_url
36
39
 
37
40
  add_command(
@@ -42,6 +45,16 @@ module Semaph
42
45
  "open-github",
43
46
  )
44
47
  end
48
+
49
+ def add_open_project_command
50
+ add_command(
51
+ ::Semaph::Commands::VisitUrlCommand.new(
52
+ "https://#{project.client.host}/projects/#{project.name}",
53
+ "browse to project",
54
+ ),
55
+ "open-project",
56
+ )
57
+ end
45
58
  end
46
59
  end
47
60
  end
@@ -13,6 +13,7 @@ module Semaph
13
13
  end
14
14
 
15
15
  def execute(branch)
16
+ @workflow_collection.reload
16
17
  @workflow_collection.all.each_with_index do |workflow, index|
17
18
  next unless workflow.branch.include?(branch)
18
19
 
@@ -1,4 +1,5 @@
1
1
  require "semaph/shells/workflow/workflow_shell"
2
+ require "semaph/shells/pipeline/pipeline_shell"
2
3
 
3
4
  module Semaph
4
5
  module Shells
@@ -14,9 +15,15 @@ module Semaph
14
15
 
15
16
  def execute(index_string)
16
17
  index = index_string.to_i - 1
17
- ::Semaph::Shells::Workflow::WorkflowShell.new(
18
- @workflow_collection.all[index],
19
- ).push
18
+
19
+ workflow = @workflow_collection.all[index]
20
+
21
+ unless workflow
22
+ puts "There is no workflow at position #{index}"
23
+ return
24
+ end
25
+
26
+ ::Semaph::Shells::Workflow::WorkflowShell.new(workflow).push
20
27
  end
21
28
  end
22
29
  end
@@ -10,8 +10,9 @@ module Semaph
10
10
  end
11
11
 
12
12
  def execute(_whatever)
13
+ @pipeline_collection.reload
13
14
  @pipeline_collection.all.each_with_index do |pipeline, index|
14
- puts "#{index + 1} #{pipeline.yaml} #{pipeline.state} #{pipeline.result}"
15
+ puts "#{index + 1} #{pipeline.description}"
15
16
  end
16
17
  end
17
18
  end
@@ -14,9 +14,15 @@ module Semaph
14
14
 
15
15
  def execute(index_string)
16
16
  index = index_string.to_i - 1
17
- ::Semaph::Shells::Pipeline::PipelineShell.new(
18
- @pipeline_collection.all[index],
19
- ).push
17
+
18
+ pipeline = @pipeline_collection.all[index]
19
+
20
+ unless pipeline
21
+ puts "There is no pipeline at position #{index}"
22
+ return
23
+ end
24
+
25
+ ::Semaph::Shells::Pipeline::PipelineShell.new(pipeline).push
20
26
  end
21
27
  end
22
28
  end
@@ -1,5 +1,7 @@
1
- require "semaph/commands/visit_url_command"
2
1
  require "semaph/commands/reload_command"
2
+ require "semaph/commands/rerun_workflow_command"
3
+ require "semaph/commands/stop_workflow_command"
4
+ require "semaph/commands/visit_url_command"
3
5
  require "semaph/shells/workflow/pipelines_list_command"
4
6
  require "semaph/shells/workflow/pipelines_select_command"
5
7
  require "shell_shock/context"
@@ -8,15 +10,40 @@ module Semaph
8
10
  module Shells
9
11
  module Workflow
10
12
  class WorkflowShell
13
+ attr_reader :workflow
14
+
11
15
  include ShellShock::Context
12
16
 
13
17
  def initialize(workflow)
14
18
  @workflow = workflow
15
- project = @workflow.project
16
- @prompt = "🏗 #{project.client.host} #{project.name} #{workflow.id} > "
17
- pipeline_collection = workflow.pipeline_collection
18
- add_command PipelinesListCommand.new(pipeline_collection), "list-pipelines"
19
+ @prompt = "🏗 #{project.client.name} #{project.name} #{workflow.id} > "
20
+ add_commands
21
+ @list_command.execute("")
22
+ end
23
+
24
+ private
25
+
26
+ def project
27
+ @workflow.project
28
+ end
29
+
30
+ def pipeline_collection
31
+ @workflow.pipeline_collection
32
+ end
33
+
34
+ def add_commands
35
+ @list_command = PipelinesListCommand.new(pipeline_collection)
36
+ add_command @list_command, "list-pipelines"
19
37
  add_command PipelinesSelectCommand.new(pipeline_collection), "select-pipeline"
38
+ add_command ::Semaph::Commands::RerunWorkflowCommand.new(workflow), "rerun"
39
+ add_command ::Semaph::Commands::StopWorkflowCommand.new(workflow), "stop"
40
+ add_open_branch_command
41
+ add_open_workflow_command
42
+ add_github_commands
43
+ add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
44
+ end
45
+
46
+ def add_open_workflow_command
20
47
  add_command(
21
48
  ::Semaph::Commands::VisitUrlCommand.new(
22
49
  "https://#{project.client.host}/workflows/#{workflow.id}",
@@ -24,6 +51,9 @@ module Semaph
24
51
  ),
25
52
  "open-workflow",
26
53
  )
54
+ end
55
+
56
+ def add_open_branch_command
27
57
  add_command(
28
58
  ::Semaph::Commands::VisitUrlCommand.new(
29
59
  "https://#{project.client.host}/branches/#{workflow.branch_id}",
@@ -31,18 +61,16 @@ module Semaph
31
61
  ),
32
62
  "open-branch",
33
63
  )
34
- add_github_commands(workflow)
35
- add_command(
36
- ::Semaph::Commands::ReloadCommand.new(pipeline_collection, "reload pipelines"),
37
- "reload-pipelines",
38
- )
39
64
  end
40
65
 
41
- private
42
-
43
- def add_github_commands(workflow)
66
+ def add_github_commands
44
67
  return unless workflow.project.github_url
45
68
 
69
+ add_github_branch
70
+ add_github_commit
71
+ end
72
+
73
+ def add_github_branch
46
74
  add_command(
47
75
  ::Semaph::Commands::VisitUrlCommand.new(
48
76
  "#{workflow.project.github_url}/tree/#{workflow.branch}",
@@ -50,6 +78,9 @@ module Semaph
50
78
  ),
51
79
  "open-github-branch",
52
80
  )
81
+ end
82
+
83
+ def add_github_commit
53
84
  add_command(
54
85
  ::Semaph::Commands::VisitUrlCommand.new(
55
86
  "#{workflow.project.github_url}/commit/#{workflow.sha}",
@@ -1,3 +1,3 @@
1
1
  module Semaph
2
- VERSION = "0.2.0".freeze
2
+ VERSION = "0.3.0".freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: semaph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mark Ryall
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-05-30 00:00:00.000000000 Z
11
+ date: 2020-06-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -91,6 +91,8 @@ files:
91
91
  - lib/semaph.rb
92
92
  - lib/semaph/api.rb
93
93
  - lib/semaph/commands/reload_command.rb
94
+ - lib/semaph/commands/rerun_workflow_command.rb
95
+ - lib/semaph/commands/stop_workflow_command.rb
94
96
  - lib/semaph/commands/visit_url_command.rb
95
97
  - lib/semaph/formatting.rb
96
98
  - lib/semaph/model/job.rb
@@ -108,6 +110,8 @@ files:
108
110
  - lib/semaph/shells/organisations/organisations_select_command.rb
109
111
  - lib/semaph/shells/organisations/organisations_shell.rb
110
112
  - lib/semaph/shells/pipeline/jobs_list_command.rb
113
+ - lib/semaph/shells/pipeline/jobs_logs_command.rb
114
+ - lib/semaph/shells/pipeline/jobs_poll_command.rb
111
115
  - lib/semaph/shells/pipeline/pipeline_shell.rb
112
116
  - lib/semaph/shells/project/project_shell.rb
113
117
  - lib/semaph/shells/project/workflows_list_command.rb