Skip to content

local integration simulator over the generated workflows (act + gitea) #315

Description

@joshua-temple

Problem

Tier 1 validates orchestration in-process but never runs the actual generated YAML. Some
users want to exercise the real generated workflows locally before trusting them in CI.
cascade already has this machinery for its own e2e suite; it is not exposed to users.

Goal

Expose cascade's existing e2e harness as a user-facing integration simulator via
cascade simulate --integration, a flag on the existing simulate command. The user supplies
their manifest and deploy stubs; cascade stages a repo, generates the workflows, and runs
them locally through act against a gitea instance with deploys stubbed, then reports the
outcome and resulting state.

Design notes

  • Seed from the existing harness, do not rebuild it: e2e/harness/harness.go
    (StageRepoFromConfig, stub generation via generateStubWorkflow,
    normalizeCallbackStubPath), e2e/harness/act.go (act invocation,
    workflow_dispatch event synthesis), e2e/harness/gitea.go (gitea container),
    e2e/harness/runner.go and scenario.go (scenario driving), and the
    e2e/scenarios/*.yaml fixtures as the input-format reference.
  • The harness currently lives in the e2e/ module as test code. Productizing it means
    extracting the reusable pieces behind a stable surface the CLI can call without pulling in
    test-only dependencies, or invoking the harness through a thin command layer. Pick the
    lower-risk extraction and note the module boundary in the PR.
  • Deploys are stubbed exactly as the e2e suite stubs them (inert stub workflows), preserving
    the orchestration-not-deploys boundary.
  • Docker is required (testcontainers + gitea + act). The command must detect a missing
    Docker daemon and fail with a clear, actionable message rather than a stack trace.

Tests

  • An e2e scenario (the repo requires generator/integration features to ship an e2e/
    scenario, not just a unit test) that drives the productized path end to end against a
    staged repo and asserts the resulting state, reusing the existing harness primitives.
  • A unit test for the missing-Docker detection and error message.

Acceptance

  • A user with Docker can point the integration simulator at their manifest and deploy stubs
    and watch the generated workflows run locally to a reported outcome and final state.
  • Without Docker, the command fails fast with a clear message.

Dependencies

#311 (shares the simulate command surface). Lower priority; heavier.

Command surface decision

Ship this as cascade simulate --integration, a flag on the existing simulate command,
rather than a separate subcommand. Keeping one user-facing verb for all simulation is the
decision here.

Packaging (decided)

The integration harness ships in a separate Go module (the existing e2e module or a sibling
module), exposed as its own binary or command. It does NOT ship inside the main CLI module,
and NOT behind a build tag, because a build tag would not remove the testcontainers and
Docker dependencies from the main module's dependency graph. Module separation is what keeps
the main CLI module lean.

Schema-2 compatibility

Must stay compatible with the schema-2 state model and be updated when schema-2 lands; it is
not blocked on schema-2 and can be built against the current schema.

Metadata

Metadata

Assignees

No one assigned

    Labels

    dxDeveloper experiencee2efeatfleetharnessE2E / integration harnesssimulatorLocal pipeline simulator feature

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions