|
Pierre-Yves Chibon |
aabc84 |
# -*- coding: utf-8 -*-
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
"""
|
|
Pierre-Yves Chibon |
aabc84 |
(c) 2016 - Copyright Red Hat Inc
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
Authors:
|
|
Pierre-Yves Chibon |
aabc84 |
Pierre-Yves Chibon <pingou@pingoured.fr></pingou@pingoured.fr>
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
"""
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
67d1cc |
from __future__ import unicode_literals, absolute_import
|
|
Aurélien Bompard |
dcf6f6 |
|
|
Pierre-Yves Chibon |
b130e5 |
import flask
|
|
Pierre-Yves Chibon |
aabc84 |
import sqlalchemy as sa
|
|
Pierre-Yves Chibon |
aabc84 |
import wtforms
|
|
Pierre-Yves Chibon |
9c2953 |
|
|
Pierre-Yves Chibon |
5a5352 |
try:
|
|
Pierre-Yves Chibon |
2011e2 |
from flask_wtf import FlaskForm
|
|
Pierre-Yves Chibon |
2011e2 |
except ImportError:
|
|
Pierre-Yves Chibon |
5a5352 |
from flask_wtf import Form as FlaskForm
|
|
Pierre-Yves Chibon |
aabc84 |
from sqlalchemy.orm import relation
|
|
Pierre-Yves Chibon |
aabc84 |
from sqlalchemy.orm import backref
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
930073 |
import pagure.lib.login
|
|
Pierre-Yves Chibon |
43d465 |
from pagure.hooks import BaseHook, BaseRunner, RequiredIf
|
|
Pierre-Yves Chibon |
e24815 |
from pagure.lib.model import BASE, Project
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
class PagureCITable(BASE):
|
|
Pierre-Yves Chibon |
aabc84 |
""" Stores information about the CI linked to on a project.
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
Table -- hook_pagure_ci
|
|
Pierre-Yves Chibon |
aabc84 |
"""
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
9c2953 |
__tablename__ = "hook_pagure_ci"
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
id = sa.Column(sa.Integer, primary_key=True)
|
|
Pierre-Yves Chibon |
aabc84 |
project_id = sa.Column(
|
|
Pierre-Yves Chibon |
aabc84 |
sa.Integer,
|
|
Pierre-Yves Chibon |
9c2953 |
sa.ForeignKey("projects.id", onupdate="CASCADE", ondelete="CASCADE"),
|
|
Pierre-Yves Chibon |
aabc84 |
nullable=False,
|
|
Pierre-Yves Chibon |
aabc84 |
unique=True,
|
|
Pierre-Yves Chibon |
9c2953 |
index=True,
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
9c2953 |
pagure_ci_token = sa.Column(sa.String(32), nullable=True, index=True)
|
|
Pierre-Yves Chibon |
9c2953 |
ci_type = sa.Column(sa.String(255), nullable=True)
|
|
Pierre-Yves Chibon |
9c2953 |
ci_url = sa.Column(sa.String(255), nullable=True, unique=False)
|
|
Pierre-Yves Chibon |
9c2953 |
ci_job = sa.Column(sa.String(255), nullable=True, unique=False)
|
|
Pierre-Yves Chibon |
9c6dee |
ci_username = sa.Column(sa.String(255), nullable=True, unique=False)
|
|
Pierre-Yves Chibon |
9c6dee |
ci_password = sa.Column(sa.String(255), nullable=True, unique=False)
|
|
Pierre-Yves Chibon |
aabc84 |
active = sa.Column(sa.Boolean, nullable=False, default=False)
|
|
Clement Verna |
44c44e |
active_commit = sa.Column(sa.Boolean, nullable=False, default=False)
|
|
Clement Verna |
44c44e |
active_pr = sa.Column(sa.Boolean, nullable=False, default=False)
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
project = relation(
|
|
Pierre-Yves Chibon |
9c2953 |
"Project",
|
|
Pierre-Yves Chibon |
9c2953 |
remote_side=[Project.id],
|
|
Pierre-Yves Chibon |
aabc84 |
backref=backref(
|
|
Pierre-Yves Chibon |
9c2953 |
"ci_hook",
|
|
Pierre-Yves Chibon |
9c2953 |
cascade="delete, delete-orphan",
|
|
Pierre-Yves Chibon |
9c2953 |
single_parent=True,
|
|
Pierre-Yves Chibon |
9c2953 |
uselist=False,
|
|
Pierre-Yves Chibon |
9c2953 |
),
|
|
Pierre-Yves Chibon |
aabc84 |
)
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
e24815 |
|
|
Pierre-Yves Chibon |
43d465 |
class PagureCIRunner(BaseRunner):
|
|
Pierre-Yves Chibon |
43d465 |
""" Runner for the pagure-ci hook, it does nothing as the magic is part
|
|
Pierre-Yves Chibon |
43d465 |
of the CI system itself (to see if there was a commit made and build if
|
|
Pierre-Yves Chibon |
43d465 |
so).
|
|
Pierre-Yves Chibon |
43d465 |
"""
|
|
Pierre-Yves Chibon |
998b35 |
|
|
Pierre-Yves Chibon |
43d465 |
pass
|
|
Pierre-Yves Chibon |
43d465 |
|
|
Pierre-Yves Chibon |
43d465 |
|
|
Pierre-Yves Chibon |
e24815 |
tmpl = """
|
|
Pierre-Yves Chibon |
c99ccd |
{% if repo | hasattr('ci_hook') and repo.ci_hook and
|
|
Pierre-Yves Chibon |
78837b |
repo.ci_hook.pagure_ci_token %}
|
|
Pierre-Yves Chibon |
005f5d |
|
|
Pierre-Yves Chibon |
005f5d |
The token to be used by jenkins to trigger the build is:
|
|
Pierre-Yves Chibon |
005f5d |
|
|
Pierre-Yves Chibon |
78837b |
{{ repo.ci_hook.pagure_ci_token}}
|
|
Pierre-Yves Chibon |
005f5d |
|
|
Pierre-Yves Chibon |
005f5d |
|
|
Pierre-Yves Chibon |
005f5d |
The URL to be used to POST the results of your build is:
|
|
Pierre-Yves Chibon |
e24815 |
|
|
Pierre-Yves Chibon |
e24815 |
{{ (config['APP_URL'][:-1] if config['APP_URL'].endswith('/')
|
|
Pierre-Yves Chibon |
e24815 |
else config['APP_URL'])
|
|
Pierre-Yves Chibon |
78837b |
+ url_for('api_ns.%s_ci_notification' % repo.ci_hook.ci_type,
|
|
Pierre-Yves Chibon |
5c0b16 |
repo=repo.name, username=username, namespace=repo.namespace,
|
|
Pierre-Yves Chibon |
78837b |
pagure_ci_token=repo.ci_hook.pagure_ci_token) }}
|
|
Pierre-Yves Chibon |
e24815 |
|
|
Pierre-Yves Chibon |
e24815 |
|
|
Pierre-Yves Chibon |
e24815 |
{% else %}
|
|
Clement Verna |
524438 |
You will have access to the token used by the CI service to trigger the job
|
|
Pierre-Yves Chibon |
2c9f94 |
and the URL needed to report back the job status in pagure after the plugin
|
|
Pierre-Yves Chibon |
2c9f94 |
activation.
|
|
Pierre-Yves Chibon |
e24815 |
{% endif %}
|
|
Pierre-Yves Chibon |
e24815 |
"""
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
5a5352 |
class PagureCiForm(FlaskForm):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Form to configure the CI hook. """
|
|
Pierre-Yves Chibon |
9c2953 |
|
|
Pierre-Yves Chibon |
e24815 |
ci_type = wtforms.SelectField(
|
|
Pierre-Yves Chibon |
9c2953 |
"Type of CI service",
|
|
Pierre-Yves Chibon |
9c2953 |
[RequiredIf(["active_commit", "active_pr"])],
|
|
Pierre-Yves Chibon |
9c2953 |
choices=[],
|
|
Pierre-Yves Chibon |
aabc84 |
)
|
|
Clement Verna |
44c44e |
|
|
Lenka Segura |
643d50 |
ci_url = wtforms.StringField(
|
|
Pierre-Yves Chibon |
9c2953 |
"URL to the project on the CI service",
|
|
Pierre-Yves Chibon |
9c2953 |
[
|
|
Pierre-Yves Chibon |
9c2953 |
RequiredIf(["active_commit", "active_pr"]),
|
|
Pierre-Yves Chibon |
9c2953 |
wtforms.validators.Length(max=255),
|
|
Pierre-Yves Chibon |
9c2953 |
],
|
|
Pierre-Yves Chibon |
aabc84 |
)
|
|
Clement Verna |
5434db |
|
|
Pierre-Yves Chibon |
9c6dee |
ci_username = wtforms.StringField(
|
|
Pierre-Yves Chibon |
9c6dee |
"Username to authenticate with if needed",
|
|
Pierre-Yves Chibon |
9c6dee |
[wtforms.validators.Optional(), wtforms.validators.Length(max=255)],
|
|
Pierre-Yves Chibon |
9c6dee |
)
|
|
Pierre-Yves Chibon |
9c6dee |
|
|
Pierre-Yves Chibon |
9c6dee |
ci_password = wtforms.StringField(
|
|
Pierre-Yves Chibon |
9c6dee |
"Password to authenticate with if needed",
|
|
Pierre-Yves Chibon |
9c6dee |
[wtforms.validators.Optional(), wtforms.validators.Length(max=255)],
|
|
Pierre-Yves Chibon |
9c6dee |
)
|
|
Pierre-Yves Chibon |
9c6dee |
|
|
Lenka Segura |
643d50 |
ci_job = wtforms.StringField(
|
|
Pierre-Yves Chibon |
9c2953 |
"Name of the job to trigger",
|
|
Pierre-Yves Chibon |
9c2953 |
[
|
|
Pierre-Yves Chibon |
9c2953 |
RequiredIf(["active_commit", "active_pr"]),
|
|
Pierre-Yves Chibon |
9c2953 |
wtforms.validators.Length(max=255),
|
|
Pierre-Yves Chibon |
9c2953 |
],
|
|
Clement Verna |
5434db |
)
|
|
Clement Verna |
44c44e |
|
|
Clement Verna |
dd6f03 |
# The active field is not render in the UI it used
|
|
Clement Verna |
dd6f03 |
# to hold the result of a logical OR between active_pr
|
|
Clement Verna |
dd6f03 |
# and active_commit.
|
|
Clement Verna |
dd6f03 |
# The value of active is set in pagure.ui.plugins.view_plugin
|
|
Pierre-Yves Chibon |
aabc84 |
active = wtforms.BooleanField(
|
|
Pierre-Yves Chibon |
9c2953 |
"Activate Pagure CI service", [wtforms.validators.Optional()]
|
|
Clement Verna |
44c44e |
)
|
|
Clement Verna |
44c44e |
|
|
Clement Verna |
44c44e |
active_commit = wtforms.BooleanField(
|
|
Pierre-Yves Chibon |
9c2953 |
"Trigger CI job on commits", [wtforms.validators.Optional()]
|
|
Clement Verna |
44c44e |
)
|
|
Clement Verna |
44c44e |
|
|
Clement Verna |
44c44e |
active_pr = wtforms.BooleanField(
|
|
Pierre-Yves Chibon |
9c2953 |
"Trigger CI job on pull-requests", [wtforms.validators.Optional()]
|
|
Pierre-Yves Chibon |
aabc84 |
)
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
def __init__(self, *args, **kwargs):
|
|
Pierre-Yves Chibon |
aabc84 |
""" Calls the default constructor with the normal argument but
|
|
Pierre-Yves Chibon |
aabc84 |
uses the list of collection provided to fill the choices of the
|
|
Pierre-Yves Chibon |
aabc84 |
drop-down list.
|
|
Pierre-Yves Chibon |
aabc84 |
"""
|
|
Pierre-Yves Chibon |
aabc84 |
super(PagureCiForm, self).__init__(*args, **kwargs)
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
9c2953 |
types = pagure.config.config.get("PAGURE_CI_SERVICES", [])
|
|
Pierre-Yves Chibon |
9c2953 |
self.ci_type.choices = [(ci_type, ci_type) for ci_type in types]
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
class PagureCi(BaseHook):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Continuous Integration (CI) hooks. """
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
9c2953 |
name = "Pagure CI"
|
|
Pierre-Yves Chibon |
9c2953 |
description = (
|
|
Pierre-Yves Chibon |
9c2953 |
"Integrate continuous integration (CI) services into your "
|
|
Pierre-Yves Chibon |
9c2953 |
"pagure project, providing you notifications for every pull-request "
|
|
Pierre-Yves Chibon |
9c2953 |
"opened in the project."
|
|
Pierre-Yves Chibon |
9c2953 |
)
|
|
Pierre-Yves Chibon |
e24815 |
extra_info = tmpl
|
|
Pierre-Yves Chibon |
aabc84 |
form = PagureCiForm
|
|
Pierre-Yves Chibon |
aabc84 |
db_object = PagureCITable
|
|
Pierre-Yves Chibon |
9c2953 |
backref = "ci_hook"
|
|
Pierre-Yves Chibon |
9c2953 |
form_fields = ["ci_type", "ci_url", "ci_job", "active_commit", "active_pr"]
|
|
Pierre-Yves Chibon |
43d465 |
runner = PagureCIRunner
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
@classmethod
|
|
Pierre-Yves Chibon |
aabc84 |
def set_up(cls, project):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Install the generic post-receive hook that allow us to call
|
|
Pierre-Yves Chibon |
aabc84 |
multiple post-receive hooks as set per plugin.
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
8bb53a |
pass
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
@classmethod
|
|
Pierre-Yves Chibon |
aabc84 |
def install(cls, project, dbobj):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Method called to install the hook for a project.
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
:arg project: a ``pagure.model.Project`` object to which the hook
|
|
Pierre-Yves Chibon |
aabc84 |
should be installed
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Pierre-Yves Chibon |
8bb53a |
if not dbobj.pagure_ci_token:
|
|
Pierre-Yves Chibon |
8bb53a |
dbobj.pagure_ci_token = pagure.lib.login.id_generator(32)
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
@classmethod
|
|
Pierre-Yves Chibon |
aabc84 |
def remove(cls, project):
|
|
Pierre-Yves Chibon |
9c2953 |
""" Method called to remove the hook of a project.
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
aabc84 |
:arg project: a ``pagure.model.Project`` object to which the hook
|
|
Pierre-Yves Chibon |
aabc84 |
should be installed
|
|
Pierre-Yves Chibon |
aabc84 |
|
|
Pierre-Yves Chibon |
9c2953 |
"""
|
|
Farhaan Bukhsh |
322d8d |
if project.ci_hook is not None:
|
|
Pierre-Yves Chibon |
fc5bca |
project.ci_hook.pagure_ci_token = None
|
|
Pierre-Yves Chibon |
b130e5 |
flask.g.session.commit()
|