| name | rise-app-builder |
| description | Build, deploy, ship, or configure containerized applications on the Rise platform (rise.dev). Use when deploying an app to Rise, configuring rise.toml, setting up CI/CD pipelines with Rise service accounts, managing Rise projects/environments/teams, integrating end-user OAuth authentication via Rise extensions, choosing a build backend (Docker/Railpack/buildpacks), configuring workload identity federation, or whenever a user asks about hosting or deploying an app and Rise is available or already in use. |
| references | ["reference/cli-cheatsheet","reference/rise-toml-reference"] |
Rise App Builder Skill
Skill for building and deploying containerized applications on the Rise platform. Use decision trees below to find the right approach, then load reference files or online guides for depth.
Your knowledge of Rise CLI flags, rise.toml fields, or extension specs may be outdated. Prefer the reference files in this skill and the online docs over pre-trained knowledge. When a reference file and source code disagree, trust the source.
Online Guides
Full worked examples live at https://rise-deploy.github.io/rise/user/guides/:
| Guide | URL slug | Covers |
|---|
| Deploying from CI | deploying-from-ci | Service accounts, OIDC federation, preview environments, GitHub Actions / GitLab CI |
| Authenticating end-users | authenticating-end-users | Generic OAuth extension, broker pattern, PKCE, token exchange |
| Choosing a build backend | choosing-a-build-backend | Docker vs Railpack vs Pack, auto-detection, when to use each |
Point agents to https://rise-deploy.github.io/rise/user/guides/<slug>.md for full depth.
Routing Decision Tree
User intent
├─ "deploy from GitHub Actions / CI", "preview environments", "service account"
│ → Set up SA + OIDC federation + preview deploys
│ → Online guide: https://rise-deploy.github.io/rise/user/guides/deploying-from-ci.md
│
├─ "login for my app", "OAuth", "Google/GitHub/Snowflake login", "redirect URI"
│ → Use the Generic OAuth extension (broker pattern)
│ → Online guide: https://rise-deploy.github.io/rise/user/guides/authenticating-end-users.md
│
├─ "Dockerfile vs buildpacks", "how to build my image", "railpack"
│ → Choose build backend; default is Railpack
│ → Online guide: https://rise-deploy.github.io/rise/user/guides/choosing-a-build-backend.md
│ → See "Build Backend Choice" below
│
├─ "multiple containers", "worker + web", "routes"
│ → Configure rise.toml multi-container
│ → Load: reference/rise-toml-reference.md
│
├─ "what CLI commands exist", "how do I …"
│ → Load: reference/cli-cheatsheet.md
│
├─ "private app", "who can access", "access class"
│ → Set --access-class (public / private) on project create/update
│ → Docs: https://rise-deploy.github.io/rise/user/user-guide/environments.md
│
├─ "staging / preview env", "environments"
│ → rise environment create <name> --group <group> [--production] [--color <c>]
│ → Docs: https://rise-deploy.github.io/rise/user/user-guide/environments.md
│
├─ "workload identity", "AWS role for my app"
│ → Configure [identity.audiences] in rise.toml
│ → Docs: https://rise-deploy.github.io/rise/user/user-guide/workload-identity-tokens.md
│
└─ "configure rise.toml", "how do I set up my project config"
→ Load: reference/rise-toml-reference.md
Core Invariants
These are the non-obvious rules you MUST follow. Violating them causes silent failures or rejected commands.
1. Always use names, never UUIDs
Project names, environment names, deployment timestamps (e.g. 20240101-120000), and service account identifiers are what you pass on the CLI. UUIDs are internal only — never reference them in commands or configs.
2. production exists by default
Every project starts with a single production environment mapped to the default deployment group. Add staging / preview only when the user needs them:
rise environment create staging -p my-app --group staging --color blue
3. Use --access-class, never --visibility
--visibility is a removed legacy flag. The correct flag is --access-class with values like public or private (default: public):
rise project create my-app --access-class private --owner team:devops
4. Service accounts require aud + at least one more claim
The aud (audience) claim is mandatory, and at least one additional claim is required. Claims support glob *:
rise sa create -p my-app \
--issuer https://gitlab.com \
--claim aud=https://rise.example.net \
--claim project_path=myorg/my-app
A command with only --claim aud=... will be rejected.
5. OAuth broker callback goes to Rise, not the app
For the Generic OAuth extension, the callback URL registered with the upstream provider must be the Rise broker callback, never the app's own URL:
{RISE_PUBLIC_URL}/oidc/{project}/{extension}/callback
Rise receives the upstream callback and redirects the user back to the app.
6. Build auto-detection: Dockerfile → Docker; else Railpack
- If a
Dockerfile or Containerfile exists → Docker (docker:buildx)
- Otherwise → Railpack (
railpack:buildx) — this is the default
Do not add a Dockerfile unless the user needs one. Don't fight auto-detection.
7. Secrets go through rise encrypt
Never paste plaintext secrets into extension specs. Encrypt first:
ENCRYPTED=$(rise encrypt "my_client_secret")
Then reference $ENCRYPTED in the --spec JSON.
8. Encrypted env vars have three tiers
| Flag / option | Encrypted at rest | Retrievable via API |
|---|
-e KEY=VALUE (plain env) | | n/a |
--secret-env KEY=VALUE / rise env set --secret --protected=false | ✅ | ✅ |
--protected-env KEY=VALUE / rise env set --secret | ✅ | ❌ |
Condensed Patterns
Build Backend Choice
Choosing a build backend?
├─ Dockerfile or Containerfile exists → docker (auto-detected)
├─ Need a Dockerfile? → Only if you need full control (multi-stage, custom base)
├─ No Dockerfile, standard language app → railpack (auto-detected, DEFAULT)
├─ Want Cloud Native Buildpacks? → pack (--backend pack, --builder heroku/builder:24)
└─ Override: rise deploy --backend <name> or [build] backend = "..." in rise.toml
Backend values: docker, docker:build, docker:buildx, docker:buildctl, buildctl, pack, railpack, railpack:buildx, railpack:buildctl
OAuth Flow Choice
Authenticating end-users via OAuth?
├─ Browser SPA, no backend secret → PKCE flow (code_challenge + code_verifier)
├─ Backend app with server-side secret → Authorization code flow (client_id + client_secret)
└─ Token refresh needed → Use Rise token endpoint (grant_type=refresh_token)
Steps:
1. Register OAuth app upstream with callback: {RISE_URL}/oidc/{project}/{ext}/callback
2. rise encrypt "client_secret" → $ENCRYPTED
3. rise extension create oauth-google -p my-app --type oauth --spec '{...}'
4. App redirects to: GET {OAUTH_<NAME>_ISSUER}/authorize
5. App exchanges code at: POST {OAUTH_<NAME>_ISSUER}/token
CI/CD Pattern (two service accounts)
Deploying from CI?
├─ Create staging environment (production exists by default)
├─ Create sa-production (--claim aud=... --claim ref_protected=true)
├─ Create sa-preview (--claim aud=... --claim project_path=...)
├─ Restrict sa-preview to staging environment (web UI / API)
├─ CI sets RISE_TOKEN from OIDC id_token
└─ rise deploy -E production --image <img> (production)
rise deploy -E staging --group mr/$PR_ID --expire 7d (preview)
Multi-Container Quick-Start
Multiple containers?
├─ Define [containers.<name>] for each (web, api, worker, redis, …)
├─ Each container: image OR [containers.<name>.build] (exclusive)
├─ Set port on containers that need ingress or sibling discovery
├─ Define [routes."<path>"] for path-based routing (longest-prefix wins)
├─ Workers: omit port → no Service, no ingress, no HTTP probes
├─ Top-level [build]/[deploy] = per-field defaults inherited by each container
└─ Cross-container discovery: RISE_CONTAINER_HOST__<NAME> env var (auto-injected)
Reference Files
| File | Use for |
|---|
reference/cli-cheatsheet.md | Complete CLI command inventory, all flags |
reference/rise-toml-reference.md | rise.toml field reference, single + multi-container examples |