A run is an OpenTofu plan of a workspace’s configuration, followed by policy checks and, once you approve it, an apply. Runs execute in an isolated run environment.
Run kinds
| Kind | Dashboard label | What it does |
|---|---|---|
plan_and_apply |
Plan and apply | Plan, policy, approval, then apply |
plan_only |
Plan only | Plan and policy; never applies |
speculative |
Speculative plan | Pull-request plan and policy; never applies and never writes state |
drift_check |
Drift check | Scheduled refresh-only plan that looks for drift; never applies, never writes or locks state |
Destroy runs (tofu destroy, tofu plan -destroy) are not supported. A
normal plan that removes resources shows them in its destroy count and can be
applied after review.
Remote runs don’t accept -var or -var-file. Set inputs as
workspace variables instead.
Start a run
| From | How | Run kind |
|---|---|---|
| GitHub push | Push to the workspace’s tracked branch | Plan and apply |
| GitHub pull request | Open or update a pull request against the tracked branch | Speculative plan |
| OpenTofu CLI | tofu apply in a directory with a cloud {} block |
Plan and apply |
| OpenTofu CLI | tofu plan |
Plan only |
| REST API | POST /v1/runs with workspace_id and configuration_version_id |
Any except drift check |
| Schedule | Turn on drift detection for the workspace | Drift check |
See GitHub source connections and OpenTofu CLI for setup.
Every run (GET /v1/runs/{run_id}) includes the configuration_version_id
it ran, so you can start another run from the same configuration through the
REST API or the stackship_create_run MCP tool.
If the workspace’s state changes while a run is being queued (for example,
another apply finishes or someone runs tofu state push), the run is refused
with 409 STATE_INPUT_OUTDATED. Nothing started; start the run again.
Every change requires human approval. -auto-approve is rejected with an
error asking you to rerun without it; tofu apply then waits for approval in
the terminal or the dashboard. A plan with no changes finishes without
approval.
Pull requests from forks never receive cloud credentials, state, or access to your private module registry. Sensitive workspace variables are never passed to speculative plans.
Find runs
Runs in the sidebar lists every run in the organization, newest first.
Filter by text (run ID, message, or workspace), status, workspace, or kind.
Filters are kept in the URL, so you can share a view such as
/runs?status=awaiting_approval or /runs?kind=drift_check.
Review a run
The run page shows, from top to bottom:
- Header — the run message (or commit), status, run ID, kind, workspace, commit, author, and duration, plus Cancel run while the run is active.
- Stages — Plan, Policy, Approval, and Apply, each with its status and duration, and the plan’s create, change, and destroy counts.
- Plan changes — each changed resource with its address, provider, action, and attribute-level before and after values. Sensitive values are redacted and unknown values are marked.
- Stage logs — expand a stage to read its log.
- Approval bar — Approve plan and Discard run while a decision is needed. See Run approvals.
When a run fails, the header shows the reason and the last lines of the failing log.
Downloads
| Download | Who can use it |
|---|---|
| Redacted plan | Anyone who can read the run |
| Raw plan | Owners and admins, with a reason |
| Emergency state | Owners and admins, for recovery only |
Raw downloads are recorded in the audit log with the reason you enter.
From the API, use GET /v1/runs/{run_id}/plan-changes for the redacted
resource changes and GET /v1/runs/{run_id}/logs for logs.
GET /api/v2/plans/{plan_id}/json-output returns the machine-readable plan
(up to 100 MB). It contains sensitive values, so only owners and admins
signed in with tofu login can read it, and every read is recorded in the
audit log. Workspace tokens can’t read it.
GitHub checks
Runs started from GitHub report their status to the commit or pull request as a GitHub check. StackShip doesn’t send Slack, email, or webhook notifications for runs. The one exception is the email owners and admins get when drift detection finds drift.
Next steps
- Run lifecycle — what each status means
- Run approvals — approve, discard, and cancel
- Run environment — versions, the six execution regions, and limits
- Policy sets — the checks between plan and approval