general: paint it black

This commit is contained in:
Frédéric Péters 2020-01-19 18:35:48 +01:00
parent 3097d75276
commit 0856ac758f
16 changed files with 218 additions and 164 deletions

View File

@ -9,9 +9,7 @@ TEMPLATE_DEBUG = False
SECRET_KEY = open('/etc/%s/secret' % PROJECT_NAME).read() SECRET_KEY = open('/etc/%s/secret' % PROJECT_NAME).read()
ADMINS = ( ADMINS = (('Tous', 'root@localhost'),)
('Tous', 'root@localhost'),
)
EMAIL_SUBJECT_PREFIX = '[%s] ' % PROJECT_NAME EMAIL_SUBJECT_PREFIX = '[%s] ' % PROJECT_NAME
@ -27,14 +25,9 @@ MEDIA_ROOT = os.path.join(VAR_DIR, 'media')
CSRF_COOKIE_SECURE = True CSRF_COOKIE_SECURE = True
SESSION_COOKIE_SECURE = True SESSION_COOKIE_SECURE = True
SESSION_EXPIRE_AT_BROWSER_CLOSER = True SESSION_EXPIRE_AT_BROWSER_CLOSER = True
SESSION_COOKIE_AGE = 36000 # 10h SESSION_COOKIE_AGE = 36000 # 10h
DATABASES = { DATABASES = {'default': {'ENGINE': 'django.db.backends.postgresql_psycopg2', 'NAME': PROJECT_NAME,}}
'default': {
'ENGINE': 'django.db.backends.postgresql_psycopg2',
'NAME': PROJECT_NAME,
}
}
# #
# local settings # local settings

6
debian/settings.py vendored
View File

@ -15,15 +15,15 @@
DEBUG = False DEBUG = False
TEMPLATE_DEBUG = False TEMPLATE_DEBUG = False
#ADMINS = ( # ADMINS = (
# # ('User 1', 'watchdog@example.net'), # # ('User 1', 'watchdog@example.net'),
# # ('User 2', 'janitor@example.net'), # # ('User 2', 'janitor@example.net'),
#) # )
# ALLOWED_HOSTS must be correct in production! # ALLOWED_HOSTS must be correct in production!
# See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts # See https://docs.djangoproject.com/en/dev/ref/settings/#allowed-hosts
ALLOWED_HOSTS = [ ALLOWED_HOSTS = [
'*', '*',
] ]
# Databases # Databases

View File

@ -2,31 +2,37 @@ from django.contrib import admin
from .models import Project, Platform, Service, InstalledService, Module from .models import Project, Platform, Service, InstalledService, Module
class ProjectAdmin(admin.ModelAdmin): class ProjectAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('title',)} prepopulated_fields = {'slug': ('title',)}
admin.site.register(Project, ProjectAdmin) admin.site.register(Project, ProjectAdmin)
class PlatformAdmin(admin.ModelAdmin): class PlatformAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('title',)} prepopulated_fields = {'slug': ('title',)}
admin.site.register(Platform, PlatformAdmin) admin.site.register(Platform, PlatformAdmin)
class ServiceAdmin(admin.ModelAdmin): class ServiceAdmin(admin.ModelAdmin):
prepopulated_fields = {'slug': ('title',)} prepopulated_fields = {'slug': ('title',)}
admin.site.register(Service, ServiceAdmin) admin.site.register(Service, ServiceAdmin)
class InstalledServiceAdmin(admin.ModelAdmin): class InstalledServiceAdmin(admin.ModelAdmin):
pass pass
admin.site.register(InstalledService, InstalledServiceAdmin) admin.site.register(InstalledService, InstalledServiceAdmin)
class ModuleAdmin(admin.ModelAdmin): class ModuleAdmin(admin.ModelAdmin):
pass pass
admin.site.register(Module, ModuleAdmin) admin.site.register(Module, ModuleAdmin)

View File

@ -10,23 +10,21 @@ class Command(BaseCommand):
help = 'Scrutiny services for changes' help = 'Scrutiny services for changes'
def handle(self, verbosity, *args, **options): def handle(self, verbosity, *args, **options):
self.verbose = (int(verbosity) > 1) self.verbose = int(verbosity) > 1
for service in InstalledService.objects.all(): for service in InstalledService.objects.all():
if not service.url.endswith('/'): if not service.url.endswith('/'):
service.url = '%s/' % service.url service.url = '%s/' % service.url
if self.verbose: if self.verbose:
print('Checking %s' % service.url) print('Checking %s' % service.url)
try: try:
response = requests.get('%s__version__' % service.url, response = requests.get('%s__version__' % service.url, timeout=5, verify=True)
timeout=5, verify=True)
response.raise_for_status() response.raise_for_status()
except requests.RequestException as e: except requests.RequestException as e:
print('Error with %s (%r)' % (service.url, e)) print('Error with %s (%r)' % (service.url, e))
continue continue
versions = response.json() versions = response.json()
current_modules = set([x for x in current_modules = set([x for x in service.service.get_modules(platforms=[service.platform])])
service.service.get_modules(platforms=[service.platform])])
seen_modules = set() seen_modules = set()
for module_name, version_string in versions.items(): for module_name, version_string in versions.items():
@ -44,8 +42,7 @@ class Command(BaseCommand):
version = module.version_set.create(version=version_string) version = module.version_set.create(version=version_string)
try: try:
installed_version = InstalledVersion.objects.get( installed_version = InstalledVersion.objects.get(service=service, version=version)
service=service, version=version)
except InstalledVersion.DoesNotExist: except InstalledVersion.DoesNotExist:
installed_version = InstalledVersion() installed_version = InstalledVersion()
installed_version.service = service installed_version.service = service

View File

@ -27,7 +27,9 @@ class Command(BaseCommand):
continue continue
try: try:
issues = list(redmine_server.issue.filter(project_id=module.redmine_project, status_id=RESOLVED_ID)) issues = list(
redmine_server.issue.filter(project_id=module.redmine_project, status_id=RESOLVED_ID)
)
except redmine.exceptions.ResourceNotFoundError: except redmine.exceptions.ResourceNotFoundError:
if verbosity > 1: if verbosity > 1:
print('unknown redmine module:', module.name) print('unknown redmine module:', module.name)
@ -36,13 +38,20 @@ class Command(BaseCommand):
deployment_status = get_issue_deployment_status(issue.id) deployment_status = get_issue_deployment_status(issue.id)
if not deployment_status.get('platforms'): if not deployment_status.get('platforms'):
if verbosity > 1: if verbosity > 1:
print(' unknown status for https://dev.entrouvert.org/issues/%s (%s)' % ( print(
issue.id, module.redmine_project)) ' unknown status for https://dev.entrouvert.org/issues/%s (%s)'
% (issue.id, module.redmine_project)
)
continue continue
platforms_ok = [x.rsplit(' / ', 1)[0] for x in deployment_status['platforms'].keys() platforms_ok = [
if deployment_status['platforms'][x]['status'] == 'ok'] x.rsplit(' / ', 1)[0]
for x in deployment_status['platforms'].keys()
if deployment_status['platforms'][x]['status'] == 'ok'
]
if settings.REDMINE_REFERENCE_PLATFORM in platforms_ok: if settings.REDMINE_REFERENCE_PLATFORM in platforms_ok:
if verbosity > 0: if verbosity > 0:
print('%s - https://dev.entrouvert.org/issues/%s' % (module.redmine_project, issue.id)) print(
'%s - https://dev.entrouvert.org/issues/%s' % (module.redmine_project, issue.id)
)
issue.status_id = DEPLOYED_ID issue.status_id = DEPLOYED_ID
issue.save() issue.save()

View File

@ -6,85 +6,98 @@ from django.db import models, migrations
class Migration(migrations.Migration): class Migration(migrations.Migration):
dependencies = [ dependencies = []
]
operations = [ operations = [
migrations.CreateModel( migrations.CreateModel(
name='InstalledService', name='InstalledService',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
'id',
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
),
('url', models.URLField()), ('url', models.URLField()),
], ],
options={ options={},
},
bases=(models.Model,), bases=(models.Model,),
), ),
migrations.CreateModel( migrations.CreateModel(
name='InstalledVersion', name='InstalledVersion',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
'id',
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
),
('timestamp', models.DateTimeField()), ('timestamp', models.DateTimeField()),
('service', models.ForeignKey(to='projects.InstalledService')), ('service', models.ForeignKey(to='projects.InstalledService')),
], ],
options={ options={},
},
bases=(models.Model,), bases=(models.Model,),
), ),
migrations.CreateModel( migrations.CreateModel(
name='Module', name='Module',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
'id',
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
),
('name', models.CharField(max_length=50)), ('name', models.CharField(max_length=50)),
('repository_url', models.URLField()), ('repository_url', models.URLField()),
], ],
options={ options={},
},
bases=(models.Model,), bases=(models.Model,),
), ),
migrations.CreateModel( migrations.CreateModel(
name='Platform', name='Platform',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
'id',
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
),
('title', models.CharField(max_length=50)), ('title', models.CharField(max_length=50)),
('slug', models.SlugField()), ('slug', models.SlugField()),
], ],
options={ options={},
},
bases=(models.Model,), bases=(models.Model,),
), ),
migrations.CreateModel( migrations.CreateModel(
name='Project', name='Project',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
'id',
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
),
('title', models.CharField(max_length=50)), ('title', models.CharField(max_length=50)),
('slug', models.SlugField()), ('slug', models.SlugField()),
], ],
options={ options={},
},
bases=(models.Model,), bases=(models.Model,),
), ),
migrations.CreateModel( migrations.CreateModel(
name='Service', name='Service',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
'id',
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
),
('title', models.CharField(max_length=50)), ('title', models.CharField(max_length=50)),
('slug', models.SlugField()), ('slug', models.SlugField()),
('project', models.ForeignKey(to='projects.Project')), ('project', models.ForeignKey(to='projects.Project')),
], ],
options={ options={},
},
bases=(models.Model,), bases=(models.Model,),
), ),
migrations.CreateModel( migrations.CreateModel(
name='Version', name='Version',
fields=[ fields=[
('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)), (
'id',
models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True),
),
('version', models.CharField(max_length=50)), ('version', models.CharField(max_length=50)),
('module', models.ForeignKey(to='projects.Module')), ('module', models.ForeignKey(to='projects.Module')),
], ],
options={ options={},
},
bases=(models.Model,), bases=(models.Model,),
), ),
migrations.AddField( migrations.AddField(

View File

@ -11,10 +11,7 @@ class Migration(migrations.Migration):
] ]
operations = [ operations = [
migrations.AlterModelOptions( migrations.AlterModelOptions(name='platform', options={'ordering': ['order']},),
name='platform',
options={'ordering': ['order']},
),
migrations.AddField( migrations.AddField(
model_name='platform', model_name='platform',
name='order', name='order',

View File

@ -5,6 +5,7 @@ import subprocess
from django.conf import settings from django.conf import settings
from django.db import models from django.db import models
class Project(models.Model): class Project(models.Model):
title = models.CharField(max_length=50) title = models.CharField(max_length=50)
slug = models.SlugField() slug = models.SlugField()
@ -40,14 +41,14 @@ class Service(models.Model):
platforms = self.project.platform_set.all() platforms = self.project.platform_set.all()
for platform in platforms: for platform in platforms:
try: try:
installed_service = InstalledService.objects.get(service=self, installed_service = InstalledService.objects.get(service=self, platform=platform)
platform=platform)
except InstalledService.DoesNotExist: except InstalledService.DoesNotExist:
continue continue
seen_modules = [] seen_modules = []
uninstalled_modules = [] uninstalled_modules = []
for installed_version in InstalledVersion.objects.filter( for installed_version in InstalledVersion.objects.filter(service=installed_service).order_by(
service=installed_service).order_by('-timestamp'): '-timestamp'
):
if installed_version.version.module in seen_modules: if installed_version.version.module in seen_modules:
continue continue
seen_modules.append(installed_version.version.module) seen_modules.append(installed_version.version.module)
@ -59,8 +60,7 @@ class Service(models.Model):
def get_installed_service(self, platform): def get_installed_service(self, platform):
try: try:
installed_service = InstalledService.objects.get(service=self, installed_service = InstalledService.objects.get(service=self, platform=platform)
platform=platform)
except InstalledService.DoesNotExist: except InstalledService.DoesNotExist:
return None return None
return installed_service return installed_service
@ -72,9 +72,12 @@ class InstalledService(models.Model):
url = models.URLField() url = models.URLField()
def __unicode__(self): def __unicode__(self):
return '%s / %s / %s (@ %s)' % (self.platform.project.title, return '%s / %s / %s (@ %s)' % (
self.platform.title, self.service.title, self.platform.project.title,
self.url) self.platform.title,
self.service.title,
self.url,
)
class Module(models.Model): class Module(models.Model):
@ -94,13 +97,13 @@ class Module(models.Model):
def get_installed_version(self, platform, service): def get_installed_version(self, platform, service):
try: try:
installed_service = InstalledService.objects.get( installed_service = InstalledService.objects.get(platform=platform, service=service)
platform=platform, service=service)
except InstalledService.DoesNotExist: except InstalledService.DoesNotExist:
return None return None
try: try:
v = InstalledVersion.objects.filter( v = InstalledVersion.objects.filter(service=installed_service, version__module=self).order_by(
service=installed_service, version__module=self).order_by('-timestamp')[0] '-timestamp'
)[0]
except IndexError: except IndexError:
return None return None
return v return v
@ -141,12 +144,14 @@ class Module(models.Model):
if grep: if grep:
cmd.append('--grep') cmd.append('--grep')
cmd.append(grep) cmd.append(grep)
def get_ref(v): def get_ref(v):
if re.findall(r'\.g([0-9a-f]{7})', v): if re.findall(r'\.g([0-9a-f]{7})', v):
return re.findall(r'\.g([0-9a-f]{7})', v)[0] return re.findall(r'\.g([0-9a-f]{7})', v)[0]
if re.findall(r'\+g([0-9a-f]{7})', v): if re.findall(r'\+g([0-9a-f]{7})', v):
return re.findall(r'\+g([0-9a-f]{7})', v)[0] return re.findall(r'\+g([0-9a-f]{7})', v)[0]
return 'v' + v return 'v' + v
cmd.append('%s...%s' % (get_ref(v1), get_ref(v2))) cmd.append('%s...%s' % (get_ref(v1), get_ref(v2)))
p = subprocess.Popen(cmd, **kws) p = subprocess.Popen(cmd, **kws)
@ -162,6 +167,7 @@ class Module(models.Model):
versions.add(version.version.version) versions.add(version.version.version)
return versions return versions
class Version(models.Model): class Version(models.Model):
module = models.ForeignKey('Module') module = models.ForeignKey('Module')
version = models.CharField(max_length=100, blank=True) version = models.CharField(max_length=100, blank=True)
@ -177,9 +183,8 @@ class InstalledVersion(models.Model):
def get_previous_version(self): def get_previous_version(self):
try: try:
return InstalledVersion.objects.filter(service=self.service, return InstalledVersion.objects.filter(
version__module=self.version.module, service=self.service, version__module=self.version.module, timestamp__lt=self.timestamp
timestamp__lt=self.timestamp ).order_by('-timestamp')[0]
).order_by('-timestamp')[0]
except IndexError: except IndexError:
return None return None

View File

@ -2,6 +2,7 @@ from django import template
register = template.Library() register = template.Library()
@register.simple_tag @register.simple_tag
def installed_version(module, platform, service): def installed_version(module, platform, service):
v = module.get_installed_version(platform, service) v = module.get_installed_version(platform, service)
@ -9,6 +10,7 @@ def installed_version(module, platform, service):
return '' return ''
return v.version.version return v.version.version
@register.simple_tag @register.simple_tag
def service_url(platform, service): def service_url(platform, service):
installed_service = service.get_installed_service(platform=platform) installed_service = service.get_installed_service(platform=platform)

View File

@ -1,8 +1,17 @@
from django.conf.urls import url from django.conf.urls import url
from .views import (ModulesView, ProjectDetailView, ProjectSummaryHistoryView, from .views import (
ProjectHistoryView, ModuleDiffView, IssuesSnippet, ModuleIssuesView, ModulesView,
ModuleDeploymentsView, module_deployments_json, api_issues_json) ProjectDetailView,
ProjectSummaryHistoryView,
ProjectHistoryView,
ModuleDiffView,
IssuesSnippet,
ModuleIssuesView,
ModuleDeploymentsView,
module_deployments_json,
api_issues_json,
)
urlpatterns = [ urlpatterns = [
@ -10,14 +19,18 @@ urlpatterns = [
url(r'^(?P<slug>[\w,-]+)/$', ProjectDetailView.as_view(), name='project-view'), url(r'^(?P<slug>[\w,-]+)/$', ProjectDetailView.as_view(), name='project-view'),
url(r'^(?P<slug>[\w,-]+)/history$', ProjectSummaryHistoryView.as_view(), name='project-summary-history'), url(r'^(?P<slug>[\w,-]+)/history$', ProjectSummaryHistoryView.as_view(), name='project-summary-history'),
url(r'^(?P<slug>[\w,-]+)/detailed-history$', ProjectHistoryView.as_view(), name='project-history'), url(r'^(?P<slug>[\w,-]+)/detailed-history$', ProjectHistoryView.as_view(), name='project-history'),
url(r'^modules/(?P<name>[\w,-]+)/diff/(?P<commit1>[\w,\.-]+)/(?P<commit2>[\w,\.-]+)$', url(
ModuleDiffView.as_view(), name='module-diff'), r'^modules/(?P<name>[\w,-]+)/diff/(?P<commit1>[\w,\.-]+)/(?P<commit2>[\w,\.-]+)$',
ModuleDiffView.as_view(),
name='module-diff',
),
url(r'^issues/snippet/$', IssuesSnippet.as_view(), name='issues-snippet'), url(r'^issues/snippet/$', IssuesSnippet.as_view(), name='issues-snippet'),
url(r'^modules/(?P<name>[\w,-]+)/issues/(?P<commit1>[\w,\.-]+)/(?P<commit2>[\w,\.-]+)$', url(
ModuleIssuesView.as_view(), name='module-issues'), r'^modules/(?P<name>[\w,-]+)/issues/(?P<commit1>[\w,\.-]+)/(?P<commit2>[\w,\.-]+)$',
url(r'^modules/(?P<name>[\w,-]+)/$', ModuleIssuesView.as_view(),
ModuleDeploymentsView.as_view(), name='module-deployments'), name='module-issues',
url(r'^modules/(?P<name>[\w,-]+)/json$', ),
module_deployments_json, name='module-deployments-json'), url(r'^modules/(?P<name>[\w,-]+)/$', ModuleDeploymentsView.as_view(), name='module-deployments'),
url(r'^modules/(?P<name>[\w,-]+)/json$', module_deployments_json, name='module-deployments-json'),
url(r'^api/issues/(?P<issue>\d+)/$', api_issues_json), url(r'^api/issues/(?P<issue>\d+)/$', api_issues_json),
] ]

View File

@ -23,8 +23,9 @@ class Issue(object):
def update_content(self): def update_content(self):
response = requests.get( response = requests.get(
'%s/issues/%s.json' % (settings.REDMINE_URL, self.id), '%s/issues/%s.json' % (settings.REDMINE_URL, self.id),
headers={'X-Redmine-API-Key': settings.REDMINE_API_KEY}) headers={'X-Redmine-API-Key': settings.REDMINE_API_KEY},
)
response.raise_for_status() response.raise_for_status()
content = response.json() content = response.json()
cache.set('issue-%s' % self.id, content, CACHE_DURATION) cache.set('issue-%s' % self.id, content, CACHE_DURATION)
@ -64,7 +65,6 @@ class Issue(object):
class CommitAndIssues(object): class CommitAndIssues(object):
def __init__(self, oneline): def __init__(self, oneline):
self.issues = [] self.issues = []
self.commit = oneline.strip() self.commit = oneline.strip()
@ -91,6 +91,7 @@ class CommitAndIssues(object):
def get_issue_deployment_status(issue_id): def get_issue_deployment_status(issue_id):
from .models import Module, InstalledService from .models import Module, InstalledService
data = {} data = {}
for module in Module.objects.all(): for module in Module.objects.all():
try: try:
@ -112,16 +113,17 @@ def get_issue_deployment_status(issue_id):
if not version_number: if not version_number:
continue continue
service_name = '%s / %s / %s' % ( service_name = '%s / %s / %s' % (
installed_version.service.platform.project.title, installed_version.service.platform.project.title,
installed_version.service.platform.title, installed_version.service.platform.title,
installed_version.service.service.title) installed_version.service.service.title,
)
version_hash = module.get_version_hash(version_number) version_hash = module.get_version_hash(version_number)
if not version_hash in git_log_hashes: if not version_hash in git_log_hashes:
continue continue
version_index = git_log_hashes.index(version_hash) version_index = git_log_hashes.index(version_hash)
data['platforms'][service_name] = { data['platforms'][service_name] = {
'version': version_number, 'version': version_number,
'status': 'ok' if version_index <= fix_index else 'nok' 'status': 'ok' if version_index <= fix_index else 'nok',
} }
if data: if data:
break break

View File

@ -11,6 +11,7 @@ from django.views.generic.detail import DetailView
from .models import Project, InstalledService, Module, InstalledVersion from .models import Project, InstalledService, Module, InstalledVersion
from .utils import CommitAndIssues, decorate_commit_line, get_issue_deployment_status from .utils import CommitAndIssues, decorate_commit_line, get_issue_deployment_status
class ProjectDetailView(DetailView): class ProjectDetailView(DetailView):
model = Project model = Project
@ -36,8 +37,11 @@ class ModuleDiffView(TemplateView):
context['commit2'] = commit2 context['commit2'] = commit2
context['difflog'] = '\n'.join( context['difflog'] = '\n'.join(
[decorate_commit_line(line) for line in \ [
context['module'].get_diff_log(commit1, commit2).splitlines()]) decorate_commit_line(line)
for line in context['module'].get_diff_log(commit1, commit2).splitlines()
]
)
return context return context
@ -50,8 +54,7 @@ class ModuleIssuesView(TemplateView):
context['module'] = Module.objects.get(name=name) context['module'] = Module.objects.get(name=name)
context['commit1'] = commit1 context['commit1'] = commit1
context['commit2'] = commit2 context['commit2'] = commit2
commits = CommitAndIssues.get_for_commits( commits = CommitAndIssues.get_for_commits(context['module'], commit1, commit2)
context['module'], commit1, commit2)
issues = {} issues = {}
for commit in commits: for commit in commits:
for issue in commit.issues: for issue in commit.issues:
@ -75,8 +78,9 @@ class ProjectHistoryView(DetailView):
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ProjectHistoryView, self).get_context_data(**kwargs) context = super(ProjectHistoryView, self).get_context_data(**kwargs)
installed_versions = InstalledVersion.objects.filter( installed_versions = InstalledVersion.objects.filter(service__platform__project=self.object).order_by(
service__platform__project=self.object).order_by('-timestamp')[:1000] '-timestamp'
)[:1000]
context['installed_versions'] = installed_versions context['installed_versions'] = installed_versions
@ -89,30 +93,42 @@ class ProjectSummaryHistoryView(DetailView):
# XXX: add an 'interesting' attribute to module model? # XXX: add an 'interesting' attribute to module model?
interesting_modules = [ interesting_modules = [
'publik-base-theme', 'combo', 'wcs', 'hobo', 'authentic2', 'publik-base-theme',
'welco', 'chrono', 'corbo', 'passerelle', 'fargo', 'mandayejs', 'combo',
'bijoe', 'wcs-olap', 'gadjo', 'wcs',
] 'hobo',
'authentic2',
'welco',
'chrono',
'corbo',
'passerelle',
'fargo',
'mandayejs',
'bijoe',
'wcs-olap',
'gadjo',
]
def get_context_data(self, **kwargs): def get_context_data(self, **kwargs):
context = super(ProjectSummaryHistoryView, self).get_context_data(**kwargs) context = super(ProjectSummaryHistoryView, self).get_context_data(**kwargs)
platforms = list(self.get_object().platform_set.all()) platforms = list(self.get_object().platform_set.all())
platform = platforms[-1] platform = platforms[-1]
installed_versions = list(InstalledVersion.objects.filter( installed_versions = list(
InstalledVersion.objects.filter(
timestamp__gt=timezone.now() - datetime.timedelta(days=120), timestamp__gt=timezone.now() - datetime.timedelta(days=120),
version__module__name__in=self.interesting_modules, version__module__name__in=self.interesting_modules,
service__platform=platform).exclude( service__platform=platform,
version__version='').order_by('-timestamp')[:1000]) )
.exclude(version__version='')
.order_by('-timestamp')[:1000]
)
installed_versions.reverse() installed_versions.reverse()
versions_and_day = {} versions_and_day = {}
for installed in installed_versions: for installed in installed_versions:
installed_day = installed.timestamp.strftime('%Y-%m-%d') installed_day = installed.timestamp.strftime('%Y-%m-%d')
if not installed_day in versions_and_day: if not installed_day in versions_and_day:
versions_and_day[installed_day] = { versions_and_day[installed_day] = {'modules': {}, 'day': installed.timestamp.date()}
'modules': {},
'day': installed.timestamp.date()
}
if installed.version.module.name in versions_and_day[installed_day]['modules']: if installed.version.module.name in versions_and_day[installed_day]['modules']:
continue continue
versions_and_day[installed_day]['modules'][installed.version.module.name] = { versions_and_day[installed_day]['modules'][installed.version.module.name] = {
@ -135,17 +151,17 @@ class ProjectSummaryHistoryView(DetailView):
if len(platforms) > 1: if len(platforms) > 1:
validation_platform = platforms[-2] validation_platform = platforms[-2]
future_versions = { future_versions = {'modules': {}, 'day': 'future'}
'modules': {},
'day': 'future'
}
module_names = previous_versions.keys() module_names = previous_versions.keys()
for module_name in module_names: for module_name in module_names:
try: try:
installed_version = InstalledVersion.objects.filter( installed_version = (
version__module__name=module_name, InstalledVersion.objects.filter(
service__platform=validation_platform).exclude( version__module__name=module_name, service__platform=validation_platform
version__version='').order_by('-timestamp')[0] )
.exclude(version__version='')
.order_by('-timestamp')[0]
)
except IndexError: except IndexError:
continue continue
if not installed_version.version.version: if not installed_version.version.version:
@ -175,12 +191,14 @@ class ModulesView(TemplateView):
context['modules'] = Module.objects.all().order_by('name') context['modules'] = Module.objects.all().order_by('name')
return context return context
def try_int(x): def try_int(x):
try: try:
return int(x) return int(x)
except ValueError: except ValueError:
return 0 return 0
version_re = re.compile(r'[\.\+-]d?e?v?') version_re = re.compile(r'[\.\+-]d?e?v?')
@ -215,11 +233,18 @@ def module_deployments_json(request, name, **kwargs):
if version and not version in installed_versions: if version and not version in installed_versions:
installed_versions.append(version) installed_versions.append(version)
json.dump([{'version': x.version.version, json.dump(
[
{
'version': x.version.version,
'project': x.service.platform.project.slug, 'project': x.service.platform.project.slug,
'service': x.service.service.slug, 'service': x.service.service.slug,
'platform': x.service.platform.slug} for x in installed_versions], 'platform': x.service.platform.slug,
response) }
for x in installed_versions
],
response,
)
return response return response
@ -244,12 +269,11 @@ class IssuesSnippet(TemplateView):
if not module.repository_url: if not module.repository_url:
continue continue
commits = CommitAndIssues.get_for_commits( commits = CommitAndIssues.get_for_commits(
module, module, str(module_info.get('previous_version')), str(module_info.get('current_version'))
str(module_info.get('previous_version')), )
str(module_info.get('current_version')))
for commit in commits: for commit in commits:
for issue in commit.issues: for issue in commit.issues:
if issue.subject == '---': # private issue if issue.subject == '---': # private issue
continue continue
if not int(issue.id) in issues: if not int(issue.id) in issues:
issues[int(issue.id)] = issue issues[int(issue.id)] = issue
@ -261,7 +285,7 @@ class IssuesSnippet(TemplateView):
context['issues'] = list(issues.values()) context['issues'] = list(issues.values())
context['issues'].sort(key=lambda x: x.closed_on) context['issues'].sort(key=lambda x: x.closed_on)
context['issues'].reverse() # most recent on top context['issues'].reverse() # most recent on top
return context return context

View File

@ -40,8 +40,7 @@ MIDDLEWARE_CLASSES = (
) )
# Serve xstatic files, required for gadjo # Serve xstatic files, required for gadjo
STATICFILES_FINDERS = list(global_settings.STATICFILES_FINDERS) + \ STATICFILES_FINDERS = list(global_settings.STATICFILES_FINDERS) + ['gadjo.finders.XStaticFinder']
['gadjo.finders.XStaticFinder']
ROOT_URLCONF = 'scrutiny.urls' ROOT_URLCONF = 'scrutiny.urls'
@ -51,10 +50,7 @@ WSGI_APPLICATION = 'scrutiny.wsgi.application'
# https://docs.djangoproject.com/en/1.7/ref/settings/#databases # https://docs.djangoproject.com/en/1.7/ref/settings/#databases
DATABASES = { DATABASES = {
'default': { 'default': {'ENGINE': 'django.db.backends.sqlite3', 'NAME': os.path.join(BASE_DIR, 'scrutiny.sqlite3'),}
'ENGINE': 'django.db.backends.sqlite3',
'NAME': os.path.join(BASE_DIR, 'scrutiny.sqlite3'),
}
} }
# Internationalization # Internationalization
@ -70,7 +66,7 @@ USE_L10N = True
USE_TZ = True USE_TZ = True
LOCALE_PATHS = (os.path.join(BASE_DIR, 'scrutiny', 'locale'), ) LOCALE_PATHS = (os.path.join(BASE_DIR, 'scrutiny', 'locale'),)
# Static files (CSS, JavaScript, Images) # Static files (CSS, JavaScript, Images)
# https://docs.djangoproject.com/en/1.7/howto/static-files/ # https://docs.djangoproject.com/en/1.7/howto/static-files/
@ -78,9 +74,7 @@ LOCALE_PATHS = (os.path.join(BASE_DIR, 'scrutiny', 'locale'), )
STATIC_URL = '/static/' STATIC_URL = '/static/'
# Additional locations of static files # Additional locations of static files
STATICFILES_DIRS = ( STATICFILES_DIRS = (os.path.join(BASE_DIR, 'scrutiny', 'static'),)
os.path.join(BASE_DIR, 'scrutiny', 'static'),
)
MEDIA_ROOT = os.path.join(BASE_DIR, 'media') MEDIA_ROOT = os.path.join(BASE_DIR, 'media')
@ -89,9 +83,7 @@ MEDIA_URL = '/media/'
TEMPLATES = [ TEMPLATES = [
{ {
'BACKEND': 'django.template.backends.django.DjangoTemplates', 'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [ 'DIRS': [os.path.join(BASE_DIR, 'scrutiny', 'templates'),],
os.path.join(BASE_DIR, 'scrutiny', 'templates'),
],
'APP_DIRS': True, 'APP_DIRS': True,
'OPTIONS': { 'OPTIONS': {
'context_processors': [ 'context_processors': [
@ -139,13 +131,13 @@ MELLON_USERNAME_TEMPLATE = '{attributes[name_id_content]}'
MELLON_IDENTITY_PROVIDERS = [] MELLON_IDENTITY_PROVIDERS = []
REDMINE_REFERENCE_PLATFORM = 'SaaS2 / Test' REDMINE_REFERENCE_PLATFORM = 'SaaS2 / Test'
REDMINE_URL = 'https://dev.entrouvert.org' REDMINE_URL = 'https://dev.entrouvert.org'
REDMINE_API_KEY = None REDMINE_API_KEY = None
local_settings_file = os.environ.get('SCRUTINY_SETTINGS_FILE', local_settings_file = os.environ.get(
os.path.join(os.path.dirname(__file__), 'local_settings.py')) 'SCRUTINY_SETTINGS_FILE', os.path.join(os.path.dirname(__file__), 'local_settings.py')
)
if os.path.exists(local_settings_file): if os.path.exists(local_settings_file):
exec(open(local_settings_file).read()) exec(open(local_settings_file).read())

View File

@ -19,10 +19,10 @@ def login(request, *args, **kwargs):
if any(get_idps()): if any(get_idps()):
if not 'next' in request.GET: if not 'next' in request.GET:
return HttpResponseRedirect(resolve_url('mellon_login')) return HttpResponseRedirect(resolve_url('mellon_login'))
return HttpResponseRedirect(resolve_url('mellon_login') + '?next=' return HttpResponseRedirect(resolve_url('mellon_login') + '?next=' + quote(request.GET.get('next')))
+ quote(request.GET.get('next')))
return auth_views.login(request, *args, **kwargs) return auth_views.login(request, *args, **kwargs)
def logout(request, next_page=None): def logout(request, next_page=None):
if any(get_idps()): if any(get_idps()):
return HttpResponseRedirect(resolve_url('mellon_logout')) return HttpResponseRedirect(resolve_url('mellon_logout'))
@ -34,7 +34,6 @@ def logout(request, next_page=None):
return HttpResponseRedirect(next_page) return HttpResponseRedirect(next_page)
class Home(TemplateView): class Home(TemplateView):
template_name = 'scrutiny/home.html' template_name = 'scrutiny/home.html'
@ -43,4 +42,5 @@ class Home(TemplateView):
context['projects'] = Project.objects.all() context['projects'] = Project.objects.all()
return context return context
home = Home.as_view() home = Home.as_view()

View File

@ -7,7 +7,9 @@ For more information on this file, see
https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/ https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/
""" """
import os import os
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "scrutiny.settings") os.environ.setdefault("DJANGO_SETTINGS_MODULE", "scrutiny.settings")
from django.core.wsgi import get_wsgi_application from django.core.wsgi import get_wsgi_application
application = get_wsgi_application() application = get_wsgi_application()

View File

@ -5,6 +5,7 @@ from distutils.command.sdist import sdist
import os import os
import subprocess import subprocess
class eo_sdist(sdist): class eo_sdist(sdist):
def run(self): def run(self):
if os.path.exists('VERSION'): if os.path.exists('VERSION'):
@ -17,6 +18,7 @@ class eo_sdist(sdist):
if os.path.exists('VERSION'): if os.path.exists('VERSION'):
os.remove('VERSION') os.remove('VERSION')
def get_version(): def get_version():
'''Use the VERSION, if absent generates a version with git describe, if not '''Use the VERSION, if absent generates a version with git describe, if not
tag exists, take 0.0- and add the length of the commit log. tag exists, take 0.0- and add the length of the commit log.
@ -25,38 +27,35 @@ def get_version():
with open('VERSION', 'r') as v: with open('VERSION', 'r') as v:
return v.read() return v.read()
if os.path.exists('.git'): if os.path.exists('.git'):
p = subprocess.Popen(['git','describe','--dirty=.dirty','--match=v*'], p = subprocess.Popen(
stdout=subprocess.PIPE, stderr=subprocess.PIPE) ['git', 'describe', '--dirty=.dirty', '--match=v*'],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
)
result = p.communicate()[0] result = p.communicate()[0]
if p.returncode == 0: if p.returncode == 0:
result = result.decode('ascii').strip()[1:] # strip spaces/newlines and initial v result = result.decode('ascii').strip()[1:] # strip spaces/newlines and initial v
if '-' in result: # not a tagged version if '-' in result: # not a tagged version
real_number, commit_count, commit_hash = result.split('-', 2) real_number, commit_count, commit_hash = result.split('-', 2)
version = '%s.post%s+%s' % (real_number, commit_count, commit_hash) version = '%s.post%s+%s' % (real_number, commit_count, commit_hash)
else: else:
version = result version = result
return version return version
else: else:
return '0.0.post%s' % len( return '0.0.post%s' % len(subprocess.check_output(['git', 'rev-list', 'HEAD']).splitlines())
subprocess.check_output(
['git', 'rev-list', 'HEAD']).splitlines())
return '0.0' return '0.0'
setup(name='scrutiny',
version=get_version(), setup(
license='AGPLv3', name='scrutiny',
description='', version=get_version(),
author="Entr'ouvert", license='AGPLv3',
author_email="info@entrouvert.com", description='',
packages=find_packages(os.path.dirname(__file__) or '.'), author="Entr'ouvert",
scripts=['manage.py'], author_email="info@entrouvert.com",
include_package_data = True, packages=find_packages(os.path.dirname(__file__) or '.'),
install_requires=[ scripts=['manage.py'],
'django >= 1.8, < 1.12', include_package_data=True,
'requests', install_requires=['django >= 1.8, < 1.12', 'requests', 'gadjo',],
'gadjo', cmdclass={'sdist': eo_sdist,},
],
cmdclass={
'sdist': eo_sdist,
},
) )