UpuaiUpuai
Configuração como Código

upuai.toml

Configure build, release phase (migrations) e deploy diretamente no repo do seu app. Versionado, revisado em PR. Equivalente a Procfile (Heroku), fly.toml (Fly.io), railway.toml (Railway), netlify.toml (Netlify).

O que é

upuai.toml é um arquivo de configuração declarativa que vive na raiz do rootDirectory do seu service no monorepo (ex: apps/api/upuai.toml). Permite declarar como o Upuai Cloud builda, faz release phase (rodar migrations antes do rollout) e inicia seu app — sem precisar mexer na UI.

Cada plataforma tem seu formato porque tem features que não cabem em formato alheio. O Upuai usa este. É o mesmo padrão de mercado de Procfile (Heroku), fly.toml (Fly.io), railway.toml (Railway), render.yaml (Render), netlify.toml (Netlify).

Quick start

Para um app Node + Prisma rodando migrations automáticas a cada deploy, copie o snippet abaixo para apps/api/upuai.toml (ou upuai.toml na raiz, em single-package). Próximo deploy roda automaticamente.

upuai.toml
#:schema https://upuai.com.br/schemas/upuai-toml-v1.json

[deploy]
releaseCommand = "pnpm exec prisma migrate deploy"

Schema v1 completo

Todas as keys são opcionais. Validação .strict() rejeita keys desconhecidas com erro explícito.

upuai.toml
#:schema https://upuai.com.br/schemas/upuai-toml-v1.json

[build]
builder = "railpack"           # default; outro valor: "dockerfile"
buildCommand = "pnpm build"    # opcional, override do railpack
dockerfilePath = "Dockerfile"  # só pra builder = "dockerfile"

[deploy]
startCommand = "node dist/server.js"
releaseCommand = "pnpm exec prisma migrate deploy"
releaseTimeoutSeconds = 300    # default 300s, max 1800s
healthCheckPath = "/health"
KeyTipoDescrição
build.builder"railpack" | "dockerfile"Build method. Railpack auto-detecta stack; dockerfile usa o Dockerfile do repo.
build.buildCommandstringOverride do comando de build do railpack.
build.dockerfilePathstringPath do Dockerfile (relativo ao rootDirectory). Só pra builder=dockerfile.
deploy.startCommandstringComando que inicia o app (ex: node dist/server.js).
deploy.releaseCommandstringRelease phase: roda em Job efêmero ANTES do rollout (mesma imagem + env vars). Falha bloqueia traffic shift; pods velhos continuam servindo. Tipicamente usado pra migrations de DB. Idempotência é responsabilidade do comando.
deploy.releaseTimeoutSeconds10..1800Timeout do release Job em segundos. Default 300.
deploy.healthCheckPathstringEndpoint HTTP que K8s usa pra readiness. Default vem do framework detectado (NestJS=/health, Spring=/actuator/health, Rails=/up).

Processos (Procfile App)

Declare múltiplos processos (web + worker + release + clock) a partir de um único repositório/build, no estilo Procfile do Heroku. Um push builda a imagem uma vez e roda N processos compartilhando essa imagem — cada um com seu próprio comando, réplicas e recursos. Variáveis de ambiente são compartilhadas por todos os processos (paridade Heroku config vars). Gerencie com `upuai ps`, `upuai scale web=2 worker=1` / `upuai logs --process worker` por processo, ou pela aba Processos no dashboard.

upuai.toml
#:schema https://upuai.com.br/schemas/upuai-toml-v1.json

# 1 push → 1 build → N processos compartilhando a imagem (web + worker + ...).
[processes.web]
command = "bundle exec puma"

[processes.worker]
command = "bundle exec sidekiq"
type = "worker"      # opcional; inferido do nome (web→web, worker→worker, clock/cron→clock)
instances = 2        # opcional; default 1

[processes.release]
command = "bundle exec rails db:migrate"
type = "release"
type é opcional: inferido do nome (web→web, worker→worker, clock/cron→clock, release→release; qualquer outro nome → worker). Apenas um processo web é permitido. release não vira runtime — roda na release phase (mesma semântica do deploy.releaseCommand).

Release Command por framework

Lista curated de commands recomendados. Explicit, sem mágica — copie pro seu upuai.toml.

StackreleaseCommand
Prisma (Node monorepo pnpm)pnpm exec prisma migrate deploy
Prisma (single-package)npx prisma migrate deploy
Drizzlepnpm exec drizzle-kit migrate
TypeORMpnpm typeorm migration:run
Knexpnpm knex migrate:latest
Sequelizepnpm sequelize db:migrate
Djangopython manage.py migrate --noinput
Alembic (SQLAlchemy)alembic upgrade head
Rails (Active Record)bundle exec rails db:migrate
Laravelphp artisan migrate --force
Phoenix / Ecto (Elixir)mix ecto.migrate
golang-migrate (Go)migrate -path migrations -database $DATABASE_URL up
atlas (Go)atlas migrate apply --url $DATABASE_URL
Não vê seu stack? Qualquer comando shell funciona — release phase roda na mesma imagem do seu app, com mesmas env vars. Idempotência é sua responsabilidade. Flyway / Liquibase (Java) geralmente vêm embutidos no startup do Spring Boot, ou em comando standalone.

Monorepo

Cada service tem seu próprio rootDirectory — coloque o upuai.toml em <rootDirectory>/upuai.toml. O rootDirectory é a working directory dos commands releaseCommand e startCommand: eles rodam como se você tivesse feito cd <rootDirectory> antes — sem precisar de pnpm --filter, cd, ou --prefix no command. Services que não precisam de release phase / build customizado simplesmente não criam o arquivo. Ausência = nenhum override.

tree
my-monorepo/
├── apps/
│   ├── api/
│   │   ├── upuai.toml      # service "api" — releaseCommand pra migrations
│   │   └── src/
│   ├── web/
│   │   └── src/            # service "web" — sem upuai.toml (não precisa)
│   └── landing/
│       └── src/            # service "landing" — sem upuai.toml
└── pnpm-workspace.yaml

Precedência

Quando o mesmo campo aparece em mais de uma fonte, esta é a ordem de prioridade aplicada pelo Upuai.

  1. 1

    UI (Service Settings)

    Vence sempre. Use para override operacional sem precisar de PR (ex: aumentar timeout em incident).

  2. 2

    upuai.toml

    Config canonical, versionada, revisada em PR.

  3. 3

    Procfile release: line

    Legacy compat Heroku-style. Continua suportado.

Empty string na UI não bloqueia o valor do toml — só valor não-vazio sobrepõe.

VS Code autocomplete

Adicione a primeira linha apontando para o JSON Schema público. Com a extensão Even Better TOML (tamasfe.even-better-toml), você ganha autocomplete e validação inline.

upuai.toml
#:schema https://upuai.com.br/schemas/upuai-toml-v1.json

[deploy]
releaseCommand = "..."

Versioning

Schema segue SemVer. Mudanças backward-compat (novas keys opcionais) entram como v1.x sem mudar a URL. Breaking changes só num eventual v2 com janela mínima de 6 meses.

v1.x (atual)

Novas keys são opcionais e backward-compat. URL do #:schema continua a mesma.

v2 (futuro)

Breaking changes. URL muda pra upuai-toml-v2.json. Janela de transição mínima de 6 meses com aviso prévio.

FAQ

Perguntas frequentes sobre upuai.toml.

E se o meu repo já tem Procfile?

Continua funcionando. Procfile release: ... é legacy compat. Recomendamos migrar pro upuai.toml pra ganhar mais opções (timeout, health check, etc), mas não é obrigatório.

Como override sem deletar do repo?

Edite o campo na UI (Service Settings → Build & Deploy). UI override sempre vence o toml. Útil pra casos transitórios (incident, debug). v1.1 vai ter botão "Reset to upuai.toml" no painel do service pra limpar override sem deletar valor.

TOML é case-sensitive?

Sim. releaseCommand é diferente de ReleaseCommand.

Posso ter configs diferentes por ambiente (production/staging)?

Não em v1. upuai.toml é por service+rootDirectory, não por environment. Para config por env, use UI Service Settings ou env vars (ex: RELEASE_CMD_PROD, RELEASE_CMD_STAGING e um wrapper script).

Por que não auto-detectam o framework?

Heroku/Railway/Fly não auto-detectam ORM porque há centenas de migration tools (Prisma, Drizzle, TypeORM, Django, Alembic, Rails, Laravel, Flyway, golang-migrate, atlas, etc). Cada um com configurações específicas. Heurística que tenta cobrir isso quebra mais do que conserta. Explicit é o estado-da-arte — você declara o comando, a plataforma roda. Mesma filosofia do web: no Procfile.

Roadmap de v1.1+?

v1.1: [deploy] resources (cpu/memory/instances). v1.2: [networking].egress — declarar allowlist no repo. v1.3: UI editor inline pro arquivo. v1.4: restartPolicy, sleepApplication, autoDeploy. v1.5: [env] block — variáveis NÃO-secret commitáveis (LOG_LEVEL, NODE_ENV). v2: cronSchedule, podSecurityContext, multi-service array.

Recursos

Links para o JSON Schema, CLI e outras referências.