Skip to content

Commit 2b2d5ab

Browse files
committedSep 3, 2017
JenkinsWorld 2017 presentation and groovy examples
0 parents  commit 2b2d5ab

19 files changed

+370
-0
lines changed
 

‎.gitignore

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
.classpath
2+
.project
3+
.settings/
4+
target/
5+
.idea/
6+
*.iml
7+
*.ipr
8+
*.iws
9+
.DS_Store

‎2017_Jenkins_World_VictorMartinez.pdf

4.35 MB
Binary file not shown.

‎LICENSE

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
The MIT License
2+
3+
Copyright (c) 2017, Victor Martinez
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in
13+
all copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21+
THE SOFTWARE.

‎README.md

+47
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Jenkins World 2017
2+
3+
This talk was presented during Jenkins World 2017 in San Francisco, CA on August 29th-31st.
4+
5+
## Presentation
6+
7+
[2017_Jenkins_World_VictorMartinez.pdf](2017_Jenkins_World_VictorMartinez.pdf) contains the slides of the presentation.
8+
9+
*NOTE*: The presentation was recorded although the video URL hasn't been released yet.
10+
11+
## Best Practices
12+
13+
You can find some example groovy scripts to analyse what Jenkins projects don't follow those practices.
14+
15+
It does use the internal Jenkins API and therefore you need to be cautious to avoid doing evil things:
16+
17+
* http://unethicalblogger.com/2017/08/03/donut-disable-groovy-sandbox.html
18+
19+
Bear in mind, some of those scripts are just read only but others are also adding some details in the project description and also disabling those jobs.
20+
21+
This groovy implementation is just a basic/simple implementation, it might not cover all the use cases. The final solution was implemented as a Jenkins Plugin called Jenkins Lint plugin.
22+
23+
* [Example 1](groovy/description.groovy) - shows list of projects without any description
24+
* [Example 2](groovy/spaces.groovy) - shows list of projects with whitespaces in their name
25+
* [Example 3](groovy/label.groovy) - shows list of projects without any label restriction
26+
* [Example 4](groovy/workspace.groovy) - shows list of projects without any workspace cleanup policy
27+
* [Example 5](groovy/logrotator.groovy) - shows list of projects without any log rotator policy or empty values
28+
* [Example 6](groovy/pushing.groovy) - shows list of projects using polling
29+
* [Example 7](groovy/shallow.groovy) - shows list of projects which use git but no shallow cloning
30+
* [Example 8](groovy/reference.groovy) - shows list of projects which use git but no git reference repos
31+
* [Example 9](groovy/system_exit.groovy) - shows list of Projects which some system exit when using groovy post build actions
32+
* [Example 10](groovy/groovy_sandbox.groovy) - shows list of pipelines without the groovy sandbox option
33+
* [Example 11](groovy/maven.groovy) - shows list of Maven job types
34+
* [Example 12](groovy/timeout.groovy) - shows list of projects which don't use the Build Timeout plugin
35+
* [Example 13](groovy/bfa.groovy) - shows list of projects which don't use the Build Failure plugin
36+
37+
### How to run them
38+
39+
* Open the script console page: This feature can be accessed from the "manage Jenkins" link, typically at your http://server/jenkins/script. [ScriptConsole Wiki](https://wiki.jenkins.io/display/JENKINS/Jenkins+Script+Console)
40+
* Copy one of those groovy Script and paste in the script console text area.
41+
* Run and look at the output.
42+
43+
## Further details
44+
For more information on JenkinsLint, please visit [JenkinsLint](https://plugins.jenkins.io/jenkinslint).
45+
46+
There are even further examples of using the internal Jenkins API in the below links:
47+
* https://github.com/jenkinsci/jenkins-scripts/tree/master/scriptler

‎groovy/bfa.groovy

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Build Failure Analyser Best Practice
4+
*/
5+
6+
import com.sonyericsson.jenkins.plugins.bfa.model.ScannerJobProperty
7+
jenkins.model.Jenkins.instance?.
8+
getAllItems()?.
9+
each {
10+
def bfa = it.getAllProperties()?.find { prop -> prop instanceof ScannerJobProperty }
11+
if (!bfa || bfa?.isDoNotScan()) {
12+
println "'${it.fullName}' is not using BFA"
13+
}
14+
}
15+
16+
println '' // Avoid printing the data from the latest closure

‎groovy/description.groovy

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Description Best Practice
4+
*
5+
* Further details:
6+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractItem.html#getDescription
7+
*/
8+
9+
jenkins.model.Jenkins.instance?.
10+
getAllItems()?.
11+
findAll { !it.getDescription() }?.
12+
each {
13+
println "'${it.fullName}' doesn't explain what it does..."
14+
}
15+
16+
println '' // Avoid printing the data from the latest closure

‎groovy/groovy_sandbox.groovy

+16
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
/*
2+
* List what Pipelines are not using Groovy Sandbox
3+
*
4+
* Further details:
5+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getPublishersList--
6+
* - http://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowJob.html#getDefinition--
7+
*/
8+
9+
jenkins.model.Jenkins.instance?.
10+
getAllItems(org.jenkinsci.plugins.workflow.job.WorkflowJob.class)?.
11+
findAll { !it.getDefinition()?.isSandbox() }?.
12+
each {
13+
println "Pipeline -> '${it.name}' doesn't use Groovy Sandbox"
14+
}
15+
16+
println '' // Avoid printing the data from the latest closure

‎groovy/label.groovy

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Label Best Practice
4+
*
5+
* Further details:
6+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getAssignedLabel
7+
* - http://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowJob.html#getAssignedLabel
8+
*/
9+
10+
jenkins.model.Jenkins.instance?.
11+
getAllItems()?.
12+
findAll { !it.getAssignedLabel() }?.
13+
each {
14+
println "'${it.fullName}' doesn't have any assigned agent/label"
15+
}
16+
17+
println '' // Avoid printing the data from the latest closure

‎groovy/logrotator.groovy

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* List what Jobs don't follow the Clean Workspace Best Practice
3+
* Further details:
4+
* - http://javadoc.jenkins-ci.org/hudson/model/Job.html#getBuildDiscarder
5+
*/
6+
7+
jenkins.model.Jenkins.instance?.
8+
getAllItems(Job.class)?.
9+
each {
10+
found = true
11+
if (it.getBuildDiscarder() )
12+
found = it.getBuildDiscarder().getArtifactDaysToKeep() < 0 &&
13+
it.getBuildDiscarder().getArtifactNumToKeep() < 0 &&
14+
it.getBuildDiscarder().getDaysToKeep() < 0 &&
15+
it.getBuildDiscarder().getNumToKeep() < 0
16+
if (found)
17+
println "'${it.fullName}' doesn't have any log rotator configuration"
18+
}
19+
20+
println '' // Avoid printing the data from the latest closure

‎groovy/maven.groovy

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/*
2+
* List what Projects are Maven types
3+
*/
4+
5+
jenkins.model.Jenkins.instance?.
6+
getAllItems(hudson.maven.MavenModuleSet.class)?.
7+
each {
8+
println "'${it.fullName}' is a Maven Project!"
9+
}
10+
11+
println '' // Avoid printing the data from the latest closure

‎groovy/pushing.groovy

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Pushing Best Practice
4+
*
5+
* Further details:
6+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getTrigger-java.lang.Class-
7+
* - http://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowJob.html#getTriggers--
8+
*/
9+
10+
jenkins.model.Jenkins.instance?.
11+
getAllItems()?.
12+
each {
13+
try {
14+
if (it.getTrigger(hudson.triggers.SCMTrigger.class) ) {
15+
println "'${it.fullName}' is polling!"
16+
}
17+
} catch (groovy.lang.MissingMethodException mme) { } // Skip items without build discarder method
18+
}
19+
20+
println '' // Avoid printing the data from the latest closure
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Pushing Best Practice and notify as a Warning Description
4+
*
5+
* Further details:
6+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getTrigger-java.lang.Class-
7+
* - http://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowJob.html#getTriggers--
8+
*/
9+
10+
def message = '''<div class="alert alert-warning">
11+
<strong>Warning!</strong> Git+Polling is deprecated. This job will be disabled from 1st, May
12+
</div>'''
13+
14+
jenkins.model.Jenkins.instance?.
15+
getAllItems()?.
16+
each {
17+
try {
18+
if (it.getTrigger(hudson.triggers.SCMTrigger.class) ) {
19+
println "INFO '${it.fullName}' is polling!"
20+
if (!it.getDescription().toLowerCase().contains('git+polling')) {
21+
it.setDescription(it.getDescription() + message)
22+
}
23+
}
24+
} catch (groovy.lang.MissingMethodException mme) { } // Skip items without build discarder method
25+
}
26+
27+
println '' // Avoid printing the data from the latest closure

‎groovy/pushing_removed_policy.groovy

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Pushing Best Practice and disable those projects.
4+
*
5+
* Further details:
6+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getTrigger-java.lang.Class-
7+
* - http://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowJob.html#getTriggers--
8+
*/
9+
10+
def message = '''<div class="alert alert-warning">
11+
<strong>Important! Git+Polling is not supported</strong>. Please read this <a href=http://>page</a>
12+
</div>'''
13+
14+
jenkins.model.Jenkins.instance?.
15+
getAllItems()?.
16+
findAll { !it.isDisabled() }. // Skip disabled jobs by default
17+
each {
18+
try {
19+
if (it.getTrigger(hudson.triggers.SCMTrigger.class) ) {
20+
println "INFO '${it.fullName}' is polling!"
21+
it.setDescription(it.getDescription() + message)
22+
it.disable()
23+
}
24+
} catch (groovy.lang.MissingMethodException mme) { } // Skip items without build discarder method
25+
}
26+
27+
println '' // Avoid printing the data from the latest closure

‎groovy/reference.groovy

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Git Reference Best Practice.
4+
*
5+
* Further details:
6+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getScm--
7+
* - http://javadoc.jenkins-ci.org/git/hudson/plugins/git/extensions/impl/CloneOption.html#getReference()
8+
*/
9+
10+
import hudson.plugins.git.extensions.impl.CloneOption
11+
jenkins.model.Jenkins.instance?.
12+
getAllItems()?.
13+
findAll { it.getScm().getType().toLowerCase().contains('git') }?.
14+
each { job ->
15+
if (job.scm.getExtensions().empty) { // When no options
16+
println "'${job.fullName}' is not using Git Reference Repo"
17+
}
18+
job.scm.getExtensions()?.findAll { it instanceof CloneOption }.each { p ->
19+
if (!p.getReference().trim()){
20+
println "'${job.fullName}' is not using Git Reference Repo"
21+
}
22+
}
23+
}
24+
25+
println '' // Avoid printing the data from the latest closure

‎groovy/shallow.groovy

+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Shallow Best Practice
4+
*
5+
* Further details:
6+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getScm--
7+
* - http://javadoc.jenkins.io/plugin/workflow-job/org/jenkinsci/plugins/workflow/job/WorkflowJob.html#getSCMs--
8+
* - http://javadoc.jenkins-ci.org/git/hudson/plugins/git/extensions/impl/CloneOption.html#isShallow()
9+
*/
10+
11+
import hudson.plugins.git.extensions.impl.CloneOption
12+
jenkins.model.Jenkins.instance?.
13+
getAllItems()?.
14+
findAll { try { it.getScm() } catch (groovy.lang.MissingMethodException mme) {} }?.
15+
findAll { it.getScm() instanceof hudson.plugins.git.GitSCM }?.
16+
each {
17+
isShallow = false
18+
if (it.getScm().getExtensions() && it.getScm().getExtensions()?.
19+
find {
20+
it instanceof CloneOption &&
21+
it.isShallow()
22+
}
23+
) {
24+
isShallow = true
25+
}
26+
if (!isShallow)
27+
println "'${it.fullName}' is not using shallow cloning"
28+
}
29+
30+
println '' // Avoid printing the data from the latest closure

‎groovy/spaces.groovy

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Space Best Practice
4+
*/
5+
6+
jenkins.model.Jenkins.instance?.
7+
getAllItems()?.
8+
findAll { it.name.contains(' ') }?.
9+
each {
10+
println "'${it.fullName}' contains spaces!"
11+
}
12+
13+
println '' // Avoid printing the data from the latest closure

‎groovy/system_exit.groovy

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* List what AbstractProjects with Groovy PostBuild actions use system.exit
3+
*
4+
* Further details:
5+
* - http://javadoc.jenkins-ci.org/hudson/model/AbstractProject.html#getPublishersList--
6+
*/
7+
8+
jenkins.model.Jenkins.instance?.
9+
getAllItems(AbstractProject.class)?.
10+
findAll { it.getPublishersList() &&
11+
it.getPublishersList().
12+
findAll { it.getClass().getName().endsWith('GroovyPostbuildRecorder') &&
13+
it.getScript()?.getScript()?.toLowerCase().contains('system.exit')}
14+
}?.each {
15+
println "'${it.fullName}' is using System Exit"
16+
}
17+
18+
println '' // Avoid printing the data from the latest closure

‎groovy/timeout.groovy

+18
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the TimeOut Best Practice
4+
*/
5+
6+
import hudson.plugins.build_timeout.BuildTimeoutWrapper
7+
jenkins.model.Jenkins.instance?.
8+
getAllItems()?.
9+
findAll {
10+
try {
11+
!it.getBuildWrappers()?.find { k,v -> v instanceof BuildTimeoutWrapper }
12+
} catch (groovy.lang.MissingMethodException mee) {} // avoid items without getBuildWrappers
13+
}?.
14+
each {
15+
println "'${it.fullName}' doesn't use Build Timeout Plugin"
16+
}
17+
18+
println '' // Avoid printing the data from the latest closure

‎groovy/workspace.groovy

+19
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/*
2+
* List what Items (Folder, FreeStylejob, Pipeline, Multijob, MavenJobs... ) don't
3+
* follow the Clean Workspace Best Practice
4+
*/
5+
6+
import hudson.plugins.git.extensions.impl.WipeWorkspace
7+
jenkins.model.Jenkins.instance?.
8+
getAllItems()?.
9+
findAll {
10+
!(it.getPublishersList()?.find {it.getClass().getName().contains('WsCleanup')}) &&
11+
!(it.getBuildWrappers()?.find{ k,v -> k.getClass().getName().contains('PreBuildCleanup') } != null ) &&
12+
!(it.scm && it.scm.getClass().getName().contains('hudson.plugins.git.GitSCM') &&
13+
it.scm.getExtensions()?.find { it instanceof WipeWorkspace } != null )
14+
}?.
15+
each {
16+
println "'${it.fullName}' is not cleaning up its workspace"
17+
}
18+
19+
println '' // Avoid printing the data from the latest closure

0 commit comments

Comments
 (0)
Please sign in to comment.