Class: Cody::Tailer
Instance Method Summary
collapse
#cfn, #codebuild
#are_you_sure?, #inferred_project_name, #inferred_stack_name, #project_name_convention, #stack_exists?
Constructor Details
#initialize(options, build_id) ⇒ Tailer
Returns a new instance of Tailer.
7
8
9
10
11
12
13
14
|
# File 'lib/cody/tailer.rb', line 7
def initialize(options, build_id)
@options, @build_id = options, build_id
@output = [] @shown_phases = []
@thread = nil
set_trap
end
|
Instance Method Details
#build_time(build) ⇒ Object
175
176
177
178
|
# File 'lib/cody/tailer.rb', line 175
def build_time(build)
duration = build.phases.inject(0) { |sum,p| sum + p.duration_in_seconds.to_i }
pretty_time(duration)
end
|
#cloudwatch_tail ⇒ Object
75
76
77
78
79
80
81
82
83
84
85
|
# File 'lib/cody/tailer.rb', line 75
def cloudwatch_tail
since = @options[:since] || "7d" cw_tail = AwsLogs::Tail.new(
log_group_name: @log_group_name,
log_stream_names: [@log_stream_name],
since: since,
follow: true,
format: "simple",
)
cw_tail.run
end
|
#complete_failed?(build) ⇒ Boolean
build.build_status : The current status of the build. Valid values include:
FAILED : The build failed.
FAULT : The build faulted.
IN_PROGRESS : The build is still in progress.
STOPPED : The build stopped.
SUCCEEDED : The build succeeded.
TIMED_OUT : The build timed out.
116
117
118
119
|
# File 'lib/cody/tailer.rb', line 116
def complete_failed?(build)
return if ENV["CODY_TEST"]
build.build_complete && build.build_status != "SUCCEEDED"
end
|
#display_failed_phases(build) ⇒ Object
48
49
50
51
52
53
54
55
56
57
58
|
# File 'lib/cody/tailer.rb', line 48
def display_failed_phases(build)
failed_phases = build.phases.select do |phase|
phase.phase_status != "SUCCEEDED" && phase.phase_status.to_s != ""
end
return if failed_phases.empty?
puts "Failed Phases:"
failed_phases.each do |phase|
puts "#{phase.phase_type}: #{phase.phase_status.color(:red)}"
end
end
|
#display_phase(details) ⇒ Object
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
|
# File 'lib/cody/tailer.rb', line 141
def display_phase(details)
already_shown = @shown_phases.detect do |p|
p[:phase_type] == details[:phase_type] &&
p[:phase_status] == details[:phase_status] &&
p[:start_time] == details[:start_time] &&
p[:duration_in_seconds] == details[:duration_in_seconds]
end
return if already_shown
status = details[:phase_status].to_s status = status == "SUCCEEDED" ? status.color(:green) : status.color(:red)
say [
"Phase:".color(:green), details[:phase_type],
"Status:".color(:purple), status,
"Duration:".color(:purple), details[:duration_in_seconds],
].join(" ")
end
|
#final_message(build) ⇒ Object
40
41
42
43
44
45
46
|
# File 'lib/cody/tailer.rb', line 40
def final_message(build)
status = build.build_status.to_s status = status != "SUCCEEDED" ? status.color(:red) : status.color(:green)
puts "Final build status: #{status}"
display_failed_phases(build) if status != "SUCCEEDED"
puts "The build took #{build_time(build)} to complete."
end
|
#find_build ⇒ Object
60
61
62
63
|
# File 'lib/cody/tailer.rb', line 60
def find_build
resp = codebuild.batch_get_builds(ids: [@build_id])
resp.builds.first
end
|
#logs_command? ⇒ Boolean
103
104
105
|
# File 'lib/cody/tailer.rb', line 103
def logs_command?
ARGV.join(" ").include?("logs")
end
|
#output ⇒ Object
164
165
166
|
# File 'lib/cody/tailer.rb', line 164
def output
@output.join("\n") + "\n"
end
|
#pretty_time(total_seconds) ⇒ Object
181
182
183
184
185
186
187
188
189
|
# File 'lib/cody/tailer.rb', line 181
def pretty_time(total_seconds)
minutes = (total_seconds / 60) % 60
seconds = total_seconds % 60
if total_seconds < 60
"#{seconds.to_i}s"
else
"#{minutes.to_i}m #{seconds.to_i}s"
end
end
|
#print_phases(build) ⇒ Object
128
129
130
131
132
133
134
135
136
137
138
139
|
# File 'lib/cody/tailer.rb', line 128
def print_phases(build)
build.phases.each do |phase|
details = {
phase_type: phase.phase_type,
phase_status: phase.phase_status,
start_time: phase.start_time,
duration_in_seconds: phase.duration_in_seconds,
}
display_phase(details)
@shown_phases << details
end
end
|
#run ⇒ Object
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
|
# File 'lib/cody/tailer.rb', line 16
def run
puts "Showing logs for build #{@build_id}"
complete = false
until complete do
build = find_build
unless build
puts "ERROR: Build id not found: #{@build_id}".color(:red)
return
end
print_phases(build)
set_log_group_name(build)
complete = build.build_complete
next if ENV["CODY_TEST"]
start_cloudwatch_tail
sleep 5
end
stop_cloudwatch_tail(build)
final_message(build)
end
|
#say(text) ⇒ Object
160
161
162
|
# File 'lib/cody/tailer.rb', line 160
def say(text)
ENV["CODY_TEST"] ? @output << text : puts(text)
end
|
#set_log_group_name(build) ⇒ Object
Setting enables start_cloudwatch_tail
122
123
124
125
126
|
# File 'lib/cody/tailer.rb', line 122
def set_log_group_name(build)
logs = build.logs
@log_group_name = logs.group_name if logs.group_name
@log_stream_name = logs.stream_name if logs.stream_name
end
|
#set_trap ⇒ Object
168
169
170
171
172
173
|
# File 'lib/cody/tailer.rb', line 168
def set_trap
Signal.trap("INT") {
puts "\nCtrl-C detected. Exiting..."
exit }
end
|
#start_cloudwatch_tail ⇒ Object
65
66
67
68
69
70
71
72
73
|
# File 'lib/cody/tailer.rb', line 65
def start_cloudwatch_tail
return if @cloudwatch_tail_started
return unless @log_group_name && @log_stream_name
@thread = Thread.new do
cloudwatch_tail
end
@cloudwatch_tail_started = true
end
|
#stop_cloudwatch_tail(build) ⇒ Object
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
# File 'lib/cody/tailer.rb', line 87
def stop_cloudwatch_tail(build)
return if ENV["CODY_TEST"]
sleep 10 if complete_failed?(build) and !logs_command?
AwsLogs::Tail.stop_follow!
@thread.join if @thread
end
|