Skip to content
Permalink
Browse files

[JENKINS-46162] Support workflow/pipeline linting (#30)

* Supporting pipeline jobs, fixed some bugs, bumped minimal version to allow the usage of the pipelines

* Supporting GroovySandbox checker only in Jenkinsfiles, aka WorkflowJobs

* [JENKINS-46162] Support Pipeline project to be linted

* Added TestCases for the Pipeline jobs

* Enable System Groovy detection

* Missing testcases

* Enabling JenkinsLint action for pipelines/workflows

Change-Id: Ideaa90900b836d2a2f115fc7eefa7c2ab5533197

* Support pipeline timer trigger check

Change-Id: I857d85210a0f95c22226798320508132cecaf9fa

* Fixed TimeoutChecker for pipeline (some false positives)

Change-Id: I2f9cdd04a73702ffa16cb7050123dc6a63fb759b

* Support pipeline PollingSCMtrigger check

Change-Id: I7ef1a3228096c2e43713495629e044bbb141d898
  • Loading branch information...
v1v committed Aug 14, 2017
1 parent 07b8bc8 commit 2b5910a98e8c5c3790eccf6b0b1638b9dd0e3ee2
Showing with 399 additions and 84 deletions.
  1. +15 −1 pom.xml
  2. +2 −3 src/main/java/org/jenkins/ci/plugins/jenkinslint/JenkinsLintAction.java
  3. +10 −0 src/main/java/org/jenkins/ci/plugins/jenkinslint/JenkinsLintGlobalConfiguration.java
  4. +18 −5 src/main/java/org/jenkins/ci/plugins/jenkinslint/JobLintAction.java
  5. +0 −17 src/main/java/org/jenkins/ci/plugins/jenkinslint/LintActionFactory.java
  6. +11 −0 src/main/java/org/jenkins/ci/plugins/jenkinslint/SlaveLintAction.java
  7. +0 −17 src/main/java/org/jenkins/ci/plugins/jenkinslint/SlaveLintActionFactory.java
  8. +50 −0 src/main/java/org/jenkins/ci/plugins/jenkinslint/check/GroovySandboxChecker.java
  9. +24 −8 src/main/java/org/jenkins/ci/plugins/jenkinslint/check/GroovySystemExitChecker.java
  10. +18 −2 src/main/java/org/jenkins/ci/plugins/jenkinslint/check/JobDescriptionChecker.java
  11. +20 −2 src/main/java/org/jenkins/ci/plugins/jenkinslint/check/PollingSCMTriggerChecker.java
  12. +6 −0 src/main/java/org/jenkins/ci/plugins/jenkinslint/check/SlaveVersionChecker.java
  13. +9 −1 src/main/java/org/jenkins/ci/plugins/jenkinslint/check/TimeoutChecker.java
  14. +28 −8 src/main/java/org/jenkins/ci/plugins/jenkinslint/check/TimerTriggerChecker.java
  15. +7 −1 src/main/java/org/jenkins/ci/plugins/jenkinslint/model/AbstractAction.java
  16. +3 −0 src/main/resources/org/jenkins/ci/plugins/jenkinslint/JenkinsLintGlobalConfiguration/config.jelly
  17. +6 −0 src/main/resources/org/jenkins/ci/plugins/jenkinslint/check/Messages.properties
  18. +10 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/AbstractTestCase.java
  19. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/ArtifactCheckerTestCase.java
  20. +11 −5 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/BFACheckerTestCase.java
  21. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/CleanupWorkspaceCheckerTestCase.java
  22. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/GitRefCheckerTestCase.java
  23. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/GitRefSubmoduleCheckerTestCase.java
  24. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/GitShallowCheckerTestCase.java
  25. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/GradleWrapperCheckerTestCase.java
  26. +49 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/GroovySandboxCheckerTestCase.java
  27. +8 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/GroovySystemExitCheckerTestCase.java
  28. +4 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/HardcodedScriptCheckerTestCase.java
  29. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/JavadocCheckerTestCase.java
  30. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/JobAssignedLabelCheckerTestCase.java
  31. +9 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/JobDescriptionCheckerTestCase.java
  32. +10 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/JobLogRotatorCheckerTestCase.java
  33. +7 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/JobNameCheckerTestCase.java
  34. +4 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/MasterLabelCheckerTestCase.java
  35. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/MavenJobTypeCheckerTestCase.java
  36. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/MultibranchJobTypeCheckerTestCase.java
  37. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/NullSCMCheckerTestCase.java
  38. +7 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/PollingSCMTriggerCheckerTestCase.java
  39. +3 −0 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/TimeoutCheckerTestCase.java
  40. +17 −14 src/test/java/org/jenkins/ci/plugins/jenkinslint/check/TimerTriggerCheckerTestCase.java
16 pom.xml
@@ -11,10 +11,11 @@
</parent>

<properties>
<jenkins.version>1.580</jenkins.version>
<jenkins.version>1.607</jenkins.version>
<jenkins-test-harness.version>1.580</jenkins-test-harness.version>
<!--TODO: make true after the code cleanup-->
<findbugs.failOnError>false</findbugs.failOnError>
<workflow.version>1.14.2</workflow.version>
</properties>

<artifactId>jenkinslint</artifactId>
@@ -195,6 +196,19 @@
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-job</artifactId>
<version>${workflow.version}</version>
<scope>test</scope>
</dependency>

<dependency>
<groupId>org.jenkins-ci.plugins.workflow</groupId>
<artifactId>workflow-cps</artifactId>
<version>${workflow.version}</version>
<scope>test</scope>
</dependency>
<!-- JENKINS-29427 -->
<dependency>
<groupId>org.jenkins-ci.plugins</groupId>
@@ -29,14 +29,13 @@ public void getData() throws IOException {
this.reloadCheckList();
this.reloadSlaveCheckList();

for (AbstractProject item : Jenkins.getInstance().getAllItems(AbstractProject.class)) {
LOG.log(Level.FINER, "queryChecks " + item.getDisplayName());
for (hudson.model.Job item : Jenkins.getInstance().getAllItems(hudson.model.Job.class)) {
LOG.log(Level.FINER, "queryChecks " + item.getName());
Job newJob = new Job(item.getName(), item.getUrl());
for (InterfaceCheck checker : this.getCheckList()) {
LOG.log(Level.FINER, checker.getName() + " " + item.getName() + " " + checker.executeCheck(item));
// Lint is disabled when is ignored or globally disabled
newJob.addLint(new Lint(checker.getName(), checker.executeCheck(item), checker.isIgnored(item.getDescription()), checker.isEnabled()));

}
jobSet.put(item.getName(),newJob);
LOG.log(Level.FINER, newJob.toString());
@@ -44,6 +44,8 @@
private boolean timerTriggerCheckerEnabled = true;
private boolean windowsSlaveLaunchCheckerEnabled = true;

private boolean groovySandboxCheckerEnabled = true;

private int hardcodedScriptThreshold = HardcodedScriptChecker.THRESHOLD;
private boolean hardcodedScriptIgnoredComment = false;

@@ -302,6 +304,14 @@ public void setHardcodedScriptIgnoredComment(boolean hardcodedScriptIgnoredComme
this.hardcodedScriptIgnoredComment = hardcodedScriptIgnoredComment;
}

public boolean isGroovySandboxCheckerEnabled() {
return groovySandboxCheckerEnabled;
}

public void setWorkflowSandboxCheckerEnabled(boolean groovySandboxCheckerEnabled) {
this.groovySandboxCheckerEnabled = groovySandboxCheckerEnabled;
}

/**
* Performs on-the-fly validation of the form field 'name'.
*
@@ -1,7 +1,8 @@
package org.jenkins.ci.plugins.jenkinslint;

import hudson.model.AbstractProject;
import hudson.Extension;
import hudson.model.Action;
import jenkins.model.TransientActionFactory;
import org.jenkins.ci.plugins.jenkinslint.model.AbstractAction;
import org.jenkins.ci.plugins.jenkinslint.model.InterfaceCheck;
import org.jenkins.ci.plugins.jenkinslint.model.Job;
@@ -10,25 +11,27 @@
import org.kohsuke.stapler.export.ExportedBean;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;

@ExportedBean
public final class JobLintAction extends AbstractAction implements Action {

private static final Logger LOG = Logger.getLogger(JobLintAction.class.getName());
private AbstractProject<?, ?> project;
private hudson.model.Job project;
private Job job;

public static boolean isDisabled () {
return !JenkinsLintGlobalConfiguration.get().isJobActionEnabled();
}

public JobLintAction(AbstractProject<?, ?> project) {
public JobLintAction(hudson.model.Job project) {
this.project = project;
}

public AbstractProject<?, ?> getProject() {
public final hudson.model.Job<?, ?> getProject() {
return project;
}

@@ -38,7 +41,6 @@ public Job getJob() {
}

public void getData() throws IOException {

this.reloadCheckList();
this.job = new Job(this.project.getName(), this.project.getUrl());
for (InterfaceCheck checker : this.getCheckList()) {
@@ -47,5 +49,16 @@ public void getData() throws IOException {
LOG.log(Level.FINE, this.job.getLintList().toString());
}

@Extension
public static class Factory extends TransientActionFactory<hudson.model.Job> {
@Override
public Class<hudson.model.Job> type() {
return hudson.model.Job.class;
}

@Override
public Collection<? extends Action> createFor(hudson.model.Job target) {
return Collections.singleton(new JobLintAction(target));
}
}
}

This file was deleted.

Oops, something went wrong.
@@ -1,7 +1,9 @@
package org.jenkins.ci.plugins.jenkinslint;

import hudson.Extension;
import hudson.model.Action;
import hudson.model.Computer;
import hudson.model.TransientComputerActionFactory;
import org.jenkins.ci.plugins.jenkinslint.model.AbstractAction;
import org.jenkins.ci.plugins.jenkinslint.model.InterfaceSlaveCheck;
import org.jenkins.ci.plugins.jenkinslint.model.Lint;
@@ -10,6 +12,8 @@
import org.kohsuke.stapler.export.ExportedBean;

import java.io.IOException;
import java.util.Collection;
import java.util.Collections;
import java.util.logging.Level;
import java.util.logging.Logger;

@@ -43,4 +47,11 @@ public void getData() throws IOException {
}
}

@Extension
public static class Factory extends TransientComputerActionFactory {
@Override
public Collection<? extends Action> createFor(Computer target) {
return Collections.singleton(new SlaveLintAction(target));
}
}
}

This file was deleted.

Oops, something went wrong.
@@ -0,0 +1,50 @@
package org.jenkins.ci.plugins.jenkinslint.check;

import hudson.model.Item;
import hudson.model.Job;
import org.jenkins.ci.plugins.jenkinslint.model.AbstractCheck;

import java.util.logging.Level;

/**
* @author Victor Martinez
*/
public class GroovySandboxChecker extends AbstractCheck {

public GroovySandboxChecker(boolean enabled) {
super(enabled);
this.setDescription(Messages.GroovySandboxCheckerDesc());
this.setSeverity(Messages.GroovySandboxCheckerSeverity());
}

public boolean executeCheck(Item item) {
LOG.log(Level.FINE, "executeCheck " + item);
if (item instanceof Job) {
// Pipeline support
if (item.getClass().getSimpleName().equals("WorkflowJob")) {
try {
Object getDefinition = item.getClass().getMethod("getDefinition", null).invoke(item);
if (getDefinition.getClass().getSimpleName().equals("CpsFlowDefinition")) {
return !isSandbox(getDefinition);
}
} catch (Exception e) {
LOG.log(Level.FINE, "Exception " + e.getMessage(), e.getCause());
}
}
}
return false;
}

private boolean isSandbox(Object object) {
boolean status = true;
if (object != null) {
try {
Object isSandbox = object.getClass().getMethod("isSandbox", null).invoke(object);
return ((Boolean) isSandbox);
} catch (Exception e) {
LOG.log(Level.WARNING, "Exception " + e.getMessage(), e.getCause());
}
}
return status;
}
}
@@ -3,8 +3,7 @@
import hudson.model.AbstractProject;
import hudson.model.Descriptor;
import hudson.model.Item;
import hudson.model.JobProperty;
import hudson.model.JobPropertyDescriptor;
import hudson.model.Job;
import hudson.model.ParameterDefinition;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Project;
@@ -14,7 +13,6 @@
import org.jenkins.ci.plugins.jenkinslint.model.AbstractCheck;

import java.util.List;
import java.util.Map;
import java.util.logging.Level;

/**
@@ -54,13 +52,31 @@ public boolean executeCheck(Item item) {
}
}

if (isSystemExitInPublisher(((AbstractProject) item).getPublishersList())) {
found = true;
if (item instanceof AbstractProject) {
if (isSystemExitInPublisher(((AbstractProject) item).getPublishersList())) {
found = true;
}

if (((AbstractProject) item).getProperty(ParametersDefinitionProperty.class) != null) {
if (isSystemExitInParameters(((ParametersDefinitionProperty) ((AbstractProject) item).getProperty(ParametersDefinitionProperty.class)).getParameterDefinitions())) {
found = true;
}
}
}

if (((AbstractProject) item).getProperty(ParametersDefinitionProperty.class)!=null) {
if (isSystemExitInParameters(((ParametersDefinitionProperty)((AbstractProject) item).getProperty(ParametersDefinitionProperty.class)).getParameterDefinitions())) {
found = true;
if (item instanceof Job) {
// Pipeline support
if (item.getClass().getSimpleName().equals("WorkflowJob")) {
try {
Object getDefinition = item.getClass().getMethod("getDefinition", null).invoke(item);
if (getDefinition.getClass().getSimpleName().equals("CpsFlowDefinition")) {
if (containsSystemExit(getDefinition.getClass().getMethod("getScript",null).invoke(getDefinition))) {
found = true;
}
}
} catch (Exception e) {
LOG.log(Level.FINE, "Exception " + e.getMessage(), e.getCause());
}
}
}
return found;
@@ -4,6 +4,9 @@
import hudson.model.Item;
import org.jenkins.ci.plugins.jenkinslint.model.AbstractCheck;

import java.lang.reflect.Method;
import java.util.logging.Level;

/**
* @author Victor Martinez
*/
@@ -17,9 +20,22 @@ public JobDescriptionChecker(boolean enabled) {

public boolean executeCheck(Item item) {
if (item instanceof AbstractItem) {
return (((AbstractItem) item).getDescription() == null
|| ((AbstractItem) item).getDescription().length() == 0);
return isDescription(((AbstractItem) item).getDescription());
}
if (item.getClass().getSimpleName().equals("WorkflowJob")) {
try {
Object getDescription = item.getClass().getMethod("getDescription", null).invoke(item);
if (getDescription instanceof String) {
return isDescription((String) getDescription);
}
} catch (Exception e) {
LOG.log(Level.FINE, "Exception " + e.getMessage(), e.getCause());
}
}
return false;
}

private boolean isDescription(String description) {
return (description == null || description.length() == 0);
}
}
@@ -5,6 +5,9 @@
import hudson.triggers.SCMTrigger;
import org.jenkins.ci.plugins.jenkinslint.model.AbstractCheck;

import java.util.Map;
import java.util.logging.Level;

/**
* @author Victor Martinez
*/
@@ -17,9 +20,24 @@ public PollingSCMTriggerChecker(boolean enabled) {
}

public boolean executeCheck(Item item) {
boolean found = false;
if (item instanceof AbstractProject) {
return (((AbstractProject) item).getTrigger(SCMTrigger.class) != null);
found = (((AbstractProject) item).getTrigger(SCMTrigger.class) != null);
}
if (item.getClass().getSimpleName().equals("WorkflowJob")) {
try {
Object getTriggers = item.getClass().getMethod("getTriggers", null).invoke(item);
if (getTriggers instanceof Map) {
for (Object value : ((Map) getTriggers).values()) {
if (value instanceof SCMTrigger) {
found = true;
}
}
}
} catch (Exception e) {
LOG.log(Level.FINE, "Exception " + e.getMessage(), e.getCause());
}
}
return false;
return found;
}
}
Oops, something went wrong.

0 comments on commit 2b5910a

Please sign in to comment.
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.