Verified Commit 02fc68dc authored by Huste, Tobias (FWCC) - 111645's avatar Huste, Tobias (FWCC) - 111645
Browse files

global: process release celery task

parent 86f030e0
Pipeline #8643 failed with stage
in 6 minutes and 24 seconds
......@@ -28,11 +28,12 @@ from invenio_oauth2server.models import Token as ProviderToken
from invenio_oauthclient.handlers import token_getter
from invenio_oauthclient.models import RemoteAccount, RemoteToken
from invenio_oauthclient.proxies import current_oauthclient
from invenio_pidstore import current_pidstore
from six import string_types
from werkzeug.local import LocalProxy
from werkzeug.utils import cached_property, import_string
from .models import Project
from .models import Project, ReleaseStatus
from .utils import iso_utcnow, parse_timestamp, utcnow
......@@ -340,11 +341,30 @@ class GitLabRelease(object):
# TODO: update metadata with additional metadata here
return output
@cached_property
def record(self):
"""Get release record."""
return self.model.record
@cached_property
def status(self):
"""Return the release status of the model."""
return self.model.status
@cached_property
def pid(self):
"""Get PID object for the release record."""
if self.model.status == ReleaseStatus.PUBLISHED and self.record:
fetcher = current_pidstore.fetchers[
current_app.config.get('GITLAB_PID_FETCHER')
]
return fetcher(self.record.id, self.record)
def verify_sender(self):
"""Check if the sender is valid."""
return self.project['path_with_namespace'] in \
self.gl.account.extra_data['projects']
def publish(self):
"""Publish GitLab release as a record."""
with db.session.begin_nested():
......
......@@ -62,6 +62,15 @@ This variable must be set explicitly. Example:
GITLAB_DEPOSIT_CLASS = 'invenio_deposit.api:Deposit'
"""Deposit class that implements a `publish` method."""
GITLAB_RELEASE_CLASS = 'invenio_gitlab.api:GitLabRelease'
"""GitLab API class used for release handling."""
GITLAB_RECORD_SERIALIZER = None
"""Serializer to use to display record metadata."""
GITLAB_PID_FETCHER = 'recid'
"""PID Fetcher for Release records."""
GITLAB_WEBHOOK_RECEIVER_ID = 'gitlab'
"""Local name of webhook receiver."""
......
......@@ -24,6 +24,10 @@ class GitLabError(Exception):
"""General GitLab error."""
class InvalidSenderError(GitLabError):
"""Invalid release sender error."""
class ProjectDisabledError(GitLabError):
"""Tried to create Release, but Project is disabled."""
......
......@@ -21,7 +21,12 @@
from __future__ import absolute_import, print_function
from flask import current_app
from six import string_types
from werkzeug.utils import cached_property, import_string
from . import config
from .api import GitLabRelease
class InvenioGitLab(object):
......@@ -32,6 +37,15 @@ class InvenioGitLab(object):
if app:
self.init_app(app)
@cached_property
def release_api_class(self):
"""Gitlab release API class."""
cls = current_app.config['GITLAB_RELEASE_CLASS']
if isinstance(cls, string_types):
cls = import_string(cls)
assert issubclass(cls, GitLabRelease)
return cls
def init_app(self, app):
"""Flask application initialization."""
self.init_config(app)
......
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 HZDR
#
# This file is part of RODARE.
#
# invenio-gitlab is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# invenio-gitlab is distributed in the hope that
# it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Rodare. If not, see <http://www.gnu.org/licenses/>.
"""Proxy for current gitlab extension."""
from flask import current_app
from werkzeug.local import LocalProxy
current_gitlab = LocalProxy(
lambda: current_app.extenstions['invenio-gitlab']
)
# -*- coding: utf-8 -*-
#
# Copyright (C) 2019 HZDR
#
# This file is part of RODARE.
#
# invenio-gitlab is free software: you can redistribute it
# and/or modify it under the terms of the GNU General Public License as
# published by the Free Software Foundation, either version 3 of the License,
# or (at your option) any later version.
#
# invenio-gitlab is distributed in the hope that
# it will be useful, but WITHOUT ANY WARRANTY; without even the implied
# warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Rodare. If not, see <http://www.gnu.org/licenses/>.
"""Celery tasks for GitLab integration."""
from __future__ import absolute_import
import json
from celery import shared_task
from flask import current_app
@shared_task(ignore_result=True)
def process_release(release_id, verify_sender=False):
"""Process a received release from GitLab."""
from invenio_db import db
from invenio_rest.errors import RESTException
from .errors import InvalidSenderError
from .models import Release, ReleaseStatus
from .proxies import current_gitlab
release_model = Release.query.filter(
Release.release_id == release_id,
Release.status.in_([ReleaseStatus.RECEIVED, ReleaseStatus.FAILED]),
).one()
release_model.status = ReleaseStatus.PROCESSING
db.session.commit()
release = current_gitlab.release_api_class(release_model)
if verify_sender and not release.verify_sender():
raise InvalidSenderError(
u'Invalid sender for event {event} for user {user}'
.format(event=release.event.id, user=release.event.user_id)
)
def _get_err_obj(msg):
"""Generate the error entry with a Sentry ID."""
err = {'errors': msg}
if hasattr(g, 'sentry_event_id'):
err['error_id'] = str(g.sentry_event_id)
return err
try:
release.publish()
release.models.status = ReleaseStatus.PUBLISHED
except RESTException as rest_ex:
release.model.errors = json.loads(rest_ex.get_body())
release.model.status = ReleaseStatus.FAILED
current_app.logger.exception(
u'Error while processing {release}'.format(release=release.model))
except Exception:
release.model.errors = _get_err_obj('Unknown error occured.')
release.model.status = ReleaseStatus.FAILED
current_app.logger.exception(
u'Error while processing {release}'.format(release=release.model))
finally:
db.session.commit()
......@@ -69,14 +69,17 @@ setup_requires = [
install_requires = [
'Flask>=0.11.1',
'Flask-BabelEx>=0.9.2',
'Flask-OAuthlib>=0.9.3',
'humanize>=0.5.1',
'invenio-accounts>=1.0.0',
'invenio-assets>=1.0.0',
'invenio-celery>=1.0.0',
'invenio-deposit>=1.0.0a9',
'invenio-oauthclient>=1.0.0',
'invenio-oauth2server>=1.0.0',
'invenio-pidstore>=1.0.0',
'invenio-records>=1.0.0',
'invenio-webhooks>=1.0.0a4',
'oauthlib>=2.0.0,<3.0.0',
'python-gitlab>=1.7.0',
]
......@@ -113,6 +116,9 @@ setup(
'invenio_i18n.translations': [
'messages = invenio_gitlab',
],
'invenio_celery.tasks': [
'invenio_gitlab = invenio_gitlab.tasks',
],
'invenio_db.models': [
'invenio_gitlab = invenio_gitlab.models',
],
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment