diff --git a/.github/workflows/publish-to-pages.yaml b/.github/workflows/publish-to-pages.yaml new file mode 100644 index 000000000..d9b8e6d0b --- /dev/null +++ b/.github/workflows/publish-to-pages.yaml @@ -0,0 +1,41 @@ +name: publish to github pages + +on: + push: + branches: [ main ] + +# Cancel already running jobs +concurrency: + group: publish_to_pages_${{ github.head_ref }} + cancel-in-progress: true + +# Sets permissions of the GITHUB_TOKEN to allow deployment to GitHub Pages +permissions: + contents: read + pages: write + id-token: write + +jobs: + build: + strategy: + matrix: + include: + - name: Publish website to Github Pages + runner: ubuntu-latest + environment: + name: github-pages + url: ${{ steps.setup_pages.outputs.base_url }} + name: ${{ matrix.name }} + runs-on: ${{ matrix.runner }} + steps: + - uses: actions/checkout@v4 + - name: Build website + run: cargo run -p website + - name: Setup Pages + uses: actions/configure-pages@v4 + - name: Upload pages + uses: actions/upload-pages-artifact@v3 + with: + path: 'website/root' + - name: Deploy pages + uses: actions/deploy-pages@v4 diff --git a/.gitignore b/.gitignore index 7b69c6476..218ac7692 100644 --- a/.gitignore +++ b/.gitignore @@ -10,6 +10,7 @@ /.project /docs/book /docs/mdbook_bin +/website/root /shotover-proxy/build/packages /some_local_file /test-helpers/src/connection/kafka/node/node_modules \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock index 038791f70..e1b5133b1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1622,6 +1622,12 @@ dependencies = [ "cipher", ] +[[package]] +name = "devserver_lib" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "edf215dbb8cb1409cca7645aaed35f9e39fb0a21855bba1ac48bc0334903bf66" + [[package]] name = "diff" version = "0.1.13" @@ -5804,6 +5810,16 @@ dependencies = [ "rustls-pki-types", ] +[[package]] +name = "website" +version = "0.1.0" +dependencies = [ + "anyhow", + "clap", + "devserver_lib", + "subprocess", +] + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 366e90819..f355d903e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ members = [ "custom-transforms-example", "ec2-cargo", "windsock-cloud-docker", + "website", ] resolver = "2" diff --git a/website/Cargo.toml b/website/Cargo.toml new file mode 100644 index 000000000..f05ab3de4 --- /dev/null +++ b/website/Cargo.toml @@ -0,0 +1,12 @@ +[package] +name = "website" +version = "0.1.0" +edition = "2021" +license = "Apache-2.0" +publish = false + +[dependencies] +subprocess.workspace = true +anyhow.workspace = true +devserver_lib = { version = "0.4.2", default-features = false } +clap.workspace = true diff --git a/website/src/cli.rs b/website/src/cli.rs new file mode 100644 index 000000000..411979141 --- /dev/null +++ b/website/src/cli.rs @@ -0,0 +1,10 @@ +use clap::Parser; + +/// Generates the shotover website. +#[derive(Parser, Clone)] +#[clap()] +pub struct Args { + /// As well as generating the site, serve the contents of the site over http. + #[clap(long)] + pub serve: bool, +} diff --git a/website/src/docs.rs b/website/src/docs.rs new file mode 100644 index 000000000..33fca764b --- /dev/null +++ b/website/src/docs.rs @@ -0,0 +1,32 @@ +use crate::run_command; +use anyhow::Result; +use std::{fs::create_dir_all, path::Path}; + +pub fn generate_all_docs(current_dir: &Path) -> Result<()> { + let root = current_dir.join("website").join("root"); + println!("Generating main"); + create_dir_all(root.join("docs")).unwrap(); + build_docs( + current_dir, + Path::new("docs"), + &root.join("docs").join("main"), + ); + + Ok(()) +} + +fn build_docs(current_dir: &Path, in_path: &Path, out_path: &Path) { + let temp_docs_dir = current_dir.join("target").join("temp_docs_build"); + std::fs::remove_dir_all(&temp_docs_dir).ok(); + run_command( + in_path, + "mdbook", + &["build", "--dest-dir", temp_docs_dir.to_str().unwrap()], + ) + .ok(); + + std::fs::remove_dir_all(out_path).ok(); + std::fs::rename(temp_docs_dir.join("html"), out_path).unwrap(); + + std::fs::remove_dir_all(&temp_docs_dir).ok(); +} diff --git a/website/src/main.rs b/website/src/main.rs new file mode 100644 index 000000000..519f743ac --- /dev/null +++ b/website/src/main.rs @@ -0,0 +1,76 @@ +use anyhow::{anyhow, Result}; +use clap::Parser; +use cli::Args; +use std::{path::Path, process::Command}; +use subprocess::{Exec, Redirection}; + +mod cli; +mod docs; + +fn main() { + // Set standard path to root of repo so this always runs in the same directory, regardless of where the user ran it from. + let current_dir = Path::new(env!("CARGO_MANIFEST_DIR")).parent().unwrap(); + std::env::set_current_dir(current_dir).unwrap(); + + let args = Args::parse(); + + println!("Ensuring mdbook is installed"); + // TODO: Once mdbook starts doing macos aarch64 binary releases we should download the release directly instead of compiling. + // https://github.com/rust-lang/mdBook/pull/2500 + if !Command::new("cargo") + .args(["install", "mdbook", "--version", "0.4.43"]) + .status() + .unwrap() + .success() + { + return; + } + + let root = current_dir.join("website").join("root"); + std::fs::remove_dir_all(&root).unwrap(); + std::fs::create_dir_all(&root).unwrap(); + + if let Err(err) = docs::generate_all_docs(current_dir) { + println!("{err}"); + return; + } + + if args.serve { + println!("Hosting website at: http://localhost:8000"); + + devserver_lib::run( + "localhost", + 8000, + current_dir.join("website").join("root").to_str().unwrap(), + false, + "", + ); + } else { + let out = current_dir.join("website").join("root"); + println!( + "Succesfully generated website at: file://{}", + out.to_str().unwrap() + ); + } +} + +pub fn run_command(dir: impl AsRef, command: &str, args: &[&str]) -> Result { + let data = Exec::cmd(command) + .args(args) + .cwd(dir) + .stdout(Redirection::Pipe) + .stderr(Redirection::Merge) + .capture()?; + + if data.exit_status.success() { + Ok(data.stdout_str()) + } else { + Err(anyhow!( + "command {} {:?} exited with {:?} and output:\n{}", + command, + args, + data.exit_status, + data.stdout_str() + )) + } +}