Set StashNotifier with Groovy - jenkins

I am trying to add the StashNotifier configuration to Jenkins via Groovy
import jenkins.model.*;
import org.jenkinsci.plugins.stashNotifier.*
def instance = Jenkins.getInstance()
def bitbucket = instance.getDescriptor(StashNotifier)
println "--> configure Stash Notifier..."
def bitBucketNotifier = new StashNotifier (
"https://servername:8443", //stashServerBaseUrl
"user", //credentialsId
false, //ignoreUnverifiedSSLPeer
"", //commitSha1
false, //includeBuildNumberInKey
"", //projectKey
false, //prependParentProjectKey
false //disableInprogressNotification
)
bitbucket.save()
println "--> configure Stash Notifier... done"
The xml configuration I am trying to implement is
<?xml version='1.0' encoding='UTF-8'?>
<org.jenkinsci.plugins.stashNotifier.StashNotifier_-DescriptorImpl plugin="stashNotifier#1.11.6">
<credentialsId>user</credentialsId>
<stashRootUrl>https://servername:8443/</stashRootUrl>
<ignoreUnverifiedSsl>false</ignoreUnverifiedSsl>
<includeBuildNumberInKey>false</includeBuildNumberInKey>
<prependParentProjectKey>false</prependParentProjectKey>
<disableInprogressNotification>false</disableInprogressNotification>
</org.jenkinsci.plugins.stashNotifier.StashNotifier_-DescriptorImpl>
I am new to Java and groovy, but I cannot get this to work. I feel I am close, probably missing one or two little bits.
I am trying to get Jenkins to configure upon start-up and then reconfigure itself if any changes are made to core integrations. In this case, the BitBucket server won't change but if users do make the change to point at something else, Jenkins is reconfigured to point at the correct thing

#flue42 has a great answer, though going through the JSON and FormData is a bit tough to follow. Instead you can simply write the values to their respective properties on the object and save it.
If you happened to have multiple Stash servers you wanted to notify (not suppported at the global configuration level), you'll need to override the global setting on a per job basis, see my other answer with the skeleton of doing it using the Job DSL plugin.
Perhaps the most annoying part of looking at this to implement myself was in the code it references stashServerBaseUrl (as you noted in your comment) but then the required name in the Groovy/form is stashRootUrl. The place to find the right names is right around here
#!groovy
import jenkins.model.*;
import org.jenkinsci.plugins.stashNotifier.*;
String url = 'https://stashblablablabla';
String credentials = '01111111-e222-3333-eeff-4f4444e44bc4';
def j = Jenkins.getInstance();
def stash = instance.getDescriptor(StashNotifier)
stash.stashRootUrl = url //stashServerBaseUrl
stash.credentialsId = credentials //credentialsId
stash.ignoreUnverifiedSsl = false //ignoreUnverifiedSSLPeer
stash.includeBuildNumberInKey = false //includeBuildNumberInKey
stash.projectKey = "" //projectKey
stash.prependParentProjectKey = false //prependParentProjectKey
stash.disableInprogressNotification = false //disableInprogressNotification
stash.save()

I've done something like that :
#!groovy
import jenkins.model.*;
import org.jenkinsci.plugins.*;
import net.sf.json.JSONObject;
String url = 'https://stashblablablabla';
String credentials = '01111111-e222-3333-eeff-4f4444e44bc4';
def j = Jenkins.getInstance();
def stash = j.getExtensionList(
stashNotifier.StashNotifier.DescriptorImpl.class)[0];
def formData = [
stashRootUrl: url,
credentialsId: credentials,
ignoreUnverifiedSsl: false,
includeBuildNumberInKey: false,
prependParentProjectKey: false,
disableInprogressNotification: false,
considerUnstableAsSuccess: false
] as JSONObject;
stash.configure(null, formData);
j.save();
I've figured that solution out reading that:
https://github.com/jenkinsci/stashnotifier-plugin/blob/release/1.x/src/main/java/org/jenkinsci/plugins/stashNotifier/StashNotifier.java
https://github.com/samrocketman/jenkins-bootstrap-slack/blob/master/scripts/configure-slack.groovy
It appears to be working in my test platform.

If you are looking to do it via Job DSL you can use this example from the Job DSL repo.
// notify Stash using the global Jenkins settings
job('example-1') {
publishers {
stashNotifier()
}
}
// notify Stash using the global Jenkins settings and sets keepRepeatedBuilds to true
job('example-2') {
publishers {
stashNotifier {
keepRepeatedBuilds()
}
}
}
https://github.com/jenkinsci/job-dsl-plugin/blob/master/job-dsl-core/src/main/docs/examples/javaposse/jobdsl/dsl/helpers/publisher/PublisherContext/stashNotifier.groovy

Related

Jenkins add Git Behaviors using groovy scripts

I'm creating my Jenkins instance using groovy scripts because I'm automating the Jenkins creation process. I create this script:
/* Adds a multibranch pipeline job to Jenkins */
import hudson.model.*
import hudson.util.PersistedList
import jenkins.*
import jenkins.branch.*
import jenkins.model.*
import jenkins.model.Jenkins
import jenkins.plugins.git.*
import com.cloudbees.hudson.plugins.folder.computed.PeriodicFolderTrigger
import org.jenkinsci.plugins.workflow.multibranch.*
// Create job
def env = System.getenv()
Jenkins jenkins = Jenkins.instance
String jobName = "Job"
String jobScript = "Jenkinsfile"
def job = jenkins.getItem(jobName)
// Create the folder if it doesn't exist
if (job == null) {
job = jenkins.createProject(WorkflowMultiBranchProject.class, jobName)
}
job.getProjectFactory().setScriptPath(jobScript)
// Add git repo
String id = null
String remote = env.CODE_COMMIT_URL
String includes = "*"
String excludes = ""
boolean ignoreOnPushNotifications = false
GitSCMSource gitSCMSource = new GitSCMSource(id, remote, null, includes, excludes, ignoreOnPushNotifications)
BranchSource branchSource = new BranchSource(gitSCMSource)
// Remove and replace?
PersistedList sources = job.getSourcesList()
sources.clear()
sources.add(branchSource)
job.addTrigger(new PeriodicFolderTrigger("1m"))
and paste it at $JENKINS_HOME/ref/init.groovy.d/. When I start Jenkins, by job was already created. Besides that, I need to add some Git Behaviors to my job and I'd like to know if is there a way to add Git Behaviors using groovy script?
My Git after created:
Git behaviors I'd like to add at initialization (Discover tags, Check out to matching local branch, Custom user name/e-mail address)
Thank you!
I think what you want is managed through traits (I haven't actually tried this):
import jenkins.plugins.git.traits.*
def traits = []
// Add your traits...
traits.add(new TagDiscoveryTrait())
traits.add(new LocalBranchTrait())
gitSCMSource.setTraits(traits)

how to get the trigger information in Jenkins programmatically

I need to add the next build time scheduled in a build email notification after a build in Jenkins.
The trigger can be "Build periodically" or "Poll SCM", or anything with schedule time.
I know the trigger info is in the config.xml file e.g.
<triggers>
<hudson.triggers.SCMTrigger>
<spec>8 */2 * * 1-5</spec>
<ignorePostCommitHooks>false</ignorePostCommitHooks>
</hudson.triggers.SCMTrigger>
</triggers>
and I also know how to get the trigger type and spec with custom scripting from the config.xml file, and calculate the next build time.
I wonder if Jenkins has the API to expose this information out-of-the-box. I have done the search, but not found anything.
I realise you probably no longer need help with this, but I just had to solve the same problem, so here is a script you can use in the Jenkins console to output all trigger configurations:
#!groovy
Jenkins.instance.getAllItems().each { it ->
if (!(it instanceof jenkins.triggers.SCMTriggerItem)) {
return
}
def itTrigger = (jenkins.triggers.SCMTriggerItem)it
def triggers = itTrigger.getSCMTrigger()
println("Job ${it.name}:")
triggers.each { t->
println("\t${t.getSpec()}")
println("\t${t.isIgnorePostCommitHooks()}")
}
}
This will output all your jobs that use SCM configuration, along with their specification (cron-like expression regarding when to run) and whether post-commit hooks are set to be ignored.
You can modify this script to get the data as JSON like this:
#!groovy
import groovy.json.*
def result = [:]
Jenkins.instance.getAllItems().each { it ->
if (!(it instanceof jenkins.triggers.SCMTriggerItem)) {
return
}
def itTrigger = (jenkins.triggers.SCMTriggerItem)it
def triggers = itTrigger.getSCMTrigger()
triggers.each { t->
def builder = new JsonBuilder()
result[it.name] = builder {
spec "${t.getSpec()}"
ignorePostCommitHooks "${t.isIgnorePostCommitHooks()}"
}
}
}
return new JsonBuilder(result).toPrettyString()
And then you can use the Jenkins Script Console web API to get this from an HTTP client.
For example, in curl, you can do this by saving your script as a text file and then running:
curl --data-urlencode "script=$(<./script.groovy)" <YOUR SERVER>/scriptText
If Jenkins is using basic authentication, you can supply that with the -u <USERNAME>:<PASSWORD> argument.
Ultimately, the request will result in something like this:
{
"Build Project 1": {
"spec": "H/30 * * * *",
"ignorePostCommitHooks": "false"
},
"Test Something": {
"spec": "#hourly",
"ignorePostCommitHooks": "false"
},
"Deploy ABC": {
"spec": "H/20 * * * *",
"ignorePostCommitHooks": "false"
}
}
You should be able to tailor these examples to fit your specific use case. It seems you won't need to access this remotely but just from a job, but I also included the remoting part as it might come in handy for someone else.

Inject Configuration into multiple Jenkins jobs via DSL

I have a number of maven project in Jenkins and I would like a mechanism where i can inject a piece of configuration into all of them at once.
or example if I decide to change the logRotation.
I found this can be done via the DSL plugin, but I so far I am only able to inject one project at a time.
mavenJob('EXAMPLE_TEST1') {
publishers {
textFinder(/There are test failures/, '', false, false, true)
}
}
The above works and inject a piece of config for the textFinder plugin into a maven project
How do i achieve the same for EXAMPLE_TEST2, 3, 4, 5, 6 etc
Appreciate any help
I decided to go a little further and create an array of all jobs in Jenkins
import hudson.model.*
allTests(Hudson.instance.items)
def allTests(items){
def list = []
for (item in items) {
def name = item.getName()
if (name.contains("API")){
} else {
list << item.getName()
}
}
list.each { job ->
mavenJob("${job}")
{
publishers {
textFinder(/There are test failures/, '', false, false, true)
}
}
}
}
Sorry for the above format
So this will now grab every job in Jenkins that does not contain the text API and add it to an array and will inject the configuration required.

Custom changelog in Jenkins Pipelines

I was wondering if it is possible to have a custom changelog appear for Jenkins Pipelines. Ideally, I'd like to propagate the downstream changelogs, but failing that I've tried to create a custom changelog derived from the downstream builds. However, it doesn't appear to work (with no option for viewing the pipeline's workspace either).
I was wondering if this is something that I'm just getting wrong or whether it's actually supported or not.
This is the sample code I'm testing with
node('master')
{
stage('Source')
{
build 'SourceBuild'
def rootDir = currentBuild.rawBuild.getRootDir().toString()
echo rootDir
def changelog = new File(rootDir, "changelog.xml")
PrintWriter writer = new PrintWriter(new FileWriter(changelog));
writer.println("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
writer.println("<changelog>");
writer.println(String.format("\t\t<user>%s</user>", 'User'));
writer.println(String.format("\t\t<comment>Change</comment>", 'Comment'));
writer.println("\t</changeset>");
writer.println("</changelog>");
writer.close();
}
}
Many thanks
In Jenkins pipeline, I noticed that there is a global variable named currentBuild. It has a readable property called changeSets. I would rather take this approach with pipeline instead of playing around with changelog.xml
stage('some name') {
def gitChangeSetList = currentBuild.changeSets
formatGitChangeLog(gitChangeSetList)
}
def formatGitChangeLog(GitChangeSetList changeSetList) {
def formatStr = ""
for (setItem in changeSetList) {
for (change in setItem.getLogs()) {
formatStr += "${change.getAuthor().getDisplayName()}: ${change.getMsg()}\n"
}
}
return formatStr
}
currentBuild.changeSets is of type GitChangeSetList. From the javadoc, we can derive various methods involved in GitChangeSet.

Can a Job DSL script be tested

Ideally I'd like to be able to invoke the script with some kind of unit test before I have it execute on a Jenkins.
Is there any way to test a Job DSL script other than having jenkins run it?
Besides the examples in job-dsl-gradle-example, you can also go a step further and write tests for individual files or jobs. For example let's assume you have a job configuration file located in jobs/deployJob.groovy
import javaposse.jobdsl.dsl.DslScriptLoader
import javaposse.jobdsl.dsl.MemoryJobManagement
import javaposse.jobdsl.dsl.ScriptRequest
import spock.lang.Specification
class TestDeployJobs extends Specification {
def 'test basic job configuration'() {
given:
URL scriptURL = new File('jobs').toURI().toURL()
ScriptRequest scriptRequest = new ScriptRequest('deployJob.groovy', null, scriptURL)
MemoryJobManagement jobManagement = new MemoryJobManagement()
when:
DslScriptLoader.runDslEngine(scriptRequest, jobManagement)
then:
jobManagement.savedConfigs.each { String name, String xml ->
with(new XmlParser().parse(new StringReader(xml))) {
// Make sure jobs only run manually
triggers.'hudson.triggers.TimerTrigger'.spec.text().isEmpty()
// only deploy every environment once at a time
concurrentBuild.text().equals('false')
// do a workspace cleanup
buildWrappers.'hudson.plugins.ws__cleanup.PreBuildCleanup'
// make sure masked passwords are active
!buildWrappers.'com.michelin.cio.hudson.plugins.maskpasswords.MaskPasswordsBuildWrapper'.isEmpty()
}
}
}
}
This way you are able to go through every XML node you want to make sure to have all the right values set.
Have a look at the job-dsl-gradle-example. The repo contains a test for DSL scripts.
Doing it in the same way as crasp but using Jenkins test harness as explained in Jenkins Unit Test page, which is slower but would work with auto-generated DSL giving syntax errors as explained here.
After setting the code as explained here, you can just do a test like this one:
#Unroll
void 'check descriptions #file.name'(File file) {
given:
JobManagement jobManagement = new JenkinsJobManagement(System.out, [:], new File('.'))
Jenkins jenkins = jenkinsRule.jenkins
when:
GeneratedItems items = new DslScriptLoader(jobManagement).runScript(file.text)
then:
if (!items.jobs.isEmpty()) {
items.jobs.each { GeneratedJob generatedJob ->
String text = getItemXml(generatedJob, jenkins)
with(new XmlParser().parse(new StringReader(text))) {
// Has some description
!description.text().isEmpty()
}
}
}
where:
file << TestUtil.getJobFiles()
}

Resources