How to Invoke GitHub Actions Workflow from the Jenkins Pipeline? - jenkins

Is there any method or solution to invoke the GitHub Actions Workflow from the Jenkins Declarative Pipeline?
What the Jenkinsfile should include to call said action?

You should be able to call the API to Create a workflow dispatch event.
See "How to trigger a Github action with an HTTP request" from Riku Rouvila
pipeline {
agent any
stages {
stage("Using curl example to trigger a GitHub Action") {
steps {
script {
final String url = "https://api.github.com/repos/<USERNAME>/<REPO>/dispatches"
final String response = sh(script: "curl --request POST \
--url '$url' \
--header 'authorization: Bearer <TOKEN>' \
--data '{"event_type": "hello"}'", returnStdout: true).trim()
echo response
}
}
}
}
}
Replace <USERNAME>/<REPO> and <TOKEN> by the approate value (<TOKEN> would be a Jenkins secret)
And the curl command should be in one line (the \ multiline presentation is here for readability)

Related

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.")
}
}
}

Need to Invoke lambda function using jenkinsfile

I am trying to invoke AWS Lambda function using Jenkinsfile with the payload. Not able to inject the instance_ip variable into the payload.
def instance_ip = "10.X.X.X"
pipeline {
agent any
stages {
stage('Terminate Machine') {
steps {
script {
sh(script: 'aws lambda invoke --function-name terminate-instance --payload '{"private_ip_address":"${instance_ip}" }')
}
}
}
}
}
You need to scape some characters and set --incvocation-type as Event:
sh(script: "aws lambda invoke \
--function-name 'terminate-instance' \
--invocation-type Event \
--payload '{ \"private_ip_address\":\"${instance_ip}\" }' \
/tmp/response.json")
I was facing the same issue. So to pass the payload, in Jenkins file, I am creating a Json payload file using echo and then passing it to the aws cli. It may not be the cleanest solution but it works. Here's what my code looks like:
echo '{ "tagKey"':'"'"${tagKey}"'"', '"tagValue"':'"'"${tagValue}"'"', '"region"':'"'"${region}"'"' } > json.json
cat json.json
ls -alrt
aws lambda invoke --function-name tag_remediator --cli-binary-format raw-in-base64-out --payload file://json.json out_"$tagKey".txt --region "${region}"

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.

Fetching github payload in jenkinsfile

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.

jenkinsfile variable scope

I'm trying to call a remote job from one Jenkins server to another, I have this working fine via a shell script. However, trying to translate it into a Jenkinsfile is causing me issues. The environment variable is always "null" when used inside of a stage, even thought this article says it should be globally available?
pipeline {
agent any
/* get crumb for CSRF */
environment {
def crumb = sh 'curl https://jenkins-remote/crumbIssuer/'
}
stages {
/* call remote job */
stage("remote") {
steps {
sh "curl -X POST -H ${env.crumb} https://jenkins-remote/buildWithParameters?foo"
}
}
}
}
The trimmed output looks like:
[remote_pipeline] Running shell script
+ curl -X POST -H null
I am using Jenkins v2.89.4, new "Pipeline" job, "pipeline script".
Thanks to #TrafLaf for pointing out the variable is null because it does not get set to the output of the curl command. My hacky solution was this:
environment {
def crumbRequest = sh 'curl https://jenkins-remote/crumbIssuer/ > crumbHeader'
crumbHeader = readFile('crumbHeader').trim()
}
As per the official documentation, This is how you define environment variables.
pipeline {
agent any
environment {
DISABLE_AUTH = 'true'
DB_ENGINE = 'sqlite'
}
stages {
stage('Build') {
steps {
echo "${env.DB_ENGINE}" # to access
}
}
}
}
But you have coded wrong,
environment {
def crumb = sh 'curl https://jenkins-remote/crumbIssuer/'
}
So please do the rest.
The sh task can now return output, so in theory the following should work (untested):
environment {
crumb = sh(script: 'curl https://jenkins-remote/crumbIssuer/',
returnStdout: true).trim()
}

Resources