Currently I am trying to implement examples for both continuous delivery and deployment using Kubernetes and Jenkins. I have successfully implemented continuous deployment. Automatically, my REST API is deploying to my Kubernetes cluster via Jenkins. Both test and prod namespaces are deploying.
Now I am trying to implement continuous delivery by making a manual user approval before releasing to prod namespace. Means implement a manual approval by implementing one switch in between test and prod environments.
For more clarity I am adding here screenshots I got while I am exploring,
Continuous Delivery & Continuous Deployment Difference in Manual Approval
Here my confusion is that, when I am implementing the delivery, how I can add the user interaction? Do I need to change any parameter in my deployment.yaml or service.yaml? Or do I need to change anything when I am creating my Jenkins pipeline job in Jenkins UI?
I am new to the continuous delivery side. Can anyone suggest any documentation or tutorials or any method to explore please?
You can use the Jenkins Input Step to do something like this. Input step coupled with a try/catch will enable you fairly good control over success/failure of the job also.
The example below is from CloudBees support portal and uses the input box, captures the input and uses that input value to set the success/failure of the current build
def userInput
try {
userInput = input(
id: 'Proceed1', message: 'Was this successful?', parameters: [
[$class: 'BooleanParameterDefinition', defaultValue: true, description: '', name: 'Please confirm you agree with this']
])
} catch(err) { // input false
def user = err.getCauses()[0].getUser()
userInput = false
echo "Aborted by: [${user}]"
}
node {
if (userInput == true) {
// do something
echo "this was successful"
} else {
// do something else
echo "this was not successful"
currentBuild.result = 'FAILURE'
}
}
We are using a shared library in Jenkins. We will pause the pipeline for 1 day and send mail to Approval DL mention in AD with the link. If not approval timely we will terminate deployment.
Approval has to login jenkins using the link to the approval of the deployment. (we thought about direct approval link but it is a security risk.)
timeout(time: 1, unit: "DAY")
{
log("Send an email to approvers#example.net with link)
sendEmail()
def inputResult = input (
id: "123",
message: "I approve this deployment",
)
}
Related
We have two environments, qa and dev, and that is configured as parameters in Jenkinsfile. Plugin Role-based Authorization Strategy is enabled, and there are two groups of users, qa and dev (same as environment). The problem here is that qa users can start to build jobs with dev environment. Is there any way that we restrict this behavior?
Here is a simple example:
pipeline {
agent any
choice(name: 'environment', choices: ['dev', 'qa']
stages {
stage('test') {
script {
if (params.environment == 'dev' && env.BUILD_USER_ID not in env.BUILD_USER_GROUPS) {echo "User ${env.BUILD_USER_ID} can not start build on DEV enviroment"}
else if (params.environment == 'qa' && env.BUILD_USER_ID not in env.BUILD_USER_GROUPS) {echo "User ${env.BUILD_USER_ID} can not start build on QA enviroment"}
else {echo "You can run job, You are in proper group for this enviroment"}
}
}
}
}
An example is not real, and maybe not working, but I hope that can be understood what I want to accomplish.
P.S. Documentation for this is not so good, and also can't find much more examples on web.
Instead of blocking (or failing) the execution after it started, you can use a different approach and prevent an unauthorized user to even start the build with irrelevant parameters (dev environment in this case).
To do so you can use the Extended Choice Parameter plugin, it enables you to create a select list value (multi or single select) based on the return value of a groovy script.
Then you can use the following script:
def buildUserGroup = ["group1","group 2","group3"]
def environments = ['qa'] // This default value will be available to everyone
// All the groups that the current logged in user is a member of
def currentUserGroups = hudson.model.User.current().getAuthorities()
if (currentUserGroups.any{ buildUserGroup.contains(it) }) {
environments.add("dev") // Add relevant environments according to groups
}
return environments
This way you can define the logic that will add environments according to group membership and adjusted it according to your needs. The user that builds the job wont even see the environments that he is not allowed to build and you will get the restriction you need.
In a Pipeline Job using your requirements the configuration can be simplified and will look like:
pipeline {
agent any
parameters {
extendedChoice(name: 'environment', type: 'PT_SINGLE_SELECT', description: 'Environment type', visibleItemCount: 10,
groovyScript:"return hudson.model.User.current().getAuthorities().contains('dev') ? ['dev','qa'] : ['qa']")
}
stages {
stage('test') {
....
}
}
}
Update:
If you are using the Role-based Authorization Strategy and want to use the above solution with roles instead of groups you can use the following code (based on this script in your parameter:
def environments = ['qa'] // This default value will be available to everyone
def userID = hudson.model.User.current().id // The current user it
def authStrategy = jenkins.model.Jenkins.instance.getAuthorizationStrategy()
def permissions = authStrategy.roleMaps.inject([:]){map, it -> map + it.value.grantedRoles}
// Validate current user is in the 'dev' role
if (permissions.any{it.key.name == 'dev' && it.value.contains(userID)}) {
environments.add("dev") // Add relevant environments according to groups
}
return environments
I use the Jenkins Office 365 Connector and it sends messages of the build status to MS Teams as expected.
Now I want to add the value of a Jenkins job parameter to the message.
My usecase: I use a single job to deploy several services. I want to know in the message which service was deployed.
Notification from Dev_Deploy
Latest status of build #43
Status
Build Success
Remarks
Started by user XXX
Service
service-abc
I've seen in the Advanced configuration that there are Macros and Fact Definitions. Unfortunately there is no documentation in the plugin docs. Perhaps this configuration could help?
There is no option to customize the message in the jenkins GUI.
But a custom message can be specified in the pipeline script:
steps {
// some instructions here
office365ConnectorSend webhookUrl: 'https://outlook.office.com/webhook/123456...',
message: 'Application has been [deployed](https://uat.green.biz)',
status: 'Success',
color: '#0000FF'
}
Hint: The status color is not automatically set. So you have to set the color depending on the status.
Official documentation
In order to get the repository data, you can follow instructions to create a checkout snippet through the Jenkins UI in the configuration.
Once you input the correct URL, browser, and so on, you may invoke the office365ConnectorSend plugin. You may adapt the card sent by passing the factDefinitions attribute an array of [name,template] objects as outlined in Jenkins Docs. You can find an example in the open-source code readme.
there are some defaulted add-ons, but this should set you on the correct path.
Here is an example of my office365ConnectorSend:
office365ConnectorSend (
webhookUrl: "${webhookURL}",
color: "${currentBuild.currentResult} == 'SUCCESS' ? '00ff00' : 'ff0000'",
factDefinitions:[
[ name: "Commit Message", template: "${commit_message}"],
[ name: "Pipeline Duration", template: "${currentBuild.durationString.minus(' and counting')}"]
]
)
What i did:
I managed to send Notifications with Status of every Build to my private Slack Channel. So i configured my Jenkins as well as my Slack app.
What i want to do:
Sending messages to other users private Channels.
What i have tried:
I added channels to my Jenkinsfile and checked them in the Slack App of Jenkins and it wasn't successful. I think i have to create sth like a Bot, which is in the specific Channel i want to send a message to. Very sure that Jenkins can't see the channel because its a private channel of another person(obviously) and is not able to find it. Couldn't find a solution for this Problem.
Thanks a lot for your help, i think i wasted way to much time trying to find an answer for that.
I setup our build pipeline to send Slack notifications to commit authors. The biggest challenge is mapping to the Slack username. I had every developer on the team change their git user.name to match their Slack Display name. This is the most straight-forward way I know to make this work.
git config --global user.name "Mona Lisa" where "Mona Lisa" is the Slack display name of the user.
In the Jenkins pipeline, I used env.GIT_COMMIT_AUTHOR to get this value back.
Note, that the environment variable provides the commit author at the HEAD of whatever was checked out. For pull requests in a multi-branch pipeline, if the PR is not a fast forward, the commit is what the merge would produce, resulting in an author of 'Jenkins'. So, in that case, you would need the author from HEAD~1
In my experience sending Slack messages to a private channel requires OAuth. I have only succeeded sending to private channels via slackSend() when Jenkins is added to Slack as a bot and invited to the channel.
Here's an example pipeline that works:
#!/usr/bin/env groovy
pipeline {
agent {
node {
label "master"
}
}
stages {
stage('Send Notification') {
steps {
script {
def color = "${params.MESSAGE_STATUS}" == "GOOD"? "good" : "warning"
slackSend(color: "${color}", message: "${params.MESSAGE}", channel: "${params.CHANNEL}")
}
}
}
}
parameters {
string(name: 'MESSAGE', defaultValue: 'Hello')
string(name: 'CHANNEL', defaultValue: '#test_private')
choice(name: 'MESSAGE_STATUS', choices: ['GOOD', 'WARNING'], description: '')
}
}
Sending via bots etc. hasn't been successful as Slack reports the channel as non-existant.
I can find tons of information in the internet about integrating HipChat in a scripted Jenkins pipeline. So that works fine for me. But how can I post a status message to HipChat that contains an element to trigger an action back in Jenkins?
Currently I have input steps in Jenkins to approve a deployment to the next stage, e.g. PROD.
I also send a HipChat message if approval is needed which contains a link to JENKINS. That looks like this:
hipchatSend color: "${color}", notify: true, room: "Jenkins Team FooBar", message: "${env.JOB_NAME}#${env.BUILD_NUMBER}: ${message}", textFormat: true
/************** PROD **************/
stage ('Approval for PROD') {
try {
timeout(time: approvalTime, unit: approvalTimeUnit) {
input 'Do you approve the deployment to PROD?'
}
} catch (Exception ex) {
finishBuild = true
}
}
// Stop build if flag was set
if (finishBuild)
return
How can I define actions in that hipChat message? Is there a way that I can approve the next build step within HipChat?
I have not found a tutorial or documentation on how to define other kinds of hipchat messages with this plugin.
I could send a POST request to JENKINS if the message would contain standard HTML. Any ideas on how to do that?
How would it work with cards?
Thanks in advance.
Is it possible to access information about committers and/or culprits of a Jenkins workflow job when checking out from one or more SCMs (either via checkout() or other SCM steps like git/svn)?
The intention is to use that information to notify committers and/or culprits about the job status, for example in a mail step.
A small example of a workflow definition:
node {
// checkout from one or more SCMs, e.g.
git url: '<URL>'
checkout([$class:...])
...
// how can we know about committers or culprits at this point?
$committers = ??
// send a mail to committers or culprits
mail to: '$committers', subject: 'JENKINS', body: '<information about the job status>'
}
How could this be adapted to get a collection of the committers after running the SCM steps?
Edit:
I am currently working with Jenkins version 1.596.2 and Workflow: Aggregator version 1.6 and it seems this is an open issue in JENKINS-24141
This is now possible using the email-ext plugin.
def to = emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'DevelopersRecipientProvider'],
[$class: 'RequesterRecipientProvider']])
if (to != null && !to.isEmpty()) {
mail to: to, subject: "JENKINS", body: "See ${env.BUILD_URL}"
}
However, if you just want to send an email on failures, you may want to use Mailer (based on the email-ext pipeline examples):
step([$class: 'Mailer',
notifyEveryUnstableBuild: true,
recipients: emailextrecipients([[$class: 'CulpritsRecipientProvider'],
[$class: 'RequesterRecipientProvider']])])
Using groovy within a pipeline script:
#NonCPS // Necessary to allow .each to work.
def changelist() {
def changes = ""
currentBuild.changeSets.each { set ->
set.each { entry ->
changes += "${entry.commitId} by ${entry.author.fullName}\n"
}
}
changes
}
similar to the answer from #szym, but without the #NonCPS required:
def authors = currentBuild.changeSets.collectMany { it.toList().collect { it.author } }.unique()
As you found, pending JENKINS-24141 this is not supported. Changes to Jenkins core are required.
You can get the xml info for a job in which you will find the name of the person who committed the change along with the commit messages.
http://<Jenkins URL>:<Port Number>/job/<Jobname>/<BuildNumber>/api/xml?
Give this a go in your browser. Search for "user".
You can dump this information in a text file to process.
It seems that this feature was implemented inside the email-ext plugin but the author forgot to document the way we are supposed to use this.
Please check https://issues.jenkins-ci.org/browse/JENKINS-34763 -- and add a comment there, asking for an example. I already did.
You can fetch committers email :
committerEmail = sh (
script: 'git --no-pager show -s --format=\'%ae\'',
returnStdout: true
).trim()
and send:
emailext body: 'text you choose', subject: 'subject you choose', recipientProviders: [[$class: 'DevelopersRecipientProvider']], to: committerEmail
taken from : https://medium.com/#dilunika/find-the-git-commit-user-jenkins-pipeline-b6790613f8b5
In the emailext plugin you can provide culprits, developers, requestor etc in the recipientProviders directly.
emailext body: '',
recipientProviders: [culprits(),
developers(),
brokenBuildSuspects(),
brokenTestsSuspects(),
requestor()],
subject: ''
Description
Culprits: Sends email to the list of users who committed a change since the last non-broken build till now. This list at least always include people who made changes in this build, but if the previous build was a failure it also includes the culprit list from there.
Developers: Sends email to all the people who caused a change in the change set.
Broken Build suspects: Sends email to the list of users suspected of causing the build to begin failing.
Broken Test suspects: Sends email to the list of users suspected of causing a unit test to begin failing. This list includes committers and requestors of the build where the test began to fail, and those for any consecutive failed builds prior to the build in which the test began to fail.
Source: Jenkins Pipeline Syntax - Snippet Generator
If you want to notify the culprits who broke the build, You do not need to any checks, Use email plugin in jenkins. This plugin gives you option to send mails to commiter between past good build and current broken build.
If you are using "Editable email notifier plugin" You get option of send mail to culprit.
If you are using email plugin then you get the option "Send separate e-mails to individuals who broke the build".