Search code examples
androidgradlespotbugs

Adding SpotBugs to my project


I've been working on adding SpotBugs to the android project I'm currently working on. I managed to get it working but I'm not overly thrilled of the way it's set up. For now the configuration resides inside my app/build.gradle file, which makes the file less manageable.

I was wondering if there's an expert on SpotBugs/Gradle who knows a way to pull the configuration out into a separate file.

Here's my app/build.gradle (boilerplate removed):

buildscript {
    repositories {
        ...
    }

    dependencies {
        classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.2'
        classpath 'io.fabric.tools:gradle:1.25.4'
        classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
    }
}

plugins {
    id 'com.gladed.androidgitversion' version '0.4.3'
    id "com.github.spotbugs" version "1.6.2"
}

...
apply plugin: 'com.github.spotbugs'
apply from: '../config/quality/quality.gradle'
apply from: '../app/jacoco.gradle'
apply from: '../app/ktlint.gradle'
apply from: '../app/androidgit.gradle'

...

spotbugs {
    toolVersion = '3.1.3'
    ignoreFailures = false

    effort = "min"
    // This selects what level of bugs to report: low means low priority issues will be reported
    // (in addition to medium+high), which corresponds to warning about everything.
    // TODO: boost this to low once low priority issues are fixed.
    reportLevel = "medium"

    excludeFilter = new File("$project.rootDir/config/quality/spotbugs/android-exclude-filter.xml")
}

task spotbugs(type: com.github.spotbugs.SpotBugsTask, dependsOn: 'assemble', group: 'verification') {
    classes = files("$projectDir.absolutePath/build/intermediates/app_classes/debug")

    source = fileTree('src/main/java')


    // Only one report format is supported. Html is easier to read, so let's use that
    // (xml is the one that's enabled by default).
    reports {
        xml.enabled = false
        html.enabled = true
    }

    classpath = files()
}

EDIT

Whenever I'm trying to separate SpotBugs from my app/build.gradle I run into the following error:

Could not get unknown property 'SpotBugsTask' for project ':app' of type org.gradle.api.Project.

Here's my gradle file:

apply plugin: 'com.github.spotbugs'

dependencies {
    checkstyle 'com.puppycrawl.tools:checkstyle:8.11'
    spotbugs "gradle.plugin.com.github.spotbugs:spotbugs-gradle-plugin:1.6.2"
//    spotbugs configurations.spotbugsPlugins.dependencies
//    spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.8.0'
}

def qualityConfigDir = "$project.rootDir/config/quality";
def reportsDir = "$project.buildDir/reports"

check.dependsOn 'checkstyle'

task checkstyle(type: Checkstyle, group: 'Verification', description: 'Runs code style checks') {
    configFile file("$qualityConfigDir/checkstyle/checkstyle-config.xml")
    source 'src/main/java'
    include '**/*.java'
    exclude '**/model/**'
    exclude '**/AppLogger.java'
    reports {
        xml.enabled = true
        xml {
            destination file("$reportsDir/checkstyle/checkstyle.xml")
        }
    }

    classpath = files()
}

spotbugs {
    toolVersion = '3.1.3'
    ignoreFailures = false

    effort = "min"
    // This selects what level of bugs to report: low means low priority issues will be reported
    // (in addition to medium+high), which corresponds to warning about everything.
    // TODO: boost this to low once low priority issues are fixed.
    reportLevel = "medium"

    excludeFilter = new File("$project.rootDir/config/quality/spotbugs/android-exclude-filter.xml")
}

task spotbugs(type: SpotBugsTask, dependsOn: 'assemble', group: 'verification') {
    classes = files("$projectDir.absolutePath/build/intermediates/app_classes/debug")

    source = fileTree('src/main/java')


    // Only one report format is supported. Html is easier to read, so let's use that
    // (xml is the one that's enabled by default).
    reports {
        xml.enabled = false
        html.enabled = true
    }

    classpath = files()
}

Solution

  • Finally managed to find a solution.

    I had to add the following to the section where I apply all the plugins in my app/build.gradle file:

    project.extensions.extraProperties.set('SpotBugsTask', com.github.spotbugs.SpotBugsTask)

    So it ended up looking like this:

    buildscript {
        repositories {
            mavenCentral()
            jcenter()
            maven { url 'https://maven.fabric.io/public' }
        }
    
        dependencies {
            classpath 'com.stanfy.spoon:spoon-gradle-plugin:1.2.2'
            classpath 'io.fabric.tools:gradle:1.25.4'
            classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:$dokka_version"
        }
    }
    
    plugins {
        id 'com.gladed.androidgitversion' version '0.4.3'
        id "com.github.spotbugs" version "1.6.2"
    }
    
    // Workaround to be able to access SpotBugsTask from external gradle script.
    // More info: https://discuss.gradle.org/t/buildscript-dependencies-in-external-script/23243
    project.extensions.extraProperties.set('SpotBugsTask', com.github.spotbugs.SpotBugsTask)
    apply plugin: 'com.android.application'
    apply plugin: 'kotlin-android'
    apply plugin: 'kotlin-android-extensions'
    apply plugin: 'kotlin-kapt'
    apply plugin: 'org.jetbrains.dokka-android'
    apply plugin: 'io.fabric'
    apply plugin: 'spoon'
    apply from: '../app/checkstyle.gradle'
    apply from: '../app/jacoco.gradle'
    apply from: '../app/ktlint.gradle'
    apply from: '../app/androidgit.gradle'
    apply from: '../app/spotbugs.gradle'
    
    android {
    ...
    

    My spotbugs.gradle file:

    dependencies {
        spotbugs configurations.spotbugsPlugins.dependencies
        spotbugsPlugins 'com.h3xstream.findsecbugs:findsecbugs-plugin:1.8.0'
    }
    
    def qualityConfigDir = "$project.rootDir/config/quality"
    def reportsDir = "$project.buildDir/reports"
    
    spotbugs {
        toolVersion = "$spotbugs_version"
        ignoreFailures = false
    
        effort = "min"
        // This selects what level of bugs to report: low means low priority issues will be reported
        // (in addition to medium+high), which corresponds to warning about everything.
        // TODO: boost this to low once low priority issues are fixed.
        reportLevel = "medium"
    
        excludeFilter = new File("$qualityConfigDir/config/quality/spotbugs/android-exclude-filter.xml")
    }
    
    tasks.register("spotbugs", SpotBugsTask) {
        dependsOn 'assemble'
        group = "verification"
        classes = files("$projectDir.absolutePath/build/intermediates/app_classes/debug")
    
        source = fileTree('src/main/java')
    
    
        // Only one report format is supported. Html is easier to read, so let's use that
        // (xml is the one that's enabled by default).
        reports {
            xml.enabled = true
            xml {
                destination file("$reportsDir/spotbugs/spotbugs.xml")
            }
            html.enabled = true
        }
    
        classpath = files()
    }