mirror of
https://github.com/SAP/jenkins-library.git
synced 2024-12-12 10:55:20 +02:00
Add Maven static code checks
* add static code checks for maven based projects as: * pmd plugin * spotBugs plugin * test modules as unit-tests and integration-tests will be ignored by default. Additional modules to ignore are configurable * for pmd: rulesets and excludes are configurable * for spotBugs: includeFilter and excludeFilter are configurable
This commit is contained in:
parent
84f3e10e3b
commit
de2909e64b
90
cmd/mavenStaticCodeChecks.go
Normal file
90
cmd/mavenStaticCodeChecks.go
Normal file
@ -0,0 +1,90 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/command"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/maven"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
)
|
||||
|
||||
func mavenStaticCodeChecks(config mavenStaticCodeChecksOptions, telemetryData *telemetry.CustomData) {
|
||||
c := command.Command{}
|
||||
c.Stdout(log.Entry().Writer())
|
||||
c.Stderr(log.Entry().Writer())
|
||||
err := runMavenStaticCodeChecks(&config, telemetryData, &c)
|
||||
if err != nil {
|
||||
log.Entry().WithError(err).Fatal("step execution failed")
|
||||
}
|
||||
}
|
||||
|
||||
func runMavenStaticCodeChecks(config *mavenStaticCodeChecksOptions, telemetryData *telemetry.CustomData, command execRunner) error {
|
||||
var defines []string
|
||||
var goals []string
|
||||
|
||||
if !config.SpotBugs && !config.Pmd {
|
||||
log.Entry().Fatal("Neither SpotBugs nor Pmd are configured. At least one of those tools have to be enabled")
|
||||
}
|
||||
|
||||
if testModulesExcludes := maven.GetTestModulesExcludes(); testModulesExcludes != nil {
|
||||
defines = append(defines, testModulesExcludes...)
|
||||
}
|
||||
if config.MavenModulesExcludes != nil {
|
||||
for _, module := range config.MavenModulesExcludes {
|
||||
defines = append(defines, "-pl")
|
||||
defines = append(defines, "!"+module)
|
||||
}
|
||||
}
|
||||
|
||||
if config.SpotBugs {
|
||||
spotBugsMavenParameters := getSpotBugsMavenParameters(config)
|
||||
defines = append(defines, spotBugsMavenParameters.Defines...)
|
||||
goals = append(goals, spotBugsMavenParameters.Goals...)
|
||||
}
|
||||
if config.Pmd {
|
||||
pmdMavenParameters := getPmdMavenParameters(config)
|
||||
defines = append(defines, pmdMavenParameters.Defines...)
|
||||
goals = append(goals, pmdMavenParameters.Goals...)
|
||||
}
|
||||
finalMavenOptions := maven.ExecuteOptions{
|
||||
Goals: goals,
|
||||
Defines: defines,
|
||||
}
|
||||
_, err := maven.Execute(&finalMavenOptions, command)
|
||||
return err
|
||||
}
|
||||
|
||||
func getSpotBugsMavenParameters(config *mavenStaticCodeChecksOptions) *maven.ExecuteOptions {
|
||||
var defines []string
|
||||
if config.SpotBugsIncludeFilterFile != "" {
|
||||
defines = append(defines, "-Dspotbugs.includeFilterFile="+config.SpotBugsIncludeFilterFile)
|
||||
}
|
||||
if config.SpotBugsExcludeFilterFile != "" {
|
||||
defines = append(defines, "-Dspotbugs.excludeFilterFile="+config.SpotBugsExcludeFilterFile)
|
||||
}
|
||||
|
||||
mavenOptions := maven.ExecuteOptions{
|
||||
Goals: []string{"com.github.spotbugs:spotbugs-maven-plugin:3.1.12:spotbugs"},
|
||||
Defines: defines,
|
||||
}
|
||||
|
||||
return &mavenOptions
|
||||
}
|
||||
|
||||
func getPmdMavenParameters(config *mavenStaticCodeChecksOptions) *maven.ExecuteOptions {
|
||||
var defines []string
|
||||
if config.PmdExcludes != nil {
|
||||
defines = append(defines, "-Dpmd.excludes="+strings.Join(config.PmdExcludes, ","))
|
||||
}
|
||||
if config.PmdRuleSets != nil {
|
||||
defines = append(defines, "-Dpmd.rulesets="+strings.Join(config.PmdRuleSets, ","))
|
||||
}
|
||||
|
||||
mavenOptions := maven.ExecuteOptions{
|
||||
Goals: []string{"org.apache.maven.plugins:maven-pmd-plugin:3.13.0:pmd"},
|
||||
Defines: defines,
|
||||
}
|
||||
|
||||
return &mavenOptions
|
||||
}
|
143
cmd/mavenStaticCodeChecks_generated.go
Normal file
143
cmd/mavenStaticCodeChecks_generated.go
Normal file
@ -0,0 +1,143 @@
|
||||
// Code generated by piper's step-generator. DO NOT EDIT.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/config"
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
"github.com/SAP/jenkins-library/pkg/telemetry"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
type mavenStaticCodeChecksOptions struct {
|
||||
SpotBugs bool `json:"spotBugs,omitempty"`
|
||||
Pmd bool `json:"pmd,omitempty"`
|
||||
MavenModulesExcludes []string `json:"mavenModulesExcludes,omitempty"`
|
||||
SpotBugsExcludeFilterFile string `json:"spotBugsExcludeFilterFile,omitempty"`
|
||||
SpotBugsIncludeFilterFile string `json:"spotBugsIncludeFilterFile,omitempty"`
|
||||
PmdExcludes []string `json:"pmdExcludes,omitempty"`
|
||||
PmdRuleSets []string `json:"pmdRuleSets,omitempty"`
|
||||
}
|
||||
|
||||
// MavenStaticCodeChecksCommand Execute static code checks for Maven based projects. The plugins SpotBugs and PMD are used.
|
||||
func MavenStaticCodeChecksCommand() *cobra.Command {
|
||||
metadata := mavenStaticCodeChecksMetadata()
|
||||
var stepConfig mavenStaticCodeChecksOptions
|
||||
var startTime time.Time
|
||||
|
||||
var createMavenStaticCodeChecksCmd = &cobra.Command{
|
||||
Use: "mavenStaticCodeChecks",
|
||||
Short: "Execute static code checks for Maven based projects. The plugins SpotBugs and PMD are used.",
|
||||
Long: `Executes Spotbugs Maven plugin as well as Pmd Maven plugin for static code checks.
|
||||
SpotBugs is a program to find bugs in Java programs. It looks for instances of “bug patterns” — code instances that are likely to be errors.
|
||||
For more information please visit https://spotbugs.readthedocs.io/en/latest/maven.html
|
||||
PMD is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It supports Java, JavaScript, Salesforce.com Apex and Visualforce, PLSQL, Apache Velocity, XML, XSL.
|
||||
For more information please visit https://pmd.github.io/`,
|
||||
PreRunE: func(cmd *cobra.Command, args []string) error {
|
||||
startTime = time.Now()
|
||||
log.SetStepName("mavenStaticCodeChecks")
|
||||
log.SetVerbose(GeneralConfig.Verbose)
|
||||
return PrepareConfig(cmd, &metadata, "mavenStaticCodeChecks", &stepConfig, config.OpenPiperFile)
|
||||
},
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
telemetryData := telemetry.CustomData{}
|
||||
telemetryData.ErrorCode = "1"
|
||||
handler := func() {
|
||||
telemetryData.Duration = fmt.Sprintf("%v", time.Since(startTime).Milliseconds())
|
||||
telemetry.Send(&telemetryData)
|
||||
}
|
||||
log.DeferExitHandler(handler)
|
||||
defer handler()
|
||||
telemetry.Initialize(GeneralConfig.NoTelemetry, "mavenStaticCodeChecks")
|
||||
mavenStaticCodeChecks(stepConfig, &telemetryData)
|
||||
telemetryData.ErrorCode = "0"
|
||||
},
|
||||
}
|
||||
|
||||
addMavenStaticCodeChecksFlags(createMavenStaticCodeChecksCmd, &stepConfig)
|
||||
return createMavenStaticCodeChecksCmd
|
||||
}
|
||||
|
||||
func addMavenStaticCodeChecksFlags(cmd *cobra.Command, stepConfig *mavenStaticCodeChecksOptions) {
|
||||
cmd.Flags().BoolVar(&stepConfig.SpotBugs, "spotBugs", true, "Parameter to turn off SpotBugs.")
|
||||
cmd.Flags().BoolVar(&stepConfig.Pmd, "pmd", true, "Parameter to turn off PMD.")
|
||||
cmd.Flags().StringSliceVar(&stepConfig.MavenModulesExcludes, "mavenModulesExcludes", []string{}, "Maven modules which should be excluded by the static code checks. By default the modules 'unit-tests' and 'integration-tests' will be excluded.")
|
||||
cmd.Flags().StringVar(&stepConfig.SpotBugsExcludeFilterFile, "spotBugsExcludeFilterFile", os.Getenv("PIPER_spotBugsExcludeFilterFile"), "Path to a filter file with bug definitions which should be excluded.")
|
||||
cmd.Flags().StringVar(&stepConfig.SpotBugsIncludeFilterFile, "spotBugsIncludeFilterFile", os.Getenv("PIPER_spotBugsIncludeFilterFile"), "Path to a filter file with bug definitions which should be included.")
|
||||
cmd.Flags().StringSliceVar(&stepConfig.PmdExcludes, "pmdExcludes", []string{}, "A comma-separated list of exclusions (.java source files) expressed as an Ant-style pattern relative to the sources root folder, i.e. application/src/main/java for maven projects.")
|
||||
cmd.Flags().StringSliceVar(&stepConfig.PmdRuleSets, "pmdRuleSets", []string{}, "The PMD rulesets to use. See the Stock Java Rulesets for a list of available rules. Defaults to a custom ruleset provided by this maven plugin.")
|
||||
|
||||
}
|
||||
|
||||
// retrieve step metadata
|
||||
func mavenStaticCodeChecksMetadata() config.StepData {
|
||||
var theMetaData = config.StepData{
|
||||
Spec: config.StepSpec{
|
||||
Inputs: config.StepInputs{
|
||||
Parameters: []config.StepParameters{
|
||||
{
|
||||
Name: "spotBugs",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "pmd",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "bool",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "mavenModulesExcludes",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{},
|
||||
},
|
||||
{
|
||||
Name: "spotBugsExcludeFilterFile",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "spotBugs/excludeFilterFile"}},
|
||||
},
|
||||
{
|
||||
Name: "spotBugsIncludeFilterFile",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "spotBugs/includeFilterFile"}},
|
||||
},
|
||||
{
|
||||
Name: "pmdExcludes",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "pmd/excludes"}},
|
||||
},
|
||||
{
|
||||
Name: "pmdRuleSets",
|
||||
ResourceRef: []config.ResourceReference{},
|
||||
Scope: []string{"PARAMETERS", "STAGES", "STEPS"},
|
||||
Type: "[]string",
|
||||
Mandatory: false,
|
||||
Aliases: []config.Alias{{Name: "pmd/rulesSets"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
return theMetaData
|
||||
}
|
16
cmd/mavenStaticCodeChecks_generated_test.go
Normal file
16
cmd/mavenStaticCodeChecks_generated_test.go
Normal file
@ -0,0 +1,16 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestMavenStaticCodeChecksCommand(t *testing.T) {
|
||||
|
||||
testCmd := MavenStaticCodeChecksCommand()
|
||||
|
||||
// only high level testing performed - details are tested in step generation procudure
|
||||
assert.Equal(t, "mavenStaticCodeChecks", testCmd.Use, "command name incorrect")
|
||||
|
||||
}
|
110
cmd/mavenStaticCodeChecks_test.go
Normal file
110
cmd/mavenStaticCodeChecks_test.go
Normal file
@ -0,0 +1,110 @@
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"testing"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/log"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/mock"
|
||||
|
||||
"github.com/SAP/jenkins-library/pkg/maven"
|
||||
"github.com/stretchr/testify/assert"
|
||||
)
|
||||
|
||||
func TestRunMavenStaticCodeChecks(t *testing.T) {
|
||||
t.Run("should run spotBugs and pmd with all configured options", func(t *testing.T) {
|
||||
execMockRunner := mock.ExecMockRunner{}
|
||||
config := mavenStaticCodeChecksOptions{
|
||||
SpotBugs: true,
|
||||
Pmd: true,
|
||||
PmdExcludes: []string{"*test.java", "*prod.java"},
|
||||
PmdRuleSets: []string{"myRule.xml", "anotherRule.xml"},
|
||||
SpotBugsExcludeFilterFile: "excludeFilter.xml",
|
||||
SpotBugsIncludeFilterFile: "includeFilter.xml",
|
||||
MavenModulesExcludes: []string{"testing-lib", "test-helpers"},
|
||||
}
|
||||
expected := mock.ExecCall{
|
||||
Exec: "mvn",
|
||||
Params: []string{"-pl", "!unit-tests", "-pl", "!integration-tests",
|
||||
"-pl", "!testing-lib", "-pl", "!test-helpers",
|
||||
"-Dspotbugs.includeFilterFile=includeFilter.xml",
|
||||
"-Dspotbugs.excludeFilterFile=excludeFilter.xml",
|
||||
"-Dpmd.excludes=*test.java,*prod.java",
|
||||
"-Dpmd.rulesets=myRule.xml,anotherRule.xml",
|
||||
"--batch-mode",
|
||||
"com.github.spotbugs:spotbugs-maven-plugin:3.1.12:spotbugs",
|
||||
"org.apache.maven.plugins:maven-pmd-plugin:3.13.0:pmd",
|
||||
},
|
||||
}
|
||||
|
||||
currentDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
t.Fatal("Could not get current working directory")
|
||||
}
|
||||
defer os.Chdir(currentDir)
|
||||
os.Chdir("../test/resources/maven/")
|
||||
|
||||
err = runMavenStaticCodeChecks(&config, nil, &execMockRunner)
|
||||
|
||||
assert.Nil(t, err)
|
||||
assert.Equal(t, expected, execMockRunner.Calls[0])
|
||||
})
|
||||
t.Run("should log fatal if all tools are turned off", func(t *testing.T) {
|
||||
var hasFailed bool
|
||||
log.Entry().Logger.ExitFunc = func(int) { hasFailed = true }
|
||||
execMockRunner := mock.ExecMockRunner{}
|
||||
config := mavenStaticCodeChecksOptions{
|
||||
SpotBugs: false,
|
||||
Pmd: false,
|
||||
}
|
||||
_ = runMavenStaticCodeChecks(&config, nil, &execMockRunner)
|
||||
assert.True(t, hasFailed, "expected command to exit with fatal")
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetPmdMavenParameters(t *testing.T) {
|
||||
t.Run("should return maven options with excludes and rulesets", func(t *testing.T) {
|
||||
config := mavenStaticCodeChecksOptions{
|
||||
Pmd: true,
|
||||
PmdExcludes: []string{"*test.java", "*prod.java"},
|
||||
PmdRuleSets: []string{"myRule.xml", "anotherRule.xml"},
|
||||
}
|
||||
expected := maven.ExecuteOptions{
|
||||
Goals: []string{"org.apache.maven.plugins:maven-pmd-plugin:3.13.0:pmd"},
|
||||
Defines: []string{"-Dpmd.excludes=*test.java,*prod.java", "-Dpmd.rulesets=myRule.xml,anotherRule.xml"},
|
||||
}
|
||||
|
||||
assert.Equal(t, &expected, getPmdMavenParameters(&config))
|
||||
})
|
||||
t.Run("should return maven goal only", func(t *testing.T) {
|
||||
config := mavenStaticCodeChecksOptions{}
|
||||
expected := maven.ExecuteOptions{
|
||||
Goals: []string{"org.apache.maven.plugins:maven-pmd-plugin:3.13.0:pmd"}}
|
||||
|
||||
assert.Equal(t, &expected, getPmdMavenParameters(&config))
|
||||
})
|
||||
}
|
||||
|
||||
func TestGetSpotBugsMavenParameters(t *testing.T) {
|
||||
t.Run("should return maven options with excludes and include filters", func(t *testing.T) {
|
||||
config := mavenStaticCodeChecksOptions{
|
||||
SpotBugs: true,
|
||||
SpotBugsExcludeFilterFile: "excludeFilter.xml",
|
||||
SpotBugsIncludeFilterFile: "includeFilter.xml",
|
||||
}
|
||||
expected := maven.ExecuteOptions{
|
||||
Goals: []string{"com.github.spotbugs:spotbugs-maven-plugin:3.1.12:spotbugs"},
|
||||
Defines: []string{"-Dspotbugs.includeFilterFile=includeFilter.xml", "-Dspotbugs.excludeFilterFile=excludeFilter.xml"},
|
||||
}
|
||||
|
||||
assert.Equal(t, &expected, getSpotBugsMavenParameters(&config))
|
||||
})
|
||||
t.Run("should return maven goal only", func(t *testing.T) {
|
||||
config := mavenStaticCodeChecksOptions{}
|
||||
expected := maven.ExecuteOptions{
|
||||
Goals: []string{"com.github.spotbugs:spotbugs-maven-plugin:3.1.12:spotbugs"}}
|
||||
|
||||
assert.Equal(t, &expected, getSpotBugsMavenParameters(&config))
|
||||
})
|
||||
}
|
@ -59,6 +59,7 @@ func Execute() {
|
||||
rootCmd.AddCommand(MtaBuildCommand())
|
||||
rootCmd.AddCommand(ProtecodeExecuteScanCommand())
|
||||
rootCmd.AddCommand(MavenExecuteCommand())
|
||||
rootCmd.AddCommand(MavenStaticCodeChecksCommand())
|
||||
|
||||
addRootFlags(rootCmd)
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
|
71
resources/metadata/mavenStaticCodeChecks.yaml
Normal file
71
resources/metadata/mavenStaticCodeChecks.yaml
Normal file
@ -0,0 +1,71 @@
|
||||
metadata:
|
||||
name: mavenStaticCodeChecks
|
||||
description: Execute static code checks for Maven based projects. The plugins SpotBugs and PMD are used.
|
||||
longDescription: |
|
||||
Executes Spotbugs Maven plugin as well as Pmd Maven plugin for static code checks.
|
||||
SpotBugs is a program to find bugs in Java programs. It looks for instances of “bug patterns” — code instances that are likely to be errors.
|
||||
For more information please visit https://spotbugs.readthedocs.io/en/latest/maven.html
|
||||
PMD is a source code analyzer. It finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so forth. It supports Java, JavaScript, Salesforce.com Apex and Visualforce, PLSQL, Apache Velocity, XML, XSL.
|
||||
For more information please visit https://pmd.github.io/
|
||||
spec:
|
||||
inputs:
|
||||
params:
|
||||
- name: spotBugs
|
||||
description: Parameter to turn off SpotBugs.
|
||||
type: bool
|
||||
default: true
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: pmd
|
||||
description: Parameter to turn off PMD.
|
||||
type: bool
|
||||
default: true
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: mavenModulesExcludes
|
||||
description: Maven modules which should be excluded by the static code checks. By default the modules 'unit-tests' and 'integration-tests' will be excluded.
|
||||
type: '[]string'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
- name: spotBugsExcludeFilterFile
|
||||
description: Path to a filter file with bug definitions which should be excluded.
|
||||
type: string
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
aliases:
|
||||
- name: spotBugs/excludeFilterFile
|
||||
- name: spotBugsIncludeFilterFile
|
||||
description: Path to a filter file with bug definitions which should be included.
|
||||
type: string
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
aliases:
|
||||
- name: spotBugs/includeFilterFile
|
||||
- name: pmdExcludes
|
||||
description: A comma-separated list of exclusions (.java source files) expressed as an Ant-style pattern relative to the sources root folder, i.e. application/src/main/java for maven projects.
|
||||
type: '[]string'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
aliases:
|
||||
- name: pmd/excludes
|
||||
- name: pmdRuleSets
|
||||
description: The PMD rulesets to use. See the Stock Java Rulesets for a list of available rules. Defaults to a custom ruleset provided by this maven plugin.
|
||||
type: '[]string'
|
||||
scope:
|
||||
- PARAMETERS
|
||||
- STAGES
|
||||
- STEPS
|
||||
aliases:
|
||||
- name: pmd/rulesSets
|
Loading…
Reference in New Issue
Block a user