Commit 5c3ecd2d authored by Leo Iannacone's avatar Leo Iannacone

Merge branch 'master' into portable

parents 5dab766b 94ee6bd6
......@@ -17,47 +17,75 @@
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA.
#
# Log information about building packages in a JSON format.
# Log information about debomatic status in a JSON format.
#
# If you want to config this module, please add this info
# to your debomatic.conf
# [jsonlogger]
# jsonfile = /path/to/jsonfile.log
import os
from time import time
from json import dumps as toJSON
class DebomaticModule_JSONLogger:
def __init__(self):
self.logfile = '/var/log/debomatic-json.log'
self.jsonfile = '/var/log/debomatic-json.log'
def _set_jsonfile(self, args):
"""If debomatic config file has section [jsonlogger] try to get
'jsonfile' option and override the default value."""
if 'opts' in args and args['opts'].has_section('jsonlogger'):
self.jsonfile = args['opts'].get('jsonlogger', 'jsonfile').strip()
def _set_logfile(self, args):
if args['opts'].has_section('jsonlogger'):
self.logfile = args['opts'].get('jsonlogger', 'jsonfile').strip()
def _append_info_to_logfile(self, args, info):
"""Write info to jsonfile converted in JSON format."""
self._set_jsonfile(args)
info['time'] = int(time())
with open(self.jsonfile, 'a') as logfd:
json = toJSON(info)
logfd.write(json + '\n')
def _get_info(self, args):
def _get_distribution_info(self, args):
"""From args to distribution info."""
info = {}
info['status'] = args['cmd']
info['distribution'] = args['distribution']
if 'success' in args:
info['success'] = args['success']
return info
def _get_package_info(self, args):
"""From args to package info."""
keys = ['package', 'distribution', 'uploader']
info = {}
for k in keys:
if args.has_key(k):
if k in args:
info[k] = args[k]
return info
def pre_chroot(self, args):
distribution = self._get_distribution_info(args)
self._append_info_to_logfile(args, distribution)
def post_chroot(self, args):
distribution = self._get_distribution_info(args)
self._append_info_to_logfile(args, distribution)
def pre_build(self, args):
self._set_logfile(args)
with open(self.logfile, 'a') as fd:
package = self._get_info(args)
package['status'] = 'building'
json = toJSON(package)
fd.write(json + '\n')
package = self._get_package_info(args)
package['status'] = 'build'
self._append_info_to_logfile(args, package)
def post_build(self, args):
self._set_logfile(args)
with open(self.logfile, 'a') as fd:
status = 'build-failed'
package = self._get_info(args)
package = self._get_package_info(args)
package['status'] = 'build'
package['success'] = False
resultdir = os.path.join(args['directory'], 'pool', args['package'])
for filename in os.listdir(resultdir):
if filename.endswith('.dsc'):
status = 'build-successed'
package['success'] = True
break
package['status'] = status
json = toJSON(package)
fd.write(json + '\n')
self._append_info_to_logfile(args, package)
......@@ -59,15 +59,14 @@ server.listen(config.port, config.host, null, function(err){
}
// statuses
var status = {}
status.packages = []
var status = []
var broadcast = new Broadcaster(io.sockets, status)
io.sockets.on('connection', function(socket) {
var client = new Client(socket)
client.start()
if (status.packages.length > 0)
if (status.length > 0)
client.send_status(status)
});
......
......@@ -2,9 +2,24 @@ var config = require('./config.js')
, fs = require('fs')
, Tail = require('./tail.js')
function __watch_status_check_same_obj (obj1, obj2) {
if (obj1.status == obj2.status) {
if (obj1.distribution == obj2.distribution) {
if (obj1.hasOwnProperty('package') &&
obj2.hasOwnProperty('package'))
{
if (obj1.package == obj2.package)
return true;
return false
}
return true
}
}
return false
}
// watcher on build_status
function __watch_build_status (socket, status) {
function __watch_status (socket, status) {
var watcher = new Tail(config.debomatic.jsonfile)
watcher.on('line', function(new_content) {
......@@ -12,39 +27,24 @@ function __watch_build_status (socket, status) {
try {
data = JSON.parse(new_content)
} catch (err) {
utils.errors_handler('Broadcaster:__watch_build_status:JSON.parse(new_content) - ', err, socket)
utils.errors_handler('Broadcaster:__watch_status:JSON.parse(new_content) - ', err, socket)
return
}
// looking for same package already in status.packages
var index = -1
for(i = 0; i < status.packages.length; i++)
{
p = status.packages[i]
if ( p.package == data.package
&& p.distribution == data.distribution )
{
index = i
break
// looking for same status already in statuses lists
if (data.hasOwnProperty('success')) {
for(i = 0; i < status.length; i++) {
if (__watch_status_check_same_obj(data, status[i])) {
status.splice(i, 1)
break;
}
else
continue;
}
if (data.status == config.status.package.building) {
if (index == -1) { // not found in status.packages
status.packages.push(data)
socket.emit(config.events.broadcast.status_update, data)
return
}
}
if (data.status == config.status.package.successed
|| data.status == config.status.package.failed )
{
if (index >= 0) { // found in status.packages - remove
status.packages.splice(index, 1)
else {
status.push(data)
}
socket.emit(config.events.broadcast.status_update, data)
}
})
watcher.on('error', function(msg) {
socket.emit(config.events.error, msg)
......@@ -65,7 +65,7 @@ function Broadcaster (sockets, status) {
var sockets = sockets
__watch_build_status(sockets, status)
__watch_status(sockets, status)
__watch_distributions(sockets)
......
......@@ -52,6 +52,7 @@ function __send_package_status(socket, data, package_data) {
new_data.package = package_data
var status_data = {}
status_data.status = config.status.build
status_data.distribution = data.distribution.name
status_data.package = package_data.orig_name
......@@ -62,9 +63,9 @@ function __send_package_status(socket, data, package_data) {
// + building: wc -l .datestamp == 1 (FIX_ME)
// + failed: else
var base_path = path.join(package_path, package_data.orig_name)
fs.exists(base_path + '.dsc', function(changes_exists){
if (changes_exists) {
status_data.status = config.status.package.successed
fs.exists(base_path + '.dsc', function(dsc_exists){
if (dsc_exists) {
status_data.success = config.status.success
socket.emit(event_name, status_data)
}
else {
......@@ -80,10 +81,8 @@ function __send_package_status(socket, data, package_data) {
if (chunk[i] == 10) count++;
})
.on('end', function() {
if (count <= 1)
status_data.status = config.status.package.building
else
status_data.status = config.status.package.failed
if (count > 1)
status_data.success = config.status.fail
socket.emit(event_name, status_data)
});
}
......
......@@ -51,7 +51,7 @@ config.web.preferences = {}
config.web.preferences.autoscroll = true
config.web.preferences.header = true
config.web.preferences.sidebar = true
config.web.preferences.glossy_theme = false
config.web.preferences.glossy_theme = true
config.web.preferences.file_background = true
config.web.preferences.file_fontsize = 13 // valid values are [13..16]
config.web.preferences.debug = 0 // debug level - 0 means disabled
......@@ -61,7 +61,7 @@ config.web.preferences.debug = 0 // debug level - 0 means disabled
// DO NOT TOUCH these ones
config.version = '0.1-b1'
config.version = '0.2.0'
// A simple function to quickly have
// get and set strings for client events
......@@ -86,13 +86,13 @@ config.events.client.file = _event_get_set('file')
config.events.client.file_newcontent = 'file_newcontent'
config.events.client.status = 'status'
// packages status according with JSONLogger.py module
// debomatic status according with JSONLogger.py module
config.status = {}
config.status.package = {}
config.status.package.building = 'building'
config.status.package.failed = 'build-failed'
config.status.package.successed = 'build-successed'
config.status.build = 'build'
config.status.create = 'create'
config.status.update = 'update'
config.status.success = true
config.status.fail = false
// read user configuration and merge it
/*
......
// function to get all files in on click
// event comes from HTML
function download_all (div_id) {
frame_id = 'downloadAllFrame'
if ($("#" + frame_id).length > 0)
frame = $($("#" + frame_id)[0])
else {
frame = $('<iframe></iframe>')
frame.hide()
frame.attr('id', frame_id)
$('body').append(frame)
}
files = $(div_id).find('ul li a')
$.each(files, function(index, item) {
setTimeout(function() {
frame.attr('src', item.href)
}, index * 1000)
})
}
function Page_Distrubion(socket)
{
......@@ -16,6 +36,7 @@ function Page_Distrubion(socket)
view.package.version
view.package.orig_name
view.package.status
view.package.success
view.package.files = [file]
view.package.debs = [file]
view.package.sources = [file]
......@@ -34,7 +55,8 @@ function Page_Distrubion(socket)
status_data = {}
status_data.distribution --- the distribution name
status_data.package --- the package name as name_version
status_data.status --- one of config.status.*.*
status_data.status --- one of config.status.[build|create|update]
status_data.success --- true | false
*/
......@@ -112,7 +134,7 @@ function Page_Distrubion(socket)
$('#packages ul').append('<li class="text-muted">No packages yet</li>')
}
packages.show()
sticky.reset()
sticky.updateOffset()
},
clean: function () {
$('#packages ul').html('')
......@@ -139,7 +161,11 @@ function Page_Distrubion(socket)
if ( view.distribution.name == status_data.distribution
&& view.packages[status_data.package] )
{
view.packages[status_data.package].status = Utils.clone(status_data.status)
view.packages[status_data.package].status = status_data.status
if (status_data.hasOwnProperty('success'))
view.packages[status_data.package].success = status_data.success
else
delete(view.packages[status_data.package].success)
}
// and in html
var p_html = $("#packages li[id='package-"+ status_data.package + "'] a")
......@@ -150,7 +176,7 @@ function Page_Distrubion(socket)
&& view.distribution.name == status_data.distribution)
{
// in case user is watching this package, update also view.package
view.package.status = Utils.clone(status_data.status)
view.package = Utils.clone(view.packages[status_data.package])
}
},
show: function() {
......@@ -201,7 +227,7 @@ function Page_Distrubion(socket)
$('#sources').show()
}
files.show()
sticky.reset()
sticky.updateOffset()
},
clean: function() {
$('#logs ul').html('');
......@@ -310,20 +336,21 @@ function Page_Distrubion(socket)
sticky.show()
} else {
sticky.hide()
sticky.updateOffset()
}
},
start: function() {
$(window).scroll(sticky.init)
},
stop: function() {
$(window).off("scroll")
},
reset: function() {
sticky.stop()
sticky.update()
sticky.init()
sticky.start()
},
stop: function() {
$(window).off("scroll")
},
show: function() {
if (config.preferences.sidebar) {
$("#sticky").addClass('fixed')
......@@ -336,8 +363,7 @@ function Page_Distrubion(socket)
$("#sticky-package").fadeOut(150)
},
update: function() {
var sidebar = $("#files")
sidebarOffset = sidebar.offset().top
sticky.updateOffset()
if (Utils.check_view_distribution(view))
$("#sticky-package .distribution").html(view.distribution.name)
if (Utils.check_view_package(view)) {
......@@ -346,12 +372,18 @@ function Page_Distrubion(socket)
sticky.set_status()
}
},
updateOffset: function() {
var sidebar = $("#files")
sidebarOffset = sidebar.offset().top
},
set_status: function(status_data) {
if (! status_data) {
status_data = {}
status_data.distribution = view.distribution.name
status_data.package = view.package.orig_name
status_data.status = view.package.status
if (view.package.hasOwnProperty('success'))
status_data.success = view.package.success
}
if ( Utils.check_view_package(view)
&& status_data.distribution == view.distribution.name
......@@ -472,21 +504,16 @@ function Page_Distrubion(socket)
populate()
return
}
else if ( ! Utils.check_view_package(old_view)
|| ! Utils.check_view_package(view)
|| view.package.orig_name != old_view.package.orig_name
)
else if ( ! Utils.check_view_package(old_view) ||
! Utils.check_view_package(view) ||
view.package.orig_name != old_view.package.orig_name )
{ // new package view
// set status from packages
if (view.packages[view.package.orig_name])
view.package.status = view.packages[view.package.orig_name].status
files.get()
file.get()
}
else if ( ! Utils.check_view_file(old_view)
|| ! Utils.check_view_file(view)
|| view.file.name != old_view.file.name
)
else if ( ! Utils.check_view_file(old_view) ||
! Utils.check_view_file(view) ||
view.file.name != old_view.file.name )
{ // new file view
file.get()
}
......@@ -560,12 +587,12 @@ function Page_Distrubion(socket)
// reset current view
view.distribution = Utils.clone(new_view.distribution)
view.package = Utils.clone(new_view.package)
if (view.packages[view.package.orig_name])
view.package.status = view.packages[view.package.orig_name].status
if (view.packages[new_view.package.orig_name])
view.package = Utils.clone(view.packages[new_view.package.orig_name])
view.file = Utils.clone(new_view.file)
update.page(old_view)
$('html,body').animate({scrollTop: 0}, 0);
debug(1, "changing view", "old:", old_view, "new:", new_view)
debug(1, "changing view", "old:", old_view, "new:", view)
});
if (! __check_hash_makes_sense())
......
......@@ -2,20 +2,49 @@ function Page_Generic()
{
var _e = config.events
function __get_status_html(status_package) {
var s = status_package
function __get_status_html_id(status_data) {
var result = 'status-' + status_data.status + '-' + status_data.distribution
if (status_data.hasOwnProperty('package'))
result += '-' + status_data.package
return result
}
function __get_status_html_href(status_data) {
result = config.paths.distribution + '#' + status_data.distribution
if (status_data.hasOwnProperty('package'))
result += '/' + status_data.package.replace('_', '/') + '/datestamp'
return result
}
function __get_status_html_title(status_data) {
result = status_data.status + ': ' + status_data.distribution
if (status_data.hasOwnProperty('package'))
result += ' > ' + status_data.package
if (status_data.hasOwnProperty('uploader') && status_data.uploader.length > 0)
result += ' by ' + status_data.uploader
return result
}
function __get_status_html_inner(status_data) {
if (status_data.hasOwnProperty('package'))
return status_data.package;
return status_data.distribution
}
function __get_status_html(status_data) {
var _s = status_data
var li = $('<li></li>')
li.attr('id', 'status-' + s.distribution + "-" + s.package)
li.attr('id', __get_status_html_id(status_data))
var button = $('<a></a>')
button.addClass('btn btn-xs')
button.addClass(s.status)
button.attr('title', s.status + ': ' + s.distribution + ' > ' + s.package)
button.attr('href', config.paths.distribution + '#' + s.distribution + '/' + s.package.replace('_', '/') + '/datestamp')
button.html(s.package.split('_')[0])
var info = Utils.get_status_icon_and_class(s)
button.addClass(_s.status)
button.attr('title', __get_status_html_title(_s))
button.attr('href', __get_status_html_href(_s))
button.html(__get_status_html_inner(_s))
var info = Utils.get_status_icon_and_class(_s)
button.addClass('btn-' + info.className)
// add icon
button.html(button.html() + ' ' + Utils.get_status_icon_html(s))
button.html(button.html() + ' ' + Utils.get_status_icon_html(_s))
li.html(button)
var result = $('<div></div>')
result.html(li)
......@@ -45,36 +74,37 @@ function Page_Generic()
var status = {
set: function(data_status) {
$("#status ul").html('')
if (data_status.packages.length > 0) {
data_status.packages.forEach(function(p){
status.append(p)
if (data_status.length > 0) {
data_status.forEach(function(s){
status.append(s)
})
}
},
append: function(status_package) {
append: function(status_data) {
$('#status .idle').hide()
$("#status ul").append(__get_status_html(status_package))
$("#status ul").append(__get_status_html(status_data))
},
update: function(status_package) {
update: function(status_data) {
var li = $("#status li[id='status-" + status_package.distribution + "-" + status_package.package + "']")
var li = $("#status li[id='" + __get_status_html_id(status_data) + "']")
if (li.length > 0
&& status_package.status != config.status.package.building)
&& status_data.hasOwnProperty('success'))
{
// Update color and icon
li.html($(__get_status_html(status_package)).children())
li = $(li[0])
li.html($(__get_status_html(status_data)).children())
li.attr('id', '')
// This is a chain to have a fadeOut and correctly
// delete package from list.
// The first timemout fades out the package.
// delete status li from list.
// The first timemout fades out the status element.
setTimeout(function() {
li.children().fadeOut(config.status.delay.fadeOut)
// Then resize packages list.
// Then resize list.
setTimeout(function() {
li.animate({width: 'toggle'})
}, config.status.delay.fadeOut)
// Finally remove package html
// and show idle status if necessary.
// Finally remove status html
// and show idle label if necessary.
setTimeout(function() {
li.remove()
if ($('#status li').length == 0)
......@@ -82,8 +112,8 @@ function Page_Generic()
}, config.status.delay.remove + 2000) // more delay on remove html
}, config.status.delay.remove)
}
else if (status_package.status == config.status.package.building) {
status.append(status_package)
else if (!status_data.hasOwnProperty('success')) {
status.append(status_data)
}
},
}
......@@ -99,6 +129,7 @@ function Page_Generic()
}
if (config.preferences.glossy_theme) {
if ($("head").find("link[href='/external_libs/bootstrap-3.1.1-dist/css/bootstrap-theme.min.css']").length == 0)
$("head").append('<link rel="stylesheet" href="/external_libs/bootstrap-3.1.1-dist/css/bootstrap-theme.min.css">')
}
else {
......@@ -121,9 +152,9 @@ function Page_Generic()
distributions.set(socket_distributions)
});
socket.on(_e.client.status, function(packages_status) {
debug_socket("received", _e.client.status, packages_status)
status.set(packages_status)
socket.on(_e.client.status, function(socket_status) {
debug_socket("received", _e.client.status, socket_status)
status.set(socket_status)
})
socket.on(_e.broadcast.status_update, function(package_status) {
......
......@@ -56,17 +56,19 @@ var Utils = {
var _s = status_data
var className = null
var icon = null
if (_s.status == config.status.package.building) {
className = _c.building
icon = _i.building
if (_s.hasOwnProperty('success')) {
if (_s.success == true) {
className = _c.success
icon = _i.success
}
else {
className = _c.fail
icon = _i.fail
}
else if (_s.status == config.status.package.failed) {
className = _c.failed
icon = _i.failed
}
else {
className = _c.successed
icon = _i.successed
className = _c[_s.status]
icon = _i[_s.status]
}
return {
className: className,
......
......@@ -28,7 +28,11 @@
<ul></ul>
</nav>
<nav id="debs">
<h4>Debs</h4>
<h4>Debs
<a class="btn btn-link" title="Get all debs in one click" onclick="download_all('#debs')">
<span class="glyphicon glyphicon-download-alt"></span>
</a>
</h4>
<ul></ul>
</nav>
</div>
......
......@@ -10,7 +10,7 @@
</div>
</footer>
<script src='/socket.io/socket.io.js'></script>
<script src='/socket.io/socket.io.js?<%= version %>'></script>
<script src='/external_libs/jquery/jquery-1.11.0.min.js'></script>
<script src="/external_libs/bootstrap-3.1.1-dist/js/bootstrap.min.js"></script>
......@@ -18,14 +18,18 @@
var config = <%- JSON.stringify(web) %>
config.status.className = {}
config.status.className.building = 'info'
config.status.className.successed = 'success'
config.status.className.failed = 'danger'
config.status.className.build = 'info'
config.status.className.create = 'warning'
config.status.className.update = 'default'
config.status.className.success = 'success'
config.status.className.fail = 'danger'
config.status.icons = {}
config.status.icons.building = 'refresh'
config.status.icons.successed = 'ok'
config.status.icons.failed = 'remove'
config.status.icons.build = 'refresh'
config.status.icons.create = 'asterisk'
config.status.icons.update = 'upload'
config.status.icons.success = 'ok'
config.status.icons.fail = 'remove'
config.status.delay = {}
config.status.delay.remove = 10000
......@@ -33,12 +37,12 @@
</script>
<script src='/javascripts/debug.js'></script>
<script src='/javascripts/utils.js'></script>
<script src='/javascripts/preferences.js'></script>
<script src='/javascripts/page_generic.js'></script>
<script src='/javascripts/page_distribution.js'></script>
<script src='/javascripts/main.js'></script>
<script src='/javascripts/debug.js?<%= version %>'></script>
<script src='/javascripts/utils.js?<%= version %>'></script>
<script src='/javascripts/preferences.js?<%= version %>'></script>
<script src='/javascripts/page_generic.js?<%= version %>'></script>
<script src='/javascripts/page_distribution.js?<%= version %>'></script>
<script src='/javascripts/main.js?<%= version %>'></script>
</body>
</html>
......@@ -5,7 +5,8 @@
<title><%= web.title %></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/external_libs/bootstrap-3.1.1-dist/css/bootstrap.min.css">
<link rel="stylesheet" href="/stylesheets/style.css">
<link rel="stylesheet" href="/external_libs/bootstrap-3.1.1-dist/css/bootstrap-theme.min.css">
<link rel="stylesheet" href="/stylesheets/style.css?<%= version %>">
</head>
<body>
......
#!/bin/bash
if [ $# == 0 ] ; then
echo "Please specify a version number."
exit
fi
VERSION=$1
BASE_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )/.."
CONFIG=${BASE_DIR}/debomatic-webui/lib/config.js
CURRENT="`grep "^config.version" ${CONFIG} | awk -F"'" '{print $2}'`"
y='n'
echo -n "Current version is ${CURRENT}. Bump to ${VERSION} ? [y/N] "
read y
if [ "$y" == "y" -o "$y" == "Y" ] ; then
sed -r "s/^config.version = '(.*)'/config.version = '${VERSION}'/" -i $CONFIG || exit 1
y='n'
echo -n "Do git-commit? [y/N] "
read y
if [ "$y" == "y" -o "$y" == "Y" ] ; then
git commit -m "Bumped version ${VERSION}" ${CONFIG}
y='n'
echo -n "Do git-tag? [y/N] "
read y
if [ "$y" == "y" -o "$y" == "Y" ] ; then
git tag -m "Released version ${VERSION}" "v${VERSION}"
fi
fi
fi
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