New job on Jenkins on creation of new branch in BitBucket - jenkins

I have integrated my BitBucket to my Jenkins. Is there a way to trigger a new job creation in Jenkins when a new branch is created in BitBucket?. The job name should be same as the new branch created. Can I do it with scripts, or Jenkins CLI or using BitBucket API.
I am new to Jenkins, any help would be appreciated.

Sure. This could be done. I recommend you to look at Job DSL Plugin. This is really convenient plugin. Moreover you could also put your job scripts under version control system (VCS).
All scripting is done in Groovy language. Find example below:
def project = 'quidryan/aws-sdk-test'
def branchApi = new URL("https://api.github.com/repos/${project}/branches")
def branches = new groovy.json.JsonSlurper().parse(branchApi.newReader())
branches.each {
def branchName = it.name
def jobName = "${project}-${branchName}".replaceAll('/','-')
job(jobName) {
scm {
git("git://github.com/${project}.git", branchName)
}
steps {
maven("test -Dproject.name=${project}/${branchName}")
}
}
}
Also take a look at online job playground for this plugin - Jenkins Job DSL Playground.
It is just a recommendation where to look at. Probably you will have more concrete questions on this topic. But definitely take a look at this plugin.

Related

Multibranch Pipeline in Jenkins with SVN

I have SVN as my SCM. The SVN Root URL structure is as follows.
https://svn.domain.com/orgName
Under this, I have a folder called "test". Then I have tags, branches and trunk. For example,
https://svn.domain.com/orgName/test/trunk
https://svn.domain.com/orgName/test/branches
Under trunk and branches, I have various modules. One module is Platform which is the core module. The URL structure for my project under Platform is as follows.
https://svn.domain.com/orgName/test/trunk/Platform/MyProject
https://svn.domain.com/orgName/test/branches/Platform/1.0.0.0/MyProject
Not sure if the above structure is correct or not. But this is how it is structured in my organization and it can't be changed. Now, I have the following questions.
At what level should I maintain the Jenkinsfile?
How should I pass the branch name (including trunk) to this file?
It will be great if someone can provide some details (if possible step by step) on how to use Multibranch pipeline with SVN. Unfortunately, I could not find any tutorial or examples to achieve this.
I figured this out on my own. Here are the details, in case, someone needs help.
For Trunk, add the Jenkinsfile inside trunk/Platform (in my case) and for Branches, add Jenkinsfile inside branches/Platform/ folder. For branches, it is better to keep the Jenkinsfile inside each version folder since it has some benefits. This approach will create a Jenkins job for each version.
In the Jenkins job (for multibranch pipeline), add the base url for Project Repository Base. In my case, it is https://svn.domain.com/orgName/test. In Include branches field, add trunk/Platform, branches/Platform/* in my case. In Jenkinsfile, to get branch name, use the built in variable $BRANCH_NAME. This gives trunk/Platform for trunk and branches/Platform/1.0.0.0 (for example) for branches.
Only challenge is that job names are created like Trunk/Platform, Branches/Platform/1.0.0.0. So the workspace gets created like Trunk%2FPlatform, Branches%2FPlatform%2F1.0.0.0 since "/" gets encoded with %2F. While using in jobs, make sure the job name is appropriately modified using the below code.
def cws = "${WORKSPACE_DIR}\\" + "${JOB_NAME}".replace("%2F","_").replace("/","\\")
echo "\u2600 workspace=${cws}"
def isTrunk = "${JOB_NAME}".toLowerCase().contains("trunk")
def version = ""
def verWithBldNum = ""
echo "\u2600 isTrunk=${isTrunk}"
if(!isTrunk)
{
version = "${JOB_NAME}".substring("${JOB_NAME}".lastIndexOf("%2F") + 3, "${JOB_NAME}".length())
echo "\u2600 version=${version}"
verWithBldNum = "${version}".substring(0, "${version}".lastIndexOf('.') + 1) + "${BUILD_NUMBER}"
echo "\u2600 verWithBldNum=${verWithBldNum}"
}
else
{
echo "\u2600 Branch is Trunk"
}

Jenkins and Nexus Repository Manager Choice Parameter

I know there is a Nexus Platform plugin https://plugins.jenkins.io/nexus-jenkins-plugin/ in Jenkins but I am not sure if the below is possible any advise or suggestions would be appreciated.
In Jenkins you have Git choice parameter this allows you to build specific tags / branches within your job is there something similar for Sonatype Nexus? We have an internal nexus where we upload and tag docker images.
I currently have a Jenkins job I have to manually type in the image version.
Is there a way in Jenkins to get a choice parameter where i can query all the tags in nexus.
So for example I can run the command - > docker pull internal/application/service:0.0.1
So the developers would upload a new version for example 0.0.2
From Jenkins I would like to display a list of 0.0.1 or 0.0.2 for the support team to build.
Not sure if this is currently possible ?
Update 2020/07/15
I have read up on the active choice paramater plugin. This allows you to execute a groovy script.
So i created the below
import groovy.json.JsonSlurper
// GET
try {
def get = new URL("http://internalserver:8081/service/rest/v1/search?repository=docker-internal&name=application/service/moo").openConnection();
def getRC = get.getResponseCode();
//println(getRC);
if (getRC.equals(200)) {
//println(get.getInputStream().getText());
JsonSlurper slurper = new JsonSlurper()
Map parsedJson = slurper.parseText(get.getInputStream().getText())
tags = parsedJson.items.version
//println(tags)
def sorted_tags = []
sorted_tags.push(tags)
println(sorted_tags)
}
}catch(Exception e){
println(e)
}
This code does print out the tags if i run it from my IDE but if i add it to the active choice plugin my drop down menu is blank ?
Ok i got it to work Jenkins combo box requires a return type.
So if anyone ever wants to do something similar the below worked for me.
<code>
import groovy.json.JsonSlurper
try {
def get = new URL("http://yourinternalnexusurl:8018/applicacation/v1...etc").openConnection();
def getRC = get.getResponseCode();
if (getRC.equals(200)) {
def nexus_response = [:]
nexus_response = new JsonSlurper().parseText(get.getInputStream().getText())
def image_tag_list = []
for (tag in nexus_response.items.version){
image_tag_list.add(tag)
}
return image_tag_list.sort()
}
}catch(Exception e){
println(e)
}
</code>
The Maven Artifact ChoiceListProvider (Nexus) may satisfy your requirements.
With this extension its possible to use the Service API from a Maven Repositories like Nexus, Maven-Central or Artifactory to search for artifacts using groupId, artifactId and packaging.
This plugin will let the user choose a version from the available artifacts in the repository and will publish the URL as an environment variable. The Plugin will return the full URL of the choosen artifact, so that it will be available during the build, i.E. you can retrieve the artifact by using "wget"
Example
You might then have to parse (groovy ?) the resulting env variable to feed as your parameter.

How to get latest build number from another job in jenkins pipeline

I am using jenkins pipeline 2.0, and I would like to get another job's latest successful build number.
What's the pipeline syntax to use?
You can get it this way
def buildNumber = Jenkins.instance.getItem('jobName').lastSuccessfulBuild.number
If you get a RejectedAccessException you will have to approve those methods, see In-process Script Approval
To add to Vitalii's answer, this is in case you're using Multibranch Pipeline Plugin:
def buildNumber = Jenkins.instance.getItem('jobName').getItem('branchName').lastSuccessfulBuild.number
It's so annoying to get approvals in enterprise environment(a lot of request and approvals)
So I am using following API way to get the latest build number.
import groovy.json.JsonSlurperClassic
httpRequest url: 'https://jenkinsurl.local/job/Build/api/json', outputFile: 'output.json'
def jsonFile = readFile(file: 'output.json')
def data = new JsonSlurperClassic().parseText(jsonFile)
latestBuildNumber = "${data.lastSuccessfulBuild.number}"
def build_job = build job: "Build"
build_job_number = build_job.getNumber()

Mark Jenkins Pipeline as Promoted

Last I knew, Jenkins Pipelines did not support promotions, so to work around this, I created a job called "job-name-promotion" which would gather artifacts from the job I wanted to promote, and then mark the corresponding build as "Keep Forever." Is there a way to mark the build that was kept forever as "promoted" somehow? Preferably using one of the Stars that typically denote promotions? Or even better, is there a way to add Promotion Process steps to pipelines now?
Since it appears that pipelines still do not support promotions (as of 11/21/2017), I wrote a custom groovy script to iterate over all the jobs on the Jenkins server, locate the one we wish to promote and add a gold star to the corresponding build number:
import hudson.model.*
import jenkins.model.*
import org.jvnet.hudson.plugins.groovypostbuild.GroovyPostbuildAction
def log = manager.listener.logger
build = Thread.currentThread().executable
String jobName = build.project.getName()
// note: these two variables are defined as parameters of the current job
def number = manager.build.buildVariables.get("NUMBER") as int
def buildJobName = manager.build.buildVariables.get("BUILD_JOB_NAME")
Jenkins jenkins = Jenkins.getInstance()
List<Job> projects = jenkins.getAllItems(Job.class)
for (Job project : projects) {
if (project.getName().equals("platform-lanai-pipeline")) {
log.println("Found it!")
Run usb = project.getBuildByNumber(number)
usb.getActions().add(GroovyPostbuildAction.createBadge('star-gold.png', ''))
}
}

Jenkins, how to check regressions against another job

When you set up a Jenkins job various test result plugins will show regressions if the latest build is worse than the previous one.
We have many jobs for many projects on our Jenkins and we wanted to avoid having a 'job per branch' set up. So currently we are using a parameterized build to build eg different development branches using a single job.
But that means when I build a new branch any regressions are measured against the previous build, which may be for a different branch. What I really want is to measure regressions in a feature branch against the latest build of the master branch.
I thought we should probably set up a separate 'master' build alongside the parameterized 'branches' build. But I still can't see how I would compare results between jobs. Is there any plugin that can help?
UPDATE
I have started experimenting in the Script Console to see if I could write a post-build script... I have managed to get the latest build of master branch in my parameterized job... I can't work out how to get to the test results from the build object though.
The data I need is available in JSON at
http://<jenkins server>/job/<job name>/<build number>/testReport/api/json?pretty=true
...if I could just get at this data structure it would be great!
I tried using JsonSlurper to load the json via HTTP but I get 403, I guess because my script has no auth session.
I guess I could load the xml test results from disk and parse them in my script, it just seems a bit stupid when Jenkins has already done this.
I eventually managed to achieve everything I wanted, using a Groovy script in the Groovy Postbuild Plugin
I did a lot of exploring using the script console http://<jenkins>/script and also the Jenkins API class docs are handy.
Everyone's use is going to be a bit different as you have to dig down into the build plugins to get the info you need, but here's some bits of my code which may help.
First get the build you want:
def getProject(projectName) {
// in a postbuild action use `manager.hudson`
// in the script web console use `Jenkins.instance`
def project = manager.hudson.getItemByFullName(projectName)
if (!project) {
throw new RuntimeException("Project not found: $projectName")
}
project
}
// CloudBees folder plugin is supported, you can use natural paths:
project = getProject('MyFolder/TestJob')
build = project.getLastCompletedBuild()
The main test results (jUnit etc) seem to be available directly on the build as:
result = build.getTestResultAction()
// eg
failedTestNames = result.getFailedTests().collect{ test ->
test.getFullName()
}
To get the more specialised results from eg Violations plugin or Cobertura code coverage you have to look for a specific build action.
// have a look what's available:
build.getActions()
You'll see a list of stuff like:
[hudson.plugins.git.GitTagAction#2b4b8a1c,
hudson.scm.SCMRevisionState$None#40d6dce2,
hudson.tasks.junit.TestResultAction#39c99826,
jenkins.plugins.show_build_parameters.ShowParametersBuildAction#4291d1a5]
These are instances, the part in front of the # sign is the class name so I used that to make this method for getting a specific action:
def final VIOLATIONS_ACTION = hudson.plugins.violations.ViolationsBuildAction
def final COVERAGE_ACTION = hudson.plugins.cobertura.CoberturaBuildAction
def getAction(build, actionCls) {
def action = build.getActions().findResult { act ->
actionCls.isInstance(act) ? act : null
}
if (!action) {
throw new RuntimeException("Action not found in ${build.getFullDisplayName()}: ${actionCls.getSimpleName()}")
}
action
}
violations = getAction(build, VIOLATIONS_ACTION)
// you have to explore a bit more to find what you're interested in:
pylint_count = violations?.getReport()?.getViolations()?."pylint"
coverage = getAction(build, COVERAGE_ACTION)?.getResults()
// if you println it looks like a map but it's really an Enum of Ratio objects
// convert to something nicer to work with:
coverage_map = coverage.collectEntries { key, val -> [key.name(), val.getPercentageFloat()] }
With these building blocks I was able to put together a post-build script which compared the results for two 'unrelated' build jobs, then using the Groovy Postbuild plugin's helper methods to set the build status.
Hope this helps someone else.

Resources