diff --git a/.gitignore b/.gitignore index fb0b6e93..b7fc8477 100644 --- a/.gitignore +++ b/.gitignore @@ -8,5 +8,6 @@ /example/share-services/pgweb/data/ /example/simple/data/ /example/grafana-tempo/data/ +/example/cargo-doc-live/target /.pre-commit-config.yaml diff --git a/doc/cargo-doc-live.md b/doc/cargo-doc-live.md new file mode 100644 index 00000000..725c7698 --- /dev/null +++ b/doc/cargo-doc-live.md @@ -0,0 +1,44 @@ +# cargo-doc-live + +[cargo-doc-live] is live server version of `cargo doc` ― edit Rust code, and see the docs view in your web browser update automatically. + +https://github.com/srid/cargo-doc-live/assets/3998/37378858-dda1-40fb-8f6a-f76dc857a661 + +{#start} + +## Getting started + +```nix +# In `perSystem.process-compose.` +{ + services.cargo-doc-live."cargo-doc-live1".enable = true; +} +``` + +{#port} + +### The port for `cargo doc`, the default value is 8008, while you could override it if 8008 is in use for another service. + +```nix +{ + services.cargo-doc-live."cargo-doc-live1" = { + enable = true; + projectRoot = ./.; + port = 8080; + }; +} +``` + +{#crateName} + +### The crate to use when opening docs in browser, the crate name will be derived from Cargo.toml. + +```nix +{ + services.cargo-doc-live."cargo-doc-live1" = { + enable = true; + projectRoot = ./.; + crateName = "chrono"; + }; +} +``` diff --git a/doc/services.md b/doc/services.md index cec51d9a..5364488d 100644 --- a/doc/services.md +++ b/doc/services.md @@ -4,7 +4,7 @@ short-title: Services # Supported services ->[!warning] WIP +> [!warning] WIP > Documentation for the services is still in progress. Please refer to [this issue][gh] for progress. - [[apache-kafka]]# @@ -25,5 +25,6 @@ short-title: Services - [[prometheus]]# - [[cassandra]]# - [[weaviate]]# +- [[cargo-doc-live]]# [gh]: https://github.com/juspay/services-flake/issues/132 diff --git a/example/cargo-doc-live/Cargo.lock b/example/cargo-doc-live/Cargo.lock new file mode 100644 index 00000000..33b959e2 --- /dev/null +++ b/example/cargo-doc-live/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "test" +version = "0.0.0" diff --git a/example/cargo-doc-live/Cargo.toml b/example/cargo-doc-live/Cargo.toml new file mode 100644 index 00000000..40392766 --- /dev/null +++ b/example/cargo-doc-live/Cargo.toml @@ -0,0 +1,2 @@ +[package] +name = "test" diff --git a/example/cargo-doc-live/README.md b/example/cargo-doc-live/README.md new file mode 100644 index 00000000..660666a9 --- /dev/null +++ b/example/cargo-doc-live/README.md @@ -0,0 +1,8 @@ +A demonstration of cargo-doc-live. + +To run, + +``` +cd ./example/cargo-doc-live +nix run .#cargo-doc-live +``` diff --git a/example/cargo-doc-live/flake.lock b/example/cargo-doc-live/flake.lock new file mode 100644 index 00000000..e253a45b --- /dev/null +++ b/example/cargo-doc-live/flake.lock @@ -0,0 +1,106 @@ +{ + "nodes": { + "flake-parts": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1717285511, + "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1719082008, + "narHash": "sha256-jHJSUH619zBQ6WdC21fFAlDxHErKVDJ5fpN0Hgx4sjs=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "9693852a2070b398ee123a329e68f0dab5526681", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "lastModified": 1717284937, + "narHash": "sha256-lIbdfCsf8LMFloheeE6N31+BMIeixqyQWbSr2vk79EQ=", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + }, + "original": { + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs/archive/eb9ceca17df2ea50a250b6b27f7bf6ab0186f198.tar.gz" + } + }, + "process-compose-flake": { + "locked": { + "lastModified": 1718031437, + "narHash": "sha256-+RrlkAVZx0QhyeHAGFJnjST+/7Dc3zsDU3zAKXoDXaI=", + "owner": "Platonic-Systems", + "repo": "process-compose-flake", + "rev": "9344fac44edced4c686721686a6ad904d067c546", + "type": "github" + }, + "original": { + "owner": "Platonic-Systems", + "repo": "process-compose-flake", + "type": "github" + } + }, + "root": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": "nixpkgs", + "process-compose-flake": "process-compose-flake", + "services-flake": "services-flake", + "systems": "systems" + } + }, + "services-flake": { + "locked": { + "lastModified": 1719102528, + "narHash": "sha256-wLoHpUJXVELcnFh7XgJ9m4q1Hu8WgGfrZQQHpS5eRcM=", + "owner": "juspay", + "repo": "services-flake", + "rev": "641937bc0f523405fbac4bb89c074de613dcee4d", + "type": "github" + }, + "original": { + "owner": "juspay", + "repo": "services-flake", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/example/cargo-doc-live/flake.nix b/example/cargo-doc-live/flake.nix new file mode 100644 index 00000000..b5c52783 --- /dev/null +++ b/example/cargo-doc-live/flake.nix @@ -0,0 +1,54 @@ +{ + inputs = { + nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; + flake-parts.url = "github:hercules-ci/flake-parts"; + systems.url = "github:nix-systems/default"; + process-compose-flake.url = "github:Platonic-Systems/process-compose-flake"; + services-flake.url = "github:juspay/services-flake"; + }; + outputs = inputs: + inputs.flake-parts.lib.mkFlake { inherit inputs; } { + systems = import inputs.systems; + imports = [ + inputs.process-compose-flake.flakeModule + ]; + perSystem = { self', pkgs, lib, ... }: { + process-compose."cargo-doc-live" = _: + { + tui = false; + + imports = [ + inputs.services-flake.processComposeModules.default + ]; + + preHook = '' + # Set pipefail option for safer bash + set -euo pipefail + + # Copy project root to a mutable area + export HOME="$TMP" + cp -r ${inputs.self} "$HOME"/project + chmod -R a+w "$HOME"/project + cd "$HOME"/project + ''; + + services.cargo-doc-live."cargo-doc-live1" = { + projectRoot = inputs.self; + enable = true; + port = 8009; + }; + + settings.processes.test = { + command = pkgs.writeShellApplication { + name = "cargo-doc-live-test"; + runtimeInputs = [ pkgs.curl ]; + text = '' + curl http://127.0.0.1:8009/test + ''; + }; + depends_on."cargo-doc-live1-browser-sync".condition = "process_healthy"; + }; + }; + }; + }; +} diff --git a/example/cargo-doc-live/src/main.rs b/example/cargo-doc-live/src/main.rs new file mode 100644 index 00000000..e7a11a96 --- /dev/null +++ b/example/cargo-doc-live/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/flake.nix b/flake.nix index 3dada658..f1bb27b0 100644 --- a/flake.nix +++ b/flake.nix @@ -28,6 +28,10 @@ }; dir = "./example/share-services/pgweb"; }; + cargo-doc-live-example = { + inherit overrideInputs; + dir = "./example/cargo-doc-live"; + }; test = { inherit overrideInputs; dir = "./test"; diff --git a/nix/cargo-doc-live.nix b/nix/cargo-doc-live.nix new file mode 100644 index 00000000..a3f6dcb1 --- /dev/null +++ b/nix/cargo-doc-live.nix @@ -0,0 +1,91 @@ +{ pkgs, lib, name, config, ... }: +let + inherit (lib) types; +in +{ + options = { + enable = lib.mkEnableOption name; + + projectRoot = lib.mkOption { + type = types.path; + description = "Path to the cargo project root"; + default = ./.; + }; + + port = lib.mkOption { + type = types.port; + description = "The port for 'cargo doc'"; + default = 8008; + }; + + crateName = lib.mkOption { + type = types.str; + description = "The crate to use when opening docs in browser"; + default = builtins.replaceStrings [ "-" ] [ "_" ] + ((lib.trivial.importTOML "${config.projectRoot}/Cargo.toml").package.name); + defaultText = "The crate name is derived from the Cargo.toml file"; + }; + + outputs.settings = lib.mkOption { + type = types.deferredModule; + internal = true; + readOnly = true; + default = { + processes = { + "${name}-cargo-doc" = { + command = pkgs.writeShellApplication { + name = "cargo-doc"; + runtimeInputs = with pkgs; [ cargo cargo-watch nodePackages.browser-sync ]; + text = + '' + run-cargo-doc() { + cargo doc --document-private-items --all-features + browser-sync reload --port ${toString config.port} # Trigger reload in browser + }; export -f run-cargo-doc + cargo-watch watch -s run-cargo-doc + ''; + }; + readiness_probe = { + period_seconds = 1; + failure_threshold = 100000; # 'cargo doc' can take quite a while. + exec.command = '' + # Wait for the first 'cargo doc' to have completed. + # We'll use this state to block browser-sync from starting + # and opening the URL in the browser. + ls target/doc/${config.crateName}/index.html + ''; + }; + namespace = name; + availability.restart = "on_failure"; + }; + "${name}-browser-sync" = { + command = pkgs.writeShellApplication { + name = "browser-sync"; + runtimeInputs = [ pkgs.nodePackages.browser-sync ]; + text = + '' + browser-sync start --port ${toString config.port} --ss target/doc -s target/doc \ + --startPath /${config.crateName}/ + ''; + }; + readiness_probe = { + http_get = { + scheme = "http"; + host = "localhost"; + port = config.port; + path = config.crateName; + }; + initial_delay_seconds = 15; + period_seconds = 10; + timeout_seconds = 2; + success_threshold = 1; + failure_threshold = 5; + }; + namespace = name; + depends_on."${name}-cargo-doc".condition = "process_healthy"; + }; + }; + }; + }; + }; +} diff --git a/nix/default.nix b/nix/default.nix index 1adbd7c3..45e89d24 100644 --- a/nix/default.nix +++ b/nix/default.nix @@ -22,5 +22,6 @@ in ./tempo.nix ./weaviate.nix ./searxng.nix + ./cargo-doc-live.nix ]; }