Allow users to pick Green Jenkins builds to deploy - jenkins

I want to allow testers/BAT users/Ops etc to have a list of builds to pick from that they can deploy to a list of environments. The list should only contain builds that have passed all the way through our automated Jenkins Pipeline and the environment list will be a pre defined list. They should be able to pick from old and new builds. The deployment job is all setup. I was looking at writing a simple web page interface that hooks into Jenkins via the JSON API but if there is any way of doing this via Jenkins then that would be great.

You can do this:
CI build store successful artifacts in artifact repository (i.e: Artifactory)
Build has a parameter called "BuildToDeploy" or similar. That build parameter is created with Dynamic Parameter Plugin so it gets populated with list of builds from Artifactory.
Testers choose a build from a list of green artifacts.
In order to achieve step 2 as "Default value Script" of parameter you add some Groovy code that gets the artifact list from artifact repository. In Artifactory it would be something like jfrog rt list CIBuildArtifacts

Interestingly enough with Jenkins declarative pipeline you can do that in a very simple OOTB way. Although you have to twist the idea a bit.
In general for any pipeline that you would like to be able to promote you could have an extra stage using input, submitter
An optional comma-separated list of users or external group names who are allowed to submit this input. Defaults to allowing any user.
and parameters.
pipeline {
agent any
stages {
stage('Example') {
input {
message "Should we continue?"
ok "Yes, we should."
submitter "alice,bob"
parameters {
choice(name: 'DEPLOYMENT_ENV', choices: ['one', 'two', 'three'], description: 'where to deploy?')
}
}
steps {
echo "Hello, ${PERSON}, nice to meet you."
}
}
}
}

Related

This build is parameterized option missing in Jenkins

I'm trying to get a parameterized build running with Jenkins. All the tutorials point to a This build is parameterized check box like here. Other tutorials point to this documentation but after searching around I can't figure out how to get the check box to actually show up. Am I missing something?
Edit: Figured it out - the This build is parameterized check box was there all along under a different header. The Office 365 Connector plugin creates a new header that splits the general options in half. I thought that the check box was being used specifically for that plugin, but the header was just misleading.
If you looking for "This project is parameterised" option that is a native Jenkins functionality. You don't need any plugin for that. It should be under the General tab.
see my plugins list; I have not installed any plugin.
In Jenkins 2.330 (without related plugins) we see no option like This build is parameterized or This project is parameterized at repo level.
Jenkins does draw a Build with parameters button for us instead of the usual Build button, provided the Jenkinsfile declares some parameters.
At branch level, View Configuration button then shows a greyed out, enabled checkbox This project is parameterized (it is not greyed out in repos where the Jenkinsfile declares no parameters, but we opted to configure things at above-repo level so it is not clickable)
Example Jenkinsfile:
#!groovy
properties([
parameters([
booleanParam(name: 'destroy', defaultValue: false,
description: 'delete images', )
])
])
node('normal') {
if (this.env.destroy == 'true') {
sh 'echo DESTROY MODE'
} else {
sh 'echo DRY RUN'
}
}
Might have to click Scan Multibranch Pipeline Now after adding those parameters:

Using a Jenkins pipeline multiline /multi-line string parameter

I'm converting a bunch of jobs to use the Jenkins pipeline language.
In plain/normal Jenkins we can use parameter types including:
string
boolean
choice, and also
multi-line string.
A parameter using one of these types will pop up and prompt the user for input when they run the Jenkins job.
The available parameter types for Jenkins pipeline are: (According to here).
booleanParam
choice
file
text
password
run
string
There is no multiline string input parameter listed for pipeline. The Jenkins documentation say the documentation is "young" and still incomplete.
Has anyone managed to get a multi-line string input parameter working with the Jenkins pipeline?
Multi-line string parameters are in the out-of-the-box Jenkins package, but doesn't seem to be there in the pipeline.
I discovered the solution by looking at the Jenkins source code:
parameters{ text(name: 'mytextparam',
defaultValue: 'Default lines for the parameter',
description: 'A description of this param')
}
This pops up a multi-line text input prompt which becomes the parameter value which you can refer to later as params.mytextparam
This is not documented in the Jenkins Pipeline documentation, so there might be issues like it being unsupported or withdrawn in a future release. Or it could go the other way and they might document it in the next release.
There is a plugin that called:
"pipeline-syntax"
You should use it if you need some stuff for Jenkins pipeline.
1.Install the plugin: I installed it from "plugins" in my Jenkins server under "Manage Jenkins" then, Plugin Manager. source:https://wiki.jenkins.io/display/JENKINS/Pipeline+Plugin
2.You will see the plugin in the main screen of Jenkins on the left side. select it.
3.On the plugin select whatever you want for the plugin. here is an example of what you need now, check this out:
Go To Pipeline syntax dialog (/pipeline-syntax)
Select properties: Set Job Properties
6.After that press on "GENERATE PIPELINE SCRIPT".
7.copy the code (or part of it that you need) and add it to your Jenkins pipeline..
Let me know if this was helpful
Multi-line string parameters are text parameters in pipeline syntax. They are described on the Jenkins Pipeline Syntax page.
Example:
parameters { text(name: 'DEPLOY_TEXT', defaultValue: 'One\nTwo\nThree\n', description: '') }

Trigger Multibranch Job from another

I have a job in Jenkins and I need to trigger another one when it ends (if it ends right).
The second job is a multibranch, so I want to know if there's any way to, when triggering this job, pass the branch I want to. For example, if I start the first job in the branch develop, I need it to trigger the second one for the develop branch also.
Is there any way to achieve this?
Just think about the multibranch job being a folder containing the real jobs named after the available branches:
Using Pipeline Job
When using the pipeline build step you'll have to use something like:
build(job: 'JOB_NAME/BRANCH_NAME'). Of course you may use a variable to specify the branch name.
Using Freestyle Job
When triggering from a Freestyle job you most probably have to
Use the parameterized trigger plugin as the plain old downstream build plugin still has issues triggering pipeline jobs (at least the version we're using)
As job name use the same pattern as described above: JOB_NAME/BRANCH_NAME
Should be possible to use a job parameter to specify the branch name here. However I didn't give it a try, though.
Yes, you can call downstream job by adding post build step: Trigger/Call build on other projects(you may need to install "Parameterized Trigger Plugin"):
where in Parameters section you define vars for the downstream job associated with vars from current job.
Also multibranch_PARAM1 and *PARAM2 must be configured in the downstreamjob:
Sometimes you want to call one or more subordinate multibranch jobs and have them build all of their branches, not just one. A script can retrieve the branch names and build them.
Because the script calls the Jenkins API, it should be in a shared library to avoid sandbox restrictions. The script should clear non-serializable references before calling the build step.
Shared library script jenkins-lib/vars/mbhelper.groovy:
def callMultibranchJob(String name) {
def item = jenkins.model.Jenkins.get().getItemByFullName(name)
def jobNames = item.allJobs.collect {it.fullName}
item = null // CPS -- remove reference to non-serializable object
for (jobName in jobNames) {
build job: jobName
}
}
Pipeline:
pipeline {
agent any
stages {
stage('Build') {
steps {
script {
library 'jenkins-lib'
mbhelper.callMultibranchJob 'multibranch-job-one'
mbhelper.callMultibranchJob 'multibranch-job-two'
}
}
}
}
}

Adding custom job property to Jenkins job

I want to add a new mandatory job property to capture the some custom fields in the jenkins job. I searched in the plugins list but couldn't find any relevant plugin that solves the issue. Is there any plugin to solve this ? (Note: Extra columns plugin doesn't solve my usecase)
A freestyle job can be configured to build with parameters. See: https://wiki.jenkins.io/display/JENKINS/Parameterized+Build
You can configure the parameter type (string, boolean, drop down etc), give a description of the parameter and a default value. The string parameters can include validation rules:
https://wiki.jenkins.io/display/JENKINS/Validating+String+Parameter+Plugin
Though this only warns when the current parameter value does not meet the regex validation rule, it doesn't prevent the build from being submitted. If submitted in this state, however, the build will fail.
From a quick google, it appears this doesn't work for pipeline jobs, See the last comment on the plugin page url above from Miguelángel Fernández:
If you look at the implementation of class ValidatingStringParameterValue you'll see that it overrides the implementation of public BuildWrapper createBuildWrapper(AbstractBuild build) in a way that aborts if the string is invalid. This will only work on Freestyle jobs and other job types extending AbstractBuild. I'm afraid this does not apply to pipeline jobs. Maybe in your prior project you used freestyle jobs.
An alternative for freestyle jobs is to do in job validation before initiating any build steps using the 'Prepare an environment for the run' from:
https://wiki.jenkins.io/display/JENKINS/EnvInject+Plugin
You would need to write groovy to check the parameters submitted and abort the build at this point if the values aren't suitable. Something like:
def validateString = binding.variables.get('testParam')
if (!binding.variables.get('testParam').matches('\\d+')) {
println "failure of parameter validation - does not match regex"
throw new InterruptedException()
} else {
println "Validation passed carry on with build"
}
This doesn't work on pipeline builds - as the plugin is quote:
'This plugin has some known limitations. For Example, Pipeline Plugin is not fully supported.'.
But if you are using scripted pipelines you can implement something similar:
stage 'start up'
if(!env.testParam.matches('\\d+')) {
error 'failure of parameter validation - does not match regex'
}

ensure jenkins pipeline using same node for download stream job

Case:
I have 3 machine (A,B,C) for slave (sharing the same node label e.g 'build')
I have a pipeline which may trigger different downstream job. And i need to make sure that all the job and downstream job using same node (for sharing some file etc.). How i can do that?
a) I pass the node label to downstream but i am not sure if the downstream will take the same node.(parent job using slave "A" and i pass the node label 'build' to downstream job but maybe in downstream job it take slave 'B')
b) is that some way to get the runtime slave when the pipeline is executing, when i pass this slave name to downstream?
or is that any better way to do that?
I advice you to try NodeLable Parameter Plugin.
Once installed, check 'This project is parametrized' option and select 'node' from 'Add Parameter' drop down.
It will populate all nodes as drop down while building job with parameters.
It also have some other options which may help you.
Most important question to me would be: Why do they need to run on the very same node?
Anyway. One way to achieve this would be to retrieve the name of the node in the node block in the first pipeline, like (CAUTION: was not able to verify code written below):
// Code for upstream job
#NonCPS
def getNodeName(def context) {
context.toComputer().name
}
def nodeName = 'undefined'
node('build') {
nodeName = steps.getContext(FilePath)
}
build job: 'downstream', parameters: [string(name: 'nodeName', value: nodeName)]
In the downtstream you use that string parameter as input to your node block - of course you should make sure that the downstream actually is parameterized in the first place having a string parameter named nodeName:
node(nodeName) {
// do some stuff
}
Even having static agents, workspaces are eventually cleaned up, so don't rely on existence of files in the workspace on your builds.
Just archive whatever you need in the upstream job (using the archive step) and then use Copy Artifact Plugin in downstream jobs to get what you need there. You'll probably need to parameterize downstream jobs to pass them the reference to the upstream artifact(s) you need (there are plenty of selectors available in the Copy Artifact plugin that you can play with to achieve what you want.
If you are triggering child jobs manually from pipeline, then you can use syntax as this to pass the specific node label
build job: 'test_job', parameters: [[$class: 'LabelParameterValue', name: 'node', label: 'tester1']]
build job: 'test_job', parameters: [[$class: 'LabelParameterValue', name: 'node', label: 'tester2']]
current label of node you should be able to get this way ${env.NODE_NAME}"
found at How to trigger a jenkins build on specific node using pipeline plugin?
ref. to docs- https://jenkins.io/doc/pipeline/steps/pipeline-build-step/
But yes, if you want to manipulate with some files from this job in other jobs, then you will need to use eg. mentioned copy artifacts plugin, because workspaces of the jobs are independent and each job will have different content.

Resources