{"id":15102854,"url":"https://github.com/st4s1k/scenario-rs","last_synced_at":"2026-04-10T02:20:40.998Z","repository":{"id":253032428,"uuid":"842248868","full_name":"st4s1k/scenario-rs","owner":"st4s1k","description":"Rust SSH automation tool","archived":false,"fork":false,"pushed_at":"2025-05-16T20:40:08.000Z","size":27369,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-05-16T21:24:36.637Z","etag":null,"topics":["angular","automation","cicd","rust","ssh","tauri"],"latest_commit_sha":null,"homepage":"","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/st4s1k.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2024-08-14T01:07:16.000Z","updated_at":"2025-05-16T20:40:11.000Z","dependencies_parsed_at":"2024-08-14T03:32:23.779Z","dependency_job_id":"8871d812-a4d4-4003-ab19-1d919e11b089","html_url":"https://github.com/st4s1k/scenario-rs","commit_stats":{"total_commits":71,"total_committers":2,"mean_commits":35.5,"dds":"0.21126760563380287","last_synced_commit":"f82a13dff063c0a58811314af4afa04398aa08c0"},"previous_names":["st4s1k/deploy-rs","st4s1k/scenario-rs"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/st4s1k/scenario-rs","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st4s1k%2Fscenario-rs","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st4s1k%2Fscenario-rs/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st4s1k%2Fscenario-rs/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st4s1k%2Fscenario-rs/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/st4s1k","download_url":"https://codeload.github.com/st4s1k/scenario-rs/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/st4s1k%2Fscenario-rs/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":262068629,"owners_count":23253841,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","automation","cicd","rust","ssh","tauri"],"created_at":"2024-09-25T19:08:24.520Z","updated_at":"2026-04-10T02:20:40.989Z","avatar_url":"https://github.com/st4s1k.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# scenario-rs\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) or [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)\n\n\u003ctable\u003e\n\u003ctr\u003e\u003ctd\u003ePublish\u003c/td\u003e\u003ctd\u003e\u003ca href=\"https://github.com/st4s1k/scenario-rs/actions/workflows/scenario-rs.yml\"\u003e\u003cimg src=\"https://github.com/st4s1k/scenario-rs/actions/workflows/scenario-rs.yml/badge.svg\" alt=\"publish\"\u003e\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eRust Coverage\u003c/td\u003e\u003ctd\u003e\u003ca href=\"https://codecov.io/gh/st4s1k/scenario-rs\"\u003e\u003cimg src=\"https://codecov.io/gh/st4s1k/scenario-rs/graph/badge.svg?flag=rust\" alt=\"Rust Coverage\"\u003e\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003eAngular Coverage\u003c/td\u003e\u003ctd\u003e\u003ca href=\"https://codecov.io/gh/st4s1k/scenario-rs\"\u003e\u003cimg src=\"https://codecov.io/gh/st4s1k/scenario-rs/graph/badge.svg?flag=angular\" alt=\"Angular Coverage\"\u003e\u003c/a\u003e\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\nA powerful automation tool for executing remote commands and transferring files via SSH. It uses configuration files to define execution scenarios, making system administration and deployment tasks repeatable and reliable.\n\n## Features\n\n- **Scenario Configuration**: Define your tasks in TOML files with inheritance support\n- **Remote Command Execution**: Run commands on remote servers with sudo support\n- **File Transfer**: Copy files to remote servers via SFTP\n- **Variable Substitution**: Use variables in your commands and file paths\n- **Error Recovery**: Define fallback tasks to execute when operations fail\n- **Path Handling**: Special handling for file paths with automatic basename extraction\n- **Progress Tracking**: Monitor execution progress with detailed feedback\n- **GUI, TUI \u0026 CLI Interfaces**: Choose between a graphical interface, terminal UI, or command-line tool\n\n## Usage\n\n### Configuration Files\n\nScenario configurations are defined in TOML files:\n\n```toml\n# Basic structure for a scenario configuration\n[credentials]\nusername = \"your-username\" # will be added to the variables\npassword = \"your-password\" # optional, will use SSH agent if not provided\n\n[server]\nhost = \"your-server.example.com\" # required\nport = \"22\" # optional, default is 22\n\n[execute]\n# Define the execution order of tasks\nsteps = [\n  { task = \"deploy_app\" },\n  { task = \"extract_app\" },\n  { task = \"copy_config\", on-fail = [\"rollback_deployment\"] }  # With error recovery\n]\n\n# Variables that must be provided by the user\n[variables.required]\napp_archive = { type = \"Path\", label = \"Application Archive\" }\ndeployment_env = { type = \"String\", label = \"Environment\" }\ntimestamp = { type = \"Timestamp\", label = \"Deployment Time\", format = \"%Y-%m-%dT%H%M%S%:z\", read_only = true }\n\n# Define variables to be used in commands and file paths\n[variables.defined]\napp_name = \"myapp\"\napp_version = \"1.0.0\"\nremote_app_path = \"/opt/{app_name}\"\n\n# Define tasks that can be referenced in execution steps\n[tasks.deploy_app]\ntype = \"RemoteSudo\"\ndescription = \"Deploy application\"\ncommand = \"mkdir -p {remote_app_path} \u0026\u0026 cp /tmp/{basename:app_archive} {remote_app_path}/\"\nerror_message = \"Failed to deploy application\"\n\n[tasks.extract_app]\ntype = \"RemoteSudo\"\ndescription = \"Extract application archive\"\ncommand = \"tar -xzf {remote_app_path}/{basename:app_archive} -C {remote_app_path}\"\nerror_message = \"Failed to extract application\"\n\n[tasks.copy_config]\ntype = \"SftpCopy\"\ndescription = \"Copy configuration file\"\nsource_path = \"config/{deployment_env}.conf\"\ndestination_path = \"{remote_app_path}/config.conf\"\nerror_message = \"Failed to copy configuration\"\n\n[tasks.rollback_deployment]\ntype = \"RemoteSudo\"\ndescription = \"Rollback failed deployment\"\ncommand = \"rm -rf {remote_app_path}/*\"\nerror_message = \"Failed to rollback deployment\"\n```\n\n### Variable Types\n\nThe application supports different variable types:\n\n- **String**: Regular text input\n- **Path**: File path with special handling (automatically extracts basename)\n- **Timestamp**: Automatically generated timestamp with specified format\n\n### Inheritance\n\nYou can split your configuration across multiple files and use inheritance:\n\n#### Parent file (base.toml)\n```toml\n[credentials]\nusername = \"default-user\"\n\n[server]\nhost = \"default-host\"\nport = \"22\"\n\n[variables.required]\ntimestamp = { type = \"Timestamp\", label = \"Deployment Time\", format = \"%Y-%m-%d\", read_only = true }\n\n[variables.defined]\napp_name = \"default-app\"\n```\n\n#### Child file (specific.toml)\n```toml\nparent = \"base.toml\"  # Will inherit and override from parent\n\n[credentials]\nusername = \"specific-user\"\n\n[variables.required]\nenv_name = { type = \"String\", label = \"Environment Name\" }\n\n[variables.defined]\napp_version = \"1.0.0\"  # Adds new variable while keeping app_name from parent\n```\n\n## GUI\n\nThe GUI provides a modern Tauri-based interface for managing and executing scenarios:\n\n### Features\n\n- **Configuration Management**: Load, validate, and execute scenario configurations\n- **Variable Management**: Set and update required variables with type-specific controls\n- **Real-time Execution**: Monitor scenario execution with step-by-step progress\n- **State Persistence**: Save and restore application state between sessions\n- **Task \u0026 Step Visualization**: Visual representation of scenario tasks and steps\n- **Detailed Logging**: View detailed execution logs with filtering options\n- **Variable Resolution**: See how variables are resolved during execution\n\n### Interface Components\n\n- **Configuration Loader**: Open dialog for selecting TOML configuration files\n- **Variable Editor**: Type-appropriate input fields for required variables\n- **Execution Panel**: Control execution and view real-time progress\n- **Log Viewer**: Structured view of execution events and messages\n- **Task Explorer**: Hierarchical view of tasks and their relationships\n- **Variables Inspector**: View all defined and resolved variables\n\n## TUI\n\nThe TUI provides an interactive terminal interface for selecting configs, filling in variables, and monitoring execution — no desktop environment required.\n\n```\nscenario-rs-tui [--config-path \u003cpath-to-config.toml\u003e]\n```\n\n### Features\n\n- **File Browser**: Browse and select TOML configuration files interactively\n- **Variable Form**: Fill in required variables with type-aware input (includes file picker for Path variables)\n- **Live Execution View**: Monitor step-by-step progress with output and error details\n- **Keyboard-Driven**: Fully navigable with keyboard shortcuts\n\n### Keyboard Shortcuts\n\n| Screen | Key | Action |\n|---|---|---|\n| File Browser | `↑/↓` | Navigate entries |\n| File Browser | `Enter` | Open directory / confirm file |\n| File Browser | `Backspace` | Go to parent directory |\n| File Browser | `Esc` | Cancel |\n| Variables | `Tab/↑/↓` | Navigate fields |\n| Variables | `Ctrl+B` | Open file picker (Path fields) |\n| Variables | `Ctrl+D` | Toggle debug mode |\n| Variables | `Enter` | Start execution |\n| Variables | `Esc` | Quit |\n| Executing | `↑/↓` | Select step |\n| Executing | `PgUp/PgDn` | Scroll output |\n| Done | `q/Esc` | Quit |\n| Done | `r` | Re-run same scenario |\n| Done | `n` | Pick new scenario |\n\n## CLI\n\nFor automation scripts or CI/CD pipelines, use the command-line interface:\n\n```\nscenario-rs-cli --config-path \u003cpath-to-config.toml\u003e [options]\n```\n\n### Command Line Arguments:\n\n```\nUsage: scenario-rs-cli [OPTIONS] --config-path \u003cTOML_FILE\u003e\n\nOptions:\n  -c, --config-path \u003cTOML_FILE\u003e                Path to the TOML file containing the scenario configuration\n  -l, --log-level \u003cLOG_LEVEL\u003e                  Log level for the application [default: INFO]\n  -r, --required-variables \u003cREQUIRED_VARIABLES\u003e  Required variables in the format KEY=VALUE\n  -h, --help                                   Print help\n  -V, --version                                Print version\n```\n\n#### Examples\n\nBasic execution:\n```\nscenario-rs-cli -c ./example_configs/example-scenario.toml\n```\n\nWith required variables:\n```\nscenario-rs-cli -c ./example_configs/deploy-scenario.toml -r app_version=1.2.3 -r env=production\n```\n\nWith custom log level:\n```\nscenario-rs-cli -c ./example_configs/example-scenario.toml -l debug\n```\n\n## GUI Demo\n\n[![demo](demo/demo_video.mp4)](https://github.com/user-attachments/assets/035dcca9-293b-41ea-a6ec-bfb94d922e63)\n\n## Screenshots\n\n![screenshot](demo/screenshot_0.png)\n\n\u003cdetails\u003e\n  \u003csummary\u003e\u003cb\u003e❗click here to view more screenshots❗\u003cb\u003e\u003c/summary\u003e\n\n  \u003ch2\u003eVariables\u003c/h2\u003e\n\n  ![screenshot](demo/screenshot_1.png)\n\n  \u003ch2\u003eTasks\u003c/h2\u003e\n\n  ![screenshot](demo/screenshot_2.png)\n\n  \u003ch2\u003eSteps\u003c/h2\u003e\n\n  ![screenshot](demo/screenshot_3.png)\n\n  \u003ch2\u003eExecution progress\u003c/h2\u003e\n\n  ![screenshot](demo/screenshot_4.png)\n\n  ![screenshot](demo/screenshot_5.png)\n\n\u003c/details\u003e\n\n## Build with just\n\nAll build tasks can be run from the project root using [just](https://github.com/casey/just).\n\n### Setup\n\n```\ncargo install just\n```\n\n### Available Recipes\n\nRun `just` to list all available recipes.\n\n| Command | Description |\n|---|---|\n| `just` | List all available recipes |\n| `just check` | Run `cargo check` on the workspace |\n| `just build` | Build the workspace (debug) |\n| `just build-release` | Build the workspace (release) |\n| `just test` | Run Rust tests with coverage (requires [cargo-tarpaulin](https://github.com/xd009642/tarpaulin)) |\n| `just ng-test` | Run Angular unit tests with coverage |\n| `just test-all` | Run all tests with coverage (Rust + Angular) |\n| `just npm-install` | Install frontend dependencies |\n| `just ng-build` | Build Angular frontend |\n| `just tui-run` | Run TUI in development mode |\n| `just tui-build` | Build TUI (release) |\n| `just tauri-dev` | Run GUI in development mode |\n| `just tauri-build` | Build GUI (release) |\n| `just tauri-build-debug` | Build GUI (debug) |\n| `just build-all` | Build everything (Rust + GUI debug) |\n| `just build-all-release` | Build everything (Rust + GUI release) |\n| `just verify` | Full verification: check + all tests + Angular build |\n| `just version` | Show current version |\n| `just bump-version x.y.z` | Set version across all packages |\n\n## DIY\n\n### ✨ [gui]\n\n❗ **go to:**\n\n```\n\u003ccloned-dir\u003e/scenario-rs/gui/\n```\n\n### ✨ [gui.dev] 🚧\n\n▶️ **run:**\n\n```\nnpm run tauri dev\n```\n\n🛠️ **build:**\n\n```\nnpm run tauri build -- --debug\n```\n\n⚡ **run executable:**\n\n```\n\u003ccloned-dir\u003e/scenario-rs/target/debug/scenario-rs.exe\n```\n\n### ✨ [gui.release] 🎁\n\n🛠️ **build:**\n\n```\nnpm run tauri build\n```\n\n⚡ **run executable:**\n\n```\n\u003ccloned-dir\u003e/scenario-rs/target/release/scenario-rs.exe\n```\n\n### �️ [tui]\n\n▶️ **run:**\n\n```\ncargo run -p scenario-rs-tui\n```\n\nor with a config:\n\n```\ncargo run -p scenario-rs-tui -- -c ./example_configs/example-scenario.toml\n```\n\n🛠️ **build (release):**\n\n```\ncargo build -p scenario-rs-tui --release\n```\n\n⚡ **run executable:**\n\n```\n\u003ccloned-dir\u003e/scenario-rs/target/release/scenario-rs-tui.exe\n```\n\n### �📟 [cli]\n\n❗ **go to:**\n\n```\n\u003ccloned-dir\u003e/scenario-rs/cli\n```\n\n### 📟 [cli.dev] 🚧\n\n▶️ **run:**\n\n```\ncargo run -- -c ./example_configs/example-scenario.toml\n```\n\n🛠️ **build:**\n\n```\ncargo build\n```\n\n⚡ **run executable:**\n\n```\n\u003ccloned-dir\u003e/scenario-rs/target/debug/scenario-rs-cli.exe --config-path ./example_configs/example-scenario.toml\n```\n\nor\n\n```\n\u003ccloned-dir\u003e/scenario-rs/target/debug/scenario-rs-cli.exe -c ./example_configs/example-scenario.toml\n```\n\n### 📟 [cli.release] 🎁\n\n🛠️ **build:**\n\n```\ncargo build --release\n```\n\n⚡ **run executable:**\n\n```\n\u003ccloned-dir\u003e/scenario-rs/target/release/scenario-rs-cli.exe --config-path ./example_configs/example-scenario.toml\n```\n\nor\n\n```\n\u003ccloned-dir\u003e/scenario-rs/target/release/scenario-rs-cli.exe -c ./example_configs/example-scenario.toml\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fst4s1k%2Fscenario-rs","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fst4s1k%2Fscenario-rs","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fst4s1k%2Fscenario-rs/lists"}