Skip to content
Snippets Groups Projects
Commit f6f71d2a authored by Markus Günther's avatar Markus Günther
Browse files

[TASK] Initial commit of the gitlab commit webhook

This is the first commit in the public git repository if the
gitlab commit webhook.
parents
No related branches found
No related tags found
No related merge requests found
vendor/
Ressources/TemplatesCached/
commits.log
error.log
config.yaml
<?php
namespace SGalinski\Utility;
/*******************************************************************************
*
* Copyright (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
******************************************************************************/
use Gitlab\Api\Groups;
use Gitlab\Api\Projects;
use Gitlab\Api\Users;
use Gitlab\Client;
use Gitlab\Exception\RuntimeException;
/**
* Class with helper methods for the gitlab webhook.
*/
class GeneralUtility {
/**
* @var array
*/
protected $settings = [];
/**
* @var Client
*/
protected $client;
/**
* Construct for general utility
*/
public function __construct($settings, Client $client = NULL) {
$this->setSettings($settings);
if (!$client) {
$client = new Client($this->settings['Configuration']['Gitlab']['apiUrl']);
$client->authenticate($this->settings['Configuration']['Gitlab']['authToken'], Client::AUTH_URL_TOKEN);
}
$this->setClient($client);
}
/**
* Method gets a commit message as string and the id of the project. With the project
* id we can get the web url to the issue and if we find issue number with #number in the
* commit message, we replace the number with a link to the issue.
*
* @param String $commitMessage
* @param array $projectData
* @return String
*/
public function findIssueIdsAndLinkThem($commitMessage, $projectData) {
if (!count($projectData)) {
return $commitMessage;
}
$processingCommitMessage = $commitMessage;
preg_match_all('/#[0-9]{1,4}/', $processingCommitMessage, $matches, PREG_SET_ORDER);
// get url of an issue
$issueUrl = '';
if (count($matches)) {
$issueUrl = $projectData['web_url'];
}
// generate the markup of a link to the issue and replace the #issue in the commit message
foreach ($matches as $entry) {
if (strlen($issueUrl)) {
$entryUrl = $issueUrl . '/issues/' . str_replace('#', '', $entry[0]);
$entryLink = '<a href="' . $entryUrl . '" target="_blank">' . $entry[0] . '</a>';
$commitMessage = str_replace($entry[0], $entryLink, $commitMessage);
}
}
return $commitMessage;
}
/**
* Method checks the commit log if the given commit id is known.
*
* @param string $commitId
* @return boolean
*/
public function checkLogForCommitId($commitId) {
$commitFailures = file_get_contents($this->settings['Configuration']['Logging']['commitIdLog']);
if ($commitFailures === FALSE) {
$this->createLogFile();
}
return (strpos($commitFailures, $commitId) > 0) ? TRUE : FALSE;
}
/**
* Actually we need to log the commit ids, because there is an error in gitlab. Sometimes the
* webhook is triggered twice and so we send the mails twice. This method logs the commit id.
*
* @param string $commitId
* @return void
*/
public function logCommitId($commitId) {
// need double ticks here because the line break does not work with single ticks
$commitIdLog = $commitId . ",\r\n";
$logFilePath = $this->settings['Configuration']['Logging']['commitIdLog'];
if (file_put_contents($logFilePath, $commitIdLog, FILE_APPEND | LOCK_EX) === FALSE) {
$this->createLogFile();
file_put_contents($logFilePath, $commitIdLog, FILE_APPEND | LOCK_EX);
}
}
/**
* Create a log file for the commit ids.
*
* @return void
*/
protected function createLogFile() {
$filename = $this->settings['Configuration']['Logging']['commitIdLog'];
// need double ticks here because the line break does not work with single ticks
$firstLine = "# Log file for commit ids.\r\n";
$file = fopen($filename, 'a');
if (!$file) {
error_log('Cannot open file (' . $filename . ')');
exit;
}
if (fwrite($file, $firstLine) === FALSE) {
error_log('Cannot write to file (' . $filename . ')');
exit;
}
fclose($file);
}
/**
* The method fetch the project members and the members of the group. The name and email address
* of the fetched persons will be returned in an array.
*
* @param array $projectData
* @return array
*/
public function getRecipientsForProject(array $projectData) {
if (!count($projectData)) {
return [];
}
$users = [];
$recipients = [];
$fallbackRecipient = [$this->settings['Configuration']['MailConfiguration']['fallbackRecipient']];
$groupId = intval($projectData['namespace']['id']);
// get members of the project
$projectMember = $this->getProjectMembers($projectData['id']);
foreach ($projectMember as $member) {
$users[] = $member['id'];
}
$group = $this->getMemberDataOfAGroup($groupId);
foreach ($group as $member) {
$users[] = $member['id'];
}
// Need to fetch the email addresses with another API call because since gitlab 7.0 the email address
// will not returned for project and group members.
$allUsers = $this->getUsers();
foreach ($allUsers as $user) {
if (in_array((int) $user['id'], $users)) {
$recipients[$user['email']] = $user['name'];
}
}
return (!count($recipients)) ? $fallbackRecipient : $recipients;
}
/**
* Get member for a given project id. Returns an empty array if there are no
* members for the given project.
*
* @param integer $id
* @return array
*/
public function getProjectMembers($id) {
$members = [];
try {
/** @var Projects $projects */
$projects = $this->client->api('projects');
/** @var array $members */
$members = $projects->members($id);
} catch (RuntimeException $e) {
error_log('Unable to get project member data', $e->getMessage());
}
return count($members) ? $members : [];
}
/**
* Get the gitlab users. Returns an empty array if no users can be found.
*
* @return array
*/
public function getUsers() {
$userData = [];
try {
/** @var Users $users */
$users = $this->client->api('users');
/** @var array $userData */
$userData = $users->all();
} catch (RuntimeException $e) {
error_log('Unable to get user data', $e->getMessage());
}
return count($userData) ? $userData : [];
}
/**
* Method gets a id of a group and returns an array with the member data of the group.
* If we can't find the group we return NULL.
*
* @param Integer $groupId
* @return array
*/
public function getMemberDataOfAGroup($groupId) {
$groupData = [];
try {
/** @var Groups $groups */
$groups = $this->client->api('groups');
/** @var array $groupData */
$groupData = $groups->members($groupId);
} catch (RuntimeException $e) {
error_log('Unable to get group data', $e->getMessage());
}
return count($groupData) ? $groupData : [];
}
/**
* Setter for settings.
*
* @param array $settings
* @return void
*/
public function setSettings($settings) {
$this->settings = $settings;
}
/**
* Getter for debug.
*
* @return array
*/
public function getSettings() {
return $this->settings;
}
/**
* Getter for client
*
* @return Client
*/
public function getClient() {
return $this->client;
}
/**
* Setter for client
*
* @param Client $client
* @return void
*/
public function setClient(Client $client) {
$this->client = $client;
}
}
<?php
namespace SGalinski;
/*******************************************************************************
*
* Copyright (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
******************************************************************************/
use Buzz\Browser;
use Buzz\Exception\ClientException;
use Gitlab\Api\Projects;
use Gitlab\Client;
use Gitlab\Exception\RuntimeException;
use Gitlab\HttpClient\Listener\AuthListener;
use SGalinski\Utility\GeneralUtility;
use Swift_Attachment;
use Swift_Mailer;
use Swift_Message;
use Swift_SendmailTransport;
use Symfony\Component\DomCrawler\Crawler;
use TijsVerkoyen\CssToInlineStyles\CssToInlineStyles;
use Twig_Environment;
use Twig_Loader_Filesystem;
use Twig_Template;
/**
* The web hook class is responsible for the web hook processing.
*/
class Webhook {
/**
* @var array
*/
protected $settings = [];
/**
* Array with the json data of the push to the repository.
*
* @var array
*/
protected $request = [];
/**
* @var Twig_Template
*/
protected $view;
/**
* @var boolean
*/
protected $debugMode = FALSE;
/**
* @var array
*/
static protected $diffCache = [];
/**
* Construct sets request and setting property for the web hook object.
*
* @param $jsonString
* @param array $settings
*/
public function __construct($jsonString, array $settings) {
$this->setRequest(json_decode($jsonString, TRUE));
$this->setSettings($settings);
// set up view
$loader = new Twig_Loader_Filesystem('Ressources/Templates');
$twig = new Twig_Environment($loader, ['cache' => 'Ressources/TemplatesCached']);
$this->view = $twig->loadTemplate('Commit.html');
// set debug mode
$this->debugMode = ($this->settings['Configuration']['Debug']['enableDebugMode'] === TRUE) ? TRUE : FALSE;
}
public function processWebhook() {
$configuration = $this->settings['Configuration']['Gitlab'];
$authenticationToken = ($configuration['authToken'] ? $configuration['authToken'] : NULL);
$sudo = ($configuration['sudo'] ? $configuration['sudo'] : NULL);
$apiClient = new Client($this->settings['Configuration']['Gitlab']['apiUrl']);
$apiClient->authenticate(
$authenticationToken, Client::AUTH_URL_TOKEN, $sudo
);
$utility = new GeneralUtility($this->settings, $apiClient);
$branchName = str_replace('refs/heads/', '', $this->request['ref']);
$projectId = $this->request['project_id'];
try {
/** @var Projects $projects */
$projects = $apiClient->api('projects');
/** @var array $members */
$projectData = $projects->show($projectId);
} catch (RuntimeException $e) {
error_log('Unable to get project data', $e->getMessage());
exit;
}
foreach ($this->request['commits'] as $commit) {
// skip commit if the commit has been logged
if ($utility->checkLogForCommitId($commit['id'])) {
continue;
}
// adjust commit message
$commit['message'] = $utility->findIssueIdsAndLinkThem($commit['message'], $projectData);
$bindings = [
'username' => $this->request['user_name'],
'branch' => $this->request['ref'],
'repository' => $projectData['name_with_namespace'],
'commit' => $commit,
'diff' => $this->crawlCommitDiffContent($commit)
];
$mailBody = $this->view->render($bindings);
$mailBody = $this->includeStyleSheets($mailBody, 'Ressources/StyleSheets/Mail.css');
// Mail Handling
$transport = Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs');
$mailer = Swift_Mailer::newInstance($transport);
$commitMessageAsArray = explode(chr(10), $commit['message']);
$subject = 'Commit: ' . $projectData['name_with_namespace'] . ' / ' .
$branchName . ' ' . $commitMessageAsArray[0];
/** @var Swift_Message $message */
$message = Swift_Message::newInstance($subject)
->setFrom($this->settings['Configuration']['MailConfiguration']['from'])
->setBody($mailBody, 'text/html')
->setCharset('utf-8');
// Send the message
$failedRecipients = [];
$recipients = $utility->getRecipientsForProject($projectData);
$debugRecipient = [$this->settings['Configuration']['Debug']['debugMailAdresse']];
$recipients = $this->debugMode ? $debugRecipient : $recipients;
// attach diffs if it is configured
$attachtmentConfiguration = $this->settings['Configuration']['MailConfiguration']['attachment'];
if ($attachtmentConfiguration['diffAsHtml'] === TRUE) {
$htmlAttatchment = $this->crawlCommitDiffAsHtml($commit);
$message->attach($htmlAttatchment);
}
if ($attachtmentConfiguration['diffAsFile'] === TRUE) {
$diffAttatchment = $this->crawlCommitDiffAsFile($commit);
$message->attach($diffAttatchment);
}
foreach ($recipients as $mail => $name) {
filter_var($name, FILTER_VALIDATE_EMAIL) ? $message->setTo($name) : $message->setTo([$mail => $name]);
$mailer->send($message, $failedRecipients);
}
// log commit id to prevent sending mails twice
$utility->logCommitId($commit['id']);
}
}
/**
* The method downloads the diff file of the given commit and the diff as an Swift_Attachment instance.
*
* @param array $commit
* @return Swift_Attachment
*/
protected function crawlCommitDiffAsFile($commit) {
$diff = $this->crawlCommitDiffContent($commit);
$attachment = Swift_Attachment::newInstance()
->setFilename($commit['id'] . '.diff')
->setContentType('text/plain')
->setBody(($diff !== '') ? $diff : '');
return $attachment;
}
/**
* The method downloads the diff file of the given commit and return the content as string.
*
* @param array $commit
* @return string
*/
protected function crawlCommitDiffContent($commit) {
if (!array_key_exists($commit['id'], self::$diffCache)) {
$diffUrl = $commit['url'] . '.diff?private_token=' . $this->settings['Configuration']['Gitlab']['authToken'];
$browser = $this->getAuthenticatedBrowser();
try {
self::$diffCache[$commit['id']] = $browser->get($diffUrl)->getContent();
} catch (ClientException $e) {
error_log('Buzz ClientException : Unable to get diff data');
}
}
return (self::$diffCache[$commit['id']] !== '') ? self::$diffCache[$commit['id']] : '';
}
/**
* The method crawl the DOM of the commit page for the file diffs and concatenate the markup for creating an
* HTML file. The HTML file gets inline stylesheets and will be returned as an Swift_Attachment instance.
*
* @param array $commit
* @return Swift_Attachment
*/
protected function crawlCommitDiffAsHtml($commit) {
$html = '<html><body>';
$content = '';
$commitUrl = $commit['url'] . '?private_token=' . $this->settings['Configuration']['Gitlab']['authToken'];
$browser = $this->getAuthenticatedBrowser();
try {
$response = $browser->get($commitUrl);
$content = $response->getContent();
} catch (ClientException $e) {
error_log('Buzz ClientException : Unable to get diff data');
}
/** @var Crawler $crawler */
$crawler = new Crawler();
$crawler->addContent($content);
foreach ($crawler->filter('.files') as $node) {
$html .= $node->ownerDocument->saveHTML($node);
}
$html .= '</body></html>';
$message = $this->includeStyleSheets($html, 'Ressources/StyleSheets/Diff.css');
$attachment = Swift_Attachment::newInstance()
->setFilename($commit['id'] . '.html')
->setContentType('text/html')
->setBody($message);
return $attachment;
}
/**
* Method includes stylesheets as inline css to the given markup.
*
* @param string $markup
* @param string $pathToCssFile
* @return string
*/
protected function includeStyleSheets($markup, $pathToCssFile) {
$css = file_get_contents($pathToCssFile);
if ($css) {
// convert CSS to inline styles for GMail
$inline = new CssToInlineStyles($markup, $css);
$markup = $inline->convert();
}
return $markup;
}
/**
* Create a Buzz/Browser object and set authentication token for Gitlab.
*
* @return Browser
*/
protected function getAuthenticatedBrowser() {
$authToken = $this->settings['Configuration']['Gitlab']['authToken'];
$authentication = new AuthListener($authToken, Client::AUTH_HTTP_TOKEN);
$browser = new Browser();
$browser->addListener($authentication);
return $browser;
}
/**
* Setter for settings array.
*
* @param array $settings
* @return void
*/
public function setSettings(array $settings) {
$this->settings = $settings;
}
/**
* Getter for settings array.
*
* @return array
*/
public function getSettings() {
return $this->settings;
}
/**
* Setter for request array.
*
* @param array $request
* @return void
*/
public function setRequest(array $request) {
$this->request = $request;
}
/**
* Getter for request array.
*
* @return array
*/
public function getRequest() {
return $this->request;
}
}
# Commit Email Hook
This PHP script is a webhook for gitlab. The hook was created to notify project and group members about a pushed commit.
Gitlab itself has a 'Emails on push' service. But for these service you have to enter the email addresses to a
textfield manually.
So the advantages of the hook are:
1. The hook get the project and team members by the gitlab api and dispatches the mails.
2. The hook links to mentioned issues and to the commit itself. So you save time if you want to get more information or want to comment the commit.
3. You can change and style the mail template.
4. You can enable diffs as a file or as an html attachment.
5. You can extend the hook if you need more features.
## Installation
We use composer to manage all required packages. So the first step is to install composer.
```
curl -sS https://getcomposer.org/installer | php
```
If you have root access you can install composer globaly. So you can use composer like this `composer install`.
```
mv composer.phar /usr/local/bin/composer
```
If you do not have the access to do that or don't want to use composer globaly use instead of the composer command
`php /pathToComposer/composer.phar`.
In the second and last step you only have to clone the repository and use composer to install all dependend packages.
That all you need.
```
git clone git@gitlab.sgalinski.de:internal/commit-gitlab-webhook.git webhook
cd webhook
composer install
```
## Configuration
The configuration is as simple as the installation. You only have to copy the example configuration and adjust some
settings. The used configuration language is [YAML](http://symfony.com/doc/current/components/yaml/yaml_format.html).
```
mv config.yaml.example config.yaml
vim config.yaml
```
### GitLab
* Add you Gitlab token to the `authToken` property in the Gitlab section.
* Change the `apiUrl` 'http://gitlab.domain.com/api/v3/' to your domain.
After these changes your webhook is ready to run. But it is recommended to configure the MailConfiguration
section as well. Otherwise your mail recipients get wrong sender information.
### Mail configuration
* Change the email address of the from property to configure the right sender.
* The fallbackRecipient property configures an email address as fallback. E.g. if the API did not get project or group member - the fallback will get the mail. This can be your development leader or someone else.
### Addition configuration
If you want to extend the webhook or test something else you can enable the debugging mode of the webhook.
All emails will send now to the email address that is configured in debugMailAdresse property.
\ No newline at end of file
a {
text-decoration: none;
}
a.commit {
text-decoration: underline;
}
table {
width: 100%;
max-width: 100%;
background-color: transparent;
border-collapse: collapse;
border-spacing: 0;
}
.file {
border: 1px solid #CCC;
margin-bottom: 1em;
}
.file .header {
padding: 5px 5px 5px 10px;
color: #555;
border-bottom: 1px solid #CCC;
background: #EEE;
background-image: -webkit-gradient(linear, 0 0, 0 30, color-stop(0.066, #EEE), to(#DFDFDF));
background-image: -webkit-linear-gradient(#EEE 6.6%, #DFDFDF);
background-image: -moz-linear-gradient(#EEE 6.6%, #DFDFDF);
background-image: -o-linear-gradient(#EEE 6.6%, #DFDFDF)
}
.file .header a {
display: none;
}
.file .header>span {
font-family: "Menlo", "Liberation Mono", "Consolas", "Courier New", "andale mono", "lucida console", monospace;
font-size: 14px;
line-height: 30px
}
.file .content {
overflow: auto;
overflow-y: hidden;
background: #FFF;
color: #333;
font-size: 12px;
font-family: Menlo, 'Liberation Mono', Consolas, 'Courier New', 'andale mono', 'lucida console', monospace;
}
.file .content .old span.idiff {
background-color: #FAA;
}
.file .content .new span.idiff {
background-color: #AFA;
}
.file .content table td {
line-height: 18px;
font-family: Menlo, 'Liberation Mono', Consolas, 'Courier New', 'andale mono', 'lucida console', monospace;
}
.file .content_image {
background: #EEE;
text-align: center;
}
.file .content_image img {
max-width: 400px;
margin: 50px;
padding: 1px;
}
.file .content_image img.diff_image_removed {
border: 1px solid #C00;
}
.file .content_image img.diff_image_added {
border: 1px solid #0C0;
}
.file .content_image.img_compared img {
max-width: 300px;
}
.content table {
border: none;
margin: 0;
padding: 0;
}
.content table tr td {
font-size: 12px;
}
.content .old_line, .content .new_line {
border: none;
background: #EEE;
color: #666;
border-right: 1px solid #CCC;
text-align: right;
min-width: 35px;
max-width: 35px;
width: 35px;
margin: 0;
padding: 0 5px;
}
.content .old_line a, .content .new_line a {
float: left;
width: 35px;
font-weight: 400;
color: #666;
}
.content .old_line a:hover, .content .new_line a:hover {
text-decoration: underline;
}
.content .line_content {
white-space: pre;
height: 14px;
border: none;
margin: 0;
padding: 0;
}
.content .line_content.new {
background: #CFD;
}
.content .line_content.old {
background: #FDD;
}
.content .line_content.matched {
color: #CCC;
background: #FAFAFA;
}
.commit-title {
display: block;
margin-bottom: 10px;
}
.commit-author, .commit-committer {
display: block;
color: #999;
font-weight: 400;
font-style: italic;
}
.commit-author strong, .commit-committer strong {
font-weight: 700;
font-style: normal;
}
.commit .notes_count {
float: right;
margin: -6px 8px 6px;
}
.commit code {
background: #FCEEC1;
color: #474D57;
}
.commit .commit_short_id {
float: left;
min-width: 65px;
font-family: Menlo, 'Liberation Mono', Consolas, 'Courier New', 'andale mono', 'lucida console', monospace;
}
.commit .commit-author-name {
color: #777;
}
.header a, .file_stats a {
color: #474D57;
}
.file_stats span img {
width: 14px;
float: left;
margin-right: 6px;
padding: 2px 0;
}
.label_commit {
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
border-radius: 4px;
border: none;
font-size: 13px;
background: #474D57;
color: #FFF;
font-family: Menlo, 'Liberation Mono', Consolas, 'Courier New', 'andale mono', 'lucida console', monospace;
padding: 2px 4px;
}
.commit .browse_code_link_holder, .commit .committed_ago {
float: right;
}
h1, h2 {
margin: 0 0 .5em;
color: #C0392A;
font-weight: normal;
line-height: 1.1;
font-size: 23px;
}
h2 {
font-size: 20px;
margin-top: 30px;
}
.container {
width: 40em;
padding: 1em;
background: #FCFCFC;
border: 1px solid #D9D9D9;
font-family: Lato, Arial, Helvetica, sans-serif;
font-size: 16px;
color: #575757;
}
.container pre {
font: 0.8em Arial, sans-serif;
}
dl {
margin: 0;
padding: 0;
font: 0.8em Arial, sans-serif;
width: 30em;
}
dt {
position: relative;
top: 1.5em;
width: 10em;
text-align: center;
font-weight: bold;
padding: 0.5em;
background: #C0392A;
text-align: center;
text-shadow: -1px -1px 1px rgba(0, 0, 0, 0.4);
color: #FFF;
}
dd {
margin: 0 0 0 12em;
padding: 0 0 0 0.5em;
border-left: 1px solid #D9D9D9;
}
dd a,
dd a:active,
dd a:hover,
dd a:visited {
background: #FCFCFC;
color: #C83B2C;
text-decoration: none;
}
a.button,
a:active.button,
a:hover.button,
a:visited.button {
color: #C83B2C;
text-decoration: none;
font-size: 16px;
font-weight: bold;
}
\ No newline at end of file
<h1>New commit has been pushed</h1>
<div class="container">
<dl>
<dt>User</dt>
<dd>{{username}}</dd>
<dt>Branch</dt>
<dd>{{branch}}</dd>
<dt>Repository</dt>
<dd>{{repository}}</dd>
<dt>Commit Message</dt>
<dd>{{commit.message|raw|nl2br}}</dd>
</dl>
</div>
<p>
<a href="{{commit.url}}" target="_blank" class="button">To Commit {{commit.id|slice(0, 8)}}</a>
</p>
{% if not diff is empty %}
<h2>Diff of {{commit.id|slice(0, 8)}}</h2>
<div class="container">
<pre>
{{diff}}
</pre>
</div>
{% endif %}
\ No newline at end of file
{
"name": "sgalinski/webhooks",
"description": "Webhook library for Gitlab",
"require": {
"m4tthumphrey/php-gitlab-api": "dev-master",
"symfony/dom-crawler": "2.4.*",
"symfony/yaml": "2.4.*",
"symfony/css-selector": "2.4.*",
"swiftmailer/swiftmailer": "5.0.*",
"twig/twig": "1.15.*",
"tijsverkoyen/css-to-inline-styles": "dev-master"
},
"keywords": ["gitlab"],
"license": "MIT",
"authors": [
{
"name": "Markus Günther",
"email": "markus@sgalinski.de"
}
],
"autoload": {
"psr-4": {
"SGalinski\\": "Classes/"
}
},
"minimum-stability": "beta"
}
# #
# Configuration for the Gitlab webhook #
# #
# This file contains the default configuration for the Gitlab webhook #
# Modify this file before using the webhook script. The Gitlab section #
# is mandatory for using the script. Add an authToken and the apiUrl. #
# Without this configuration your webhook is doing nothing #
# #
Configuration:
Gitlab:
authToken: ''
apiUrl: 'http://gitlab.domain.com/api/v3/'
sudo: ''
# Debug configuration
Debug:
enableDebugMode: FALSE
debugMailAdresse: 'debug@domain.com'
# Mail configuration
MailConfiguration:
from: 'no-reply@domain.com'
fallbackRecipient: 'fallback@domain.com'
# Logging configuration
Logging:
commitIdLog: 'commits.log'
\ No newline at end of file
<?php
/*******************************************************************************
*
* Copyright (c) sgalinski Internet Services (http://www.sgalinski.de)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
******************************************************************************/
require_once __DIR__ . '/vendor/autoload.php';
use SGalinski\Webhook;
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Parser;
/** @var Parser $yamlParser */
$yamlParser = new Parser();
try {
$settings = $yamlParser->parse(file_get_contents(__DIR__ . '/config.yaml'));
// read hook request
$request = file_get_contents('php://input');
$webhook = new Webhook($request, $settings);
$webhook->processWebhook();
} catch (ParseException $e) {
error_log('Unable to parse the YAML string: %s', $e->getMessage());
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment