.tf files, and your state — Ravion becomes the place where plans and applies run, get reviewed, and get approved.
Nothing is imported or recreated. An rvn-stack module points at your repo and your existing backend. The first plan reads your current state; if your infrastructure has no drift, it shows no changes.
What you get
Everyrvn-stack module runs your organization’s change pipeline — terraform:plan → approval → terraform:apply — on temporary EC2 runners in your AWS account. Your code, variables, and credentials never enter the Ravion control plane.
Two independent inputs decide what each git event runs. Each accepts none, plan, or plan_and_apply:
planrunsterraform:planand finishes. Nothing is applied. Review the plan in the Ravion run view or with the CLI; posting it to the PR as a comment and commit check is coming soon.plan_and_applyruns the full pipeline and stops at the approval gate. Only runs you approve apply, and the apply uses exactly the plan file you reviewed.nonedoesn’t start a run for that event.
ravion stack trigger-pipeline, or Plan / Apply / Destroy in the dashboard) always target the primary branch and aren’t affected by these inputs.
Pick your git workflow
- Plan on the PR, apply from the primary branch
- Plan and apply from the PR, then merge
primary_branch_autoapprove_enabled: true. Plans that destroy or replace resources still stop for approval.pull_request_runs and primary_branch_runs require rvn-stack 1.3.0 or later. Earlier versions run plan → approve → apply on every push and every pull request.Before you start
Keep your existing state backend
Keep your existing state backend
use_ravion_state_backend to false so Ravion uses the backend block already in your configuration (S3 + DynamoDB, Terraform Cloud, and so on). This input is immutable after creation, so get it right the first time.Leave use_ravion_state_backend at its default (true) only for a new configuration that declares an empty terraform { cloud {} } block — Ravion then hosts state for you. Turning it on for an existing configuration would start from empty state and plan to create everything.Let the runner authenticate with its own role
Let the runner authenticate with its own role
AdministratorAccess.Make sure your provider and backend blocks work with the default credential chain — remove hardcoded profile, access_key, or shared_credentials_files settings. If your provider uses assume_role into another account, that role’s trust policy must allow the runner account. If your state bucket is encrypted with a customer-managed KMS key, the plan role needs kms:Decrypt on that key.Pick OpenTofu (recommended) or Terraform
Pick OpenTofu (recommended) or Terraform
rvn-stack runs OpenTofu or Terraform. Only open-source Terraform releases (below 1.6.0) are available, and Terraform refuses to read state written by a newer Terraform version — so if your state was written by Terraform 1.6 or later, choose OpenTofu. OpenTofu reads state written by Terraform; see the OpenTofu migration guide for the version pairing that matches your current Terraform release.Once OpenTofu writes state, keep using OpenTofu for that stack.Move local-only inputs into module inputs
Move local-only inputs into module inputs
-var-fileflags →terraform_variable_files(paths relative tobase_path)-varflags →tf_variables- Environment variables, including
TF_VAR_*and provider tokens →env_variables, withfrom_secrets_managerorfrom_parameter_storefor secret values
Use an agent
The steps are the manual walkthrough below — copy this prompt into your coding agent in the repository containing your Terraform code:Connect this repo's Terraform to Ravion and run the first plan.
Manual walkthrough
Add an rvn-stack module to your project config
ravion.yaml, add one module instance per Terraform root module (one per environment is typical). Point repo and base_path at the directory that holds your .tf files. The highlighted lines are the ones that matter for an existing stack — keep your state backend, and choose where applies happen:watch_paths defaults to <base_path>/**, so changes outside the root module directory don’t trigger runs. Add shared module directories if your root module references them:rvn-stack inputs reference for every field. If you don’t have a project yet, ravion project config apply creates it — see Project config file.Apply the config and run the first plan
PIPELINE_RUN_ID for the run it started. Wait for it to reach the approval gate and read the plan:ravion module create --initial-stack-run PLAN.Confirm the plan matches what you expect
Open a pull request
watch_paths and open a PR against main. With pull_request_runs: plan, Ravion plans the branch and nothing applies. The run appears on the stack’s Runs tab in the dashboard; posting the summary back to the PR as a comment and commit check is coming soon.Read the full plan from the run, or from the CLI:pull_request_runs: plan_and_apply, the same run also stops at an approval gate; approving it applies the PR branch. Only do this if you chose the apply-from-PR workflow.Merge, then approve the primary branch run
main. With primary_branch_runs: plan_and_apply, Ravion runs a fresh plan against the merged commit and your current state — it doesn’t reuse the PR plan, so it can’t be stale. When the run reaches the approval gate, review and approve in the dashboard or with the CLI:primary_branch_autoapprove_enabled: true to skip this step for non-destructive plans.If you apply from PRs instead (primary_branch_runs: none), merging starts nothing — the branch was already applied.Ad-hoc plans and drift checks
Trigger a run on the primary branch at any time, regardless ofprimary_branch_runs. A run with no changes finishes on its own; one with changes stops at the approval gate, so this doubles as a drift check:
Next steps
Import into a Terraform Stack
Terraform Stack module
rvn-stack input reference: triggers, tfvars, environment variables, state backend options.