Skip to content

Commit

Permalink
feat(buildPluginWithGradle) Add quality checks (jenkins-infra#652)
Browse files Browse the repository at this point in the history
  • Loading branch information
alextu authored and smerle33 committed Jan 16, 2024
1 parent d04f8c0 commit a94c6b8
Show file tree
Hide file tree
Showing 4 changed files with 132 additions and 4 deletions.
6 changes: 5 additions & 1 deletion README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,11 @@ buildPluginWithGradle(/*...*/, configurations: [

* `tests`: (default: `null`) - a map of parameters to run tests during the build
** `skip` - If `true`, skip all the tests.
* `jacoco`: (default: `null`) - a map of parameters to change the default configuration of the `recordCoverage` step of the https://github.com/jenkinsci/code-coverage-api-plugin[Code Coverage Plugin]. This step is called after a plugin build to record the code coverage results of JaCoCo. See https://www.jenkins.io/doc/pipeline/steps/code-coverage-api/#recordcoverage-record-code-coverage-results[recordCoverage step documentation] for a list of available configuration parameters.
* `spotbugs`, `checkstyle`: (default: `null`) - a map of parameters to archive SpotBugs or CheckStyle warnings, respectively.
These values can replace or amend the default configuration for the `recordIssues` step of the https://github.com/jenkinsci/warnings-ng-plugin[Warnings NG Plugin].
See https://github.com/jenkinsci/warnings-ng-plugin/blob/master/doc/Documentation.md#configuration[Warnings NG Plugin documentation]
for a list of available configuration parameters.
* `timeout`: (default: `60`) - the number of minutes for build timeout, cannot be bigger than 180, i.e. 3 hours.

==== Limitations
Expand All @@ -126,7 +131,6 @@ Not all features of `buildPlugin()` for Maven are supported in the gradle flow.
Examples of not supported features:

* Deployment of incremental versions (link:https://github.com/jenkinsci/jep/tree/master/jep/305[JEP-305])
* Publishing of static analysis and coverage reports (Checkstyle, SpotBugs, JaCoCo)
* Configuring `jenkinsVersion` for the build flow (as standalone arguments or as `configurations`)
* Usage of link:https://azure.microsoft.com/en-us/services/container-instances/[Azure Container Instances] as agents (only Maven agents are configured)

Expand Down
72 changes: 72 additions & 0 deletions test/groovy/BuildPluginWithGradleStepTests.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -80,4 +80,76 @@ class BuildPluginWithGradleStepTests extends BaseTest {
assertTrue(assertMethodCallContainsPattern('error', 'There were test failures'))
assertJobStatusFailure()
}

@Test
void test_buildPluginWithGradle_with_warnings_ng() throws Exception {
def script = loadScript(scriptName)
script.call()
printCallStack()

assertTrue(assertMethodCall('java'))
assertTrue(assertMethodCall('javaDoc'))
assertTrue(assertMethodCallContainsPattern('recordIssues', '{enabledForFailure=true, tools=[java, javadoc], filters=[true], sourceCodeEncoding=UTF-8, skipBlames=true, trendChartType=TOOLS_ONLY}'))

assertTrue(assertMethodCall('spotBugs'))
assertTrue(assertMethodCallContainsPattern('recordIssues', '{tool=spotbugs, sourceCodeEncoding=UTF-8, skipBlames=true, trendChartType=TOOLS_ONLY, qualityGates=[{threshold=1, type=NEW, unstable=true}]}'))

assertTrue(assertMethodCall('checkStyle'))
assertTrue(assertMethodCallContainsPattern('recordIssues', '{tool=checkstyle, sourceCodeEncoding=UTF-8, skipBlames=true, trendChartType=TOOLS_ONLY, qualityGates=[{threshold=1, type=TOTAL, unstable=true}]}'))

assertTrue(assertMethodCallContainsPattern('taskScanner', '{includePattern=**/*.java, excludePattern=**/build/**, highTags=FIXME, normalTags=TODO}'))
assertTrue(assertMethodCallContainsPattern('recordIssues', '{enabledForFailure=true, tool=tasks, sourceCodeEncoding=UTF-8, skipBlames=true, trendChartType=NONE}'))
}

@Test
void test_buildPluginWithGradle_with_warnings_ng_and_thresholds() throws Exception {
def script = loadScript(scriptName)
script.call(spotbugs: [
qualityGates : [
[threshold: 3, type: 'TOTAL', unstable: true],
[threshold: 4, type: 'NEW', unstable: true],
],
sourceCodeEncoding: 'UTF-16'])
printCallStack()

assertTrue(assertMethodCallContainsPattern('recordIssues', '{tool=spotbugs, sourceCodeEncoding=UTF-16, skipBlames=true, trendChartType=TOOLS_ONLY, qualityGates=[{threshold=3, type=TOTAL, unstable=true}, {threshold=4, type=NEW, unstable=true}]}'))
}

@Test
void test_buildPluginWithGradle_with_warnings_ng_and_checkstyle() throws Exception {
def script = loadScript(scriptName)
script.call(checkstyle: [
qualityGates: [
[threshold: 3, type: 'TOTAL', unstable: true],
[threshold: 4, type: 'NEW', unstable: true],
],
filters : '[includeFile(\'MyFile.*.java\'), excludeCategory(\'WHITESPACE\')]'])
printCallStack()

assertTrue(assertMethodCallContainsPattern('recordIssues', '{tool=checkstyle, sourceCodeEncoding=UTF-8, skipBlames=true, trendChartType=TOOLS_ONLY, qualityGates=[{threshold=3, type=TOTAL, unstable=true}, {threshold=4, type=NEW, unstable=true}], filters=[includeFile(\'MyFile.*.java\'), excludeCategory(\'WHITESPACE\')]}'))
}

@Test
void test_buildPluginWithGradle_with_record_coverage_defaults() throws Exception {
def script = loadScript(scriptName)
script.call()
printCallStack()

assertTrue(assertMethodCall('recordCoverage'))
assertDefaultRecordCoverageWithJaCoCo()
}

private assertDefaultRecordCoverageWithJaCoCo() {
assertTrue(assertMethodCallContainsPattern('recordCoverage', '{tools=[{parser=JACOCO, pattern=**/build/reports/jacoco/**/*.xml}], sourceCodeRetention=MODIFIED}'))
}

@Test
void test_buildPluginWithGradle_with_record_coverage_custom() throws Exception {
def script = loadScript(scriptName)
script.call(jacoco: [sourceCodeRetention: 'EVERY_BUILD', sourceDirectories: [[path: 'plugin/src/main/java']]])
printCallStack()

assertTrue(assertMethodCall('recordCoverage'))
assertTrue(assertMethodCallContainsPattern('recordCoverage', '{tools=[{parser=JACOCO, pattern=**/build/reports/jacoco/**/*.xml}], sourceCodeRetention=EVERY_BUILD, sourceDirectories=[{path=plugin/src/main/java}]}'))
}
}
56 changes: 54 additions & 2 deletions vars/buildPluginWithGradle.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -65,11 +65,63 @@ def call(Map params = [:]) {
}

stage("Archive (${stageIdentifier})") {
//TODO(oleg-nenashev): Add static analysis results publishing like in buildPlugin() for Maven

if (failFast && currentBuild.result == 'UNSTABLE') {
error 'There were test failures; halting early'
}
echo "Recording static analysis results on '${stageIdentifier}'"

recordIssues(
enabledForFailure: true,
tools: [java(), javaDoc()],
filters: [excludeFile('.*Assert.java')],
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY'
)

// Default configuration for SpotBugs can be overwritten using a `spotbugs`, `checkstyle', etc. parameter (map).
// Configuration see: https://github.com/jenkinsci/warnings-ng-plugin/blob/master/doc/Documentation.md#configuration
Map spotbugsArguments = [tool: spotBugs(pattern: '**/build/reports/spotbugs/*.xml'),
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY',
qualityGates: [[threshold: 1, type: 'NEW', unstable: true]]]
if (params?.spotbugs) {
spotbugsArguments.putAll(params.spotbugs as Map)
}
recordIssues spotbugsArguments

Map checkstyleArguments = [tool: checkStyle(pattern: '**/build/reports/checkstyle/*.xml'),
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'TOOLS_ONLY',
qualityGates: [[threshold: 1, type: 'TOTAL', unstable: true]]]
if (params?.checkstyle) {
checkstyleArguments.putAll(params.checkstyle as Map)
}
recordIssues checkstyleArguments

Map jacocoArguments = [tools: [[parser: 'JACOCO', pattern: '**/build/reports/jacoco/**/*.xml']], sourceCodeRetention: 'MODIFIED']
if (params?.jacoco) {
jacocoArguments.putAll(params.jacoco as Map)
}
recordCoverage jacocoArguments


recordIssues(
enabledForFailure: true, tool: taskScanner(
includePattern:'**/*.java',
excludePattern:'**/build/**',
highTags:'FIXME',
normalTags:'TODO'),
sourceCodeEncoding: 'UTF-8',
skipBlames: true,
trendChartType: 'NONE'
)
if (failFast && currentBuild.result == 'UNSTABLE') {
error 'Static analysis quality gates not passed; halting early'
}

if (doArchiveArtifacts) {
archiveArtifacts artifacts: '**/build/libs/*.hpi,**/build/libs/*.jpi', fingerprint: true, allowEmptyArchive: true
}
Expand Down
2 changes: 1 addition & 1 deletion vars/buildPluginWithGradle.txt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
<p>
The implementation follows the standard build/test/archive pattern.
Note that the Gradle flow for Jenkins plugins offers less functionality than the Maven flow,
some key features are not supported: Incrementals - JEP-305, standard static analysis flows, etc.
some key features are not supported: Incrementals - JEP-305, etc.
The current version also does not allow configuring the <code>jenkinsVersion</code>.
</p>

Expand Down

0 comments on commit a94c6b8

Please sign in to comment.