Dois deploys em producao da mesma branch
Voce tem um repositorio (ex.: um miniSMTP) e precisa rodar dois deploys em producao com configuracoes diferentes — dominios, HELO, credenciais de relay. Mesmo codigo, mesma branch, configs distintas.
Feito do jeito errado, um deploy sobrescreve o outro. Este guia mostra o jeito que nao quebra.
O que quebra (e por que)
Se voce simplesmente registra a mesma branch duas vezes:
- o
.deploy.ymle um so (esta na branch compartilhada) — colocar os dois configs literais nele faz um sobrescrever o outro; - o bundle cifrado tem um caminho no repo — dois registros escrevendo no mesmo nome se clobberam;
runner addbloqueia o segundo registro (exige--force-duplicate);- e ha uma nuance de qual instancia o deploy escolhe — resolvida na v2.55.1 (veja Qual instancia o deploy escolhe).
O anti-pattern e por o valor especifico de cada deploy dentro do manifesto. A branch e compartilhada; o manifesto so pode carregar o formato.
O principio
.deploy.yml → SHAPE: nome da instancia, {{::REFERENCIAS}}, literais COMUNS
secret.enc → VALORES de cada deploy (namespaced por instancia)Detalhes em Hierarquia env/secrets.
Saida recomendada: um manifesto por deploy
Cada deploy ganha seu proprio manifesto dentro do mesmo repo. Assim cada registro tem uma unica instancia — sem ambiguidade de "qual instancia deployar" — alem de app dir, ckey e bundle proprios.
1. Crie um manifesto por deploy no repo
seu-repo/
├── src/
├── deploy/
│ ├── cliente-a/.deploy.yml
│ └── cliente-b/.deploy.ymldeploy/cliente-a/.deploy.yml:
project: smtp-cliente-a
system: sys
type: sys
image: python:3.12-slim
port: 2525
github:
repo: usuario/smtp-mini
dist_branch: main
version:
source: git-commit
environment:
SMTP_MAX_SIZE: "26214400" # literal COMUM aos dois
SMTP_HELO: mx.clientea.com # literal DESTE deploy
secrets:
SMTP_RELAY_PASSWORD: "{{::SMTP_RELAY_PASSWORD}}" # referencia; valor no bundle
healthcheck:
tcp: 2525
instances:
cliente-a: # UMA instancia por manifesto
domain: mx.clientea.com
source:
type: dist
keep_versions: 3deploy/cliente-b/.deploy.yml e igual, trocando project, SMTP_HELO, o nome da instancia (cliente-b) e o dominio.
Como cada manifesto tem uma unica instancia, ela e o default — e tanto
runner deployquantofetch --deployacertam sozinhos.
2. Registre os dois (cada um com sua ckey)
runner add --repo usuario/smtp-mini --branch main \
--token "$(gh auth token)" \
--manifest-path deploy/cliente-a/.deploy.yml \
--slug smtp-cliente-a \
--instance cliente-a \
--ckey "<ckey-do-cliente-a>"
runner add --repo usuario/smtp-mini --branch main \
--token "$(gh auth token)" \
--manifest-path deploy/cliente-b/.deploy.yml \
--slug smtp-cliente-b \
--instance cliente-b \
--ckey "<ckey-do-cliente-b>"| Flag | Papel |
|---|---|
--manifest-path |
aponta o manifesto daquele deploy (implica --force-duplicate quando ja existe outro app do mesmo repo) |
--slug |
nome/diretorio proprio do registro (/data/apps/smtp-cliente-a) — isola .env/.secrets/state |
--instance |
fixa a instancia do registro e namespaceia o bundle (secrets.cliente-a.enc) |
--ckey |
chave propria — o bundle de A nunca abre com a ckey de B |
3. Preencha os valores sensiveis (por registro)
runner env set --secret smtp-cliente-a SMTP_RELAY_PASSWORD 'senha-do-A'
runner env set --secret smtp-cliente-b SMTP_RELAY_PASSWORD 'senha-do-B'Valor com caractere especial vai sempre aqui (o store e verbatim), nunca no manifesto — as aspas sao do seu shell.
4. Deploy
runner deploy smtp-cliente-a
runner deploy smtp-cliente-bCada um sobe com seu dominio, seu env e seus secrets. No repo, os bundles ficam separados:
.runner/
├── secrets.cliente-a.enc # so abre com a ckey de A
└── secrets.cliente-b.enc # so abre com a ckey de BAlternativa: manifesto unico com `instances:`
Se a config que diverge e apenas nao-sensivel (dominio, HELO, portas) e os secrets sao os mesmos, da pra usar um manifesto so com duas instancias:
instances:
cliente-a:
domain: mx.clientea.com
source: { type: dist }
environment_overrides: # prioridade maxima
SMTP_HELO: mx.clientea.com
cliente-b:
domain: mx.clienteb.com
source: { type: dist }
environment_overrides:
SMTP_HELO: mx.clienteb.comLimites desta alternativa:
- Uma ckey por registro.
state.ckeye um campo unico por app registrado — duas instancias no mesmo registro compartilham ckey e.env/.secrets. Se os secrets divergem, use a saida recomendada. - Rodar
runner set-ckeycom uma ckey diferente da ja registrada retorna erro loud (exit 1) sem escrever nada.
Qual instancia o deploy escolhe (v2.55.1+)
A partir da v2.55.1, runner deploy, runner deploy --all e runner fetch --deploy resolvem a instancia da mesma forma: state.instance (a instancia com que o app foi registrado via runner add --instance <N>) → default do manifesto → production.
Ou seja, num manifesto com duas instancias, cada registro deploya a sua instancia registrada — tanto no manual quanto no cron.
runner deploy smtp-cliente-b # honra state.instance = cliente-b
runner fetch --deploy smtp-cliente-b # idemEm runners anteriores a v2.55.1, os deploys manuais (
deploy/--all) ignoravamstate.instancee miravam sempre a instancia default do manifesto — so ofetch --deployrespeitava o registro. Se voce esta numa versao antiga, atualize (runner self-update) ou registre um manifesto por deploy (a saida recomendada, que elimina a ambiguidade em qualquer versao).
Verificacao
runner list # os dois registros, dominios distintos
runner manifest smtp-cliente-a # manifesto resolvido daquele deploy
runner secrets show smtp-cliente-a # abre so com a ckey de A
runner status smtp-cliente-bArmadilhas
| Nao faca | Por que |
|---|---|
| Dois blocos de config literais no mesmo manifesto | a branch e compartilhada — um sobrescreve o outro |
| Mesma ckey nos dois deploys | vazou uma, abriu as duas (perde o blast-radius) |
Mesmo --slug (ou sem slug) |
os registros colidem no mesmo app dir |
Sem --instance |
os bundles colidem no mesmo nome no repo |
| Secret com caractere especial no manifesto | o YAML reinterpreta $, {}, # — use env set --secret |
Veja tambem
- Hierarquia env/secrets — o contrato
secret.enc > env > deploy.yml. - Secrets por instancia — isolamento por servidor e o failover de resolucao do bundle.
- Anatomia do .deploy.yml — schema completo.