How can I add job description in Jenkins 2 multi-branch pipeline? - jenkins

I have a multi-branch pipeline job in Jenkins 2, connected to a GitHub repository (available here). Each pull request in the GitHub repository creates a new "job" in Jenkins, but the job inherits its name from the pull request number (i.e. jobs are called PR-1, PR-2, and so on) which is meaningless in a Jenkins context.
Is it possible (and how) to configure the job or Jenkinsfile to add a job description to each pull request ?

Here is how I was able to set the job description from the content of the pull request :
if (env.BRANCH_NAME.startsWith('PR')) {
def resp = httpRequest url: "https://api.github.com/repos/xxx/yyy/pulls/${env.BRANCH_NAME.substring(3)}"
def ttl = getTitle(resp)
def itm = getItem(env.BRANCH_NAME)
itm.setDisplayName("PR '${ttl}'")
}
}
#NonCPS
def getItem(branchName) {
Jenkins.instance.getItemByFullName("sonar-openedge/${branchName}")
}
#NonCPS
def getTitle(json) {
def slurper = new groovy.json.JsonSlurper()
def jsonObject = slurper.parseText(json.content)
jsonObject.title
}
This allows having job description available directly from the job overview page (as in this example: https://ci.rssw.eu/job/sonar-openedge/ )
The full commit and Jenkinsfile are available here:
https://github.com/Riverside-Software/sonar-openedge/commit/e2c76ca58b812e4ceac65c406f0b2aae9fbf3f5f

Related

Jenkins Pipeline dynamically set parameter based on Artifactory trigger URL

I have a pipeline job that triggers when finding changes in Artifactory at a specific path. I want to pass the Artifactory url value to a parameter (my goal for this job is to allow users to manually build this job and enter a path as well as have this job automatically trigger when changes are found in a specific path in Artifactory and pass that value to the parameter).
node {
def server
def rtTriggerUrl = currentBuild.getBuildCauses('org.jfrog.hudson.trigger.ArtifactoryCause')[0]?.url
stage ('Artifactory configuration') {
server = Artifactory.server 'artifactory-1'
}
stage('Trigger build') {
server.setBuildTrigger spec: "H/2 * * * *", paths: "maven-examplerepo-local/path/to/jar"
}
}
pipeline {
parameters {
string(
name: 'JAR_LOCATION',
defaultValue: rtTriggerUrl,
trim: true,
description: 'Artifactory URL of jar'
I have tried setting it a couple different ways:
defaultValue: rtTriggerUrl
defaultValue: "${currentBuild.getBuildCauses('org.jfrog.hudson.trigger.ArtifactoryCause')[0]?.url}"
However these gave blank or null values (I also tried setting the rtTriggerUrl function before node to see if that'd make it available to the parameter but that didn't work either).
Has anyone figured out how to do this? As a workaround I created an upstream job that triggers when changes are in Artifactory, then it triggers the downstream job and passes the url value to the downstream job's parameter. I wanted to see if I could combine that logic into one job.

Jenkins Remote Access API: Retrieve up-to-date parameter choices

I'm currently building my choices depending on available agents and its labels in a pipeline:
def loadConfigurations() {
def configurations = [];
def jenkins = Jenkins.instance;
def onlineComputers = jenkins.computers.findAll { it.online };
def availableLabels = onlineComputers.collect {
it.assignedLabels.collect { LabelAtom.escape(it.expression) } }
.flatten().unique(false);
def lineage16Configurations = ['samsung:klte:lineage:16.0'];
if (availableLabels.containsAll(['lineage', '16.0'])) {
configurations.addAll(lineage16Configurations);
}
return configurations;
}
def configurations = loadConfigurations();
pipeline {
agent { label 'master' }
parameters {
choice name: 'CONFIG', choices: configurations, description: 'Configuration containing vendor, device, OS and its version. Each separated by a colon.'
}
//...
Now, lets say all agents are offline, when requesting the remote access API I don't get up-to-date choices cause they're only updated when starting a build. Is there any existing way to retrieve them somehow through remote access API or do I need to write my own plugin which adds a new endpoint for the remote access API?
I've already tried the Active Choices Parameter and the Extended Choice Parameter without success. Both don't display any choices in the API.
I was playing around with the Extensible Choice Parameter and created a Pull Request which exposes the choiceList to the Remote Access API. The API was then returning changed choices without building the job.

Can I access current stage id in Jenkins pipeline?

I'm using shared library to build CI/CD pipelines in Jenkins. And in my case, some of the stages need to send the execute info through web apis. In this case, we need to add stage id for current stage to api calls.
How can I access the stage id similar with ${STAGE_NAME}?
I use Pipeline REST API Plugin as well as HTTP Request Plugin
Your methods in Jenkinsfile can look like:
#NonCPS
def getJsonObjects(String data){
return new groovy.json.JsonSlurperClassic().parseText(data)
}
def getStageFlowLogUrl(){
def buildDescriptionResponse = httpRequest httpMode: 'GET', url: "${env.BUILD_URL}wfapi/describe", authentication: 'mtuktarov-creds'
def buildDescriptionJson = getJsonObjects(buildDescriptionResponse.content)
def stageDescriptionId = false
buildDescriptionJson.stages.each{ it ->
if (it.name == env.STAGE_NAME){
stageDescriptionId = stageDescription.id
}
}
return stageDescriptionId
}
Questiion is old but i found the solution: use some code from pipeline-stage-view-plugin( looks like it is already installed in jenkins by default)
we can take current job ( workflowrun ) and pass it as an argument to
com.cloudbees.workflow.rest.external.RunExt.create , and whoala: we have object that contains info about steps and time spent on it's execution.
Full code will looks like this:
import com.cloudbees.workflow.rest.external.RunExt
import com.cloudbees.workflow.rest.external.StageNodeExt
def getCurrentBuildStagesDuration(){
LinkedHashMap stagesInfo = [:]
def buildObject = com.cloudbees.workflow.rest.external.RunExt.create(currentBuild.getRawBuild())
for (StageNodeExt stage : buildObject.getStages()) {
stagesInfo.put(stage.getName(), stage.getDurationMillis())
}
return stagesInfo
}
Function will return
{SomeStage1=7, SomeStage2=1243, SomeStage3=5}
Tested with jenkins shared library and Jenkins 2.303.1
Hope it helps someone )

Bitbucket Jenkins plugin constructs wrong push URL

We use Bitbucket server and want to trigger a Jenkins build whenever something is pushed to Bitbucket.
I tried to set up everything according to this page:
https://wiki.jenkins.io/display/JENKINS/BitBucket+Plugin
So I created a Post Webhook in Bitbucket, pointing at the Jenkins Bitbucket plugin's endpoint.
Bitbucket successfully notifies the plugin when a push occurs. According to the Jenkins logs, the plugin then iterates over all jobs where "Build when a change is pushed to BitBucket" is checked, and tries to match that job's repo URL to the URL of the push that occurred.
So, if the repo URL is
https://jira.mycompany.com/stash/scm/PROJ/project.git, the plugin tries to match it against
https://jira.mycompany.com/stash/PROJ/project, which obviously fails.
As per official info from Atlassian, Bitbucket cannot be prevented from inserting the "/scm/" part in the path.
The corresponding code in the Bitbucket Jenkins plugin is in class com.cloudbees.jenkins.plugins.BitbucketPayloadProcessor:
private void processWebhookPayloadBitBucketServer(JSONObject payload) {
JSONObject repo = payload.getJSONObject("repository");
String user = payload.getJSONObject("actor").getString("username");
String url = "";
if (repo.getJSONObject("links").getJSONArray("self").size() != 0) {
try {
URL pushHref = new URL(repo.getJSONObject("links").getJSONArray("self").getJSONObject(0).getString("href"));
url = pushHref.toString().replaceFirst(new String("projects.*"), new String(repo.getString("fullName").toLowerCase()));
String scm = repo.has("scmId") ? repo.getString("scmId") : "git";
probe.triggerMatchingJobs(user, url, scm, payload.toString());
} catch (MalformedURLException e) {
LOGGER.log(Level.WARNING, String.format("URL %s is malformed", url), e);
}
}
}
In the JSON payload that Bitbucket sends to the plugin, the actual checkout URL doesn't appear, only the link to the repository's Bitbucket page. The above method from the plugin appears to construct the checkout URL from that URL by removing everything after and including projects/ and adding the "full name" of the repo, resulting in the above wrong URL.
Official info from Atlassian is that Bitbucket cannot be prevented from adding the "scm" part to the checkout URL.
Is this a bug in the Jenkins plugin? If so, how can the plugin work for anyone?
I found the reason for the failure.
The issue is that the Bitbucket plugin for Jenkins does account for the /scm part in the path, but only if it's the first part after the host name.
If your Bitbucket server instance is configured not under its own domain but under a path of another service, matching the checkout URLs will fail.
Example:
https://bitbucket.foobar.com/scm/PROJ/myproject.git will work,
https://jira.foobar.com/stash/scm/PROJ/myproject.git will not work.
Someone who also had this problem has already created a fix for the plugin, the pull request for which is pending: JENKINS-49177: Now removing first occurrence of /scm

How to get the last build number from a Trigger/call builds on other projects if a multibranch pipeline Build is called?

I use the Parameterized Trigger Plugin for Jenkins to trigger a Multibranch Pipeline project (RED Outlook Addin). After the build has finished I want to copy the artifacts via Copy Artifact Plugin.
I Add a build step "copy artifacts from another project" with project name "RED Outlook Addin/${CIOS_BRANCH_NAME}" because I get the branch name as a parameter. This works if I specify the build number like "12". But if I set the build number to $TRIGGERED_BUILD_NUMBER_RED_Outlook_Addin_${CIOS_BRANCH_NAME} I get this error: Unable to find project for artifact copy.
How can I call the $TRIGGERED_BUILD_NUMBER_ Parameter with the specified branch?
Thx for help
Chris
You could query the json api of your jenkins server, for example using httpRequest plugin:
#NonCPS
def parseJson(String text) {
def sup = new JsonSlurper()
def json = sup.parseText(text)
sup = null
return json
}
def getLastStableBuildNumber(String project, String branchName = 'master') {
def response = httpRequest url: "http://jenkins/job/${project}/job/${branchName}/lastStableBuild/api/json", validResponseCodes: '200'
def json = parseJson(response.content)
return json.number
}

Resources