logs.gokuls.in

11 pull requests merged across 2 repos

bahdotsh/wrkflw

  • Rewrote main README from 610 lines to ~170 — removed duplicate sections, speculative roadmap, and verbose limitation disclaimers
  • Removed 12 dead files: junk test files (hello.cpp, hello.rs, test.py), duplicate AGENTS.md, verbose VERSION_MANAGEMENT.md, GITLAB_USAGE.md (merged into README), TESTING_PODMAN.md, README_SECURITY.md, 3 asciinema recordings, and 2 unused GIFs (~7MB)
  • Updated crate READMEs: crates/README.md now lists all 14 crates with descriptions; tests/README.md and examples/secrets-demo/README.md trimmed

Net: 3,819 lines deleted, 197 added.

Test plan

  • Verify all links in README.md resolve correctly (demo.gif still exists)
  • Verify crate README table matches actual crates in crates/
  • Confirm no removed file is referenced by Cargo.toml or build scripts
  • Adds post-step read-back of GITHUB_OUTPUT, GITHUB_ENV, GITHUB_PATH, and GITHUB_STEP_SUMMARY files, enabling inter-step data flow in GHA emulation
  • Adds ${{ steps.<id>.outputs.<key> }} and ${{ env.<name> }} expression substitution so step outputs and dynamic env vars are resolved in run commands
  • Restructures the execute_job() step loop from an async-block wrapper to a deadline-based timeout, allowing job_env mutation between steps

What works now

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - id: set-output
        run: echo "version=1.2.3" >> $GITHUB_OUTPUT
      - run: echo "Got ${{ steps.set-output.outputs.version }}"
      # ^ resolves to "Got 1.2.3"

      - run: echo "MY_VAR=hello" >> $GITHUB_ENV
      - run: echo "$MY_VAR"
      # ^ sees "hello" in env

      - run: echo "/custom/bin" >> $GITHUB_PATH
      - run: echo "$PATH"
      # ^ has /custom/bin prepended

Files changed

FileChange
crates/executor/src/github_env_files.rsNEW — GHA key-value file parser (simple + heredoc format) with 11 tests
crates/executor/src/engine.rsExtended StepResult with outputs field, restructured step loops, added post-step read-back
crates/executor/src/substitution.rsAdded steps.*.outputs.* and env.* regex patterns + substitution functions with 7 tests
crates/executor/src/lib.rsModule registration
crates/ui/src/handlers/workflow.rsBackward-compatible StepResult field addition

Test plan

  • cargo fmt --all — clean
  • cargo clippy --workspace — zero warnings
  • cargo test --workspace — all 344 tests pass (18 new tests added)
  • Manual smoke test with a workflow using $GITHUB_OUTPUT step outputs

Implements four low-risk, well-scoped fixes to improve GitHub Actions emulation fidelity:

  • **Expand github.* context**: Adds 13 missing GITHUB_* env vars (CI, GITHUB_ACTIONS, GITHUB_REF_NAME, GITHUB_REF_TYPE, GITHUB_REPOSITORY_OWNER, GITHUB_RUN_ATTEMPT, GITHUB_SERVER_URL, GITHUB_API_URL, GITHUB_GRAPHQL_URL, GITHUB_HEAD_REF, GITHUB_BASE_REF, GITHUB_TRIGGERING_ACTOR, GITHUB_RETENTION_DAYS), improves GITHUB_ACTOR to derive from git config user.name/$USER, adds GITHUB_JOB per-job
  • Enforce timeout-minutes: Parses job-level timeout-minutes, wraps job execution in tokio::time::timeout (default 360 min per GHA spec), wraps step execution when step.timeout_minutes is set
  • Implement defaults.run: Adds Defaults/DefaultsRun structs, supports defaults.run.shell and defaults.run.working-directory at both workflow and job level with proper fallback chain (step > job defaults > workflow defaults > bash). Shell now uses -e flag for bash/sh matching real GHA behavior
  • Implement hashFiles(): Adds sha2/glob dependencies, implements glob-based file matching with SHA-256 hashing, deterministic sort order, wired into the expression substitution pipeline

Test plan

  • cargo fmt --all — no issues
  • cargo clippy --workspace — no warnings
  • cargo test --workspace — all tests pass (164 executor, 21 parser, all others)
  • 11 new unit tests for environment helper functions
  • 1 new parser test for timeout-minutes
  • 1 new parser test for defaults.run
  • 7 new unit tests for hashFiles() (single/multiple patterns, no matches, recursive, deterministic, inline text, combined with matrix)

Replace monolithic build.yml with split ci.yml (parallel fmt, clippy, build+test jobs). Update all actions to modern versions (checkout@v4, dtolnay/rust-toolchain, rust-cache@v2). Overhaul release workflow with more build targets (musl, aarch64), simpler changelog, and crates.io publish step.

  • Adds a job selection sub-view to the TUI Workflows tab — press Enter on a workflow to see its jobs, then Enter on a job to run just that one (with transitive deps), a to run all, or Esc to go back
  • Reuses the existing ExecutionConfig.target_job and filter_plan_to_job() machinery that the CLI --job flag already uses
  • Updates status bar hints and help overlay to document the new keybindings

Test plan

  • cargo build --features tui compiles cleanly
  • cargo clippy --features tui passes
  • cargo test target_job — existing target_job tests pass
  • Manual: wrkflw tui → select workflow → Enter → see jobs listed → Enter on a job → only that job executes
  • Manual: In job selection mode, press a → all jobs execute
  • Manual: In job selection mode, press Esc → returns to workflow list
  • Adds a tui Cargo feature flag (enabled by default) to wrkflw-ui and the main binary crate
  • When built with --no-default-features, ratatui/crossterm are excluded, the tui subcommand is removed, and running with no args prints help
  • All CLI subcommands (validate, run, trigger, list) remain fully functional without TUI
  • Removes unused direct crossterm/ratatui deps from the binary crate (they were only needed transitively via wrkflw-ui)

Usage

# Default build (TUI included, same as before)
cargo build

# Minimal build (no TUI, smaller binary)
cargo build --no-default-features

# Install without TUI
cargo install wrkflw --no-default-features

Test plan

  • cargo check — default build compiles
  • cargo check --no-default-features — no-TUI build compiles
  • cargo test — all tests pass with default features
  • cargo test --no-default-features — all tests pass without TUI
  • cargo clippy — clean on both feature configurations
  • cargo fmt --check — formatting clean
  • When a workflow step uses a local composite action (uses: ./path), wrkflw validate now reads the action's action.yml, identifies inputs with required: true (and no default), and reports an error if they're missing from the step's with: block.
  • Threads the repo root path through the validator chain (evaluate_workflow_filevalidate_jobsvalidate_stepsvalidate_action_reference) so local action paths can be resolved.
  • Case-insensitive input matching (consistent with GitHub Actions behavior). Graceful degradation when repo root or action file is unavailable.

Closes #67

Test plan

  • 10 new unit tests in crates/validators/src/actions.rs covering: missing required input, provided input, required+default passes, no inputs section, missing action dir, missing action.yml, case-insensitive matching, multiple missing inputs, None repo_root skips, .yaml extension
  • All existing tests updated for new signatures and passing
  • cargo test — full suite passes (273 tests, 0 failures)
  • cargo fmt --check — clean
  • cargo clippy --all-targets — no new warnings
  • Add --job <name> to wrkflw run to execute a single job in isolation, for both GitHub workflows and GitLab pipelines
  • Add --jobs flag to wrkflw list to display job names within each workflow/pipeline file
  • If the specified job doesn't exist, error message lists all available jobs

Closes #68

Test plan

  • cargo build — compiles cleanly
  • cargo test — all 243 tests pass
  • wrkflw list --jobs — shows jobs grouped under each workflow file
  • wrkflw run --job <name> <workflow> — runs only the specified job
  • wrkflw run --job nonexistent <workflow> — errors with available job names

Setup actions like actions/setup-node and shivammathur/setup-php now correctly propagate their Docker images to subsequent run: steps instead of falling back to ubuntu:latest.

  • Single setup action: Uses that runtime's image directly (e.g., node:20-slim for setup-node)
  • Multiple setup actions: Builds a combined Docker image with all required runtimes (e.g., PHP + Node.js for Laravel workflows)
  • No setup actions: Fully backward compatible — no behavior change
  • Skips spurious pull_image for locally-built wrkflw-* images
  • Bumps build_image timeout from 2min to 10min for combined image builds

Changes

  • crates/executor/src/engine.rs: Added detect_setup_runtimes(), build_combined_runtime_image(), resolve_runner_image(), and get_install_script(). Modified execute_job() and execute_matrix_job() to use the resolved image. Added 14 unit tests.
  • crates/executor/src/docker.rs: Skip pull for wrkflw-* images, increase build timeout.
  • tests/workflows/multi-runtime-test.yml: New test workflow with PHP + Node.js in same job.

Test plan

  • cargo fmt --all — clean
  • cargo clippy — no warnings
  • cargo test — all 219 tests pass (14 new)
  • Manual test: single Node.js workflow (setup-noderun: node --version) — passes, uses node:20-slim
  • Manual test: single PHP workflow (setup-phprun: php --version) — passes, uses composer:latest
  • Manual test: multi-runtime workflow (PHP + Node.js in same job) — passes, builds combined image
  • Manual test: step failure stops job execution — confirmed working

— third-party Docker-based GitHub Actions (like super-linter/super-linter/slim@v7) were silently passing without ever actually running. The engine resolved the action image correctly but then ran echo 'Would execute GitHub action: ...' inside it regardless of runtime mode.

Root cause (two separate failures):

  • prepare_action() errored on ActionType::DockerBuild with "not yet supported", fell back to determine_action_image(), and returned node:20-slim for super-linter
  • The PreparedAction::Image execution branch had three sub-paths (is_docker, is_local, else) that all just ran echo commands — the resolved image was never actually used

Changes:

  • Add NativeDocker variant to PreparedAction — runs the image with its built-in ENTRYPOINT (no command override)
  • Implement DockerBuild support: clone repo via shallow_clone, resolve Dockerfile path from action.yml, build it, return the tag
  • Fix build_image_inner to tar the full context directory (not just the Dockerfile) so COPY instructions work
  • Allow empty cmd in run_container to mean "use image's default ENTRYPOINT/CMD"
  • Emulation mode gracefully handles empty cmd instead of erroring

The existing PreparedAction::Image path with all special-cased action handling (actions-rs, checkout, etc.) is untouched.

Test plan

  • cargo build — compiles cleanly
  • cargo test — all 171 tests pass
  • cargo clippy — no warnings
  • Manual test: run a workflow with a Docker-based action (e.g., docker://alpine) and verify it actually executes
  • Manual test: run a workflow with a DockerBuild action (e.g., super-linter) and verify the Dockerfile is built and run

rust-lang/this-week-in-rust