semaph 0.4.0 → 0.9.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.
- checksums.yaml +4 -4
- data/.rubocop.yml +39 -0
- data/.semaph +9 -0
- data/.semaphore/semaphore.yml +5 -1
- data/Gemfile.lock +21 -1
- data/README.md +12 -8
- data/Rakefile +4 -1
- data/lib/semaph.rb +43 -8
- data/lib/semaph/{api.rb → client.rb} +24 -3
- data/lib/semaph/commands.rb +63 -0
- data/lib/semaph/commands/rerun_workflow_command.rb +0 -2
- data/lib/semaph/commands/stop_workflow_command.rb +0 -2
- data/lib/semaph/formatting.rb +19 -1
- data/lib/semaph/model/job.rb +21 -2
- data/lib/semaph/model/job_collection.rb +19 -3
- data/lib/semaph/model/pipeline.rb +29 -3
- data/lib/semaph/model/promotion.rb +31 -0
- data/lib/semaph/model/promotion_collection.rb +21 -0
- data/lib/semaph/model/workflow.rb +17 -3
- data/lib/semaph/shells/organisation/organisation_shell.rb +4 -4
- data/lib/semaph/shells/organisation/projects_select_command.rb +6 -0
- data/lib/semaph/shells/organisations/organisations_list_command.rb +2 -2
- data/lib/semaph/shells/organisations/organisations_select_command.rb +11 -2
- data/lib/semaph/shells/organisations/organisations_shell.rb +2 -2
- data/lib/semaph/shells/pipeline/job_debug_command.rb +29 -0
- data/lib/semaph/shells/pipeline/job_log_command.rb +17 -15
- data/lib/semaph/shells/pipeline/job_log_grep_command.rb +5 -11
- data/lib/semaph/shells/pipeline/job_show_command.rb +28 -0
- data/lib/semaph/shells/pipeline/job_stop_command.rb +28 -0
- data/lib/semaph/shells/pipeline/jobs_list_command.rb +4 -2
- data/lib/semaph/shells/pipeline/jobs_poll_command.rb +58 -22
- data/lib/semaph/shells/pipeline/pipeline_shell.rb +28 -68
- data/lib/semaph/shells/pipeline/promote_command.rb +21 -0
- data/lib/semaph/shells/pipeline/promotions_list_command.rb +21 -0
- data/lib/semaph/shells/project/project_shell.rb +4 -2
- data/lib/semaph/shells/project/save_command.rb +26 -0
- data/lib/semaph/shells/project/workflows_list_command.rb +11 -17
- data/lib/semaph/shells/workflow/pipelines_list_command.rb +3 -1
- data/lib/semaph/shells/workflow/workflow_shell.rb +6 -66
- data/lib/semaph/version.rb +1 -1
- data/semaph.gemspec +1 -0
- metadata +30 -6
@@ -0,0 +1,28 @@
|
|
1
|
+
module Semaph
|
2
|
+
module Shells
|
3
|
+
module Pipeline
|
4
|
+
class JobStopCommand
|
5
|
+
attr_reader :usage, :help
|
6
|
+
|
7
|
+
def initialize(job_collection)
|
8
|
+
@job_collection = job_collection
|
9
|
+
@usage = "<job index>"
|
10
|
+
@help = "stop 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
|
+
job.stop
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "semaph/formatting"
|
2
|
+
|
1
3
|
module Semaph
|
2
4
|
module Shells
|
3
5
|
module Pipeline
|
@@ -9,10 +11,10 @@ module Semaph
|
|
9
11
|
@help = "list jobs"
|
10
12
|
end
|
11
13
|
|
12
|
-
def execute(_whatever)
|
14
|
+
def execute(_whatever = nil)
|
13
15
|
@job_collection.reload
|
14
16
|
@job_collection.all.each_with_index do |job, index|
|
15
|
-
puts
|
17
|
+
puts [::Semaph::Formatting.index(index + 1), job.description].join(" ")
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
@@ -1,35 +1,71 @@
|
|
1
|
+
require "semaph/formatting"
|
2
|
+
|
1
3
|
module Semaph
|
2
4
|
module Shells
|
3
5
|
module Pipeline
|
4
6
|
class JobsPollCommand
|
5
|
-
attr_reader :usage, :help
|
7
|
+
attr_reader :usage, :help, :job_collection
|
6
8
|
|
7
|
-
def initialize(job_collection)
|
9
|
+
def initialize(job_collection, list_command)
|
8
10
|
@job_collection = job_collection
|
11
|
+
@list_command = list_command
|
9
12
|
@help = "poll jobs"
|
10
13
|
@can_notify = !`which terminal-notifier`.chomp.empty?
|
11
14
|
end
|
12
15
|
|
13
|
-
def execute(_whatever)
|
14
|
-
|
15
|
-
while
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
16
|
+
def execute(_whatever = nil)
|
17
|
+
puts "Polling #{job_collection.pipeline.workflow.description}:"
|
18
|
+
report_and_reload(15) while job_collection.incomplete.count.positive? && job_collection.failed.count.zero?
|
19
|
+
report_final
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def report_and_reload(period)
|
25
|
+
period.times { report_incomplete }
|
26
|
+
job_collection.reload
|
27
|
+
end
|
28
|
+
|
29
|
+
def report_final
|
30
|
+
@list_command.execute
|
31
|
+
failed_job_count = job_collection.failed.count
|
32
|
+
notify(
|
33
|
+
"Workflow completed",
|
34
|
+
"#{job_collection.pipeline.workflow.description} completed with #{failed_job_count} failed jobs",
|
35
|
+
failed_job_count.positive?,
|
36
|
+
)
|
37
|
+
end
|
38
|
+
|
39
|
+
def report_incomplete
|
40
|
+
base = [nil, elapsed, report_ratio, "jobs remaining"].join(" ")
|
41
|
+
erase base
|
42
|
+
end
|
43
|
+
|
44
|
+
def report_ratio
|
45
|
+
[
|
46
|
+
job_collection.incomplete.count.to_s.rjust(2, "0"),
|
47
|
+
job_collection.all.count.to_s.rjust(2, "0"),
|
48
|
+
].join("/")
|
49
|
+
end
|
50
|
+
|
51
|
+
def elapsed
|
52
|
+
duration = Time.now.to_i - job_collection.created_at.to_i
|
53
|
+
mins = duration / 60
|
54
|
+
secs = duration % 60
|
55
|
+
[mins.to_s.rjust(2, "0"), secs.to_s.rjust(2, "0")].join(":")
|
56
|
+
end
|
57
|
+
|
58
|
+
def erase(string)
|
59
|
+
print string
|
60
|
+
print "\b" * string.length
|
61
|
+
end
|
62
|
+
|
63
|
+
def notify(title, message, failed)
|
64
|
+
return unless @can_notify
|
65
|
+
|
66
|
+
sound = failed ? "basso" : "blow"
|
67
|
+
|
68
|
+
`terminal-notifier -group semaph -message "#{message}" -title "#{title}" -sound #{sound}`
|
33
69
|
end
|
34
70
|
end
|
35
71
|
end
|
@@ -1,9 +1,13 @@
|
|
1
|
-
require "semaph/commands
|
2
|
-
require "semaph/
|
3
|
-
require "semaph/shells/pipeline/jobs_list_command"
|
1
|
+
require "semaph/commands"
|
2
|
+
require "semaph/shells/pipeline/job_debug_command"
|
4
3
|
require "semaph/shells/pipeline/job_log_command"
|
5
4
|
require "semaph/shells/pipeline/job_log_grep_command"
|
5
|
+
require "semaph/shells/pipeline/job_show_command"
|
6
|
+
require "semaph/shells/pipeline/job_stop_command"
|
7
|
+
require "semaph/shells/pipeline/jobs_list_command"
|
6
8
|
require "semaph/shells/pipeline/jobs_poll_command"
|
9
|
+
require "semaph/shells/pipeline/promote_command"
|
10
|
+
require "semaph/shells/pipeline/promotions_list_command"
|
7
11
|
require "shell_shock/context"
|
8
12
|
|
9
13
|
module Semaph
|
@@ -16,83 +20,39 @@ module Semaph
|
|
16
20
|
|
17
21
|
def initialize(pipeline)
|
18
22
|
@pipeline = pipeline
|
23
|
+
workflow = pipeline.workflow
|
24
|
+
project = workflow.project
|
19
25
|
@prompt = "🏗 #{project.client.name} #{project.name} #{workflow.id} #{pipeline.yaml} > "
|
26
|
+
add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
|
20
27
|
add_commands
|
21
|
-
|
28
|
+
jobs_list_command.execute
|
22
29
|
end
|
23
30
|
|
24
31
|
private
|
25
32
|
|
26
|
-
def project
|
27
|
-
workflow.project
|
28
|
-
end
|
29
|
-
|
30
|
-
def workflow
|
31
|
-
pipeline.workflow
|
32
|
-
end
|
33
|
-
|
34
|
-
def job_collection
|
35
|
-
pipeline.job_collection
|
36
|
-
end
|
37
|
-
|
38
33
|
def add_commands
|
39
|
-
|
40
|
-
|
41
|
-
add_command
|
42
|
-
add_command
|
43
|
-
add_command JobLogGrepCommand.new(job_collection), "grep-logs"
|
44
|
-
add_command ::Semaph::Commands::RerunWorkflowCommand.new(workflow), "rerun"
|
45
|
-
add_open_branch_command
|
46
|
-
add_open_workflow_command
|
47
|
-
add_github_commands
|
48
|
-
add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
|
49
|
-
end
|
50
|
-
|
51
|
-
def add_open_workflow_command
|
52
|
-
add_command(
|
53
|
-
::Semaph::Commands::VisitUrlCommand.new(
|
54
|
-
"https://#{project.client.host}/workflows/#{workflow.id}",
|
55
|
-
"browse to workflow",
|
56
|
-
),
|
57
|
-
"open-workflow",
|
58
|
-
)
|
34
|
+
::Semaph::Commands.workflow_commands(self, pipeline.workflow)
|
35
|
+
add_job_collection_commands(pipeline.job_collection)
|
36
|
+
add_command PromoteCommand.new(pipeline), "promote"
|
37
|
+
add_command PromotionsListCommand.new(pipeline.promotion_collection), "list-promotions"
|
59
38
|
end
|
60
39
|
|
61
|
-
def
|
62
|
-
add_command(
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
)
|
40
|
+
def add_job_collection_commands(job_collection)
|
41
|
+
add_command JobsPollCommand.new(job_collection, jobs_list_command), "poll"
|
42
|
+
add_command JobLogCommand.new(job_collection), "log"
|
43
|
+
add_command JobDebugCommand.new(job_collection), "debug"
|
44
|
+
add_command JobShowCommand.new(job_collection), "show"
|
45
|
+
add_command JobStopCommand.new(job_collection), "stop"
|
46
|
+
add_command JobLogGrepCommand.new(job_collection, :all), "grep-all-logs"
|
47
|
+
add_command JobLogGrepCommand.new(job_collection, :failed), "grep-failed-logs"
|
69
48
|
end
|
70
49
|
|
71
|
-
def
|
72
|
-
return
|
73
|
-
|
74
|
-
add_github_branch
|
75
|
-
add_github_commit
|
76
|
-
end
|
77
|
-
|
78
|
-
def add_github_branch
|
79
|
-
add_command(
|
80
|
-
::Semaph::Commands::VisitUrlCommand.new(
|
81
|
-
"#{workflow.project.github_url}/tree/#{workflow.branch}",
|
82
|
-
"browse to the branch in github",
|
83
|
-
),
|
84
|
-
"open-github-branch",
|
85
|
-
)
|
86
|
-
end
|
50
|
+
def jobs_list_command
|
51
|
+
return @jobs_list_command if @jobs_list_command
|
87
52
|
|
88
|
-
|
89
|
-
add_command
|
90
|
-
|
91
|
-
"#{workflow.project.github_url}/commit/#{workflow.sha}",
|
92
|
-
"browse to the commit in github",
|
93
|
-
),
|
94
|
-
"open-github-commit",
|
95
|
-
)
|
53
|
+
@jobs_list_command = JobsListCommand.new(pipeline.job_collection)
|
54
|
+
add_command @jobs_list_command, "list-jobs", "ls"
|
55
|
+
@jobs_list_command
|
96
56
|
end
|
97
57
|
end
|
98
58
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Semaph
|
2
|
+
module Shells
|
3
|
+
module Pipeline
|
4
|
+
class PromoteCommand
|
5
|
+
attr_reader :usage, :help
|
6
|
+
|
7
|
+
def initialize(pipeline)
|
8
|
+
@pipeline = pipeline
|
9
|
+
@usage = "<promotion name>"
|
10
|
+
@help = "promote pipeline"
|
11
|
+
end
|
12
|
+
|
13
|
+
def execute(name)
|
14
|
+
@pipeline.promote(name.chomp.strip)
|
15
|
+
rescue ::Semaph::Client::RequestException => e
|
16
|
+
puts e.message
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Semaph
|
2
|
+
module Shells
|
3
|
+
module Pipeline
|
4
|
+
class PromotionsListCommand
|
5
|
+
attr_reader :usage, :help
|
6
|
+
|
7
|
+
def initialize(promotion_collection)
|
8
|
+
@promotion_collection = promotion_collection
|
9
|
+
@help = "list promotions"
|
10
|
+
end
|
11
|
+
|
12
|
+
def execute(_whatever)
|
13
|
+
@promotion_collection.reload
|
14
|
+
@promotion_collection.all.each_with_index do |promotion, index|
|
15
|
+
puts "#{index + 1} #{promotion.description}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -1,5 +1,6 @@
|
|
1
1
|
require "semaph/commands/reload_command"
|
2
2
|
require "semaph/commands/visit_url_command"
|
3
|
+
require "semaph/shells/project/save_command"
|
3
4
|
require "semaph/shells/project/workflows_list_command"
|
4
5
|
require "semaph/shells/project/workflows_select_command"
|
5
6
|
require "shell_shock/context"
|
@@ -28,9 +29,10 @@ module Semaph
|
|
28
29
|
def add_commands
|
29
30
|
add_github_command
|
30
31
|
add_open_project_command
|
32
|
+
add_command SaveCommand.new(project), "save"
|
31
33
|
@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 @workflows_list_command, "list-workflows", "ls"
|
35
|
+
add_command WorkflowsSelectCommand.new(workflow_collection), "select-workflow", "cd"
|
34
36
|
add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
|
35
37
|
end
|
36
38
|
|
@@ -0,0 +1,26 @@
|
|
1
|
+
require "yaml"
|
2
|
+
|
3
|
+
module Semaph
|
4
|
+
module Shells
|
5
|
+
module Project
|
6
|
+
class SaveCommand
|
7
|
+
attr_reader :help, :project
|
8
|
+
|
9
|
+
def initialize(project)
|
10
|
+
@project = project
|
11
|
+
@help = "save current project as default for this folder"
|
12
|
+
end
|
13
|
+
|
14
|
+
def execute(_ignored)
|
15
|
+
config = {
|
16
|
+
host: project.client.host,
|
17
|
+
project: project.raw,
|
18
|
+
}
|
19
|
+
File.open(".semaph", "w") do |file|
|
20
|
+
file.puts config.to_yaml
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -1,9 +1,9 @@
|
|
1
|
+
require "semaph/formatting"
|
2
|
+
|
1
3
|
module Semaph
|
2
4
|
module Shells
|
3
5
|
module Project
|
4
6
|
class WorkflowsListCommand
|
5
|
-
TIME_FORMAT = "%Y-%m-%d %H:%M:%S".freeze
|
6
|
-
|
7
7
|
attr_reader :usage, :help
|
8
8
|
|
9
9
|
def initialize(workflow_collection)
|
@@ -14,24 +14,18 @@ module Semaph
|
|
14
14
|
|
15
15
|
def execute(branch)
|
16
16
|
@workflow_collection.reload
|
17
|
-
@workflow_collection.all.each_with_index do |workflow, index|
|
17
|
+
@workflow_collection.all.slice(0..9).each_with_index do |workflow, index|
|
18
18
|
next unless workflow.branch.include?(branch)
|
19
19
|
|
20
|
-
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
private
|
20
|
+
pipelines = workflow.pipeline_collection.reload
|
25
21
|
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
workflow.branch,
|
34
|
-
].join(" ")
|
22
|
+
puts [
|
23
|
+
::Semaph::Formatting.index(index + 1),
|
24
|
+
pipelines.last&.icon,
|
25
|
+
::Semaph::Formatting.length(pipelines),
|
26
|
+
workflow.description,
|
27
|
+
].join(" ")
|
28
|
+
end
|
35
29
|
end
|
36
30
|
end
|
37
31
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "semaph/formatting"
|
2
|
+
|
1
3
|
module Semaph
|
2
4
|
module Shells
|
3
5
|
module Workflow
|
@@ -12,7 +14,7 @@ module Semaph
|
|
12
14
|
def execute(_whatever)
|
13
15
|
@pipeline_collection.reload
|
14
16
|
@pipeline_collection.all.each_with_index do |pipeline, index|
|
15
|
-
puts
|
17
|
+
puts [::Semaph::Formatting.index(index + 1), pipeline.description].join(" ")
|
16
18
|
end
|
17
19
|
end
|
18
20
|
end
|
@@ -1,7 +1,4 @@
|
|
1
|
-
require "semaph/commands
|
2
|
-
require "semaph/commands/rerun_workflow_command"
|
3
|
-
require "semaph/commands/stop_workflow_command"
|
4
|
-
require "semaph/commands/visit_url_command"
|
1
|
+
require "semaph/commands"
|
5
2
|
require "semaph/shells/workflow/pipelines_list_command"
|
6
3
|
require "semaph/shells/workflow/pipelines_select_command"
|
7
4
|
require "shell_shock/context"
|
@@ -16,6 +13,7 @@ module Semaph
|
|
16
13
|
|
17
14
|
def initialize(workflow)
|
18
15
|
@workflow = workflow
|
16
|
+
project = @workflow.project
|
19
17
|
@prompt = "🏗 #{project.client.name} #{project.name} #{workflow.id} > "
|
20
18
|
add_commands
|
21
19
|
@list_command.execute("")
|
@@ -23,71 +21,13 @@ module Semaph
|
|
23
21
|
|
24
22
|
private
|
25
23
|
|
26
|
-
def project
|
27
|
-
@workflow.project
|
28
|
-
end
|
29
|
-
|
30
|
-
def pipeline_collection
|
31
|
-
@workflow.pipeline_collection
|
32
|
-
end
|
33
|
-
|
34
24
|
def add_commands
|
25
|
+
pipeline_collection = @workflow.pipeline_collection
|
35
26
|
@list_command = PipelinesListCommand.new(pipeline_collection)
|
36
|
-
add_command @list_command, "list-pipelines"
|
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
|
27
|
+
add_command @list_command, "list-pipelines", "ls"
|
28
|
+
add_command PipelinesSelectCommand.new(pipeline_collection), "select-pipeline", "cd"
|
43
29
|
add_command ::Semaph::Commands::ReloadCommand.new, "reload" if ENV["SEMAPH_RELOAD"]
|
44
|
-
|
45
|
-
|
46
|
-
def add_open_workflow_command
|
47
|
-
add_command(
|
48
|
-
::Semaph::Commands::VisitUrlCommand.new(
|
49
|
-
"https://#{project.client.host}/workflows/#{workflow.id}",
|
50
|
-
"browse to workflow",
|
51
|
-
),
|
52
|
-
"open-workflow",
|
53
|
-
)
|
54
|
-
end
|
55
|
-
|
56
|
-
def add_open_branch_command
|
57
|
-
add_command(
|
58
|
-
::Semaph::Commands::VisitUrlCommand.new(
|
59
|
-
"https://#{project.client.host}/branches/#{workflow.branch_id}",
|
60
|
-
"browse to branch in semaphore",
|
61
|
-
),
|
62
|
-
"open-branch",
|
63
|
-
)
|
64
|
-
end
|
65
|
-
|
66
|
-
def add_github_commands
|
67
|
-
return unless workflow.project.github_url
|
68
|
-
|
69
|
-
add_github_branch
|
70
|
-
add_github_commit
|
71
|
-
end
|
72
|
-
|
73
|
-
def add_github_branch
|
74
|
-
add_command(
|
75
|
-
::Semaph::Commands::VisitUrlCommand.new(
|
76
|
-
"#{workflow.project.github_url}/tree/#{workflow.branch}",
|
77
|
-
"browse to the branch in github",
|
78
|
-
),
|
79
|
-
"open-github-branch",
|
80
|
-
)
|
81
|
-
end
|
82
|
-
|
83
|
-
def add_github_commit
|
84
|
-
add_command(
|
85
|
-
::Semaph::Commands::VisitUrlCommand.new(
|
86
|
-
"#{workflow.project.github_url}/commit/#{workflow.sha}",
|
87
|
-
"browse to the commit in github",
|
88
|
-
),
|
89
|
-
"open-github-commit",
|
90
|
-
)
|
30
|
+
::Semaph::Commands.workflow_commands(self, workflow)
|
91
31
|
end
|
92
32
|
end
|
93
33
|
end
|