Skip to content

Instantly share code, notes, and snippets.

@thinhbuzz
Created October 16, 2018 17:03
Show Gist options
  • Save thinhbuzz/84e06bc52d1d5cb12292abfa6a6f3c75 to your computer and use it in GitHub Desktop.
Save thinhbuzz/84e06bc52d1d5cb12292abfa6a6f3c75 to your computer and use it in GitHub Desktop.
Node JS gitlab webhook receiver and trigger pipelines
const qs = require('querystring');
const http = require('http');
const https = require('https');
const assert = require('assert');
const config = {
port: 3000,
projectId: '',
pipelineTriggerToken: '',
secretToken: null
};
assert(config.projectId, 'projectId must not empty');
assert(config.pipelineTriggerToken, 'pipelineTriggerToken must not empty');
server = http.createServer((req, res) => {
new Promise((resolve, reject) => {
res.writeHead(200, {'Content-Type': 'application/json'});
if (req.method === 'POST') {
verifyToken(req.headers);
let body = '';
req.on('data', data => {
body += data;
});
req.on('end', () => {
try {
resolve({body: JSON.parse(body), headers: req.headers});
} catch (error) {
reject(error);
}
});
req.on('error', error => {
reject(error);
});
}
})
.then(({body}) => {
switch (body.object_kind) {
case 'merge_request':
processMergeRequestEvent(body);
break;
}
res.end(JSON.stringify({message: 'nodejs gitlab Webhook receiver'}));
res.writeHead(200, {'Content-Type': 'application/json'});
})
.catch(error => {
res.writeHead(500, {'Content-Type': 'application/json'});
res.end(JSON.stringify({message: typeof error === 'object' && error.message ? error.message : 'Internal server error!'}));
});
});
server.listen(config.port, () => {
console.log('Listening on port ' + config.port);
});
function processMergeRequestEvent(body) {
let ref;
switch (body.object_attributes.state) {
case 'opened':
ref = body.object_attributes.source_branch;
break;
case 'merged':
ref = body.object_attributes.target_branch;
break;
}
if (!ref) {
return;
}
post({ref})
.then(console.info.bind(console, 'Trigger pipelines success with response:'))
.catch(console.error.bind(console, 'Trigger pipelines with error:'));
}
function verifyToken(headers) {
if (!config.secretToken) {
return;
}
if (!headers['x-gitlab-token'] || headers['x-gitlab-token'] !== config.secretToken) {
throw new Error('Secret token miss match');
}
}
function post(data) {
return new Promise((resolve, reject) => {
data['token'] = config.pipelineTriggerToken;
const requestData = qs.stringify(data);
const requestOptions = {
host: 'gitlab.com',
port: 443,
path: `/api/v4/projects/${config.projectId}/trigger/pipeline`,
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
'Content-Length': Buffer.byteLength(requestData)
}
};
const request = https.request(requestOptions, res => {
res.setEncoding('utf8');
let body = '';
res.on('data', data => {
body += data;
});
res.on('end', () => {
try {
resolve({body: JSON.parse(body), headers: res.headers});
} catch (error) {
reject(error);
}
});
res.on('error', error => {
reject(error);
});
});
request.write(requestData);
request.end();
});
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment