diff --git a/README.md b/README.md index 893b556..49cccd0 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ ## Simple C++ WebAPI to work with GitHub Webhooks -Currently creating a local copy of remote files on every push +This application is a simple C++ WebAPI that listens for GitHub Webhooks and performs actions based on the received data and configuration. -## Usage +## Installation ### Use installation script (recommended) @@ -20,7 +20,7 @@ Head over to the [Releases Page](https://github.com/TiagoRG/gh-wh-handler/releas Run the application using your configuration file: ```console -/path/to/gh-wh-handler. /path/to/config.json +/path/to/gh-wh-handler. /path/to/config.json /path/to/logs_dir ``` You can see the config file format below. @@ -32,7 +32,7 @@ You can see the config file format below. - [CrowCpp](https://crowcpp.org/master/) - [nlohmann::json](https://github.com/nlohmann/json) -#### Build the application: +#### Build and install the application: 1. Clone the repository: @@ -55,7 +55,7 @@ cmake .. sudo make install ``` -#### Run the application: +## Usage The application is running on a systemd service, which is both enabled and started after installation. @@ -80,45 +80,51 @@ As of now, the configuration menu is not yet implemented so you have to create t ### Config File -The configuration file can be found in `/services/gh-wh-handler/config.json` and has the following format: +The configuration file can be found in `/services/gh-wh-handler/config.json` and has the following base format: ```json { "port": 65001, - "update-files": { - "owner/repo-name": { - "branch": "main", - "files": { - "path/to/remote/file": "/path/to/local/file", - "...": "..." - }, - "post-update": [ - "post-update-command", - "post-update-script", - "..." - ] - } - }, - "run-scripts": { - "owner/repo-name": { - "branch": "main", - "actions": [ - "command", - "script", - ] - } - }, "tokens": { "owner/repo-name": "token" } } ``` +This configuration will then have more fields for each endpoint that you want to configure. + +Note: Tokens are only required for private repositories. + ## 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. -Since only the `/update-files` endpoint is implemented, the configuration file may not contain the `run-scripts` field. +### `/update-files` + +#### Webhook event: `push` + +This endpoint allows the application to update specific files on the server when a push to a specific branch is made. This way, there's no need to manually update the files on the server or to pull the entire repository. + +It also allows the application to run post-update scripts after the files are updated. + +The configuration file must contain the `update-files` field, which is an object with the following format: + +```json +"update-files": { + "owner/repo-name": { + "branch": "main", + "files": { + "path/to/remote/file": "/path/to/local/file", + "...": "..." + }, + "post-update": [ + "post-update-command", + "post-update-script", + "..." + ] + } +} +``` ## License diff --git a/src/config.cpp b/src/config.cpp index 15d37bb..7e53473 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -9,8 +9,6 @@ void Config::create_config(std::string config_file_path) { std::cout << "Creating config file" << std::endl; nlohmann::json config = { {"port", 65001}, - {"update-files", nlohmann::json::array()}, - {"run-scripts", nlohmann::json::array()}, {"tokens", nlohmann::json::array()}, }; std::string path_to_config = config_file_path.substr(0, config_file_path.find_last_of('/')); @@ -43,6 +41,20 @@ nlohmann::json Config::get_config(std::string config_file_path) { Logger::fatal("Error loading config file: " + std::string(e.what())); } + if (config.is_null()) { + Logger::fatal("[Config] Config file is empty"); + } + + if (config.find("port") == config.end()) { + Logger::warn("[Config] Port not found in config file, using default port 65001"); + config["port"] = 65001; + } + + if (config.find("tokens") == config.end()) { + Logger::warn("[Config] Tokens not found in config file, using empty array. Private repositories will not be accessible."); + config["tokens"] = nlohmann::json::array(); + } + Logger::success("[Config] Loaded config file: " + config_file_path); Logger::info("[Config] Loaded config: "); Logger::code(config.dump(2)); diff --git a/src/routes.cpp b/src/routes.cpp index 4a25a17..c5a434d 100644 --- a/src/routes.cpp +++ b/src/routes.cpp @@ -23,39 +23,43 @@ Routes::Routes(nlohmann::json config) { return crow::response(200, response.dump()); }); - Logger::info("Registering route \"/update-files\""); - CROW_ROUTE(this->app, "/update-files") - .methods("POST"_method) - .name("Update Files") - ([&config_update_files, &config_tokens](const crow::request &req) { - try { - return update_files(config_update_files, config_tokens, req); - } catch (const std::exception &e) { - Logger::error("Unknown error in update_files: " + std::string(e.what())); - nlohmann::json response = { - {"status", 500}, - {"error", "Internal server error"} - }; - return crow::response(500, response.dump()); - } - }); + if (!config_update_files.is_null()) { + Logger::info("Registering route \"/update-files\""); + CROW_ROUTE(this->app, "/update-files") + .methods("POST"_method) + .name("Update Files") + ([&config_update_files, &config_tokens](const crow::request &req) { + try { + return update_files(config_update_files, config_tokens, req); + } catch (const std::exception &e) { + Logger::error("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("Registering route \"/run-scripts\""); - CROW_ROUTE(this->app, "/run-scripts") - .methods("POST"_method) - .name("Run Scripts") - ([&config_run_scripts, &config_tokens](const crow::request &req) { - try { - return run_scripts(config_run_scripts, config_tokens, req); - } catch (const std::exception &e) { - Logger::error("Unknown error in run_scripts: " + std::string(e.what())); - nlohmann::json response = { - {"status", 500}, - {"error", "Internal server error"} - }; - return crow::response(500, response.dump()); - } - }); + if (!config_run_scripts.is_null()) { + Logger::info("Registering route \"/run-scripts\""); + CROW_ROUTE(this->app, "/run-scripts") + .methods("POST"_method) + .name("Run Scripts") + ([&config_run_scripts, &config_tokens](const crow::request &req) { + try { + return run_scripts(config_run_scripts, config_tokens, req); + } catch (const std::exception &e) { + Logger::error("Unknown error in run_scripts: " + std::string(e.what())); + nlohmann::json response = { + {"status", 500}, + {"error", "Internal server error"} + }; + return crow::response(500, response.dump()); + } + }); + } Logger::info("Starting server"); try {