report version and usage messages

add -h|--help usage messages to laminarc and laminard

add a mechanism to compile in a version number, and display the
version in the help messages and in the frontend.

resolves #119
pull/137/head
Oliver Giles 4 years ago
parent ae560b9de4
commit 09a208ebeb

@ -25,6 +25,19 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
add_definitions("-std=c++17 -Wall -Wextra -Wno-unused-parameter -Wno-sign-compare")
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -Werror -DDEBUG")
# Allow passing in the version string, for e.g. patched/packaged versions
if(NOT LAMINAR_VERSION AND EXISTS ${CMAKE_SOURCE_DIR}/.git)
execute_process(COMMAND git describe --tags --abbrev=8 --dirty
WORKING_DIRECTORY ${CMAKE_SOURCE_DIR}
OUTPUT_VARIABLE LAMINAR_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
endif()
if(NOT LAMINAR_VERSION)
set(LAMINAR_VERSION xx-unversioned)
endif()
set_source_files_properties(src/version.cpp PROPERTIES COMPILE_DEFINITIONS
LAMINAR_VERSION=${LAMINAR_VERSION})
# This macro takes a list of files, gzips them and converts the output into
# object files so they can be linked directly into the application.
# ld generates symbols based on the string argument given to its executable,
@ -93,6 +106,7 @@ set(LAMINARD_CORE_SOURCES
src/rpc.cpp
src/run.cpp
src/server.cpp
src/version.cpp
laminar.capnp.c++
index_html_size.h
)
@ -102,7 +116,7 @@ add_executable(laminard ${LAMINARD_CORE_SOURCES} src/main.cpp ${COMPRESSED_BINS}
target_link_libraries(laminard capnp-rpc capnp kj-http kj-async kj pthread sqlite3 z)
## Client
add_executable(laminarc src/client.cpp laminar.capnp.c++)
add_executable(laminarc src/client.cpp src/version.cpp laminar.capnp.c++)
target_link_libraries(laminarc capnp-rpc capnp kj-async kj pthread)
## Tests

@ -54,7 +54,7 @@ Lightweight Continuous Integration Service
%prep
%build
cmake3 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DSYSTEMD_UNITDIR=%{_unitdir} %{_sourcedir}/laminar-$VERSION
cmake3 -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DLAMINAR_VERSION=$VERSION -DSYSTEMD_UNITDIR=%{_unitdir} %{_sourcedir}/laminar-$VERSION
pwd
make

@ -51,7 +51,7 @@ Lightweight Continuous Integration Service
%prep
%build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DSYSTEMD_UNITDIR=%{_unitdir} %{_sourcedir}/laminar-$VERSION
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DLAMINAR_VERSION=$VERSION -DSYSTEMD_UNITDIR=%{_unitdir} %{_sourcedir}/laminar-$VERSION
pwd
make

@ -17,7 +17,7 @@ docker run --rm -i -v $SOURCE_DIR:/laminar:ro -v $OUTPUT_DIR:/output $DOCKER_TAG
mkdir /build
cd /build
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DZSH_COMPLETIONS_DIR=/usr/share/zsh/functions/Completion/Unix /laminar
cmake -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/usr -DLAMINAR_VERSION=$VERSION -DZSH_COMPLETIONS_DIR=/usr/share/zsh/functions/Completion/Unix /laminar
make -j4
mkdir laminar
make DESTDIR=laminar install/strip

@ -31,6 +31,7 @@ cmake \
-DCMAKE_STRIP=/usr/bin/arm-linux-gnueabihf-strip \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_INSTALL_PREFIX=/usr \
-DLAMINAR_VERSION=$VERSION \
-DZSH_COMPLETIONS_DIR=/usr/share/zsh/functions/Completion/Unix \
/laminar
make -j4

@ -17,10 +17,12 @@
/// along with Laminar. If not, see <http://www.gnu.org/licenses/>
///
#include "laminar.capnp.h"
#include "log.h"
#include <capnp/ez-rpc.h>
#include <kj/vector.h>
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
@ -77,11 +79,35 @@ static void printTriggerLink(const char* job, uint run) {
printf("\033[{%s:%d\033\\\n", job, run);
}
static void usage(std::ostream& out) {
out << "laminarc version " << laminar_version() << "\n";
out << "Usage: laminarc [-h|--help] COMMAND [PARAMETERS...]]\n";
out << " -h|--help show this help message\n";
out << "where COMMAND is:\n";
out << " queue JOB_LIST... queues one or more jobs for execution and returns immediately.\n";
out << " start JOB_LIST... queues one or more jobs for execution and blocks until it starts.\n";
out << " run JOB_LIST... queues one or more jobs for execution and blocks until it finishes.\n";
out << " set PARAMETER_LIST... sets the given parameters as environment variables in the currently\n";
out << " runing job. Fails if run outside of a job context.\n";
out << " abort NAME NUMBER aborts the run identified by NAME and NUMBER.\n";
out << " show-jobs lists all known jobs.\n";
out << " show-queued lists currently queued jobs.\n";
out << " show-running lists currently running jobs.\n";
out << "JOB_LIST is of the form:\n";
out << " [JOB_NAME [PARAMETER_LIST...]]...\n";
out << "PARAMETER_LIST is of the form:\n";
out << " [KEY=VALUE]...\n";
out << "Example:\n";
out << " laminarc start \\\n";
out << " nightly-build branch=master type=release \\\n";
out << " nightly-build branch=master type=debug\n";
}
int main(int argc, char** argv) {
if(argc < 2) {
fprintf(stderr, "Usage: %s <command> [parameters...]\n", argv[0]);
return EXIT_BAD_ARGUMENT;
}
if(argc < 2)
return usage(std::cerr), EXIT_BAD_ARGUMENT;
else if(strcmp("-h", argv[1]) == 0 || strcmp("--help", argv[1]) == 0)
return usage(std::cout), EXIT_SUCCESS;
struct: public kj::TaskSet::ErrorHandler {
void taskFailed(kj::Exception&& e) override {

@ -227,6 +227,7 @@ std::string Laminar::getStatus(MonitorScope scope) {
Json j;
j.set("type", "status");
j.set("title", getenv("LAMINAR_TITLE") ?: "Laminar");
j.set("version", laminar_version());
j.set("time", time(nullptr));
j.startObject("data");
if(scope.type == MonitorScope::RUN) {

@ -1,5 +1,5 @@
///
/// Copyright 2015-2019 Oliver Giles
/// Copyright 2015-2020 Oliver Giles
///
/// This file is part of Laminar
///
@ -67,5 +67,7 @@ namespace _ {
for (::kj::_::Debug::Fault f(__FILE_BASE__, __LINE__, \
_kjSyscallResult.getErrorNumber(), #call, #__VA_ARGS__, ##__VA_ARGS__);; f.fatal())
const char* laminar_version();
#endif // LAMINAR_LOG_H_

@ -20,7 +20,9 @@
#include "leader.h"
#include "server.h"
#include "log.h"
#include <fcntl.h>
#include <iostream>
#include <kj/async-unix.h>
#include <kj/filesystem.h>
#include <signal.h>
@ -44,6 +46,13 @@ constexpr const char* INTADDR_HTTP_DEFAULT = "*:8080";
constexpr const char* ARCHIVE_URL_DEFAULT = "/archive/";
}
static void usage(std::ostream& out) {
out << "laminard version " << laminar_version() << "\n";
out << "Usage:\n";
out << " -h|--help show this help message\n";
out << " -v enable verbose output\n";
}
int main(int argc, char** argv) {
if(argv[0][0] == '{')
return leader_main();
@ -51,6 +60,11 @@ int main(int argc, char** argv) {
for(int i = 1; i < argc; ++i) {
if(strcmp(argv[i], "-v") == 0) {
kj::_::Debug::setLogLevel(kj::_::Debug::Severity::INFO);
} else if(strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "--help") == 0) {
return usage(std::cout), EXIT_SUCCESS;
} else {
std::cerr << "Unknown argument " << argv[i] << "\n";
return usage(std::cerr), EXIT_FAILURE;
}
}
@ -79,6 +93,8 @@ int main(int argc, char** argv) {
signal(SIGINT, &laminar_quit);
signal(SIGTERM, &laminar_quit);
printf("laminard version %s started\n", laminar_version());
server->start();
delete laminar;

@ -177,7 +177,7 @@
</div></template>
<main id="app" style="display: grid; grid-template-rows: auto 1fr auto; height: 100%;">
<nav id="nav-top" style="display: grid; grid-template-columns: auto auto 1fr auto; grid-gap: 15px;">
<nav id="nav-top" style="display: grid; grid-template-columns: auto auto 1fr auto auto; grid-gap: 15px;">
<router-link to="/" style="display: grid; grid-auto-flow: column; align-items: center; margin: 5px; font-size: 20px;">
<img src="icon.png"> {{title}}
</router-link>
@ -186,6 +186,7 @@
<router-link v-for="(crumb,i) in _route.path.slice(1).split('/').slice(1,-1)" :to="_route.path.split('/').slice(0,i+3).join('/')">{{crumb}}</router-link>
</div>
<div></div>
<span class="version">{{version}}</span>
<div style="display: grid; align-items: center; padding: 0 15px">
<a v-on:click="toggleNotifications(!notify)" class="nav-icon" :class="{active:notify}" v-show="supportsNotifications" :title="(notify?'Disable':'Enable')+' notifications'">
<svg width="18" viewBox="0 0 12 12">

@ -50,6 +50,7 @@ const ServerEventHandler = function() {
comp.esReconnectInterval = 500;
// Update html and nav titles
document.title = comp.$root.title = msg.title;
comp.$root.version = msg.version;
// Calculate clock offset (used by ProgressUpdater)
comp.$root.clockSkew = msg.time - Math.floor((new Date()).getTime()/1000);
comp.$root.connected = true;
@ -726,6 +727,7 @@ new Vue({
el: '#app',
data: {
title: '', // populated by status ws message
version: '',
clockSkew: 0,
connected: false,
notify: 'localStorage' in window && localStorage.getItem('showNotifications') == 1

@ -40,6 +40,12 @@ body {
#nav-top a { color: var(--nav-fg); }
#nav-top a:hover { color: white; text-decoration: none; }
.version {
align-self: center;
font-size: x-small;
color: rgba(255,255,255,0.3);
}
/* navbar svg icons (enable notifications) */
.nav-icon { display: inherit; }
.nav-icon svg { fill: var(--nav-fg); stroke: #000; }

@ -0,0 +1,25 @@
///
/// Copyright 2020 Oliver Giles
///
/// This file is part of Laminar
///
/// Laminar 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.
///
/// Laminar 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 Laminar. If not, see <http://www.gnu.org/licenses/>
///
#define str(x) #x
#define xstr(x) str(x)
const char* laminar_version() {
return xstr(LAMINAR_VERSION);
}
Loading…
Cancel
Save