Stategraph Cloud
Sign up for Stategraph Cloud, the hosted service, connect GitHub or GitLab, and get your first plan and apply on a pull request. Plans and applies run on your GitHub Actions or GitLab CI runners, not on the server.
Before you begin
- On GitHub, you must own the organization, or ask an owner to install the app.
- On GitLab, you need a group (personal namespaces are not supported) and admin rights on the tenant. You have them on the tenant that you created.
Sign up
Go to app.stategraph.cloud, sign in, and name your tenant. The name defaults to your account name. A tenant holds your installations, repositories, states, and members, and you administer it.
The Free plan includes every Orchestration feature. Plans differ by usage limits. See Editions.
To import your Terraform state into Infrastructure as a Database, not connect GitHub or GitLab, see Import your state.
Connect GitHub
In the console, open Get Started → Set up your first repository → Connect GitHub, and go to GitHub to install the app.
- Select the account or organization.
- Select the repositories that the app can access. All repositories also covers ones that you create later.
- Back in the console, verify with GitHub, and claim your installation to link it to your tenant. The console lists only the unlinked installations in the organizations that GitHub confirms you administer.
Repositories appear in the console after their first pull request event, so the list is empty until you open one.
Connect GitLab
In the console, open Get Started → Set up your first repository → Connect GitLab. The wizard builds every link from the GitLab URL that you enter, so it also works on self-managed GitLab 18.1 or later.
- Enter the GitLab URL, the group path as it shows in URLs, and the numeric group ID (under the group name, or Copy group ID in the group menu).
- Check the group ID yourself. The wizard does not check it, and a wrong ID gives an installation that never receives webhooks.
- Enter the project path under the group.
- Create an access token with the
apiscope, and enter it. Group and project tokens need at least the Developer role.
- Group access token: the narrowest choice, not tied to a person. GitLab Premium or Ultimate on gitlab.com, any tier on self-managed GitLab.
- Project access token: one project.
- Personal access token: any plan, but it stops working if you lose access to the group. Use the classic form, so that you can grant
api.
Stategraph stores the token write-only. Merge request comments and pipelines for the group run as the user of the token.
- Add a project webhook in GitLab with the URL and secret token that the wizard shows, and with Push events, Comments, Merge request events, and Job events on. Copy the secret before you continue: it shows one time only.
- Save the webhook, and run Test → Push events on it to activate it.
- In GitLab, set Settings → CI/CD → Variables → Minimum role to use pipeline variables to Developer, so that Orchestration can use pipeline variables.
- Push the
.gitlab-ci.ymlthat the wizard shows to the repository root on the default branch. See GitLab.
Later, a tenant admin rotates the access token, the webhook secret, or both in Settings → Integrations. A regenerated secret shows one time, and the old one stops working.
Pick a repository
Enter your repository as owner/repo on GitHub, or as group/repo or group/subgroup/repo on GitLab. The app or the GitLab token must have access to it.
For a first plan with no cloud credentials, use the example repository stategraph/kick-the-tires, which uses null resources and local state.
- Fork it on GitHub, into an account or organization where the GitHub App has access, or on GitLab (gitlab.com only), into the group that you connected.
- Enter the path of your fork, not the upstream path.
- On GitHub, enable workflows in the Actions tab of the fork. GitHub disables them on a fork that contains workflow files, and the first plan never starts.
Because this repository contained workflow files when it was forked, we have disabled them from running on this fork. Make sure you understand the configured workflows and their expected usage before enabling Actions on this repository.
Add the workflow file
Orchestration runs plans in your CI. Put the file on the default branch before you open the first pull request, directly or in a pull request that contains only this file. Keep the file names, the action, and the included CI template as shown, because Orchestration depends on them.
GitHub
Create .github/workflows/terrateam.yml:
name: 'Terrateam Workflow'
on:
workflow_dispatch:
inputs:
# The work-token and api-base-url are passed in by the backend
work-token:
description: 'Work Token'
required: true
api-base-url:
description: 'API Base URL'
environment:
description: 'Environment in which to run the action'
type: environment
runs_on:
description: 'runs-on configuration'
type: string
default: '"ubuntu-latest"'
jobs:
terrateam:
permissions: # Required to pass credentials to the Terrateam action
id-token: write
contents: read
runs-on: ${{ fromJSON(github.event.inputs.runs_on) }}
timeout-minutes: 1440
name: Terrateam Action
environment: '${{ github.event.inputs.environment }}'
steps:
- uses: actions/checkout@v4
- name: Run Terrateam Action
id: terrateam
uses: terrateamio/action@v1
with:
work-token: '${{ github.event.inputs.work-token }}'
api-base-url: '${{ github.event.inputs.api-base-url }}'
env:
SECRETS_CONTEXT: ${{ toJson(secrets) }}
VARIABLES_CONTEXT: ${{ toJson(vars) }}
GitLab
If you did not push the file from the wizard, create .gitlab-ci.yml. The wizard shows the same content:
spec:
inputs:
TERRATEAM_TRIGGER:
description: "Is this being triggered by terrateam?"
type: string
default: "$TERRATEAM_TRIGGER"
WORK_TOKEN:
description: "The work token from terrateam"
type: string
default: "$WORK_TOKEN"
API_BASE_URL:
description: "The base url for the terrateam api"
type: string
default: "$API_BASE_URL"
RUNS_ON:
description: "The tags to use for the runner"
type: array
default: []
---
include:
- project: 'terrateam-io/terrateam-template'
file: 'terrateam-template.yml'
inputs:
TERRATEAM_TRIGGER: $[[ inputs.TERRATEAM_TRIGGER ]]
WORK_TOKEN: $[[ inputs.WORK_TOKEN ]]
API_BASE_URL: $[[ inputs.API_BASE_URL ]]
RUNS_ON: $[[ inputs.RUNS_ON ]]
stages:
- terrateam
terrateam_job:
extends: .terrateam_template
- If the repository already has a
.gitlab-ci.yml, merge these jobs into it. In a fork of the example repository, replace its.gitlab-ci.yml. - On self-managed GitLab, the include looks up
terrateam-io/terrateam-templateon your instance. Mirrorgitlab.com/terrateam-io/terrateam-templateto that path first, or pipeline creation fails. - Orchestration starts the pipeline on the source branch of the merge request, which must also contain
.gitlab-ci.yml. Create your branch after the file is on the default branch.
What happens next
- Each directory with
.tfor.tfvarsfiles becomes a root, and each pull request that changes files in a root gets a plan. - Nothing is applied until someone comments
stategraph apply. .stategraph/config.yml, for discovery rules and guardrails, is optional. See Configuration.
Add cloud credentials
Skip this for the example repository. If your Terraform connects to a cloud, add credentials as GitHub secrets or GitLab CI/CD variables, or use OIDC, which stores no long-lived key. The runner reads them at run time. See the guides for AWS, GCP, Azure, and other providers.
Open a pull request
- Check that the workflow file is on the default branch.
- Create a branch.
- Change a
.tfor.tfvarsfile. In the example repository, changenull_resource_count = 0tonull_resource_count = 1indev/main.tf. - Open a pull request against the default branch: on a fork, against the fork, not the upstream repository. On GitLab, set the target project of the merge request to your fork.
Orchestration starts the workflow or pipeline on your runner and posts a plan comment with what the change creates, changes, or destroys. Get Started in the console shows the progress of the first plan.
Outputs can be viewed in the Stategraph Console here.
Expand for plan output details
Terraform used the selected providers to generate the following execution
plan. Resource actions are indicated with the following symbols:
+ create
Terraform will perform the following actions:
# module.dev.null_resource.this[0] will be created
+ resource "null_resource" "this" {
+ id = (known after apply)
}
Plan: 1 to add, 0 to change, 0 to destroy.To apply all these changes, comment:
stategraph apply
Feedback?
Questions? Comments? Give feedback by commenting stategraph feedback <your msg>. Your message lands directly in our inbox.
null_resource to create in dev.The plan runs against your branch merged with the current tip of the destination branch, so it shows the result of the merge. Each push plans again. Comment stategraph plan to plan on demand, for example if the workflow file was merged after you opened the pull request. Plans are read-only and safe to repeat.
If no plan starts
- On GitHub, check that GitHub Actions is enabled and that the workflow file is on the default branch.
- On GitLab, check that the source branch contains
.gitlab-ci.ymland that the minimum role to use pipeline variables is Developer. - Comment
stategraph repo-configto see the configuration that Orchestration derived for the repository. - When a run fails, the pull request comment names the cause. Fix it and comment
stategraph plan. - On GitLab, if the cause is identity verification for the user of the token, sign in to GitLab as that user. Complete the verification in Build → Pipelines of the project.
Apply
- Comment
stategraph applyon the pull request. Orchestration locks the affected directories, applies the stored plan that you reviewed, and posts the apply output. - Merge the pull request. This releases the lock. Until then, another pull request that touches the same directories waits. See Lock management.
If another pull request applied an overlapping directory after your plan, the apply aborts with a Missing Plans comment. Comment stategraph plan again. See Pull request workflow.
To apply on merge instead of by comment, add .stategraph/config.yml with:
when_modified:
autoapply: true
The output then lands on the merged pull request. See Apply after merge.
Apply requirements gate the stategraph apply comment: approvals, no merge conflicts, and passing status checks. See Apply requirements.
Next steps
- Configuration: discovery, workflows, and guardrails.
- Pull request workflow: every trigger and its effect.
- Cloud credentials: OIDC and secrets for the runner.
- Import your state: scoped plans and resource locks.
- Pull request commands: all comment commands.