From f17c98703fad0086ac091c9c6ef7ef136e9bcad4 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Thu, 8 Feb 2024 14:55:09 -0500 Subject: [PATCH 01/15] Add logging of JSON requests. --- src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 950bec6..53b7105 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,7 +52,9 @@ async fn echo_request( warn!("Received a non-JSON body."); None }, - Some(Json(value)) => Some(value), + Some(Json(value)) => { + info!("JSON request: {}", value.to_string()); + Some(value)}, }; let response = EchoResponse { method, -- 2.40.1 From bba5134531efd6b15c677073b0958b59691d69d0 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Thu, 8 Feb 2024 14:57:57 -0500 Subject: [PATCH 02/15] Update the readme with changes. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 813c531..ce3157a 100644 --- a/README.md +++ b/README.md @@ -29,5 +29,5 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb" * [x] Migrate actix to axum for easier maintainability. * [x] Add mirroring of JSON request. * [x] Add logging to server. -* [ ] Add convenience path to access logging for a certain date / records. +* [x] ~~Add convenience path to access logging for a certain date / records.~~ * [ ] Dockerize mirror-server for easier distribution. -- 2.40.1 From 2ccf33e9728da15d5690c86182039ddda4e3f75f Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Tue, 13 Feb 2024 16:25:03 -0500 Subject: [PATCH 03/15] Add tests for the mirror-server handling of requests. --- Cargo.toml | 4 ++ src/main.rs | 161 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 147 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index afabaa1..b41e7eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,7 @@ tower = "0.4" tower-http = { version = "0.5", features = ["trace"] } tracing = "0.1" tracing-subscriber = "0.3" + +[dev-dependencies] +axum-test = "14.0" +rstest = "0.18" diff --git a/src/main.rs b/src/main.rs index 53b7105..fde7472 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,14 @@ use axum::{ - extract::{Host, OriginalUri, Json}, + extract::{Host, Json, OriginalUri}, http::{header::HeaderMap, Method}, Router, }; use clap::Parser; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::BTreeMap; use tower_http::trace; -use tracing::{Level, info, warn}; +use tracing::{info, warn, Level}; #[derive(Parser)] #[command(author, version, about, long_about = None)] @@ -22,7 +22,7 @@ struct CliArgs { ips: String, } -#[derive(Serialize)] +#[derive(Serialize, Deserialize, Debug, PartialEq)] struct EchoResponse { method: String, path: String, @@ -37,7 +37,7 @@ async fn echo_request( original_uri: OriginalUri, host: Host, header_map: HeaderMap, - body: Option> + body: Option>, ) -> Json { let method = method.to_string(); let host = host.0; @@ -47,25 +47,34 @@ async fn echo_request( .map(|(name, value)| (name.to_string(), value.to_str().unwrap_or("").to_string())) .collect(); - let json_body = match body { + let body = match body { None => { warn!("Received a non-JSON body."); None - }, + } Some(Json(value)) => { info!("JSON request: {}", value.to_string()); - Some(value)}, + Some(value) + } }; let response = EchoResponse { method, host, path, headers, - body: json_body, + body, }; Json(response) } +fn app() -> Router { + Router::new().fallback(echo_request).layer( + trace::TraceLayer::new_for_http() + .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) + .on_response(trace::DefaultOnResponse::new().level(Level::INFO)), + ) +} + #[tokio::main] async fn main() { let cli_args = CliArgs::parse(); @@ -73,20 +82,136 @@ async fn main() { let listen_on = format!("{ip}:{port}", ip = listen_on.0, port = listen_on.1); // From https://stackoverflow.com/questions/75009289/how-to-enable-logging-tracing-with-axum - tracing_subscriber::fmt() - .with_max_level(Level::INFO) - .init(); - let app = Router::new().fallback(echo_request).layer( - trace::TraceLayer::new_for_http() - .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) - .on_response(trace::DefaultOnResponse::new().level(Level::INFO)), - ); + tracing_subscriber::fmt().with_max_level(Level::INFO).init(); info!("Starting the mirror-server to listen to {}", listen_on); let listener = tokio::net::TcpListener::bind(&listen_on) .await .unwrap_or_else(|_| panic!("Failed to binding to {}", listen_on)); - axum::serve(listener, app) + axum::serve(listener, app()) .await .expect("Server should start"); } + +#[cfg(test)] +mod tests { + use super::*; + use axum::http::{HeaderName, HeaderValue, Method, StatusCode}; + use axum_test::TestServer; + use rstest::rstest; + + #[tokio::test] + async fn handles_simple_get_request() { + let expected_headers: BTreeMap = BTreeMap::new(); + let expected_response = EchoResponse { + method: "GET".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.get("/").await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[rstest] + #[case::single_level("/test")] + #[case::multiple_level("/test/multiple/levels/")] + #[case::slash_ending("/test/")] + #[tokio::test] + async fn handles_different_urls(#[case] url: String) { + let expected_headers: BTreeMap = BTreeMap::new(); + let expected_response = EchoResponse { + method: "GET".to_string(), + path: url.clone(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.get(&url).await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[rstest] + #[case::post(Method::POST)] + #[case::put(Method::PUT)] + #[case::patch(Method::PATCH)] + #[case::delete(Method::DELETE)] + #[tokio::test] + async fn handles_different_http_methods(#[case] http_method: Method) { + let expected_headers: BTreeMap = BTreeMap::new(); + let expected_response = EchoResponse { + method: http_method.to_string(), + path: "/testing".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.method(http_method, "/testing").await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[tokio::test] + async fn handle_non_json_request() { + let mut expected_headers: BTreeMap = BTreeMap::new(); + expected_headers.insert("content-type".to_string(), "text/plain".to_string()); + let expected_response = EchoResponse { + method: "POST".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.post("/").text("hello world").await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[tokio::test] + async fn handle_json_request() { + let test_json = serde_json::json!({"hello": "world"}); + let mut expected_headers: BTreeMap = BTreeMap::new(); + expected_headers.insert("content-type".to_string(), "application/json".to_string()); + let expected_response = EchoResponse { + method: "POST".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: Some(test_json.clone()), + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.post("/").json(&test_json).await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[tokio::test] + async fn handle_extra_headers() { + let mut expected_headers: BTreeMap = BTreeMap::new(); + expected_headers.insert("x-test-message".to_string(), "Howdy!".to_string()); + let expected_response = EchoResponse { + method: "GET".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server + .get("/") + .add_header( + HeaderName::from_static("x-test-message"), + HeaderValue::from_static("Howdy!"), + ) + .await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } +} -- 2.40.1 From 8010008268bcb58345d2bdf42ff06c132741ed87 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Thu, 8 Feb 2024 14:55:09 -0500 Subject: [PATCH 04/15] Add logging of JSON requests. --- src/main.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 950bec6..53b7105 100644 --- a/src/main.rs +++ b/src/main.rs @@ -52,7 +52,9 @@ async fn echo_request( warn!("Received a non-JSON body."); None }, - Some(Json(value)) => Some(value), + Some(Json(value)) => { + info!("JSON request: {}", value.to_string()); + Some(value)}, }; let response = EchoResponse { method, -- 2.40.1 From 05bffc7996ce1066de646fbc7ddaf99eba12dd0b Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Thu, 8 Feb 2024 14:57:57 -0500 Subject: [PATCH 05/15] Update the readme with changes. --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 813c531..ce3157a 100644 --- a/README.md +++ b/README.md @@ -29,5 +29,5 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb" * [x] Migrate actix to axum for easier maintainability. * [x] Add mirroring of JSON request. * [x] Add logging to server. -* [ ] Add convenience path to access logging for a certain date / records. +* [x] ~~Add convenience path to access logging for a certain date / records.~~ * [ ] Dockerize mirror-server for easier distribution. -- 2.40.1 From 264cd468e33d948aedba9c9f6151e90b5bd7d1be Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Tue, 13 Feb 2024 16:25:03 -0500 Subject: [PATCH 06/15] Add tests for the mirror-server handling of requests. --- Cargo.toml | 4 ++ src/main.rs | 161 ++++++++++++++++++++++++++++++++++++++++++++++------ 2 files changed, 147 insertions(+), 18 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index afabaa1..b41e7eb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -25,3 +25,7 @@ tower = "0.4" tower-http = { version = "0.5", features = ["trace"] } tracing = "0.1" tracing-subscriber = "0.3" + +[dev-dependencies] +axum-test = "14.0" +rstest = "0.18" diff --git a/src/main.rs b/src/main.rs index 53b7105..fde7472 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,14 +1,14 @@ use axum::{ - extract::{Host, OriginalUri, Json}, + extract::{Host, Json, OriginalUri}, http::{header::HeaderMap, Method}, Router, }; use clap::Parser; -use serde::Serialize; +use serde::{Deserialize, Serialize}; use serde_json::Value; use std::collections::BTreeMap; use tower_http::trace; -use tracing::{Level, info, warn}; +use tracing::{info, warn, Level}; #[derive(Parser)] #[command(author, version, about, long_about = None)] @@ -22,7 +22,7 @@ struct CliArgs { ips: String, } -#[derive(Serialize)] +#[derive(Serialize, Deserialize, Debug, PartialEq)] struct EchoResponse { method: String, path: String, @@ -37,7 +37,7 @@ async fn echo_request( original_uri: OriginalUri, host: Host, header_map: HeaderMap, - body: Option> + body: Option>, ) -> Json { let method = method.to_string(); let host = host.0; @@ -47,25 +47,34 @@ async fn echo_request( .map(|(name, value)| (name.to_string(), value.to_str().unwrap_or("").to_string())) .collect(); - let json_body = match body { + let body = match body { None => { warn!("Received a non-JSON body."); None - }, + } Some(Json(value)) => { info!("JSON request: {}", value.to_string()); - Some(value)}, + Some(value) + } }; let response = EchoResponse { method, host, path, headers, - body: json_body, + body, }; Json(response) } +fn app() -> Router { + Router::new().fallback(echo_request).layer( + trace::TraceLayer::new_for_http() + .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) + .on_response(trace::DefaultOnResponse::new().level(Level::INFO)), + ) +} + #[tokio::main] async fn main() { let cli_args = CliArgs::parse(); @@ -73,20 +82,136 @@ async fn main() { let listen_on = format!("{ip}:{port}", ip = listen_on.0, port = listen_on.1); // From https://stackoverflow.com/questions/75009289/how-to-enable-logging-tracing-with-axum - tracing_subscriber::fmt() - .with_max_level(Level::INFO) - .init(); - let app = Router::new().fallback(echo_request).layer( - trace::TraceLayer::new_for_http() - .make_span_with(trace::DefaultMakeSpan::new().level(Level::INFO)) - .on_response(trace::DefaultOnResponse::new().level(Level::INFO)), - ); + tracing_subscriber::fmt().with_max_level(Level::INFO).init(); info!("Starting the mirror-server to listen to {}", listen_on); let listener = tokio::net::TcpListener::bind(&listen_on) .await .unwrap_or_else(|_| panic!("Failed to binding to {}", listen_on)); - axum::serve(listener, app) + axum::serve(listener, app()) .await .expect("Server should start"); } + +#[cfg(test)] +mod tests { + use super::*; + use axum::http::{HeaderName, HeaderValue, Method, StatusCode}; + use axum_test::TestServer; + use rstest::rstest; + + #[tokio::test] + async fn handles_simple_get_request() { + let expected_headers: BTreeMap = BTreeMap::new(); + let expected_response = EchoResponse { + method: "GET".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.get("/").await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[rstest] + #[case::single_level("/test")] + #[case::multiple_level("/test/multiple/levels/")] + #[case::slash_ending("/test/")] + #[tokio::test] + async fn handles_different_urls(#[case] url: String) { + let expected_headers: BTreeMap = BTreeMap::new(); + let expected_response = EchoResponse { + method: "GET".to_string(), + path: url.clone(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.get(&url).await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[rstest] + #[case::post(Method::POST)] + #[case::put(Method::PUT)] + #[case::patch(Method::PATCH)] + #[case::delete(Method::DELETE)] + #[tokio::test] + async fn handles_different_http_methods(#[case] http_method: Method) { + let expected_headers: BTreeMap = BTreeMap::new(); + let expected_response = EchoResponse { + method: http_method.to_string(), + path: "/testing".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.method(http_method, "/testing").await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[tokio::test] + async fn handle_non_json_request() { + let mut expected_headers: BTreeMap = BTreeMap::new(); + expected_headers.insert("content-type".to_string(), "text/plain".to_string()); + let expected_response = EchoResponse { + method: "POST".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.post("/").text("hello world").await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[tokio::test] + async fn handle_json_request() { + let test_json = serde_json::json!({"hello": "world"}); + let mut expected_headers: BTreeMap = BTreeMap::new(); + expected_headers.insert("content-type".to_string(), "application/json".to_string()); + let expected_response = EchoResponse { + method: "POST".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: Some(test_json.clone()), + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server.post("/").json(&test_json).await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } + + #[tokio::test] + async fn handle_extra_headers() { + let mut expected_headers: BTreeMap = BTreeMap::new(); + expected_headers.insert("x-test-message".to_string(), "Howdy!".to_string()); + let expected_response = EchoResponse { + method: "GET".to_string(), + path: "/".to_string(), + host: "localhost".to_string(), + body: None, + headers: expected_headers, + }; + let server = TestServer::new(app()).unwrap(); + let response = server + .get("/") + .add_header( + HeaderName::from_static("x-test-message"), + HeaderValue::from_static("Howdy!"), + ) + .await; + response.assert_status(StatusCode::OK); + response.assert_json::(&expected_response); + } +} -- 2.40.1 From 0ab408fbb04bedc03680a0162218b5e27f9ef141 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Pu=C5=82a?= Date: Wed, 21 Feb 2024 21:44:18 -0500 Subject: [PATCH 07/15] Clean up code and add plans for future releases. --- README.md | 4 +++- src/main.rs | 4 ++-- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index ce3157a..17354d6 100644 --- a/README.md +++ b/README.md @@ -30,4 +30,6 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb" * [x] Add mirroring of JSON request. * [x] Add logging to server. * [x] ~~Add convenience path to access logging for a certain date / records.~~ -* [ ] Dockerize mirror-server for easier distribution. +* [ ] Create Docker image for mirror-server for easier distribution. +* [ ] Add publishing of DEB and Docker image to DroneCI. +* [ ] Add OpenAPI/Swagger UI diff --git a/src/main.rs b/src/main.rs index fde7472..95c8ff1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -35,12 +35,12 @@ struct EchoResponse { async fn echo_request( method: Method, original_uri: OriginalUri, - host: Host, + Host(host): Host, header_map: HeaderMap, body: Option>, ) -> Json { let method = method.to_string(); - let host = host.0; + let host = host; let path = original_uri.path().to_string(); let headers = header_map .iter() -- 2.40.1 From 5e390951f05e3b5611cadbe3474f3125b27d179a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Pu=C5=82a?= Date: Wed, 21 Feb 2024 21:49:55 -0500 Subject: [PATCH 08/15] Add more plans to the TODO list. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 17354d6..f979b80 100644 --- a/README.md +++ b/README.md @@ -33,3 +33,5 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb" * [ ] Create Docker image for mirror-server for easier distribution. * [ ] Add publishing of DEB and Docker image to DroneCI. * [ ] Add OpenAPI/Swagger UI +* [ ] Add documentation to the API. +* [ ] Publish crate on . -- 2.40.1 From 055aad7a900051adfb50a913998d5392930cf13a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Pu=C5=82a?= Date: Wed, 21 Feb 2024 23:17:17 -0500 Subject: [PATCH 09/15] Add a Dockerfile and initial DroneCI configuration. --- .dockerignore | 4 ++++ .drone.yml | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++ Dockerfile | 38 ++++++++++++++++++++++++++++++++++ README.md | 6 +++--- 4 files changed, 102 insertions(+), 3 deletions(-) create mode 100644 .dockerignore create mode 100644 .drone.yml create mode 100644 Dockerfile diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..e3c9650 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +target/ +Cargo.lock +**/*.rs.bk +.idea diff --git a/.drone.yml b/.drone.yml new file mode 100644 index 0000000..941141d --- /dev/null +++ b/.drone.yml @@ -0,0 +1,57 @@ +--- +kind: pipeline +type: docker +name: mirror-server + +steps: + - name: create-build-image + image: plugins/docker + settings: + username: + from_secret: docker-username + password: + from_secret: docker-password + registry: code.birch-tree.net + repo: code.birch-tree.net/dorian/mirror-server + target: BUILD + tags: + - build + cache_from: + - code.birch-tree.net/dorian/mirror-server:build + + - name: test + image: code.birch-tree.net/dorian/mirror-server:build + commands: + - cargo test + depends_on: + - create-build-image + + - name: create-release-image + image: plugins/docker + settings: + username: + from_secret: docker-username + password: + from_secret: docker-password + registry: code.birch-tree.net + repo: code.birch-tree.net/dorian/mirror-server + tags: + - 0.3.0 + - latest + cache_from: + - code.birch-tree.net/dorian/mirror-server:latest + - code.birch-tree.net/dorian/mirror-server:build + depends_on: + - test + + - name: create-debian-package + image: code.birch-tree.net/dorian/mirror-server:build + commands: + - cargo deb +# - TODO: Add a publish step based on the publish-deb.sh + depends_on: + - test + + +image_pull_secrets: + - docker-config diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..39f5973 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,38 @@ +FROM rust:1.76 AS BUILD + +ENV APP_NAME=mirror-server +ENV APP_HOME=/srv/${APP_NAME} +RUN apt update \ + && apt install -y curl \ + && cargo install cargo-deb + +# Setup working env. +RUN mkdir -p ${APP_HOME} +WORKDIR ${APP_HOME} + +# Create build target cache. +RUN USER=root cargo init --bin . +COPY ["Cargo.toml", "Cargo.lock", "./"] +RUN cargo build \ + && cargo build --tests \ + && cargo build --release \ + && rm src/*.rs + +# Bring in the source +COPY ["src", "./src/"] + +# Build the example API. +RUN cargo build --release + +# Create the minimal server image. +FROM debian:buster-slim AS SERVER + +ENV APP_NAME=mirror-server +ENV APP_HOME=/srv/${APP_NAME} +RUN apt update + +RUN mkdir -p ${APP_HOME} +WORKDIR ${APP_HOME} + +COPY --from=BUILD ${APP_HOME}/target/release/${APP_NAME} /usr/local/bin/ +CMD ${APP_NAME} \ No newline at end of file diff --git a/README.md b/README.md index f979b80..92c0eec 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,8 @@ A simple server for mirroring HTTP requests for testing. +[![Build Status](https://ci.birch-tree.net/api/badges/dorian/mirror-server/status.svg)](https://ci.birch-tree.net/dorian/mirror-server) + ## Getting Started * Use the latest stable version of Rust using rustup. @@ -29,9 +31,7 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb" * [x] Migrate actix to axum for easier maintainability. * [x] Add mirroring of JSON request. * [x] Add logging to server. -* [x] ~~Add convenience path to access logging for a certain date / records.~~ -* [ ] Create Docker image for mirror-server for easier distribution. +* [x] Create Docker image for mirror-server for easier distribution. * [ ] Add publishing of DEB and Docker image to DroneCI. -* [ ] Add OpenAPI/Swagger UI * [ ] Add documentation to the API. * [ ] Publish crate on . -- 2.40.1 From d4b26d9e3e153612fe28eb734a458b0fcd6767e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Pu=C5=82a?= Date: Wed, 21 Feb 2024 23:42:24 -0500 Subject: [PATCH 10/15] Fix issue with missing Cargo.lock in Dockerfile causing build failures. --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 39f5973..097a0da 100644 --- a/Dockerfile +++ b/Dockerfile @@ -12,7 +12,7 @@ WORKDIR ${APP_HOME} # Create build target cache. RUN USER=root cargo init --bin . -COPY ["Cargo.toml", "Cargo.lock", "./"] +COPY ["Cargo.toml", "./"] RUN cargo build \ && cargo build --tests \ && cargo build --release \ -- 2.40.1 From 299273c72f99f35ad95ef0fd359131003864aa64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Pu=C5=82a?= Date: Thu, 22 Feb 2024 21:06:58 -0500 Subject: [PATCH 11/15] Add support for uploading the Debian package. --- .drone.yml | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/.drone.yml b/.drone.yml index 941141d..cdc7ad5 100644 --- a/.drone.yml +++ b/.drone.yml @@ -47,8 +47,18 @@ steps: - name: create-debian-package image: code.birch-tree.net/dorian/mirror-server:build commands: - - cargo deb -# - TODO: Add a publish step based on the publish-deb.sh + - export PKG_PATH=$(cargo deb) + - export PKG_FILENAME=$(basename $PKG_PATH) + - export PKG_NAME=$(basename $PKG_PATH | awk -F _ '{print $1}') + - export PKG_VERSION=$(basename $PKG_PATH | awk -F _ '{print $2}') + - | + curl --user "${USERNAME}:${PASSWORD}" -X PUT + --upload-file "${PKG_PATH}" + "https://code.birch-tree.net/api/packages/${USERNAME}/generic/${PKG_NAME}/${PKG_VERSION}/${PKG_FILENAME}" + environment: + USERNAME: dorian + PASSWORD: + from_secret: gitea-release-password depends_on: - test -- 2.40.1 From 52aab1fae8614810d111c5f4cce2f5c39a0c2aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Pu=C5=82a?= Date: Thu, 22 Feb 2024 21:15:27 -0500 Subject: [PATCH 12/15] Fix issue with invalid environment substitution in .drone.yml --- .drone.yml | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.drone.yml b/.drone.yml index cdc7ad5..5762429 100644 --- a/.drone.yml +++ b/.drone.yml @@ -51,10 +51,12 @@ steps: - export PKG_FILENAME=$(basename $PKG_PATH) - export PKG_NAME=$(basename $PKG_PATH | awk -F _ '{print $1}') - export PKG_VERSION=$(basename $PKG_PATH | awk -F _ '{print $2}') + - echo $$PKG_FILENAME + - echo $$PKG_NAME v$$PKG_VERSION - | - curl --user "${USERNAME}:${PASSWORD}" -X PUT - --upload-file "${PKG_PATH}" - "https://code.birch-tree.net/api/packages/${USERNAME}/generic/${PKG_NAME}/${PKG_VERSION}/${PKG_FILENAME}" + curl --user "$${USERNAME}:$${PASSWORD}" -X PUT + --upload-file "$${PKG_PATH}" + "https://code.birch-tree.net/api/packages/$${USERNAME}/generic/$${PKG_NAME}/$${PKG_VERSION}/$${PKG_FILENAME}" environment: USERNAME: dorian PASSWORD: -- 2.40.1 From e87ee2fa0b14ba3528d616fda191b155a6e50219 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dorian=20Pu=C5=82a?= Date: Thu, 22 Feb 2024 22:29:16 -0500 Subject: [PATCH 13/15] Fix up the curl shell command. --- .drone.yml | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/.drone.yml b/.drone.yml index 5762429..58cb704 100644 --- a/.drone.yml +++ b/.drone.yml @@ -49,13 +49,12 @@ steps: commands: - export PKG_PATH=$(cargo deb) - export PKG_FILENAME=$(basename $PKG_PATH) + - echo $$PKG_FILENAME - export PKG_NAME=$(basename $PKG_PATH | awk -F _ '{print $1}') - export PKG_VERSION=$(basename $PKG_PATH | awk -F _ '{print $2}') - - echo $$PKG_FILENAME - echo $$PKG_NAME v$$PKG_VERSION - - | - curl --user "$${USERNAME}:$${PASSWORD}" -X PUT - --upload-file "$${PKG_PATH}" + - curl --user "$${USERNAME}:$${PASSWORD}" \ + -X PUT --upload-file "$${PKG_PATH}" \ "https://code.birch-tree.net/api/packages/$${USERNAME}/generic/$${PKG_NAME}/$${PKG_VERSION}/$${PKG_FILENAME}" environment: USERNAME: dorian -- 2.40.1 From 0482a50317dfed0fa1da9cc9cf4b603740fd0b97 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Fri, 23 Feb 2024 14:20:42 -0500 Subject: [PATCH 14/15] Simplify running the publishing step. --- .drone.yml | 11 +---------- publish-deb.sh | 40 ++++++++++++++++++++++------------------ 2 files changed, 23 insertions(+), 28 deletions(-) diff --git a/.drone.yml b/.drone.yml index 58cb704..c398f79 100644 --- a/.drone.yml +++ b/.drone.yml @@ -47,15 +47,7 @@ steps: - name: create-debian-package image: code.birch-tree.net/dorian/mirror-server:build commands: - - export PKG_PATH=$(cargo deb) - - export PKG_FILENAME=$(basename $PKG_PATH) - - echo $$PKG_FILENAME - - export PKG_NAME=$(basename $PKG_PATH | awk -F _ '{print $1}') - - export PKG_VERSION=$(basename $PKG_PATH | awk -F _ '{print $2}') - - echo $$PKG_NAME v$$PKG_VERSION - - curl --user "$${USERNAME}:$${PASSWORD}" \ - -X PUT --upload-file "$${PKG_PATH}" \ - "https://code.birch-tree.net/api/packages/$${USERNAME}/generic/$${PKG_NAME}/$${PKG_VERSION}/$${PKG_FILENAME}" + - ./publish-deb.sh environment: USERNAME: dorian PASSWORD: @@ -63,6 +55,5 @@ steps: depends_on: - test - image_pull_secrets: - docker-config diff --git a/publish-deb.sh b/publish-deb.sh index aee0fff..8f3fa6a 100755 --- a/publish-deb.sh +++ b/publish-deb.sh @@ -1,22 +1,26 @@ -#!/usr/bin/env bash +#!/usr/bin/bash -read -r -p "Username: " USERNAME -read -r -s -p "Password: " PASSWORD - -_pkg_name=mirror-server -_pkg_version=0.2.0 -_deb_file="${_pkg_name}_${_pkg_version}_amd64.deb" -_deb_path="target/debian" -_gitea_server="code.birch-tree.net" - -if [[ ! -f "${_deb_path}/${_deb_file}" ]]; -then - echo "Run cargo deb first!" - exit 1 +if [[ -z "${USERNAME}" ]]; then + echo "Set the USERNAME for Gitea" + exit 1 fi -curl --user "${USERNAME}:${PASSWORD}" \ - --upload-file "${_deb_path}/${_deb_file}" \ - -X PUT \ - "https://${_gitea_server}/api/packages/${USERNAME}/generic/${_pkg_name}/${_pkg_version}/${_deb_file}" +if [[ -z "${PASSWORD}" ]]; then + echo "Set the PASSWORD for Gitea" + exit 1 +fi + +echo 'Create the Debian package...' + +pkg_full_path=$(cargo deb) +pkg_filename=$(basename "${pkg_full_path}") +pkg_name=$(echo "${pkg_filename}" | awk -F _ '{print $1}') +pkg_version=$(echo "${pkg_filename}" | awk -F _ '{print $2}') + +gitea_server="code.birch-tree.net" + +curl --user "${USERNAME}:${PASSWORD}" \ + --upload-file "${pkg_full_path}" \ + -X PUT \ + "https://${gitea_server}/api/packages/${USERNAME}/generic/${pkg_name}/${pkg_version}/${pkg_filename}" -- 2.40.1 From b2a605415422e189f3ce0b9bd6fd481a336211e0 Mon Sep 17 00:00:00 2001 From: Dorian Pula Date: Fri, 23 Feb 2024 14:29:48 -0500 Subject: [PATCH 15/15] Update README and improve publishing script. --- README.md | 2 +- publish-deb.sh | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 92c0eec..c165ec7 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,6 @@ sudo dpkg -i "mirror-server-${VERSION}_amd64.deb" * [x] Add mirroring of JSON request. * [x] Add logging to server. * [x] Create Docker image for mirror-server for easier distribution. -* [ ] Add publishing of DEB and Docker image to DroneCI. +* [x] Add publishing of DEB and Docker image to DroneCI. * [ ] Add documentation to the API. * [ ] Publish crate on . diff --git a/publish-deb.sh b/publish-deb.sh index 8f3fa6a..b5b23aa 100755 --- a/publish-deb.sh +++ b/publish-deb.sh @@ -21,6 +21,8 @@ gitea_server="code.birch-tree.net" curl --user "${USERNAME}:${PASSWORD}" \ --upload-file "${pkg_full_path}" \ + --silent \ -X PUT \ "https://${gitea_server}/api/packages/${USERNAME}/generic/${pkg_name}/${pkg_version}/${pkg_filename}" +echo "Published ${pkg_name} v${pkg_version} ===> ${pkg_filename}" -- 2.40.1