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 (--failure-level=LEVEL)
- if this level is reached by a log message, it triggers a non-zero exit code
  • Loading branch information
mojavelinux committed Apr 20, 2018
1 parent 31e0159 commit 95f0bd9
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 9 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ Enhancements::
* add NullLogger to prevent messages from being logged (#44, PR #2660)
* log message containing source location / cursor as an object; provides more context (#44, PR #2660)
* add :logger option to API to set logger instance (#44, PR #2660)
* add --failure-level=LEVEL option to CLI to force non-zero exit code if specified logging level is reached (#2003, PR #2674)
* resolve nested includes in remote documents relative to URI (#2506, PR #2511)
* support name!@, !name@, name!=@, and !name=@ syntax to soft unset attribute from API or CLI (#642, PR #2649)
* allow modifier to be placed at end of name to soft set an attribute (e.g., icons@=font) (#642, PR #2649)
Expand Down
4 changes: 2 additions & 2 deletions lib/asciidoctor/cli/invoker.rb
Original file line number Diff line number Diff line change
Expand Up @@ -72,8 +72,7 @@ def invoke!
$VERBOSE = false
when 2
$VERBOSE = true
old_logger_level = LoggerManager.logger.level
LoggerManager.logger.level = ::Logger::Severity::DEBUG
old_logger_level, LoggerManager.logger.level = LoggerManager.logger.level, ::Logger::Severity::DEBUG
end
else
opts[key] = val unless val.nil?
Expand Down Expand Up @@ -131,6 +130,7 @@ def invoke!
end
end
end
@code = 1 if ((logger = LoggerManager.logger).respond_to? :max_severity) && logger.max_severity && logger.max_severity >= opts[:failure_level]
rescue ::Exception => e
if ::SignalException === e
@code = e.signo
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 minimum logging 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: 9 additions & 3 deletions man/asciidoctor.1
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,12 @@
.\" Title: asciidoctor
.\" Author: Dan Allen, Sarah White, Ryan Waldron
.\" Generator: Asciidoctor 1.5.7.dev
.\" Date: 2018-04-07
.\" Date: 2018-04-20
.\" Manual: Asciidoctor Manual
.\" Source: Asciidoctor 1.5.6.2
.\" Language: English
.\"
.TH "ASCIIDOCTOR" "1" "2018-04-07" "Asciidoctor 1.5.6.2" "Asciidoctor Manual"
.TH "ASCIIDOCTOR" "1" "2018-04-20" "Asciidoctor 1.5.6.2" "Asciidoctor Manual"
.ie \n(.g .ds Aq \(aq
.el .ds Aq '
.ss \n[.ss] 0
Expand Down Expand Up @@ -169,6 +169,12 @@ Matching templates found in subsequent directories override ones previously disc
.RE
.SS "Processing Information"
.sp
\fB\-\-failure\-level\fP=\fILEVEL\fP
.RS 4
The minimum logging level that triggers a non\-zero exit code (failure).
If this option is not set (default: FATAL), the program exits with a status code zero even if warnings or errors have been logged.
.RE
.sp
\fB\-q, \-\-quiet\fP
.RS 4
Silence warnings.
Expand Down Expand Up @@ -254,4 +260,4 @@ Dan Allen
.sp
Sarah White
.sp
Ryan Waldron
Ryan Waldron
4 changes: 4 additions & 0 deletions man/asciidoctor.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,10 @@ Matching templates found in subsequent directories override ones previously disc

=== Processing Information

*--failure-level*=_LEVEL_::
The minimum logging level that triggers a non-zero exit code (failure).
If this option is not set (default: FATAL), the program exits with a status code zero even if warnings or errors have been logged.

*-q, --quiet*::
Silence warnings.

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 95f0bd9

Please sign in to comment.