Class: LocalCI::Output

Inherits:
Object
  • Object
show all
Defined in:
lib/local_ci/output.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(flow:) ⇒ Output

Returns a new instance of Output.



5
6
7
8
9
10
# File 'lib/local_ci/output.rb', line 5

def initialize(flow:)
  @flow = flow
  @first_paint = true
  @start = 0
  @mutex = Mutex.new
end

Instance Attribute Details

#jobObject (readonly)

Returns the value of attribute job.



3
4
5
# File 'lib/local_ci/output.rb', line 3

def job
  @job
end

Instance Method Details

#color(message) ⇒ Object



120
121
122
123
124
125
126
127
128
# File 'lib/local_ci/output.rb', line 120

def color(message)
  if passed?
    pastel.green(message)
  elsif failed?
    pastel.red(message)
  else
    pastel.blue(message)
  end
end

#cursorObject



31
32
33
# File 'lib/local_ci/output.rb', line 31

def cursor
  TTY::Cursor
end

#done?Boolean

Returns:

  • (Boolean)


63
64
65
# File 'lib/local_ci/output.rb', line 63

def done?
  @flow.jobs.all?(&:done?)
end

#draw(final: false) ⇒ Object



102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
# File 'lib/local_ci/output.rb', line 102

def draw(final: false)
  print cursor.hide
  if @first_paint
    @start = Time.now
    @first_paint = false
  else
    print cursor.clear_line + cursor.up(@flow.jobs.size + 2)
  end

  puts heading_line
  @flow.jobs.each { |job| puts job_line job }
  puts footer_line

  puts if final
ensure
  print cursor.show
end

#durationObject



162
163
164
# File 'lib/local_ci/output.rb', line 162

def duration
  LocalCI::Helper.human_duration(Time.now - @start)
end

#failed?Boolean

Returns:

  • (Boolean)


59
60
61
# File 'lib/local_ci/output.rb', line 59

def failed?
  @flow.failures.any?
end

#failuresObject



88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/local_ci/output.rb', line 88

def failures
  return unless tty?

  @mutex.synchronize {
    @flow.failures.each do |failure|
      puts "        \#{pastel.bold.red(\"FAIL:\")} \#{failure.job}\n        \#{failure.message}\n\n      STR\n    end\n  }\nend\n"

#finishObject



22
23
24
25
# File 'lib/local_ci/output.rb', line 22

def finish
  @thread_should_exit = true
  @thread.join
end


166
167
168
169
# File 'lib/local_ci/output.rb', line 166

def footer_line
  start_length = screen.width - 4 - duration.size - 1
  color "#{"-" * start_length}(#{pastel.bold duration})---"
end

#heading_lineObject



130
131
132
133
134
135
136
137
# File 'lib/local_ci/output.rb', line 130

def heading_line
  heading = @flow.heading.dup
  heading = "#{heading[...(screen.width - 11)]}…" if heading.length > (screen.width - 10)

  tail_length = screen.width - 5 - heading.length - 2

  color "===| #{pastel.bold heading} |#{"=" * tail_length}"
end

#job_line(job) ⇒ Object



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/local_ci/output.rb', line 139

def job_line(job)
  name = job.name.dup

  name = "#{name[...(screen.width - 4)]}…" if name.length > (screen.width - 3)

  result = cursor.clear_line
  if job.waiting?
    result << "[ ] "
  elsif job.running?
    result << "[-] "
  elsif job.success?
    result << "[#{pastel.green "✓"}] "
  elsif job.failed?
    result << "[#{pastel.red "✗"}] "
  end

  result << name

  result << " (#{pastel.yellow LocalCI::Helper.human_duration(job.duration)})" unless job.waiting?

  result
end

#json_outputObject



171
172
173
174
175
176
177
178
# File 'lib/local_ci/output.rb', line 171

def json_output
  puts({
    flow: @flow.heading,
    job: @job.name,
    duration: @job.duration,
    state: @job.state
  }.to_json)
end

#passed?Boolean

Returns:

  • (Boolean)


55
56
57
# File 'lib/local_ci/output.rb', line 55

def passed?
  @flow.jobs.all?(&:success?)
end

#pastelObject



27
28
29
# File 'lib/local_ci/output.rb', line 27

def pastel
  LocalCI::Helper.pastel
end

#plain_outputObject



180
181
182
183
184
185
186
187
188
189
# File 'lib/local_ci/output.rb', line 180

def plain_output
  result = "=== #{@flow.heading} - #{@job.name} [#{@job.state}] "
  result << if @job.waiting? || @job.running?
    "==="
  else
    "(#{LocalCI::Helper.human_duration(@job.duration)}) ==="
  end

  puts(result)
end

#screenObject



35
36
37
# File 'lib/local_ci/output.rb', line 35

def screen
  TTY::Screen
end

#start_threadObject



12
13
14
15
16
17
18
19
20
# File 'lib/local_ci/output.rb', line 12

def start_thread
  @thread = Thread.new {
    loop do
      @mutex.synchronize { draw(final: @thread_should_exit) }
      break if @thread_should_exit
      sleep 0.1
    end
  }
end

#styleObject



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/local_ci/output.rb', line 43

def style
  result = LocalCI::Helper.ci? ? "plain" : "realtime"
  result = "plain" unless tty?
  result = ENV.fetch("LOCAL_CI_STYLE", result)

  unless ["plain", "json", "realtime"].include? result
    raise ArgumentError, "LOCAL_CI_STYLE must be one of plain, json, or realtime"
  end

  result
end

#tty?Boolean

Returns:

  • (Boolean)


39
40
41
# File 'lib/local_ci/output.rb', line 39

def tty?
  $stdout.isatty
end

#update(job) ⇒ Object



67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/local_ci/output.rb', line 67

def update(job)
  case style
  when "realtime"
    finish and return if done?

    return if @thread&.alive?

    start_thread

  when "json"
    @job = job

    @mutex.synchronize { json_output }

  when "plain"
    @job = job

    @mutex.synchronize { plain_output }
  end
end