diff --git a/clippy.toml b/.clippy.toml similarity index 98% rename from clippy.toml rename to .clippy.toml index 1351e239..df7de270 100644 --- a/clippy.toml +++ b/.clippy.toml @@ -18,4 +18,4 @@ # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -# SOFTWARE. +# SOFTWARE. \ No newline at end of file diff --git a/.github/workflows/cargo.yml b/.github/workflows/cargo.yml index 0667a239..8b66c443 100644 --- a/.github/workflows/cargo.yml +++ b/.github/workflows/cargo.yml @@ -34,6 +34,12 @@ concurrency: env: RUSTFLAGS: "-Dwarnings" jobs: + clippy: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + - run: cargo clippy --all-targets --all-features + - run: cargo fmt --check build: strategy: fail-fast: false @@ -42,11 +48,6 @@ jobs: runs-on: ${{ matrix.os }} steps: - uses: actions/checkout@v4 + - run: cargo clean - run: cargo test - - run: cargo test --release - run: cargo fmt --check - clippy: - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v4 - - run: cargo clippy --all-targets --all-features diff --git a/Cargo.toml b/Cargo.toml index c23b6b20..7a106f78 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -19,25 +19,9 @@ # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE # SOFTWARE. - -[package] -name = "fakehub" -version = "0.0.0" -edition = "2021" -license = "MIT" -description = """ -GitHub API Server Stub. Fully functional fake version of a GitHub API that -supports all the features and works locally, with no connection to GitHub at -all. -""" -authors = ["Aliaksei BialĂ­auski ", "Ivanchuk Ivan "] - -[dependencies] -anyhow = "1.0.86" -serde = { version = "1.0.203", features = ["derive"] } -serde_json = "1.0.117" -tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros", "fs"] } -axum = "0.7.5" -log = { version = "0.4.21", features = [] } -env_logger = "0.11.3" -tempdir = "0.3.7" +[workspace] +members = [ + "server", + "cli", +] +resolver = "1" diff --git a/cli/Cargo.toml b/cli/Cargo.toml new file mode 100644 index 00000000..1208f733 --- /dev/null +++ b/cli/Cargo.toml @@ -0,0 +1,39 @@ +# The MIT License (MIT) +# +# Copyright (c) 2024 Aliaksei Bialiauski +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +[package] +name = "cli" +version = "0.1.0" +edition = "2021" + +[[bin]] +name = "cli" +path = "src/main.rs" + +[dev-dependencies] +assert_cmd = "2.0.14" + +[dependencies] +anyhow = "1.0.86" +clap = { version = "4.5.7", features = ["derive"] } +server = { path = "../server" } +tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros"] } +log = "0.4.21" diff --git a/cli/src/args.rs b/cli/src/args.rs new file mode 100644 index 00000000..f318fc80 --- /dev/null +++ b/cli/src/args.rs @@ -0,0 +1,33 @@ +// The MIT License (MIT) +// +// Copyright (c) 2024 Aliaksei Bialiauski +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +use clap::Parser; + +// @todo #13:15min Handle port argument +// We should process the port argument and +// pass it to the server on `start` command. +// Start command should be added also with clap +#[derive(Parser, Debug)] +pub(crate) struct Args { + /// The port to run + #[arg(short, long, default_value_t = 3000)] + pub(crate) port: usize, +} diff --git a/src/main.rs b/cli/src/main.rs similarity index 74% rename from src/main.rs rename to cli/src/main.rs index 50bb2df1..73b8ccc4 100644 --- a/src/main.rs +++ b/cli/src/main.rs @@ -19,17 +19,12 @@ // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. -use axum::routing::get; -use axum::Router; -mod routes; -mod xml; -use crate::routes::home; -use crate::xml::storage::touch_storage; +use clap::Parser; -#[tokio::main] -async fn main() { - touch_storage(Some("fakehub.xml")); - let app = Router::new().route("/", get(home::home)); - let listener = tokio::net::TcpListener::bind("0.0.0.0:3000").await.unwrap(); - axum::serve(listener, app).await.unwrap(); +use crate::args::Args; + +mod args; + +fn main() { + let _ = Args::parse(); } diff --git a/cli/tests/integration_test.rs b/cli/tests/integration_test.rs new file mode 100644 index 00000000..5ec3e2ab --- /dev/null +++ b/cli/tests/integration_test.rs @@ -0,0 +1,36 @@ +// The MIT License (MIT) +// +// Copyright (c) 2024 Aliaksei Bialiauski +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +use std::str; + +use anyhow::Result; +use assert_cmd::Command; + +#[test] +fn should_output_help() -> Result<()> { + env!("CARGO_BIN_EXE_cli"); + let assertion = Command::cargo_bin("cli")?.arg("--help").assert(); + let bytes = assertion.get_output().stdout.as_slice(); + let output = str::from_utf8(bytes)?; + assert!(output.contains("The port to run")); + assert!(output.contains("3000")); + Ok(()) +} diff --git a/cli/tests/mod.rs b/cli/tests/mod.rs new file mode 100644 index 00000000..42e5db33 --- /dev/null +++ b/cli/tests/mod.rs @@ -0,0 +1,22 @@ +// The MIT License (MIT) +// +// Copyright (c) 2024 Aliaksei Bialiauski +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +mod integration_test; diff --git a/server/Cargo.toml b/server/Cargo.toml new file mode 100644 index 00000000..e9d6b4b1 --- /dev/null +++ b/server/Cargo.toml @@ -0,0 +1,45 @@ +# The MIT License (MIT) +# +# Copyright (c) 2024 Aliaksei Bialiauski +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included +# in all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +# SOFTWARE. +[package] +name = "server" +version = "0.0.0" +edition = "2021" +license = "MIT" +description = """ +GitHub API Server Stub. Fully functional fake version of a GitHub API that +supports all the features and works locally, with no connection to GitHub at +all. +""" +authors = ["Aliaksei BialĂ­auski ", "Ivanchuk Ivan "] + +[lib] +path = "src/lib.rs" + +[dependencies] +anyhow = "1.0.86" +serde = { version = "1.0.203", features = ["derive"] } +serde_json = "1.0.117" +tokio = { version = "1.0.0", features = ["rt", "rt-multi-thread", "macros", "fs"] } +axum = "0.7.5" +log = { version = "0.4.21", features = [] } +env_logger = "0.11.3" +tempdir = "0.3.7" diff --git a/resources/home.json b/server/resources/home.json similarity index 100% rename from resources/home.json rename to server/resources/home.json diff --git a/server/src/lib.rs b/server/src/lib.rs new file mode 100644 index 00000000..5cf132ee --- /dev/null +++ b/server/src/lib.rs @@ -0,0 +1,72 @@ +// The MIT License (MIT) +// +// Copyright (c) 2024 Aliaksei Bialiauski +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +use std::io; + +use anyhow::Result; +use axum::routing::get; +use axum::Router; +use tokio::net::TcpListener; + +use crate::routes::home; +use crate::xml::storage::touch_storage; + +mod routes; +mod xml; + +#[derive(Default)] +pub struct Server { + port: usize, +} + +impl Server { + pub fn new(port: usize) -> Server { + Server { port } + } +} + +impl Server { + pub async fn start(self) -> Result<()> { + touch_storage(Some("fakehub.xml")); + let app: Router = Router::new().route("/", get(home::home)); + let addr: String = format!("0.0.0.0:{}", self.port); + let started: io::Result = TcpListener::bind(addr.clone()).await; + match started { + Ok(listener) => axum::serve(listener, app).await?, + Err(err) => { + panic!("Can't bind address {}: '{}'", addr.clone(), err) + } + }; + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use anyhow::Result; + + #[test] + fn creates_the_server() -> Result<()> { + let server = crate::Server::new(1234); + assert_eq!(server.port, 1234); + Ok(()) + } +} diff --git a/src/routes/home.rs b/server/src/routes/home.rs similarity index 100% rename from src/routes/home.rs rename to server/src/routes/home.rs diff --git a/src/routes/mod.rs b/server/src/routes/mod.rs similarity index 100% rename from src/routes/mod.rs rename to server/src/routes/mod.rs diff --git a/src/routes/rs_err.rs b/server/src/routes/rs_err.rs similarity index 100% rename from src/routes/rs_err.rs rename to server/src/routes/rs_err.rs diff --git a/src/xml/mod.rs b/server/src/xml/mod.rs similarity index 100% rename from src/xml/mod.rs rename to server/src/xml/mod.rs diff --git a/src/xml/storage.rs b/server/src/xml/storage.rs similarity index 94% rename from src/xml/storage.rs rename to server/src/xml/storage.rs index 1d7cff2f..165c57ff 100644 --- a/src/xml/storage.rs +++ b/server/src/xml/storage.rs @@ -39,12 +39,13 @@ pub fn touch_storage(path: Option<&str>) -> File { #[cfg(test)] mod tests { + use anyhow::Result; use tempdir::TempDir; use crate::xml::storage::touch_storage; #[test] - fn creates_xml_storage() -> anyhow::Result<()> { + fn creates_xml_storage() -> Result<()> { let temp = TempDir::new("temp")?; let path = temp.path().join("fakehub.xml"); let storage = path.to_str(); @@ -58,7 +59,7 @@ mod tests { } #[test] - fn creates_xml_storage_with_different_name() -> anyhow::Result<()> { + fn creates_xml_storage_with_different_name() -> Result<()> { let temp = TempDir::new("temp")?; let path = temp.path().join("test.xml"); let storage = path.to_str();