Class: Dash::Dockerfile::Hadolint
- Inherits:
-
Object
- Object
- Dash::Dockerfile::Hadolint
- Defined in:
- lib/dash/dockerfile/hadolint.rb
Overview
Optional supplement to the built-in rules: whatever hadolint has to say about the same
file, when the operator already has it installed.
Run as a plain local process rather than through SSHKit, so the command sequence a deploy
prints — and the cost-guard test that pins it — is unchanged. --no-fail keeps its exit
status out of the deploy, and anything that goes wrong becomes one informational finding
rather than an exception.
Constant Summary collapse
- EXECUTABLE =
"hadolint".freeze
- SEVERITIES =
hadolint's own levels.
erroris the only one worth a warning next to a deploy; the rest are style notes that should not compete with a measured finding. { "error" => :warn }.freeze
Class Method Summary collapse
-
.available? ⇒ Boolean
No shell: PATH is walked directly, so a directory with a space or a semicolon in it cannot turn a lookup into a command.
Instance Method Summary collapse
- #findings ⇒ Object
-
#initialize(path:, file: path) ⇒ Hadolint
constructor
A new instance of Hadolint.
Constructor Details
#initialize(path:, file: path) ⇒ Hadolint
Returns a new instance of Hadolint.
29 30 31 32 |
# File 'lib/dash/dockerfile/hadolint.rb', line 29 def initialize(path:, file: path) @path = path @file = file end |
Class Method Details
.available? ⇒ Boolean
No shell: PATH is walked directly, so a directory with a space or a semicolon in it cannot turn a lookup into a command.
21 22 23 24 25 26 |
# File 'lib/dash/dockerfile/hadolint.rb', line 21 def available? ENV["PATH"].to_s.split(::File::PATH_SEPARATOR).any? do |directory| path = ::File.join(directory, EXECUTABLE) ::File.executable?(path) && !::File.directory?(path) end end |
Instance Method Details
#findings ⇒ Object
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
# File 'lib/dash/dockerfile/hadolint.rb', line 34 def findings return [] unless self.class.available? output, status = Open3.capture2(EXECUTABLE, "--format", "json", "--no-fail", @file) return unavailable("exited #{status.exitstatus}") unless status.success? return [] if output.strip.empty? issues = JSON.parse(output) return unparsable("expected a JSON array, got #{issues.class.name.downcase}") unless issues.is_a?(Array) issues.map { |issue| finding_for(issue) } # Only JSON.parse raises this, so it is the one error that means "it ran fine, dash # could not read what it printed". Anything else that raises in here is dash's own. rescue JSON::ParserError => e unparsable(e..truncate(80)) rescue StandardError => e unavailable(e.) end |