# WRKFLW [![Crates.io](https://img.shields.io/crates/v/wrkflw)](https://crates.io/crates/wrkflw) [![Rust Version](https://img.shields.io/badge/rust-1.67%2B-orange)](https://www.rust-lang.org/) [![License](https://img.shields.io/crates/l/wrkflw)](LICENSE) [![Build Status](https://img.shields.io/github/actions/workflow/status/bahdotsh/wrkflw/build.yml?branch=main)](https://github.com/bahdotsh/wrkflw/actions/workflows/build.yml) [![Downloads](https://img.shields.io/crates/d/wrkflw)](https://crates.io/crates/wrkflw) WRKFLW is a powerful command-line tool for validating and executing GitHub Actions workflows locally, without requiring a full GitHub environment. It helps developers test their workflows directly on their machines before pushing changes to GitHub. ![WRKFLW Demo](demo.gif) ## Features - **TUI Interface**: A full-featured terminal user interface for managing and monitoring workflow executions - **Validate Workflow Files**: Check for syntax errors and common mistakes in GitHub Actions workflow files with proper exit codes for CI/CD integration - **Execute Workflows Locally**: Run workflows directly on your machine using Docker or Podman containers - **Multiple Container Runtimes**: Support for Docker, Podman, and emulation mode for maximum flexibility - **Job Dependency Resolution**: Automatically determines the correct execution order based on job dependencies - **Container Integration**: Execute workflow steps in isolated containers with proper environment setup - **GitHub Context**: Provides GitHub-like environment variables and workflow commands - **Rootless Execution**: Podman support enables running containers without root privileges - **Action Support**: Supports various GitHub Actions types: - Docker container actions - JavaScript actions - Composite actions - Local actions - **Special Action Handling**: Native handling for commonly used actions like `actions/checkout` - **Reusable Workflows (Caller Jobs)**: Execute jobs that call reusable workflows via `jobs..uses` (local path or `owner/repo/path@ref`) - **Output Capturing**: View logs, step outputs, and execution details - **Parallel Job Execution**: Runs independent jobs in parallel for faster workflow execution - **Trigger Workflows Remotely**: Manually trigger workflow runs on GitHub or GitLab ## Requirements ### Container Runtime (Optional) WRKFLW supports multiple container runtimes for isolated execution: - **Docker**: The default container runtime. Install from [docker.com](https://docker.com) - **Podman**: A rootless container runtime. Perfect for environments where Docker isn't available or permitted. Install from [podman.io](https://podman.io) - **Emulation**: No container runtime required. Executes commands directly on the host system ### Podman Support Podman is particularly useful in environments where: - Docker installation is not permitted by your organization - Root privileges are not available for Docker daemon - You prefer rootless container execution - Enhanced security through daemonless architecture is desired To use Podman: ```bash # Install Podman (varies by OS) # On macOS with Homebrew: brew install podman # On Ubuntu/Debian: sudo apt-get install podman # Initialize Podman machine (macOS/Windows) podman machine init podman machine start # Use with wrkflw wrkflw run --runtime podman .github/workflows/ci.yml ``` ## Installation The recommended way to install `wrkflw` is using Rust's package manager, Cargo: ### Using Cargo Install (Recommended) ```bash cargo install wrkflw ``` ### From Source Clone the repository and build using Cargo: ```bash git clone https://github.com/bahdotsh/wrkflw.git cd wrkflw cargo build --release ``` The compiled binary will be available at `target/release/wrkflw`. ## Usage The simplest way to use WRKFLW is to navigate to your project's root directory and run: ```bash wrkflw ``` This will automatically detect and load all workflows from `.github/workflows` directory into the TUI interface. WRKFLW also provides three main command modes: ### Validating Workflow Files ```bash # Validate all workflow files in the default location (.github/workflows) wrkflw validate # Validate a specific workflow file wrkflw validate path/to/workflow.yml # Validate workflows in a specific directory wrkflw validate path/to/workflows # Validate multiple files and/or directories (GitHub and GitLab are auto-detected) wrkflw validate path/to/flow-1.yml path/to/flow-2.yml path/to/workflows # Force GitLab parsing for all provided paths wrkflw validate --gitlab .gitlab-ci.yml other.gitlab-ci.yml # Validate with verbose output wrkflw validate --verbose path/to/workflow.yml # Validate GitLab CI pipelines wrkflw validate .gitlab-ci.yml --gitlab # Disable exit codes for custom error handling (default: enabled) wrkflw validate --no-exit-code path/to/workflow.yml ``` #### Exit Codes for CI/CD Integration By default, `wrkflw validate` sets the exit code to `1` when validation fails, making it perfect for CI/CD pipelines and scripts: ```bash # In CI/CD scripts - validation failure will cause the script to exit if ! wrkflw validate; then echo "❌ Workflow validation failed!" exit 1 fi echo "✅ All workflows are valid!" # For custom error handling, disable exit codes wrkflw validate --no-exit-code if [ $? -eq 0 ]; then echo "Validation completed (check output for details)" fi ``` **Exit Code Behavior:** - `0`: All validations passed successfully - `1`: One or more validation failures detected - `2`: Command usage error (invalid arguments, file not found, etc.) ### Running Workflows in CLI Mode ```bash # Run a workflow with Docker (default) wrkflw run .github/workflows/ci.yml # Run a workflow with Podman instead of Docker wrkflw run --runtime podman .github/workflows/ci.yml # Run a workflow in emulation mode (without containers) wrkflw run --runtime emulation .github/workflows/ci.yml # Run with verbose output wrkflw run --verbose .github/workflows/ci.yml # Preserve failed containers for debugging wrkflw run --preserve-containers-on-failure .github/workflows/ci.yml ``` ### Using the TUI Interface ```bash # Open TUI with workflows from the default directory wrkflw tui # Open TUI with a specific directory of workflows wrkflw tui path/to/workflows # Open TUI with a specific workflow pre-selected wrkflw tui path/to/workflow.yml # Open TUI with Podman runtime wrkflw tui --runtime podman # Open TUI in emulation mode wrkflw tui --runtime emulation ``` ### Triggering Workflows Remotely ```bash # Trigger a workflow remotely on GitHub wrkflw trigger workflow-name --branch main --input key1=value1 --input key2=value2 # Trigger a pipeline remotely on GitLab wrkflw trigger-gitlab --branch main --variable key1=value1 --variable key2=value2 ``` ## TUI Controls The terminal user interface provides an interactive way to manage workflows: - **Tab / 1-4**: Switch between tabs (Workflows, Execution, Logs, Help) - **Up/Down or j/k**: Navigate lists - **Space**: Toggle workflow selection - **Enter**: Run selected workflow / View job details - **r**: Run all selected workflows - **a**: Select all workflows - **n**: Deselect all workflows - **e**: Cycle through runtime modes (Docker → Podman → Emulation) - **v**: Toggle between Execution and Validation mode - **Esc**: Back / Exit detailed view - **q**: Quit application ## Examples ### Validating a Workflow ```bash $ wrkflw validate .github/workflows/rust.yml Validating GitHub workflow file: .github/workflows/rust.yml... Validating 1 workflow file(s)... ✅ Valid: .github/workflows/rust.yml Summary: 1 valid, 0 invalid $ echo $? 0 # Example with validation failure $ wrkflw validate .github/workflows/invalid.yml Validating GitHub workflow file: .github/workflows/invalid.yml... Validating 1 workflow file(s)... ❌ Invalid: .github/workflows/invalid.yml 1. Job 'test' is missing 'runs-on' field 2. Job 'test' is missing 'steps' section Summary: 0 valid, 1 invalid $ echo $? 1 ``` ### Running a Workflow ```bash $ wrkflw run .github/workflows/rust.yml Executing workflow: .github/workflows/rust.yml ============================================================ Runtime: Docker ------------------------------------------------------------ ✅ Job succeeded: build ------------------------------------------------------------ ✅ Checkout code ✅ Set up Rust ✅ Build ✅ Run tests ✅ Workflow completed successfully! ``` ### Quick TUI Startup ```bash # Navigate to project root and run wrkflw $ cd my-project $ wrkflw # This will automatically load .github/workflows files into the TUI ``` ## System Requirements - Rust 1.67 or later - Container Runtime (optional, for container-based execution): - **Docker**: Traditional container runtime - **Podman**: Rootless alternative to Docker - **None**: Emulation mode runs workflows using local system tools ## How It Works WRKFLW parses your GitHub Actions workflow files and executes each job and step in the correct order. For container modes (Docker/Podman), it creates containers that closely match GitHub's runner environments. The workflow execution process: 1. **Parsing**: Reads and validates the workflow YAML structure 2. **Dependency Resolution**: Creates an execution plan based on job dependencies 3. **Environment Setup**: Prepares GitHub-like environment variables and context 4. **Execution**: Runs each job and step either in containers (Docker/Podman) or through local emulation 5. **Monitoring**: Tracks progress and captures outputs in the TUI or command line ## Advanced Features ### GitHub Environment Files Support WRKFLW supports GitHub's environment files and special commands: - `GITHUB_OUTPUT`: For storing step outputs (`echo "result=value" >> $GITHUB_OUTPUT`) - `GITHUB_ENV`: For setting environment variables (`echo "VAR=value" >> $GITHUB_ENV`) - `GITHUB_PATH`: For modifying the PATH (`echo "/path/to/dir" >> $GITHUB_PATH`) - `GITHUB_STEP_SUMMARY`: For creating step summaries (`echo "# Summary" >> $GITHUB_STEP_SUMMARY`) ### Composite Actions WRKFLW supports composite actions, which are actions made up of multiple steps. This includes: - Local composite actions referenced with `./path/to/action` - Remote composite actions from GitHub repositories - Nested composite actions (composite actions that use other actions) ### Container Cleanup WRKFLW automatically cleans up any containers created during workflow execution (Docker/Podman), even if the process is interrupted with Ctrl+C. For debugging failed workflows, you can preserve containers that fail by using the `--preserve-containers-on-failure` flag: ```bash # Preserve failed containers for debugging wrkflw run --preserve-containers-on-failure .github/workflows/build.yml # Also available in TUI mode wrkflw tui --preserve-containers-on-failure ``` When a container fails with this flag enabled, WRKFLW will: - Keep the failed container running instead of removing it - Log the container ID and provide inspection instructions - Show a message like: `Preserving container abc123 for debugging (exit code: 1). Use 'docker exec -it abc123 bash' to inspect.` (Docker) - Or: `Preserving container abc123 for debugging (exit code: 1). Use 'podman exec -it abc123 bash' to inspect.` (Podman) This allows you to inspect the exact state of the container when the failure occurred, examine files, check environment variables, and debug issues more effectively. ### Podman-Specific Features When using Podman as the container runtime, you get additional benefits: **Rootless Operation:** ```bash # Run workflows without root privileges wrkflw run --runtime podman .github/workflows/ci.yml ``` **Enhanced Security:** - Daemonless architecture reduces attack surface - User namespaces provide additional isolation - No privileged daemon required **Container Inspection:** ```bash # List preserved containers podman ps -a --filter "name=wrkflw-" # Inspect a preserved container's filesystem (without executing) podman mount # Or run a new container with the same volumes podman run --rm -it --volumes-from ubuntu:20.04 bash # Clean up all wrkflw containers podman ps -a --filter "name=wrkflw-" --format "{{.Names}}" | xargs podman rm -f ``` **Compatibility:** - Drop-in replacement for Docker workflows - Same CLI options and behavior - Identical container execution environment ## Limitations ### Supported Features - ✅ Basic workflow syntax and validation (all YAML syntax checks, required fields, and structure) with proper exit codes for CI/CD integration - ✅ Job dependency resolution and parallel execution (all jobs with correct 'needs' relationships are executed in the right order, and independent jobs run in parallel) - ✅ Matrix builds (supported for reasonable matrix sizes; very large matrices may be slow or resource-intensive) - ✅ Environment variables and GitHub context (all standard GitHub Actions environment variables and context objects are emulated) - ✅ Container actions (all actions that use containers are supported in Docker and Podman modes) - ✅ JavaScript actions (all actions that use JavaScript are supported) - ✅ Composite actions (all composite actions, including nested and local composite actions, are supported) - ✅ Local actions (actions referenced with local paths are supported) - ✅ Special handling for common actions (e.g., `actions/checkout` is natively supported) - ✅ Reusable workflows (caller): Jobs that use `jobs..uses` to call local or remote workflows are executed; inputs and secrets are propagated to the called workflow - ✅ Workflow triggering via `workflow_dispatch` (manual triggering of workflows is supported) - ✅ GitLab pipeline triggering (manual triggering of GitLab pipelines is supported) - ✅ Environment files (`GITHUB_OUTPUT`, `GITHUB_ENV`, `GITHUB_PATH`, `GITHUB_STEP_SUMMARY` are fully supported) - ✅ TUI interface for workflow management and monitoring - ✅ CLI interface for validation, execution, and remote triggering - ✅ Output capturing (logs, step outputs, and execution details are available in both TUI and CLI) - ✅ Container cleanup (all containers created by wrkflw are automatically cleaned up, even on interruption) ### Limited or Unsupported Features (Explicit List) - ❌ GitHub secrets and permissions: Only basic environment variables are supported. GitHub's encrypted secrets and fine-grained permissions are NOT available. - ❌ GitHub Actions cache: Caching functionality (e.g., `actions/cache`) is NOT supported in emulation mode and only partially supported in Docker and Podman modes (no persistent cache between runs). - ❌ GitHub API integrations: Only basic workflow triggering is supported. Features like workflow status reporting, artifact upload/download, and API-based job control are NOT available. - ❌ GitHub-specific environment variables: Some advanced or dynamic environment variables (e.g., those set by GitHub runners or by the GitHub API) are emulated with static or best-effort values, but not all are fully functional. - ❌ Large/complex matrix builds: Very large matrices (hundreds or thousands of job combinations) may not be practical due to performance and resource limits. - ❌ Network-isolated actions: Actions that require strict network isolation or custom network configuration may not work out-of-the-box and may require manual container runtime configuration. - ❌ Some event triggers: Only `workflow_dispatch` (manual trigger) is fully supported. Other triggers (e.g., `push`, `pull_request`, `schedule`, `release`, etc.) are NOT supported. - ❌ GitHub runner-specific features: Features that depend on the exact GitHub-hosted runner environment (e.g., pre-installed tools, runner labels, or hardware) are NOT guaranteed to match. Only a best-effort emulation is provided. - ❌ Windows and macOS runners: Only Linux-based runners are fully supported. Windows and macOS jobs are NOT supported. - ❌ Service containers: Service containers (e.g., databases defined in `services:`) are only supported in Docker and Podman modes. In emulation mode, they are NOT supported. - ❌ Artifacts: Uploading and downloading artifacts between jobs/steps is NOT supported. - ❌ Job/step timeouts: Custom timeouts for jobs and steps are NOT enforced. - ❌ Job/step concurrency and cancellation: Features like `concurrency` and job cancellation are NOT supported. - ❌ Expressions and advanced YAML features: Most common expressions are supported, but some advanced or edge-case expressions may not be fully implemented. - ⚠️ Reusable workflows (limits): - Outputs from called workflows are not propagated back to the caller (`needs..outputs.*` not supported) - `secrets: inherit` is not special-cased; provide a mapping to pass secrets - Remote calls clone public repos via HTTPS; private repos require preconfigured access (not yet implemented) - Deeply nested reusable calls work but lack cycle detection beyond regular job dependency checks ## Reusable Workflows WRKFLW supports executing reusable workflow caller jobs. ### Syntax ```yaml jobs: call-local: uses: ./.github/workflows/shared.yml call-remote: uses: my-org/my-repo/.github/workflows/shared.yml@v1 with: foo: bar secrets: token: ${{ secrets.MY_TOKEN }} ``` ### Behavior - Local references are resolved relative to the current working directory. - Remote references are shallow-cloned at the specified `@ref` into a temporary directory. - `with:` entries are exposed to the called workflow as environment variables `INPUT_`. - `secrets:` mapping entries are exposed as environment variables `SECRET_`. - The called workflow executes according to its own `jobs`/`needs`; a summary of its job results is reported as a single result for the caller job. ### Current limitations - Outputs from called workflows are not surfaced back to the caller. - `secrets: inherit` is not supported; specify an explicit mapping. - Private repositories for remote `uses:` are not yet supported. ### Runtime Mode Differences - **Docker Mode**: Provides the closest match to GitHub's environment, including support for Docker container actions, service containers, and Linux-based jobs. Some advanced container configurations may still require manual setup. - **Podman Mode**: Similar to Docker mode but uses Podman for container execution. Offers rootless container support and enhanced security. Fully compatible with Docker-based workflows. - **🔒 Secure Emulation Mode**: Runs workflows on the local system with comprehensive sandboxing for security. **Recommended for local development**: - Command validation and filtering (blocks dangerous commands like `rm -rf /`, `sudo`, etc.) - Resource limits (CPU, memory, execution time) - Filesystem access controls - Process monitoring and limits - Safe for running untrusted workflows locally - **⚠️ Emulation Mode (Legacy)**: Runs workflows using local system tools without sandboxing. **Not recommended - use Secure Emulation instead**: - Only supports local and JavaScript actions (no Docker container actions) - No support for service containers - No caching support - **No security protections - can execute harmful commands** - Some actions may require adaptation to work locally ### Best Practices - **Use Secure Emulation mode for local development** - provides safety without container overhead - Test workflows in multiple runtime modes to ensure compatibility - **Use Docker/Podman mode for production** - provides maximum isolation and reproducibility - Keep matrix builds reasonably sized for better performance - Use environment variables instead of GitHub secrets when possible - Consider using local actions for complex custom functionality - **Review security warnings** - pay attention to blocked commands in secure emulation mode - **Start with secure mode** - only fall back to legacy emulation if necessary ## Roadmap The following roadmap outlines our planned approach to implementing currently unsupported or partially supported features in WRKFLW. Progress and priorities may change based on user feedback and community contributions. ### 1. Secrets and Permissions - **Goal:** Support encrypted secrets and fine-grained permissions similar to GitHub Actions. - **Plan:** - Implement secure secret storage and injection for workflow steps. - Add support for reading secrets from environment variables, files, or secret managers. - Investigate permission scoping for jobs and steps. ### 2. GitHub Actions Cache - **Goal:** Enable persistent caching between workflow runs, especially for dependencies. - **Plan:** - Implement a local cache directory for Docker mode. - Add support for `actions/cache` in both Docker and emulation modes. - Investigate cross-run cache persistence. ### 3. GitHub API Integrations - **Goal:** Support artifact upload/download, workflow/job status reporting, and other API-based features. - **Plan:** - Add artifact upload/download endpoints. - Implement status reporting to GitHub via the API. - Add support for job/step annotations and logs upload. ### 4. Advanced Environment Variables - **Goal:** Emulate all dynamic GitHub-provided environment variables. - **Plan:** - Audit missing variables and add dynamic computation where possible. - Provide a compatibility table in the documentation. ### 5. Large/Complex Matrix Builds - **Goal:** Improve performance and resource management for large matrices. - **Plan:** - Optimize matrix expansion and job scheduling. - Add resource limits and warnings for very large matrices. ### 6. Network-Isolated Actions - **Goal:** Support custom network configurations and strict isolation for actions. - **Plan:** - Add advanced container network configuration options for Docker and Podman. - Document best practices for network isolation. ### 7. Event Triggers - **Goal:** Support additional triggers (`push`, `pull_request`, `schedule`, etc.). - **Plan:** - Implement event simulation for common triggers. - Allow users to specify event payloads for local runs. ### 8. Windows and macOS Runners - **Goal:** Add support for non-Linux runners. - **Plan:** - Investigate cross-platform containerization and emulation. - Add documentation for platform-specific limitations. ### 9. Service Containers in Emulation Mode - **Goal:** Support service containers (e.g., databases) in emulation mode. - **Plan:** - Implement local service startup and teardown scripts. - Provide configuration for common services. ### 10. Artifacts, Timeouts, Concurrency, and Expressions - **Goal:** Support artifact handling, job/step timeouts, concurrency, and advanced YAML expressions. - **Plan:** - Add artifact storage and retrieval. - Enforce timeouts and concurrency limits. - Expand expression parser for advanced use cases. --- **Want to help?** Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for how to get started. ## License This project is licensed under the MIT License - see the LICENSE file for details. ## Remote Workflow Triggering WRKFLW allows you to manually trigger workflow runs on GitHub through both the command-line interface (CLI) and the terminal user interface (TUI). ### Requirements: 1. You need a GitHub token with workflow permissions. Set it in the `GITHUB_TOKEN` environment variable: ```bash export GITHUB_TOKEN=ghp_your_token_here ``` 2. The workflow must have the `workflow_dispatch` trigger defined in your workflow YAML: ```yaml on: workflow_dispatch: inputs: name: description: 'Person to greet' default: 'World' required: true debug: description: 'Enable debug mode' required: false type: boolean default: false ``` ### Triggering from CLI: ```bash # Trigger a workflow using the default branch wrkflw trigger workflow-name # Trigger a workflow on a specific branch wrkflw trigger workflow-name --branch feature-branch # Trigger with input parameters wrkflw trigger workflow-name --branch main --input name=Alice --input debug=true ``` After triggering, WRKFLW will provide feedback including the URL to view the triggered workflow on GitHub. ### Triggering from TUI: 1. Launch the TUI interface: ```bash wrkflw tui ``` 2. Navigate to the "Workflows" tab (use `Tab` key or press `1`). 3. Use the arrow keys (`↑`/`↓`) or `j`/`k` to select the desired workflow. 4. Press `t` to trigger the selected workflow. 5. If the workflow is successfully triggered, you'll see a notification in the UI. 6. You can monitor the triggered workflow's execution on GitHub using the provided URL. ### Verifying Triggered Workflows: To verify that your workflow was triggered: 1. Visit your GitHub repository in a web browser. 2. Navigate to the "Actions" tab. 3. Look for your workflow in the list of workflow runs. 4. Click on it to view the details of the run.