Class: Dash::Build::ProgressParser
- Inherits:
-
Object
- Object
- Dash::Build::ProgressParser
- Defined in:
- lib/dash/build/progress_parser.rb
Overview
Reads docker buildx build --progress=plain as it streams past and turns it into a
per-step report. It is an SSHKit interaction handler, so it sees the same bytes SSHKit
is already printing — no second process, no docker buildx history, no extra command.
The stream is line-oriented but arrives in chunks (the SSH backend splits on packet
boundaries, not newlines), so data is buffered and only whole lines are parsed. Every
line belongs to a vertex — #12 — and the first line for a vertex names it; the rest
are events on it (DONE, CACHED, ERROR) or its own stdout, which is ignored.
Nothing here may raise into a build. A parse error stops the parsing and is reported once by the caller; the deploy keeps whatever was collected up to that point.
Constant Summary collapse
- VERTEX =
/\A#(?<number>\d+)(?: (?<rest>.*))?\z/- STEP =
[linux/amd64 build 2/3] RUN …— the platform prefix only appears on multi-platform builds, and the stage name only when the Dockerfile named it with AS. %r{\A\[(?:(?<platform>[a-z0-9]+/[a-z0-9][\w./-]*) )?(?:(?<stage>[A-Za-z0-9][\w.-]*) )?(?<ordinal>\d+)/(?<steps_in_stage>\d+)\] (?<instruction>.+)\z}- INTERNAL =
/\A\[(?:\S+ )?internal\] (?<what>.+)\z/- DONE =
/\ADONE (?<seconds>\d+(?:\.\d+)?)s\z/- ERROR =
/\AERROR: (?<message>.+)\z/- TRANSFERRING_CONTEXT =
/\Atransferring context: (?<size>[\d.]+)(?<unit>[a-zA-Z]+)(?: (?<seconds>\d+(?:\.\d+)?)s)? done\z/- PUSHING =
/\Apushing .*?(?<seconds>\d+(?:\.\d+)?)s done\z/- BYTE_UNITS =
{ "b" => 1, "kb" => 1_000, "mb" => 1_000_000, "gb" => 1_000_000_000, "tb" => 1_000_000_000_000 }.freeze
Instance Attribute Summary collapse
-
#error ⇒ Object
readonly
Returns the value of attribute error.
Instance Method Summary collapse
-
#finish ⇒ Object
The last line of a build has no trailing newline when the command dies mid-write.
-
#initialize ⇒ ProgressParser
constructor
A new instance of ProgressParser.
-
#on_data(_command, _stream_name, data, _channel) ⇒ Object
SSHKit's interaction-handler contract.
- #result ⇒ Object
Constructor Details
#initialize ⇒ ProgressParser
Returns a new instance of ProgressParser.
28 29 30 31 32 33 34 |
# File 'lib/dash/build/progress_parser.rb', line 28 def initialize @steps = {} @order = [] @buffer = +"" @push_seconds = 0.0 @mutex = Mutex.new end |
Instance Attribute Details
#error ⇒ Object (readonly)
Returns the value of attribute error.
26 27 28 |
# File 'lib/dash/build/progress_parser.rb', line 26 def error @error end |
Instance Method Details
#finish ⇒ Object
The last line of a build has no trailing newline when the command dies mid-write.
51 52 53 54 55 56 57 58 59 60 |
# File 'lib/dash/build/progress_parser.rb', line 51 def finish @mutex.synchronize do next if @error parse_line @buffer.chomp unless @buffer.empty? @buffer = +"" rescue StandardError => e @error = e end end |
#on_data(_command, _stream_name, data, _channel) ⇒ Object
SSHKit's interaction-handler contract.
37 38 39 40 41 42 43 44 45 46 47 48 |
# File 'lib/dash/build/progress_parser.rb', line 37 def on_data(_command, _stream_name, data, _channel) @mutex.synchronize do next if @error @buffer << data.to_s while (newline = @buffer.index("\n")) parse_line @buffer.slice!(0..newline).chomp end rescue StandardError => e @error = e end end |
#result ⇒ Object
62 63 64 65 66 |
# File 'lib/dash/build/progress_parser.rb', line 62 def result @mutex.synchronize do Dash::Build::Report.new(steps: @order.map { |number| @steps[number] }, push_seconds: @push_seconds) end end |