semaph 0.1.0 → 0.6.0

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 +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