+
Release {{ release }}
+ {% for project in projects %}
+
-
-
- -
-
{{ p }}-get-source
-
- -
-
{{ p }}-source-tests
-
- -
-
{{ p }}-source
-
- -
-
{{ p }}-binaries
-
- -
-
{{ p }}-repos
-
-
+
-
+
-{% endfor %}
-
+ {% endfor %}
{% endblock %}
{% block extrajs %}
diff --git a/panel/tests.py b/panel/tests.py
deleted file mode 100644
index 221a42f..0000000
--- a/panel/tests.py
+++ /dev/null
@@ -1,18 +0,0 @@
-# Copyright (C) 2015 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
.
-
-from django.test import TestCase
-
-# Create your tests here.
diff --git a/panel/urls.py b/panel/urls.py
index 82ed423..7bddd81 100644
--- a/panel/urls.py
+++ b/panel/urls.py
@@ -13,10 +13,12 @@
# You should have received a copy of the GNU General Public License along
# with this program. If not, see
.
-from django.conf.urls import include, url
+from django.conf.urls import url
from . import views
urlpatterns = [
url(r'^$', views.index, name='index'),
- url(r'^(?P
.+)/$', views.release, name='release'),
+ url(r'^(?P[\w\d\.-]+)/$', views.release, name='release-view'),
+ url(r'^(?P[\w\d\.-]+)/(?P[\w\d-]+)/$',
+ views.project, name='project-view'),
]
diff --git a/panel/views.py b/panel/views.py
index cbafcc5..a454cd4 100644
--- a/panel/views.py
+++ b/panel/views.py
@@ -26,3 +26,8 @@ def index(request):
def release(request, release):
context = {'projects': models.PROJECTS, 'release': release}
return render(request, 'panel/release.html', context)
+
+
+def project(request, release, project):
+ context = {'project': project, 'release': release}
+ return render(request, 'panel/project.html', context)
diff --git a/repoapi/fixtures/test_model_queries.json b/repoapi/fixtures/test_model_queries.json
new file mode 100644
index 0000000..96a1bcc
--- /dev/null
+++ b/repoapi/fixtures/test_model_queries.json
@@ -0,0 +1,86 @@
+[
+ {
+ "fields": {
+ "buildnumber": 1,
+ "date": "2015-05-01T12:57:54.379Z",
+ "gerrit_change": null,
+ "gerrit_eventtype": null,
+ "gerrit_patchset": null,
+ "job_url": "https://jenkins.mgm.sipwise.com/job/foo-get-code/",
+ "param_branch": null,
+ "param_distribution": "wheezy",
+ "param_ppa": null,
+ "param_release": "mr3.1-fake",
+ "param_tag": null,
+ "projectname": "fake-source",
+ "repo_name": null,
+ "result": "FAILED",
+ "tag": "UUID1"
+ },
+ "model": "repoapi.jenkinsbuildinfo",
+ "pk": 1
+ },
+ {
+ "fields": {
+ "buildnumber": 1,
+ "date": "2015-05-04T10:41:53.788Z",
+ "gerrit_change": null,
+ "gerrit_eventtype": null,
+ "gerrit_patchset": null,
+ "job_url": "http://fake.org/gogo",
+ "param_branch": null,
+ "param_distribution": "wheezy",
+ "param_ppa": null,
+ "param_release": "mr3.1-fake",
+ "param_tag": null,
+ "projectname": "fake-get-code",
+ "repo_name": null,
+ "result": "FAILED",
+ "tag": "UUID0"
+ },
+ "model": "repoapi.jenkinsbuildinfo",
+ "pk": 2
+ },
+ {
+ "fields": {
+ "buildnumber": 1,
+ "date": "2015-05-04T10:42:13.259Z",
+ "gerrit_change": null,
+ "gerrit_eventtype": null,
+ "gerrit_patchset": null,
+ "job_url": "http://fake.org/gogo",
+ "param_branch": null,
+ "param_distribution": "wheezy",
+ "param_ppa": null,
+ "param_release": "mr3.1-fake",
+ "param_tag": null,
+ "projectname": "fake-source-tests",
+ "repo_name": null,
+ "result": "SUCCESS",
+ "tag": "UUID1"
+ },
+ "model": "repoapi.jenkinsbuildinfo",
+ "pk": 3
+ },
+ {
+ "fields": {
+ "buildnumber": 1,
+ "date": "2015-05-04T17:04:57.802Z",
+ "gerrit_change": null,
+ "gerrit_eventtype": null,
+ "gerrit_patchset": null,
+ "job_url": "https://jenkins.mgm.sipwise.com/job/foo-get-code/",
+ "param_branch": null,
+ "param_distribution": "wheezy",
+ "param_ppa": null,
+ "param_release": "mr3.1-fake",
+ "param_tag": null,
+ "projectname": "fake-get-code",
+ "repo_name": null,
+ "result": "SUCCESS",
+ "tag": "UUID1"
+ },
+ "model": "repoapi.jenkinsbuildinfo",
+ "pk": 4
+ }
+]
\ No newline at end of file
diff --git a/repoapi/migrations/0002_auto_20150507_0746.py b/repoapi/migrations/0002_auto_20150507_0746.py
new file mode 100644
index 0000000..1fd7446
--- /dev/null
+++ b/repoapi/migrations/0002_auto_20150507_0746.py
@@ -0,0 +1,19 @@
+# -*- coding: utf-8 -*-
+from __future__ import unicode_literals
+
+from django.db import models, migrations
+
+
+class Migration(migrations.Migration):
+
+ dependencies = [
+ ('repoapi', '0001_initial'),
+ ]
+
+ operations = [
+ migrations.AlterField(
+ model_name='jenkinsbuildinfo',
+ name='tag',
+ field=models.CharField(max_length=64, null=True),
+ ),
+ ]
diff --git a/repoapi/models.py b/repoapi/models.py
index 87765fb..52fdc27 100644
--- a/repoapi/models.py
+++ b/repoapi/models.py
@@ -18,17 +18,32 @@ from django.db import models
class JenkinsBuildInfoManager(models.Manager):
- def releases(self):
+ def releases(self, flat=True):
res = self.get_queryset().values('param_release').distinct()
- return res.values_list('param_release', flat=True)
+ if flat:
+ return res.values_list('param_release', flat=True)
+ else:
+ return res.values('param_release')
- def projects(self, release):
- res = self.get_queryset().filter(param_release=release).distinct()
- return res
+ def release_uuids_by_project(self, release, project, flat=True):
+ res = self.get_queryset().filter(
+ param_release=release, projectname__startswith=project).distinct()
+ if flat:
+ return res.values_list('tag', flat=True)
+ else:
+ return res.values('tag')
+
+ def projects_by_uuid(self, release, project, uuid, flat=True):
+ res = self.get_queryset().filter(tag=uuid, param_release=release,
+ projectname__startswith=project)
+ if flat:
+ return res.order_by('-date').values_list('projectname', flat=True)
+ else:
+ return res.order_by('-date').values('projectname')
class JenkinsBuildInfo(models.Model):
- tag = models.CharField(max_length=32, null=True)
+ tag = models.CharField(max_length=64, null=True)
projectname = models.CharField(max_length=100)
buildnumber = models.IntegerField()
date = models.DateTimeField(auto_now_add=True)
diff --git a/repoapi/serializers.py b/repoapi/serializers.py
index 100246d..966e584 100644
--- a/repoapi/serializers.py
+++ b/repoapi/serializers.py
@@ -13,7 +13,6 @@
# You should have received a copy of the GNU General Public License along
# with this program. If not, see .
-from django.forms import widgets
from rest_framework import serializers
import repoapi.models as models
@@ -22,3 +21,7 @@ class JenkinsBuildInfoSerializer(serializers.HyperlinkedModelSerializer):
class Meta:
model = models.JenkinsBuildInfo
+
+
+class ReleaseListSerializer(serializers.Serializer):
+ param_release = serializers.CharField(max_length=50)
diff --git a/repoapi/settings/dev.py b/repoapi/settings/dev.py
index f7407fb..93b3439 100644
--- a/repoapi/settings/dev.py
+++ b/repoapi/settings/dev.py
@@ -16,7 +16,8 @@
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+BASE_DIR = os.path.dirname(
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
# Quick-start development settings - unsuitable for production
@@ -132,7 +133,7 @@ STATICFILES_FINDERS = (
'django_assets.finders.AssetsFinder',
)
-STATIC_ROOT= os.path.join(BASE_DIR,'static_media/')
+STATIC_ROOT = os.path.join(BASE_DIR, 'static_media/')
TEMPLATE_DIRS = (
'repoapi/templates',
diff --git a/repoapi/settings/prod.py b/repoapi/settings/prod.py
index efcb6b0..9492406 100644
--- a/repoapi/settings/prod.py
+++ b/repoapi/settings/prod.py
@@ -16,7 +16,8 @@
# Build paths inside the project like this: os.path.join(BASE_DIR, ...)
import os
-BASE_DIR = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
+BASE_DIR = os.path.dirname(
+ os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
VAR_DIR = '/var/lib/repoapi'
if not os.path.exists(VAR_DIR):
@@ -123,7 +124,7 @@ STATICFILES_FINDERS = (
'django_assets.finders.AssetsFinder',
)
-STATIC_ROOT= os.path.join(BASE_DIR,'static_media/')
+STATIC_ROOT = os.path.join(BASE_DIR, 'static_media/')
TEMPLATE_DIRS = (
'repoapi/templates',
diff --git a/repoapi/test/test_model_queries.py b/repoapi/test/test_model_queries.py
new file mode 100644
index 0000000..d664057
--- /dev/null
+++ b/repoapi/test/test_model_queries.py
@@ -0,0 +1,45 @@
+# Copyright (C) 2015 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 .
+
+from django.test import TestCase
+from repoapi.models import JenkinsBuildInfo
+
+
+class JBIQueriesTestCase(TestCase):
+ fixtures = ['test_model_queries.json']
+
+ def test_releases(self):
+ releases = JenkinsBuildInfo.objects.releases()
+ self.assertItemsEqual(releases, ['mr3.1-fake', ])
+
+ def test_release_uuids_by_project(self):
+ projects = ['fake', ]
+ uuids_ok = dict()
+ uuids = dict()
+
+ uuids_ok['fake'] = ['UUID1', 'UUID0']
+ for p in projects:
+ uuids[p] = JenkinsBuildInfo.objects.release_uuids_by_project(
+ 'mr3.1-fake', p)
+ self.assertItemsEqual(uuids_ok[p], uuids[p])
+
+ def test_projects_by_uuid(self):
+ projects = JenkinsBuildInfo.objects.projects_by_uuid(
+ 'mr3.1-fake', 'fake', 'UUID0')
+ self.assertItemsEqual(['fake-get-code', ], projects)
+ projects = JenkinsBuildInfo.objects.projects_by_uuid(
+ 'mr3.1-fake', 'fake', 'UUID1')
+ self.assertItemsEqual(
+ ['fake-get-code', 'fake-source-tests', 'fake-source'], projects)
diff --git a/repoapi/urls.py b/repoapi/urls.py
index 56936cc..31cafcf 100644
--- a/repoapi/urls.py
+++ b/repoapi/urls.py
@@ -26,6 +26,16 @@ api_patterns = [
url(r'^jenkinsbuildinfo/(?P[0-9]+)/$',
views.JenkinsBuildInfoDetail.as_view(),
name='jenkinsbuildinfo-detail'),
+ url(r'^release/$',
+ views.ReleaseList.as_view(),
+ name='release-list'),
+ url(r'^release/(?P[\w\d\.-]+)/(?P[\w\d\.-]+)/$',
+ views.ProjectUUIDList.as_view(),
+ name='projectuuid-list'),
+ url(r'^release/(?P[\w\d\.-]+)'
+ '/(?P[\w\d\.-]+)/(?P[\w\d-]+)/$',
+ views.UUIDInfoList.as_view(),
+ name='uuidinfo-list'),
]
api_patterns = format_suffix_patterns(api_patterns)
diff --git a/repoapi/views.py b/repoapi/views.py
index 4ed1424..b0e3d35 100644
--- a/repoapi/views.py
+++ b/repoapi/views.py
@@ -13,12 +13,13 @@
# You should have received a copy of the GNU General Public License along
# with this program. If not, see .
-from repoapi import models, serializers
-from rest_framework import filters
+from . import serializers
+from .models import JenkinsBuildInfo as jbi
from rest_framework import generics
from rest_framework.decorators import api_view
from rest_framework.response import Response
from rest_framework.reverse import reverse
+from rest_framework.views import APIView
import django_filters
@@ -27,23 +28,46 @@ def api_root(request, format=None):
return Response({
'jenkinsbuildinfo': reverse('jenkinsbuildinfo-list',
request=request, format=format),
+ 'release': reverse('release-list',
+ request=request, format=format),
})
class JenkinsBuildInfoFilter(django_filters.FilterSet):
class Meta:
- model = models.JenkinsBuildInfo
- fields = ['tag', 'projectname', 'date']
+ model = jbi
+ fields = ['tag', 'projectname', 'param_release', 'date']
order_by = ['-date', ]
class JenkinsBuildInfoList(generics.ListCreateAPIView):
- queryset = models.JenkinsBuildInfo.objects.all()
+ queryset = jbi.objects.all()
serializer_class = serializers.JenkinsBuildInfoSerializer
filter_class = JenkinsBuildInfoFilter
class JenkinsBuildInfoDetail(generics.RetrieveUpdateDestroyAPIView):
- queryset = models.JenkinsBuildInfo.objects.all()
+ queryset = jbi.objects.all()
serializer_class = serializers.JenkinsBuildInfoSerializer
+
+
+class ReleaseList(generics.ListAPIView):
+ queryset = jbi.objects.releases(flat=False)
+ serializer_class = serializers.ReleaseListSerializer
+
+
+class ProjectUUIDList(APIView):
+
+ def get(self, request, release, project, format=None):
+ res = jbi.objects.release_uuids_by_project(
+ release, project, flat=False)
+ return Response(res)
+
+
+class UUIDInfoList(APIView):
+
+ def get(self, request, release, project, uuid, format=None):
+ res = jbi.objects.projects_by_uuid(
+ release, project, uuid, flat=False)
+ return Response(res)