cascade

module
v0.9.3-rc.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 6, 2026 License: Apache-2.0

README

cascade

Go Reference Go Version Docs

CodeQL OpenSSF Scorecard Release

Coverage Fleet E2E (live GitHub)

The cascade mascot

Declarative trunk-based CI/CD for GitHub Actions.

Define what to build and where to deploy in one manifest.
cascade generates the GitHub Actions wiring, tracks deployment state, manages releases,
and cascades promotions through your environments.


cascade is a compiler, not a control plane. You describe your environments, builds, deploys, and release policy in one manifest. cascade compiles that manifest into GitHub Actions workflows and then gets out of the way: everything runs as native GitHub Actions, with no external service, agent, or daemon watching your repository. Your build and deploy callbacks run on whatever runners you configure, GitHub-hosted or self-hosted.

How it works

The manifest (.github/manifest.yaml) holds both the pipeline configuration and the live deployment state for every environment. You run cascade generate-workflow once to compile it into GitHub Actions workflows, and commit those alongside your code. From then on the generated workflows own their own execution: a merge to trunk builds and deploys to the first environment, and a workflow_dispatch promotes the same built artifact through the rest of the chain without rebuilding it.

Read How Cascade works for the full mental model, including the release boundary and the hotfix and rollback off-ramps.


Is cascade for you?

cascade earns its keep when you promote a built artifact through a chain of environments. It is a strong fit when most of these hold:

  • You deploy to two or more environments (say dev, test, prod) and want the same artifact promoted through them, never rebuilt per stage.
  • You are on GitHub Actions and would rather own your deploy logic in reusable workflows than run a separate CD platform.
  • You want promotion gates, hotfix-to-any-environment, and rollback without hand-wiring that state machine.
  • You can adopt conventional commits (cascade derives versions, changelogs, and the breaking-change gate from them).

It is likely overkill for a single environment with a plain build-and-release on push. A repo with no deployments at all is a different case: the no-environment mode is a supported shape that still gives you conventional-commit versioning and releases.

Already running a pipeline? See the adoption guide for migrating without a rewrite.


Quickstart

go install github.com/stablekernel/cascade/cmd/cascade@latest

See Getting started for the pinned-version install and the setup-cli action, both of which most teams should use instead of a bare @latest install.

Write a manifest, write your build and deploy callbacks, then generate. Callbacks must exist first: the generator reads their workflow_call outputs to wire the rest.

# .github/manifest.yaml
ci:
  config:
    schema_version: 1
    trunk_branch: main
    cli_version: v0.9.1
    environments: [dev, staging, prod]
    builds:
      - name: app
        workflow: .github/workflows/build-app.yaml
# 1. Write .github/manifest.yaml (above)
# 2. Write your build/deploy callback workflows (they must exist first)
# 3. Generate the orchestration workflows
cascade generate-workflow --config .github/manifest.yaml
# 4. Commit everything and push to trunk to run the first pipeline

The full walkthrough, including cascade init scaffolding and the four topology shapes, lives in Getting started.


What cascade generates

A generate-workflow run emits, unconditionally:

File Purpose
.github/workflows/orchestrate.yaml Runs on merge to trunk: validate, build, deploy to the first environment, finalize state.
.github/workflows/promote.yaml Manually dispatched: cascades the same built artifact through the rest of the environment chain.
.github/workflows/cascade-hotfix.yaml Patches a single environment out of band without touching the others.
.github/workflows/cascade-rollback.yaml Rolls an environment back to its previous deployed version.
.github/actions/manage-release/action.yaml Composite action that creates, updates, and publishes the GitHub release.

Opt-in companions (drift-check, PR-preview, pin-reconcile) are emitted only when their manifest block is present. See Generated workflows for the full anatomy of each file.


Capabilities

Capability What it does
Change detection Builds and deploys run only when their declared triggers match changed paths.
Dependency ordering depends_on and optional_depends_on chain builds and deploys in the right order.
Matrix builds Fan a single build out over a matrix of dimensions, with max_parallel and fail_fast.
Concurrency control Configurable group and cancel_in_progress on orchestrate, promote, hotfix, rollback, release, and external-update workflows.
Extra triggers Attach schedule, repository_dispatch, workflow_run, and merge_group events to orchestration.
Least-privilege permissions Per-callback permissions: blocks scope each caller job, including OIDC id-token: write.
Action pinning pin_mode: tag (default) or sha, with an embedded action-pins manifest and an opt-in reconcile companion.
PR plan preview An opt-in comment on each PR shows which builds and deploys would run.
Breaking-change gate feat!: or BREAKING CHANGE: commits block the prerelease-to-release boundary unless overridden.
Artifact passing The artifact_id output from a build is stored in state and forwarded to deploys and publish.
GitHub Environments The environments command emits per-environment config (required_reviewers, wait_timer, branch_policy) for you to apply.
Schema enforcement Every CLI invocation checks schema_version and rejects incompatible manifests with a clear error.

A manifest that puts a few of these to work: web builds only after api, and each build and deploy runs only when its triggers match the changed paths.

# .github/manifest.yaml
ci:
  config:
    schema_version: 1
    trunk_branch: main
    cli_version: v0.9.1
    environments: [dev, staging, prod]
    builds:
      - name: api
        workflow: .github/workflows/build-api.yaml
        triggers: ["api/**"]
      - name: web
        workflow: .github/workflows/build-web.yaml
        triggers: ["web/**"]
        depends_on: [api]
    deploys:
      - name: services
        workflow: .github/workflows/deploy.yaml
        triggers: ["api/**", "web/**"]

Full field-by-field detail lives in the manifest reference.


Documentation

Start here
Why Cascade What cascade is, when to use it, and how it compares to adjacent tools.
How Cascade works The mental model: trunk, environment chain, release boundary.
Getting started Install, scaffold or hand-write a manifest, and run your first pipeline.
Task guides
Adopt an existing pipeline Migrate without a rewrite; coexist with tools you already use.
Promote a release Trigger and watch a promotion.
Run a hotfix Patch one environment without touching the others.
Roll back an environment Revert an environment to its previous version.
Reference
Manifest Every manifest field, its emission status, and its default.
CLI Every command, flag, environment variable, and exit code.
Callback contract The inputs and outputs your build/deploy/publish workflows exchange with cascade.
Generated workflows The exact file set and the anatomy of each generated workflow.

See the full sidebar for the rest, including security and internals.


Conventions

cascade follows these conventions in its own codebase and in the generated workflows it produces:

  • Additive manifest changes: new fields are always optional with sensible defaults, so existing manifest files keep working across minor version bumps.
  • Conventional commits: commit messages follow type: subject (for example feat:, fix:, docs:), and the changelog generator reads this format.
  • Callback isolation: generated workflows call your workflows via workflow_call, and cascade never reaches into your callback logic.
  • Metadata courier: cascade passes artifact identifiers and versions between stages. It never touches your container registry, package registry, or deployment target directly.

Development

# Build
go build -o cascade ./cmd/cascade

# Test (all packages)
go test ./...

# E2E tests (requires Docker)
cd e2e && go test -v -timeout 20m ./...

# Lint
golangci-lint run ./...

# Regenerate cascade's own workflows (uses itself)
go run ./cmd/cascade generate-workflow --config .github/manifest.yaml -f

Contributing

Contributions are welcome. Please read CONTRIBUTING.md for development setup and workflow details.

cascade uses the Developer Certificate of Origin. Sign off each commit with git commit -s. By participating you agree to the Code of Conduct.


License

Apache 2.0. See LICENSE.

Directories

Path Synopsis
cmd
cascade command
internal
branchprotection
Package branchprotection emits the JSON body an operator applies to GitHub's branch-protection API for a cascade-managed trunk.
Package branchprotection emits the JSON body an operator applies to GitHub's branch-protection API for a cascade-managed trunk.
environments
Package environments emits a per-environment configuration file an operator applies to GitHub's Environments REST API.
Package environments emits a per-environment configuration file an operator applies to GitHub's Environments REST API.
external
Package external provides CLI commands for handling external repo notifications.
Package external provides CLI commands for handling external repo notifications.
fleetreconcile
Package fleetreconcile holds the run-ledger reconcile core that backs the fleet-reconcile reusable workflow.
Package fleetreconcile holds the run-ledger reconcile core that backs the fleet-reconcile reusable workflow.
fleetreconcile/cmd command
Command fleet-reconcile is the runnable wrapper around the fleetreconcile core.
Command fleet-reconcile is the runnable wrapper around the fleetreconcile core.
git
globals
Package globals provides access to global CLI flags and state.
Package globals provides access to global CLI flags and state.
graph
Package graph drives the cascade visualizer from the command line.
Package graph drives the cascade visualizer from the command line.
hotfix
Package hotfix plans and validates per-environment hotfixes that apply a trunk commit onto an environment pinned to an older trunk base.
Package hotfix plans and validates per-environment hotfixes that apply a trunk commit onto an environment pinned to an older trunk base.
initcmd
Package initcmd implements the "cascade init" command, which scaffolds a new project: it renders a starter manifest and matching reusable-workflow stubs, self-checks them through the real generator, and writes them to disk so a repository can adopt cascade with a working configuration on the first try.
Package initcmd implements the "cascade init" command, which scaffolds a new project: it renders a starter manifest and matching reusable-workflow stubs, self-checks them through the real generator, and writes them to disk so a repository can adopt cascade with a working configuration on the first try.
log
Package log provides structured logging with INFO, DEBUG, and TRACE levels.
Package log provides structured logging with INFO, DEBUG, and TRACE levels.
orchestrate
Package orchestrate provides CLI commands for CI/CD orchestration.
Package orchestrate provides CLI commands for CI/CD orchestration.
output
Package output provides helpers for outputting data to GitHub Actions and JSON.
Package output provides helpers for outputting data to GitHub Actions and JSON.
pinreconcile
Package pinreconcile implements the pin-reconciliation engine: adopting an external action-pin change back into the manifest and regenerating so every owned file agrees with it again.
Package pinreconcile implements the pin-reconciliation engine: adopting an external action-pin change back into the manifest and regenerating so every owned file agrees with it again.
plan
Package plan implements the read-only "cascade plan" command.
Package plan implements the read-only "cascade plan" command.
reset
Package reset provides functionality to reset test repositories by wiping releases, tags, and optionally resetting state in the manifest.
Package reset provides functionality to reset test repositories by wiping releases, tags, and optionally resetting state in the manifest.
rollback
Package rollback implements the `cascade rollback` command: explicit re-promotion of a prior version or SHA to a target environment.
Package rollback implements the `cascade rollback` command: explicit re-promotion of a prior version or SHA to a target environment.
scaffold
Package scaffold renders a starter cascade manifest and the matching reusable-workflow stubs for a project, so a new repository can adopt cascade with a working, self-consistent configuration on the first try.
Package scaffold renders a starter cascade manifest and the matching reusable-workflow stubs for a project, so a new repository can adopt cascade with a working, self-consistent configuration on the first try.
schema
Package schema embeds the hand-authored JSON Schema for the cascade manifest and exposes it to the CLI and to editors.
Package schema embeds the hand-authored JSON Schema for the cascade manifest and exposes it to the CLI and to editors.
statewrite
Package statewrite provides the shared optimistic-lock retry used by every finalize verb (orchestrate, promote, rollback, hotfix) when it commits the manifest to the trunk branch through the GitHub Contents REST API.
Package statewrite provides the shared optimistic-lock retry used by every finalize verb (orchestrate, promote, rollback, hotfix) when it commits the manifest to the trunk branch through the GitHub Contents REST API.
verify
Package verify implements the read-only "cascade verify" command.
Package verify implements the read-only "cascade verify" command.
version
Package version provides semantic versioning utilities for release management.
Package version provides semantic versioning utilities for release management.
visualize
Package visualize builds a render-agnostic view of a cascade pipeline and emits it as a diagram.
Package visualize builds a render-agnostic view of a cascade pipeline and emits it as a diagram.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL