Initial commit

This commit is contained in:
Tim Schubert 2022-02-15 22:40:43 +01:00
commit f49f2f3c68
Signed by: dadada
GPG key ID: EEB8D1CE62C4DFEA
8 changed files with 122 additions and 0 deletions

4
.env.local.example Normal file
View file

@ -0,0 +1,4 @@
REDMINE_URL=http://localhost:8080
REDMINE_API_KEY=000000000000
GITLAB_TOKEN=0000000000000
CODE_CHANGES_CUSTOM_FIELD_ID=1

3
.envrc Normal file
View file

@ -0,0 +1,3 @@
export FLASK_APP=glrmmr
export FLASK_ENV=development
layout python3

4
.gitignore vendored Normal file
View file

@ -0,0 +1,4 @@
.direnv
__pycache__
venv
.env.local

8
LICENSE Normal file
View file

@ -0,0 +1,8 @@
Copyright 2022 Tim Schubert
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.

6
README.md Normal file
View file

@ -0,0 +1,6 @@
# Gitlab Redmine Merge Request URL linker
A webhook that links a Gitlab MR to a Redmine Issue using the issue ID and a custom field in Redmine.
To get started, edit the `.envrc.local` and run `flask run`.

70
glrmmr/__init__.py Normal file
View file

@ -0,0 +1,70 @@
import re
import requests
from dotenv import dotenv_values
from flask import Flask, request
config = dotenv_values(__name__ + "/../.env.local")
app = Flask(__name__)
@app.route("/", methods=['POST'])
def hook():
headers = request.headers
gitlab_validation_token = headers.get('X-Gitlab-Token')
if not gitlab_validation_token or gitlab_validation_token != config['GITLAB_TOKEN']:
return 'Invalid Gitlab token\n', 403
event_type = headers.get('X-Gitlab-Event')
if not event_type:
return 'Must set X-Gitlab-Event\n', 422
data = request.json
if not data:
return 'Must send JSON data\n', 422
attrs = data.get('object_attributes')
if not attrs:
return 'Missing object_attributes\n', 422
if event_type == 'Merge Request Hook':
mr_title = attrs.get('title')
if not mr_title:
return 'Missing MR title\n', 422
mr_url = attrs.get('url')
if not mr_url:
return 'Missing MR URL\n', 422
fail = 0
for ticket in parse_tickets(mr_title):
try:
update_ticket(ticket, mr_url)
except Exception as e:
fail = fail + 1
if fail:
return 'Failed to update %d tickets\n' % (fail,), 500
return 'OK\n', 200
def parse_tickets(string):
pattern = re.compile('#([0-9]+)')
tickets = pattern.findall(string)
return tickets
def update_ticket(ticket, mr_url):
field_id = config['CODE_CHANGES_CUSTOM_FIELD_ID']
data = {'issue': { 'custom_fields': [{'id': field_id, 'value': mr_url}]}}
result = requests.put(
'%s/issues/%s.json' % (config['REDMINE_URL'], ticket,),
headers={'X-Redmine-API-Key': config['REDMINE_API_KEY']},
json=data
)
if result.status_code != 204:
raise Exception('Failed to update %s: %d %s' % (ticket, result.status_code, result.body))

24
setup.cfg Normal file
View file

@ -0,0 +1,24 @@
[metadata]
name = glrmmr
version = 0.0.1
author = Tim Schubert
author_email = dadada@dadada.li
description = A webhook service to update Redmine with a link to a Gitlab MR
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/dadada/glrmmr
project_urls =
Bug Tracker = https://github.com/dadada/glrmmr/issues
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent
[options]
packages = :find
python_requires = >=3.6
include_package_data = true
install_requires =
Flask
python-dotenv
requests

3
setup.py Normal file
View file

@ -0,0 +1,3 @@
from setuptools import setup
setup()