From cb471e4f16b2b553671dc3bc0e423d0aaa5d5a2a Mon Sep 17 00:00:00 2001 From: Tiago Garcia Date: Tue, 10 Mar 2026 22:12:40 +0000 Subject: [PATCH] revamp config/installation Signed-off-by: Tiago Garcia --- CMakeLists.txt | 24 ++++---- build/uninstall.cmake.in | 74 +++++++++++++++++++----- include/config/dialog-menu.hpp | 9 ++- include/config/terminal-menu.hpp | 16 ------ include/logger.hpp | 3 + installer/install.sh | 33 +++-------- installer/uninstall.sh | 62 ++++++++++++-------- src/config.cpp | 25 ++++---- src/config/dialog-menu.cpp | 53 ++++++++++++++++- src/config/terminal-menu.cpp | 98 -------------------------------- src/logger.cpp | 13 ++++- src/main.cpp | 1 + 12 files changed, 208 insertions(+), 203 deletions(-) delete mode 100644 include/config/terminal-menu.hpp delete mode 100644 src/config/terminal-menu.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index b977eae..b329433 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -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() diff --git a/build/uninstall.cmake.in b/build/uninstall.cmake.in index 62ea771..cceec46 100644 --- a/build/uninstall.cmake.in +++ b/build/uninstall.cmake.in @@ -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.") diff --git a/include/config/dialog-menu.hpp b/include/config/dialog-menu.hpp index 0c1b7d7..deeb124 100644 --- a/include/config/dialog-menu.hpp +++ b/include/config/dialog-menu.hpp @@ -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 diff --git a/include/config/terminal-menu.hpp b/include/config/terminal-menu.hpp deleted file mode 100644 index 61b3362..0000000 --- a/include/config/terminal-menu.hpp +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef TERMINAL_MENU_HPP -#define TERMINAL_MENU_HPP - -#include - -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 diff --git a/include/logger.hpp b/include/logger.hpp index 089768e..d09c53d 100644 --- a/include/logger.hpp +++ b/include/logger.hpp @@ -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 diff --git a/installer/install.sh b/installer/install.sh index 4a33148..c07c18b 100755 --- a/installer/install.sh +++ b/installer/install.sh @@ -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." diff --git a/installer/uninstall.sh b/installer/uninstall.sh index a8af099..7f4c0bd 100644 --- a/installer/uninstall.sh +++ b/installer/uninstall.sh @@ -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." - diff --git a/src/config.cpp b/src/config.cpp index ed6d849..dbba6bf 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -4,7 +4,6 @@ #include #include -#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; } } diff --git a/src/config/dialog-menu.cpp b/src/config/dialog-menu.cpp index da92a50..28a09d2 100644 --- a/src/config/dialog-menu.cpp +++ b/src/config/dialog-menu.cpp @@ -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(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( diff --git a/src/config/terminal-menu.cpp b/src/config/terminal-menu.cpp deleted file mode 100644 index d07991b..0000000 --- a/src/config/terminal-menu.cpp +++ /dev/null @@ -1,98 +0,0 @@ -#include -#include -#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; - } - - } -} - diff --git a/src/logger.cpp b/src/logger.cpp index c4d263a..5c3254a 100644 --- a/src/logger.cpp +++ b/src/logger.cpp @@ -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; +} diff --git a/src/main.cpp b/src/main.cpp index df2bcc2..75b6300 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -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; }