Failing a build based on review

If you would like to mark a build as failed based on the findings in the review, you can define custom failure conditions in your configuration file:

We use a simple DSL for defining failure conditions, let’s take a look at a few examples:

# .scrutinizer.yml
    - 'elements.rating(<= D).exists'               # No classes/methods with a rating of D or worse
    - 'elements.rating(<= D).new.exists'           # No new classes/methods with a rating of D or worse
                                                   # allowed (useful for legacy code)

    - 'patches.label("Doc Comments").exists'       # No doc comments patches allowed
    - 'patches.label("Spacing").new.count > 1'     # More than 1 new spacing patch

    - 'issues.label("coding-style").exists'        # No coding style issues allowed
    - 'issues.label("coding-style").new.exists'    # No new coding style issues allowed

    - 'issues.label("coding-style").new.count > 5' # More than 5 new coding style issues.
    - 'issues.severity(>= MAJOR).new.exists'       # New issues of major or higher severity

    - 'project.metric("scrutinizer.quality", < 6)' # Code Quality Rating drops below 6
    - 'project.metric("scrutinizer.test_coverage", < 0.60)' # Code Coverage drops below 60%

    # Code Coverage decreased from previous inspection
    - 'project.metric_change("scrutinizer.test_coverage", < 0)'

    # Code Coverage decreased from previous inspection by more than 10%
    - 'project.metric_change("scrutinizer.test_coverage", < -0.10)'

If one of your failure conditions is satisfied, Scrutinizer will set the build status to failed.


Condition Scopes

The condition scope is the first part of each condition. In the above examples, we saw the scopes elements and issues; here is a full reference of all available scopes:

elements:All code elements including f.e. classes, functions, methods, etc.
classes:All classes.
operations:All functions and methods.
issues:All issues
project:Your project.


Filters are used to narrow down the initial scope further. In the example above, we already introduced some filters like rating, label or new. Some filters like rating are not available for all scopes; for example, this filter does not make sense on the issues scope.

Filters for issues

These filters can only applied when using the issues scope.

new:Only new issues.
label:label("the-label-slug-here") filters out all issues which do not have this label (available labels).
severity:severity(>= SEVERITY) filters out all issues which do not match the severity. Severities: CRITICAL, MAJOR, MINOR, INFO

Filters for other scopes

These filters can be applied when using all scopes except issues.

new:Only new elements.
rating:rating(<= RATING) filters out all elements which do not match the rating. Ratings: A, B, C, D, F
metric:metric("metric-key", <= 5) filters out all elements whose metrics do match the comparison. The following metrics can be used: scrutinizer.test_coverage, scrutinizer.quality
metric_change:metric_change("metric-key", < 0) filters based on how a metric changed between two inspections (new_value - old_value). If the change is < 0 the value decreased, if > 0 the value increased.


The last part of the condition is an assertion. Typically you want to use exists here to check whether one item matches the filters which you have set-up.

The other use-case is to use count and compare it against a fixed number, e.g. issues.count > 5 (more than 5 issues).