Compare commits
5 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
6688a89cb7 | |
|
|
549444fd47 | |
|
|
d5a2353ded | |
|
|
5c8216edd1 | |
|
|
cd769fa8bc |
|
|
@ -24,6 +24,9 @@ set(EXECUTABLE_NAME "gh-wh-handler.${ARCH}")
|
||||||
set(CMAKE_CXX_STANDARD 23)
|
set(CMAKE_CXX_STANDARD 23)
|
||||||
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
set(CMAKE_CXX_STANDARD_REQUIRED True)
|
||||||
|
|
||||||
|
# Set the compiler flags
|
||||||
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Werror -pedantic")
|
||||||
|
|
||||||
# Set the output directory
|
# Set the output directory
|
||||||
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_SOURCE_DIR}/bin)
|
||||||
|
|
||||||
|
|
@ -37,13 +40,11 @@ file(GLOB_RECURSE SOURCES "src/*.cpp")
|
||||||
# Add the executable
|
# Add the executable
|
||||||
add_executable(${EXECUTABLE_NAME} ${SOURCES})
|
add_executable(${EXECUTABLE_NAME} ${SOURCES})
|
||||||
target_include_directories(${EXECUTABLE_NAME} PUBLIC ${INCLUDE_DIR})
|
target_include_directories(${EXECUTABLE_NAME} PUBLIC ${INCLUDE_DIR})
|
||||||
|
target_link_libraries(${EXECUTABLE_NAME} PUBLIC ncurses dialog)
|
||||||
# Add compilation flags
|
|
||||||
target_compile_options(${EXECUTABLE_NAME} PRIVATE -Wall -Werror)
|
|
||||||
|
|
||||||
# Set linker flags for static linking
|
# Set linker flags for static linking
|
||||||
set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS
|
# set_target_properties(${EXECUTABLE_NAME} PROPERTIES LINK_FLAGS
|
||||||
"-static -static-libgcc -static-libstdc++")
|
# "-static -static-libgcc -static-libstdc++")
|
||||||
|
|
||||||
# Install the executable
|
# Install the executable
|
||||||
set(SERVICE_EXECUTABLE "/services/gh-wh-handler/${EXECUTABLE_NAME}")
|
set(SERVICE_EXECUTABLE "/services/gh-wh-handler/${EXECUTABLE_NAME}")
|
||||||
|
|
|
||||||
82
README.md
82
README.md
|
|
@ -108,7 +108,27 @@ Note: Tokens are only required for private repositories.
|
||||||
|
|
||||||
## Endpoints
|
## Endpoints
|
||||||
|
|
||||||
Currently, the only endpoint for the application is `/update-files`, which is used to update the local files on every push as well as run post-update scripts.
|
### `/run-actions`
|
||||||
|
|
||||||
|
#### Webhook event: `push`
|
||||||
|
|
||||||
|
This endpoint allows the application to run specific actions when a push to a specific branch is made. This way, there's no need to manually run the actions on the server.
|
||||||
|
|
||||||
|
The configuration file must contain the `run-actions` field, which is an object with the following format:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"run-actions": {
|
||||||
|
"owner/repo-name": {
|
||||||
|
"branch": "main",
|
||||||
|
"actions": [
|
||||||
|
{
|
||||||
|
"name": "action-name",
|
||||||
|
"command": "command-to-run"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
### `/update-files`
|
### `/update-files`
|
||||||
|
|
||||||
|
|
@ -129,41 +149,45 @@ The configuration file must contain the `update-files` field, which is an object
|
||||||
"...": "..."
|
"...": "..."
|
||||||
},
|
},
|
||||||
"post-update": [
|
"post-update": [
|
||||||
"post-update-command",
|
|
||||||
"post-update-script",
|
|
||||||
"..."
|
|
||||||
]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
### `/run-actions`
|
|
||||||
|
|
||||||
#### Webhook event: `push`
|
|
||||||
|
|
||||||
This endpoint allows the application to run specific actions when a push to a specific branch is made. This way, there's no need to manually run the actions on the server.
|
|
||||||
|
|
||||||
The configuration file must contain the `run-actions` field, which is an object with the following format:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"run-actions": {
|
|
||||||
"owner/repo-name": {
|
|
||||||
"branch": "main",
|
|
||||||
"actions": [
|
|
||||||
{
|
{
|
||||||
"name": "action-name",
|
"name": "post-update-action-name",
|
||||||
"command": "command-to-run",
|
"command": "command-to-run"
|
||||||
"args": [
|
|
||||||
"arg1",
|
|
||||||
"arg2",
|
|
||||||
"..."
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Nginx Configuration
|
||||||
|
|
||||||
|
If you want to use Nginx as a reverse proxy for the application, you can use the following example configuration:
|
||||||
|
|
||||||
|
```nginx
|
||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name services.example.com;
|
||||||
|
|
||||||
|
location /gh-wh-handler {
|
||||||
|
proxy_set_header Host $host;
|
||||||
|
proxy_set_header X-Real-IP $remote_addr;
|
||||||
|
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||||
|
proxy_set_header X-Forwarded-Proto $scheme;
|
||||||
|
add_header Front-End-Https on;
|
||||||
|
|
||||||
|
proxy_headers_hash_max_size 512;
|
||||||
|
proxy_headers_hash_bucket_size 64;
|
||||||
|
|
||||||
|
proxy_buffering off;
|
||||||
|
proxy_redirect off;
|
||||||
|
proxy_max_temp_file_size 0;
|
||||||
|
rewrite /gh-wh-handler/(.*) /$1 break;
|
||||||
|
proxy_pass http://127.0.0.1:65001;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
This way, you will be able to access the application using the URL `http://services.example.com/gh-wh-handler/end-point`.
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
|
This project is licensed under the GNU General Public License v3.0 - see the [LICENSE](LICENSE) file for details.
|
||||||
|
|
|
||||||
|
|
@ -7,24 +7,26 @@ class Config {
|
||||||
public:
|
public:
|
||||||
static void create_config(std::string config_file_path);
|
static void create_config(std::string config_file_path);
|
||||||
static nlohmann::json get_config(std::string config_file_path);
|
static nlohmann::json get_config(std::string config_file_path);
|
||||||
static void open_config_menu();
|
static void open_menu(nlohmann::json config, std::string config_file_path);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static void set_port(int port);
|
static void open_terminal_only_menu(nlohmann::json config, std::string config_file_path);
|
||||||
|
|
||||||
static void add_update_files_repo(std::string repo, std::string branch);
|
static nlohmann::json set_port(nlohmann::json config, int port);
|
||||||
static void add_update_files_file(std::string repo, std::string remote_path, std::string local_path);
|
|
||||||
static void add_update_files_post_update(std::string repo, std::string command);
|
|
||||||
static void add_run_scripts_repo(std::string repo, std::string branch);
|
|
||||||
static void add_run_scripts_script(std::string repo, std::string script_path);
|
|
||||||
static void add_token(std::string repo, std::string token);
|
|
||||||
|
|
||||||
static void remove_update_files_repo(std::string repo);
|
static nlohmann::json add_update_files_repo(nlohmann::json config, std::string repo, std::string branch);
|
||||||
static void remove_update_files_file(std::string repo, std::string remote_path);
|
static nlohmann::json add_update_files_file(nlohmann::json config, std::string repo, std::string remote_path, std::string local_path);
|
||||||
static void remove_update_files_post_update(std::string repo, std::string command);
|
static nlohmann::json add_update_files_post_update(nlohmann::json config, std::string repo, std::string command);
|
||||||
static void remove_run_scripts_repo(std::string repo);
|
static nlohmann::json add_run_scripts_repo(nlohmann::json config, std::string repo, std::string branch);
|
||||||
static void remove_run_scripts_script(std::string repo, std::string script_path);
|
static nlohmann::json add_run_actions_action(nlohmann::json config, std::string repo, std::string script_path);
|
||||||
static void remove_token(std::string repo, std::string token);
|
static nlohmann::json add_token(nlohmann::json config, std::string repo, std::string token);
|
||||||
|
|
||||||
|
static nlohmann::json remove_update_files_repo(nlohmann::json config, std::string repo);
|
||||||
|
static nlohmann::json remove_update_files_file(nlohmann::json config, std::string repo, std::string remote_path);
|
||||||
|
static nlohmann::json remove_update_files_post_update(nlohmann::json config, std::string repo, std::string command);
|
||||||
|
static nlohmann::json remove_run_scripts_repo(nlohmann::json config, std::string repo);
|
||||||
|
static nlohmann::json remove_run_actions_action(nlohmann::json config, std::string repo, std::string script_path);
|
||||||
|
static nlohmann::json remove_token(nlohmann::json config, std::string repo);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef CONFIG_API_HPP
|
||||||
|
#define CONFIG_API_HPP
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
class ConfigApi {
|
||||||
|
public:
|
||||||
|
static bool set_port(nlohmann::json config, int port);
|
||||||
|
static bool add_token(nlohmann::json config, std::string repo, std::string token);
|
||||||
|
static bool remove_token(nlohmann::json config, std::string repo);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
@ -0,0 +1,11 @@
|
||||||
|
#ifndef DIALOG_MENU_HPP
|
||||||
|
#define DIALOG_MENU_HPP
|
||||||
|
|
||||||
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
|
class DialogMenu {
|
||||||
|
public:
|
||||||
|
static void open_menu(nlohmann::json config, std::string config_file_path);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
#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
|
||||||
|
|
@ -5,6 +5,6 @@
|
||||||
#include <crow/http_response.h>
|
#include <crow/http_response.h>
|
||||||
#include <nlohmann/json.hpp>
|
#include <nlohmann/json.hpp>
|
||||||
|
|
||||||
crow::response run_actions(const nlohmann::json &, const nlohmann::json &,const crow::request &);
|
crow::response run_actions(const nlohmann::json &, const crow::request &);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -12,6 +12,7 @@ class Logger {
|
||||||
static void fatal(std::string message);
|
static void fatal(std::string message);
|
||||||
static void success(std::string message);
|
static void success(std::string message);
|
||||||
static void code(std::string message);
|
static void code(std::string message);
|
||||||
|
static void debug(std::string message);
|
||||||
private:
|
private:
|
||||||
static void log(std::string message, std::string level);
|
static void log(std::string message, std::string level);
|
||||||
static std::ofstream log_file;
|
static std::ofstream log_file;
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,8 @@ class Routes {
|
||||||
|
|
||||||
private:
|
private:
|
||||||
crow::SimpleApp app;
|
crow::SimpleApp app;
|
||||||
|
|
||||||
|
static bool check_ping(const crow::request &req);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -2,14 +2,17 @@
|
||||||
#include <filesystem>
|
#include <filesystem>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "config/terminal-menu.hpp"
|
||||||
|
#include "config/dialog-menu.hpp"
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
|
|
||||||
void Config::create_config(std::string config_file_path) {
|
void Config::create_config(std::string config_file_path) {
|
||||||
std::cout << "Creating config file" << std::endl;
|
std::cout << "Creating config file" << std::endl;
|
||||||
nlohmann::json config = {
|
nlohmann::json config = {
|
||||||
{"port", 65001},
|
{"port", 65001},
|
||||||
{"tokens", nlohmann::json::array()},
|
{"tokens", {}},
|
||||||
};
|
};
|
||||||
std::string path_to_config = config_file_path.substr(0, config_file_path.find_last_of('/'));
|
std::string path_to_config = config_file_path.substr(0, config_file_path.find_last_of('/'));
|
||||||
if (!std::filesystem::exists(path_to_config)) {
|
if (!std::filesystem::exists(path_to_config)) {
|
||||||
|
|
@ -62,6 +65,19 @@ nlohmann::json Config::get_config(std::string config_file_path) {
|
||||||
return config;
|
return config;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Config::open_config_menu() {
|
void Config::open_menu(nlohmann::json config, std::string config_file_path) {
|
||||||
Logger::warn("[Config] Config menu not implemented yet");
|
Logger::info("[Config] Opening config menu");
|
||||||
|
std::string menu = "";
|
||||||
|
if (std::system("which dialog > /dev/null") == 0) {
|
||||||
|
menu = "dialog";
|
||||||
|
} else {
|
||||||
|
menu = "terminal";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (menu == "dialog") {
|
||||||
|
DialogMenu::open_menu(config, config_file_path);
|
||||||
|
} else {
|
||||||
|
TerminalMenu::open_menu(config, config_file_path);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
#include "config/config-api.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
|
bool ConfigApi::set_port(nlohmann::json config, int port) {
|
||||||
|
Logger::info("[Config] Setting port to " + std::to_string(port));
|
||||||
|
config["port"] = port;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigApi::add_token(nlohmann::json config, std::string repo, std::string token) {
|
||||||
|
Logger::info("[Config] Adding token for repo " + repo);
|
||||||
|
if (config["tokens"].find(repo) != config["tokens"].end()) {
|
||||||
|
Logger::warn("Token already exists for this repo.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
config["tokens"][repo] = token;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ConfigApi::remove_token(nlohmann::json config, std::string repo) {
|
||||||
|
Logger::info("[Config] Removing token for repo " + repo);
|
||||||
|
if (config["tokens"].find(repo) == config["tokens"].end()) {
|
||||||
|
Logger::warn("Token does not exist for this repo.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
config["tokens"].erase(repo);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
#include <dialog.h>
|
||||||
|
#include "config/dialog-menu.hpp"
|
||||||
|
#include "logger.hpp"
|
||||||
|
|
||||||
|
void DialogMenu::open_menu(nlohmann::json config, std::string config_file_path) {
|
||||||
|
Logger::info("Opening dialog menu");
|
||||||
|
init_dialog(stdin, stdout);
|
||||||
|
dialog_msgbox(
|
||||||
|
"GitHub Webhook Handler - Config Menu",
|
||||||
|
"\nWelcome to the config menu!\n\nThis is a work in progress, please use the terminal menu for now.",
|
||||||
|
10, 50, 1);
|
||||||
|
Logger::warn("Dialog menu is a work in progress, please use the terminal menu for now.");
|
||||||
|
end_dialog();
|
||||||
|
Logger::info("Dialog menu closed");
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,98 @@
|
||||||
|
#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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
@ -2,7 +2,7 @@
|
||||||
|
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
|
|
||||||
crow::response run_actions(const nlohmann::json &run_actions, const nlohmann::json &tokens, const crow::request &req) {
|
crow::response run_actions(const nlohmann::json &config_run_actions, const crow::request &req) {
|
||||||
nlohmann::json payload;
|
nlohmann::json payload;
|
||||||
try {
|
try {
|
||||||
payload = nlohmann::json::parse(req.body);
|
payload = nlohmann::json::parse(req.body);
|
||||||
|
|
@ -15,61 +15,62 @@ crow::response run_actions(const nlohmann::json &run_actions, const nlohmann::js
|
||||||
return crow::response(400, response.dump());
|
return crow::response(400, response.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ref;
|
if (payload.find("ref") == payload.end() || payload.find("repository") == payload.end() || payload["repository"].find("full_name") == payload["repository"].end()) {
|
||||||
std::string repo;
|
Logger::error("[/run-actions] Invalid JSON payload");
|
||||||
|
|
||||||
try {
|
|
||||||
ref = payload["ref"];
|
|
||||||
if (size_t last_slash = ref.find_last_of('/'); last_slash != std::string::npos && last_slash + 1 < ref.length())
|
|
||||||
ref = ref.substr(last_slash + 1);
|
|
||||||
repo = payload["repository"]["full_name"];
|
|
||||||
} catch (nlohmann::json::out_of_range& e) {
|
|
||||||
Logger::error("[/run-actions] Invalid JSON payload: " + std::string(e.what()));
|
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"status", 400},
|
{"status", 400},
|
||||||
{"error", "Invalid JSON payload"}
|
{"error", "Invalid JSON payload"}
|
||||||
};
|
};
|
||||||
return crow::response(400, response.dump());
|
return crow::response(400, response.dump());
|
||||||
}
|
}
|
||||||
|
std::string ref = payload["ref"];
|
||||||
|
if (size_t last_slash = ref.find_last_of('/'); last_slash != std::string::npos && last_slash + 1 < ref.length())
|
||||||
|
ref = ref.substr(last_slash + 1);
|
||||||
|
|
||||||
|
std::string repo = payload["repository"]["full_name"];
|
||||||
|
|
||||||
Logger::info("[/run-actions] Received push to " + repo + ":" + ref);
|
Logger::info("[/run-actions] Received push to " + repo + ":" + ref);
|
||||||
|
|
||||||
if (run_actions.find(repo) == run_actions.end()) {
|
if (config_run_actions.find(repo) == config_run_actions.end()) {
|
||||||
Logger::warn("[/run-actions] No run-actions webhook configuration for repo " + repo);
|
Logger::warn("[/run-actions] No run-actions configuration for repo " + repo);
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"status", 404},
|
{"status", 404},
|
||||||
{"error", "No run-actions webhook configuration for repo"}
|
{"error", "No run-actions configuration for repo"}
|
||||||
};
|
};
|
||||||
return crow::response(404, response.dump());
|
return crow::response(404, response.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::info("[/run-actions] Found run-actions webhook configuration for repo " + repo);
|
Logger::info("[/run-actions] Found run-actions configuration for repo " + repo);
|
||||||
|
|
||||||
nlohmann::json config;
|
nlohmann::json config;
|
||||||
std::string config_branch;
|
bool found = false;
|
||||||
nlohmann::json config_actions;
|
for (auto c_repo = config_run_actions.begin(); c_repo != config_run_actions.end(); ++c_repo) {
|
||||||
try {
|
if (c_repo.key() != repo) continue;
|
||||||
config = run_actions[repo];
|
if (c_repo.value().find("branch") == c_repo.value().end() || c_repo.value().find("actions") == c_repo.value().end()) {
|
||||||
config_branch = config["branch"];
|
Logger::error("[/run-actions] Invalid run-actions configuration found for repo " + c_repo.key());
|
||||||
config_actions = config["actions"];
|
nlohmann::json response = {
|
||||||
} catch (nlohmann::json::out_of_range& e) {
|
{"status", 500},
|
||||||
Logger::error("[/run-actions] Invalid run-actions configuration for repo " + repo + ": " + std::string(e.what()));
|
{"error", "Invalid update-files configuration"}
|
||||||
nlohmann::json response = {
|
};
|
||||||
{"status", 500},
|
return crow::response(500, response.dump());
|
||||||
{"error", "Invalid run-actions configuration"}
|
}
|
||||||
};
|
if (c_repo.value()["branch"].get<std::string>() != ref) continue;
|
||||||
return crow::response(500, response.dump());
|
Logger::info("[/run-actions] Found run-actions configuration for branch " + ref);
|
||||||
|
config = c_repo.value();
|
||||||
|
found = true;
|
||||||
}
|
}
|
||||||
|
if (!found) {
|
||||||
if (ref != config_branch) {
|
Logger::info("[/run-actions] Ignoring push to non-configured branch " + ref + " on repo " + repo);
|
||||||
Logger::info("[/run-actions] Ignoring push to " + repo + " on branch " + ref);
|
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"status", 200},
|
{"status", 200},
|
||||||
{"message", "Ignoring push to " + repo + " on branch " + ref}
|
{"message", "Ignoring push to non-configured branch" + ref}
|
||||||
};
|
};
|
||||||
return crow::response(200, response.dump());
|
return crow::response(200, response.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string config_branch = config["branch"];
|
||||||
|
nlohmann::json config_actions = config["actions"];
|
||||||
|
|
||||||
if (config_actions.empty()) {
|
if (config_actions.empty()) {
|
||||||
Logger::info("[/run-actions] No actions configured for " + repo + " on branch " + ref);
|
Logger::info("[/run-actions] No actions configured for " + repo + " on branch " + ref);
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
|
|
@ -88,30 +89,22 @@ crow::response run_actions(const nlohmann::json &run_actions, const nlohmann::js
|
||||||
{"failed-actions", nlohmann::json::array()}
|
{"failed-actions", nlohmann::json::array()}
|
||||||
};
|
};
|
||||||
for (const auto &action : config_actions) {
|
for (const auto &action : config_actions) {
|
||||||
std::string action_name;
|
if (action.find("name") == action.end() || action.find("command") == action.end()) {
|
||||||
std::string action_command;
|
Logger::error("[/run-actions] Invalid action configuration for repo " + repo);
|
||||||
nlohmann::json action_args;
|
nlohmann::json e_response = {
|
||||||
try {
|
|
||||||
action_name = action["name"];
|
|
||||||
action_command = action["command"];
|
|
||||||
action_args = action["args"];
|
|
||||||
} catch (nlohmann::json::out_of_range& e) {
|
|
||||||
Logger::error("[/run-actions] Invalid action configuration for repo " + repo + ": " + std::string(e.what()));
|
|
||||||
nlohmann::json response = {
|
|
||||||
{"status", 500},
|
{"status", 500},
|
||||||
{"error", "Invalid action configuration"}
|
{"error", "Invalid action configuration"},
|
||||||
|
{"successful-actions", response["successful-actions"]},
|
||||||
|
{"failed-actions", response["failed-actions"]}
|
||||||
};
|
};
|
||||||
return crow::response(500, response.dump());
|
return crow::response(500, e_response.dump());
|
||||||
}
|
}
|
||||||
|
std::string action_name = action["name"];
|
||||||
|
std::string action_command = action["command"];
|
||||||
|
|
||||||
Logger::info("[/run-actions] Running action '" + action_name + "'");
|
Logger::info("[/run-actions] Running action '" + action_name + "'");
|
||||||
|
|
||||||
std::string action_command_with_args = action_command;
|
int ret = std::system(action_command.c_str());
|
||||||
for (const auto &arg : action_args) {
|
|
||||||
action_command_with_args += " " + arg.get<std::string>();
|
|
||||||
}
|
|
||||||
|
|
||||||
int ret = std::system(action_command_with_args.c_str());
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
Logger::info("[/run-actions] Action " + action_name + " completed successfully");
|
Logger::info("[/run-actions] Action " + action_name + " completed successfully");
|
||||||
response["successful-actions"].push_back(action_name);
|
response["successful-actions"].push_back(action_name);
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,5 @@
|
||||||
#include "endpoints/update-files.hpp"
|
#include "endpoints/update-files.hpp"
|
||||||
|
#include <cmath>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
|
|
@ -16,30 +17,10 @@ crow::response update_files(const nlohmann::json& config_update_files, const nlo
|
||||||
return crow::response(400, response.dump());
|
return crow::response(400, response.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ref;
|
if (payload.find("ref") == payload.end() || payload.find("repository") == payload.end() ||
|
||||||
std::string repo;
|
payload["repository"].find("full_name") == payload["repository"].end() || payload["repository"].find("private") == payload["repository"].end() ||
|
||||||
bool is_private;
|
payload.find("commits") == payload.end() || !payload["commits"].is_array() || payload["commits"].empty()){
|
||||||
std::string token;
|
Logger::error("[/update-files] Invalid JSON payload");
|
||||||
|
|
||||||
try {
|
|
||||||
ref = payload["ref"];
|
|
||||||
if (size_t last_slash = ref.find_last_of('/'); last_slash != std::string::npos && last_slash + 1 < ref.length())
|
|
||||||
ref = ref.substr(last_slash + 1);
|
|
||||||
repo = payload["repository"]["full_name"];
|
|
||||||
is_private = payload["repository"]["private"];
|
|
||||||
if (is_private) {
|
|
||||||
if (config_tokens.find(repo) == config_tokens.end()) {
|
|
||||||
Logger::warn("[/update-files] No token configured for private repo " + repo);
|
|
||||||
nlohmann::json response = {
|
|
||||||
{"status", 403},
|
|
||||||
{"error", "No token configured for private repo"}
|
|
||||||
};
|
|
||||||
return crow::response(403, response.dump());
|
|
||||||
}
|
|
||||||
token = config_tokens[repo];
|
|
||||||
}
|
|
||||||
} catch (nlohmann::json::out_of_range& e) {
|
|
||||||
Logger::error("[/update-files] Invalid JSON payload: " + std::string(e.what()));
|
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"status", 400},
|
{"status", 400},
|
||||||
{"error", "Invalid JSON payload"}
|
{"error", "Invalid JSON payload"}
|
||||||
|
|
@ -47,6 +28,24 @@ crow::response update_files(const nlohmann::json& config_update_files, const nlo
|
||||||
return crow::response(400, response.dump());
|
return crow::response(400, response.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string ref = payload["ref"];
|
||||||
|
if (size_t last_slash = ref.find_last_of('/'); last_slash != std::string::npos && last_slash + 1 < ref.length())
|
||||||
|
ref = ref.substr(last_slash + 1);
|
||||||
|
std::string repo = payload["repository"]["full_name"];
|
||||||
|
bool is_private = payload["repository"]["private"];
|
||||||
|
std::string token;
|
||||||
|
if (is_private) {
|
||||||
|
if (config_tokens.find(repo) == config_tokens.end()) {
|
||||||
|
Logger::warn("[/update-files] No token configured for private repo " + repo);
|
||||||
|
nlohmann::json response = {
|
||||||
|
{"status", 403},
|
||||||
|
{"error", "No token configured for private repo"}
|
||||||
|
};
|
||||||
|
return crow::response(403, response.dump());
|
||||||
|
}
|
||||||
|
token = config_tokens[repo];
|
||||||
|
}
|
||||||
|
|
||||||
Logger::info("[/update-files] Received push to " + repo + ":" + ref + " (private: " + (is_private ? "true" : "false") + ")");
|
Logger::info("[/update-files] Received push to " + repo + ":" + ref + " (private: " + (is_private ? "true" : "false") + ")");
|
||||||
|
|
||||||
if (config_update_files.find(repo) == config_update_files.end()) {
|
if (config_update_files.find(repo) == config_update_files.end()) {
|
||||||
|
|
@ -63,16 +62,24 @@ crow::response update_files(const nlohmann::json& config_update_files, const nlo
|
||||||
nlohmann::json config;
|
nlohmann::json config;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
for (auto c_repo = config_update_files.begin(); c_repo != config_update_files.end(); ++c_repo) {
|
for (auto c_repo = config_update_files.begin(); c_repo != config_update_files.end(); ++c_repo) {
|
||||||
if (const std::string &c_repo_name = c_repo.key(); c_repo_name == repo) continue;
|
if (c_repo.key() != repo) continue;
|
||||||
|
if (c_repo.value().find("branch") == c_repo.value().end() || c_repo.value().find("files") == c_repo.value().end()) {
|
||||||
|
Logger::error("[/update-files] Invalid update-files configuration found for repo " + c_repo.key());
|
||||||
|
nlohmann::json response = {
|
||||||
|
{"status", 500},
|
||||||
|
{"error", "Invalid update-files configuration"}
|
||||||
|
};
|
||||||
|
return crow::response(500, response.dump());
|
||||||
|
}
|
||||||
if (c_repo.value()["branch"] != ref) continue;
|
if (c_repo.value()["branch"] != ref) continue;
|
||||||
config = c_repo.value();
|
config = c_repo.value();
|
||||||
found = true;
|
found = true;
|
||||||
}
|
}
|
||||||
if (!found) {
|
if (!found) {
|
||||||
Logger::warn("[/update-files] No update-files webhook configuration for branch " + ref);
|
Logger::warn("[/update-files] Ignoring push to non-configured branch" + ref + " on repo " + repo);
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"status", 404},
|
{"status", 200},
|
||||||
{"error", "No update-files webhook configuration for branch" + ref}
|
{"message", "Ignoring push to non-configured branch" + ref}
|
||||||
};
|
};
|
||||||
return crow::response(404, response.dump());
|
return crow::response(404, response.dump());
|
||||||
}
|
}
|
||||||
|
|
@ -82,23 +89,31 @@ crow::response update_files(const nlohmann::json& config_update_files, const nlo
|
||||||
if (config["files"].empty()) {
|
if (config["files"].empty()) {
|
||||||
Logger::warn("[/update-files] No files configured for repo " + repo + ":" + ref);
|
Logger::warn("[/update-files] No files configured for repo " + repo + ":" + ref);
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"status", 404},
|
{"status", 200},
|
||||||
{"error", "No files configured for repo" + repo + ":" + ref}
|
{"message", "No files configured for repo " + repo + ":" + ref}
|
||||||
};
|
};
|
||||||
return crow::response(404, response.dump());
|
return crow::response(200, response.dump());
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::vector<std::string>> modified_files;
|
std::vector<std::vector<std::string>> modified_files;
|
||||||
for (auto &commit : payload["commits"]) {
|
for (auto &commit : payload["commits"]) {
|
||||||
|
if (commit.find("added") == commit.end() || commit.find("modified") == commit.end()) {
|
||||||
|
Logger::error("[/update-files] Invalid JSON payload");
|
||||||
|
nlohmann::json response = {
|
||||||
|
{"status", 400},
|
||||||
|
{"error", "Invalid JSON payload"}
|
||||||
|
};
|
||||||
|
return crow::response(400, response.dump());
|
||||||
|
}
|
||||||
for (auto &file : commit["added"]) {
|
for (auto &file : commit["added"]) {
|
||||||
std::string file_path = file;
|
std::string file_path = file;
|
||||||
if (config_update_files[repo]["files"].find(file_path) == config_update_files[repo]["files"].end()) continue;
|
if (config["files"].find(file_path) == config["files"].end()) continue;
|
||||||
std::vector<std::string> file_info = {file_path, "added"};
|
std::vector<std::string> file_info = {file_path, "added"};
|
||||||
modified_files.push_back(file_info);
|
modified_files.push_back(file_info);
|
||||||
}
|
}
|
||||||
for (auto &file : commit["modified"]) {
|
for (auto &file : commit["modified"]) {
|
||||||
std::string file_path = file;
|
std::string file_path = file;
|
||||||
if (config_update_files[repo]["files"].find(file_path) == config_update_files[repo]["files"].end()) continue;
|
if (config["files"].find(file_path) == config["files"].end()) continue;
|
||||||
std::vector<std::string> file_info = {file_path, "modified"};
|
std::vector<std::string> file_info = {file_path, "modified"};
|
||||||
modified_files.push_back(file_info);
|
modified_files.push_back(file_info);
|
||||||
}
|
}
|
||||||
|
|
@ -120,8 +135,11 @@ crow::response update_files(const nlohmann::json& config_update_files, const nlo
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
{"status", 200},
|
{"status", 200},
|
||||||
{"message", "OK"},
|
{"message", "OK"},
|
||||||
{"file_count", 0},
|
{"updated-file-count", 0},
|
||||||
{"updated-files", nlohmann::json::array()},
|
{"updated-files", {
|
||||||
|
{"successful", nlohmann::json::array()},
|
||||||
|
{"failed", nlohmann::json::array()}
|
||||||
|
}},
|
||||||
{"post-update", {
|
{"post-update", {
|
||||||
{"successful", nlohmann::json::array()},
|
{"successful", nlohmann::json::array()},
|
||||||
{"failed", nlohmann::json::array()}
|
{"failed", nlohmann::json::array()}
|
||||||
|
|
@ -130,36 +148,63 @@ crow::response update_files(const nlohmann::json& config_update_files, const nlo
|
||||||
for (auto &file : modified_files) {
|
for (auto &file : modified_files) {
|
||||||
std::string remote_path = file[0];
|
std::string remote_path = file[0];
|
||||||
|
|
||||||
std::string local_path = config_update_files[repo]["files"][remote_path];
|
std::string local_path = config["files"][remote_path];
|
||||||
if (local_path.find_last_of('/') != std::string::npos)
|
if (local_path.find_last_of('/') != std::string::npos)
|
||||||
try {
|
try {
|
||||||
std::filesystem::create_directories(local_path.substr(0, local_path.find_last_of('/')));
|
std::filesystem::create_directories(local_path.substr(0, local_path.find_last_of('/')));
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
Logger::error("[/update-files] Failed to create directories for " + local_path + ": " + std::string(e.what()));
|
Logger::error("[/update-files] Failed to create directories for " + local_path + ": " + std::string(e.what()));
|
||||||
|
response["updated-files"]["failed"].push_back(local_path);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string command = "curl -s https://raw.githubusercontent.com/" + repo + "/" + ref + "/" + remote_path + " -o " + local_path;
|
std::string command = "curl -s https://raw.githubusercontent.com/" + repo + "/" + ref + "/" + remote_path + " -o " + local_path;
|
||||||
if (is_private) command += " -H 'Authorization: token " + token + "'";
|
if (is_private) command += " -H 'Authorization: token " + token + "'";
|
||||||
std::system(command.c_str());
|
int ret = std::system(command.c_str());
|
||||||
|
if (ret != 0) {
|
||||||
|
Logger::error("[/update-files] Failed to update " + local_path);
|
||||||
|
response["updated-files"]["failed"].push_back(local_path);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
Logger::info("[/update-files] " + std::string(file[1] == "added" ? "Created" : "Updated") + " " + local_path);
|
Logger::info("[/update-files] " + std::string(file[1] == "added" ? "Created" : "Updated") + " " + local_path);
|
||||||
response["file_count"] = response["file_count"].get<int>() + 1;
|
response["updated-file-count"] = response["updated-file-count"].get<int>() + 1;
|
||||||
response["updated-files"].push_back(remote_path);
|
response["updated-files"]["successful"].push_back(local_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger::success("[/update-files] Finished updating " + std::to_string(modified_files.size()) + " files for repo " + repo + ":" + ref);
|
Logger::success("[/update-files] Finished updating " + std::to_string(modified_files.size()) + " files for repo " + repo + ":" + ref);
|
||||||
|
|
||||||
|
if (config.find("post-update") == config.end()) {
|
||||||
|
Logger::info("[/update-files] No post-update actions configured for repo " + repo + ":" + ref);
|
||||||
|
return crow::response(200, response.dump());
|
||||||
|
}
|
||||||
|
|
||||||
|
nlohmann::json post_update_actions = config["post-update"];
|
||||||
|
|
||||||
Logger::info("[/update-files] Running post-update actions for repo " + repo + ":" + ref);
|
Logger::info("[/update-files] Running post-update actions for repo " + repo + ":" + ref);
|
||||||
|
|
||||||
for (auto &c_action : config_update_files[repo]["post-update"]) {
|
for (const auto &action : post_update_actions) {
|
||||||
std::string action = c_action.get<std::string>();
|
if (action.find("name") == action.end() || action.find("command") == action.end()) {
|
||||||
Logger::info("[/update-files] Running post-update action: " + action);
|
Logger::error("[/update-files] Invalid post-update configuration for repo " + repo);
|
||||||
int return_code = std::system(action.c_str());
|
nlohmann::json e_response = {
|
||||||
if (return_code == 0) {
|
{"status", 500},
|
||||||
Logger::success("[/update-files] Post-update action " + action + " ran successfully");
|
{"error", "Invalid action configuration"},
|
||||||
response["post-update"]["successful"].push_back(action);
|
{"updated-files", response["updated-files"]},
|
||||||
|
{"post-update", response["post-update"]}
|
||||||
|
};
|
||||||
|
return crow::response(500, e_response.dump());
|
||||||
|
}
|
||||||
|
std::string action_name = action["name"];
|
||||||
|
std::string action_command = action["command"];
|
||||||
|
|
||||||
|
Logger::info("[/update-files] Running post-update action '" + action_name + "'");
|
||||||
|
|
||||||
|
int ret = std::system(action_command.c_str());
|
||||||
|
if (ret == 0) {
|
||||||
|
Logger::info("[/update-files] Action " + action_name + " completed successfully");
|
||||||
|
response["post-update"]["successful"].push_back(action_name);
|
||||||
} else {
|
} else {
|
||||||
Logger::error("[/update-files] Post-update action " + action + " failed with return code " + std::to_string(return_code));
|
Logger::error("[/update-files] Action " + action_name + " failed with exit code " + std::to_string(ret));
|
||||||
response["post-update"]["failed"].push_back(action);
|
response["post-update"]["failed"].push_back(action_name);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,10 @@ void Logger::code(std::string message) {
|
||||||
Logger::log(message, "CODE");
|
Logger::log(message, "CODE");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Logger::debug(std::string message) {
|
||||||
|
Logger::log(message, "DEBUG ");
|
||||||
|
}
|
||||||
|
|
||||||
void Logger::log(std::string message, std::string level) {
|
void Logger::log(std::string message, std::string level) {
|
||||||
std::string formatted_message = "";
|
std::string formatted_message = "";
|
||||||
if (isatty(fileno(stdout))) {
|
if (isatty(fileno(stdout))) {
|
||||||
|
|
@ -107,6 +111,11 @@ void Logger::log(std::string message, std::string level) {
|
||||||
} else if (level == "CODE") {
|
} else if (level == "CODE") {
|
||||||
formatted_message += COLORS_FG_WHITE;
|
formatted_message += COLORS_FG_WHITE;
|
||||||
formatted_message += COLORS_DIM;
|
formatted_message += COLORS_DIM;
|
||||||
|
} else if (level == "DEBUG ") {
|
||||||
|
formatted_message += COLORS_FG_BLUE;
|
||||||
|
formatted_message += COLORS_UNDERLINED;
|
||||||
|
formatted_message += COLORS_DIM;
|
||||||
|
formatted_message += COLORS_BOLD;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -117,10 +126,14 @@ void Logger::log(std::string message, std::string level) {
|
||||||
formatted_message += "(" + std::string(time_buffer) + ") ";
|
formatted_message += "(" + std::string(time_buffer) + ") ";
|
||||||
|
|
||||||
if (level == "CODE") {
|
if (level == "CODE") {
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
formatted_message += "\n" + message + "\n";
|
||||||
|
#else
|
||||||
struct winsize w;
|
struct winsize w;
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
int term_width = w.ws_col > 250 ? 250 : w.ws_col - 1;
|
int term_width = w.ws_col > 250 ? 250 : w.ws_col - 1;
|
||||||
formatted_message += "\n" + std::string(term_width, '=') + "\n" + message + "\n" + std::string(term_width, '=');
|
formatted_message += "\n" + std::string(term_width, '=') + "\n" + message + "\n" + std::string(term_width, '=');
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
formatted_message += "[" + level + "] " + message;
|
formatted_message += "[" + level + "] " + message;
|
||||||
}
|
}
|
||||||
|
|
@ -129,10 +142,14 @@ void Logger::log(std::string message, std::string level) {
|
||||||
}
|
}
|
||||||
std::cout << formatted_message << std::endl;
|
std::cout << formatted_message << std::endl;
|
||||||
if (level == "CODE") {
|
if (level == "CODE") {
|
||||||
|
#if defined(__aarch64__)
|
||||||
|
Logger::log_file << std::endl << message << std::endl;
|
||||||
|
#else
|
||||||
struct winsize w;
|
struct winsize w;
|
||||||
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
|
||||||
int term_width = w.ws_col > 250 ? 250 : w.ws_col - 1;
|
int term_width = w.ws_col > 250 ? 250 : w.ws_col - 1;
|
||||||
Logger::log_file << std::string(term_width, '=') << std::endl << message << std::endl << std::string(term_width, '=') << std::endl;
|
Logger::log_file << std::string(term_width, '=') << std::endl << message << std::endl << std::string(term_width, '=') << std::endl;
|
||||||
|
#endif
|
||||||
} else {
|
} else {
|
||||||
Logger::log_file << "[" << level << "] " << message << std::endl;
|
Logger::log_file << "[" << level << "] " << message << std::endl;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
12
src/main.cpp
12
src/main.cpp
|
|
@ -30,20 +30,20 @@ int main(int argc, char **argv) {
|
||||||
|
|
||||||
Logger::init(logs_dir);
|
Logger::init(logs_dir);
|
||||||
|
|
||||||
if (argc == 4 && std::string(argv[3]) == "--config") {
|
|
||||||
Config::open_config_menu();
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check if config file exists
|
// Check if config file exists
|
||||||
if (!std::filesystem::exists(config_file_path)) {
|
if (!std::filesystem::exists(config_file_path)) {
|
||||||
Logger::warn("Config file does not exist, creating...");
|
Logger::warn("Config file does not exist, creating...");
|
||||||
Config::create_config(config_file_path);
|
Config::create_config(config_file_path);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load configuration
|
// Load current configuration
|
||||||
nlohmann::json config = Config::get_config(config_file_path);
|
nlohmann::json config = Config::get_config(config_file_path);
|
||||||
|
|
||||||
|
if (argc == 4 && std::string(argv[3]) == "--config") {
|
||||||
|
Config::open_menu(config, config_file_path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
std::signal(SIGINT, signal_handler);
|
std::signal(SIGINT, signal_handler);
|
||||||
|
|
||||||
// Start server
|
// Start server
|
||||||
|
|
|
||||||
134
src/routes.cpp
134
src/routes.cpp
|
|
@ -6,14 +6,16 @@
|
||||||
#include "logger.hpp"
|
#include "logger.hpp"
|
||||||
|
|
||||||
Routes::Routes(nlohmann::json config) {
|
Routes::Routes(nlohmann::json config) {
|
||||||
Logger::info("Partitioning configuration");
|
Logger::info("[Routes] Partitioning configuration");
|
||||||
const nlohmann::json config_update_files = config["update-files"];
|
const nlohmann::json config_update_files = config["update-files"];
|
||||||
const nlohmann::json config_run_actions = config["run-actions"];
|
const nlohmann::json config_run_actions = config["run-actions"];
|
||||||
const nlohmann::json config_tokens = config["tokens"];
|
const nlohmann::json config_tokens = config["tokens"];
|
||||||
|
|
||||||
Logger::info("Registering route \"/\"");
|
Logger::info("[Routes] Creating server");
|
||||||
|
|
||||||
|
Logger::info("[Routes] Registering route \"/\"");
|
||||||
CROW_ROUTE(this->app, "/")
|
CROW_ROUTE(this->app, "/")
|
||||||
.methods("POST"_method)
|
.methods("POST"_method, "GET"_method)
|
||||||
.name("Ping")
|
.name("Ping")
|
||||||
([]() {
|
([]() {
|
||||||
nlohmann::json response = {
|
nlohmann::json response = {
|
||||||
|
|
@ -23,49 +25,97 @@ Routes::Routes(nlohmann::json config) {
|
||||||
return crow::response(200, response.dump());
|
return crow::response(200, response.dump());
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!config_update_files.is_null()) {
|
Logger::info("[Routes] Registering route \"/run-actions\"");
|
||||||
Logger::info("Registering route \"/update-files\"");
|
CROW_ROUTE(this->app, "/run-actions")
|
||||||
CROW_ROUTE(this->app, "/update-files")
|
.methods("POST"_method)
|
||||||
.methods("POST"_method)
|
.name("Run Actions")
|
||||||
.name("Update Files")
|
([&config_run_actions](const crow::request &req) {
|
||||||
([&config_update_files, &config_tokens](const crow::request &req) {
|
if (check_ping(req)) {
|
||||||
try {
|
nlohmann::json response = {
|
||||||
return update_files(config_update_files, config_tokens, req);
|
{"status", 200},
|
||||||
} catch (const std::exception &e) {
|
{"message", "Pong"}
|
||||||
Logger::error("Unknown error in update_files: " + std::string(e.what()));
|
};
|
||||||
nlohmann::json response = {
|
return crow::response(200, response.dump());
|
||||||
{"status", 500},
|
}
|
||||||
{"error", "Internal server error"}
|
if (config_run_actions.is_null()) {
|
||||||
};
|
Logger::warn("[Routes] No run-actions configuration found");
|
||||||
return crow::response(500, response.dump());
|
nlohmann::json response = {
|
||||||
}
|
{"status", 404},
|
||||||
});
|
{"error", "No run-actions configuration found"}
|
||||||
}
|
};
|
||||||
|
return crow::response(404, response.dump());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return run_actions(config_run_actions, req);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
Logger::error("[Routes] Unknown error in run_actions: " + std::string(e.what()));
|
||||||
|
nlohmann::json response = {
|
||||||
|
{"status", 500},
|
||||||
|
{"error", "Internal server error"}
|
||||||
|
};
|
||||||
|
return crow::response(500, response.dump());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (!config_run_actions.is_null()) {
|
Logger::info("[Routes] Registering route \"/update-files\"");
|
||||||
Logger::info("Registering route \"/run-actions\"");
|
CROW_ROUTE(this->app, "/update-files")
|
||||||
CROW_ROUTE(this->app, "/run-actions")
|
.methods("POST"_method)
|
||||||
.methods("POST"_method)
|
.name("Update Files")
|
||||||
.name("Run Actions")
|
([&config_update_files, &config_tokens](const crow::request &req) {
|
||||||
([&config_run_actions, &config_tokens](const crow::request &req) {
|
if (check_ping(req)) {
|
||||||
try {
|
nlohmann::json response = {
|
||||||
return run_actions(config_run_actions, config_tokens, req);
|
{"status", 200},
|
||||||
} catch (const std::exception &e) {
|
{"message", "Pong"}
|
||||||
Logger::error("Unknown error in run_actions: " + std::string(e.what()));
|
};
|
||||||
nlohmann::json response = {
|
return crow::response(200, response.dump());
|
||||||
{"status", 500},
|
}
|
||||||
{"error", "Internal server error"}
|
if (config_update_files.is_null()) {
|
||||||
};
|
Logger::warn("[Routes] No update-files configuration found");
|
||||||
return crow::response(500, response.dump());
|
nlohmann::json response = {
|
||||||
}
|
{"status", 404},
|
||||||
});
|
{"error", "No update-files configuration found"}
|
||||||
}
|
};
|
||||||
|
return crow::response(404, response.dump());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
return update_files(config_update_files, config_tokens, req);
|
||||||
|
} catch (const std::exception &e) {
|
||||||
|
Logger::error("[Routes] Unknown error in update_files: " + std::string(e.what()));
|
||||||
|
nlohmann::json response = {
|
||||||
|
{"status", 500},
|
||||||
|
{"error", "Internal server error"}
|
||||||
|
};
|
||||||
|
return crow::response(500, response.dump());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Logger::info("Starting server");
|
Logger::info("[Routes] Registering catch-all route (404)");
|
||||||
|
CROW_CATCHALL_ROUTE(this->app)
|
||||||
|
([](const crow::request &req) {
|
||||||
|
nlohmann::json response = {
|
||||||
|
{"status", 404},
|
||||||
|
{"error", "Not found"}
|
||||||
|
};
|
||||||
|
return crow::response(404, response.dump());
|
||||||
|
});
|
||||||
|
|
||||||
|
Logger::info("[Routes] Routes registered");
|
||||||
|
Logger::info("[Routes] Starting server");
|
||||||
try {
|
try {
|
||||||
this->app.port(config["port"].get<int>()).multithreaded().run();
|
this->app.port(config["port"].get<int>()).multithreaded().run();
|
||||||
} catch (const std::exception &e) {
|
} catch (const std::exception &e) {
|
||||||
Logger::fatal("Error starting server: " + std::string(e.what()));
|
Logger::fatal("[Routes] Error starting server: " + std::string(e.what()));
|
||||||
}
|
}
|
||||||
Logger::info("Server stopped");
|
Logger::info("[Routes] Server stopped");
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Routes::check_ping(const crow::request &req) {
|
||||||
|
if (req.headers.find("X-GitHub-Event") == req.headers.end()) {
|
||||||
|
Logger::warn("[Routes] No X-GitHub-Event header found");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (req.headers.find("X-GitHub-Event")->second == "ping") {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue