Deploy do GitHub
Clona, faz o build e publica um repo do GitHub no VPS; deploy a cada push, histórico por fases e rollback.
- Categoria: Servidores e infraestrutura
- Estado: Disponível
- Requisitos: Um VPS ativo da empresa com a função
deploy_githubdisponível; A conta do GitHub de quem vincula, conectada à ArduMaker com acesso ao repo; Ser membro da empresa com acesso a esse VPS (no Git um membro faz o mesmo que um admin) - Ferramentas MCP (Só leem):
listar_repos_github_vps,ver_repo_github_vps,listar_commits_repo_github_vps,ver_commit_repo_github_vps,listar_logs_repo_github_vps,ver_log_repo_github_vps,ver_asistente_git_app,ver_config_deploy_app,ver_propietarios_github,ver_operacion_app - Ferramentas MCP (Escrevem ou modificam):
instalar_app,vincular_repo_github_vps,crear_repo_github_vps,editar_repo_github_vps,redeploy_repo_github,guardar_config_deploy_app,controlar_app - Ferramentas MCP (Destrutivas):
eliminar_repo_github_vps,desinstalar_app,publicar_repo_en_dominio
O que permite fazer?
O deploy de Git leva um repositório do GitHub para um VPS e o mantém atualizado: clona, faz o build, deixa rodando como serviço systemd (ou contêiner), publica com HTTPS e faz o deploy de novo a cada push na branch escolhida.
- Detectar o que é o repo (Node, Django, Python, site estático, Docker, Procfile) e propor comandos de build e início.
- Declarar em um documento de deploy as fases (
pre_pull,install,build,release), os processos (serviços, temporizadores, tarefas pontuais, estáticos, Docker, TCP), as variáveis de ambiente e a publicação. - Fazer deploy automático a cada push, manual, ou de um commit específico da branch.
- Voltar ao commit de um deploy anterior que terminou bem.
- Ver o histórico de deploys com cada fase, seus tempos e os comandos com a saída (com os segredos ocultos).
- Criar um repositório novo no GitHub pela ArduMaker e fazer o deploy.
Quando convém usar?
- Um site, uma API ou um worker que vive no GitHub e precisa ficar sempre igual à branch principal.
- Tarefas agendadas do projeto (um
timer) que precisam viajar com o código. - Uma equipe que quer ver qual commit está em produção e poder voltar atrás sem entrar no servidor.
Como funciona na ArduMaker?
1. Vincular e clonar
Há duas portas. A recomendada é instalar como app (instalar_app com app_type: git, repo_id, branch e, se quiser, port e o documento deploy): fica no inventário de Apps e a operação é durável. A outra é a aba GitHub do VPS (vincular_repo_github_vps), que só clona e roda em segundo plano.
Ao vincular, a ArduMaker cria no GitHub um webhook com um segredo próprio do repo: cada entrega chega assinada com HMAC-SHA256 e sem nada secreto na URL. O repo é clonado em <pasta-do-deploy>. A URL com o token do GitHub fica na pasta .git, que pertence a root e não pode ser lida pela app.
2. Detectar e configurar
ver_asistente_git_app lista os repos que a conta do GitHub pode ler, suas branches e, com repo e branch, o que detecta lendo os arquivos sem executar nada: framework, comandos de build e início e uma porta livre do VPS. Os formatos conhecidos são Docker (também Compose), Procfile, Node web, Django, site estático Vite, Python web e manual. Uma migração proposta sempre chega sem confirmar: o documento não valida até que uma pessoa a confirme.
O que cada deploy roda é sempre um documento: o salvo com guardar_config_deploy_app ou, se o repo nunca salvou um, o derivado dos scripts de sempre (pre-pull, post-pull e serviços). Salvar um documento migra o repo: a partir daí manda o documento.
3. Deploy por fases
Cada deploy roda estas fases em ordem e as registra no histórico. Se uma falhar, as seguintes não rodam e o repo fica em error com um texto curto (Deploy failed at the <fase> phase), nunca a saída bruta de um comando.
| Fase | O que faz |
|---|---|
preparar | Usuário Linux da app, pasta da plataforma, arquivos de variáveis, Docker se necessário |
pre_pull | phases.pre_pull na pasta do clone |
pull | Traz a branch (ou deixa a pasta no commit pedido) |
install | phases.install, passo longo |
build | phases.build, passo longo; depois os contêineres dos processos docker |
release | A migração, só se confirmada |
procesos | Escreve ou reinicia unidades, temporizadores e tarefas pontuais |
publicar | Server block do domínio no nginx do VPS, se o perfil publica |
salud | Verifica se a app responde ou se as unidades continuam vivas |
Com a app instalada em Apps, o deploy é executado pelo runner de operações e é retomado se o worker cair. Um repo sem app roda o mesmo deploy em segundo plano. Vários pushes seguidos são agrupados: no máximo um deploy rodando e um na fila por app.
O que muda realmente?
<pk> é o número do repo na ArduMaker. Com policies.run_as: "root" o usuário não é criado e tudo pertence a root.
| O quê | Onde | Dono e modo |
|---|---|---|
| Usuário da app | ardu-app<pk>, de sistema, sem login | — |
| Clone | <pasta-do-deploy> | do usuário; .git de root |
| Pasta da plataforma | /etc/ardumaker/deploy/ardu-repo<pk>/ | root:ardu-app<pk> 0750 |
| Variáveis de execução e de build | …/run.env, …/build.env | ardu-app<pk> 0600 |
| Scripts de cada passo e sua saída | …/install.sh, build.sh, release.sh, <paso>.log | 0750 / root |
| Serviço principal | /etc/systemd/system/ardu-repo<pk>.service | root 0644 |
| Outros processos e temporizadores | ardu-repo<pk>-<proceso>.service / .timer | root 0644 |
| Contêineres | ardu-repo<pk>, ardu-repo<pk>-<proceso> | — |
| Server block | /etc/nginx/sites-available/<dominio>.conf | — |
Uma unidade que não mudou só é reiniciada; uma que mudou é reescrita. Uma unidade adotada (de um repo antigo) é reiniciada e nunca é escrita nem apagada. O que um deploy criou e o documento já não tem é apagado no deploy seguinte.
O documento de deploy
É um JSON versionado (schema_version: 2). É lido com ver_config_deploy_app e substituído inteiro com guardar_config_deploy_app (apply=true o aplica na hora com um reconfigure).
| Parte | Valores |
|---|---|
profile | static, web, worker, scheduled, job, docker, network e code (só código: em cada push traz o repositório e mais nada; sem instalar, compilar, migrar, processos nem publicação) |
phases | pre_pull, install, build e release (command, confirmed, on_update) |
processes | Até 20, do tipo service, timer (com schedule), oneoff, static, docker ou tcp; portas de 1024 a 65535, sem repetir |
network.publish.mode | none, auto_subdomain, domain, port |
network.health.type | http, unit, timer, static |
env | Lista de {name, value} com scope build, run ou ambos |
policies | build_timeout_s 60–7200 (600 por padrão, por passo), memory_max_mb e cpu_quota_pct sem limite por padrão, run_as (app_user ou root), rollback_on_failed_health |
autodeploy | enabled: se um push faz deploy |
Variáveis e segredos
Uma variável com nome de segredo (*_TOKEN, *_PASSWORD, *_KEY…), com secret: true ou com uma URL que traz usuário e senha é guardada criptografada e no documento fica só a referência. Na leitura, env mostra só {name, scope, has_value}, nunca um valor. Enviar uma variável sem value mantém a guardada.
- Os valores são escritos em
run.envebuild.env(0600) só na fasepreparar. Um valor com quebra de linha é recusado. - Mudar uma variável de build (
NEXT_PUBLIC_*,VITE_*) obriga a compilar de novo: oreconfigurefaz isso com o mesmo código e sem release. - No log de cada comando a carga secreta é substituída pelo tamanho e a saída leva cada segredo oculto (
[redacted]).
Passos longos, limites e saúde
install, build e release rodam cada um em uma unidade transitória própria, com o usuário da app, /tmp privado e set -e (para no primeiro comando que falhar):
sudo systemd-run --unit=ardu-deploy<pk>-<paso> --wait --collect --pipe \
-p User=ardu-app<pk> -p RuntimeMaxSec=<build_timeout_s> -p NoNewPrivileges=yes -p PrivateTmp=yes \
-p EnvironmentFile=/etc/ardumaker/deploy/ardu-repo<pk>/build.env \
/bin/bash /etc/ardumaker/deploy/ardu-repo<pk>/<paso>.sh| Saúde | O que se verifica |
|---|---|
http | curl em 127.0.0.1:<porta><caminho> até 25 vezes; sem expect vale qualquer resposta que não seja 5xx |
unit | Cada unidade ativa duas vezes com 8 s de intervalo e sem novos reinícios |
timer | O .timer habilitado e ativo, e seu horário válido |
static | A pasta existe e o nginx do VPS responde sem 5xx para o domínio |
Portas e publicação
A app escuta em uma porta interna do VPS. Se for instalada por Apps sem port (ou com "auto"), é usada a primeira porta livre. As portas dos motores e do agente nunca são publicadas. O endereço automático é git-<id> dentro da zona da plataforma; também é possível usar um domínio próprio que aponte para o VPS.
A fase publicar escreve o server block no nginx do VPS; o DNS, o proxy até o VPS, o certificado e a verificação do link por HTTPS são feitos pela publicação de Apps. Se essa parte falhar (por exemplo, o DNS ainda não propagou), a nova tentativa publica sem refazer o build. Um nginx editado à mão não é sobrescrito.
Push, commits específicos e rollback
- Um push de outra branch é ignorado. Com
autodeploydesligado, uma entrega repetida do GitHub ou um deploy já rodando, o push registra os commits mas não faz deploy, e a resposta diz por quê. redeploycomcommit_shadeixa a pasta nesse commit da branch e roda umupdatenormal, com release se confirmada.rollbackcomrun_idvolta ao commit de um deploy que terminou bem (git reset --hard <sha>) com a configuração atual. Um deploy de outro repo, um que falhou ou o que já está publicado é recusado.- Com
rollback_on_failed_health: true, um deploy disparado por push que falha emsaludvolta uma vez ao último commit saudável e desliga o autodeploy, deixando o motivo registrado.
Desvincular um repo
Excluir o repo remove o que o documento criou: unidades e temporizadores, contêineres, a pasta da plataforma, o usuário da app com sua pasta e a entrada de safe.directory; depois a unidade e o contêiner principais, o clone e o webhook do GitHub. O que foi adotado não é tocado.
Esquema
- GitHub: push na branch seguida; webhook assinado
- Backend da ArduMaker: registra commits e enfileira o deploy
- Agente do VPS: executa cada fase
- Clone + build:
systemd-runcomoardu-app<pk> - `ardu-repo<pk>.service`: a app em
127.0.0.1:<porta> - nginx do VPS: server block do domínio
- Internet: HTTPS no domínio publicado
Resultado esperado
O repo fica pulled (ou online após a instalação) com last_commit_sha igual ao commit que está na pasta. ver_repo_github_vps traz last_runs: origem (webhook, manual ou mcp), commits, resultado e como foi cada fase. Se foi publicado, ver_app mostra a URL HTTPS só quando o link foi verificado.
systemctl status ardu-repo<pk>.service
curl -I http://127.0.0.1:<puerto>/Erros e resolução
| Erro | Causa | Tentar de novo? |
|---|---|---|
github_no_vinculado | Quem pede não tem GitHub conectado ou o token venceu | Sim, após reconectar o GitHub |
repo_inaccesible / rama_inexistente | A conta não lê o repo ou a branch não existe | Não |
clon_fallido / github_no_responde | O clone falhou (não deixa nada) ou o GitHub não respondeu | Sim |
puerto_ocupado | Outro app do VPS já usa essa porta | Com outra porta |
deploy_en_curso | Já havia outro deploy rodando nesse repo | Sim, quando terminar |
preparacion_fallida, pull_fallido, build_fallido, release_fallida, app_no_arranco, salud_fallida, nginx_del_vps_invalido | A fase que falhou | Manualmente, nunca sozinho |
config_invalida | O documento não valida; errors por caminho (processes.web.port) | Corrigindo o documento |
preparar failed - missing value for <VARIABLE>: falta o valor de uma variável; o deploy para antes de tocar o VPS.- Aviso
limits_not_applied: o VPS recusou os limites de memória ou CPU e o passo rodou sem eles. - Aviso
health_check_failed: em um repo de configuração herdada a saúde que não passa é um aviso, não um erro. - A app responde só em
[::1]: o nginx do VPS chega por127.0.0.1; é preciso escutar em127.0.0.1ou0.0.0.0.
Onde olhar: ver_repo_github_vps (últimos deploys e fases), listar_logs_repo_github_vps e ver_log_repo_github_vps (comando e saída, com o token e os segredos ocultos), e ver_operacion_app para a operação de Apps.
Relação com MCP
O deploy de Git tem acesso MCP completo; referência em /mcp/docs e /mcp/deploy. As escritas podem ser feitas por qualquer membro com acesso ao VPS, exceto um agente autorizado como somente leitura.
| Tipo | Ferramentas |
|---|---|
| Leitura | listar_repos_github_vps, ver_repo_github_vps, listar_commits_repo_github_vps, ver_commit_repo_github_vps, listar_logs_repo_github_vps, ver_log_repo_github_vps, ver_asistente_git_app, ver_config_deploy_app, ver_propietarios_github |
| Modificam | instalar_app, vincular_repo_github_vps, crear_repo_github_vps, editar_repo_github_vps, guardar_config_deploy_app, redeploy_repo_github, controlar_app, publicar_repo_en_dominio |
| Destrutivas | eliminar_repo_github_vps, desinstalar_app |
controlar_app sobre um app git aceita redeploy (com commit_sha opcional), rollback (com run_id) e reconfigure (aplica o documento sem trazer código). publicar_repo_en_dominio faz em uma chamada domínio, verificação, ativação com SSL, server block e instalação; com simular=true mostra o plano e com desde retoma onde falhou.