{"id":27607790,"url":"https://github.com/bahdotsh/wrkflw","last_synced_at":"2026-10-19T01:02:19.798Z","repository":{"id":285057069,"uuid":"956947576","full_name":"bahdotsh/wrkflw","owner":"bahdotsh","description":"Validate and Run GitHub Actions locally.","archived":false,"fork":false,"pushed_at":"2026-09-08T17:53:22.000Z","size":24920,"stargazers_count":3321,"open_issues_count":14,"forks_count":63,"subscribers_count":15,"default_branch":"main","last_synced_at":"2026-09-23T19:15:47.781Z","etag":null,"topics":["ci","cli","devops","github","github-actions","hacktoberfest","ratatui","rust","tui"],"latest_commit_sha":null,"homepage":"https://github.com/bahdotsh/wrkflw","language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bahdotsh.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","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,"notice":null,"maintainers":null,"copyright":null,"agents":null,"claude":"CLAUDE.md","gemini":null,"cursor":null,"copilot":null,"dco":null,"cla":null,"disclosure":null},"funding":{"github":["bahdotsh"]}},"created_at":"2025-03-29T07:25:48.000Z","updated_at":"2026-09-23T05:40:22.000Z","dependencies_parsed_at":"2026-09-08T15:23:02.845Z","dependency_job_id":null,"html_url":"https://github.com/bahdotsh/wrkflw","commit_stats":null,"previous_names":["bahdotsh/wrkflw"],"tags_count":60,"template":false,"template_full_name":null,"purl":"pkg:github/bahdotsh/wrkflw","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahdotsh%2Fwrkflw","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahdotsh%2Fwrkflw/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahdotsh%2Fwrkflw/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahdotsh%2Fwrkflw/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bahdotsh","download_url":"https://codeload.github.com/bahdotsh/wrkflw/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bahdotsh%2Fwrkflw/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":344872684,"owners_count":38344170,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-10-03T21:59:58.778Z","status":"online","status_checked_at":"2026-10-18T02:00:06.448Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["ci","cli","devops","github","github-actions","hacktoberfest","ratatui","rust","tui"],"created_at":"2025-04-22T22:01:42.289Z","updated_at":"2026-10-19T01:02:19.788Z","avatar_url":"https://github.com/bahdotsh.png","language":"Rust","funding_links":["https://github.com/sponsors/bahdotsh"],"categories":["Rust","\u003ca name=\"git\"\u003e\u003c/a\u003eGit and accessories","💻 Apps"],"sub_categories":["⌨️ Development Tools"],"readme":"# WRKFLW\n\n[![Crates.io](https://img.shields.io/crates/v/wrkflw)](https://crates.io/crates/wrkflw)\n[![License](https://img.shields.io/crates/l/wrkflw)](LICENSE)\n[![Build Status](https://img.shields.io/github/actions/workflow/status/bahdotsh/wrkflw/ci.yml?branch=main)](https://github.com/bahdotsh/wrkflw/actions/workflows/ci.yml)\n[![Downloads](https://img.shields.io/crates/d/wrkflw)](https://crates.io/crates/wrkflw)\n\nA command-line tool for validating and executing GitHub Actions workflows locally. Test your workflows on your machine before pushing to GitHub.\n\n![WRKFLW Demo](demo.gif)\n\n## Features\n\n- **TUI interface** — interactive terminal UI with Workflows, Execution, DAG, Logs, Trigger, Secrets, and Help tabs\n- **Workflow validation** — syntax checks, structural validation, and composite action input cross-checking with CI/CD-friendly exit codes\n- **Local execution** — Docker, Podman, emulation, or sandboxed **secure emulation** (no containers)\n- **Diff-aware filtering** — skip workflows whose `on:` block doesn't match the simulated event and changed file set\n- **Watch mode** — rerun workflows automatically on file changes, with trigger-aware filtering\n- **Job selection** — run individual jobs with `--job` or via TUI job selection mode\n- **Job dependency resolution** — automatic ordering based on `needs` with parallel execution of independent jobs\n- **Expression evaluator** — evaluates `${{ ... }}` expressions including `toJSON`, `fromJSON`, `contains`, `startsWith`, etc.\n- **Action support** — Docker container actions, JavaScript actions, composite actions (with output propagation), and local actions\n- **Reusable workflows** — execute caller jobs via `jobs.\u003cid\u003e.uses` (local or `owner/repo/path@ref`) with output propagation\n- **Artifacts, cache, and inter-job outputs** — `actions/upload-artifact`, `actions/download-artifact`, `actions/cache`, and `needs.\u003cid\u003e.outputs.*`\n- **GitHub context emulation** — environment variables, `GITHUB_OUTPUT`, `GITHUB_ENV`, `GITHUB_PATH`, `GITHUB_STEP_SUMMARY`\n- **Matrix builds** — full support for `include`, `exclude`, `max-parallel`, and `fail-fast`\n- **Secrets management** — multiple providers (env, file, Vault, AWS, Azure, GCP) with masking and AES-256-GCM encrypted storage\n- **Remote triggering** — trigger `workflow_dispatch` runs on GitHub or GitLab pipelines\n- **GitLab support** — validate and trigger GitLab CI pipelines\n\n## Not yet supported\n\n- GitHub encrypted secrets and fine-grained permissions\n- Event triggers other than `workflow_dispatch` for the remote `trigger` command\n- Private repos for remote `uses:` — reusable workflows clone over unauthenticated HTTPS\n- `concurrency:` groups and `cancel-in-progress` — parsed but not enforced\n- Service containers — `services:` is parsed but never started, in any runtime\n- Windows and macOS runners — `runs-on: windows-*` / `macos-*` is silently mapped to a container image (macOS → a Linux image, Windows → a Windows container that won't run on Linux/macOS hosts). `${{ runner.os }}` reflects the host OS, not `runs-on`.\n\n## Installation\n\n```bash\ncargo install wrkflw\n```\n\nOr with Homebrew ([formula](https://formulae.brew.sh/formula/wrkflw)):\n\n```bash\nbrew install wrkflw\n```\n\nOr build from source:\n\n```bash\ngit clone https://github.com/bahdotsh/wrkflw.git\ncd wrkflw\ncargo build --release\n```\n\n## Quick Start\n\n```bash\n# Launch the TUI (auto-detects .github/workflows)\nwrkflw\n\n# Validate workflows\nwrkflw validate\n\n# Run a workflow\nwrkflw run .github/workflows/ci.yml\n\n# Rerun workflows automatically on file changes\nwrkflw watch\n\n# List detected workflows and pipelines\nwrkflw list\n```\n\n## Usage\n\n### Validation\n\n```bash\n# Validate all workflows in .github/workflows\nwrkflw validate\n\n# Validate specific files or directories\nwrkflw validate path/to/workflow.yml\nwrkflw validate path/to/workflows/\n\n# Validate multiple paths\nwrkflw validate flow-1.yml flow-2.yml path/to/workflows/\n\n# GitLab pipelines\nwrkflw validate .gitlab-ci.yml --gitlab\n\n# Verbose output\nwrkflw validate --verbose path/to/workflow.yml\n```\n\n**Exit codes:** `0` = all valid, `1` = validation failures, `2` = usage error. Use `--no-exit-code` to disable.\n\n### Execution\n\n```bash\n# Run with auto-detection (default: tries Docker, then Podman, then emulation)\nwrkflw run .github/workflows/ci.yml\n\n# Run with Docker explicitly\nwrkflw run --runtime docker .github/workflows/ci.yml\n\n# Run with Podman\nwrkflw run --runtime podman .github/workflows/ci.yml\n\n# Run in emulation mode (no containers)\nwrkflw run --runtime emulation .github/workflows/ci.yml\n\n# Run in sandboxed secure emulation\nwrkflw run --runtime secure-emulation .github/workflows/ci.yml\n\n# Run a specific job\nwrkflw run --job build .github/workflows/ci.yml\n\n# List jobs in a workflow\nwrkflw run --jobs .github/workflows/ci.yml\n\n# Preserve failed containers for debugging\nwrkflw run --preserve-containers-on-failure .github/workflows/ci.yml\n```\n\n### Trigger-aware execution\n\nSkip workflows whose `on:` block wouldn't fire for a given event/change set. Strict mode is on by default: `wrkflw run --event …` without `--diff` or `--changed-files` is rejected up front rather than silently skipping every `paths:`-gated workflow.\n\n```bash\n# Auto-detect changed files from git (vs origin/HEAD, main/master, or HEAD~1)\nwrkflw run --diff --event push .github/workflows/ci.yml\n\n# Pin the diff range\nwrkflw run --diff --diff-base main --diff-head HEAD --event push .github/workflows/ci.yml\n\n# Supply changed files explicitly (e.g. from a CI wrapper)\nwrkflw run --event push --changed-files src/main.rs,Cargo.toml .github/workflows/ci.yml\n\n# Simulate a pull_request — `--base-branch` is required under strict mode\nwrkflw run --event pull_request --base-branch main --diff .github/workflows/ci.yml\n\n# Opt out of strict rejection (legacy warn-and-proceed)\nwrkflw run --event push --no-strict-filter .github/workflows/ci.yml\n```\n\nSee [BREAKING_CHANGES.md](BREAKING_CHANGES.md) for full migration notes.\n\n### Watch mode\n\n```bash\n# Watch .github/workflows for changes and rerun affected workflows\nwrkflw watch\n\n# Watch a specific path, simulate pull_request, and cap concurrency\nwrkflw watch --event pull_request --base-branch main \\\n    --max-concurrency 2 --debounce 750 .github/workflows\n\n# Ignore extra directories on top of the built-in list\nwrkflw watch --ignore-dir .terraform --ignore-dir coverage\n```\n\n### TUI\n\n```bash\n# Open TUI with default directory\nwrkflw tui\n\n# Open with specific runtime\nwrkflw tui --runtime podman\n```\n\n**Tabs:** Workflows · Execution · DAG · Logs · Trigger · Secrets · Help.\n\n**Controls:**\n\n| Key | Action |\n|-----|--------|\n| `Tab` / `Shift+Tab` | Switch tabs |\n| `1`–`7` | Jump to tab by number |\n| `w` / `x` / `l` / `h` | Jump to Workflows / Execution / Logs / Help |\n| `↑`/`↓` or `k`/`j` | Navigate / scroll |\n| `Space` | Toggle workflow selection |\n| `Enter` | Run / view details |\n| `r` | Run selected workflows |\n| `a` / `n` | Select all / deselect all |\n| `Shift+R` | Reset workflow status |\n| `Shift+J` | View jobs in workflow |\n| `e` | Cycle runtime (Docker / Podman / Emulation / Secure Emulation) |\n| `v` | Toggle Execution / Validation mode |\n| `d` / `D` | Toggle diff-aware filter / cycle simulated event |\n| `t` | Trigger remote workflow |\n| `,` | Open Tweaks overlay |\n| `?` | Toggle help overlay |\n| `q` / `Esc` | Quit / back |\n\nLogs tab adds `s` (search), `f` (filter), `c` (clear), `n` (next match). Trigger tab adds `p` (github↔gitlab), `b` (edit branch), `+` (add input), `c` (copy curl preview).\n\n### Remote Triggering\n\nTrigger `workflow_dispatch` events on GitHub or GitLab.\n\n```bash\n# GitHub (requires GITHUB_TOKEN env var)\nwrkflw trigger workflow-name --branch main --input key=value\n\n# GitLab (requires GITLAB_TOKEN env var)\nwrkflw trigger-gitlab --branch main --variable key=value\n```\n\n## Runtime Modes\n\n| Mode | Description | Best for |\n|------|-------------|----------|\n| **Auto** (default) | Detects Docker, then Podman, then falls back to emulation | Most users |\n| **Docker** | Full container isolation, closest to GitHub runners | Production, CI/CD |\n| **Podman** | Rootless containers, no daemon required | Security-conscious environments |\n| **Emulation** | Runs directly on host, no containers needed | Quick local testing |\n| **Secure Emulation** | Sandboxed host processes with filesystem/network restrictions | Running untrusted workflows without a container runtime |\n\n## Reusable Workflows\n\n```yaml\njobs:\n  call-local:\n    uses: ./.github/workflows/shared.yml\n\n  call-remote:\n    uses: my-org/my-repo/.github/workflows/shared.yml@v1\n    with:\n      foo: bar\n    secrets:\n      token: ${{ secrets.MY_TOKEN }}\n```\n\n- Local refs resolve relative to the working directory\n- Remote refs are shallow-cloned at the specified `@ref`\n- `with:` entries become `INPUT_\u003cKEY\u003e` env vars; `secrets:` become `SECRET_\u003cKEY\u003e`\n- Outputs from called jobs are merged back into `needs.\u003cid\u003e.outputs.*`\n\n**Limitations:** private repos for remote `uses:` are not yet supported (the clone is unauthenticated); declared `on.workflow_call.outputs` is approximated by flattening all called-job outputs (the explicit mapping is not yet parsed).\n\n## Secrets Management\n\nWRKFLW supports GitHub Actions-compatible `${{ secrets.* }}` syntax with multiple providers:\n\n```bash\n# Environment variables (simplest)\nexport GITHUB_TOKEN=\"ghp_...\"\nwrkflw run .github/workflows/ci.yml\n\n# File-based secrets (JSON, YAML, or .env format)\n# Configure in ~/.wrkflw/secrets.yml\n```\n\nSupported providers: environment variables, file-based, HashiCorp Vault, AWS Secrets Manager, Azure Key Vault, Google Cloud Secret Manager. See the [secrets demo](examples/secrets-demo/) for detailed examples.\n\n## Project Structure\n\nWRKFLW is organized as a Cargo workspace with focused crates:\n\n| Crate | Purpose |\n|-------|---------|\n| `wrkflw` | CLI binary and library entry point |\n| `wrkflw-executor` | Workflow execution engine, expression evaluator, artifact/cache stores |\n| `wrkflw-parser` | Workflow file parsing and schema validation |\n| `wrkflw-evaluator` | Structural evaluation of workflow files |\n| `wrkflw-validators` | Validation rules for jobs, steps, triggers |\n| `wrkflw-runtime` | Container and emulation runtime abstractions |\n| `wrkflw-trigger-filter` | `on:` block parsing and change-set matching |\n| `wrkflw-watcher` | File watcher with trigger-aware re-execution |\n| `wrkflw-ui` | Terminal user interface |\n| `wrkflw-models` | Shared data structures |\n| `wrkflw-matrix` | Matrix expansion utilities |\n| `wrkflw-secrets` | Secrets management with multiple providers |\n| `wrkflw-github` | GitHub API integration |\n| `wrkflw-gitlab` | GitLab API integration |\n| `wrkflw-logging` | In-memory logging for TUI/CLI |\n| `wrkflw-utils` | Shared helpers |\n\n## License\n\nMIT License - see [LICENSE](LICENSE) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahdotsh%2Fwrkflw","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbahdotsh%2Fwrkflw","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbahdotsh%2Fwrkflw/lists"}