10

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:

  1. to trigger a parameterized Jenkins job

  2. to pass parameters when triggering the job

3
  • What are the parameters you want to pass? What action causes a trigger? Commented Feb 28, 2018 at 23:33
  • At some point I want a 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) Commented Mar 1, 2018 at 9:00
  • Why do you want to chain two CI systems ? I can't really understand it as gitlab-ci can directly trigger deployments on k8s clusters,so adding jenkins in the middle sounds more adding complexity than helping the situation. Commented Mar 1, 2018 at 15:15

4 Answers 4

11

Here's the way I do it: no plugin required, just triggering Jenkins api from gitlab-ci.

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

  • You have a Jenkins job somewhere at URL JENKINS_JOB_URL
  • this Jenkins job has a build parameter called MY_VARIABLE
  • JENKINS_USER, JENKINS_TOKEN are defined [*]

That simple?

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.

Monitoring

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.

Discussion

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

4
  • Can you post a complete example that includes monitoring? Commented Jul 7, 2020 at 13:07
  • It's a while loop, and i could not know your functional. I didn't write out a full example on purpose. I think it would be great if you could do your own! Commented Jul 7, 2020 at 13:12
  • been searching for the "monitoring" parts, I thought it's simple as waiting for the response :D Thanks for sharing this! Commented Oct 28, 2021 at 9:10
  • 1
    Thanks for the explanation. I just wanted to add (something probably obvious) to "until the result of this command is not 0" - you may want to implement a timeout here. Commented Mar 14, 2023 at 8:34
3

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.

See also https://stackoverflow.com/questions/20359810/how-to-trigger-jenkins-builds-remotely-and-to-pass-parameters.

2
  • that's what I thought also...the question is now how to make gitlab-ci aware of the success/failure of the job triggered via api; think this is ready ootb only for the trigger that originates from gitlab repo events as you say; Commented Mar 1, 2018 at 10:04
  • Hm, that would be fully managing the jenkins job, not just triggering it... Maybe using GitLab Runner locally to run a custom script which triggers the jenkins job and also monitors its status until completion reporting back the result? Commented Mar 1, 2018 at 13:48
0

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.

generic-webhook-trigger

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.

0

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() 

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.