Skip to content
Permalink
Browse files
added support for the Dashboard View plugin
[FIXES JENKINS-29146]
  • Loading branch information
daspilker committed Jan 3, 2016
1 parent c99904c commit 1aec4077c6387c7eaeaef9452ed3a698aa175492
Showing with 444 additions and 8 deletions.
  1. +2 −0 docs/Home.md
  2. +16 −0 job-dsl-core/src/main/docs/examples/javaposse/jobdsl/dsl/DslFactory/dashboardView.groovy
  3. +7 −0 ...s/examples/javaposse/jobdsl/dsl/views/portlets/DashboardPortletContext/testStatisticsChart.groovy
  4. +10 −0 ...cs/examples/javaposse/jobdsl/dsl/views/portlets/DashboardPortletContext/testStatisticsGrid.groovy
  5. +9 −0 job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/JobParent.groovy
  6. +18 −0 job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/ViewFactory.groovy
  7. +52 −0 job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/views/DashboardView.groovy
  8. +8 −0 job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/views/NestedViewsContext.groovy
  9. +47 −0 job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/views/portlets/DashboardPortletContext.groovy
  10. +14 −0 job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/views/portlets/TestStatisticsChartContext.groovy
  11. +52 −0 job-dsl-core/src/main/groovy/javaposse/jobdsl/dsl/views/portlets/TestStatisticsGridContext.groovy
  12. +21 −0 job-dsl-core/src/main/resources/javaposse/jobdsl/dsl/views/DashboardView-template.xml
  13. +26 −0 job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/JobParentSpec.groovy
  14. +1 −1 job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/views/BuildMonitorViewSpec.groovy
  15. +5 −5 job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/views/CategorizedJobsViewSpec.groovy
  16. +123 −0 job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/views/DashboardViewSpec.groovy
  17. +2 −2 job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/views/ListViewSpec.groovy
  18. +31 −0 job-dsl-core/src/test/groovy/javaposse/jobdsl/dsl/views/NestedViewSpec.groovy
@@ -21,6 +21,8 @@ Browse the Jenkins issue tracker to see any [open issues](https://issues.jenkins

## Release Notes
* 1.42 (unreleased)
* Added support for the [Dashboard View Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Dashboard+View)
([JENKINS-29146](https://issues.jenkins-ci.org/browse/JENKINS-29146))
* Added support for the [Workflow Multibranch Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Workflow+Plugin)
([JENKINS-31671](https://issues.jenkins-ci.org/browse/JENKINS-31671),
[JENKINS-31719](https://issues.jenkins-ci.org/browse/JENKINS-31719))
@@ -0,0 +1,16 @@
dashboardView('example') {
jobs {
regex(/acme-.*/)
}
columns {
status()
weather()
buildButton()
}
topPortlets {
testStatisticsChart()
}
bottomPortlets {
testStatisticsGrid()
}
}
@@ -0,0 +1,7 @@
dashboardView('example') {
topPortlets {
testStatisticsChart {
displayName('Project A Test Stats')
}
}
}
@@ -0,0 +1,10 @@
dashboardView('example') {
rightPortlets {
testStatisticsGrid {
displayName('Project A Test Stats')
skippedColor('7F7F7F')
failureColor('FF0000')
successColor('00FF00')
}
}
}
@@ -12,6 +12,7 @@ import javaposse.jobdsl.dsl.jobs.MultibranchWorkflowJob
import javaposse.jobdsl.dsl.views.BuildMonitorView
import javaposse.jobdsl.dsl.views.BuildPipelineView
import javaposse.jobdsl.dsl.views.CategorizedJobsView
import javaposse.jobdsl.dsl.views.DashboardView
import javaposse.jobdsl.dsl.views.DeliveryPipelineView
import javaposse.jobdsl.dsl.views.ListView
import javaposse.jobdsl.dsl.views.NestedView
@@ -173,6 +174,14 @@ abstract class JobParent extends Script implements DslFactory {
processView(name, CategorizedJobsView, closure)
}

/**
* @since 1.42
*/
@Override
DashboardView dashboardView(String name, @DslContext(DashboardView) Closure closure = null) {
processView(name, DashboardView, closure)
}

// this method cannot be private due to http://jira.codehaus.org/browse/GROOVY-6263
protected <T extends View> T processView(String name, Class<T> viewClass, Closure closure) {
checkNotNullOrEmpty(name, 'name must be specified')
@@ -3,6 +3,7 @@ package javaposse.jobdsl.dsl
import javaposse.jobdsl.dsl.views.BuildMonitorView
import javaposse.jobdsl.dsl.views.BuildPipelineView
import javaposse.jobdsl.dsl.views.CategorizedJobsView
import javaposse.jobdsl.dsl.views.DashboardView
import javaposse.jobdsl.dsl.views.DeliveryPipelineView
import javaposse.jobdsl.dsl.views.ListView
import javaposse.jobdsl.dsl.views.NestedView
@@ -111,4 +112,21 @@ interface ViewFactory {
*/
@RequiresPlugin(id = 'categorized-view', minimumVersion = '1.8')
CategorizedJobsView categorizedJobsView(String name, @DslContext(CategorizedJobsView) Closure closure)

/**
* Creates or updates a dashboard / portal-like view.
*
* @see #dashboardView(java.lang.String, groovy.lang.Closure)
* @since 1.42
*/
@RequiresPlugin(id = 'dashboard-view', minimumVersion = '2.9.7')
DashboardView dashboardView(String name)

/**
* Creates or updates a dashboard / portal-like view.
* @since 1.42
*/
@RequiresPlugin(id = 'dashboard-view', minimumVersion = '2.9.7')
DashboardView dashboardView(String name, @DslContext(DashboardView) Closure closure)
}
@@ -0,0 +1,52 @@
package javaposse.jobdsl.dsl.views

import javaposse.jobdsl.dsl.DslContext
import javaposse.jobdsl.dsl.JobManagement
import javaposse.jobdsl.dsl.views.portlets.DashboardPortletContext

import static javaposse.jobdsl.dsl.ContextHelper.executeInContext

class DashboardView extends ListView {
DashboardView(JobManagement jobManagement) {
super(jobManagement)
}

/**
* Adds portlets to the top of the page.
*/
void topPortlets(@DslContext(DashboardPortletContext) Closure closure) {
addPortlets('topPortlets', closure)
}

/**
* Adds portlets to the bottom of the page.
*/
void bottomPortlets(@DslContext(DashboardPortletContext) Closure closure) {
addPortlets('bottomPortlets', closure)
}

/**
* Adds portlets to the left column.
*/
void leftPortlets(@DslContext(DashboardPortletContext) Closure closure) {
addPortlets('leftPortlets', closure)
}

/**
* Adds portlets to the right column.
*/
void rightPortlets(@DslContext(DashboardPortletContext) Closure closure) {
addPortlets('rightPortlets', closure)
}

protected void addPortlets(String elementName, Closure closure) {
DashboardPortletContext context = new DashboardPortletContext()
executeInContext(closure, context)

execute {
context.portletNodes.each { node ->
it / "$elementName" << node
}
}
}
}
@@ -70,6 +70,14 @@ class NestedViewsContext extends AbstractContext implements ViewFactory {
processView(name, CategorizedJobsView, closure)
}

/**
* @since 1.42
*/
@Override
DashboardView dashboardView(String name, @DslContext(DashboardView) Closure closure = null) {
processView(name, DashboardView, closure)
}

private <T extends View> T processView(String name, Class<T> viewClass, Closure closure) {
Preconditions.checkNotNullOrEmpty(name, 'name must be specified')

@@ -0,0 +1,47 @@
package javaposse.jobdsl.dsl.views.portlets

import javaposse.jobdsl.dsl.Context
import javaposse.jobdsl.dsl.ContextHelper
import javaposse.jobdsl.dsl.DslContext

import java.security.SecureRandom

class DashboardPortletContext implements Context {
private static final Random RANDOM = new SecureRandom()

protected final List<Node> portletNodes = []

/**
* Adds a test statistics chart.
*/
void testStatisticsChart(@DslContext(TestStatisticsChartContext) Closure closure = null) {
TestStatisticsChartContext context = new TestStatisticsChartContext()
ContextHelper.executeInContext(closure, context)

portletNodes << new NodeBuilder().'hudson.plugins.view.dashboard.test.TestStatisticsChart' {
id(generatePortletId())
name(context.displayName ?: '')
}
}

/**
* Adds a test statistics grid.
*/
void testStatisticsGrid(@DslContext(TestStatisticsGridContext) Closure closure = null) {
TestStatisticsGridContext context = new TestStatisticsGridContext()
ContextHelper.executeInContext(closure, context)

portletNodes << new NodeBuilder().'hudson.plugins.view.dashboard.test.TestStatisticsPortlet' {
id(generatePortletId())
name(context.displayName ?: '')
useBackgroundColors(context.useBackgroundColors)
skippedColor(context.skippedColor ?: '')
successColor(context.successColor ?: '')
failureColor(context.failureColor ?: '')
}
}

private static String generatePortletId() {
"dashboard_portlet_${RANDOM.nextInt(32000)}"
}
}
@@ -0,0 +1,14 @@
package javaposse.jobdsl.dsl.views.portlets

import javaposse.jobdsl.dsl.Context

class TestStatisticsChartContext implements Context {
String displayName = 'Test Statistics Chart'

/**
* Sets the display name for the portlet. Defaults to {@code 'Test Statistics Chart'}.
*/
void displayName(String displayName) {
this.displayName = displayName
}
}
@@ -0,0 +1,52 @@
package javaposse.jobdsl.dsl.views.portlets

import javaposse.jobdsl.dsl.Context

class TestStatisticsGridContext implements Context {
String displayName = 'Test Statistics Grid'
boolean useBackgroundColors = false
String skippedColor = 'FDB813'
String successColor = '71E66D'
String failureColor = 'E86850'

/**
* Sets the display name for the portlet. Defaults to {@code 'Test Statistics Grid'}.
*/
void displayName(String displayName) {
this.displayName = displayName
}

/**
* If set, displays a colored background. Defaults to {@code false}.
*/
void useBackgroundColors(boolean useBackgroundColors = true) {
this.useBackgroundColors = useBackgroundColors
}

/**
* Sets the color for skipped tests as hex value. Defaults to {@code 'FDB813'}. Sets {@code useBackgroundColors} to
* {@code true}.
*/
void skippedColor(String skippedColor) {
useBackgroundColors()
this.skippedColor = skippedColor
}

/**
* Sets the color for successful tests as hex value. Defaults to {@code '71E66D'}. Sets {@code useBackgroundColors}
* to {@code true}.
*/
void successColor(String successColor) {
useBackgroundColors()
this.successColor = successColor
}

/**
* Sets the color for failed tests as hex value. Defaults to {@code 'E86850'}. Sets {@code useBackgroundColors} to
* {@code true}.
*/
void failureColor(String failureColor) {
useBackgroundColors()
this.failureColor = failureColor
}
}
@@ -0,0 +1,21 @@
<?xml version='1.0' encoding='UTF-8'?>
<hudson.plugins.view.dashboard.Dashboard>
<filterExecutors>false</filterExecutors>
<filterQueue>false</filterQueue>
<properties class="hudson.model.View$PropertyList"/>
<jobNames>
<comparator class="hudson.util.CaseInsensitiveComparator"/>
</jobNames>
<jobFilters/>
<columns/>
<recurse>false</recurse>
<useCssStyle>false</useCssStyle>
<includeStdJobList>false</includeStdJobList>
<hideJenkinsPanels>false</hideJenkinsPanels>
<leftPortletWidth>50%</leftPortletWidth>
<rightPortletWidth>50%</rightPortletWidth>
<leftPortlets/>
<rightPortlets/>
<topPortlets/>
<bottomPortlets/>
</hudson.plugins.view.dashboard.Dashboard>
@@ -11,6 +11,7 @@ import javaposse.jobdsl.dsl.jobs.MultibranchWorkflowJob
import javaposse.jobdsl.dsl.views.BuildMonitorView
import javaposse.jobdsl.dsl.views.BuildPipelineView
import javaposse.jobdsl.dsl.views.CategorizedJobsView
import javaposse.jobdsl.dsl.views.DashboardView
import javaposse.jobdsl.dsl.views.DeliveryPipelineView
import javaposse.jobdsl.dsl.views.ListView
import javaposse.jobdsl.dsl.views.NestedView
@@ -198,6 +199,31 @@ class JobParentSpec extends Specification {
1 * jobManagement.requireMinimumPluginVersion('categorized-view', '1.8')
}

def 'should add dashboard view'() {
when:
View view = parent.dashboardView('test') {
description('foo')
}

then:
view.name == 'test'
view instanceof DashboardView
parent.referencedViews.contains(view)
view.node.description[0].text() == 'foo'
1 * jobManagement.requireMinimumPluginVersion('dashboard-view', '2.9.7')
}

def 'should add dashboard view without closure'() {
when:
View view = parent.dashboardView('test')

then:
view.name == 'test'
view instanceof DashboardView
parent.referencedViews.contains(view)
1 * jobManagement.requireMinimumPluginVersion('dashboard-view', '2.9.7')
}

def 'folder'() {
when:
Folder folder = parent.folder('test') {
@@ -1,6 +1,6 @@
package javaposse.jobdsl.dsl.views

class BuildMonitorViewSpec extends ListViewSpec {
class BuildMonitorViewSpec extends ListViewSpec<BuildMonitorView> {
def setup() {
view = new BuildMonitorView(jobManagement)
}
@@ -1,6 +1,6 @@
package javaposse.jobdsl.dsl.views

class CategorizedJobsViewSpec extends ListViewSpec {
class CategorizedJobsViewSpec extends ListViewSpec<CategorizedJobsView> {
def setup() {
view = new CategorizedJobsView(jobManagement)
}
@@ -23,7 +23,7 @@ class CategorizedJobsViewSpec extends ListViewSpec {

def 'do nothing on empty categorization criteria'() {
when:
((CategorizedJobsView) view).categorizationCriteria {
view.categorizationCriteria {
}

then:
@@ -35,7 +35,7 @@ class CategorizedJobsViewSpec extends ListViewSpec {

def 'group by regex with naming'() {
when:
((CategorizedJobsView) view).categorizationCriteria {
view.categorizationCriteria {
regexGroupingRule('regex', 'naming')
}

@@ -52,7 +52,7 @@ class CategorizedJobsViewSpec extends ListViewSpec {

def 'group by regex without naming'() {
when:
((CategorizedJobsView) view).categorizationCriteria {
view.categorizationCriteria {
regexGroupingRule('regex')
}

@@ -69,7 +69,7 @@ class CategorizedJobsViewSpec extends ListViewSpec {

def 'add more than one group'() {
when:
((CategorizedJobsView) view).categorizationCriteria {
view.categorizationCriteria {
regexGroupingRule('regex1', 'naming1')
regexGroupingRule('regex2', 'naming2')
}

0 comments on commit 1aec407

Please sign in to comment.