There is supposed to be a way to trigger a Jenkins job via GitlabCi, using the respective plugin.
My question is whether there is a way:
a) to trigger a parameterized Jenkins job
b) to pass parameters when triggering the job
DevOps Stack Exchange is a question and answer site for software engineers working on automated testing, continuous delivery, service integration and monitoring, and building SDLC infrastructure. It only takes a minute to sign up.
Sign up to join this communityThere is supposed to be a way to trigger a Jenkins job via GitlabCi, using the respective plugin.
My question is whether there is a way:
a) to trigger a parameterized Jenkins job
b) to pass parameters when triggering the job
Here's the way I do it: no plugin required, just triggering Jenkins api
from gitlab-ci.
I will assume you have a gitlab-ci runner installed and configured.
First, you need to have a .gitlab-ci.yml
file in your project having a basic structure such as:
stages:
- my-jenkins-trigger
variables:
MY_VARIABLE: "EVERYTHING_IS_AWESOME"
my-jenkins-trigger-job:
stage: my-jenkins-trigger
script: curl -i -X POST --user JENKINS_USER:JENKINS_TOKEN JENKINS_JOB_URL/buildWithParameters?MY_JENK_PARAM=${MY_VARIABLE}
In the above, I also assume
JENKINS_JOB_URL
MY_VARIABLE
JENKINS_USER
, JENKINS_TOKEN
are defined [*]Well yes, but no...
That is the rough structure. That script will merely trigger a Jenkins job and forget about it. You need to work a little more to monitor the job and feed its status back in Gitlab-CI, manage security and possibly get some commit info from gitlab to inject into your job.
In order to have a proper monitoring, I recommand to write a full trigger + monitor + return value script [** ] (in whatever language available or you're familiar with).
Just start by triggering the job as I stated above.
Then, run a while
loop (don't forget to put it to sleep
[***]) on
curl --silent --user JENKINS_USER:JENKINS_TOKEN JENKINS_JOB_URL/lastBuild/api/json | grep result\":null > /dev/null
until the result of this command is not 0
.
Once the Jenkins job is finished, you would probably want to fetch the job's console in Gitlab
curl -i -X POST --user JENKINS_USER:JENKINS_TOKEN JENKINS_JOB_URL/lastBuild/consoleText
Finally you may curl
once more on JENKINS_JOB_URL/lastBuild/api/json
but this time you grep
it on UNSTABLE
, SUCCESS
or FAILURE
.
By following the guidelines above, you can fully orchestrate Jenkins jobs from Gitlab-CI. I've posted a long discussion on why and when should you do this.
I hope this will help you.
[*] Your Gitlab project Settings > CI/CD > Secret vaiables
[** ] Of course I mean by that to craft a script nicely with params, functions, nice variable names, meaningful logs... You name it.
[***] I found a sleep
of 20 seconds worked for me
FWIW, the trigger you referenced originates from Gitlab repository events, not from a GitlabCI execution.
The only possibility (that crosses my mind) of triggering a jenkins job from inside a GitlabCI execution is by having a (custom?) script invoked as part of the GitlabCI execution which remotely activates a Parameterized Trigger Plugin configured for your jenkins job, via a properly-crafted POST request which would include the desired parameters.
api
; think this is ready ootb only for the trigger that originates from gitlab repo events as you say;
If you want to keep it simple, try the generic webhook trigger plugin.
https://plugins.jenkins.io/generic-webhook-trigger
You can trigger a build by sending an http POST using a JSON body or URL parameters.
Parse the JSON request
def req = readJSON text: payload
Now you can use it in your pipeline assuming you had a deploy function.
deploy(req.environment, req.branch)
I must agree with @Tensibai. Two CI/CD systems on the surface does seem overly complex. You might want to consider sticking with one if possible.
I use a similar setup as this answer.
Difference is I cannot poll the latest job because it may refer to a job I didn't start. So instead I get the queue ID from the response headers when triggering a job, and match that with the queue ID of most recent job runs.
I did this in Python because it makes things a bit easier, but it could also be done using sh.
GitLab CI config:
Test:
stage: test
script:
- run_jenkins_job.py
--docker-image "${CI_REGISTRY_IMAGE}"
--display-name "Test ${CI_COMMIT_REF_SLUG}"
run_jenkins_job.py:
#!/usr/bin/env python3
import argparse
import sys
import time
import requests
JENKINS_JOB_URL = "https://jenkins.example.org/job/MYJOB"
JOB_BUILD_TOKEN = "MYJOBTOKEN"
api_req = requests.Session()
api_req.headers.update(
{
"Authorization": "Basic BASIC_USER_AUTH",
"Content-Type": "application/x-www-form-urlencoded",
}
)
def main():
parser = argparse.ArgumentParser(description="Run a GitLab MR job on Jenkins and poll for the result.")
parser.add_argument("--docker-image", required=True, type=str)
parser.add_argument("--display-name", required=True, type=str)
args = parser.parse_args(sys.argv[1:])
queue_id = schedule_build(args)
exit_code = poll_build(queue_id)
sys.exit(exit_code)
def schedule_build(args: argparse.Namespace) -> int:
response = api_req.post(
f"{JENKINS_JOB_URL}/buildWithParameters?token={JOB_BUILD_TOKEN}",
data={
"docker_image": args.docker_image,
"display_name": args.display_name,
},
)
response.raise_for_status()
location_header_value = response.headers["Location"]
# Example location header: "https://jenkins.example.org/queue/item/123/"
return int(location_header_value.rstrip("/").split("/")[-1])
def poll_build(queue_id: int) -> int:
job_url_shown = False
for _ in range(300):
time.sleep(15)
response = api_req.get(f"{JENKINS_JOB_URL}/api/json?tree=builds[result,queueId,url]")
response.raise_for_status()
for build in response.json()["builds"]:
if build["queueId"] != queue_id:
continue
elif build["result"] is None:
if not job_url_shown:
# Scheduled job first appeared; show URL.
print(f"\nRunning: {build['url']}\n")
job_url_shown = True
print(".", end="", flush=True)
else:
if build["result"] == "SUCCESS":
return 0
else:
return 1
if __name__ == "__main__":
main()
gitlab-ci
job to invoke jenkins to perform a deployment on an orchestrator (Rancher
). The parameters will be the name of the environment and the repo-branch from which the checkout of the code will be performed (so that the images to be deployed are built)