Commit a5774969 authored by Miquel Torres's avatar Miquel Torres Committed by GitHub
Browse files

Merge pull request #224 from tobami/default-banch-in-db

Default banch in db
parents 69f74055 3743ece0
......@@ -185,10 +185,6 @@ several parameters (the file includes comments with full examples).
* `grid`: will always show as default the grid of plots
* `show_none`: will show a text message (better default when there are lots of benchmarks)
* `mybench`: will select benchmark named "mybench"
* `DEF_BRANCH`: Defines the default branch to be used when calculating timeline and changes data for presentation. Example values:
* `default`: the default value, and usually mercurial's default branch
* `master`: usually git's default branch
* `trunk`: usually SVN's default branch
### Comparison View
* `CHART_TYPE`: Chooses the default chart type (normal bars, stacked bars or
......
# -*- coding: utf-8 -*-
from django import forms
from django.contrib import admin
from codespeed.models import (Project, Revision, Executable, Benchmark, Branch,
Result, Environment, Report)
from django.contrib import admin
class ProjectForm(forms.ModelForm):
default_branch = forms.CharField(max_length=32, required=False)
def clean(self):
if not self.cleaned_data.get('default_branch'):
repo_type = self.cleaned_data['repo_type']
if repo_type in [Project.GIT, Project.GITHUB]:
self.cleaned_data['default_branch'] = "master"
elif repo_type == Project.MERCURIAL:
self.cleaned_data['default_branch'] = "default"
elif repo_type == Project.SUBVERSION:
self.cleaned_data['default_branch'] = "trunk"
else:
self.add_error('default_branch', 'This field is required.')
class Meta:
model = Project
fields = '__all__'
@admin.register(Project)
class ProjectAdmin(admin.ModelAdmin):
list_display = ('name', 'repo_type', 'repo_path', 'track')
form = ProjectForm
@admin.register(Branch)
class BranchAdmin(admin.ModelAdmin):
......
......@@ -35,15 +35,14 @@ class ResultFeed(Feed):
class LatestEntries(ResultFeed):
description = "Last benchmark runs"
description = "Last Results"
def result_filter(self):
return Q(revision__branch__name=settings.DEF_BRANCH)
return Q()
class LatestSignificantEntries(ResultFeed):
description = "Last benchmark runs with significant changes"
description = "Last results with significant changes"
def result_filter(self):
return Q(revision__branch__name=settings.DEF_BRANCH,
colorcode__in=('red', 'green'))
return Q(colorcode__in=('red', 'green'))
......@@ -3,26 +3,28 @@
"pk": 1,
"model": "codespeed.project",
"fields": {
"repo_type": "N",
"repo_type": "G",
"name": "MyProject",
"commit_browsing_url": "",
"repo_user": "",
"track": true,
"repo_pass": "",
"repo_path": ""
"repo_path": "",
"default_branch": "master"
}
},
{
"pk": 2,
"model": "codespeed.project",
"fields": {
"repo_type": "N",
"repo_type": "M",
"name": "Other",
"commit_browsing_url": "",
"repo_user": "",
"track": true,
"repo_pass": "",
"repo_path": ""
"repo_path": "",
"default_branch": "default"
}
},
{
......@@ -35,7 +37,8 @@
"repo_user": "",
"track": false,
"repo_pass": "",
"repo_path": ""
"repo_path": "",
"default_branch": "master"
}
},
{
......@@ -59,7 +62,7 @@
"model": "codespeed.branch",
"fields": {
"project": 2,
"name": "master"
"name": "default"
}
},
{
......
# -*- coding: utf-8 -*-
# Generated by Django 1.9.13 on 2017-08-04 03:45
from __future__ import unicode_literals
from django.db import migrations, models
def get_default_branch_name():
from django.conf import settings
try:
return settings.DEF_BRANCH
except AttributeError:
return "master"
class Migration(migrations.Migration):
dependencies = [
('codespeed', '0002_median'),
]
operations = [
migrations.AddField(
model_name='project',
name='default_branch',
field=models.CharField(default=get_default_branch_name, max_length=32),
preserve_default=False,
),
migrations.AlterField(
model_name='branch',
name='name',
field=models.CharField(max_length=32),
),
]
......@@ -42,6 +42,7 @@ class Project(models.Model):
commit_browsing_url = models.CharField("Commit browsing URL",
blank=True, max_length=200)
track = models.BooleanField("Track changes", default=True)
default_branch = models.CharField(max_length=32)
def __str__(self):
return self.name
......@@ -103,7 +104,7 @@ class HistoricalValue(object):
@python_2_unicode_compatible
class Branch(models.Model):
name = models.CharField(max_length=20)
name = models.CharField(max_length=32)
project = models.ForeignKey(Project, related_name="branches")
def __str__(self):
......@@ -138,7 +139,7 @@ class Revision(models.Model):
else:
date = self.date.strftime("%b %d, %H:%M")
string = " - ".join(filter(None, (date, self.commitid, self.tag)))
if self.branch.name != settings.DEF_BRANCH:
if self.branch.name != self.branch.project.default_branch:
string += " - " + self.branch.name
return string
......
......@@ -134,6 +134,9 @@ def save_result(data):
def create_report_if_enough_data(rev, exe, e):
"""Triggers Report creation when there are enough results"""
if exe.project.track is not True:
return False
last_revs = Revision.objects.filter(
branch=rev.branch
).order_by('-date')[:2]
......
......@@ -6,9 +6,6 @@ WEBSITE_NAME = "MySpeedSite" # This name will be used in the reports RSS feed
DEF_ENVIRONMENT = None # Name of the environment which should be selected as default
DEF_BRANCH = "master" # Defines the default branch to be used.
# In git projects, this branch is usually called "master"
DEF_BASELINE = None # Which executable + revision should be default as a baseline
# Given as the name of the executable and commitid of the revision
# Example: defaultbaseline = {'executable': 'myexe', 'revision': '21'}
......
......@@ -3,7 +3,6 @@ from datetime import datetime, timedelta
import copy
import json
from django.conf import settings
from django.test import TestCase, override_settings
from django.core.urlresolvers import reverse
......@@ -342,19 +341,24 @@ class TestTimeline(TestCase):
"base": "2+4",
"ben": "float",
"env": "1",
"revs": 2
"revs": "2"
}
response = self.client.get(path, data)
self.assertEquals(response.status_code, 200)
responsedata = json.loads(response.content.decode())
self.assertEquals(
responsedata['error'], "None", "there should be no errors")
self.assertEquals(
len(responsedata['timelines']), 1, "there should be 1 benchmark")
self.assertEquals(
len(responsedata['timelines'][0]['branches']['master']),
len(responsedata['timelines'][0]['branches']),
2,
"there should be 2 timelines")
"there should be 2 branches")
self.assertEquals(
len(responsedata['timelines'][0]['branches']['default']),
1,
"there should be 1 timeline for master")
self.assertEquals(
len(responsedata['timelines'][0]['branches']['master']['1']),
2,
......@@ -371,7 +375,7 @@ class TestReports(TestCase):
Environment.objects.create(name='Dual Core', cpu='Core 2 Duo 8200')
self.data = {
'commitid': 'abcd1',
'branch': settings.DEF_BRANCH,
'branch': 'master',
'project': 'MyProject',
'executable': 'myexe O3 64bits',
'benchmark': 'float',
......@@ -399,3 +403,13 @@ class TestReports(TestCase):
response = self.client.post(reverse('codespeed.views.reports'), {})
self.assertEqual(response.status_code, 405)
class TestFeeds(TestCase):
def test_latest_result_feed(self):
response = self.client.get(reverse('latest-results'))
self.assertEqual(response.status_code, 200)
content = response.content.decode()
self.assertIn('<atom:link ', content)
......@@ -9,9 +9,9 @@ urlpatterns = patterns('',
url(r'^$', TemplateView.as_view(template_name='home.html'), name='home'),
url(r'^about/$', TemplateView.as_view(template_name='about.html'), name='about'),
# RSS for reports
url(r'^feeds/latest/$', LatestEntries(), name='latest_feeds'),
url(r'^feeds/latest/$', LatestEntries(), name='latest-results'),
url(r'^feeds/latest_significant/$', LatestSignificantEntries(),
name='latest_significant_feeds'),
name='latest-significant-results'),
)
urlpatterns += patterns('codespeed.views',
......
......@@ -5,17 +5,18 @@ import json
import logging
import django
from django.conf import settings
from django.core.urlresolvers import reverse
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.http import HttpResponse, Http404, HttpResponseBadRequest,\
HttpResponseNotFound
from django.db.models import F
from django.shortcuts import get_object_or_404, render_to_response
from django.views.decorators.http import require_GET, require_POST
from django.views.decorators.csrf import csrf_exempt
from django.template import RequestContext
from django.conf import settings
from .auth import basic_auth_required
from .auth import basic_auth_required
from .models import (Environment, Report, Project, Revision, Result,
Executable, Benchmark, Branch)
from .views_data import (get_default_environment, getbaselineexecutables,
......@@ -231,8 +232,18 @@ def gettimelinedata(request):
timeline_list = {'error': 'None', 'timelines': []}
executables = data.get('exe', "").split(",")
if not filter(None, executables):
executable_ids = data.get('exe', '').split(',')
executables = []
for i in executable_ids:
if not i:
continue
try:
executables.append(Executable.objects.get(id=int(i)))
except Executable.DoesNotExist:
pass
if not executables:
timeline_list['error'] = "No executables selected"
return HttpResponse(json.dumps(timeline_list))
environment = None
......@@ -270,16 +281,14 @@ def gettimelinedata(request):
'branches': {},
'baseline': "None",
}
# Temporary
trunks = []
if Branch.objects.filter(name=settings.DEF_BRANCH):
trunks.append(settings.DEF_BRANCH)
# For now, we'll only work with trunk branches
append = False
for branch in trunks:
append = False
timeline['branches'][branch] = {}
for branch in Branch.objects.filter(
project__track=True, name=F('project__default_branch')):
# For now, we'll only work with default branches
for executable in executables:
if executable.project != branch.project:
continue
resultquery = Result.objects.filter(
benchmark=bench
).filter(
......@@ -287,12 +296,13 @@ def gettimelinedata(request):
).filter(
executable=executable
).filter(
revision__branch__name=branch
revision__branch=branch
).select_related(
"revision"
).order_by('-revision__date')[:number_of_revs]
if not len(resultquery):
continue
timeline['branches'].setdefault(branch.name, {})
results = []
for res in resultquery:
......@@ -313,7 +323,7 @@ def gettimelinedata(request):
[
res.revision.date.strftime('%Y/%m/%d %H:%M:%S %z'),
res.value, val_max, q3, q1, val_min,
res.revision.get_short_commitid(), res.revision.tag, branch
res.revision.get_short_commitid(), res.revision.tag, branch.name
]
)
else:
......@@ -324,34 +334,37 @@ def gettimelinedata(request):
[
res.revision.date.strftime('%Y/%m/%d %H:%M:%S %z'),
res.value, std_dev,
res.revision.get_short_commitid(), res.revision.tag, branch
res.revision.get_short_commitid(), res.revision.tag, branch.name
]
)
timeline['branches'][branch][executable] = results
timeline['branches'][branch.name][executable.id] = results
append = True
if baselinerev is not None and append:
try:
baselinevalue = Result.objects.get(
executable=baselineexe,
benchmark=bench,
revision=baselinerev,
environment=environment
).value
except Result.DoesNotExist:
timeline['baseline'] = "None"
else:
# determine start and end revision (x axis)
# from longest data series
results = []
if baselinerev is not None and append:
try:
baselinevalue = Result.objects.get(
executable=baselineexe,
benchmark=bench,
revision=baselinerev,
environment=environment
).value
except Result.DoesNotExist:
timeline['baseline'] = "None"
else:
# determine start and end revision (x axis)
# from longest data series
results = []
for branch in timeline['branches']:
for exe in timeline['branches'][branch]:
if len(timeline['branches'][branch][exe]) > len(results):
results = timeline['branches'][branch][exe]
end = results[0][0]
start = results[len(results) - 1][0]
timeline['baseline'] = [
[str(start), baselinevalue],
[str(end), baselinevalue]
]
end = results[0][0]
start = results[len(results) - 1][0]
timeline['baseline'] = [
[str(start), baselinevalue],
[str(end), baselinevalue]
]
if append:
timeline_list['timelines'].append(timeline)
......@@ -401,8 +414,8 @@ def timeline(request):
branch_list.sort()
defaultbranch = ""
if settings.DEF_BRANCH in branch_list:
defaultbranch = settings.DEF_BRANCH
if defaultproject.default_branch in branch_list:
defaultbranch = defaultproject.default_branch
if data.get('bran') in branch_list:
defaultbranch = data.get('bran')
......@@ -576,7 +589,7 @@ def changes(request):
for proj in Project.objects.filter(track=True):
executables[proj] = Executable.objects.filter(project=proj)
projectlist.append(proj)
branch = Branch.objects.filter(name=settings.DEF_BRANCH, project=proj)
branch = Branch.objects.filter(name=proj.default_branch, project=proj)
revisionlists[proj.name] = list(Revision.objects.filter(
branch=branch
).order_by('-date')[:revlimit])
......@@ -631,15 +644,11 @@ def reports(request):
context = {}
context['reports'] = \
Report.objects.filter(
revision__branch__name=settings.DEF_BRANCH
).order_by('-revision__date')[:10]
context['significant_reports'] = \
Report.objects.filter(
revision__branch__name=settings.DEF_BRANCH,
colorcode__in=('red', 'green')
).order_by('-revision__date')[:10]
Report.objects.order_by('-revision__date')[:10]
context['significant_reports'] = Report.objects.filter(
colorcode__in=('red', 'green')
).order_by('-revision__date')[:10]
return render_to_response('codespeed/reports.html', context,
context_instance=RequestContext(request))
......
......@@ -3,8 +3,9 @@ from __future__ import absolute_import
from django.conf import settings
from django.core.exceptions import ObjectDoesNotExist
from codespeed.models import Executable, Revision, Project, Branch,\
Environment, Benchmark, Result
from codespeed.models import (
Executable, Revision, Project, Branch,
Environment, Benchmark, Result)
def get_default_environment(enviros, data, multi=False):
......
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