Web interface to view logs

This commit is contained in:
Juan 2018-05-02 08:32:19 +02:00
parent c9f6b0a678
commit aee9face99
14 changed files with 212 additions and 32 deletions

2
debian/changelog vendored
View File

@ -1,4 +1,4 @@
vn-repo (2.0.20) stable; urgency=low
vn-repo (2.0.21) stable; urgency=low
* Initial Release.

2
debian/control vendored
View File

@ -10,7 +10,7 @@ Vcs-Git: https://git.verdnatura.es/vn-repo
Package: vn-repo
Architecture: all
Depends: reprepro, git, sudo, devscripts
Suggests: apache2 | httpd, git, gitweb, gitweb-theme, nodejs
Suggests: apache2 | httpd, git, gitweb, gitweb-theme, nodejs, vn-host
Section: vcs
Priority: optional
Description: Helper to set up a repository

3
debian/install vendored
View File

@ -1,5 +1,6 @@
vn-repo.conf etc/apache2/conf-available
git-hooks/post-receive usr/bin
git-hooks usr/share/vn-repo
web usr/share/vn-repo
vn-branch usr/bin
vn-deploy usr/bin
vn-debuild usr/bin

2
debian/postrm vendored
View File

@ -3,7 +3,7 @@ set -e
# Removes the repository user
# FIXME: This package cannot upgrade itself because user is logged in
# FIXME: This package cannot deploy itself because user is logged in
#userdel vn-repo
# Enables Apache configuration

2
deploy
View File

@ -2,4 +2,4 @@
set -e
vn-debuild
vn-deploy www1.static www2.static
vn-deploy root@www1.static root@www2.static

View File

@ -3,8 +3,7 @@ set -e
while read oldrev newrev ref
do
if [[ ! $ref =~ .*/master$ ]]
then
if [[ ! $ref =~ .*/master$ ]]; then
continue
fi

View File

@ -8,8 +8,10 @@ fi
projectName=$1
repoDir="/var/lib/git/$projectName"
srcDir="/tmp/vn-repo/$projectName/src"
logFile="/var/cache/reprepro/logs/$projectName.out"
logDir="$HOME/logs"
logFile="$logDir/$projectName.out"
mkdir -p "$logDir"
rm -f "$logFile"
echo -e "\n# Deploying started\n" >> "$logFile"
@ -21,8 +23,7 @@ echo " * Host: $(hostname)" >> "$logFile"
mkdir -p "$srcDir"
git --work-tree="$srcDir" --git-dir="$repoDir" checkout -f
if [ -f "$srcDir/deploy" ]
then
if [ -f "$srcDir/deploy" ]; then
(cd "$srcDir" && "$srcDir/deploy" >> "$logFile" 2>&1)
fi

View File

@ -11,14 +11,12 @@ buildDir="$srcDir/.."
repreproDir="/var/cache/reprepro"
codename="stable"
if [ -f "$srcDir/package.json" ]
then
if [ -f "$srcDir/package.json" ]; then
echo -e "\n# Installing Node dependencies\n"
(cd "$srcDir" && npm --silent install)
fi
if [ -f "$srcDir/debian/changelog" ]
then
if [ -f "$srcDir/debian/changelog" ]; then
echo -e "\n# Cleaning last build\n"
rm -f $buildDir/*.deb
rm -f $buildDir/*.changes
@ -31,10 +29,8 @@ then
echo -e "\n# Adding packages to repository\n"
cut -d" " -f1 "$srcDir/debian/files" |
while read debFile
do
if [[ ! "$debFile" =~ .*\.deb$ ]]
then
while read debFile; do
if [[ ! "$debFile" =~ .*\.deb$ ]]; then
continue
fi

View File

@ -3,22 +3,19 @@ set -e
hosts="$@"
if [ -z "$hosts" ]
then
echo "Usage: $(basename $0) host1 [host2]..."
if [ -z "$hosts" ]; then
echo "Usage: $(basename $0) [user1@]host1 [[user2@]host2]..."
exit 1
fi
packages=""
while read -r line
do
while read -r line; do
packageName=$(echo $line | cut -d"_" -f1)
packages="$packages $packageName"
done < "$PWD/debian/files"
if [ -z "$packages" ]
then
if [ -z "$packages" ]; then
echo "No packages found to install."
exit 1
fi
@ -27,8 +24,7 @@ fi
echo -e "\n# Upgrading servers\n"
for host in $hosts
do
for host in $hosts; do
echo " * Upgrading $host"
ssh root@$host "update-repo vn && apt-get install $packages"
ssh $host "update-repo vn && apt-get --quiet --yes install $packages"
done

View File

@ -6,10 +6,8 @@ changesFile="/tmp/vn-repo.changes"
(
flock -n 200 || exit
if [ -f "$changesFile" ]
then
while read -r line
do
if [ -f "$changesFile" ]; then
while read -r line; do
projectName=$(echo $line | cut -d" " -f1)
branch=$(echo $line | cut -d" " -f2)

View File

@ -1,4 +1,5 @@
#Alias /apt /var/cache/reprepro/
#Alias /repo /var/cache/vn-repo/web/
<Directory /var/cache/reprepro/>
Options Indexes
@ -6,3 +7,10 @@
AllowOverride None
Require all granted
</Directory>
<Directory /var/cache/vn-repo/web>
Options Indexes
Options +FollowSymLinks
AllowOverride None
Require all granted
</Directory>

30
web/index.html Normal file
View File

@ -0,0 +1,30 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1.0, user-scalable=no"/>
<meta name="mobile-web-app-capable" content="yes"/>
<meta name="content-language" content="en"/>
<link rel="stylesheet" href="style.css"/>
<title>Deployment logs - Verdnatura</title>
</head>
<body>
<div id="top">
<h1>Deployment logs</h1>
<div id="form">
<label>
Project
<select id="project" onchange="refresh(true)">
<option disabled selected>Select project</option>
</select>
</label>
<label class="checkbox clickable">
<input id="autorefresh" type="checkbox" onclick="refresh()" checked/>Autorefresh
</label>
<button onclick="refresh()">Refresh</button>
</div>
</div>
<pre></pre>
<script type="text/javascript" src="main.js"></script>
</body>
</html>

59
web/main.js Normal file
View File

@ -0,0 +1,59 @@
let logsPath = '/logs';
window.onload = () => {
let select = $('select');
let parser = new DOMParser();
let request = new XMLHttpRequest();
request.open('GET', logsPath);
request.onreadystatechange = () => {
if (request.readyState !== 4 || request.status !== 200) return;
let htmlDoc = parser.parseFromString(request.responseText, 'text/html');
let links = htmlDoc.querySelectorAll('td > a');
for (let link of links) {
let matches = /^(.+)?\.out$/.exec(link.getAttribute('href'));
if (matches) {
let option = document.createElement('option');
option.value = matches[0];
option.appendChild(document.createTextNode(matches[1]));
select.appendChild(option);
}
}
refresh();
};
request.send();
refresh();
setInterval(() => {
if ($('#autorefresh').checked)
refresh();
}, 5000);
};
function refresh(doScroll) {
if (!$('select').value) {
$('pre').textContent = '';
return;
}
let request = new XMLHttpRequest();
request.onreadystatechange = () => {
if (request.readyState !== 4 || request.status !== 200) return;
if ($('pre').textContent === request.responseText) return;
doScroll = doScroll || window.pageYOffset + window.innerHeight >= document.body.scrollHeight;
$('pre').textContent = request.responseText;
if (doScroll)
window.scrollTo(0, document.body.scrollHeight);
};
request.open('GET', `${logsPath}/${$('select').value}`);
request.send();
}
function $(selector) {
return document.querySelector(selector);
}

92
web/style.css Normal file
View File

@ -0,0 +1,92 @@
body {
margin: 0;
font-family: sans-serif;
color: #333;
font-size: 12pt;
overflow: auto;
}
#top {
position: fixed;
top: 0;
left: 0;
width: 100%;
background-color: white;
box-shadow: 0 .1em .4em rgba(0, 0, 0, .4);
}
h1 {
background-color: #3f51b5;
color: white;
font-size: 1.3em;
padding: .7em;
margin: 0;
font-weight: normal;
}
#form {
padding: 1em;
}
label {
display: block;
color: #666;
font-size: .9em;
margin-bottom: .8em;
}
select {
width: 100%;
display: block;
margin: auto;
box-sizing: border-box;
border: none;
border-bottom: 1px solid gray;
height: 2em;
background: none;
color: #333;
}
select,
.clickable {
transition: background-color 250ms ease-in-out;
}
select:hover,
.clickable:hover {
background-color: rgba(0, 0, 0, .05);
cursor: pointer;
}
option {
cursor: pointer;
background-color: rgba(0, 0, 0, .05);
}
input[type=checkbox] {
vertical-align: middle;
margin: 0;
margin-right: .5em;
}
.checkbox {
padding: .2em 0;
}
button {
box-sizing: border-box;
width: 100%;
border: none;
background: none;
cursor: pointer;
text-transform: uppercase;
font-weight: bold;
padding: .4em;
background-color: #f44336;
color: white;
border-radius: .1em;
transition: opacity 250ms ease-in-out;
}
button:hover {
opacity: .85;
cursor: pointer;
}
pre {
display: block;
width: 100%;
margin: auto;
border: none;
box-sizing: border-box;
padding: 1em;
padding-top: 16em;
font-size: .9em;
}