Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
77 changes: 77 additions & 0 deletions docs/src/content/docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ ci:
| `cli_version` | string | No | latest | CLI version: `latest`, `beta`, or specific version (e.g., `v2.0.4`) |
| `cli_version_sha` | string | No | - | 40-hex commit SHA that `cli_version` resolves to. With `pin_mode: sha`, the generated setup-cli ref is pinned to this commit. See [cli_version_sha](#cli_version_sha). |
| `triggers` | list | No | - | Global path patterns that activate orchestration |
| `release_trigger` | string | No | `push` | How the orchestrate workflow fires. `push` keeps the push-on-trunk plus `workflow_dispatch` triggers; `dispatch` drops the `push:` trigger so releases run only on manual `workflow_dispatch`. See [Release trigger](#release-trigger). |
| `pin_mode` | string | No | `tag` | Third-party action pin policy. `tag` emits `<action>@<major-tag>`; `sha` emits `<action>@<commit-sha>` with the version as a trailing comment. See [Action pinning](#action-pinning). |
| `action_pins` | map | No | - | Per-action ref overrides keyed by action path (e.g. `actions/checkout`), applied regardless of `pin_mode`. See [Action pinning](#action-pinning). |
| `tag_prefix` | string | No | `v` | Version tag prefix |
| `release_token` | string | No | `state_token` if set, else `${{ secrets.GITHUB_TOKEN }}` | Token expression for release API calls and the rc tag; inherits `state_token` when unset so the rc-to-release chain has a trigger-capable token |
| `state_token` | string | No | `${{ secrets.GITHUB_TOKEN }}` | Token expression for writing manifest state to the trunk branch |
Expand Down Expand Up @@ -124,6 +127,46 @@ The `with: version:` input the action reads to select the release asset stays th

This closes the supply-chain gap where the cascade self-action was referenced by a mutable tag while third-party actions were already SHA-pinned. The field is optional and only takes effect under `pin_mode: sha`; leave it unset (or use the default `pin_mode: tag`) to keep the tag-based ref. Set `cli_version_sha` alongside `cli_version` whenever you bump the pinned version. Because cascade release tags are annotated, resolve the underlying commit (not the tag object) with `git ls-remote https://github.com/stablekernel/cascade 'refs/tags/<tag>^{}'`.

### Release trigger

`release_trigger` selects how the generated orchestrate workflow fires. It is opt-in; repos that leave it unset keep the push triggers.

| Value | Behavior |
|-------|----------|
| `push` | Default. Orchestrate fires on trunk pushes (filtered by `triggers:`) plus `workflow_dispatch`. |
| `dispatch` | Drops the `push:` trigger so orchestrate runs only on `workflow_dispatch`, letting a maintainer-owned gate decide when a release candidate is cut. |

```yaml
ci:
config:
release_trigger: dispatch
```

### Action pinning

cascade governs how the third-party actions it emits into your workflows (for example `actions/checkout` and `actions/github-script`) are referenced. Two fields control the policy.

`pin_mode` sets the reference style for every third-party action cascade emits:

| Value | Behavior |
|-------|----------|
| `tag` | Default. Emits `<action>@<major-tag>` (for example `actions/checkout@v4`). Never `@latest`. |
| `sha` | Emits `<action>@<commit-sha> # <version>`, pinning each action to an immutable commit with the human-readable version as a trailing comment. Under `sha`, pair `cli_version` with [`cli_version_sha`](#cli_version_sha) so the cascade self-action ref is pinned too. |

The default `sha` values come from a single committed pin table (`internal/generate/action_pins.yaml`); no per-repo configuration is needed to adopt SHA pinning beyond setting `pin_mode: sha`.

`action_pins` overrides the built-in ref for individual actions, keyed by action path. The map value is the bare ref emitted after `@` for that same action path (a tag or a commit SHA); it cannot repoint an action to a different owner or repository. An override is applied regardless of `pin_mode`, so use it to hold an action at a known-good commit or tag:

```yaml
ci:
config:
pin_mode: sha
action_pins:
actions/checkout: 0123456789abcdef0123456789abcdef01234567
```

That emits `uses: actions/checkout@0123456789abcdef0123456789abcdef01234567`. An action that is neither in the built-in table nor overridden is emitted unchanged.

### Token authentication

Two seams call GitHub on cascade's behalf: `release_token` for release API calls and `state_token` for writing manifest state back to the trunk branch. Both default to `${{ secrets.GITHUB_TOKEN }}`, which is enough for a single-repo project whose trunk is unprotected. When the default token cannot do the job, supply your own token through one of two paths: a static secret (PAT) or a GitHub App.
Expand Down Expand Up @@ -554,6 +597,40 @@ Behavior:
- **Least-privilege scope.** The toggle adds `deployments: write` to the workflow's top-level permissions only when enabled; the OFF-state output is unchanged.
- **Opt-in and additive.** Omit `deployments` and nothing is emitted. The field did not bump `schema_version`.

### Validate-check workflow (opt-in)

Set `validate_check.enabled: true` and `generate-workflow` emits a lightweight `pull_request` workflow (`.github/workflows/cascade-validate.yaml`) that runs [`cascade parse-config`](/cli-reference/#parse-config) against the manifest and fails the check when the configuration is invalid, so a malformed manifest cannot merge to trunk.

```yaml
ci:
config:
validate_check:
enabled: true
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | false | Emit the manifest-validation PR check (`.github/workflows/cascade-validate.yaml`) |

The check validates cascade's own configuration only. It does not run the repository's build or test suites, requests `contents: read` alone, and has no dry-run or comment side effects.

### Merge-queue workflow (opt-in)

Set `merge_queue.enabled: true` and cascade emits a `merge_group`-triggered workflow (`.github/workflows/cascade-merge-queue.yaml`) that validates the prospective trunk commit: it runs `cascade parse-config` as a validity gate and a dry-run `cascade orchestrate setup` to preview the build and deploy decisions against the merge-group candidate ref.

```yaml
ci:
config:
merge_queue:
enabled: true
```

| Field | Type | Default | Description |
|-------|------|---------|-------------|
| `enabled` | bool | false | Emit the merge-queue validation lane (`.github/workflows/cascade-merge-queue.yaml`) |

The lane is read-only: no state writes, no releases, no deploys. It reports a status the merge queue can require. This generator owns the lane behavior; the raw `merge_group` trigger itself is expressible separately under `extra_triggers.merge_group`, and the two are intentionally distinct.

## State Section

The `state` section tracks deployment state per environment plus a synthetic `release` slot. The framework manages it automatically. Do not hand-edit.
Expand Down
6 changes: 4 additions & 2 deletions internal/generate/action_pins.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,10 @@ func mustParseActionPins(data []byte) map[string]actionPin {
// uniformly and no ref is missed.
//
// Resolution order:
// 1. config.action_pins[action]: explicit per-action override (any ref/sha),
// applied regardless of pin_mode. Use this for forks or org-mirrored actions.
// 1. config.action_pins[action]: explicit per-action ref override (a tag or
// sha), applied regardless of pin_mode. The override is the bare ref after
// "@" for the same action path; it cannot repoint to a different owner/repo.
// Use it to hold an action at a known-good commit or tag.
// 2. pin_mode: sha: emit <action>@<sha> # <version> from the built-in table.
// 3. pin_mode: tag (default): emit <action>@<tag>, today's behavior, never
// @latest for a third-party action.
Expand Down
Loading