mirror of https://github.com/sipwise/repoapi.git
* fix duplicate rule in Makefile * Implement just hotfix for now * /var/lib/repoapi/gerrit.ini needed [gerrit REST HTTP password] Change-Id: I80286e9d97846cf037566eaca74079362fa6e54achanges/11/8411/11
parent
8f0ff90375
commit
16a3bcc4e0
@ -0,0 +1,22 @@
|
|||||||
|
# Copyright (C) 2016 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.Project)
|
||||||
|
class ProjectAdmin(admin.ModelAdmin):
|
||||||
|
pass
|
@ -0,0 +1,31 @@
|
|||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
# Generated by Django 1.9 on 2016-09-23 11:48
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
from django_extensions.db.fields import ModificationDateTimeField
|
||||||
|
from django_extensions.db.fields.json import JSONField
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Project',
|
||||||
|
fields=[
|
||||||
|
('id', models.AutoField(
|
||||||
|
auto_created=True, primary_key=True,
|
||||||
|
serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=50, unique=True)),
|
||||||
|
('json_tags', JSONField(null=True)),
|
||||||
|
('json_branches', JSONField(null=True)),
|
||||||
|
('modified', ModificationDateTimeField(
|
||||||
|
auto_now=True, null=True)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
@ -0,0 +1,88 @@
|
|||||||
|
# Copyright (C) 2016 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 re
|
||||||
|
import json
|
||||||
|
from django.db import models
|
||||||
|
from django_extensions.db.fields.json import JSONField
|
||||||
|
from django_extensions.db.fields import ModificationDateTimeField
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class Project(models.Model):
|
||||||
|
name = models.CharField(max_length=50, unique=True, null=False)
|
||||||
|
json_tags = JSONField(null=True)
|
||||||
|
json_branches = JSONField(null=True)
|
||||||
|
modified = ModificationDateTimeField(null=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _filter_values(cls, values, val_ok_filter, regex=None):
|
||||||
|
res = set()
|
||||||
|
|
||||||
|
for value in values:
|
||||||
|
logger.debug("ref[%s]", value["ref"])
|
||||||
|
match = re.search(val_ok_filter, value["ref"])
|
||||||
|
if match:
|
||||||
|
val_ok = match.group(1)
|
||||||
|
if regex is not None:
|
||||||
|
if re.search(regex, val_ok):
|
||||||
|
res.add(val_ok)
|
||||||
|
logger.debug("val_ok[%s] regex", val_ok)
|
||||||
|
else:
|
||||||
|
logger.debug("val_ok[%s]", val_ok)
|
||||||
|
res.add(val_ok)
|
||||||
|
return sorted(res, reverse=True)
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def _get_filtered_json(cls, text):
|
||||||
|
"""gerrit responds with malformed json
|
||||||
|
https://gerrit-review.googlesource.com/Documentation/rest-api.html#output
|
||||||
|
"""
|
||||||
|
logging.debug("json[:5]: %s", text[:5])
|
||||||
|
return json.loads(text[5:])
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tags(self):
|
||||||
|
return Project._filter_values(self.json_tags, '^refs/tags/(.+)$')
|
||||||
|
|
||||||
|
@tags.setter
|
||||||
|
def tags(self, value):
|
||||||
|
self.json_tags = Project._get_filtered_json(value)
|
||||||
|
|
||||||
|
@property
|
||||||
|
def branches(self):
|
||||||
|
return Project._filter_values(self.json_branches, '^refs/heads/(.+)$')
|
||||||
|
|
||||||
|
@branches.setter
|
||||||
|
def branches(self, value):
|
||||||
|
self.json_branches = Project._get_filtered_json(value)
|
||||||
|
|
||||||
|
def filter_tags(self, regex):
|
||||||
|
return Project._filter_values(self.json_tags,
|
||||||
|
'^refs/tags/(.+)$', regex)
|
||||||
|
|
||||||
|
def filter_branches(self, regex):
|
||||||
|
return Project._filter_values(self.json_branches,
|
||||||
|
'^refs/heads/(.+)$', regex)
|
||||||
|
|
||||||
|
def branches_mrXX(self):
|
||||||
|
return self.filter_branches(r'^mr[0-9]+\.[0-9]+$')
|
||||||
|
|
||||||
|
def branches_mrXXX(self):
|
||||||
|
return self.filter_branches(r'^mr[0-9]+\.[0-9]+\.[0-9]+$')
|
@ -0,0 +1,27 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$('select#common_select').change(function() {
|
||||||
|
var selected_version = $('select#common_select option:selected').val();
|
||||||
|
var ignored = $('.version option[value="ignore"]' );
|
||||||
|
var version = "";
|
||||||
|
if(selected_version.match(/^branch/)) {
|
||||||
|
version = selected_version.replace(
|
||||||
|
/^branch\/(mr[0-9]+\.[0-9]+(\.[0-9]+)?)$/g, "$1");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
version = selected_version.replace(
|
||||||
|
/^tag\/(mr[0-9]+\.[0-9]+\.[0-9]+)(\.[0-9]+)?$/g, "$1");
|
||||||
|
}
|
||||||
|
// set ignored for all
|
||||||
|
ignored.prop('selected', true);
|
||||||
|
ignored.each(function(){ $(this).change(); });
|
||||||
|
$('tr.repo option[value="ignore"]').closest('tr').children('td,th').css('background-color','#F78181');
|
||||||
|
var selected = $('.version option[value="'+ selected_version + '"]' )
|
||||||
|
selected.prop('selected', true);
|
||||||
|
selected.each(function(){ $(this).change(); });
|
||||||
|
$('tr.repo option[value="'+ selected_version + '"]').closest('tr').children('td,th').css('background-color','white');
|
||||||
|
var text = "Selected " + selected.length + " of " + ignored.length;
|
||||||
|
$('#select_text_info').text(text);
|
||||||
|
$('input#version_release').val("release-" + version);
|
||||||
|
});
|
@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function csrfSafeMethod(method) {
|
||||||
|
// these HTTP methods do not require CSRF protection
|
||||||
|
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
|
||||||
|
}
|
||||||
|
|
||||||
|
function csrftokenFunc(xhr, settings) {
|
||||||
|
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
|
||||||
|
xhr.setRequestHeader("X-CSRFToken", csrftoken);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function getCookie(name) {
|
||||||
|
var cookieValue = null;
|
||||||
|
if (document.cookie && document.cookie !== '') {
|
||||||
|
var cookies = document.cookie.split(';');
|
||||||
|
for (var i = 0; i < cookies.length; i++) {
|
||||||
|
var cookie = jQuery.trim(cookies[i]);
|
||||||
|
// Does this cookie string begin with the name we want?
|
||||||
|
if (cookie.substring(0, name.length + 1) === (name + '=')) {
|
||||||
|
cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cookieValue;
|
||||||
|
}
|
||||||
|
var csrftoken = getCookie('csrftoken');
|
@ -0,0 +1,61 @@
|
|||||||
|
/**
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
$('button.hotfix').click(function(e){
|
||||||
|
// don't send the form
|
||||||
|
e.preventDefault();
|
||||||
|
var button = $(this);
|
||||||
|
var id = button.attr('id').replace('hotfix_','');
|
||||||
|
var branch = $('select#version_' + id + ' option:selected').val().replace('branch/', '');
|
||||||
|
var repo = id;
|
||||||
|
var span = $('span#hotfix_error_' + id);
|
||||||
|
var push = $('select#push_' + id + ' option:selected').val();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: branch + '/' + repo + '/',
|
||||||
|
type: 'POST',
|
||||||
|
data: JSON.stringify({push: push }),
|
||||||
|
contentType: "application/json; charset=utf-8",
|
||||||
|
dataType: "json",
|
||||||
|
success: successFunc,
|
||||||
|
error: errorFunc,
|
||||||
|
beforeSend: csrftokenFunc
|
||||||
|
});
|
||||||
|
|
||||||
|
button.attr("disabled", "disabled");
|
||||||
|
span.html('processing');
|
||||||
|
span.show();
|
||||||
|
|
||||||
|
function successFunc(data, status) {
|
||||||
|
span.html('');
|
||||||
|
span.append('<a href="' + data.url + '">Done</a>');
|
||||||
|
button.removeAttr("disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorFunc(jqXHR, status, error) {
|
||||||
|
span.html(error);
|
||||||
|
button.removeAttr("disabled");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
$('td.version > select').change(function() {
|
||||||
|
var id = $(this).attr('id').replace('version_','');
|
||||||
|
var version = $(this).val();
|
||||||
|
var button = $('button#hotfix_' + id);
|
||||||
|
var span = $('span#hotfix_error_' + id);
|
||||||
|
|
||||||
|
if (version.match(/^branch\/mr[0-9]+\.[0-9]+\.[0-9]+$/)) {
|
||||||
|
button.html("Release hotfix");
|
||||||
|
button.removeAttr("disabled");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
button.html("Select branch to hotfix");
|
||||||
|
button.attr("disabled", "disabled");
|
||||||
|
}
|
||||||
|
span.html('');
|
||||||
|
});
|
||||||
|
|
||||||
|
$( document ).ready(function() {
|
||||||
|
$('td.version > select option[value^="branch/mr"]').each(function(){ $(this).change(); });
|
||||||
|
});
|
@ -0,0 +1,66 @@
|
|||||||
|
/**
|
||||||
|
* refresh info
|
||||||
|
*/
|
||||||
|
$('button#refresh_all').click(function(e){
|
||||||
|
// don't send the form
|
||||||
|
e.preventDefault();
|
||||||
|
var button = $(this);
|
||||||
|
var span = $('span#refresh_all_error');
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/release_panel/refresh/',
|
||||||
|
type: 'POST',
|
||||||
|
success: successFunc,
|
||||||
|
error: errorFunc,
|
||||||
|
beforeSend: csrftokenFunc
|
||||||
|
});
|
||||||
|
|
||||||
|
function successFunc(data, status) {
|
||||||
|
span.html('');
|
||||||
|
span.append('<a href="' + data.url + '">Done</a><br/>');
|
||||||
|
span.append('This will take a while. Refresh the page in a few');
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorFunc(jqXHR, status, error) {
|
||||||
|
span.html(error);
|
||||||
|
button.removeAttr("disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
//deactivate button
|
||||||
|
button.attr("disabled", "disabled");
|
||||||
|
span.html('processing');
|
||||||
|
span.show();
|
||||||
|
});
|
||||||
|
|
||||||
|
$('button.refresh').click(function(e){
|
||||||
|
// don't send the form
|
||||||
|
e.preventDefault();
|
||||||
|
var button = $(this);
|
||||||
|
var project = button.attr('id').replace('refresh_','');
|
||||||
|
var span = $('span#refresh_error_' + project );
|
||||||
|
|
||||||
|
function successFunc(data, status) {
|
||||||
|
span.html('');
|
||||||
|
span.append('<a href="' + data.url + '">Done</a>');
|
||||||
|
button.removeAttr("disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
function errorFunc(jqXHR, status, error) {
|
||||||
|
span.html(error);
|
||||||
|
button.removeAttr("disabled");
|
||||||
|
}
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '/release_panel/refresh/' + project + '/',
|
||||||
|
type: 'POST',
|
||||||
|
success: successFunc,
|
||||||
|
error: errorFunc,
|
||||||
|
beforeSend: csrftokenFunc
|
||||||
|
});
|
||||||
|
|
||||||
|
//deactivate button
|
||||||
|
button.attr("disabled", "disabled");
|
||||||
|
span.html('processing');
|
||||||
|
span.show();
|
||||||
|
|
||||||
|
});
|
@ -0,0 +1,38 @@
|
|||||||
|
# Copyright (C) 2016 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 release_dashboard.models import Project
|
||||||
|
from django.conf import settings
|
||||||
|
from .utils import get_gerrit_tags, get_gerrit_branches
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
rd_settings = settings.RELEASE_DASHBOARD_SETTINGS
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(ignore_result=True)
|
||||||
|
def gerrit_fetch_info(projectname):
|
||||||
|
project, _ = Project.objects.get_or_create(name=projectname)
|
||||||
|
project.tags = get_gerrit_tags(projectname)
|
||||||
|
project.branches = get_gerrit_branches(projectname)
|
||||||
|
project.save()
|
||||||
|
|
||||||
|
|
||||||
|
@shared_task(ignore_result=True)
|
||||||
|
def gerrit_fetch_all():
|
||||||
|
for project in rd_settings['projects']:
|
||||||
|
gerrit_fetch_info.delay(project)
|
@ -0,0 +1,4 @@
|
|||||||
|
{% extends "panel/base.html" %}
|
||||||
|
{% block applist %}
|
||||||
|
<li><a href="{% url 'panel:index' %}">Panel</a></li>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,79 @@
|
|||||||
|
{% extends "release_dashboard/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% block title %}Build release{% endblock %}
|
||||||
|
{% block navlist %}
|
||||||
|
<li><a href="{% url 'release_dashboard:index'%}">Release Dashboard</a></li>
|
||||||
|
<li><a href="{% url 'release_dashboard:build_release'%}">Build release</a></li>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Actions</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form class="form-inline">{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="common_select">Common selection</label>
|
||||||
|
<select class="form-control" id="common_select"
|
||||||
|
name="common_select">
|
||||||
|
<option value="ignore">ignore</option>
|
||||||
|
{% for v in common_versions.tags %}
|
||||||
|
<option value="tag/{{ v }}">tag/{{ v }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
{% for v in common_versions.branches %}
|
||||||
|
<option value="branch/{{ v }}">branch/{{ v }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<span id="select_text_info"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="version_release">Release version</label>
|
||||||
|
<input class="form-control" id="version_release"
|
||||||
|
name="version_release" type="text" value="">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="distribution">Debian release</label>
|
||||||
|
<select class="form-control" id="distribution"
|
||||||
|
name="distribution">
|
||||||
|
{% for d in debian %}
|
||||||
|
<option value="{{ d }}">{{ d }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Project</th>
|
||||||
|
<th>Version</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for p in projects %}
|
||||||
|
<tr class="repo">
|
||||||
|
<th><label for="version_{{ p.name }}">{{ p.name }}</label></th>
|
||||||
|
<td class="version">
|
||||||
|
<select id="version_{{ p.name }}" name="version_{{ p.name }}">
|
||||||
|
<option value="ignore">ignore</option>
|
||||||
|
{% for t in p.tags %}
|
||||||
|
<option value="tag/{{ t }}">tag/{{ t }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
{% for b in p.branches %}
|
||||||
|
<option value="branch/{{ b }}">branch/{{ b }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block extrajs %}
|
||||||
|
<script src="{% static "release_dashboard/js/build.js" %}"></script>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,79 @@
|
|||||||
|
{% extends "release_dashboard/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% block title %}Build dependences{% endblock %}
|
||||||
|
{% block navlist %}
|
||||||
|
<li><a href="{% url 'release_dashboard:index'%}">Release Dashboard</a></li>
|
||||||
|
<li><a href="{% url 'release_dashboard:build_deps'%}">Build dependences</a></li>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Actions</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form class="form-inline">{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="common_select">Common selection</label>
|
||||||
|
<select class="form-control" id="common_select"
|
||||||
|
name="common_select">
|
||||||
|
<option value="ignore">ignore</option>
|
||||||
|
{% for v in common_versions.tags %}
|
||||||
|
<option value="tags/{{ v }}">tags/{{ v }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
{% for v in common_versions.branches %}
|
||||||
|
<option value="branch/{{ v }}">branch/{{ v }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
<span id="select_text_info"></span>
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="version_release">Release version</label>
|
||||||
|
<input class="form-control" id="version_release"
|
||||||
|
name="version_release" type="text" value="">
|
||||||
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="distribution">Debian release</label>
|
||||||
|
<select class="form-control" id="distribution"
|
||||||
|
name="distribution">
|
||||||
|
{% for d in debian %}
|
||||||
|
<option value="{{ d }}">{{ d }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Project</th>
|
||||||
|
<th>Version</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{% for p in projects %}
|
||||||
|
<tr class="repo">
|
||||||
|
<th><label for="version_{{ p.name }}">{{ p.name }}</label></th>
|
||||||
|
<td class="version">
|
||||||
|
<select id="version_{{ p.name }}" name="version_{{ p.name }}">
|
||||||
|
<option value="ignore">ignore</option>
|
||||||
|
{% for t in p.tags %}
|
||||||
|
<option value="tag/{{ t }}">tag/{{ t }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
{% for b in p.branches %}
|
||||||
|
<option value="branch/{{ b }}">branch/{{ b }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block extrajs %}
|
||||||
|
<script src="{% static "release_dashboard/js/build.js" %}"></script>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,58 @@
|
|||||||
|
{% extends "release_dashboard/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% block title %}Hotfixes{% endblock %}
|
||||||
|
{% block navlist %}
|
||||||
|
<li><a href="{% url 'release_dashboard:index'%}">Release Dashboard</a></li>
|
||||||
|
<li><a href="{% url 'release_dashboard:hotfix'%}">Hotfixes</a></li>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Project</th>
|
||||||
|
<th>Version</th>
|
||||||
|
<th>Push</th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<form class="form-inline">{% csrf_token %}</form>
|
||||||
|
{% for p in projects %}
|
||||||
|
<tr class="repo">
|
||||||
|
<th><label for="version_{{ p.name }}">{{ p.name }}</label></th>
|
||||||
|
<td class="version">
|
||||||
|
<select class="form-control" id="version_{{ p.name }}" name="version_{{ p.name }}">
|
||||||
|
<option value="ignore">ignore</option>
|
||||||
|
{% for t in p.tags %}
|
||||||
|
<option value="tag/{{ t }}">tag/{{ t }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
{% for b in p.branches %}
|
||||||
|
<option value="branch/{{ b }}">branch/{{ b }}</option>
|
||||||
|
{% endfor %}
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<select class="form-control" id="push_{{ p.name }}">
|
||||||
|
<option value="yes" selected="selected">yes</option>
|
||||||
|
<option value="no">no</option>
|
||||||
|
</select>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button type="button" id="hotfix_{{ p.name }}" class="btn btn-warning hotfix" disabled="disabled">Select branch to hotfix</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span class="text-danger" id="hotfix_error_{{ p.name }}"></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block extrajs %}
|
||||||
|
<script src="{% static "release_dashboard/js/csrf.js" %}"></script>
|
||||||
|
<script src="{% static "release_dashboard/js/hotfix.js" %}"></script>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,36 @@
|
|||||||
|
{% extends "release_dashboard/base.html" %}
|
||||||
|
{% block title %}Release Dashboard{% endblock %}
|
||||||
|
{% block navlist %}
|
||||||
|
<li><a href="{% url 'release_dashboard:index'%}">Release Dashboard</a></li>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Actions</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<ul class="list-group">
|
||||||
|
<!-- Not implemented
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a href="{% url 'release_dashboard:build_deps'%}">
|
||||||
|
Build release dependences</a>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a href="{% url 'release_dashboard:build_release'%}">
|
||||||
|
Build release</a>
|
||||||
|
</li>
|
||||||
|
-->
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a href="{% url 'release_dashboard:hotfix'%}">
|
||||||
|
Hotfixes</a>
|
||||||
|
</li>
|
||||||
|
<li class="list-group-item">
|
||||||
|
<a href="{% url 'release_dashboard:refresh_all'%}">
|
||||||
|
Refresh tag/branch Info</a>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,53 @@
|
|||||||
|
{% extends "release_dashboard/base.html" %}
|
||||||
|
{% load staticfiles %}
|
||||||
|
{% block title %}Hotfixes{% endblock %}
|
||||||
|
{% block navlist %}
|
||||||
|
<li><a href="{% url 'release_dashboard:index'%}">Release Dashboard</a></li>
|
||||||
|
<li><a href="{% url 'release_dashboard:refresh_all'%}">Refresh Info</a></li>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="container">
|
||||||
|
<div class="panel panel-default">
|
||||||
|
<div class="panel-heading">
|
||||||
|
<h3 class="panel-title">Actions</h3>
|
||||||
|
</div>
|
||||||
|
<div class="panel-body">
|
||||||
|
<form class="form-inline">{% csrf_token %}
|
||||||
|
<div class="form-group">
|
||||||
|
<button type="button" class="btn btn-danger" id="refresh_all">Refresh All</button>
|
||||||
|
<span style="display:none" id="refresh_all_error"></span>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<table class="table table-condensed">
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>Project</th>
|
||||||
|
<th></th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<form class="form-inline">{% csrf_token %}</form>
|
||||||
|
{% for p in projects %}
|
||||||
|
<tr class="repo">
|
||||||
|
<th><label for="version_{{ p.name }}">{{ p.name }}</label></th>
|
||||||
|
<td>
|
||||||
|
<button type="button" class="btn btn-info refresh" id="refresh_{{ p.name }}" class="refresh">Refresh</button>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span style="display:none" class="text-danger" id="refresh_error_{{ p.name }}"></span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{% endfor %}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{% endblock %}
|
||||||
|
{% block extrajs %}
|
||||||
|
<script src="{% static "release_dashboard/js/csrf.js" %}"></script>
|
||||||
|
<script src="{% static "release_dashboard/js/refresh_info.js" %}"></script>
|
||||||
|
{% endblock %}
|
@ -0,0 +1,155 @@
|
|||||||
|
# Copyright (C) 2016 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/>.
|
||||||
|
import copy
|
||||||
|
from django.test import TestCase
|
||||||
|
from release_dashboard.models import Project
|
||||||
|
|
||||||
|
GERRIT_REST_TAGS = """
|
||||||
|
)]}'
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"ref": "refs/tags/mr2.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ref": "refs/tags/mr1.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
FILTERED_TAGS = [
|
||||||
|
{
|
||||||
|
"ref": "refs/tags/mr2.0.0"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ref": "refs/tags/mr1.0.0"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
GERRIT_REST_BRANCHES = """
|
||||||
|
)]}'
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"ref": "refs/heads/master"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ref": "refs/heads/vseva/1789"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
"""
|
||||||
|
FILTERED_BRANCHES = [
|
||||||
|
{
|
||||||
|
"ref": "refs/heads/master"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"ref": "refs/heads/vseva/1789"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
class ProjectTestCase(TestCase):
|
||||||
|
|
||||||
|
def test_create(self):
|
||||||
|
proj = Project.objects.create(name="fake")
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
|
||||||
|
def test_tags(self):
|
||||||
|
proj = Project.objects.create(name="fake", json_tags=FILTERED_TAGS)
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertIsInstance(proj.tags, list)
|
||||||
|
self.assertItemsEqual(proj.tags, ["mr2.0.0", "mr1.0.0", ])
|
||||||
|
|
||||||
|
def test_tags_null(self):
|
||||||
|
proj = Project.objects.create(name="fake")
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertIsInstance(proj.tags, list)
|
||||||
|
self.assertItemsEqual(proj.tags, [])
|
||||||
|
|
||||||
|
def test_branches(self):
|
||||||
|
proj = Project.objects.create(name="fake",
|
||||||
|
json_branches=FILTERED_BRANCHES)
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertIsInstance(proj.branches, list)
|
||||||
|
self.assertItemsEqual(proj.branches, ["vseva/1789", "master"])
|
||||||
|
|
||||||
|
def test_branches_null(self):
|
||||||
|
proj = Project.objects.create(name="fake")
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertIsInstance(proj.branches, list)
|
||||||
|
self.assertItemsEqual(proj.branches, [])
|
||||||
|
|
||||||
|
def test_filtered_json(self):
|
||||||
|
res = Project._get_filtered_json(GERRIT_REST_TAGS)
|
||||||
|
self.assertEquals(res, FILTERED_TAGS)
|
||||||
|
|
||||||
|
def test_filter_values(self):
|
||||||
|
values = copy.deepcopy(FILTERED_TAGS)
|
||||||
|
res = Project._filter_values(FILTERED_TAGS, '^refs/tags/(.+)$')
|
||||||
|
self.assertEquals(res, ['mr2.0.0', 'mr1.0.0'])
|
||||||
|
values.append({"ref": "no/no"})
|
||||||
|
res = Project._filter_values(values, '^refs/tags/(.+)$')
|
||||||
|
self.assertEquals(res, ['mr2.0.0', 'mr1.0.0'])
|
||||||
|
|
||||||
|
def test_filter_values_regex(self):
|
||||||
|
values = copy.deepcopy(FILTERED_TAGS)
|
||||||
|
res = Project._filter_values(FILTERED_TAGS, '^refs/tags/(.+)$',
|
||||||
|
r'^mr[0-9]+\.[0-9]+\.[0-9]+$')
|
||||||
|
self.assertEquals(res, ['mr2.0.0', 'mr1.0.0'])
|
||||||
|
values.append({"ref": "refs/tags/3.7.8"})
|
||||||
|
res = Project._filter_values(values, '^refs/tags/(.+)$',
|
||||||
|
r'^mr[0-9]+\.[0-9]+\.[0-9]+$')
|
||||||
|
self.assertEquals(res, ['mr2.0.0', 'mr1.0.0'])
|
||||||
|
res = Project._filter_values(values, '^refs/tags/(.+)$',
|
||||||
|
r'^[0-9]+\.[0-9]+\.[0-9]+$')
|
||||||
|
self.assertEquals(res, ['3.7.8'])
|
||||||
|
|
||||||
|
def test_tags_set(self):
|
||||||
|
proj = Project.objects.create(name="fake")
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertIsInstance(proj.tags, list)
|
||||||
|
self.assertItemsEqual(proj.tags, [])
|
||||||
|
proj.tags = GERRIT_REST_TAGS
|
||||||
|
self.assertItemsEqual(proj.tags, ["mr2.0.0", "mr1.0.0"])
|
||||||
|
|
||||||
|
def test_branches_set(self):
|
||||||
|
proj = Project.objects.create(name="fake")
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertIsInstance(proj.branches, list)
|
||||||
|
self.assertItemsEqual(proj.branches, [])
|
||||||
|
proj.branches = GERRIT_REST_BRANCHES
|
||||||
|
self.assertItemsEqual(proj.branches, ["master", "vseva/1789"])
|
||||||
|
|
||||||
|
def test_branches_mrXX(self):
|
||||||
|
tmp = [
|
||||||
|
{"ref": "refs/heads/master"},
|
||||||
|
{"ref": "refs/heads/mr0.1"},
|
||||||
|
{"ref": "refs/heads/mr0.1.1"},
|
||||||
|
{"ref": "refs/heads/vseva/nono"},
|
||||||
|
]
|
||||||
|
proj = Project.objects.create(name="fake",
|
||||||
|
json_branches=tmp)
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertItemsEqual(proj.branches_mrXX(),
|
||||||
|
["mr0.1", ])
|
||||||
|
|
||||||
|
def test_branches_mrXXX(self):
|
||||||
|
tmp = [
|
||||||
|
{"ref": "refs/heads/master"},
|
||||||
|
{"ref": "refs/heads/mr0.1"},
|
||||||
|
{"ref": "refs/heads/mr0.1.1"},
|
||||||
|
{"ref": "refs/heads/vseva/nono"},
|
||||||
|
]
|
||||||
|
proj = Project.objects.create(name="fake",
|
||||||
|
json_branches=tmp)
|
||||||
|
self.assertEquals(proj.name, "fake")
|
||||||
|
self.assertItemsEqual(proj.branches_mrXXX(),
|
||||||
|
["mr0.1.1", ])
|
@ -0,0 +1,28 @@
|
|||||||
|
# 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
from django.conf.urls import url
|
||||||
|
from . import views
|
||||||
|
|
||||||
|
urlpatterns = [
|
||||||
|
url(r'^$', views.index, name='index'),
|
||||||
|
url(r'^build_deps/$', views.build_deps, name='build_deps'),
|
||||||
|
url(r'^build/$', views.build_release, name='build_release'),
|
||||||
|
url(r'^hotfix/$', views.hotfix, name='hotfix'),
|
||||||
|
url(r'^hotfix/(?P<branch>[^/]+)/(?P<project>[^/]+)/$',
|
||||||
|
views.hotfix_build),
|
||||||
|
url(r'^refresh/$', views.refresh_all, name='refresh_all'),
|
||||||
|
url(r'^refresh/(?P<project>[^/]+)/$', views.refresh, name='refresh'),
|
||||||
|
]
|
@ -0,0 +1,87 @@
|
|||||||
|
# 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import uuid
|
||||||
|
import urllib
|
||||||
|
import requests
|
||||||
|
from requests.auth import HTTPDigestAuth
|
||||||
|
from django.conf import settings
|
||||||
|
from repoapi.utils import openurl
|
||||||
|
from release_dashboard.models import Project
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
def get_response(url):
|
||||||
|
auth = HTTPDigestAuth(
|
||||||
|
settings.GERRIT_REST_HTTP_USER,
|
||||||
|
settings.GERRIT_REST_HTTP_PASSWD)
|
||||||
|
response = requests.get(url, auth=auth)
|
||||||
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
def trigger_hotfix(project, branch, push="yes"):
|
||||||
|
flow_uuid = uuid.uuid4()
|
||||||
|
params = {
|
||||||
|
"base": settings.JENKINS_URL,
|
||||||
|
'token': urllib.quote(settings.JENKINS_TOKEN),
|
||||||
|
'action': urllib.quote("--hotfix"),
|
||||||
|
'branch': urllib.quote(branch),
|
||||||
|
'project': urllib.quote(project),
|
||||||
|
'push': urllib.quote(push),
|
||||||
|
'uuid': flow_uuid,
|
||||||
|
}
|
||||||
|
url = ("{base}/job/release-tools-runner/buildWithParameters?"
|
||||||
|
"token={token}&action={action}&branch={branch}&"
|
||||||
|
"PROJECTNAME={project}&repository={project}&"
|
||||||
|
"push={push}&uuid={uuid}".format(**params))
|
||||||
|
|
||||||
|
if settings.DEBUG:
|
||||||
|
logger.debug("Debug mode, would trigger: %s", url)
|
||||||
|
# raise Exception("debug error")
|
||||||
|
else:
|
||||||
|
openurl(url)
|
||||||
|
return "%s/job/release-tools-runner/" % settings.JENKINS_URL
|
||||||
|
|
||||||
|
|
||||||
|
def get_gerrit_info(url):
|
||||||
|
if settings.DEBUG:
|
||||||
|
logger.debug("Debug mode, would trigger: %s", url)
|
||||||
|
return r")]}'\n[]"
|
||||||
|
else:
|
||||||
|
response = get_response(url)
|
||||||
|
response.raise_for_status()
|
||||||
|
return response.text
|
||||||
|
|
||||||
|
|
||||||
|
def get_tags(projectname, regex=None):
|
||||||
|
project, _ = Project.objects.get_or_create(name=projectname)
|
||||||
|
return project.filter_tags(regex)
|
||||||
|
|
||||||
|
|
||||||
|
def get_branches(projectname, regex=None):
|
||||||
|
project, _ = Project.objects.get_or_create(name=projectname)
|
||||||
|
return project.filter_branches(regex)
|
||||||
|
|
||||||
|
|
||||||
|
def get_gerrit_tags(project, regex=None):
|
||||||
|
url = settings.GERRIT_URL.format("a/projects/%s/tags/" % project)
|
||||||
|
return get_gerrit_info(url)
|
||||||
|
|
||||||
|
|
||||||
|
def get_gerrit_branches(project, regex=None):
|
||||||
|
url = settings.GERRIT_URL.format("a/projects/%s/branches/" % project)
|
||||||
|
return get_gerrit_info(url)
|
@ -0,0 +1,142 @@
|
|||||||
|
# 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 <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import logging
|
||||||
|
import re
|
||||||
|
import json
|
||||||
|
from django.shortcuts import render
|
||||||
|
from django.http import HttpResponseNotFound, JsonResponse
|
||||||
|
from django.conf import settings
|
||||||
|
from django.views.decorators.http import require_http_methods
|
||||||
|
from release_dashboard.models import Project
|
||||||
|
from .utils import get_tags, get_branches, trigger_hotfix
|
||||||
|
from .tasks import gerrit_fetch_info, gerrit_fetch_all
|
||||||
|
|
||||||
|
rd_settings = settings.RELEASE_DASHBOARD_SETTINGS
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
regex_hotfix = re.compile(r'^mr[0-9]+\.[0-9]+\.[0-9]+$')
|
||||||
|
regex_mr = re.compile(r'^mr.+$')
|
||||||
|
|
||||||
|
|
||||||
|
def index(request):
|
||||||
|
context = {}
|
||||||
|
return render(request, 'release_dashboard/index.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
def _projects_versions(projects, regex=None, tag_only=False, ):
|
||||||
|
res = []
|
||||||
|
for project in projects:
|
||||||
|
info = {
|
||||||
|
'name': project,
|
||||||
|
'tags': get_tags(project, regex),
|
||||||
|
}
|
||||||
|
if not tag_only:
|
||||||
|
info['branches'] = get_branches(project, regex)
|
||||||
|
res.append(info)
|
||||||
|
logger.debug(res)
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def _common_versions(context):
|
||||||
|
common_versions = {'tags': set(), 'branches': set()}
|
||||||
|
|
||||||
|
for project in context['projects']:
|
||||||
|
common_versions['tags'] |= set(project['tags'])
|
||||||
|
common_versions['branches'] |= set(project['branches'])
|
||||||
|
context['common_versions'] = {
|
||||||
|
'tags': sorted(common_versions['tags']),
|
||||||
|
'branches': sorted(common_versions['branches']),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@require_http_methods(["POST", ])
|
||||||
|
def hotfix_build(request, branch, project):
|
||||||
|
if project not in rd_settings['projects']:
|
||||||
|
error = "repo:%s not valid" % project
|
||||||
|
logger.error(error)
|
||||||
|
return HttpResponseNotFound(error)
|
||||||
|
|
||||||
|
if not regex_hotfix.match(branch):
|
||||||
|
error = "branch:%s not valid. Not mrX.X.X format" % branch
|
||||||
|
logger.error(error)
|
||||||
|
return HttpResponseNotFound(error)
|
||||||
|
proj = Project.objects.get(name=project)
|
||||||
|
|
||||||
|
if branch not in proj.branches_mrXXX():
|
||||||
|
error = "branch:%s not valid" % branch
|
||||||
|
logger.error(error)
|
||||||
|
return HttpResponseNotFound(error)
|
||||||
|
|
||||||
|
json_data = json.loads(request.body)
|
||||||
|
if json_data['push'] == 'no':
|
||||||
|
logger.warn("dryrun for %s:%s", project, branch)
|
||||||
|
url = trigger_hotfix(project, branch, json_data['push'])
|
||||||
|
return JsonResponse({'url': url})
|
||||||
|
|
||||||
|
|
||||||
|
def build_deps(request):
|
||||||
|
context = {
|
||||||
|
'projects': _projects_versions(
|
||||||
|
rd_settings['build_deps'],
|
||||||
|
regex_mr
|
||||||
|
),
|
||||||
|
'debian': rd_settings['debian_supported'],
|
||||||
|
}
|
||||||
|
_common_versions(context)
|
||||||
|
return render(request, 'release_dashboard/build_deps.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
def hotfix(request):
|
||||||
|
context = {
|
||||||
|
'projects': _projects_versions(
|
||||||
|
rd_settings['projects'],
|
||||||
|
regex_hotfix
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return render(request, 'release_dashboard/hotfix.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
def build_release(request):
|
||||||
|
context = {
|
||||||
|
'projects': _projects_versions(
|
||||||
|
rd_settings['projects'],
|
||||||
|
regex_mr
|
||||||
|
),
|
||||||
|
'debian': rd_settings['debian_supported'],
|
||||||
|
}
|
||||||
|
_common_versions(context)
|
||||||
|
return render(request, 'release_dashboard/build.html', context)
|
||||||
|
|
||||||
|
|
||||||
|
def refresh_all(request):
|
||||||
|
if request.method == "POST":
|
||||||
|
res = gerrit_fetch_all.delay()
|
||||||
|
return JsonResponse({'url': '/flower/task/%s' % res.id})
|
||||||
|
else:
|
||||||
|
projects = []
|
||||||
|
for project in rd_settings['projects']:
|
||||||
|
info = {
|
||||||
|
'name': project,
|
||||||
|
'tags': None
|
||||||
|
}
|
||||||
|
projects.append(info)
|
||||||
|
return render(request, 'release_dashboard/refresh.html',
|
||||||
|
{'projects': projects})
|
||||||
|
|
||||||
|
|
||||||
|
@require_http_methods(["POST", ])
|
||||||
|
def refresh(request, project):
|
||||||
|
res = gerrit_fetch_info.delay(project)
|
||||||
|
return JsonResponse({'url': '/flower/task/%s' % res.id})
|
Loading…
Reference in new issue