@@ -14,11 +14,37 @@ PR aberto
1414 → Escaneia arquivos sem cobertura
1515 → Chama Claude API para cada arquivo
1616 → Gera arquivos *Test.kt
17- → Cria branch + abre PR automático com os testes
17+ → Cria branch cover/test (auto-incremento) + abre PR automático
18+ → PR body mostra evolução de cobertura (antes vs depois)
1819```
1920
2021---
2122
23+ ## Como usar este guia em um novo repositório
24+
25+ Se você está replicando este fluxo em um repo diferente, passe as seguintes
26+ instruções para o Claude Code no início da sessão:
27+
28+ ```
29+ Quero configurar geração automática de testes com Claude API + GitHub Actions.
30+ Leia o arquivo claude-doc/step_command_ci_test.md do repositório CodandoTV/CraftD
31+ e replique o mesmo fluxo aqui para o módulo <nome-do-modulo>.
32+
33+ Contexto:
34+ - Módulo alvo: <caminho/do/modulo>
35+ - Source sets: <commonMain e/ou androidMain>
36+ - CI existente: <nome exato do workflow de CI>
37+ - Secrets já configurados: ANTHROPIC_API_KEY=sim/não, GH_PAT=sim/não
38+ ```
39+
40+ O Claude vai:
41+ 1 . Analisar os arquivos sem cobertura no módulo
42+ 2 . Criar ` .github/scripts/generate_tests.py `
43+ 3 . Criar ` .github/workflows/generate-tests.yml `
44+ 4 . Abrir o PR — você só precisa mergear e cadastrar os secrets
45+
46+ ---
47+
2248## Fase 1 — Análise do módulo
2349
2450Antes de configurar qualquer coisa, entenda o que existe no módulo alvo.
@@ -132,14 +158,46 @@ if: |
132158| Step | O que faz |
133159|------|-----------|
134160| Resolve trigger context | Normaliza `head_sha` e `pr_number` para os dois gatilhos |
135- | Checkout | Usa `GH_PAT` (não `GITHUB_TOKEN`) para permitir push |
136- | Set up Python | Versão 3.11 |
161+ | Checkout | **Sem token** — repo público não precisa de auth para fetch |
162+ | Check for Kotlin changes | Verifica `git diff origin/main...HEAD` — pula tudo se não houver `.kt` modificado. `workflow_dispatch` sempre passa. |
163+ | Set up Python | Versão 3.11 (só roda se houver `.kt` modificado) |
137164| Install dependencies | `pip install anthropic` |
138- | Find uncovered files | `find` nos diretórios `commonMain` e `androidMain` |
165+ | Find uncovered files | **`workflow_run`** : só processa `.kt` modificados no PR sem teste. **`workflow_dispatch`** sem override: scan completo. Calcula cobertura antes/depois. |
139166| Generate tests | Chama `generate_tests.py` com `CHANGED_FILES` |
140167| Check generated files | Usa `find` (não `git status`) para contar `*Test.kt` |
141- | Commit tests | `git add --force` + push para nova branch |
142- | Open PR | Usa `GH_TOKEN : ${{ secrets.GH_PAT }}` |
168+ | Commit tests | Branch com auto-incremento `cover/test` → `cover/test-1` → ..., `git add --force` + push autenticado via `git remote set-url` |
169+ | Open PR | Usa `GH_TOKEN : ${{ secrets.GH_PAT }}` com tabela de evolução de cobertura |
170+
171+ > ⚠️ `workflow_run` não suporta filtros de `paths` nativamente (ao contrário de `push`/`pull_request`).
172+ > O filtro de `.kt` é feito manualmente via `git diff` dentro do job.
173+
174+ **Autenticação no push (crítico):**
175+ ` ` ` yaml
176+ # Checkout SEM token — repo público não precisa de auth para fetch
177+ - name: Checkout
178+ uses: actions/checkout@v4
179+ with:
180+ ref: ${{ steps.ctx.outputs.head_sha }}
181+ fetch-depth: 0
182+ # NÃO colocar token aqui — causa "fatal: could not read Username" mesmo em repo público
183+
184+ # Push autentica via remote URL (não via checkout token)
185+ - name: Commit generated tests
186+ run: |
187+ git remote set-url origin https://x-access-token:${{ secrets.GH_PAT }}@github.com/org/repo.git
188+ git push origin "$BRANCH"
189+ ` ` `
190+
191+ **Branch com auto-incremento:**
192+ ` ` ` bash
193+ BASE="cover/test"
194+ BRANCH="$BASE"
195+ N=1
196+ while git ls-remote --exit-code --heads origin "$BRANCH" > /dev/null 2>&1; do
197+ BRANCH="${BASE}-${N}"
198+ N=$((N + 1))
199+ done
200+ ` ` `
143201
144202---
145203
@@ -154,8 +212,7 @@ Configure em: **Settings → Secrets and variables → Actions → New repositor
154212
155213# ## 🔑 `ANTHROPIC_API_KEY` — Chave da API do Claude
156214
157- **O que é:** A chave que autentica as chamadas à Claude API. Sem ela o script
158- não consegue chamar o modelo e nenhum teste é gerado.
215+ **O que é:** A chave que autentica as chamadas à Claude API.
159216
160217**Como obter:**
1612181. Acesse [console.anthropic.com](https://console.anthropic.com)
@@ -175,8 +232,7 @@ não consegue chamar o modelo e nenhum teste é gerado.
175232| `claude-haiku-4-5-20251001` | ~$0.09 | ~$0.25 |
176233| `claude-opus-4-6` | ~$1.50 | ~$4.50 |
177234
178- > Use **Haiku** para geração de testes — é ~10x mais barato e suficiente para
179- > data classes, extension functions, DiffUtil e enums.
235+ > Use **Haiku** para geração de testes — é ~10x mais barato e suficiente.
180236
181237**Erro comum:** key correta mas conta sem saldo →
182238```
@@ -188,8 +244,7 @@ Solução: console.anthropic.com → Plans & Billing → Add credits.
188244
189245### 🔑 `GH_PAT` — Personal Access Token do GitHub
190246
191- **O que é:** Um token pessoal do GitHub que permite ao workflow abrir PRs
192- em nome de um usuário real. Substitui o `GITHUB_TOKEN` padrão do Actions.
247+ **O que é:** Um token pessoal do GitHub que permite ao workflow fazer push e abrir PRs.
193248
194249**Por que não usar `GITHUB_TOKEN`:**
195250O `GITHUB_TOKEN` gerado automaticamente pelo Actions tem uma restrição de segurança
@@ -200,13 +255,14 @@ intencional do GitHub — ele **não pode abrir PRs** que disparariam outros wor
2002551. Acesse seu perfil no GitHub → **Settings**
2012562. **Developer settings → Personal access tokens → Tokens (classic)**
2022573. **Generate new token (classic)**
203- 4. Marque o escopo : `repo` (acesso completo)
258+ 4. Marque **apenas** os escopos : `repo` e `workflow`
2042595. Copie o token (começa com `ghp_...`)
205260
206261**Boas práticas:**
207262- Dê um nome descritivo ao token (ex: `craftd-actions-bot`)
208263- Defina uma data de expiração (90 dias é um bom equilíbrio)
209264- Guarde o token em local seguro — o GitHub não mostra novamente
265+ - Se o token expirar, crie um novo e atualize o secret `GH_PAT` no repositório
210266
211267**Erro comum:** usar `GITHUB_TOKEN` no lugar do PAT →
212268```
@@ -251,7 +307,7 @@ Para testar antes do merge, use `workflow_dispatch` manualmente.
251307### ❌ Actions não consegue criar PR (permission error)
252308** Causa:** ` GITHUB_TOKEN ` não tem permissão para abrir PRs que disparam workflows.
253309
254- ** Solução:** Criar um PAT pessoal com escopo ` repo ` , salvar como secret ` GH_PAT `
310+ ** Solução:** Criar um PAT pessoal com escopo ` repo ` + ` workflow ` , salvar como secret ` GH_PAT `
255311e usar ` GH_TOKEN: ${{ secrets.GH_PAT }} ` no step de criação de PR.
256312
257313---
@@ -264,6 +320,81 @@ Com Haiku, $5 cobrem ~50 execuções completas do módulo.
264320
265321---
266322
323+ ### ❌ ` token: ` no checkout causa "fatal: could not read Username"
324+ ** Causa:** Passar o ` GH_PAT ` como ` token: ` no step de ` actions/checkout ` configura
325+ um credential helper que falha mesmo em repos públicos quando o token está
326+ vazio, inválido ou expirado — bloqueando até o simples ` git fetch ` .
327+
328+ ** Solução:** Remover o ` token: ` do checkout completamente. Para repos públicos,
329+ o fetch não precisa de autenticação. A autenticação só é necessária no ` git push ` ,
330+ e deve ser feita via ` git remote set-url ` :
331+ ``` yaml
332+ # ✅ Checkout sem token
333+ - name : Checkout
334+ uses : actions/checkout@v4
335+ with :
336+ ref : ${{ steps.ctx.outputs.head_sha }}
337+ fetch-depth : 0
338+
339+ # ✅ Push autenticado via remote URL
340+ - name : Commit generated tests
341+ run : |
342+ git remote set-url origin https://x-access-token:${{ secrets.GH_PAT }}@github.com/org/repo.git
343+ git push origin "$BRANCH"
344+ ` ` `
345+
346+ ---
347+
348+ ### ❌ Push rejeitado com "non-fast-forward" em re-runs
349+ **Causa:** O branch ` cover/test` já existia no remote de uma execução anterior.
350+ O `git push` padrão não sobrescreve branches divergentes.
351+
352+ **Solução:** Usar auto-incremento no nome do branch — verifica se existe no remote
353+ antes de criar :
354+ ` ` ` bash
355+ BASE="cover/test"
356+ BRANCH="$BASE"
357+ N=1
358+ while git ls-remote --exit-code --heads origin "$BRANCH" > /dev/null 2>&1; do
359+ BRANCH="${BASE}-${N}"
360+ N=$((N + 1))
361+ done
362+ # Resulta em: cover/test, cover/test-1, cover/test-2, ...
363+ ` ` `
364+
365+ ---
366+
367+ # ## ❌ `printf` com variável errada + sem redirecionamento
368+ **Causa:** Ao editar o workflow manualmente, o step de scan ficou assim (errado):
369+ ` ` ` bash
370+ printf "files<<EOF\n %s\n EOF\n " "$UNCOVER_OUTPUT" # ❌
371+ ` ` `
372+ ` $UNCOVER_OUTPUT` apontava para o path do arquivo `$GITHUB_OUTPUT`, não para a lista
373+ de arquivos. Além disso, faltava o redirecionamento.
374+
375+ **Solução:**
376+ ` ` ` bash
377+ printf "files<<EOF\n %s\n EOF\n " "$UNCOVERED" >> "$GITHUB_OUTPUT" # ✅
378+ ` ` `
379+
380+ ---
381+
382+ # ## ❌ Repo renomeado quebra o checkout
383+ **Causa:** O repositório `CodandoTV/CraftD-android` foi renomeado para `CodandoTV/CraftD`.
384+ Sem o campo `repository:` explícito no checkout, o Actions usa o nome antigo e falha.
385+
386+ **Solução:** Sempre especificar `repository:` no checkout de workflows que usam `workflow_run`:
387+ ` ` ` yaml
388+ - name: Checkout
389+ uses: actions/checkout@v4
390+ with:
391+ repository: org/repo # nome atual do repositório
392+ ref: ${{ steps.ctx.outputs.head_sha }}
393+ fetch-depth: 0
394+ ` ` `
395+
396+ ---
397+
267398# # Fase 6 — Como testar antes do merge
268399
269400**Opção 1 — Rodar o script localmente:**
@@ -295,11 +426,12 @@ Deixe o campo vazio para escanear tudo, ou informe arquivos específicos.
295426
296427Após o workflow rodar, verifique:
297428
298- 1 . ** Step "Find uncovered Kotlin files"** — lista os arquivos detectados
429+ 1. **Step "Find uncovered Kotlin files"** — lista os arquivos detectados e mostra cobertura antes/depois
2994302. **Step "Generate unit tests with Claude API"** — cada arquivo deve mostrar `[OK] Written: ...`
3004313. **Step "Check generated files"** — deve mostrar `Found N test file(s)`
301- 4 . ** Step "Open Pull Request"** — URL do PR gerado aparece no log
302- 5 . ** PR aberto automaticamente** com os testes em ` src/test/java/... `
432+ 4. **Step "Commit tests"** — deve mostrar o nome do branch escolhido (`cover/test`, `cover/test-1` etc.)
433+ 5. **Step "Open Pull Request"** — URL do PR gerado aparece no log
434+ 6. **PR aberto automaticamente** com tabela de evolução de cobertura no body
303435
304436---
305437
@@ -328,7 +460,8 @@ Após o workflow rodar, verifique:
328460- [ ] Criar `.github/scripts/generate_tests.py`
329461- [ ] Criar `.github/workflows/generate-tests.yml` apontando para o nome correto do CI
330462- [ ] Adicionar secret `ANTHROPIC_API_KEY` (console.anthropic.com)
331- - [ ] Adicionar secret ` GH_PAT ` (PAT com escopo ` repo ` )
463+ - [ ] Adicionar secret `GH_PAT` (PAT classic com escopos `repo` + `workflow`)
464+ - [ ] **Não colocar `token:` no step de checkout** — usar `git remote set-url` para push
332465- [ ] Abrir PR com os arquivos do workflow e mergear para `main`
333466- [ ] Abrir qualquer PR tocando o módulo alvo e acompanhar o Actions
334-
467+ - [ ] Verificar que o PR gerado mostra a tabela de evolução de cobertura
0 commit comments