Pipeline de Release

Do cargo build ate o agent baixar a versao nova via tatuzim-agent self-update. O fluxo e totalmente automatizado depois do gh release create.

Visao geral

[dev: /proj/tatuzim/server]
        |
        |  ./build_multiarch.sh         (cross-compile musl x86_64 + aarch64)
        v
   tatuzim-agent-x86_64.zip + tatuzim-agent-aarch64.zip
        |
        |  gh release create vX.Y.Z ...
        v
[GitHub Release]  ────── webhook ──────>  [GitOps Worker]
                                                 |
                                                 |  baixa ZIPs do release
                                                 |  assina com minisign (tatuzim-release.key)
                                                 |  publica em B2 (bucket ccs-systems, folder tatuzim/)
                                                 v
                                          [B2: backblaze]
                                                 |
                                                 |  proxy via CDN backend
                                                 v
                                  https://get.tatuzim.com/...
                                                 |
                                                 |  HTTPS via Traefik + Cloudflare
                                                 v
                              [tatuzim-agent self-update na VPS]

Tudo orquestrado: cada gh release create reflete em https://get.tatuzim.com/ em segundos.

1. Build local (multi-arch)

Toda binarizacao acontece no servidor de dev (regra /proj/CLAUDE.md — sem build remoto). O script build_multiarch.sh usa `cross` pra compilar musl-static em ambas as arquiteturas.

cd /proj/tatuzim/server

# Release (ambas as arches — obrigatorio antes de publicar)
./build_multiarch.sh

# Dev/teste rapido (so x86_64)
./build_multiarch.sh --arch amd

Saida (release):

tatuzim-agent-x86_64.zip      (~3 MB, musl static)
tatuzim-agent-aarch64.zip     (~3 MB, musl static)

Cada ZIP contem apenas o binario tatuzim-agent (sem README, sem manifest). Padrao GitOps.

Versao e extraida automaticamente do [workspace.package].version em Cargo.toml.

2. Criar GitHub Release

cd /proj/tatuzim
VERSION=$(grep '^version' server/Cargo.toml | head -1 | sed -E 's/.*"([^"]+)".*/\1/')

gh release create "v$VERSION" \
    --title "v$VERSION" \
    --notes "Notas em PT-BR — o que mudou nesta versao" \
    server/tatuzim-agent-x86_64.zip \
    server/tatuzim-agent-aarch64.zip

A release deve estar published (nao draft) — o GitOps so processa releases publicas.

3. GitOps Worker processa

Configurado em /proj/tatuzim/.gitops.yml (v3.0). O Worker:

  1. Recebe webhook do GitHub Release
  2. Baixa os ZIPs anexos
  3. Extrai os binarios (tatuzim-agent)
  4. Assina cada binario com a chave minisign de release (/proj/.secrets/tatuzim-release/tatuzim-release.key)
  5. Publica em B2 no caminho ccs-systems/tatuzim/<arch>/...

Layout publicado em B2

ccs-systems/tatuzim/
  latest                              -> ponteiro pra ultima versao stable
  x86_64/
    tatuzim-agent                     (binario)
    tatuzim-agent.minisig             (assinatura)
    tatuzim-agent.zip                 (ZIP original)
  aarch64/
    tatuzim-agent
    tatuzim-agent.minisig
    tatuzim-agent.zip
  vX.Y.Z/                             (versionado, preservado)
    x86_64/
      tatuzim-agent
      tatuzim-agent.minisig
    aarch64/
      tatuzim-agent
      tatuzim-agent.minisig

Versoes antigas sao preservadas (ate max_versions: 10 em .gitops.yml).

Release Candidates

Tags vX.Y.Z-rc.N em branch dev saem em canal RC, separadas das stable:

ccs-systems/tatuzim/rc/
  x86_64/tatuzim-agent
  aarch64/tatuzim-agent
  vX.Y.Z-rc.1/...

Agent so consome RC se o self-update for chamado com --rc (futuro).

4. CDN serve a partir do B2

O dominio get.tatuzim.com esta mapeado no CDN sys (cdn.borlot.com.br) pra servir o folder tatuzim/ do bucket ccs-systems:

  • Path rule /tatuzim/** → bucket ccs-systems
  • Domain get.tatuzim.com → path rule /tatuzim/**
  • Traefik gera config dinamica em /opt/traefik/dynamic/cdn_tatuzim_ccs_systems.yml
  • Cloudflare proxy (CNAME get.tatuzim.com → cdn.borlot.com.br) com TLS na borda

Quando o GitOps termina o upload, o conteudo ja esta disponivel em:

https://get.tatuzim.com/x86_64/tatuzim-agent
https://get.tatuzim.com/x86_64/tatuzim-agent.minisig
https://get.tatuzim.com/aarch64/tatuzim-agent
https://get.tatuzim.com/aarch64/tatuzim-agent.minisig
https://get.tatuzim.com/vX.Y.Z/x86_64/tatuzim-agent

Detalhes de URLs em Distribuicao.

5. Agent consome via self-update

O agent ja instalado pode atualizar sozinho:

# Detecta arch automaticamente:
sudo tatuzim-agent self-update --url https://get.tatuzim.com/x86_64

Fluxo interno:

  1. GET <url>/tatuzim-agent → binario novo
  2. GET <url>/tatuzim-agent.minisig → assinatura
  3. Verifica com a pubkey embutida no proprio binario atual (compile-time)
  4. Se valido: atomic rename → swap
  5. Se invalido: aborta sem mudar nada

Pubkey embutida (compile-time): RWSeTpgYV+16Z//WwZku61OpIYgaU8iyyN/dEYm7bOGru0vFTbdLSAcD

Pubkey publica: https://get.tatuzim.com/tatuzim-release.pub (futuro — hoje vem embutida).

Tempo total

Etapa Duracao
build_multiarch.sh (cold cache) 3-5 min
build_multiarch.sh (sccache quente) 30-60s
gh release create + GitOps webhook < 10s
GitOps download + sign + upload B2 5-15s
Cloudflare cache invalidation imediato (cache-control: max-age=300)

Tipicamente de cargo build ate o self-update puxar a versao nova: menos de 5 minutos.

Troubleshooting

Release feito mas CDN ainda devolve versao antiga

  1. Confere se o GitOps processou: curl -s https://gitops.borlot.com.br/api/processed?repo=devborlot/tatuzim | head
  2. Confere B2 direto: b2 file list ccs-systems tatuzim/x86_64/
  3. Cloudflare cache: curl -sI https://get.tatuzim.com/x86_64/tatuzim-agent | grep -i cf-cache — se HIT, purgar via dashboard

Build falhando com glibc

Use o script multiarch — ele compila com musl static, evitando dependencia de glibc do host. Nunca rode cargo build --release diretamente pra release.

Webhook do GitOps deu 401

A GITHUB_WEBHOOK_SECRET no GitHub config tem que bater com o env do container GitOps. Verificar em https://github.com/devborlot/tatuzim/settings/hooks

Proximos passos

By Borlot.com.br on 07/06/2026