├── .gitignore ├── .npmignore ├── LICENSE ├── README.md ├── index.js └── package.json /.gitignore: -------------------------------------------------------------------------------- 1 | # file of projects 2 | *.sublime-* 3 | nbproject/ 4 | .idea/ 5 | 6 | # npm modules 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log 11 | 12 | .DS_Store 13 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | # file of projects 2 | *.sublime-* 3 | nbproject/ 4 | .idea/ 5 | 6 | # npm modules 7 | node_modules/ 8 | 9 | # logs 10 | npm-debug.log 11 | 12 | .DS_Store 13 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Andrii Kolomiichenko (bboywilld@gmail.com) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # gitlab-webhooker 2 | 3 | This is a simple way to update your production code by GitLab triggers. 4 | Added token to web hook get URL. For example: `http://myapp.com:4400?token=qwerty123`. Look how to use GitLab web hooks on official manual [here](https://gitlab.com/gitlab-org/gitlab-ce/blob/master/doc/web_hooks/web_hooks.md). 5 | 6 | ### How to start 7 | 8 | ```javascript 9 | var webhooker = require('gitlab-webhooker'); 10 | 11 | webhooker.init({ 12 | token: 'qwerty123', // Optional. Default: ''. Secret key 13 | port: 4400, // Optional. Default: 4400. Listen port 14 | path: '/webhook', // Optional. Default '/' 15 | branches: ['master', 'dev'], // Optional. Default '*'. Branches for track 16 | events: ['push', 'merge_request'], // Optional. Default: 'push'. Event list for track 17 | onEvent: function(json) { /* some js */ }, // Optional. Default: null. Call before exec command 18 | condition: function(json){ /* some logic */}, // Optional. Default null. Called to check weather to execute onEvent or not. Use the json from the gitlab request to check some logic. 19 | onSuccess: function(json,err, stdout, stderr){ /* some logic */}, // Optional. Default null. Gets call after the command has been executed 20 | command: 'cd ~/myapp; ./deploy.sh', // Optional. Shell command when triggered 21 | exit: true, // Optional. Default: false. process.exit(0) after complete command (if you use Docker) 22 | logLevel: 'info' // set Loglevel trace, debug, info, warn, error 23 | }); 24 | ``` 25 | 26 | ### NOTE 27 | 28 | If you use forever don't forget to use `.foreverignore` file with `**/.git/**`. 29 | This will save you from false code restarting. 30 | 31 | ### License 32 | 33 | The MIT License (MIT) 34 | 35 | Copyright (c) 2015 Andrii Kolomiichenko (bboywilld@gmail.com) 36 | 37 | Permission is hereby granted, free of charge, to any person obtaining a copy 38 | of this software and associated documentation files (the "Software"), to deal 39 | in the Software without restriction, including without limitation the rights 40 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 41 | copies of the Software, and to permit persons to whom the Software is 42 | furnished to do so, subject to the following conditions: 43 | 44 | The above copyright notice and this permission notice shall be included in all 45 | copies or substantial portions of the Software. 46 | 47 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 48 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 49 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 50 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 51 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 52 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 53 | SOFTWARE. 54 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | var app = require('orangebox').app(1); 2 | var exec = require('child_process').exec; 3 | var path = require('path').resolve(); 4 | var extend = require('util')._extend; 5 | var log = require('loglevel'); 6 | 7 | module.exports.init = function(opt) { 8 | 9 | var config = { 10 | token: '', 11 | port: 4400, 12 | path: '/', 13 | branches: '*', 14 | events: 'push', 15 | onEvent: null, 16 | onSuccess: null, 17 | command: 'cd ' + path + '; git pull origin master; if git diff --name-status HEAD HEAD~1 | grep -e package.json -e shrinkwrap.js; then npm update; fi', 18 | exit: false, 19 | logLevel: 'warn' 20 | }; 21 | 22 | extend(config, opt); 23 | 24 | log.setDefaultLevel(config.logLevel || 'warn') 25 | app.get(config.path, function(req, res) { 26 | 27 | try { 28 | log.info('Request received!'); 29 | log.debug(req); 30 | var json = JSON.parse(Object.keys(req.body)[0]); 31 | } catch (e) { 32 | log.warn('gitlab-webhooker: Post data are not GitLab JSON'); 33 | log.debug(e); 34 | var json = {}; 35 | res.status(400).send({status: 'Post data are not GitLab JSON'}); 36 | return false; 37 | } 38 | 39 | var requestToken = req.header('x-gitlab-token') || req.query.token || false 40 | log.debug(requestToken) 41 | 42 | var branch = '*'; 43 | if (!config.branches.includes('*')) { 44 | branch = (json.object_kind === 'push') ? json.ref.split('/').pop() : 45 | (json.object_kind === 'merge_request') ? json.object_attributes.target_branch : 46 | (json.object_kind === 'build') ? json.ref.split('/').pop() : json.ref; 47 | } 48 | 49 | var passed_condition = true 50 | if(config.condition && typeof(config.condition) === "function"){ 51 | passed_condition = config.condition.call(this,json) 52 | } 53 | 54 | 55 | log.debug("token: " + requestToken); 56 | log.debug("condition: " + passed_condition); 57 | log.debug("branch: " + json.ref); 58 | 59 | if ( 60 | config.events.includes(json.object_kind) && 61 | config.token === requestToken && 62 | passed_condition && 63 | config.branches.includes(branch) 64 | ) { 65 | 66 | res.status(200).send({status: 'OK'}); 67 | 68 | if (typeof config.onEvent === 'function') config.onEvent(json); 69 | 70 | exec(config.command, function(err, stdout, stderr) { 71 | if (typeof config.onEvent === 'function') config.onSuccess.call(this, json, err, stdout, stderr) 72 | if (config.exit) process.exit(0); 73 | }); 74 | 75 | } else { 76 | res.status(400).send({ status: 'Bad request' }); 77 | log.warn("Bad request") 78 | log.info(req) 79 | } 80 | }); 81 | 82 | app.listen(config.port, function() { 83 | log.info('gitlab-webhooker started on http://localhost:' + config.port); 84 | }); 85 | }; 86 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "gitlab-webhooker", 3 | "version": "2.2.8", 4 | "description": "GitLab web hooks listener", 5 | "author": { 6 | "name": "Andrii Kolomiichenko", 7 | "email": "bboywilld@gmail.com", 8 | "url": "http://github.com/kolomiichenko" 9 | }, 10 | "contributors": [ 11 | { 12 | "name": "Andrii Kolomiichenko", 13 | "email": "bboywilld@gmail.com" 14 | } 15 | ], 16 | "engines": { 17 | "node": ">= 0.10.38" 18 | }, 19 | "scripts": {}, 20 | "repository": { 21 | "type": "git", 22 | "url": "http://git@github.com/kolomiichenko/gitlab-webhooker.git" 23 | }, 24 | "keywords": [ 25 | "git", 26 | "gitlab", 27 | "webhook", 28 | "hook", 29 | "listen", 30 | "exec" 31 | ], 32 | "license": "MIT", 33 | "dependencies": { 34 | "orangebox": "^0.3.0", 35 | "loglevel": "^1.4.1" 36 | }, 37 | "readmeFilename": "README.md", 38 | "gitHead": "b0cc91b1f8f3c22f9b345d45f63659b6b3939979", 39 | "bugs": { 40 | "url": "http://github.com/kolomiichenko/gitlab-webhooker/issues" 41 | }, 42 | "homepage": "http://github.com/kolomiichenko/gitlab-webhooker", 43 | "devDependencies": { 44 | "loglevel": "^1.4.1" 45 | } 46 | } 47 | --------------------------------------------------------------------------------