semaph 0.2.0 → 0.7.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +2 -1
  3. data/.rubocop.yml +39 -0
  4. data/.semaphore/semaphore.yml +5 -1
  5. data/Gemfile.lock +21 -1
  6. data/README.md +85 -11
  7. data/Rakefile +4 -1
  8. data/lib/semaph/client.rb +115 -0
  9. data/lib/semaph/commands.rb +63 -0
  10. data/lib/semaph/commands/reload_command.rb +5 -4
  11. data/lib/semaph/commands/rerun_workflow_command.rb +16 -0
  12. data/lib/semaph/commands/stop_workflow_command.rb +16 -0
  13. data/lib/semaph/formatting.rb +15 -1
  14. data/lib/semaph/model/job.rb +70 -1
  15. data/lib/semaph/model/job_collection.rb +18 -5
  16. data/lib/semaph/model/pipeline.rb +54 -2
  17. data/lib/semaph/model/pipeline_collection.rb +0 -1
  18. data/lib/semaph/model/project.rb +1 -1
  19. data/lib/semaph/model/project_collection.rb +0 -1
  20. data/lib/semaph/model/promotion.rb +31 -0
  21. data/lib/semaph/model/promotion_collection.rb +21 -0
  22. data/lib/semaph/model/workflow.rb +28 -4
  23. data/lib/semaph/model/workflow_collection.rb +0 -1
  24. data/lib/semaph/shells/organisation/organisation_shell.rb +15 -11
  25. data/lib/semaph/shells/organisation/projects_list_command.rb +1 -0
  26. data/lib/semaph/shells/organisation/projects_select_command.rb +6 -0
  27. data/lib/semaph/shells/organisations/organisations_select_command.rb +8 -1
  28. data/lib/semaph/shells/organisations/organisations_shell.rb +6 -2
  29. data/lib/semaph/shells/pipeline/job_debug_command.rb +29 -0
  30. data/lib/semaph/shells/pipeline/job_log_command.rb +44 -0
  31. data/lib/semaph/shells/pipeline/job_log_grep_command.rb +28 -0
  32. data/lib/semaph/shells/pipeline/job_show_command.rb +28 -0
  33. data/lib/semaph/shells/pipeline/job_stop_command.rb +28 -0
  34. data/lib/semaph/shells/pipeline/jobs_list_command.rb +6 -16
  35. data/lib/semaph/shells/pipeline/jobs_poll_command.rb +55 -0
  36. data/lib/semaph/shells/pipeline/pipeline_shell.rb +42 -7
  37. data/lib/semaph/shells/pipeline/promote_command.rb +21 -0
  38. data/lib/semaph/shells/pipeline/promotions_list_command.rb +21 -0
  39. data/lib/semaph/shells/project/project_shell.rb +31 -18
  40. data/lib/semaph/shells/project/workflows_list_command.rb +4 -16
  41. data/lib/semaph/shells/project/workflows_select_command.rb +10 -3
  42. data/lib/semaph/shells/workflow/pipelines_list_command.rb +4 -1
  43. data/lib/semaph/shells/workflow/pipelines_select_command.rb +9 -3
  44. data/lib/semaph/shells/workflow/workflow_shell.rb +13 -42
  45. data/lib/semaph/version.rb +1 -1
  46. data/semaph.gemspec +1 -0
  47. metadata +33 -6
  48. data/lib/semaph/api.rb +0 -61
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b22217dbedbfa234279e494e23d64af812563e6fa8d57e2e2b14f185b3fbe52c
4
- data.tar.gz: 36c3a0944ef6408730c18b2f147f734616300023792e9e82b0c5ebc0956bab05
3
+ metadata.gz: 7db37cbca829e1b13372c7a8687b86080b1e4a579bbb7707e6cc207ebdcb4ba1
4
+ data.tar.gz: 4b5015379f62ad0382991f26b525583d2a6e077889071e5bde58dc1399d69ada
5
5
  SHA512:
6
- metadata.gz: 4fdda4999337920b39947b2c2fe09ea2cf62830998f948fed2d835dd74f5436172276dace4d59f0e493f14381aae349aaa0aafaa123b5f452ab4ed6a1fba0db0
7
- data.tar.gz: c5f969a3450d98f8a9b7a9eeb66d134856558e0376259070206ad0a8e76d4e3c38e6a12e3b27312aa272a48cc08af50288e99b443983ffc1d374d5401f82eb85
6
+ metadata.gz: 243de9cc3425299a5d7a5a11d3a6e06a89e56ad22e0bab59fe4568544fc8e05f0a6e902363497d493811a00c30f84a95456a0679417fb7d4d39b10ad35ece692
7
+ data.tar.gz: f1fd8d22e22885357f0b5c1ba962ac1edb91b61b6ab3b9e03cfec9aeda88197a40bfcfe2b047417d3d2629e5eb8f9fa3e32b9dde40e8feefeb09bae8e7e5527d
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,3 +1,42 @@
1
+ Layout/EmptyLinesAroundAttributeAccessor:
2
+ Enabled: true
3
+
4
+ Layout/SpaceAroundMethodCallOperator:
5
+ Enabled: true
6
+
7
+ Lint/DeprecatedOpenSSLConstant:
8
+ Enabled: true
9
+
10
+ Lint/MixedRegexpCaptureTypes:
11
+ Enabled: true
12
+
13
+ Lint/RaiseException:
14
+ Enabled: true
15
+
16
+ Lint/StructNewOverride:
17
+ Enabled: true
18
+
19
+ Style/ExponentialNotation:
20
+ Enabled: true
21
+
22
+ Style/HashEachMethods:
23
+ Enabled: true
24
+
25
+ Style/HashTransformKeys:
26
+ Enabled: true
27
+
28
+ Style/HashTransformValues:
29
+ Enabled: true
30
+
31
+ Style/RedundantRegexpCharacterClass:
32
+ Enabled: true
33
+
34
+ Style/RedundantRegexpEscape:
35
+ Enabled: true
36
+
37
+ Style/SlicingWithRange:
38
+ Enabled: true
39
+
1
40
  Style/Documentation:
2
41
  Enabled: false
3
42
 
@@ -16,4 +16,8 @@ blocks:
16
16
  - name: Build
17
17
  commands:
18
18
  - checkout
19
- - echo "done"
19
+ - sem-version ruby $(grep ruby .tool-versions | cut -d ' ' -f 2)
20
+ - cache restore $(git ls-tree HEAD Gemfile.lock | cut -f3 -d$' ' | cut -f1 -d$'\t')
21
+ - bundle install --deployment --path vendor/bundle
22
+ - cache store $(git ls-tree HEAD Gemfile.lock | cut -f3 -d$' ' | cut -f1 -d$'\t') vendor/bundle
23
+ - bundle exec rake
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- semaph (0.1.0)
4
+ semaph (0.7.0)
5
5
  faraday
6
6
  rainbow
7
7
  shell_shock
@@ -9,18 +9,37 @@ PATH
9
9
  GEM
10
10
  remote: https://rubygems.org/
11
11
  specs:
12
+ ast (2.4.0)
12
13
  coderay (1.1.2)
13
14
  faraday (1.0.1)
14
15
  multipart-post (>= 1.2, < 3)
15
16
  method_source (1.0.0)
16
17
  minitest (5.14.1)
17
18
  multipart-post (2.1.1)
19
+ parallel (1.19.1)
20
+ parser (2.7.1.3)
21
+ ast (~> 2.4.0)
18
22
  pry (0.13.1)
19
23
  coderay (~> 1.1)
20
24
  method_source (~> 1.0)
21
25
  rainbow (3.0.0)
22
26
  rake (12.3.3)
27
+ regexp_parser (1.7.0)
28
+ rexml (3.2.4)
29
+ rubocop (0.85.0)
30
+ parallel (~> 1.10)
31
+ parser (>= 2.7.0.1)
32
+ rainbow (>= 2.2.2, < 4.0)
33
+ regexp_parser (>= 1.7)
34
+ rexml
35
+ rubocop-ast (>= 0.0.3)
36
+ ruby-progressbar (~> 1.7)
37
+ unicode-display_width (>= 1.4.0, < 2.0)
38
+ rubocop-ast (0.0.3)
39
+ parser (>= 2.7.0.1)
40
+ ruby-progressbar (1.10.1)
23
41
  shell_shock (0.0.5)
42
+ unicode-display_width (1.7.0)
24
43
 
25
44
  PLATFORMS
26
45
  ruby
@@ -29,6 +48,7 @@ DEPENDENCIES
29
48
  minitest (~> 5.0)
30
49
  pry
31
50
  rake (~> 12.0)
51
+ rubocop
32
52
  semaph!
33
53
 
34
54
  BUNDLED WITH
data/README.md CHANGED
@@ -1,28 +1,102 @@
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
+ ### project shell
64
+
65
+ 🏗 foo.semaphoreci.com my-app >
66
+
67
+ From this shell, you will mostly be interested in `list-workflows <branch>` (where 'branch' is any
68
+ substring of the git branch you want to see workflows for) and then `select-workflow <index>`
69
+ (where 'index' is the number displayed for each workflow `list-workflows` - tab completion on uuids
70
+ seemed a bad idea) to enter a shell for that specific workflow.
71
+
72
+ You can also `open-github` (opens a web browser for the github project associated with the project) and `open-project`
73
+ (opens the semaphoreci project in a browser).
74
+
75
+ ### workflow shell
76
+
77
+ 🏗 foo.semaphoreci.com my-app workflowuuid >
78
+
79
+ From this shell, you can `list-pipelines` for the selected workflow. These are the builds usually starting
80
+ from `semaphore.yml` plus any promotion pipelines that might be executed. You can `select-pipeline` to monitor
81
+ what's happening with the pipeline.
82
+
83
+ You can also `open-github-branch`, `open-github-commit` to see the branch/commit in a browser and
84
+ `open-workflow`, `open-branch` to see the semaphore branch/workflow in a browser.
85
+
86
+ ### pipeline shell
87
+
88
+ 🏗 foo.semaphoreci.com my-app workflowuuid semaphore.yml >
89
+
90
+ From this shell, you can `list-jobs`, `poll-jobs`, `job-log` and `grep-logs`.
91
+
92
+ Job polling will stop as soon as any one job has failed and send a system notification
93
+ (as long as `terminal-notifier` is installed).
94
+
95
+ You can look at the log for a specific job (by the index presented in `list-jobs`) using `less`.
96
+
97
+ You can grep across all jobs (using `ag`) with `grep-logs` which will download the logs for all completed jobs.
24
98
 
25
- TODO: Write usage instructions here
99
+ You can also open the same browser views in semaphoreci and github from this shell.
26
100
 
27
101
  ## Development
28
102
 
data/Rakefile CHANGED
@@ -1,5 +1,6 @@
1
1
  require "bundler/gem_tasks"
2
2
  require "rake/testtask"
3
+ require "rubocop/rake_task"
3
4
 
4
5
  Rake::TestTask.new(:test) do |t|
5
6
  t.libs << "test"
@@ -7,4 +8,6 @@ Rake::TestTask.new(:test) do |t|
7
8
  t.test_files = FileList["test/**/*_test.rb"]
8
9
  end
9
10
 
10
- task default: :test
11
+ RuboCop::RakeTask.new(:cop)
12
+
13
+ task default: %i[cop test]
@@ -0,0 +1,115 @@
1
+ require "faraday"
2
+ require "json"
3
+
4
+ module Semaph
5
+ # Refer to https://docs.semaphoreci.com/reference/api-v1alpha/
6
+ class Client
7
+ class RequestException < RuntimeError
8
+ attr_reader :url, :response
9
+
10
+ def initialize(url, response)
11
+ @url = url
12
+ @response = response
13
+ super("http response #{response.status} received for #{url}:\n#{response.body}")
14
+ end
15
+ end
16
+
17
+ attr_reader :host, :name
18
+
19
+ def initialize(token, host)
20
+ @token = token
21
+ @host = host
22
+ @name = host.split(".").first
23
+ @host_url = "https://#{host}"
24
+ @base = "#{@host_url}/api/v1alpha"
25
+ end
26
+
27
+ def projects
28
+ get "projects"
29
+ end
30
+
31
+ def workflows(project_id)
32
+ get "plumber-workflows", { project_id: project_id }
33
+ end
34
+
35
+ def workflow(workflow_id)
36
+ get "plumber-workflows/#{workflow_id}"
37
+ end
38
+
39
+ def stop_workflow(workflow_id)
40
+ post "plumber-workflows/#{workflow_id}/terminate"
41
+ end
42
+
43
+ def rerun_workflow(workflow_id)
44
+ post "plumber-workflows/#{workflow_id}/reschedule?request_token=#{workflow_id}"
45
+ end
46
+
47
+ def pipelines(options)
48
+ get "pipelines", options
49
+ end
50
+
51
+ def pipeline(id)
52
+ get "pipelines/#{id}", { detailed: true }
53
+ end
54
+
55
+ def promotions(pipeline_id)
56
+ get "promotions", { pipeline_id: pipeline_id }
57
+ end
58
+
59
+ def promote(pipeline_id, name)
60
+ post "promotions", { pipeline_id: pipeline_id, name: name }
61
+ end
62
+
63
+ def job(id)
64
+ get "jobs/#{id}"
65
+ end
66
+
67
+ def stop_job(id)
68
+ post "jobs/#{id}/stop"
69
+ end
70
+
71
+ def job_log(id)
72
+ get_raw "jobs/#{id}/plain_logs.json"
73
+ end
74
+
75
+ private
76
+
77
+ def get_raw(path, params = {})
78
+ url = "#{@host_url}/#{path}"
79
+ puts url if ENV["SEMAPH_DEBUG"]
80
+ response = Faraday.get(url, params, { "Authorization" => "Token #{@token}" })
81
+ check_response(response, url)
82
+ end
83
+
84
+ def get(path, params = {})
85
+ url = "#{@base}/#{path}"
86
+ puts url if ENV["SEMAPH_DEBUG"]
87
+ response = Faraday.get(url, params, headers)
88
+ JSON.parse(check_response(response, url)).tap do |hash|
89
+ pp hash if ENV["SEMAPH_DEBUG"]
90
+ end
91
+ end
92
+
93
+ def post(path, params = {})
94
+ url = "#{@base}/#{path}"
95
+ response = Faraday.post(url, params.to_json, headers)
96
+ JSON.parse(check_response(response, url)).tap do |hash|
97
+ pp hash if ENV["SEMAPH_DEBUG"]
98
+ end
99
+ end
100
+
101
+ def headers
102
+ {
103
+ "Authorization" => "Token #{@token}",
104
+ "Content-Type" => "application/json",
105
+ "Accept" => "application/json",
106
+ }
107
+ end
108
+
109
+ def check_response(response, url)
110
+ return response.body if response.status == 200
111
+
112
+ raise RequestException.new(url, response)
113
+ end
114
+ end
115
+ end
@@ -0,0 +1,63 @@
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"
5
+
6
+ module Semaph
7
+ module Commands
8
+ def self.workflow_commands(shell, workflow)
9
+ shell.add_command ::Semaph::Commands::RerunWorkflowCommand.new(workflow), "rerun"
10
+ shell.add_command ::Semaph::Commands::StopWorkflowCommand.new(workflow), "stop"
11
+ add_open_workflow_command(shell, workflow)
12
+ add_open_branch_command(shell, workflow)
13
+ add_github_commands(shell, workflow)
14
+ end
15
+
16
+ def self.add_open_workflow_command(shell, workflow)
17
+ shell.add_command(
18
+ ::Semaph::Commands::VisitUrlCommand.new(
19
+ "https://#{workflow.project.client.host}/workflows/#{workflow.id}",
20
+ "browse to workflow",
21
+ ),
22
+ "open-workflow",
23
+ )
24
+ end
25
+
26
+ def self.add_open_branch_command(shell, workflow)
27
+ shell.add_command(
28
+ ::Semaph::Commands::VisitUrlCommand.new(
29
+ "https://#{workflow.project.client.host}/branches/#{workflow.branch_id}",
30
+ "browse to branch in semaphore",
31
+ ),
32
+ "open-branch",
33
+ )
34
+ end
35
+
36
+ def self.add_github_commands(shell, workflow)
37
+ return unless workflow.project.github_url
38
+
39
+ add_github_branch(shell, workflow)
40
+ add_github_commit(shell, workflow)
41
+ end
42
+
43
+ def self.add_github_branch(shell, workflow)
44
+ shell.add_command(
45
+ ::Semaph::Commands::VisitUrlCommand.new(
46
+ "#{workflow.project.github_url}/tree/#{workflow.branch}",
47
+ "browse to the branch in github",
48
+ ),
49
+ "open-github-branch",
50
+ )
51
+ end
52
+
53
+ def self.add_github_commit(shell, workflow)
54
+ shell.add_command(
55
+ ::Semaph::Commands::VisitUrlCommand.new(
56
+ "#{workflow.project.github_url}/commit/#{workflow.sha}",
57
+ "browse to the commit in github",
58
+ ),
59
+ "open-github-commit",
60
+ )
61
+ end
62
+ end
63
+ end
@@ -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