Skip to content

Commit

Permalink
resolves asciidoctor#2003 allow failure level to be specified using C…
Browse files Browse the repository at this point in the history
…LI option

- add option to CLI to specify a failure level
- if this level is reached by a log message, it triggers a non-zero exit code
  • Loading branch information
mojavelinux committed Apr 16, 2018
1 parent 7ab8389 commit df4d6d9
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 8 deletions.
9 changes: 5 additions & 4 deletions lib/asciidoctor/cli/invoker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def invoke!
return unless @options

old_verbose = $VERBOSE
logger = LoggerManager.logger
old_logger = old_logger_level = nil
opts = {}
infiles = []
Expand Down Expand Up @@ -67,13 +68,12 @@ def invoke!
when 0
$VERBOSE = nil
old_logger = LoggerManager.logger
LoggerManager.logger = NullLogger.new
LoggerManager.logger = (logger = NullLogger.new)
when 1
$VERBOSE = false
when 2
$VERBOSE = true
old_logger_level = LoggerManager.logger.level
LoggerManager.logger.level = ::Logger::Severity::DEBUG
old_logger_level, logger.level = logger.level, ::Logger::Severity::DEBUG
end
else
opts[key] = val unless val.nil?
Expand Down Expand Up @@ -131,6 +131,7 @@ def invoke!
end
end
end
@code = 1 if (logger.respond_to? :max_severity) && (max_severity = logger.max_severity) && max_severity >= opts[:failure_level]
rescue ::Exception => e
if ::SignalException === e
@code = e.signo
Expand All @@ -155,7 +156,7 @@ def invoke!
if old_logger
LoggerManager.logger = old_logger
elsif old_logger_level
LoggerManager.logger.level = old_logger_level
logger.level = old_logger_level
end
end

Expand Down
5 changes: 5 additions & 0 deletions lib/asciidoctor/cli/options.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ def initialize(options = {})
self[:base_dir] = options[:base_dir]
self[:source_dir] = options[:source_dir] || nil
self[:destination_dir] = options[:destination_dir] || nil
self[:failure_level] = ::Logger::Severity::FATAL
self[:trace] = false
self[:timings] = false
end
Expand Down Expand Up @@ -119,6 +120,10 @@ def parse!(args)
'may be specified more than once') do |path|
(self[:requires] ||= []).concat(path.split ',')
end
opts.on('--failure-level LEVEL', %w(warning WARNING error ERROR), 'set severity level that triggers a non-zero exit code: [WARN, ERROR] (default: FATAL)') do |level|
level = 'WARN' if (level = level.upcase) == 'WARNING'
self[:failure_level] = ::Logger::Severity.const_get level
end
opts.on('-q', '--quiet', 'suppress warnings (default: false)') do |verbose|
self[:verbose] = 0
end
Expand Down
26 changes: 22 additions & 4 deletions lib/asciidoctor/logging.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,22 @@

module Asciidoctor
class Logger < ::Logger
attr_reader :max_severity

def initialize *args
super
self.progname = 'asciidoctor'
self.formatter = BasicFormatter.new
self.level = WARN
end

def add severity, message = nil, progname = nil
if (severity ||= UNKNOWN) > (@max_severity ||= severity)
@max_severity = severity
end
super
end

class BasicFormatter < Formatter
SEVERITY_LABELS = { 'WARN' => 'WARNING', 'FATAL' => 'FAILED' }

Expand Down Expand Up @@ -37,23 +46,32 @@ def initialize

def add severity, message = nil, progname = nil
message = block_given? ? yield : progname unless message
@messages << { :severity => SEVERITY_LABELS[severity], :message => message }
@messages << { :severity => SEVERITY_LABELS[severity || UNKNOWN], :message => message }
true
end

def clear
@messages.clear
end

def empty?
@messages.empty?
end

def clear
@messages.clear
def max_severity
empty? ? nil : @messages.map {|m| Severity.const_get m[:severity] }.max
end
end

class NullLogger < ::Logger
attr_reader :max_severity

def initialize; end

def add *args
def add severity, message = nil, progname = nil
if (severity ||= UNKNOWN) > (@max_severity ||= severity)
@max_severity = severity
end
true
end
end
Expand Down
12 changes: 12 additions & 0 deletions test/invoker_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -179,6 +179,18 @@ def readlines
assert_equal '', warnings
end

test 'should return non-zero exit code if failure level is reached' do
input = <<-EOS
2. second
3. third
EOS
exit_code, messages = redirect_streams do |_, err|
[invoke_cli(%w(-q --failure-level=WARN -o /dev/null), '-') { input }.code, err.string]
end
assert_equal 1, exit_code
assert messages.empty?
end

test 'should report usage if no input file given' do
redirect_streams do |out, err|
invoke_cli [], nil
Expand Down
27 changes: 27 additions & 0 deletions test/options_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,33 @@
end
end

test 'should set failure level to FATAL by default' do
options = Asciidoctor::Cli::Options.parse! %W(test/fixtures/sample.asciidoc)
assert_equal ::Logger::Severity::FATAL, options[:failure_level]
end

test 'should allow failure level to be set to WARN' do
%w(w warn WARN warning WARNING).each do |val|
options = Asciidoctor::Cli::Options.parse!(%W(--failure-level=#{val} test/fixtures/sample.asciidoc))
assert_equal ::Logger::Severity::WARN, options[:failure_level]
end
end

test 'should allow failure level to be set to ERROR' do
%w(e err ERR error ERROR).each do |val|
options = Asciidoctor::Cli::Options.parse!(%W(--failure-level=#{val} test/fixtures/sample.asciidoc))
assert_equal ::Logger::Severity::ERROR, options[:failure_level]
end
end

test 'should not allow failure level to be set to unknown value' do
exit_code, messages = redirect_streams do |_, err|
[(Asciidoctor::Cli::Options.parse! %W(--failure-level=foobar test/fixtures/sample.asciidoc)), err.string]
end
assert_equal 1, exit_code
assert_includes messages, 'invalid argument: --failure-level=foobar'
end

test 'should set verbose to 2 when -v flag is specified' do
options = Asciidoctor::Cli::Options.parse!(%w(-v test/fixtures/sample.asciidoc))
assert_equal 2, options[:verbose]
Expand Down

0 comments on commit df4d6d9

Please sign in to comment.