diff --git a/CHANGELOG.md b/CHANGELOG.md index e67d07fd..4797e795 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,8 @@ A `Migration` section is added to any release that bumps `schema_version`. ## [Unreleased] +## [0.16.1] - 2026-07-15 + ### Security - **setup-cli:** Verify the release archive checksum and the cosign signature @@ -589,7 +591,8 @@ Initial release of cascade: a trunk-based CI/CD orchestrator for GitHub Actions. - Self-hosted CI: cascade manages its own build, release, e2e, and promote workflows using the same manifest. -[Unreleased]: https://github.com/stablekernel/cascade/compare/v0.16.0...HEAD +[Unreleased]: https://github.com/stablekernel/cascade/compare/v0.16.1...HEAD +[0.16.1]: https://github.com/stablekernel/cascade/compare/v0.16.0...v0.16.1 [0.16.0]: https://github.com/stablekernel/cascade/compare/v0.15.0...v0.16.0 [0.15.0]: https://github.com/stablekernel/cascade/compare/v0.14.2...v0.15.0 [0.14.2]: https://github.com/stablekernel/cascade/compare/v0.14.1...v0.14.2 diff --git a/README.md b/README.md index 9cb6308e..31c41caa 100644 --- a/README.md +++ b/README.md @@ -93,7 +93,7 @@ A single `generate-workflow` run compiles the manifest into the orchestrate, pro - **SHA-keyed promotion ladder.** Promote the exact bytes that passed the previous environment, never a per-stage rebuild. See [Promote a release](https://stablekernel.github.io/cascade/guides/promote/). - **Security by construction.** Every caller job carries a per-callback least-privilege `permissions:` block, including OIDC `id-token: write`. See [Callback contract](https://stablekernel.github.io/cascade/reference/callbacks/). - **Self-healing supply chain.** Third-party action pins live in one source of truth, and a reconcile companion adopts external pin bumps back into the manifest. See [Action pins](https://stablekernel.github.io/cascade/guides/action-pins/). -- **Hotfix and rollback, race-safe.** Patch or revert a single environment with correct, race-safe concurrency. See [Run a hotfix](https://stablekernel.github.io/cascade/guides/hotfix/) and [Roll back an environment](https://stablekernel.github.io/cascade/guides/rollback/). +- **Hotfix and rollback, race-safe.** Patch or revert a single environment with correct, race-safe concurrency. Hotfix currently cherry-picks, builds, tags, and releases the fix; its generated deploy step is a placeholder, so running the deploy workflow is a manual follow-up. See [Run a hotfix](https://stablekernel.github.io/cascade/guides/hotfix/) and [Roll back an environment](https://stablekernel.github.io/cascade/guides/rollback/). Preview a pipeline before you merge: [`simulate`](https://stablekernel.github.io/cascade/guides/simulate-and-verify/) traces what a change would build and deploy, and [`graph`](https://stablekernel.github.io/cascade/guides/visualize/) renders the environment chain. diff --git a/docs/src/content/docs/guides/hotfix.md b/docs/src/content/docs/guides/hotfix.md index b2448d04..6341a140 100644 --- a/docs/src/content/docs/guides/hotfix.md +++ b/docs/src/content/docs/guides/hotfix.md @@ -19,7 +19,11 @@ gh workflow run cascade-hotfix.yaml \ -f target_env=test ``` -The `plan` job fetches env branches and tags and runs `cascade hotfix plan`. The `apply` job then cherry-picks the fix onto a per-environment integration branch and opens a resolution pull request labeled `cascade-hotfix` (or `cascade-hotfix-conflict` if the cherry-pick collides). Merging that pull request runs build, deploy, and finalize, which write the diverged state. +The `plan` job fetches env branches and tags and runs `cascade hotfix plan`. The `apply` job then cherry-picks the fix onto a per-environment integration branch and opens a resolution pull request labeled `cascade-hotfix` (or `cascade-hotfix-conflict` if the cherry-pick collides). Merging that pull request runs build and finalize, which writes the diverged state, tags the hotfix version, and creates the release. + +:::caution[Known limitation: the hotfix deploy jobs are placeholders] +The deploy and rollback jobs in `cascade-hotfix.yaml` do not yet invoke the configured deploy workflow. Each one holds the target's GitHub `environment:` gate, prints the deploy it stands in for, and succeeds. A green hotfix run therefore cherry-picks, builds, and finalizes (state, tag, release), but does not deploy the fix. Ship it yourself by running the configured deploy workflow against the hotfix merge SHA. The standalone `cascade-rollback.yaml` workflow is not affected; its deploy jobs invoke the real deploy callbacks. +::: ## Environment branches and the stale-branch self-heal @@ -56,7 +60,7 @@ A hotfix allocates its own version segment so it sorts correctly relative to the - **plan** surfaces branch-protection suggestions as `::notice::` lines when `env/*` has no required checks configured; cascade never creates protection rules itself. - **The resolution pull request** is the audit record even when no human touches it. It merges as the configured `state_token`, not `GITHUB_TOKEN`, because a `GITHUB_TOKEN` merge does not emit the event that triggers build/deploy/finalize. - **A diverged environment blocks normal promotion** until the divergence clears. Promotion into it later requires the incoming trunk SHA to contain every recorded patch; dropping one is refused unless explicitly forced. -- **Prod is a valid target.** The deploy job binds to the GitHub `environment:` of the target, so required reviewers and wait timers apply exactly as they do for a normal promotion. +- **Prod is a valid target.** The deploy job binds to the GitHub `environment:` of the target, so required reviewers and wait timers apply exactly as they do for a normal promotion. The job behind that gate is still the placeholder described above; approval does not run the configured deploy workflow. ## Wayfinding diff --git a/docs/src/content/docs/reference/cli.md b/docs/src/content/docs/reference/cli.md index b77e43c3..e0f52295 100644 --- a/docs/src/content/docs/reference/cli.md +++ b/docs/src/content/docs/reference/cli.md @@ -629,8 +629,9 @@ elevates the commit set bottom-up across the environment chain, up to and includ target environment, on each environment's `env/` integration branch. The fixes must already be on trunk; cascade refuses to apply any commit that is not an ancestor of trunk tip. The subcommands compute and validate the hotfix and write its final state; the -cherry-pick, build, and deploy run in the generated `cascade-hotfix.yaml` workflow. See -[Run a hotfix](/cascade/guides/hotfix/) for the full flow. +cherry-pick and build run in the generated `cascade-hotfix.yaml` workflow, whose deploy +and rollback jobs are placeholders that do not yet invoke the configured deploy workflow. +See [Run a hotfix](/cascade/guides/hotfix/) for the full flow and the limitation. #### hotfix plan diff --git a/docs/src/content/docs/reference/generated-workflows.md b/docs/src/content/docs/reference/generated-workflows.md index 01032a33..aec1e4e7 100644 --- a/docs/src/content/docs/reference/generated-workflows.md +++ b/docs/src/content/docs/reference/generated-workflows.md @@ -101,7 +101,7 @@ When the manifest has a `publish:` callback, promote adds a publish step that ru ## Hotfix and rollback workflows -Both carry two triggers in one file and both mirror the promote deploy shape. Full operational detail lives in the [hotfix](/cascade/guides/hotfix/) and [rollback](/cascade/guides/rollback/) guides; this is the job-level anatomy. +Both carry two triggers in one file. Rollback re-runs the same deploy callbacks promote drives; the hotfix deploy jobs are placeholders (see the caution below). Full operational detail lives in the [hotfix](/cascade/guides/hotfix/) and [rollback](/cascade/guides/rollback/) guides; this is the job-level anatomy. ### `cascade-hotfix.yaml` @@ -111,11 +111,15 @@ Both carry two triggers in one file and both mirror the promote deploy shape. Fu | apply | `workflow_dispatch` (not dry-run) | Cherry-pick onto each environment bottom-up; opens a resolution pull request. | | check | `pull_request` opened against `env/*` | Validate the manifest while the hotfix pull request is open. | | build | merged hotfix pull request | Build the merge SHA (a cherry-pick has no prebuilt artifact). | -| deploy | merged hotfix pull request | Deploy to the target environment, paired with a rollback job mirroring promote. | -| finalize | all deploys succeed | Run `cascade hotfix finalize`: write the diverged state, tag, and release. | +| deploy | merged hotfix pull request | Placeholder: holds the target's GitHub `environment:` gate and prints the configured deploy, but does not invoke it. Paired with an equally placeholder rollback job. | +| finalize | deploy jobs succeed | Run `cascade hotfix finalize`: write the diverged state, tag, and release. | Dispatch inputs: `commit` (one or more trunk fix SHAs), `target_env` (every configured environment except the first), `pr_number` (optional, to replay an existing resolution pull request), `dry_run`. The second trigger is `pull_request` on `types: [closed]` against `branches: ['env/*']`, gated on the pull request having merged with the `cascade-hotfix` label. +:::caution[Known limitation: hotfix deploy and rollback jobs do not deploy] +The `deploy-` and `rollback-` jobs in `cascade-hotfix.yaml` print the deploy they stand in for and succeed, even when the manifest configures a deploy `workflow:`. A green hotfix run cherry-picks, builds, writes the diverged state, tags, and creates the release, but never invokes the configured deploy workflow; run it yourself against the hotfix merge SHA to ship the fix. The `cascade-rollback.yaml` deploy jobs are real reusable-workflow calls and are not affected. +::: + ### `cascade-rollback.yaml` | Job | Role | diff --git a/docs/src/content/docs/start/how-it-works.md b/docs/src/content/docs/start/how-it-works.md index c00b8299..364abdd2 100644 --- a/docs/src/content/docs/start/how-it-works.md +++ b/docs/src/content/docs/start/how-it-works.md @@ -60,7 +60,7 @@ The boundary is positional, not a named environment. The second-from-top environ - **Generated file:** `cascade-rollback.yaml`. - **Fires on:** `workflow_dispatch`, plus `repository_dispatch` when `rollback.repository_dispatch` is set so an external signal can trigger it. -**Hotfix** patches an environment off a divergent branch instead of trunk, so an urgent fix can ship to one environment without waiting for the full chain. The patched ref rejoins the chain through manifest state. +**Hotfix** patches an environment off a divergent branch instead of trunk, so an urgent fix can target one environment without waiting for the full chain. The patched ref rejoins the chain through manifest state. The workflow cherry-picks, builds, tags, and releases the fix; its deploy jobs are placeholders for now, so running the configured deploy workflow is a manual step (see [Run a hotfix](/cascade/guides/hotfix/)). - **Manifest field:** two or more `environments` (the hotfix workflow is emitted whenever the environment chain can diverge). - **Generated file:** `cascade-hotfix.yaml`.