MÓDULO 5.3

🌿 Git, PRs e CI

Fork model, branch off upstream/main, push para origin, PR contra tinyhumansai:main. Pre-push hook, templates, i18n parity, gates de CI — tudo que faz seu PR mergeável sem drama.

6
Tópicos
50
Minutos
Avançado
Nível
Processo
Tipo
1

🍴 Fork setup one-time

Layout obrigatório de remotes: origin aponta pro seu fork, upstream aponta pro tinyhumansai/openhuman (fetch-only). Push direto no upstream polui branches e fura code review.

# Layout esperado
origin    git@github.com:<your-username>/openhuman.git  # push aqui
upstream  git@github.com:tinyhumansai/openhuman.git     # fetch-only

# Se clonou direto do upstream, conserte uma vez:
$ git remote rename origin upstream
$ git remote add origin git@github.com:<your-username>/openhuman.git
$ git fetch upstream

# Verifique
$ git remote -v

💡 Por quê

Push direto pro upstream cria branches no repo principal, polui a UI do GitHub e bypassa o code review (qualquer maintainer pode acabar mergeando sua branch sem PR). Tratando upstream como leitura, você força o fluxo limpo: fork → PR → review.

origin
Seu fork
upstream
tinyhumansai
Fetch
Sempre upstream
Push
Sempre origin
2

🌳 Nunca escreva em main

Antes de qualquer mudança de código, crie uma feature branch a partir do upstream atualizado. Main fica limpa e só avança via merge.

# Workflow padrão antes de qualquer feature
$ git fetch upstream
$ git checkout -b feat/cron-jobs-export upstream/main

# Trabalho, commits, etc.
$ git add -p && git commit -m "feat(cron): add JSON export"

# Quando precisar atualizar com main recente:
$ git fetch upstream
$ git rebase upstream/main

✓ Padrão saudável

  • Branch atômica por feature
  • Nome descritivo (feat/..., fix/...)
  • Rebase sobre upstream/main quando necessário
  • main local sempre limpa

✗ Receita de dor

  • Commit direto em main local
  • Misturar 3 features na mesma branch
  • Branch baseada em fork/main (defasada)
  • git reset --hard sem entender o estado
Base
upstream/main
Sync
git fetch upstream
Atualizar
git rebase upstream/main
Atomicidade
1 PR = 1 propósito
3

🚀 Push e PR: cuidado com --head

Push pra origin, abre PR contra tinyhumansai/openhuman:main usando --head <seu-user>:<branch>. O --head resolve ambiguidade quando a mesma branch existe em múltiplos remotes.

# Push pra seu fork
$ git push origin feat/cron-jobs-export

# PR via gh CLI (recomendado)
$ gh pr create \
    --repo tinyhumansai/openhuman \
    --base main \
    --head <seu-user>:feat/cron-jobs-export \
    --title "feat(cron): JSON export for scheduled jobs" \
    --body-file PR_BODY.md

📋 Templates do repo

  • .github/ISSUE_TEMPLATE/feature.md — pedido de feature
  • .github/ISSUE_TEMPLATE/bug.md — bug report
  • .github/PULL_REQUEST_TEMPLATE.md — corpo do PR

Siga os templates verbatim. AI-authored também — não improvise as seções, apenas preencha.

🎯 Boa estrutura de PR

  • Título: conventional commits (feat(cron): ..., fix(memory): ...)
  • Resumo: o que muda e por quê (não como)
  • Tests: liste o que foi adicionado / atualizado
  • Screenshots/GIFs: para mudanças de UI
  • Breaking changes: seção dedicada se houver
Push
origin
PR target
tinyhumansai:main
Head
seu-user:branch
Template
Verbatim
4

🪝 Pre-push hook (Husky)

Husky roda pnpm rust:check automaticamente antes de cada push. Falha rápida = feedback rápido = menos tempo desperdiçado com CI quebrado.

# Ciclo local antes de pushar
$ pnpm format          # Prettier + cargo fmt
$ pnpm lint            # ESLint --cache
$ pnpm typecheck       # tsc --noEmit (alias: pnpm compile)
$ pnpm rust:check      # cargo check no Tauri shell
$ pnpm test            # Vitest
$ pnpm test:rust       # cargo + mock

# Push (hook roda automaticamente)
$ git push origin feat/cron-jobs-export

⚠️ Quando usar --no-verify

Apenas quando o hook falha em código não relacionado ao seu PR — ex: main atual já está quebrada por motivo alheio.

  • • Se falha no seu código → conserte, não pule.
  • • Se falha em código pré-existente → use --no-verify + mencione no corpo do PR.
  • • Nunca pule hook como atalho preguiçoso. CI vai pegar e PR vai voltar.

💡 Otimização

Configure seu editor pra rodar Prettier on-save e ESLint inline. A maior parte do que o hook checa já estará verde quando você for pushar.

Hook
pnpm rust:check
Format
Prettier + cargo fmt
Types
tsc --noEmit
Bypass
--no-verify (raro)
5

🌍 i18n parity: 12 locales, sem exceção

Toda string visível ao usuário em app/src/** passa por useT(). Chave nova vai em en.ts e no chunk correspondente en-N.ts e na mesma posição em todos os 12 locales. CI bloqueia merge se faltar qualquer chave.

🗂️ Estrutura de chunks

Source of truth são os chunks em app/src/lib/i18n/chunks/:

  • en.ts + en-1.ts, en-2.ts, ..., en-5.ts
  • pt-1.ts...pt-5.ts, es-1.ts...es-5.ts, etc.

Locales obrigatórios: ar, bn, de, es, fr, hi, id, it, ko, pt, ru, zh-CN.

Use o valor em inglês como placeholder nos outros locales — tradutores corrigem depois. O importante é a chave existir.

✓ Padrão correto

const t = useT();
<button label={t('cron.export.button')}>

Chave registrada em en.ts, en-3.ts, e em todos os <loc>-3.ts.

✗ Bloqueia CI

<button label="Export JSON">
<button aria-label="Exportar">

Hard-coded em JSX, label=, placeholder=, aria-label=. Não passa lint nem revisão.

# Roda o gate localmente antes de pushar
$ pnpm i18n:check

# Listará exatamente quais chaves faltam em quais locales

🔍 Exceções permitidas

Logs de debug dev-only, identificadores de código (slug, URL, sentinel), valores técnicos que nunca aparecem ao usuário. Quando em dúvida, traduza.

API
useT()
Source
chunks/<loc>-N.ts
Locales
12 obrigatórios
Gate
pnpm i18n:check
6

✅ CI checks: rode antes, mergee depois

Conhecer os gates de CI = não ter PR vermelho por surpresa. Tudo que CI checa, você pode rodar local. A diferença é só tempo de feedback.

1

Format + Lint

Prettier, ESLint, cargo fmt --check

Local: pnpm format:check && pnpm lint

2

Typecheck

tsc --noEmit + cargo check

Local: pnpm typecheck && pnpm rust:check

3

Testes (3 níveis)

Vitest, cargo + mock, WDIO

Local: pnpm test && pnpm test:rust

4

Coverage gate (≥80% diff)

.github/workflows/coverage.yml

Local: pnpm test:coverage e abra app/coverage/lcov-report/index.html

5

i18n parity

Chaves consistentes em todos os locales

Local: pnpm i18n:check

⏱️ Cheat sheet pre-PR

pnpm format && pnpm lint && pnpm typecheck \
  && pnpm rust:check && pnpm i18n:check \
  && pnpm test && pnpm test:rust \
  && pnpm test:coverage

Tudo verde aqui = altíssima chance de CI verde também.

Workflows
.github/workflows/
Gates
format+lint+types+test+cov+i18n
Debug
pnpm debug logs
Rebase
Quando upstream avança

🎓 Resumo do Módulo

Fork model — origin=seu fork, upstream=tinyhumansai (fetch-only)
Nunca escreva em main — sempre branch off upstream/main
PR target preciso — tinyhumansai:main com --head <user>:<branch>
Pre-push hook — Husky roda pnpm rust:check; --no-verify só pra falhas alheias
i18n parity — 12 locales, chave em todos os chunks, pnpm i18n:check
CI gates conhecidos — rode local antes pra evitar vai-e-vem

Próxima Trilha:

Trilha 6 — Troubleshooting & Dicas (erros comuns, debug, recovery)