revamp config/installation

Signed-off-by: Tiago Garcia <tiago.rgarcia@ua.pt>
This commit is contained in:
Tiago Garcia 2026-03-10 22:12:40 +00:00
parent 6688a89cb7
commit cb471e4f16
Signed by: TiagoRG
GPG Key ID: DFCD48E3F420DB42
12 changed files with 208 additions and 203 deletions

View File

@ -47,30 +47,32 @@ target_link_libraries(${EXECUTABLE_NAME} PUBLIC ncurses dialog)
# "-static -static-libgcc -static-libstdc++")
# Install the executable
set(SERVICE_EXECUTABLE "/services/gh-wh-handler/${EXECUTABLE_NAME}")
set(SERVICE_CONFIG "/services/gh-wh-handler/config.json")
set(SERVICE_LOGS "/services/gh-wh-handler/logs")
set(SERVICE_EXECUTABLE "/usr/bin/${EXECUTABLE_NAME}")
set(SERVICE_CONFIG "/etc/gh-wh-handler/config.json")
set(SERVICE_LOGS "/var/log/gh-wh-handler")
configure_file(
"${CMAKE_CURRENT_BINARY_DIR}/gh-wh-handler.service.in"
"${CMAKE_CURRENT_BINARY_DIR}/gh-wh-handler.service"
@ONLY)
install(CODE "file(MAKE_DIRECTORY /services/gh-wh-handler)")
install(CODE "file(MAKE_DIRECTORY /services/gh-wh-handler/logs)")
install(TARGETS ${EXECUTABLE_NAME} DESTINATION /services/gh-wh-handler)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/config.json"
DESTINATION /services/gh-wh-handler)
install(CODE "file(MAKE_DIRECTORY /etc/gh-wh-handler)")
install(CODE "file(MAKE_DIRECTORY /var/log/gh-wh-handler)")
install(TARGETS ${EXECUTABLE_NAME} DESTINATION /usr/bin)
install(CODE "execute_process(COMMAND ${CMAKE_COMMAND} -E create_symlink
/services/gh-wh-handler/${EXECUTABLE_NAME} /usr/bin/gh-wh-handler)")
/usr/bin/${EXECUTABLE_NAME} /usr/bin/gh-wh-handler)")
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/config.json"
DESTINATION /etc/gh-wh-handler)
install(FILES "${CMAKE_CURRENT_BINARY_DIR}/gh-wh-handler.service"
DESTINATION /etc/systemd/system)
install(CODE "execute_process(COMMAND systemctl daemon-reload)")
install(CODE "execute_process(COMMAND systemctl enable gh-wh-handler)")
install(CODE "execute_process(COMMAND systemctl start gh-wh-handler)")
if(NOT TARGET uninstall)
configure_file(
"${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake.in"
"${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake" IMMEDIATE @ONLY)
add_custom_target(uninstall COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake)
add_custom_target(uninstall
COMMAND ${CMAKE_COMMAND} -P ${CMAKE_CURRENT_BINARY_DIR}/uninstall.cmake
USES_TERMINAL
)
endif()

View File

@ -1,22 +1,68 @@
message(STATUS "[0%] Stopping systemd service...")
execute_process(COMMAND systemctl stop gh-wh-handler)
function(ask_user_permission PROMPT_TEXT RESULT_VAR)
execute_process(COMMAND printf "${PROMPT_TEXT} [Y/n]: ")
message(STATUS "[15%] Disabling systemd service...")
execute_process(COMMAND systemctl disable gh-wh-handler)
execute_process(
COMMAND bash -c "read -n 1 -s -r; echo \"$REPLY\""
OUTPUT_VARIABLE USER_INPUT
OUTPUT_STRIP_TRAILING_WHITESPACE
)
message(STATUS "[30%] Removing service configuration file from systemd directory...")
file(REMOVE /etc/systemd/system/gh-wh-handler.service)
string(TOLOWER "${USER_INPUT}" INPUT_LOWER)
message(STATUS "[45%] Reloading systemd daemon...")
if("${INPUT_LOWER}" STREQUAL "y" OR "${INPUT_LOWER}" STREQUAL "")
set(${RESULT_VAR} TRUE PARENT_SCOPE)
execute_process(COMMAND echo "Y")
else()
set(${RESULT_VAR} FALSE PARENT_SCOPE)
execute_process(COMMAND echo "n")
endif()
endfunction()
if(NOT DEFINED CMAKE_SCRIPT_MODE_FILE)
message(FATAL_ERROR "This script should be run via: cmake -P uninstall.cmake")
endif()
execute_process(
COMMAND id -u
OUTPUT_VARIABLE USER_ID
OUTPUT_STRIP_TRAILING_WHITESPACE
)
if(NOT USER_ID EQUAL 0)
message(FATAL_ERROR "This script must be run as root (UID 0). Current UID: ${USER_ID}")
endif()
execute_process(COMMAND uname -m OUTPUT_VARIABLE ARCH OUTPUT_STRIP_TRAILING_WHITESPACE)
message(STATUS "Uninstalling gh-wh-handler [${ARCH}]...")
message(STATUS "Stopping and disabling service...")
execute_process(COMMAND systemctl stop gh-wh-handler ERROR_QUIET)
execute_process(COMMAND systemctl disable gh-wh-handler ERROR_QUIET)
message(STATUS "Removing service file...")
file(REMOVE "/etc/systemd/system/gh-wh-handler.service")
message(STATUS "Reloading systemd...")
execute_process(COMMAND systemctl daemon-reload)
message(STATUS "[55%] Removing symlink to service executable...")
execute_process(COMMAND rm /usr/bin/gh-wh-handler)
message(STATUS "Removing binaries...")
file(REMOVE "/usr/bin/gh-wh-handler")
file(REMOVE "/usr/bin/gh-wh-handler.${ARCH}")
message(STATUS "[70%] Removing service executable from service directory...")
file(REMOVE /services/gh-wh-handler/@EXECUTABLE_NAME@)
ask_user_permission("Do you want to remove the configuration file?" REMOVE_CONFIG)
if(REMOVE_CONFIG)
message(STATUS "Removing /etc/gh-wh-handler...")
file(REMOVE_RECURSE "/etc/gh-wh-handler")
else()
message(STATUS "Skipping configuration removal.")
endif()
message(STATUS "[85%] Removing all log files...")
execute_process(COMMAND rm -fr /services/gh-wh-handler/logs)
ask_user_permission("Do you want to remove the logs?" REMOVE_LOGS)
if(REMOVE_LOGS)
message(STATUS "Removing /var/log/gh-wh-handler...")
file(REMOVE_RECURSE "/var/log/gh-wh-handler")
else()
message(STATUS "Skipping log removal.")
endif()
message(STATUS "[100%] Uninstallation complete!")
message(STATUS "Uninstallation complete.")

View File

@ -5,7 +5,14 @@
class DialogMenu {
public:
static void open_menu(nlohmann::json config, std::string config_file_path);
static void open_menu(nlohmann::json config, std::string config_file_path, std::string default_editor);
private:
static void open_main_menu();
static nlohmann::json s_config;
static std::string s_config_path;
static std::string s_editor;
};
#endif

View File

@ -1,16 +0,0 @@
#ifndef TERMINAL_MENU_HPP
#define TERMINAL_MENU_HPP
#include <nlohmann/json.hpp>
class TerminalMenu {
public:
static void open_menu(nlohmann::json config, std::string config_file_path);
private:
static void general_menu(nlohmann::json config, std::string config_file_path);
static void update_files_menu(nlohmann::json config, std::string config_file_path);
static void run_scripts_menu(nlohmann::json config, std::string config_file_path);
};
#endif

View File

@ -13,9 +13,12 @@ class Logger {
static void success(std::string message);
static void code(std::string message);
static void debug(std::string message);
static void enable_config_mode();
private:
static void log(std::string message, std::string level);
static std::ofstream log_file;
static bool is_config_mode;
};
#endif

View File

@ -1,68 +1,49 @@
#!/bin/sh
# Check if the script is being run as root
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root."
echo "Error: This script must be run as root (UID 0). Current UID: $(id -u)"
exit 1
fi
# Save the current directory
CUR_DIR=$(pwd)
# Get system architecture
ARCH=$(uname -m)
# Change to the temporary directory
cd /tmp
# Download the latest version of the package for the system architecture
# Exit if the download fails
echo "Downloading gh-wh-handler..."
curl -fsSL https://cdn.tiagorg.pt/gh-wh-handler/gh-wh-handler.${ARCH}.latest.tar.gz -o gh-wh-handler.tar.gz || { echo "Download failed."; exit 1; }
# Extract the package
echo "Extracting gh-wh-handler..."
tar -xzf gh-wh-handler.tar.gz || { echo "Extraction failed."; exit 1; }
# Change to the extracted directory
cd gh-wh-handler
# Install the package
echo "Installing gh-wh-handler..."
# Create service directory
echo "Creating service directory..."
mkdir -p /services/gh-wh-handler
mkdir -p /services/gh-wh-handler/logs
echo "Creating directories..."
mkdir -p /etc/gh-wh-handler
mkdir -p /var/log/gh-wh-handler
# Copy the binary and configuration file to the service directory
echo "Copying files..."
cp "gh-wh-handler.${ARCH}" /services/gh-wh-handler/
cp "config.json" /services/gh-wh-handler/
cp "gh-wh-handler.${ARCH}" /usr/bin/
ln -s /usr/bin/gh-wh-handler.${ARCH} /usr/bin/gh-wh-handler
cp "config.json" /etc/gh-wh-handler/
# Create a symbolic link to the binary in /usr/bin
echo "Creating symbolic link..."
ln -sf /services/gh-wh-handler/gh-wh-handler.${ARCH} /usr/bin/gh-wh-handler
# Copy the service file to the systemd directory
echo "Copying service file..."
cp "gh-wh-handler.service" /etc/systemd/system/
# Reload systemd
echo "Reloading systemd..."
systemctl daemon-reload
# Enable and start the service
echo "Enabling and starting service..."
systemctl enable gh-wh-handler
systemctl start gh-wh-handler
# Clean up
echo "Cleaning up..."
cd /tmp
rm -rf gh-wh-handler
rm gh-wh-handler.tar.gz
# Change back to the original directory
cd $CUR_DIR
echo "Installation complete."

View File

@ -1,42 +1,54 @@
#!/bin/sh
#!/bin/bash
ask_user_permission() {
local PROMPT_TEXT=$1
printf "${PROMPT_TEXT} [Y/n]: "
read -n 1 -s -r USER_INPUT
if [[ -z "$USER_INPUT" ]] || [[ "$USER_INPUT" =~ ^[Yy]$ ]]; then
echo "Y"
return 0
else
echo "n"
return 1
fi
}
# Check if the script is being run as root
if [ "$(id -u)" -ne 0 ]; then
echo "This script must be run as root."
echo "Error: This script must be run as root (UID 0). Current UID: $(id -u)"
exit 1
fi
# Save the current directory
CUR_DIR=$(pwd)
# Get system architecture
ARCH=$(uname -m)
echo "Uninstalling gh-wh-handler [${ARCH}]..."
echo "Uninstalling gh-wh-handler..."
# Stop and disable the service
echo "Stopping and disabling service..."
systemctl stop gh-wh-handler
systemctl disable gh-wh-handler
systemctl stop gh-wh-handler 2>/dev/null
systemctl disable gh-wh-handler 2>/dev/null
# Remove the service file
echo "Removing service file..."
rm /etc/systemd/system/gh-wh-handler.service
rm -f "/etc/systemd/system/gh-wh-handler.service"
# Reload systemd
echo "Reloading systemd..."
systemctl daemon-reload
# Remove the symbolic link
echo "Removing symbolic link..."
rm /usr/bin/gh-wh-handler
echo "Removing binaries..."
rm -f "/usr/bin/gh-wh-handler"
rm -f "/usr/bin/gh-wh-handler.${ARCH}"
# Remove the logs directory and binary
echo "Removing files..."
rm -rf /services/gh-wh-handler/logs
rm -f /services/gh-wh-handler/gh-wh-handler.${ARCH}
if ask_user_permission "Do you want to remove the configuration file?"; then
echo "Removing /etc/gh-wh-handler..."
rm -rf "/etc/gh-wh-handler"
else
echo "Skipping configuration removal."
fi
if ask_user_permission "Do you want to remove the logs?"; then
echo "Removing /var/log/gh-wh-handler..."
rm -rf "/var/log/gh-wh-handler"
else
echo "Skipping log removal."
fi
# Change back to the original directory
cd $CUR_DIR
echo "Uninstallation complete."

View File

@ -4,7 +4,6 @@
#include <fstream>
#include <unistd.h>
#include "config/terminal-menu.hpp"
#include "config/dialog-menu.hpp"
#include "logger.hpp"
@ -66,18 +65,24 @@ nlohmann::json Config::get_config(std::string config_file_path) {
}
void Config::open_menu(nlohmann::json config, std::string config_file_path) {
Logger::info("[Config] Opening config menu");
std::string menu = "";
if (std::system("which dialog > /dev/null") == 0) {
menu = "dialog";
} else {
menu = "terminal";
Logger::info("[Config] Opening config...");
const char* visual_env = std::getenv("VISUAL");
const char* editor_env = std::getenv("EDITOR");
std::string default_editor = "vi";
if (visual_env) {
Logger::info("[Config] VISUAL environment variable found: " + std::string(visual_env));
default_editor = visual_env;
} else if (editor_env) {
Logger::info("[Config] EDITOR environment variable found: " + std::string(editor_env));
default_editor = editor_env;
}
if (menu == "dialog") {
DialogMenu::open_menu(config, config_file_path);
if (std::system("which dialog > /dev/null") == 0) {
DialogMenu::open_menu(config, config_file_path, default_editor);
} else {
TerminalMenu::open_menu(config, config_file_path);
std::string command = default_editor + " " + config_file_path;
}
}

View File

@ -2,7 +2,58 @@
#include "config/dialog-menu.hpp"
#include "logger.hpp"
void DialogMenu::open_menu(nlohmann::json config, std::string config_file_path) {
nlohmann::json DialogMenu::s_config;
std::string DialogMenu::s_config_path;
std::string DialogMenu::s_editor;
void DialogMenu::open_menu(nlohmann::json config, std::string config_file_path, std::string default_editor) {
Logger::info("Opening dialog menu");
init_dialog(stdin, stdout);
// Define the menu items: { "Tag", "Description" }
const char *items[] = {
"1", "Continue with visual menu",
"2", "Open default editor"
};
int item_count = 2;
// dialog_menu returns 0 on success (Enter), 1 on Cancel/ESC
int result = dialog_menu(
"GitHub Webhook Handler - Config Menu", // Title
"Select an option to proceed:", // Prompt
12, 50, // Height, Width
item_count, // Menu height inside box
item_count, // Number of items
const_cast<char**>(items) // Items array
);
if (result == 0) {
std::string choice = dialog_vars.input_result;
if (choice == "1") {
Logger::info("User chose: Visual Menu");
s_config = config;
s_config_path = config_file_path;
s_editor = default_editor;
open_main_menu();
} else if (choice == "2") {
Logger::info("User chose: Default Editor");
// Logic to launch default_editor with config_file_path
std::string command = default_editor + " " + config_file_path;
system(command.c_str());
}
} else {
Logger::info("User cancelled the menu");
}
end_dialog();
Logger::info("Dialog menu closed");
}
void DialogMenu::open_main_menu() {
Logger::info("Opening dialog menu");
init_dialog(stdin, stdout);
dialog_msgbox(

View File

@ -1,98 +0,0 @@
#include <iostream>
#include <fstream>
#include "config/terminal-menu.hpp"
#include "config/config-api.hpp"
#include "logger.hpp"
void print_menu() {
std::cout << "1. Print menu" << std::endl;
std::cout << "2. Preview current config" << std::endl;
std::cout << "3. Set port" << std::endl;
std::cout << "4. Add token" << std::endl;
std::cout << "5. Remove token" << std::endl;
std::cout << "6. Add run actions repo" << std::endl;
std::cout << "7. Add run actions action" << std::endl;
std::cout << "8. Remove run actions repo" << std::endl;
std::cout << "9. Remove run actions action" << std::endl;
std::cout << "10. Add update files repo" << std::endl;
std::cout << "11. Add update files file" << std::endl;
std::cout << "12. Add update files post-update" << std::endl;
std::cout << "13. Remove update files repo" << std::endl;
std::cout << "14. Remove update files file" << std::endl;
std::cout << "15. Remove update files post-update" << std::endl;
std::cout << "16. Exit and save changes" << std::endl;
std::cout << "17. Exit and discard changes" << std::endl;
}
void TerminalMenu::open_menu(nlohmann::json config, std::string config_file_path) {
Logger::warn("[Config] Config menu (no TUI available, using terminal only)");
print_menu();
while (true) {
std::cout << ">>> ";
int choice;
std::cin >> choice;
switch (choice) {
case 1: {
print_menu();
break;
}
case 2: {
Logger::info("[Config] Current config: ");
Logger::code(config.dump(2));
break;
}
case 3: {
int port;
std::cout << "Enter new port: ";
std::cin >> port;
config = ConfigApi::set_port(config, port);
break;
}
case 4: {
std::string repo, token;
std::cout << "Enter repo name (owner/name): ";
std::cin >> repo;
if (config["tokens"].find(repo) != config["tokens"].end()) {
std::cout << "Token already exists for this repo. Do you want to update it? (y/N): ";
char update;
std::cin >> update;
if (update != 'y') {
break;
}
}
std::cout << "Enter token: ";
std::cin >> token;
config = ConfigApi::add_token(config, repo, token);
break;
}
case 5: {
std::string repo;
std::cout << "Enter repo name (owner/name): ";
std::cin >> repo;
config = ConfigApi::remove_token(config, repo);
break;
}
case 16: {
Logger::info("[Config] Saving changes to config file: " + config_file_path);
Logger::info("[Config] New config: ");
std::ofstream config_file(config_file_path);
Logger::code(config.dump(2));
config_file << config.dump(2);
config_file.close();
return;
}
case 17: {
std::cout << "Exiting without saving changes" << std::endl;
return;
}
default:
std::cout << "Invalid choice" << std::endl;
}
}
}

View File

@ -33,6 +33,7 @@
#define COLORS_BG_WHITE "\033[47m"
std::ofstream Logger::log_file;
bool Logger::is_config_mode = false;
void Logger::init(std::string logs_dir) {
std::cout << "Initializing logger" << std::endl;
@ -62,6 +63,7 @@ void Logger::init(std::string logs_dir) {
if (!Logger::log_file.is_open()) {
std::cerr << "Error opening log file" << std::endl;
}
Logger::success("Logger initialized");
}
@ -137,10 +139,15 @@ void Logger::log(std::string message, std::string level) {
} else {
formatted_message += "[" + level + "] " + message;
}
if (isatty(fileno(stdout))) {
formatted_message += COLORS_RESET;
}
std::cout << formatted_message << std::endl;
if (!Logger::is_config_mode) {
std::cout << formatted_message << std::endl;
}
if (level == "CODE") {
#if defined(__aarch64__)
Logger::log_file << std::endl << message << std::endl;
@ -160,3 +167,7 @@ void Logger::log(std::string message, std::string level) {
std::exit(1);
}
}
void Logger::enable_config_mode() {
Logger::is_config_mode = true;
}

View File

@ -40,6 +40,7 @@ int main(int argc, char **argv) {
nlohmann::json config = Config::get_config(config_file_path);
if (argc == 4 && std::string(argv[3]) == "--config") {
Logger::enable_config_mode();
Config::open_menu(config, config_file_path);
return 0;
}