When integrating GitLab merge request webhooks with Jenkins, we frequently encounter parameter naming mismatches. While GitLab sends payload with keys like id
, target_branch
and source_branch
, Jenkins' GitLab Merge Request Builder plugin expects gitlabMergeRequestId
, gitlabTargetBranch
and gitlabSourceBranch
.
Here are three practical approaches to bridge this parameter gap:
// Option 1: Using a proxy script (Python example)
import requests
import json
from flask import Flask, request
app = Flask(__name__)
@app.route('/gitlab-webhook', methods=['POST'])
def transform_hook():
data = request.json
transformed = {
'gitlabMergeRequestId': data['id'],
'gitlabTargetBranch': data['target_branch'],
'gitlabSourceBranch': data['source_branch']
}
jenkins_url = "http://jenkins.example.com/job/your-job/buildWithParameters"
response = requests.post(jenkins_url, data=transformed)
return response.text
if __name__ == '__main__':
app.run(port=5000)
For Jenkins Pipeline users, we can handle the raw webhook payload directly:
pipeline {
agent any
triggers {
GenericTrigger(
genericVariables: [
[key: 'id', value: '$.id'],
[key: 'target_branch', value: '$.target_branch'],
[key: 'source_branch', value: '$.source_branch']
],
causeString: 'GitLab Merge Request Trigger',
token: 'SECRET_TOKEN',
printContributedVariables: true,
printPostContent: true
)
}
stages {
stage('Build MR') {
steps {
script {
// Use the parameters directly
echo "Building MR ${id} from ${source_branch} to ${target_branch}"
// Your build steps here
}
}
}
}
}
The most maintainable solution involves creating a custom parameter mapping in Jenkins:
- Install the Parameterized Trigger plugin
- Create an intermediate job that receives the raw GitLab webhook
- Configure parameter mapping in the downstream job trigger
When implementing webhook solutions:
- Always validate webhook origin using GitLab's secret token
- Consider rate limiting to prevent abuse
- Log webhook payloads for debugging but sanitize sensitive data
When integrating GitLab merge request webhooks with Jenkins, we frequently encounter parameter naming mismatches between what GitLab sends and what Jenkins plugins expect. The GitLab webhook payload contains merge request data under keys like id
, target_branch
, and source_branch
, while the Jenkins GitLab Merge Request Builder plugin specifically looks for gitlabMergeRequestId
, gitlabTargetBranch
, and gitlabSourceBranch
.
Here are three practical approaches to bridge this parameter gap:
1. Using Jenkins Parameterized Build
Create a parameterized Jenkins job with these parameters:
Name: gitlabMergeRequestId
Default Value: ${id}
Name: gitlabTargetBranch
Default Value: ${target_branch}
Name: gitlabSourceBranch
Default Value: ${source_branch}
Then configure your GitLab webhook to trigger this parameterized build.
2. Webhook Proxy Solution
Create a simple middleware script (Node.js example) to transform the payload:
const express = require('express');
const bodyParser = require('body-parser');
const axios = require('axios');
const app = express();
app.use(bodyParser.json());
app.post('/gitlab-webhook', (req, res) => {
const { id, target_branch, source_branch } = req.body.object_attributes;
const jenkinsParams = new URLSearchParams();
jenkinsParams.append('gitlabMergeRequestId', id);
jenkinsParams.append('gitlabTargetBranch', target_branch);
jenkinsParams.append('gitlabSourceBranch', source_branch);
axios.post('http://jenkins/job/your-job/buildWithParameters', jenkinsParams)
.then(() => res.sendStatus(200))
.catch(err => res.status(500).send(err.message));
});
app.listen(3000);
3. Custom Jenkins Plugin Modification
If you need a more permanent solution, consider modifying the plugin source to accept both parameter naming conventions. The key class to modify would be the one handling parameter parsing in the GitLab Merge Request Builder plugin.
For Jenkins Pipeline jobs, you can process the raw payload directly:
properties([
parameters([
string(name: 'gitlabMergeRequestId', defaultValue: ''),
string(name: 'gitlabTargetBranch', defaultValue: ''),
string(name: 'gitlabSourceBranch', defaultValue: '')
])
])
node {
stage('Process MR') {
script {
def payload = readJSON text: params.payload
env.gitlabMergeRequestId = payload.object_attributes.id
env.gitlabTargetBranch = payload.object_attributes.target_branch
env.gitlabSourceBranch = payload.object_attributes.source_branch
}
}
}
For most teams, the webhook proxy solution (option 2) provides the best balance between maintainability and functionality. It keeps your Jenkins configuration clean while providing flexibility to handle future API changes from GitLab.
Remember to secure your webhook endpoint with validation tokens and consider implementing retry logic for failed builds. The GitLab API also provides additional merge request context that you might want to capture, such as the commit SHA or author information, which can be valuable for your build process.