Fetching github payload in jenkinsfile - jenkins

Need some help on fetching the GitHub payload into the Jenkins file without installing any plugin.
If anyone can provide the Jenkins file code snippet to access the GitHub payload from the webhook. it would be of great help.
I am able to call the Jenkins job from GitHub webhook. but need the payload as well to process further.
Any help would be appreciated. Thanks.

Please find the below groovy script:
stage('Pull Request Info') {
agent {
docker {
image 'maven'
args '-v $HOME/.m2:/home/jenkins/.m2 -ti -u 496 -e MAVEN_CONFIG=/home/jenkins/.m2 -e MAVEN_OPTS=-Xmx2048m'
}
}
steps {
script {
withCredentials([usernameColonPassword(credentialsId: "${env.STASH_CREDENTIAL_ID}",
variable: 'USERPASS')]) {
def hasChanges = maven.updateDependencies()
if (hasChanges != '') {
def pr1 = sh(
script: "curl -s -u ${"$USERPASS" } -H 'Content-Type: application/json' https://xx.example/rest/some/endpoint",
returnStdout: true
)
def pr = readJSON(text: pr1)
println pr.fromRef
}
}
}
}
}
Above script uses, curl to fetch the details about Pull request. I have stored the credentials in the jenkins and created an environment variable for the credentialId.
You can replace the url with your endpoint. You can also modify the script to use jq if you have jq installed in the machine.
In this case, I'm using readJSON to parse the JSON which is part of pipeline utilities plugin. My question would be, why not use the plugin as it provides the needed functionalities?
If you still dont want to use plugin, take a look at json parsing with groovy.

Related

How can use File Spec in an API Call in Jfrog

I have a question about how to use File Sepc in an API Call in JFrog.
I used Jenkins Artifactory Plugin to upload or download artifacts to JFrog, I try to rewrite the function using JFrog API (GET/PUT) to do the same thing.
but I have now a problem, for some artifacts I used file Spec to set some properties and finally I upload this file spec.
"files": [
{
"pattern": "${file}",
"target": "${target}" """
if (runID) {
uploadSpec += """,
"props": "artifactId=${runID}"
"""
}
uploadSpec += """
}
]
as you can see this artifactId.
in this case when I use JFrog API to upload artifacts how should I set properties?
sh """
curl -sSf -u user:pw -X PUT -T ${zipFile} 'https://${config.artifactory.name}.xxxx:443/artifactory/${path}'
"""
How can I call put api and set "props": "artifactId=${runID}"
any solutions??
First - if you can use the JFrog CLI - you should use it, because it makes it simpler and provides some advanced features out-of-the-box, such as batch parallel uploads/downloads, file-specs, attaching properties, build-info, authentication, etc.
If you still want to use the Artifactory API directly for setting properties, which is indeed a viable good option, you can do one of the following:
Add the properties as matrix parameters as part of the upload (deploy) API call.
In your case, it should be something like:
sh """
curl -sSf -u user:pw -X PUT -T ${zipFile} 'https://${config.artifactory.name}.xxxx:443/artifactory/${path};artifactId=${runID}'
"""
Note the ;key=value in the end of the URL.
Do a second call, after the upload, to set the item properties.
In your case, it should be something like:
Using the set item properties API -
sh """
curl -sSf -u user:pw -X PUT 'https://${config.artifactory.name}.xxxx:443/artifactory/api/storage/${path}?properties=artifactId=${runID}'
"""
or, using the update item properties API-
sh """
curl -sSf -u user:pw -X PATCH 'https://${config.artifactory.name}.xxxx:443/artifactory/api/metadata/${path}' -d '{ "props": { "artifactId" : "${runID}" } }'
"""
For more information, see:
Working with JFrog Properties
Using Properties in Deployment and Resolution
Artifactory REST API - Item Properties

Unable to get the payload from GitHub web hook trigger in jenkins pipeline

I have configured a Github web hook with the below settings:
Payload URL: https:///github-webhook/
Content Type: application/x-www-form-urlencoded
Events : Pushes, Pull Requests
The Jenkins job that I have, is a pipeline job that has the below enabled:
Build Trigger: GitHub hook trigger for GITScm polling
With the above configuration, I see that in response to an event ie; push/PR in GitHub, the jenkins job gets triggered successfully. In GitHub, under Recent Deliveries for the web hook, I see the details of the payload and a successful Response of 200.
I am trying to get the payload in Jenkins Pipeline for further processing. I need some details eg: PR URL/PR number, refs type, branch name etc for conditional processing in the Jenkins Pipeline.
I tried accessing the "payload" variable (as mentioned in other stack overflow posts and the documentations available around) and printing it as part of the pipeline, but I have had no luck yet.
So my question is, How can I get the payload from GitHub web hook trigger in my Jenkins Pipeline ?
You need to select Content type: application/json in your webhook in GitHub. Then you would be able to access any variable from the payload GitHub sends as follows: $. pull_request.url for pr url, for example.
Unsure if this is possible.
With the GitHub plugin we use (Pipeline Github), PR number is stored in the variable CHANGE_ID.
PR URL is pretty easy to generate given the PR number. Branch name is stored in the variable BRANCH_NAME. In case of pull requests, the global variable pullRequest is populated with lots of data.
Missing information can be obtained from Github by using their API. Here's an example of checking if PR is "behind", you can modify that to your specific requirements:
def checkPrIsNotBehind(String repo) {
withCredentials([usernamePassword(credentialsId: "<...>",
passwordVariable: 'TOKEN',
usernameVariable: 'USER')]) {
def headers = ' -H "Content-Type: application/json" -H "Authorization: token $TOKEN" '
def url = "https://api.github.com/repos/<...>/<...>/pulls/${env.CHANGE_ID}"
def head_sha = sh (label: "Check PR head SHA",
returnStdout: true,
script: "curl -s ${url} ${headers} | jq -r .head.sha").trim().toUpperCase()
println "PR head sha is ${head_sha}"
headers = ' -H "Accept: application/vnd.github.v3+json" -H "Authorization: token $TOKEN" '
url = "https://api.github.com/repos/<...>/${repo}/compare/${pullRequest.base}...${head_sha}"
def behind_by = sh (label: "Check PR commits behind",
returnStdout: true,
script: "curl -s ${url} ${headers} | jq -r .behind_by").trim().toUpperCase()
if (behind_by != '0') {
currentBuild.result = "ABORTED"
currentBuild.displayName = "#${env.BUILD_NUMBER}-Out of date"
error("The head ref is out of date. Please update your branch.")
}
}
}

credential issues with curl in job dsl

I'm looking to get a get response on different jenkins pipelines to recreate them using job dsl plugin, but I'm facing issues with the credentials, so far i have been using the logic below but if trying to use the jenkins credentials in credentialsBinding, it fails to recognize them, if I use my own user and password it works fine
this is the logic im looking to implement
job('seed'){
wrappers {
credentialsBinding {
usernamePassword('USER','PASSWORD', 'credentials')
}
}
label('centos')
def confXml = "curl -s -XGET ${url} -u \$USER:\$PASSWORD".execute().text.replace("\n", "")
//do something with the respose
//recreate dsl after checking an attribute in the response
pipelineJob("Sandbox_pipelines/pipelineName") {
definition {
cpsScm {
scm {
git(repo_git, "master")
}
scriptPath("somepath")
}
}
}
}
when i run this job this should be creating the other pipelines, please let me know if you can help me on this.
Thanks in advance
The issue is that credentialsBinding loads the credentials during the build of the job being created. You want to use the credential to decide what to create and that's just not how it works.
You can use withCredentials though:
def confXml
withCredentials([usernameColonPassword(credentialsId: 'credentials', variable: 'USERPASS')]) {
confXml = "curl -s -XGET ${url} -u \$USERPASS".execute().text.replace("\n", "")
}

How to post a custom comment back to a Github PR from jenkins build

I am basically looking at how i can post a comment to a GitHub PR using jenkins multibranch pipeline job. Everything works for me and PRs are triggered and any commit to the source branch also triggers the PR build for that branch. Also the variables are getting substituted just fine, but somehow the script fails while doing a post of the custom comment from the build. Here is my sample declarative Jenkinsfile.
def PULL_REQUEST = env.CHANGE_ID
pipeline {
agent {
label "pod-custom"
}
stages {
stage('Checkout') {
steps {
checkout scm
}
}
stage('Test Plan') {
steps {
withCredentials([string(credentialsId: 'github-api', variable: 'GITHUB_TOKEN')]) {
sh "curl -s -H \"Authorization: token ${GITHUB_TOKEN}\" -X POST -d '{\"body\": \"This is my first test comment from jenkins\",\"commit_id\": \"4d0f019b93c11f1fabc8313da4c461dbdbde1fd5\",\"path\": \"Jenkinsfile\",\"position\": 4}' \"https://github.***.com/api/v3/repos/***/${env.GIT_URL.tokenize("/")[-1].tokenize(".")[0]}/pulls/${PULL_REQUEST}/comments\""
}
}
}
}
}
Here is the error i see :-
Running shell script
+ curl -s -H 'Authorization: token ****' -X POST -d '{"body": "This is my first test comment from jenkins","commit_id": "4d0f019b93c11f1fabc8313da4c461dbdbde1fd5","path": "Jenkinsfile","position": 4}' https://github.***.com/api/v3/repos/***/***/pulls/4/comments
{
"message": "Validation Failed",
"errors": [
{
"resource": "PullRequestReviewComment",
"code": "invalid",
"field": "path"
}
],
"documentation_url": "https://developer.github.com/enterprise/2.14/v3/pulls/comments/#create-a-comment"
}
I am wondering what is the GitHub API looking for as far as this error is concerned. My use case is just that i need to be able to post a comment to the PR i am pulling in the build as you can see, and this comment should be a straight comment to the PR and not the issue in GitHub.
Any help/suggestions here will be greatly appreciated as always.
i was able to figure this out by following the below post :-
Create comment on pull request. I think i wasn't quite understanding that github treats every PR as an issue while not vice-versa, and so what you could achieve by doing a POST /repos/:owner/:repo/issues/:number/comments, is exactly what i was looking here. I could test this just fine using the below :-
def PULL_REQUEST = env.CHANGE_ID
withCredentials([string(credentialsId: 'github-api', variable: 'GITHUB_TOKEN')]) {
sh "curl -s -H \"Authorization: token ${GITHUB_TOKEN}\" -X POST -d '{\"body\": \"This is my first test comment from jenkins\"}' \"https://github.***.com/api/v3/repos/***/${env.GIT_URL.tokenize("/")[-1].tokenize(".")[0]}/issues/${PULL_REQUEST}/comments\""
}
This posted the comment "This is my first test comment from jenkins" just fine under the PR conversation tab, which is what i needed.

How to update Jenkins Job config.xml file using curl

How can I edit jenkins job's parameter by updating config.xml of jenkins job using curl?
You can use:
curl -X POST 'http://my-cool-jenkins.com:8080/createItem?name=mycooljob' -u username:password --data-binary #config.xml -H "Content-Type:text/xml"
Update:
That url for creating job, for updating use:
curl -X POST 'http://my-cool-jenkins.com:8080/job/mycooljob/config.xml' -u username:password --data-binary #config.xml -H "Content-Type:text/xml"
Just updating content of config.xml file is probably not enough to change in-memory state of Jenkins job. You still need to reload configuration from disk, which can be done either in GUI with jenkins/manage/, using groovy script or simply rebooting the server. After that your example should work.
This really goes down to the fact that Jenkins config.xml are XStream serialized java objects, not actual configuration files. So changing job parameters by manually editing xml files is likely not the best solution. Instead, you could change the job configuration using Jenkins script console. For example to change default parameter value for String parameter, you can run below script in Jenkins console (e.g. http://localhost:8080/jenkins/script):
import hudson.model.ParametersDefinitionProperty
def jobName = "job_name"
def paramName = "param_to_be_changed"
def newParamValue = "param_new_value"
def job = Jenkins.instance.getItem(jobName)
def params = job.getAction(ParametersDefinitionProperty)
def paramToModify = params.getParameterDefinitions().find { param -> param.getName() == paramName }
paramToModify.setDefaultValue(newParamValue)
job.save()
If the job is inside the folder or organization, it is necessary to go one level further, i.e.:
def folderName = "folder_name"
def job = Jenkins.instance.getItem(folderName).getItem(jobName)
After that job state will be stored in config.xml file. After that you can execute the script remotely using curl. Assuming you saved above script to script.groovy file:
# Get breadcrumb from Jenkins
curl -u <username>:<password> 'http://localhost:8080/jenkins/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,":",//crumb)'
# Send script to Jenkins console
curl -X POST -u <username>:<password> -H 'Jenkins-Crumb: <crumb>' -H 'Content: text/plain' --data-urlencode "script=$(< script.groovy)" http://localhost:8080/jenkins/scriptText
More details on Parameter API in javadoc
Here is a link of a script that I've been using in order to modify a job's pipeline for the shell: https://raw.githubusercontent.com/iocanel/presentations/382074b5012d6c3ed87042298114e688424eeaed/workspace/editor/jenkins-run-pipeline

Resources