Class: Dash::Dockerfile::Parser

Inherits:
Object
  • Object
show all
Defined in:
lib/dash/dockerfile/parser.rb

Overview

Turns Dockerfile text into instructions and stages.

Line-oriented, because that is how BuildKit reads it: a physical line is joined to the next while it ends in the escape character, comment lines in between are dropped, and a heredoc redirection pulls the following lines in verbatim until its delimiter.

It is deliberately forgiving. Advice is a courtesy printed next to a deploy, so a file this parser cannot make sense of must produce fewer findings, never an exception — the authority on whether a Dockerfile builds is BuildKit, not this.

Constant Summary collapse

DIRECTIVE =
/\A#\s*(?<name>syntax|escape)\s*=\s*(?<value>\S+)\s*\z/i
COMMENT =
/\A\s*#/
BLANK =
/\A\s*\z/
INSTRUCTION =
/\A\s*(?<name>[A-Za-z]+)(?:\s+(?<rest>.*))?\z/m
FLAG =
/\A--(?<key>[a-zA-Z][\w-]*)=(?<value>(?:"[^"]*"|'[^']*'|\S)*)\s*/
HEREDOC =

<<EOF, <<-EOF, <<"EOF", <<'EOF' — the quoted forms only change how BuildKit expands the body, not where it ends.

/<<-?\s*(?<quote>["']?)(?<delimiter>[A-Za-z_]\w*)\k<quote>/
STAGE_NAME =
/\A(?<base>\S+)(?:\s+AS\s+(?<name>\S+))?\z/i

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(text) ⇒ Parser

Returns a new instance of Parser.



25
26
27
# File 'lib/dash/dockerfile/parser.rb', line 25

def initialize(text)
  @lines = text.to_s.lines.map(&:chomp)
end

Class Method Details

.parse(text) ⇒ Object



21
22
23
# File 'lib/dash/dockerfile/parser.rb', line 21

def self.parse(text)
  new(text).parse
end

Instance Method Details

#parse ⇒ Object



29
30
31
32
33
34
35
36
37
# File 'lib/dash/dockerfile/parser.rb', line 29

def parse
  directives = parse_directives
  escape = directives["escape"] == "`" ? "`" : "\\"

  instructions = parse_instructions(escape)
  stages = build_stages(instructions)

  Dash::Dockerfile::Document.new(instructions: instructions, stages: stages, directives: directives)
end