mirror of https://github.com/sipwise/repoapi.git
* using https://github.com/manosim/django-rest-framework-api-key for Permissions. Will generate an Auth KEY for jenkins to be able to trigger build from there using build REST API * store the info needed to trigger builds for a set of projects for a release - build is a list of projects to be built with branch or tag as orig and release as destination for a debian distribution * added release_uuid to JenkinsJobInfo model - release_uuid is the way to group project builds for a release - tag works for group of jobs for a project Change-Id: Iebeaa54308c3e569a167f55d98c184b52248af8achanges/42/13742/7
parent
9129897683
commit
2cf5b8da53
@ -0,0 +1,22 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.contrib import admin
|
||||
from . import models
|
||||
|
||||
|
||||
@admin.register(models.BuildRelease)
|
||||
class JenkinsBuildInfoAdmin(admin.ModelAdmin):
|
||||
list_filter = ('release',)
|
@ -0,0 +1,5 @@
|
||||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class ReleaseConfig(AppConfig):
|
||||
name = 'build'
|
@ -0,0 +1,15 @@
|
||||
[
|
||||
{
|
||||
"model": "build.buildrelease",
|
||||
"pk": 1,
|
||||
"fields": {
|
||||
"uuid": "dbe569f7-eab6-4532-a6d1-d31fb559649b",
|
||||
"start_date": "2017-07-14T07:55:11.714Z",
|
||||
"tag": "",
|
||||
"branch": "mr5.5",
|
||||
"release": "release-mr5.5",
|
||||
"distribution": "auto",
|
||||
"projects": "kamailio,lua-ngcp-kamailio,ngcp-panel"
|
||||
}
|
||||
}
|
||||
]
|
@ -0,0 +1,32 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9 on 2017-06-09 19:28
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='BuildRelease',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True,
|
||||
primary_key=True,
|
||||
serialize=False,
|
||||
verbose_name='ID')),
|
||||
('uuid', models.CharField(max_length=64, unique=True)),
|
||||
('start_date', models.DateTimeField(auto_now_add=True)),
|
||||
('tag', models.CharField(max_length=50, null=True)),
|
||||
('branch', models.CharField(max_length=50)),
|
||||
('release', models.CharField(db_index=True, max_length=50)),
|
||||
('distribution', models.CharField(max_length=50)),
|
||||
('projects', models.TextField(null=False)),
|
||||
],
|
||||
),
|
||||
]
|
@ -0,0 +1,27 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.db.models import signals
|
||||
from .br import BuildRelease
|
||||
from build.tasks import build_release
|
||||
|
||||
|
||||
def br_manage(sender, **kwargs):
|
||||
if kwargs["created"]:
|
||||
instance = kwargs["instance"]
|
||||
build_release.delay(instance.uuid)
|
||||
|
||||
post_save = signals.post_save.connect
|
||||
post_save(br_manage, sender=BuildRelease)
|
@ -0,0 +1,36 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
import logging
|
||||
from django.db import models
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class BuildRelease(models.Model):
|
||||
uuid = models.CharField(max_length=64, unique=True, null=False)
|
||||
start_date = models.DateTimeField(auto_now_add=True)
|
||||
tag = models.CharField(max_length=50, null=True, blank=True)
|
||||
branch = models.CharField(max_length=50, null=False)
|
||||
release = models.CharField(max_length=50, null=False,
|
||||
db_index=True)
|
||||
distribution = models.CharField(max_length=50, null=False)
|
||||
projects = models.TextField(null=False)
|
||||
|
||||
def __str__(self):
|
||||
return "%s[%s]" % (self.release, self.uuid)
|
||||
|
||||
@property
|
||||
def projects_list(self):
|
||||
return [x.strip() for x in self.projects.split(',')]
|
@ -0,0 +1,31 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from rest_framework import serializers
|
||||
from . import models
|
||||
|
||||
|
||||
class BuildReleaseSerializer(serializers.ModelSerializer):
|
||||
|
||||
class Meta:
|
||||
model = models.BuildRelease
|
||||
fields = '__all__'
|
||||
|
||||
def validate_projects(self, value):
|
||||
projects = [x.strip() for x in value.split(',')]
|
||||
if len(projects) <= 0:
|
||||
raise serializers.ValidationError(
|
||||
"projects is not a list of coma separate elements")
|
||||
return ','.join(projects)
|
@ -0,0 +1,36 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
from __future__ import absolute_import
|
||||
|
||||
import logging
|
||||
from celery import shared_task
|
||||
from build.utils import trigger_build
|
||||
from build.models.br import BuildRelease
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
@shared_task(ignore_result=True)
|
||||
def build_release(uuid):
|
||||
instance = BuildRelease.objects.get(uuid=uuid)
|
||||
if instance.tag:
|
||||
branch_or_tag = "tag/%s" % instance.tag
|
||||
else:
|
||||
branch_or_tag = "branch/%s" % instance.branch
|
||||
for project in instance.projects_list:
|
||||
url = trigger_build(project, instance.uuid, instance.release,
|
||||
trigger_branch_or_tag=branch_or_tag,
|
||||
trigger_distribution=instance.distribution)
|
||||
logger.debug("%s triggered" % url)
|
@ -0,0 +1,28 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this prograproj. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.test import TestCase, override_settings
|
||||
from build.models import BuildRelease
|
||||
|
||||
|
||||
@override_settings(DEBUG=True)
|
||||
class BuildReleaseTestCase(TestCase):
|
||||
fixtures = ['test_models', ]
|
||||
|
||||
def test_projects_list(self):
|
||||
build = BuildRelease.objects.get(
|
||||
uuid="dbe569f7-eab6-4532-a6d1-d31fb559649b")
|
||||
self.assertItemsEqual(build.projects_list,
|
||||
['kamailio', 'lua-ngcp-kamailio', 'ngcp-panel'])
|
@ -0,0 +1,88 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.core.urlresolvers import reverse
|
||||
from rest_framework import status
|
||||
from rest_framework.test import APITestCase
|
||||
from django.test import override_settings
|
||||
from repoapi.test.base import BaseTest
|
||||
from rest_framework_api_key.models import APIKey
|
||||
from rest_framework_api_key.helpers import generate_key
|
||||
|
||||
|
||||
class APIAuthenticatedTestCase(BaseTest, APITestCase):
|
||||
|
||||
APP_NAME = 'Project Tests'
|
||||
|
||||
def setUp(self):
|
||||
super(APIAuthenticatedTestCase, self).setUp()
|
||||
self.app_key = APIKey.objects.create(
|
||||
name=self.APP_NAME, key=generate_key())
|
||||
self.client.credentials(HTTP_API_KEY=self.app_key.key)
|
||||
|
||||
|
||||
@override_settings(DEBUG=True)
|
||||
class TestRest(APIAuthenticatedTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(TestRest, self).setUp()
|
||||
self.url = reverse('build:list')
|
||||
|
||||
def test_trunk_empty_projects(self):
|
||||
data = {
|
||||
'uuid': 'fake_uuid',
|
||||
'tag': None,
|
||||
'branch': 'master',
|
||||
'release': 'release-trunk-stretch',
|
||||
'distribution': 'stretch',
|
||||
'projects': None
|
||||
}
|
||||
response = self.client.post(self.url, data, format='json')
|
||||
self.assertNotEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
def test_trunk_wrong_projects(self):
|
||||
data = {
|
||||
'uuid': 'fake_uuid',
|
||||
'tag': None,
|
||||
'branch': 'master',
|
||||
'release': 'release-trunk-stretch',
|
||||
'distribution': 'stretch',
|
||||
'projects': ''
|
||||
}
|
||||
response = self.client.post(self.url, data, format='json')
|
||||
self.assertNotEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
|
||||
def test_trunk(self):
|
||||
data = {
|
||||
'uuid': 'fake_uuid',
|
||||
'tag': None,
|
||||
'branch': 'master',
|
||||
'release': 'release-trunk-stretch',
|
||||
'distribution': 'stretch',
|
||||
'projects': ' kamailio , sems'
|
||||
}
|
||||
data_all = {
|
||||
'uuid': 'fake_uuid',
|
||||
'tag': None,
|
||||
'branch': 'master',
|
||||
'release': 'release-trunk-stretch',
|
||||
'distribution': 'stretch',
|
||||
'projects': 'kamailio,sems'
|
||||
}
|
||||
response = self.client.post(self.url, data, format='json')
|
||||
self.assertEqual(response.status_code, status.HTTP_201_CREATED)
|
||||
data_all['start_date'] = response.data['start_date']
|
||||
data_all['id'] = response.data['id']
|
||||
self.assertItemsEqual(response.data, data_all)
|
@ -0,0 +1,24 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf.urls import url
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
url(r'^$', views.BuildReleaseList.as_view(),
|
||||
name='list'),
|
||||
url(r'^(?P<pk>[0-9]+)/?$', views.BuildReleaseDetail.as_view(),
|
||||
name='detail'),
|
||||
]
|
@ -0,0 +1,60 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import logging
|
||||
import urllib
|
||||
import uuid
|
||||
from django.conf import settings
|
||||
from repoapi.utils import openurl
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
project_url = ("{base}/job/{job}/buildWithParameters?"
|
||||
"token={token}&cause={cause}&branch={branch}&"
|
||||
"tag={tag}&release={release}&"
|
||||
"distribution={distribution}&uuid={uuid}&"
|
||||
"release_uuid={release_uuid}")
|
||||
|
||||
|
||||
def trigger_build(project, release_uuid, trigger_release=None,
|
||||
trigger_branch_or_tag=None,
|
||||
trigger_distribution=None):
|
||||
params = {
|
||||
'base': settings.JENKINS_URL,
|
||||
'job': project,
|
||||
'token': urllib.quote(settings.JENKINS_TOKEN),
|
||||
'cause': urllib.quote(trigger_release),
|
||||
'branch': 'none',
|
||||
'tag': 'none',
|
||||
'release': urllib.quote(trigger_release),
|
||||
'distribution': urllib.quote(trigger_distribution),
|
||||
'uuid': uuid.uuid4(),
|
||||
'release_uuid': release_uuid,
|
||||
}
|
||||
if trigger_branch_or_tag.startswith("tag/"):
|
||||
tag = trigger_branch_or_tag.split("tag/")[1]
|
||||
params['tag'] = urllib.quote(tag)
|
||||
elif trigger_branch_or_tag.startswith("branch/"):
|
||||
branch = trigger_branch_or_tag.split("branch/")[1]
|
||||
params['branch'] = urllib.quote(branch)
|
||||
else:
|
||||
params['branch'] = urllib.quote(trigger_branch_or_tag)
|
||||
|
||||
url = project_url.format(**params)
|
||||
if settings.DEBUG:
|
||||
logger.debug("Debug mode, would trigger: %s", url)
|
||||
else:
|
||||
openurl(url)
|
||||
return "{base}/job/{job}/".format(**params)
|
@ -0,0 +1,41 @@
|
||||
# Copyright (C) 2017 The Sipwise Team - http://sipwise.com
|
||||
|
||||
# This program 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.
|
||||
|
||||
# This program 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 this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from django.conf import settings
|
||||
import django_filters
|
||||
from rest_framework import generics
|
||||
from rest_framework_api_key.permissions import HasAPIAccess
|
||||
from . import models, serializers
|
||||
|
||||
|
||||
class BuildReleaseFilter(django_filters.FilterSet):
|
||||
|
||||
class Meta:
|
||||
model = models.BuildRelease
|
||||
fields = ['release', 'start_date']
|
||||
order_by = ['-start_date', ]
|
||||
|
||||
|
||||
class BuildReleaseList(generics.ListCreateAPIView):
|
||||
if settings.BUILD_KEY_AUTH:
|
||||
permission_classes = (HasAPIAccess,)
|
||||
queryset = models.BuildRelease.objects.all()
|
||||
serializer_class = serializers.BuildReleaseSerializer
|
||||
filter_class = BuildReleaseFilter
|
||||
|
||||
|
||||
class BuildReleaseDetail(generics.RetrieveAPIView):
|
||||
queryset = models.BuildRelease.objects.all()
|
||||
serializer_class = serializers.BuildReleaseSerializer
|
@ -0,0 +1,28 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Generated by Django 1.9 on 2017-06-09 19:54
|
||||
from __future__ import unicode_literals
|
||||
|
||||
from django.db import migrations, models
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
('repoapi', '0007_auto_20160718_1136'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='jenkinsbuildinfo',
|
||||
name='param_release_uuid',
|
||||
field=models.CharField(max_length=64, null=True),
|
||||
),
|
||||
migrations.AlterIndexTogether(
|
||||
name='jenkinsbuildinfo',
|
||||
index_together=set([
|
||||
('param_release_uuid', 'tag'),
|
||||
('param_release', 'projectname', 'tag'),
|
||||
('param_release', 'projectname')
|
||||
]),
|
||||
),
|
||||
]
|
Loading…
Reference in new issue