|
|
"""
|
|
|
rcextensions module.
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
import os
|
|
|
import imp
|
|
|
import string
|
|
|
import functools
|
|
|
|
|
|
here = os.path.dirname(os.path.abspath(__file__))
|
|
|
registered_extensions = dict()
|
|
|
|
|
|
class DotDict(dict):
|
|
|
|
|
|
def __contains__(self, k):
|
|
|
try:
|
|
|
return dict.__contains__(self, k) or hasattr(self, k)
|
|
|
except:
|
|
|
return False
|
|
|
|
|
|
# only called if k not found in normal places
|
|
|
def __getattr__(self, k):
|
|
|
try:
|
|
|
return object.__getattribute__(self, k)
|
|
|
except AttributeError:
|
|
|
try:
|
|
|
return self[k]
|
|
|
except KeyError:
|
|
|
raise AttributeError(k)
|
|
|
|
|
|
def __setattr__(self, k, v):
|
|
|
try:
|
|
|
object.__getattribute__(self, k)
|
|
|
except AttributeError:
|
|
|
try:
|
|
|
self[k] = v
|
|
|
except:
|
|
|
raise AttributeError(k)
|
|
|
else:
|
|
|
object.__setattr__(self, k, v)
|
|
|
|
|
|
def __delattr__(self, k):
|
|
|
try:
|
|
|
object.__getattribute__(self, k)
|
|
|
except AttributeError:
|
|
|
try:
|
|
|
del self[k]
|
|
|
except KeyError:
|
|
|
raise AttributeError(k)
|
|
|
else:
|
|
|
object.__delattr__(self, k)
|
|
|
|
|
|
def toDict(self):
|
|
|
return unserialize(self)
|
|
|
|
|
|
def __repr__(self):
|
|
|
keys = list(self.iterkeys())
|
|
|
keys.sort()
|
|
|
args = ', '.join(['%s=%r' % (key, self[key]) for key in keys])
|
|
|
return '%s(%s)' % (self.__class__.__name__, args)
|
|
|
|
|
|
@staticmethod
|
|
|
def fromDict(d):
|
|
|
return serialize(d)
|
|
|
|
|
|
|
|
|
def serialize(x):
|
|
|
if isinstance(x, dict):
|
|
|
return DotDict((k, serialize(v)) for k, v in x.iteritems())
|
|
|
elif isinstance(x, (list, tuple)):
|
|
|
return type(x)(serialize(v) for v in x)
|
|
|
else:
|
|
|
return x
|
|
|
|
|
|
|
|
|
def unserialize(x):
|
|
|
if isinstance(x, dict):
|
|
|
return dict((k, unserialize(v)) for k, v in x.iteritems())
|
|
|
elif isinstance(x, (list, tuple)):
|
|
|
return type(x)(unserialize(v) for v in x)
|
|
|
else:
|
|
|
return x
|
|
|
|
|
|
|
|
|
def load_extension(filename, async=False):
|
|
|
"""
|
|
|
use to load extensions inside rcextension folder.
|
|
|
for example::
|
|
|
|
|
|
callback = load_extension('email.py', async=False)
|
|
|
if callback:
|
|
|
callback('foobar')
|
|
|
|
|
|
put file named email.py inside rcextensions folder to load it. Changing
|
|
|
async=True will make the call of the plugin async, it's useful for
|
|
|
blocking calls like sending an email or notification with APIs.
|
|
|
"""
|
|
|
mod = ''.join(filename.split('.')[:-1])
|
|
|
loaded = imp.load_source(mod, os.path.join(here, filename))
|
|
|
|
|
|
callback = getattr(loaded, 'run', None)
|
|
|
if not callback:
|
|
|
raise Exception('Plugin missing `run` method')
|
|
|
if async:
|
|
|
# modify callback so it's actually an async call
|
|
|
def _async_callback(*args, **kwargs):
|
|
|
import threading
|
|
|
thr = threading.Thread(target=callback, args=args, kwargs=kwargs)
|
|
|
thr.start()
|
|
|
if kwargs.get('_async_block'):
|
|
|
del kwargs['_async_block']
|
|
|
thr.join()
|
|
|
|
|
|
return _async_callback
|
|
|
return callback
|
|
|
|
|
|
|
|
|
def _verify_kwargs(expected_parameters, kwargs):
|
|
|
"""
|
|
|
Verify that exactly `expected_parameters` are passed in as `kwargs`.
|
|
|
"""
|
|
|
expected_parameters = set(expected_parameters)
|
|
|
kwargs_keys = set(kwargs.keys())
|
|
|
if kwargs_keys != expected_parameters:
|
|
|
missing_kwargs = expected_parameters - kwargs_keys
|
|
|
unexpected_kwargs = kwargs_keys - expected_parameters
|
|
|
raise AssertionError(
|
|
|
"Missing parameters: %r, unexpected parameters: %s" %
|
|
|
(missing_kwargs, unexpected_kwargs))
|
|
|
|
|
|
|
|
|
def verify_kwargs(required_args):
|
|
|
"""
|
|
|
decorator to verify extension calls arguments.
|
|
|
|
|
|
:param required_args:
|
|
|
"""
|
|
|
def wrap(func):
|
|
|
def wrapper(*args, **kwargs):
|
|
|
_verify_kwargs(required_args, kwargs)
|
|
|
return func(*args, **kwargs)
|
|
|
return wrapper
|
|
|
return wrap
|
|
|
|
|
|
|
|
|
def register(name=None):
|
|
|
def wrap(func):
|
|
|
@functools.wraps(func)
|
|
|
def wrapper(*args, **kwargs):
|
|
|
# register load_extensions in kwargs, so we can chain plugins
|
|
|
kwargs['_load_extension'] = load_extension
|
|
|
# append this path for us to use added plugins or modules
|
|
|
import sys
|
|
|
_cur_path = os.path.dirname(os.path.abspath(__file__))
|
|
|
if _cur_path not in sys.path:
|
|
|
sys.path.append(_cur_path)
|
|
|
|
|
|
registered_extensions[func.__name__] = func
|
|
|
return func(*args, **kwargs)
|
|
|
return wrapper
|
|
|
return wrap
|
|
|
|
|
|
# =============================================================================
|
|
|
# END OF UTILITY FUNCTIONS HERE
|
|
|
# =============================================================================
|
|
|
|
|
|
# Additional mappings that are not present in the pygments lexers
|
|
|
# used for building stats
|
|
|
# format is {'ext':['Names']} eg. {'py':['Python']} note: there can be
|
|
|
# more than one name for extension
|
|
|
# NOTE: that this will override any mappings in LANGUAGES_EXTENSIONS_MAP
|
|
|
# build by pygments
|
|
|
EXTRA_MAPPINGS = {}
|
|
|
|
|
|
# additional lexer definitions for custom files it's overrides pygments lexers,
|
|
|
# and uses defined name of lexer to colorize the files. Format is {'ext':
|
|
|
# 'lexer_name'} List of lexers can be printed running:
|
|
|
# >> python -c "import pprint;from pygments import lexers;
|
|
|
# pprint.pprint([(x[0], x[1]) for x in lexers.get_all_lexers()]);"
|
|
|
|
|
|
EXTRA_LEXERS = {}
|
|
|
|
|
|
|
|
|
CONFIG = DotDict(
|
|
|
slack=DotDict(
|
|
|
api_key='api-key',
|
|
|
api_url='slack-incoming-hook-url',
|
|
|
default_room='#slack-channel',
|
|
|
default_plugin_config={},
|
|
|
),
|
|
|
redmine=DotDict(
|
|
|
api_key='api-key',
|
|
|
default_tracker_url='https://redmine.tracker.url',
|
|
|
default_project_id=None,
|
|
|
default_status_resolved_id=3
|
|
|
),
|
|
|
)
|
|
|
|
|
|
# slack conf
|
|
|
CONFIG.slack.default_plugin_config = {
|
|
|
'INCOMING_WEBHOOK_URL': CONFIG.slack.api_url,
|
|
|
'SLACK_TOKEN': CONFIG.slack.api_key,
|
|
|
'SLACK_ROOM': CONFIG.slack.default_room,
|
|
|
'SLACK_FROM': 'RhodeCode',
|
|
|
'SLACK_FROM_ICON_EMOJI': ':rhodecode:',
|
|
|
}
|
|
|
|
|
|
# redmine smart_pr configuration
|
|
|
def configure_redmine_smart_pr(issues, kwargs):
|
|
|
kwargs['REDMINE_ISSUES'] = issues
|
|
|
kwargs['redmine_tracker_url'] = kwargs.pop(
|
|
|
'redmine_tracker_url', '') or CONFIG.redmine.default_tracker_url
|
|
|
kwargs['redmine_api_key'] = kwargs.pop(
|
|
|
'redmine_api_key', '') or CONFIG.redmine.api_key
|
|
|
kwargs['redmine_project_id'] = kwargs.pop(
|
|
|
'redmine_project_id', '') or CONFIG.redmine.default_project_id
|
|
|
|
|
|
|
|
|
@register('CREATE_REPO_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'repo_name', 'repo_type', 'description', 'private',
|
|
|
'created_on', 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
|
|
|
'clone_uri', 'fork_id', 'group_id', 'created_by'])
|
|
|
def _create_repo_hook(*args, **kwargs):
|
|
|
"""
|
|
|
POST CREATE REPOSITORY HOOK. This function will be executed after
|
|
|
each repository is created. kwargs available:
|
|
|
|
|
|
:param repo_name:
|
|
|
:param repo_type:
|
|
|
:param description:
|
|
|
:param private:
|
|
|
:param created_on:
|
|
|
:param enable_downloads:
|
|
|
:param repo_id:
|
|
|
:param user_id:
|
|
|
:param enable_statistics:
|
|
|
:param clone_uri:
|
|
|
:param fork_id:
|
|
|
:param group_id:
|
|
|
:param created_by:
|
|
|
"""
|
|
|
return 0
|
|
|
CREATE_REPO_HOOK = _create_repo_hook
|
|
|
|
|
|
|
|
|
@register('CREATE_REPO_GROUP_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'group_name', 'group_parent_id', 'group_description',
|
|
|
'group_id', 'user_id', 'created_by', 'created_on', 'enable_locking'])
|
|
|
def _create_repo_group_hook(*args, **kwargs):
|
|
|
"""
|
|
|
POST CREATE REPOSITORY GROUP HOOK, this function will be
|
|
|
executed after each repository group is created. kwargs available:
|
|
|
|
|
|
:param group_name:
|
|
|
:param group_parent_id:
|
|
|
:param group_description:
|
|
|
:param group_id:
|
|
|
:param user_id:
|
|
|
:param created_by:
|
|
|
:param created_on:
|
|
|
:param enable_locking:
|
|
|
"""
|
|
|
return 0
|
|
|
CREATE_REPO_GROUP_HOOK = _create_repo_group_hook
|
|
|
|
|
|
|
|
|
@register('PRE_CREATE_USER_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'username', 'password', 'email', 'firstname',
|
|
|
'lastname', 'active', 'admin', 'created_by'])
|
|
|
def _pre_create_user_hook(*args, **kwargs):
|
|
|
"""
|
|
|
PRE CREATE USER HOOK, this function will be executed before each
|
|
|
user is created, it returns a tuple of bool, reason.
|
|
|
If bool is False the user creation will be stopped and reason
|
|
|
will be displayed to the user. kwargs available:
|
|
|
|
|
|
:param username:
|
|
|
:param password:
|
|
|
:param email:
|
|
|
:param firstname:
|
|
|
:param lastname:
|
|
|
:param active:
|
|
|
:param admin:
|
|
|
:param created_by:
|
|
|
"""
|
|
|
|
|
|
reason = 'allowed'
|
|
|
return True, reason
|
|
|
PRE_CREATE_USER_HOOK = _pre_create_user_hook
|
|
|
|
|
|
|
|
|
@register('CREATE_USER_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'username', 'full_name_or_username', 'full_contact',
|
|
|
'user_id', 'name', 'firstname', 'short_contact', 'admin', 'lastname',
|
|
|
'ip_addresses', 'extern_type', 'extern_name', 'email', 'api_key',
|
|
|
'api_keys', 'last_login', 'full_name', 'active', 'password', 'emails',
|
|
|
'inherit_default_permissions', 'created_by', 'created_on'])
|
|
|
def _create_user_hook(*args, **kwargs):
|
|
|
"""
|
|
|
POST CREATE USER HOOK, this function will be executed after each user is created
|
|
|
kwargs available:
|
|
|
|
|
|
:param username:
|
|
|
:param full_name_or_username:
|
|
|
:param full_contact:
|
|
|
:param user_id:
|
|
|
:param name:
|
|
|
:param firstname:
|
|
|
:param short_contact:
|
|
|
:param admin:
|
|
|
:param lastname:
|
|
|
:param ip_addresses:
|
|
|
:param extern_type:
|
|
|
:param extern_name:
|
|
|
:param email:
|
|
|
:param api_key:
|
|
|
:param api_keys:
|
|
|
:param last_login:
|
|
|
:param full_name:
|
|
|
:param active:
|
|
|
:param password:
|
|
|
:param emails:
|
|
|
:param inherit_default_permissions:
|
|
|
:param created_by:
|
|
|
:param created_on:
|
|
|
"""
|
|
|
return 0
|
|
|
CREATE_USER_HOOK = _create_user_hook
|
|
|
|
|
|
|
|
|
@register('DELETE_REPO_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'repo_name', 'repo_type', 'description', 'private',
|
|
|
'created_on', 'enable_downloads', 'repo_id', 'user_id', 'enable_statistics',
|
|
|
'clone_uri', 'fork_id', 'group_id', 'deleted_by', 'deleted_on'])
|
|
|
def _delete_repo_hook(*args, **kwargs):
|
|
|
"""
|
|
|
POST DELETE REPOSITORY HOOK, this function will be executed after
|
|
|
each repository deletion kwargs available:
|
|
|
|
|
|
:param repo_name:
|
|
|
:param repo_type:
|
|
|
:param description:
|
|
|
:param private:
|
|
|
:param created_on:
|
|
|
:param enable_downloads:
|
|
|
:param repo_id:
|
|
|
:param user_id:
|
|
|
:param enable_statistics:
|
|
|
:param clone_uri:
|
|
|
:param fork_id:
|
|
|
:param group_id:
|
|
|
:param deleted_by:
|
|
|
:param deleted_on:
|
|
|
"""
|
|
|
return 0
|
|
|
DELETE_REPO_HOOK = _delete_repo_hook
|
|
|
|
|
|
|
|
|
@register('DELETE_USER_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'username', 'full_name_or_username', 'full_contact',
|
|
|
'user_id', 'name', 'firstname', 'short_contact', 'admin', 'lastname',
|
|
|
'ip_addresses', 'email', 'api_key', 'last_login', 'full_name', 'active',
|
|
|
'password', 'emails', 'inherit_default_permissions', 'deleted_by'
|
|
|
])
|
|
|
def _delete_user_hook(*args, **kwargs):
|
|
|
"""
|
|
|
POST DELETE USER HOOK, this function will be executed after each
|
|
|
user is deleted kwargs available:
|
|
|
|
|
|
:param username:
|
|
|
:param full_name_or_username:
|
|
|
:param full_contact:
|
|
|
:param user_id:
|
|
|
:param name:
|
|
|
:param firstname:
|
|
|
:param short_contact:
|
|
|
:param admin:
|
|
|
:param lastname:
|
|
|
:param ip_addresses:
|
|
|
:param ldap_dn:
|
|
|
:param email:
|
|
|
:param api_key:
|
|
|
:param last_login:
|
|
|
:param full_name:
|
|
|
:param active:
|
|
|
:param password:
|
|
|
:param emails:
|
|
|
:param inherit_default_permissions:
|
|
|
:param deleted_by:
|
|
|
"""
|
|
|
return 0
|
|
|
DELETE_USER_HOOK = _delete_user_hook
|
|
|
|
|
|
|
|
|
@register('PRE_PUSH_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username',
|
|
|
'ip', 'action', 'repository', 'repo_store_path'])
|
|
|
def _pre_push_hook(*args, **kwargs):
|
|
|
"""
|
|
|
Post push hook
|
|
|
kwargs available:
|
|
|
|
|
|
:param server_url: url of instance that triggered this hook
|
|
|
:param config: path to .ini config used
|
|
|
:param scm: type of VS 'git' or 'hg'
|
|
|
:param username: name of user who pushed
|
|
|
:param ip: ip of who pushed
|
|
|
:param action: push
|
|
|
:param repository: repository name
|
|
|
:param repo_store_path: full path to where repositories are stored
|
|
|
"""
|
|
|
return 0
|
|
|
PRE_PUSH_HOOK = _pre_push_hook
|
|
|
|
|
|
|
|
|
@register('PUSH_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username',
|
|
|
'ip', 'action', 'repository', 'repo_store_path', 'pushed_revs'])
|
|
|
def _push_hook(*args, **kwargs):
|
|
|
"""
|
|
|
POST PUSH HOOK, this function will be executed after each push it's
|
|
|
executed after the build-in hook that RhodeCode uses for logging pushes
|
|
|
kwargs available:
|
|
|
|
|
|
:param server_url: url of instance that triggered this hook
|
|
|
:param config: path to .ini config used
|
|
|
:param scm: type of VS 'git' or 'hg'
|
|
|
:param username: name of user who pushed
|
|
|
:param ip: ip of who pushed
|
|
|
:param action: push
|
|
|
:param repository: repository name
|
|
|
:param repo_store_path: full path to where repositories are stored
|
|
|
:param pushed_revs: list of pushed commit ids
|
|
|
"""
|
|
|
# backward compat
|
|
|
kwargs['commit_ids'] = kwargs['pushed_revs']
|
|
|
|
|
|
# fetch extra fields from repository
|
|
|
call = load_extension('extra_fields.py')
|
|
|
_extra_fields = {}
|
|
|
if call:
|
|
|
repo_extra_fields = call(**kwargs)
|
|
|
# now update if we have extra fields, they have precedence
|
|
|
# this way users can store any configuration inside the database per
|
|
|
# repo
|
|
|
for key, data in repo_extra_fields.items():
|
|
|
kwargs[key] = data['field_value']
|
|
|
_extra_fields[key] = data['field_value']
|
|
|
|
|
|
# fetch pushed commits, from commit_ids list
|
|
|
call = load_extension('extract_commits.py')
|
|
|
extracted_commits = {}
|
|
|
if call:
|
|
|
extracted_commits = call(**kwargs)
|
|
|
# store the commits for the next call chain
|
|
|
kwargs['COMMITS'] = extracted_commits
|
|
|
|
|
|
# slack !
|
|
|
call = load_extension('slack_push_notify.py')
|
|
|
if call:
|
|
|
kwargs.update(CONFIG.slack.default_plugin_config)
|
|
|
call(**kwargs)
|
|
|
|
|
|
# fetch redmine issues from given commits
|
|
|
call = load_extension('extract_redmine_issues.py')
|
|
|
issues = {}
|
|
|
if call:
|
|
|
issues = call(**kwargs)
|
|
|
|
|
|
# redmine smart commits
|
|
|
call = load_extension('redmine_smart_commits.py')
|
|
|
if call:
|
|
|
kwargs['REDMINE_ISSUES'] = issues
|
|
|
|
|
|
kwargs['redmine_tracker_url'] = kwargs.pop(
|
|
|
'redmine_tracker_url', '') or CONFIG.redmine.default_tracker_url
|
|
|
kwargs['redmine_api_key'] = kwargs.pop(
|
|
|
'redmine_api_key', '') or CONFIG.redmine.api_key
|
|
|
kwargs['redmine_status_resolved_id'] = kwargs.pop(
|
|
|
'redmine_status_resolved_id', '') or CONFIG.redmine.default_status_resolved_id
|
|
|
kwargs['redmine_project_id'] = kwargs.pop(
|
|
|
'redmine_project_id', '') or CONFIG.redmine.default_project_id
|
|
|
call(**kwargs)
|
|
|
|
|
|
return 0
|
|
|
PUSH_HOOK = _push_hook
|
|
|
|
|
|
|
|
|
@register('PRE_PULL_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username', 'ip',
|
|
|
'action', 'repository'])
|
|
|
def _pre_pull_hook(*args, **kwargs):
|
|
|
"""
|
|
|
Post pull hook
|
|
|
kwargs available::
|
|
|
|
|
|
:param server_url: url of instance that triggered this hook
|
|
|
:param config: path to .ini config used
|
|
|
:param scm: type of VS 'git' or 'hg'
|
|
|
:param username: name of user who pulled
|
|
|
:param ip: ip of who pulled
|
|
|
:param action: pull
|
|
|
:param repository: repository name
|
|
|
"""
|
|
|
return 0
|
|
|
PRE_PULL_HOOK = _pre_pull_hook
|
|
|
|
|
|
|
|
|
@register('PULL_HOOK')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username', 'ip',
|
|
|
'action', 'repository'])
|
|
|
def _pull_hook(*args, **kwargs):
|
|
|
"""
|
|
|
POST PULL HOOK, this function will be executed after each push it's
|
|
|
executed after the build-in hook that RhodeCode uses for logging pulls
|
|
|
|
|
|
kwargs available:
|
|
|
|
|
|
:param server_url: url of instance that triggered this hook
|
|
|
:param config: path to .ini config used
|
|
|
:param scm: type of VS 'git' or 'hg'
|
|
|
:param username: name of user who pulled
|
|
|
:param ip: ip of who pulled
|
|
|
:param action: pull
|
|
|
:param repository: repository name
|
|
|
"""
|
|
|
return 0
|
|
|
PULL_HOOK = _pull_hook
|
|
|
|
|
|
|
|
|
# =============================================================================
|
|
|
# PULL REQUEST RELATED HOOKS
|
|
|
# =============================================================================
|
|
|
@register('CREATE_PULL_REQUEST')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username', 'ip',
|
|
|
'action', 'repository', 'pull_request_id', 'url', 'title', 'description',
|
|
|
'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
|
|
|
'mergeable', 'source', 'target', 'author', 'reviewers'])
|
|
|
def _create_pull_request_hook(*args, **kwargs):
|
|
|
"""
|
|
|
|
|
|
"""
|
|
|
# extract extra fields and default reviewers from target
|
|
|
kwargs['REPOSITORY'] = kwargs['target']['repository']
|
|
|
|
|
|
call = load_extension('extra_fields.py')
|
|
|
if call:
|
|
|
repo_extra_fields = call(**kwargs)
|
|
|
# now update if we have extra fields, they have precedence
|
|
|
# this way users can store any configuration inside the database per
|
|
|
# repo
|
|
|
for key, data in repo_extra_fields.items():
|
|
|
kwargs[key] = data['field_value']
|
|
|
|
|
|
call = load_extension('default_reviewers.py')
|
|
|
if call:
|
|
|
# read default_reviewers key propagated from extra fields
|
|
|
kwargs['default_reviewers'] = map(string.strip, kwargs.pop(
|
|
|
'default_reviewers', '').split(','))
|
|
|
call(**kwargs)
|
|
|
|
|
|
# extract below from source repo as commits are there
|
|
|
kwargs['REPOSITORY'] = kwargs['source']['repository']
|
|
|
|
|
|
# # fetch pushed commits, from commit_ids list
|
|
|
# call = load_extension('extract_commits.py')
|
|
|
# extracted_commits = {}
|
|
|
# if call:
|
|
|
# extracted_commits = call(**kwargs)
|
|
|
# # store the commits for the next call chain
|
|
|
# kwargs['COMMITS'] = extracted_commits
|
|
|
#
|
|
|
# # fetch issues from given commits
|
|
|
# call = load_extension('extract_redmine_issues.py')
|
|
|
# issues = {}
|
|
|
# if call:
|
|
|
# issues = call(**kwargs)
|
|
|
#
|
|
|
# # redmine smart pr update
|
|
|
# call = load_extension('redmine_pr_flow.py')
|
|
|
# if call:
|
|
|
# # updates kwargs on the fly
|
|
|
# configure_redmine_smart_pr(issues=issues, kwargs=kwargs)
|
|
|
# call(**kwargs)
|
|
|
#
|
|
|
# # slack notification on merging PR
|
|
|
# call = load_extension('slack_message.py')
|
|
|
# if call:
|
|
|
# kwargs.update(CONFIG.slack.default_plugin_config)
|
|
|
# kwargs['SLACK_ROOM'] = '#develop'
|
|
|
# kwargs['SLACK_MESSAGE'] = 'Pull request <%s|#%s> (%s) was created.' % (
|
|
|
# kwargs.get('url'), kwargs.get('pull_request_id'), kwargs.get('title'))
|
|
|
#
|
|
|
# call(**kwargs)
|
|
|
|
|
|
return 0
|
|
|
CREATE_PULL_REQUEST = _create_pull_request_hook
|
|
|
|
|
|
|
|
|
@register('REVIEW_PULL_REQUEST')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username', 'ip',
|
|
|
'action', 'repository', 'pull_request_id', 'url', 'title', 'description',
|
|
|
'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
|
|
|
'mergeable', 'source', 'target', 'author', 'reviewers'])
|
|
|
def _review_pull_request_hook(*args, **kwargs):
|
|
|
"""
|
|
|
|
|
|
"""
|
|
|
# extract extra fields and default reviewers from target
|
|
|
kwargs['REPOSITORY'] = kwargs['target']['repository']
|
|
|
|
|
|
# fetch extra fields
|
|
|
call = load_extension('extra_fields.py')
|
|
|
if call:
|
|
|
repo_extra_fields = call(**kwargs)
|
|
|
# now update if we have extra fields, they have precedence
|
|
|
# this way users can store any configuration inside the database per
|
|
|
# repo
|
|
|
for key, data in repo_extra_fields.items():
|
|
|
kwargs[key] = data['field_value']
|
|
|
|
|
|
# extract below from source repo as commits are there
|
|
|
kwargs['REPOSITORY'] = kwargs['source']['repository']
|
|
|
|
|
|
# fetch pushed commits, from commit_ids list
|
|
|
call = load_extension('extract_commits.py')
|
|
|
extracted_commits = {}
|
|
|
if call:
|
|
|
extracted_commits = call(**kwargs)
|
|
|
# store the commits for the next call chain
|
|
|
kwargs['COMMITS'] = extracted_commits
|
|
|
|
|
|
# fetch issues from given commits
|
|
|
call = load_extension('extract_redmine_issues.py')
|
|
|
issues = {}
|
|
|
if call:
|
|
|
issues = call(**kwargs)
|
|
|
|
|
|
# redmine smart pr update
|
|
|
call = load_extension('redmine_pr_flow.py')
|
|
|
if call:
|
|
|
# updates kwargs on the fly
|
|
|
configure_redmine_smart_pr(issues=issues, kwargs=kwargs)
|
|
|
call(**kwargs)
|
|
|
|
|
|
return 0
|
|
|
REVIEW_PULL_REQUEST = _review_pull_request_hook
|
|
|
|
|
|
|
|
|
@register('UPDATE_PULL_REQUEST')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username', 'ip',
|
|
|
'action', 'repository', 'pull_request_id', 'url', 'title', 'description',
|
|
|
'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
|
|
|
'mergeable', 'source', 'target', 'author', 'reviewers'])
|
|
|
def _update_pull_request_hook(*args, **kwargs):
|
|
|
"""
|
|
|
|
|
|
"""
|
|
|
# extract extra fields and default reviewers from target
|
|
|
kwargs['REPOSITORY'] = kwargs['target']['repository']
|
|
|
|
|
|
# fetch extra fields
|
|
|
call = load_extension('extra_fields.py')
|
|
|
if call:
|
|
|
repo_extra_fields = call(**kwargs)
|
|
|
# now update if we have extra fields, they have precedence
|
|
|
# this way users can store any configuration inside the database per
|
|
|
# repo
|
|
|
for key, data in repo_extra_fields.items():
|
|
|
kwargs[key] = data['field_value']
|
|
|
|
|
|
# extract below from source repo as commits are there
|
|
|
kwargs['REPOSITORY'] = kwargs['source']['repository']
|
|
|
|
|
|
# fetch pushed commits, from commit_ids list
|
|
|
call = load_extension('extract_commits.py')
|
|
|
extracted_commits = {}
|
|
|
if call:
|
|
|
extracted_commits = call(**kwargs)
|
|
|
# store the commits for the next call chain
|
|
|
kwargs['COMMITS'] = extracted_commits
|
|
|
|
|
|
# fetch issues from given commits
|
|
|
call = load_extension('extract_redmine_issues.py')
|
|
|
issues = {}
|
|
|
if call:
|
|
|
issues = call(**kwargs)
|
|
|
|
|
|
# redmine smart pr updated
|
|
|
call = load_extension('redmine_pr_flow.py')
|
|
|
if call:
|
|
|
# updates kwargs on the fly
|
|
|
configure_redmine_smart_pr(issues=issues, kwargs=kwargs)
|
|
|
call(**kwargs)
|
|
|
|
|
|
return 0
|
|
|
UPDATE_PULL_REQUEST = _update_pull_request_hook
|
|
|
|
|
|
|
|
|
@register('MERGE_PULL_REQUEST')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username', 'ip',
|
|
|
'action', 'repository', 'pull_request_id', 'url', 'title', 'description',
|
|
|
'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
|
|
|
'mergeable', 'source', 'target', 'author', 'reviewers'])
|
|
|
def _merge_pull_request_hook(*args, **kwargs):
|
|
|
"""
|
|
|
|
|
|
"""
|
|
|
# extract extra fields and default reviewers from target
|
|
|
kwargs['REPOSITORY'] = kwargs['target']['repository']
|
|
|
|
|
|
# fetch extra fields
|
|
|
call = load_extension('extra_fields.py')
|
|
|
if call:
|
|
|
repo_extra_fields = call(**kwargs)
|
|
|
# now update if we have extra fields, they have precedence
|
|
|
# this way users can store any configuration inside the database per
|
|
|
# repo
|
|
|
for key, data in repo_extra_fields.items():
|
|
|
kwargs[key] = data['field_value']
|
|
|
|
|
|
# extract below from source repo as commits are there
|
|
|
kwargs['REPOSITORY'] = kwargs['source']['repository']
|
|
|
|
|
|
# fetch pushed commits, from commit_ids list
|
|
|
call = load_extension('extract_commits.py')
|
|
|
extracted_commits = {}
|
|
|
if call:
|
|
|
extracted_commits = call(**kwargs)
|
|
|
# store the commits for the next call chain
|
|
|
kwargs['COMMITS'] = extracted_commits
|
|
|
|
|
|
# fetch issues from given commits
|
|
|
call = load_extension('extract_redmine_issues.py')
|
|
|
issues = {}
|
|
|
if call:
|
|
|
issues = call(**kwargs)
|
|
|
|
|
|
# redmine smart pr update
|
|
|
call = load_extension('redmine_pr_flow.py')
|
|
|
if call:
|
|
|
# updates kwargs on the fly
|
|
|
configure_redmine_smart_pr(issues=issues, kwargs=kwargs)
|
|
|
call(**kwargs)
|
|
|
|
|
|
# slack notification on merging PR
|
|
|
call = load_extension('slack_message.py')
|
|
|
if call:
|
|
|
kwargs.update(CONFIG.slack.default_plugin_config)
|
|
|
kwargs['SLACK_ROOM'] = '#develop'
|
|
|
kwargs['SLACK_MESSAGE'] = 'Pull request <%s|#%s> (%s) was merged.' % (
|
|
|
kwargs.get('url'), kwargs.get('pull_request_id'), kwargs.get('title'))
|
|
|
call(**kwargs)
|
|
|
|
|
|
return 0
|
|
|
MERGE_PULL_REQUEST = _merge_pull_request_hook
|
|
|
|
|
|
|
|
|
@register('CLOSE_PULL_REQUEST')
|
|
|
@verify_kwargs(
|
|
|
['_load_extension', 'server_url', 'config', 'scm', 'username', 'ip',
|
|
|
'action', 'repository', 'pull_request_id', 'url', 'title', 'description',
|
|
|
'status', 'created_on', 'updated_on', 'commit_ids', 'review_status',
|
|
|
'mergeable', 'source', 'target', 'author', 'reviewers'])
|
|
|
def _close_pull_request_hook(*args, **kwargs):
|
|
|
"""
|
|
|
|
|
|
"""
|
|
|
# extract extra fields and default reviewers from target
|
|
|
kwargs['REPOSITORY'] = kwargs['target']['repository']
|
|
|
|
|
|
# fetch extra fields
|
|
|
call = load_extension('extra_fields.py')
|
|
|
if call:
|
|
|
repo_extra_fields = call(**kwargs)
|
|
|
# now update if we have extra fields, they have precedence
|
|
|
# this way users can store any configuration inside the database per
|
|
|
# repo
|
|
|
for key, data in repo_extra_fields.items():
|
|
|
kwargs[key] = data['field_value']
|
|
|
|
|
|
# extract below from source repo as commits are there
|
|
|
kwargs['REPOSITORY'] = kwargs['source']['repository']
|
|
|
|
|
|
# fetch pushed commits, from commit_ids list
|
|
|
call = load_extension('extract_commits.py')
|
|
|
extracted_commits = {}
|
|
|
if call:
|
|
|
extracted_commits = call(**kwargs)
|
|
|
# store the commits for the next call chain
|
|
|
kwargs['COMMITS'] = extracted_commits
|
|
|
|
|
|
# fetch issues from given commits
|
|
|
call = load_extension('extract_redmine_issues.py')
|
|
|
issues = {}
|
|
|
if call:
|
|
|
issues = call(**kwargs)
|
|
|
|
|
|
# redmine smart pr update
|
|
|
call = load_extension('redmine_pr_flow.py')
|
|
|
if call:
|
|
|
# updates kwargs on the fly
|
|
|
configure_redmine_smart_pr(issues=issues, kwargs=kwargs)
|
|
|
call(**kwargs)
|
|
|
|
|
|
return 0
|
|
|
CLOSE_PULL_REQUEST = _close_pull_request_hook
|
|
|
|