diff --git a/CMakeLists.txt b/CMakeLists.txt
index ff3b6f2..e2eb1fa 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -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
diff --git a/pkg/centos7-x86_64.sh b/pkg/centos7-x86_64.sh
index b72e6f4..77932c4 100755
--- a/pkg/centos7-x86_64.sh
+++ b/pkg/centos7-x86_64.sh
@@ -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
diff --git a/pkg/centos8-x86_64.sh b/pkg/centos8-x86_64.sh
index a2f41c1..ac1e486 100755
--- a/pkg/centos8-x86_64.sh
+++ b/pkg/centos8-x86_64.sh
@@ -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
diff --git a/pkg/debian10-amd64.sh b/pkg/debian10-amd64.sh
index 127ed36..3d4e41c 100755
--- a/pkg/debian10-amd64.sh
+++ b/pkg/debian10-amd64.sh
@@ -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
diff --git a/pkg/debian10-armhf.sh b/pkg/debian10-armhf.sh
index 6010e3e..eac3063 100755
--- a/pkg/debian10-armhf.sh
+++ b/pkg/debian10-armhf.sh
@@ -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
diff --git a/src/client.cpp b/src/client.cpp
index d803e52..1ea9b8b 100644
--- a/src/client.cpp
+++ b/src/client.cpp
@@ -17,10 +17,12 @@
/// along with Laminar. If not, see
///
#include "laminar.capnp.h"
+#include "log.h"
#include
#include
+#include
#include
#include
#include
@@ -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 [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 {
diff --git a/src/laminar.cpp b/src/laminar.cpp
index 191d1bf..2ac59de 100644
--- a/src/laminar.cpp
+++ b/src/laminar.cpp
@@ -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) {
diff --git a/src/log.h b/src/log.h
index 54020c2..a0ccff4 100644
--- a/src/log.h
+++ b/src/log.h
@@ -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_
diff --git a/src/main.cpp b/src/main.cpp
index 8b37e26..2b47993 100644
--- a/src/main.cpp
+++ b/src/main.cpp
@@ -20,7 +20,9 @@
#include "leader.h"
#include "server.h"
#include "log.h"
+
#include
+#include
#include
#include
#include
@@ -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;
diff --git a/src/resources/index.html b/src/resources/index.html
index f84ebea..cb5a57f 100644
--- a/src/resources/index.html
+++ b/src/resources/index.html
@@ -177,7 +177,7 @@
-