Continuous deployment
For CI, keep state remote, gate environments by branch, and let the
pipeline run lithos deploy.
Two things matter most: remote state so every runner sees the same
graph, and branch-based gates so only main (or your release
branch) can touch production.
Prerequisites
-
Remote state configured for the project.
-
An Open Cloud API key with the right scopes — see Authentication.
-
A
ROBLOSECURITYcookie with permission to manage the experiences this project owns. -
A
lithos.ymlwhoseprodenvironment hasbranches: [main]:lithos.ymlenvironments: - label: dev targetNamePrefix: environmentLabel branches: [develop] - label: prod targetAccess: public branches: [main]
Secrets
Add four repository secrets (Settings → Secrets and variables → Actions):
| Secret | Value |
|---|---|
ROBLOSECURITY | Your Roblox cookie. |
LITHOS_OPEN_CLOUD_API_KEY | Your Open Cloud key. |
LITHOS_AWS_ACCESS_KEY_ID | S3 / R2 access key. |
LITHOS_AWS_SECRET_ACCESS_KEY | S3 / R2 secret. |
Use LITHOS_* in new CI and team docs so your workflow matches the current
examples. Legacy MANTLE_* variables are still accepted for compatibility.
A minimal workflow
name: Deploy
on:
push:
branches: [main, develop]
workflow_dispatch:
jobs:
deploy:
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@v4
- name: Install Foreman
uses: Roblox/setup-foreman@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Pick environment
id: env
run: |
if [ "${GITHUB_REF}" = "refs/heads/main" ]; then
echo "label=prod" >> "$GITHUB_OUTPUT"
else
echo "label=dev" >> "$GITHUB_OUTPUT"
fi
- name: Deploy
env:
ROBLOSECURITY: ${{ secrets.ROBLOSECURITY }}
LITHOS_OPEN_CLOUD_API_KEY: ${{ secrets.LITHOS_OPEN_CLOUD_API_KEY }}
LITHOS_AWS_ACCESS_KEY_ID: ${{ secrets.LITHOS_AWS_ACCESS_KEY_ID }}
LITHOS_AWS_SECRET_ACCESS_KEY: ${{ secrets.LITHOS_AWS_SECRET_ACCESS_KEY }}
run: lithos deploy --environment ${{ steps.env.outputs.label }} --plain-previewNotes:
--plain-previewremoves ANSI escape sequences for log viewers. Non-TTY runs auto-approve after printing the plan.- Preflight still runs and fails early on missing keys, wrong universe scope, and similar issues.
- Keep the branch-to-environment mapping in the workflow and the
branches:guard inlithos.yml. - Foreman pins the Lithos version used by CI.
If a deploy finishes in a bad state, run lithos undo --environment <label> --plain-preview against the same remote state backend.
Pull-request previews
For pull requests, run lithos diff --live and post or archive the result.
It shows planned changes and surfaces drift without applying.
name: Diff
on:
pull_request:
branches: [main, develop]
jobs:
diff:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: Roblox/setup-foreman@v1
with:
token: ${{ secrets.GITHUB_TOKEN }}
- name: Diff
env:
ROBLOSECURITY: ${{ secrets.ROBLOSECURITY }}
LITHOS_OPEN_CLOUD_API_KEY: ${{ secrets.LITHOS_OPEN_CLOUD_API_KEY }}
LITHOS_AWS_ACCESS_KEY_ID: ${{ secrets.LITHOS_AWS_ACCESS_KEY_ID }}
LITHOS_AWS_SECRET_ACCESS_KEY: ${{ secrets.LITHOS_AWS_SECRET_ACCESS_KEY }}
run: lithos diff --environment dev --live --plain-preview--live is useful here because it catches dashboard edits before they
surprise the next deploy.