semaph 0.1.0 → 0.6.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 (46) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +3 -0
  3. data/.rubocop.yml +18 -0
  4. data/.semaphore/semaphore.yml +23 -0
  5. data/.tool-versions +1 -0
  6. data/Gemfile +1 -1
  7. data/Gemfile.lock +55 -0
  8. data/README.md +85 -11
  9. data/Rakefile +4 -1
  10. data/exe/semaph +5 -0
  11. data/lib/semaph.rb +17 -1
  12. data/lib/semaph/api.rb +94 -0
  13. data/lib/semaph/commands.rb +63 -0
  14. data/lib/semaph/commands/reload_command.rb +17 -0
  15. data/lib/semaph/commands/rerun_workflow_command.rb +16 -0
  16. data/lib/semaph/commands/stop_workflow_command.rb +16 -0
  17. data/lib/semaph/commands/visit_url_command.rb +16 -0
  18. data/lib/semaph/formatting.rb +9 -0
  19. data/lib/semaph/model/job.rb +101 -0
  20. data/lib/semaph/model/job_collection.rb +47 -0
  21. data/lib/semaph/model/pipeline.rb +48 -0
  22. data/lib/semaph/model/pipeline_collection.rb +20 -0
  23. data/lib/semaph/model/project.rb +34 -0
  24. data/lib/semaph/model/project_collection.rb +19 -0
  25. data/lib/semaph/model/workflow.rb +48 -0
  26. data/lib/semaph/model/workflow_collection.rb +19 -0
  27. data/lib/semaph/shells/organisation/organisation_shell.rb +33 -0
  28. data/lib/semaph/shells/organisation/projects_list_command.rb +21 -0
  29. data/lib/semaph/shells/organisation/projects_select_command.rb +26 -0
  30. data/lib/semaph/shells/organisations/organisations_list_command.rb +20 -0
  31. data/lib/semaph/shells/organisations/organisations_select_command.rb +25 -0
  32. data/lib/semaph/shells/organisations/organisations_shell.rb +24 -0
  33. data/lib/semaph/shells/pipeline/job_log_command.rb +44 -0
  34. data/lib/semaph/shells/pipeline/job_log_grep_command.rb +28 -0
  35. data/lib/semaph/shells/pipeline/jobs_list_command.rb +21 -0
  36. data/lib/semaph/shells/pipeline/jobs_poll_command.rb +62 -0
  37. data/lib/semaph/shells/pipeline/pipeline_shell.rb +45 -0
  38. data/lib/semaph/shells/project/project_shell.rb +61 -0
  39. data/lib/semaph/shells/project/workflows_list_command.rb +24 -0
  40. data/lib/semaph/shells/project/workflows_select_command.rb +31 -0
  41. data/lib/semaph/shells/workflow/pipelines_list_command.rb +21 -0
  42. data/lib/semaph/shells/workflow/pipelines_select_command.rb +30 -0
  43. data/lib/semaph/shells/workflow/workflow_shell.rb +35 -0
  44. data/lib/semaph/version.rb +1 -1
  45. data/semaph.gemspec +12 -7
  46. metadata +115 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 4f49ea8741a162ab91ff18cb0b66618afe8eb462af876706b2d9707607f8c6be
4
- data.tar.gz: cd248141014a077dfaa4f6e7a2ffc2a209e2f96b343986bef2dfcece3e681fdd
3
+ metadata.gz: 31aeabe99b27b7a10bc26f91c6a60e87e3374b309df5e41b8354694d99bd1a90
4
+ data.tar.gz: 34499279ff5fedb14739093655ad29ff703c9c3d40222208783106d73d746841
5
5
  SHA512:
6
- metadata.gz: 7ebec8bbd45b6db77176c1e24934d5f5f7d50df018a00126d27b6fe3f5081768c9723e95cce8edab6ed8a0ad2d7abe1c1cacb9439b9343b68cfe6df03fa72408
7
- data.tar.gz: f49f85257c58f82060c4082b59eb2d2b9698c2db8bd92188974c3f969620a73880e377ca7c8bb1b73aee3d02de2652bbdcfc37355047f0c119c399d1892c8ca7
6
+ metadata.gz: 47939331aee8435b5584f29ab39cf9647730dc0ead3b340c20175df3da849120aec5e9b97d3cd7dc116aa6044ac4fd9e1c4648b6ece862afe01a40b8e5007da9
7
+ data.tar.gz: 4f7b74225fd180ea85fad14c73a8a808733fc1d4836b69b99069a25314996bdd70066c1c1bb35b5e247cbeeefe5191760af50102d338e65992fdbd44ebfe529c
data/.gitignore CHANGED
@@ -1,3 +1,6 @@
1
+ .DS_Store
2
+ *.log
3
+
1
4
  /.bundle/
2
5
  /.yardoc
3
6
  /_yardoc/
@@ -0,0 +1,18 @@
1
+ Style/Documentation:
2
+ Enabled: false
3
+
4
+ Style/FrozenStringLiteralComment:
5
+ EnforcedStyle: never
6
+
7
+ Style/StringLiterals:
8
+ EnforcedStyle: double_quotes
9
+
10
+ Style/TrailingCommaInArguments:
11
+ EnforcedStyleForMultiline: consistent_comma
12
+
13
+ Style/TrailingCommaInArrayLiteral:
14
+ EnforcedStyleForMultiline: consistent_comma
15
+
16
+ Style/TrailingCommaInHashLiteral:
17
+ EnforcedStyleForMultiline: consistent_comma
18
+
@@ -0,0 +1,23 @@
1
+ version: v1.0
2
+ name: "Main Build"
3
+ agent:
4
+ machine:
5
+ type: e1-standard-2
6
+ os_image: ubuntu1804
7
+
8
+ auto_cancel:
9
+ queued:
10
+ when: true
11
+
12
+ blocks:
13
+ - name: "Build"
14
+ task:
15
+ jobs:
16
+ - name: Build
17
+ commands:
18
+ - checkout
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
@@ -0,0 +1 @@
1
+ ruby 2.7.1
data/Gemfile CHANGED
@@ -3,5 +3,5 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in semaph.gemspec
4
4
  gemspec
5
5
 
6
- gem "rake", "~> 12.0"
7
6
  gem "minitest", "~> 5.0"
7
+ gem "rake", "~> 12.0"
@@ -0,0 +1,55 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ semaph (0.6.0)
5
+ faraday
6
+ rainbow
7
+ shell_shock
8
+
9
+ GEM
10
+ remote: https://rubygems.org/
11
+ specs:
12
+ ast (2.4.0)
13
+ coderay (1.1.2)
14
+ faraday (1.0.1)
15
+ multipart-post (>= 1.2, < 3)
16
+ method_source (1.0.0)
17
+ minitest (5.14.1)
18
+ multipart-post (2.1.1)
19
+ parallel (1.19.1)
20
+ parser (2.7.1.3)
21
+ ast (~> 2.4.0)
22
+ pry (0.13.1)
23
+ coderay (~> 1.1)
24
+ method_source (~> 1.0)
25
+ rainbow (3.0.0)
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)
41
+ shell_shock (0.0.5)
42
+ unicode-display_width (1.7.0)
43
+
44
+ PLATFORMS
45
+ ruby
46
+
47
+ DEPENDENCIES
48
+ minitest (~> 5.0)
49
+ pry
50
+ rake (~> 12.0)
51
+ rubocop
52
+ semaph!
53
+
54
+ BUNDLED WITH
55
+ 2.1.4
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,5 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ $LOAD_PATH.unshift File.join(File.dirname(__FILE__), "..", "lib")
4
+ require "semaph"
5
+ Semaph.console
@@ -1,6 +1,22 @@
1
1
  require "semaph/version"
2
+ require "semaph/shells/organisations/organisations_shell"
3
+ require "semaph/shells/organisation/organisation_shell"
4
+ require "yaml"
2
5
 
3
6
  module Semaph
4
7
  class Error < StandardError; end
5
- # Your code goes here...
8
+
9
+ def self.console
10
+ yaml_path = File.join(File.expand_path("~"), ".sem.yaml")
11
+ raise "Please install the sem tool and authenticate to semaphoreci.com" unless File.exist?(yaml_path)
12
+
13
+ sem_config = YAML.load_file(yaml_path)
14
+ contexts = sem_config["contexts"]
15
+
16
+ if contexts.count == 1
17
+ Shells::Organisation::OrganisationShell.new(contexts.values.first).push
18
+ else
19
+ Shells::Organisations::OrganisationsShell.new(contexts).push
20
+ end
21
+ end
6
22
  end
@@ -0,0 +1,94 @@
1
+ require "faraday"
2
+ require "json"
3
+
4
+ module Semaph
5
+ # Refer to https://docs.semaphoreci.com/reference/api-v1alpha/
6
+ class Api
7
+ attr_reader :host, :name
8
+
9
+ def initialize(token, host)
10
+ @token = token
11
+ @host = host
12
+ @name = host.split(".").first
13
+ @host_url = "https://#{host}"
14
+ @base = "#{@host_url}/api/v1alpha"
15
+ end
16
+
17
+ def projects
18
+ get "projects"
19
+ end
20
+
21
+ def workflows(project_id)
22
+ get "plumber-workflows", { project_id: project_id }
23
+ end
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
+
37
+ def pipelines(options)
38
+ get "pipelines", options
39
+ end
40
+
41
+ def pipeline(id)
42
+ get "pipelines/#{id}", { detailed: true }
43
+ end
44
+
45
+ def job(id)
46
+ get "jobs/#{id}"
47
+ end
48
+
49
+ def job_log(id)
50
+ get_raw "jobs/#{id}/plain_logs.json"
51
+ end
52
+
53
+ private
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
+
62
+ def get(path, params = {})
63
+ url = "#{@base}/#{path}"
64
+ puts url if ENV["SEMAPH_DEBUG"]
65
+ response = Faraday.get(url, params, headers)
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|
75
+ pp hash if ENV["SEMAPH_DEBUG"]
76
+ end
77
+ end
78
+
79
+ def headers
80
+ {
81
+ "Authorization" => "Token #{@token}",
82
+ "Content-Type" => "application/json",
83
+ "Accept" => "application/json",
84
+ }
85
+ end
86
+
87
+ def check_response(response, url)
88
+ return response.body if response.status == 200
89
+
90
+ puts "http response #{response.status} received for #{url}:\n#{response.body}"
91
+ exit 1
92
+ end
93
+ end
94
+ 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