Skip to content

Commit

Permalink
[JENKINS-46395] Feature/config disable jobs (#40)
Browse files Browse the repository at this point in the history
* [JENKINS-46395] Initial version of the enabling/disabling to analyse disabled jobs or not.

* Shown reason of empty table and changed tab name

* Cosmetic changes: removed double tab, changed description header

* Added extra tests to validate AT of using the GlobalSettings and ensure restAPI and floatingBox is shown accordingly
  • Loading branch information
v1v committed Aug 29, 2017
1 parent be1ea20 commit bae66c9
Show file tree
Hide file tree
Showing 9 changed files with 270 additions and 68 deletions.
Expand Up @@ -38,20 +38,26 @@ public void getData() throws IOException {
this.reloadCheckList();
this.reloadSlaveCheckList();

JenkinsLintGlobalConfiguration config = JenkinsLintGlobalConfiguration.get();

for (hudson.model.Job item : Jenkins.getInstance().getAllItems(hudson.model.Job.class)) {
// Fixing MatrixJobs @JENKINS-46176
if (!item.getParent().getClass().getSimpleName().equals("MatrixProject")) {
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()));
if (config.isLintDisabledJobEnabled() || isJobEnabled(item) ) {
// Fixing MatrixJobs @JENKINS-46176
if (!item.getParent().getClass().getSimpleName().equals("MatrixProject")) {
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()));
}
this.getJobSet().put(item.getName(), newJob);
LOG.log(Level.FINER, newJob.toString());
} else {
LOG.log(Level.FINER, "Excluded MatrixConfiguration " + item.getName());
}
this.getJobSet().put(item.getName(), newJob);
LOG.log(Level.FINER, newJob.toString());
} else {
LOG.log(Level.FINER, "Excluded MatrixConfiguration " + item.getName());
LOG.log(Level.FINER, "Excluded Job '" + item.getName() + "' since isLintDisabledJobEnabled has been disabled");
}
}

Expand Down Expand Up @@ -114,7 +120,6 @@ public void doPieGraph(StaplerRequest req, StaplerResponse rsp) throws IOExcepti
ChartUtil.generateGraph(req,rsp, JenkinsLintGraph.createPieChart(this.getJobSet().elements()),512,384);
}


public void doSeverityPieGraph(StaplerRequest req, StaplerResponse rsp) throws IOException {
if(ChartUtil.awtProblemCause != null) {
// not available. send out error message
Expand All @@ -123,4 +128,25 @@ public void doSeverityPieGraph(StaplerRequest req, StaplerResponse rsp) throws I
}
ChartUtil.generateGraph(req,rsp, JenkinsLintGraph.createSeverityPieChart(this.getJobSet().elements(), this.getCheckSet()),512,384);
}

/**
* Whether the job has been disabled, since isDisabled is part of the AbstractProject and WorkflowJob doesn't
* extend it then let's use reflection.
*
* @return
*/
private boolean isJobEnabled(hudson.model.Job job) {
boolean enabled = true;
if (job != null) {
try {
Object isDisabled = job.getClass().getMethod("isDisabled", null).invoke(job);
if (isDisabled instanceof Boolean) {
enabled = !(Boolean) isDisabled;
}
} catch (Exception e) {
LOG.log(Level.FINE, "Exception " + e.getMessage(), e.getCause());
}
}
return enabled;
}
}
Expand Up @@ -17,6 +17,7 @@ public final class JenkinsLintGlobalConfiguration extends GlobalConfiguration {

private boolean globalEnabled = true;
private boolean jobActionEnabled = true;
private boolean lintDisabledJobEnabled = true;

private boolean artifactCheckerEnabled = true;
private boolean bfaCheckerEnabled = true;
Expand Down Expand Up @@ -312,6 +313,14 @@ public void setWorkflowSandboxCheckerEnabled(boolean groovySandboxCheckerEnabled
this.groovySandboxCheckerEnabled = groovySandboxCheckerEnabled;
}

public boolean isLintDisabledJobEnabled() {
return lintDisabledJobEnabled;
}

public void setLintDisabledJobEnabled(boolean lintDisabledJobEnabled) {
this.lintDisabledJobEnabled = lintDisabledJobEnabled;
}

/**
* Performs on-the-fly validation of the form field 'name'.
*
Expand All @@ -330,4 +339,5 @@ public FormValidation doCheckHardcodedScriptThreshold(@QueryParameter int value)
return FormValidation.error("Please set a value greater than 1");
return FormValidation.ok();
}

}
Expand Up @@ -23,10 +23,36 @@ public final class JobLintAction extends AbstractAction implements Action {
private hudson.model.Job project;
private Job job;

/**
* Whether the project has been disabled, since isDisabled is part of the AbstractProject and WorkflowJob doesn't
* extend it then let's use reflection.
*
* @return
*/
public boolean isProjectEnabled() {
boolean enabled = true;
if (this.project != null) {
try {
Object isDisabled = this.project.getClass().getMethod("isDisabled", null).invoke(this.project);
if (isDisabled instanceof Boolean) {
enabled = !(Boolean) isDisabled;
}
} catch (Exception e) {
LOG.log(Level.FINE, "Exception " + e.getMessage(), e.getCause());
}
}
return enabled;

}

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

public static boolean isLintDisabledJobEnabled() {
return JenkinsLintGlobalConfiguration.get().isLintDisabledJobEnabled();
}

public JobLintAction(hudson.model.Job project) {
this.project = project;
}
Expand All @@ -42,11 +68,15 @@ 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()) {
this.job.addLint(new Lint(checker.getName(), checker.executeCheck(this.project), checker.isIgnored(this.project.getDescription()), checker.isEnabled()) );

// In case it has been disabled from the global settings then no run lint analysis
if (isProjectEnabled() || isLintDisabledJobEnabled()) {
this.job = new Job(this.project.getName(), this.project.getUrl());
for (InterfaceCheck checker : this.getCheckList()) {
this.job.addLint(new Lint(checker.getName(), checker.executeCheck(this.project), checker.isIgnored(this.project.getDescription()), checker.isEnabled()));
}
LOG.log(Level.FINE, this.job.getLintList().toString());
}
LOG.log(Level.FINE, this.job.getLintList().toString());
}

@Extension
Expand Down
Expand Up @@ -6,10 +6,15 @@
description="${%If Jobs should be scanned or not.}" field="globalEnabled">
<f:checkbox/>
</f:entry>
<f:entry title="${%Enable analysis of disabled Jobs}"
description="${%Whether to lint disabled jobs or not.}" field="lintDisabledJobEnabled">
<f:checkbox/>
</f:entry>
<f:entry title="${%Enable Job floating box}"
description="${%Whether to display JobAction floatingBox or not.}" field="jobActionEnabled">
<f:checkbox/>
</f:entry>

</f:section>

<f:advanced>
Expand Down
@@ -1,9 +1,11 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:d="jelly:define" xmlns:l="/lib/layout" xmlns:t="/lib/hudson" xmlns:f="/lib/form" xmlns:i="jelly:fmt" xmlns:local="local">
<j:if test="${!from.isDisabled()}">
<j:set var="data" value="${from.data}"/>
<div style="background-color: #eee; overflow-x: auto; padding:10px; margin: 1px; border: 1px solid #777;">
<img src="${rootURL}${from.getIconFileName()}" alt=""/> <img src="${rootURL}${from.job.getLintHealthReport().getIconUrl('16x16')}" alt=""/> ${from.job.getLintHealthReport().getDescription()}
</div>
<j:if test="${from.isLintDisabledJobEnabled() or from.isProjectEnabled()}">
<j:set var="data" value="${from.data}"/>
<div style="background-color: #eee; overflow-x: auto; padding:10px; margin: 1px; border: 1px solid #777;">
<img src="${rootURL}${from.getIconFileName()}" alt=""/> <img src="${rootURL}${from.job.getLintHealthReport().getIconUrl('16x16')}" alt=""/> ${from.job.getLintHealthReport().getDescription()}
</div>
</j:if>
</j:if>
</j:jelly>
@@ -1,6 +1,6 @@
<?jelly escape-by-default='true'?>
<j:jelly xmlns:j="jelly:core" xmlns:st="jelly:stapler" xmlns:l="/lib/layout">
<l:layout title="Test" norefresh="true">
<l:layout title="${%Jenkins.Lint.Title}" norefresh="true">
<st:include page="sidepanel.jelly" it="${it.project}" />
<l:main-panel>
<style>
Expand All @@ -12,47 +12,54 @@
</style>
<j:set var="index" value="0"/>
<j:set var="data" value="${it.data}"/>
<h1>${%Jenkins.Lint.Title}: ${%Project} ${it.project.name}</h1>
<h4>${%Jenkins.Lint.Description}</h4>
${%Jenkins.Lint.Description.1}
${%Jenkins.Lint.Description.2}
<br/>
<table class="sortable pane bigtable" id="jenkinsLintDescriptionTable">
<thead>
<tr>
<th class="pane-header">Status</th>
<th class="pane-header">Defect Name</th>
<th class="pane-header">Description</th>
</tr>
</thead>
<tbody id="jenkinsLintDescriptionTableBody">
<j:forEach var="lint" items="${it.job.lintList}">
<tr>
<j:if test="${!lint.isActive()}">
<j:if test="${!lint.isEnabled()}">
<td data="disabled-${lint.name}" tooltip="disabled" style="background-color: #f0f0f0;"/>
</j:if>
<j:if test="${lint.isEnabled()}">
<j:if test="${lint.isIgnored()}">
<td data="ignored-${lint.name}" tooltip="ignored" style="background-color: #f9ef9e;"/>
</j:if>
</j:if>
</j:if>
<j:if test="${lint.isActive()}">
<j:if test="${lint.found}">
<td data="found-${lint.name}" tooltip="found" style="background-color: #FF8566;"/>
</j:if>
<j:if test="${!lint.found}">
<td data="not_found-${lint.name}" tooltip="not_found" style="background-color: #B8EEB8;"/>
</j:if>
</j:if>
<td>${lint.name}</td>
<td><j:out value="${it.checkList.get(0+index).getDescription()}"/></td>
<j:set var="index" value="${index+1}"/>
</tr>
</j:forEach>
</tbody>
</table>
<h1>${%Project} ${it.project.name}</h1>
<j:if test="${it.isLintDisabledJobEnabled() or it.isProjectEnabled()}">
<h4>${%Jenkins.Lint.Description}</h4>
${%Jenkins.Lint.Description.1}
${%Jenkins.Lint.Description.2}
<br/>
<table class="sortable pane bigtable" id="jenkinsLintDescriptionTable">
<thead>
<tr>
<th class="pane-header">Status</th>
<th class="pane-header">Defect Name</th>
<th class="pane-header">Description</th>
</tr>
</thead>
<tbody id="jenkinsLintDescriptionTableBody">
<j:forEach var="lint" items="${it.job.lintList}">
<tr>
<j:if test="${!lint.isActive()}">
<j:if test="${!lint.isEnabled()}">
<td data="disabled-${lint.name}" tooltip="disabled" style="background-color: #f0f0f0;"/>
</j:if>
<j:if test="${lint.isEnabled()}">
<j:if test="${lint.isIgnored()}">
<td data="ignored-${lint.name}" tooltip="ignored" style="background-color: #f9ef9e;"/>
</j:if>
</j:if>
</j:if>
<j:if test="${lint.isActive()}">
<j:if test="${lint.found}">
<td data="found-${lint.name}" tooltip="found" style="background-color: #FF8566;"/>
</j:if>
<j:if test="${!lint.found}">
<td data="not_found-${lint.name}" tooltip="not_found" style="background-color: #B8EEB8;"/>
</j:if>
</j:if>
<td>${lint.name}</td>
<td><j:out value="${it.checkList.get(0+index).getDescription()}"/></td>
<j:set var="index" value="${index+1}"/>
</tr>
</j:forEach>
</tbody>
</table>
</j:if>
<j:if test="${!it.isLintDisabledJobEnabled() and !it.isProjectEnabled()}">
<div class="alert alert-warning">
<strong>This project is currently disabled. Please review your global settings if you would like to analyse disabled projects.</strong>
</div>
</j:if>
</l:main-panel>
</l:layout>
</j:jelly>
Expand Up @@ -9,15 +9,21 @@
import hudson.matrix.AxisList;
import hudson.matrix.MatrixProject;
import hudson.matrix.TextAxis;
import hudson.model.Action;
import hudson.model.FreeStyleProject;
import jenkins.model.GlobalConfiguration;
import org.junit.Test;
import org.jvnet.hudson.test.Issue;

import java.util.ArrayList;
import java.util.List;

import static org.hamcrest.CoreMatchers.containsString;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;

/**
* @author victor.martinez.
Expand Down Expand Up @@ -111,6 +117,31 @@ public void testMatrixJobWithConfigurations() throws Exception {
assertFalse(content.contains("axis"));
}

@Test
public void testDisabledJobs() throws Exception {
JenkinsLintGlobalConfiguration config = GlobalConfiguration.all().get(JenkinsLintGlobalConfiguration.class);
config.setLintDisabledJobEnabled(false);
config.save();
FreeStyleProject project = j.createFreeStyleProject();
project.disable();
for (Action action: j.getInstance().getActions()) {
if (action instanceof JenkinsLintAction) {
((JenkinsLintAction) action).getData();
assertEquals(((JenkinsLintAction) action).getJobSet().size(), 0);
j.createFreeStyleProject();
j.createFreeStyleProject();
((JenkinsLintAction) action).getData();
assertEquals(((JenkinsLintAction) action).getJobSet().size(), 2);
j.createFreeStyleProject().disable();
((JenkinsLintAction) action).getData();
assertEquals(((JenkinsLintAction) action).getJobSet().size(), 2);
config.setLintDisabledJobEnabled(true);
config.save();
((JenkinsLintAction) action).getData();
assertEquals(((JenkinsLintAction) action).getJobSet().size(), 4);
}
}
}

private String htmlLint (String name, String id) {
return "<th tooltip=\"" + name + "\" class=\"pane-header\">" + id + "</th>";
Expand Down
Expand Up @@ -13,9 +13,11 @@
public class JenkinsLintGlobalConfigurationTestCase extends AbstractTestCase{

@Test
public void testDefaultonfigured() throws Exception {
public void testDefaultGlobalConfiguration() throws Exception {
JenkinsLintGlobalConfiguration config = GlobalConfiguration.all().get(JenkinsLintGlobalConfiguration.class);
assertTrue(config.isGlobalEnabled());
assertTrue(config.isLintDisabledJobEnabled());
assertTrue(config.isJobActionEnabled());
}

@Test
Expand Down

0 comments on commit bae66c9

Please sign in to comment.