Skip to content

Commit 15f0fcc

Browse files
Merge pull request #111 from CodandoTV/fix/generate-tests-trigger-on-merge
fix: restrict generate-tests workflow to merged PRs only
2 parents d8f1b27 + 3ca2cea commit 15f0fcc

11 files changed

Lines changed: 336 additions & 24 deletions

File tree

.github/workflows/generate-tests.yml

Lines changed: 12 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ on:
88
required: false
99
default: ''
1010

11-
workflow_run:
12-
workflows: ["Build and Test for PRs"]
13-
types: [completed]
11+
pull_request:
12+
types: [closed]
1413

1514
permissions:
1615
contents: write
@@ -24,28 +23,17 @@ jobs:
2423
if: |
2524
github.event_name == 'workflow_dispatch' ||
2625
(
27-
github.event.workflow_run.conclusion == 'success' &&
28-
github.event.workflow_run.actor.login != 'github-actions[bot]'
26+
github.event.pull_request.merged == true &&
27+
github.event.pull_request.base.ref == 'main' &&
28+
github.event.pull_request.user.login != 'github-actions[bot]'
2929
)
3030
3131
steps:
32-
# ── 1. Normaliza contexto para os dois gatilhos ───────────────────────────
33-
- name: Resolve trigger context
34-
id: ctx
35-
run: |
36-
if [ "${{ github.event_name }}" = "workflow_dispatch" ]; then
37-
echo "head_sha=${{ github.sha }}" >> "$GITHUB_OUTPUT"
38-
echo "pr_number=manual" >> "$GITHUB_OUTPUT"
39-
else
40-
echo "head_sha=${{ github.event.workflow_run.head_sha }}" >> "$GITHUB_OUTPUT"
41-
echo "pr_number=${{ github.event.workflow_run.pull_requests[0].number }}" >> "$GITHUB_OUTPUT"
42-
fi
43-
44-
# ── 2. Checkout ───────────────────────────────────────────────────────────
32+
# ── 1. Checkout ───────────────────────────────────────────────────────────
4533
- name: Checkout
4634
uses: actions/checkout@v4
4735
with:
48-
ref: ${{ steps.ctx.outputs.head_sha }}
36+
ref: ${{ github.event_name == 'workflow_dispatch' && github.sha || github.event.pull_request.merge_commit_sha }}
4937
fetch-depth: 0
5038

5139
# ── 3. Verifica se há arquivos .kt modificados ───────────────────────────
@@ -56,7 +44,7 @@ jobs:
5644
echo "has_kotlin=true" >> "$GITHUB_OUTPUT"
5745
echo "workflow_dispatch — pulando verificação de .kt"
5846
else
59-
KT=$(git diff --name-only origin/main...HEAD | grep '\.kt$' || true)
47+
KT=$(git diff --name-only ${{ github.event.pull_request.base.sha }}...HEAD | grep '\.kt$' || true)
6048
if [ -n "$KT" ]; then
6149
echo "has_kotlin=true" >> "$GITHUB_OUTPUT"
6250
echo "Arquivos .kt detectados:"
@@ -96,8 +84,8 @@ jobs:
9684
UNCOVERED_COUNT=$(echo "$UNCOVERED" | grep -v "^$" | wc -l | tr -d ' ')
9785
echo "Modo override — arquivos informados manualmente:"
9886
99-
elif [ "${{ github.event_name }}" = "workflow_run" ]; then
100-
# Modo automático (PR) — apenas .kt modificados no PR sem teste ainda
87+
elif [ "${{ github.event_name }}" = "pull_request" ]; then
88+
# Modo automático (PR mergeado) — apenas .kt modificados no PR sem teste ainda
10189
echo "Modo PR — apenas arquivos .kt modificados neste PR sem cobertura..."
10290
UNCOVERED=""
10391
while IFS= read -r SRC; do
@@ -111,7 +99,7 @@ jobs:
11199
UNCOVERED="$UNCOVERED"$'\n'"$SRC"
112100
fi
113101
fi
114-
done < <(git diff --name-only origin/main...HEAD | grep '\.kt$' | grep -v "Test\.kt" | sort)
102+
done < <(git diff --name-only ${{ github.event.pull_request.base.sha }}...HEAD | grep '\.kt$' | grep -v "Test\.kt" | sort)
115103
UNCOVERED=$(echo "$UNCOVERED" | grep -v "^$" || true)
116104
UNCOVERED_COUNT=$(echo "$UNCOVERED" | grep -v "^$" | wc -l | tr -d ' ')
117105
@@ -223,7 +211,7 @@ jobs:
223211
env:
224212
GH_TOKEN: ${{ secrets.GH_PAT }}
225213
run: |
226-
PR_NUMBER="${{ steps.ctx.outputs.pr_number }}"
214+
PR_NUMBER="${{ github.event_name == 'workflow_dispatch' && 'manual' || github.event.pull_request.number }}"
227215
BRANCH="${{ steps.commit.outputs.branch }}"
228216
COVERED="${{ steps.check.outputs.covered_names }}"
229217
TOTAL="${{ steps.changed.outputs.total }}"
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-04-24
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
## Context
2+
3+
O workflow `generate-tests.yml` usa `workflow_run` como gatilho, o que faz com que ele execute toda vez que o workflow "Build and Test for PRs" conclui com sucesso — independentemente de haver um merge. Isso significa que a geração de testes (e o custo associado à Claude API) ocorre a cada push em branches com PR aberto.
4+
5+
O estado atual do gatilho:
6+
```yaml
7+
workflow_run:
8+
workflows: ["Build and Test for PRs"]
9+
types: [completed]
10+
```
11+
12+
A mudança substitui esse gatilho por `pull_request` com tipo `closed`, filtrando apenas merges reais.
13+
14+
## Goals / Non-Goals
15+
16+
**Goals:**
17+
- Garantir que `generate-tests.yml` rode apenas quando um PR é mergeado no `main`
18+
- Manter o `workflow_dispatch` para acionamento manual com `override_files`
19+
- Simplificar a lógica de contexto eliminando a ramificação `workflow_run`
20+
21+
**Non-Goals:**
22+
- Não alterar a lógica de geração de testes em si (Python script, Claude API, PR criado)
23+
- Não modificar outros workflows (`pr.yml`)
24+
- Não mudar o comportamento do `workflow_dispatch`
25+
26+
## Decisions
27+
28+
### Gatilho: `pull_request` com tipo `closed` + condição `merged`
29+
30+
**Decisão:** Usar `on: pull_request: types: [closed]` com `if: github.event.pull_request.merged == true` no job.
31+
32+
**Alternativas consideradas:**
33+
- `push` no branch `main` — funcionaria, mas perderia o número do PR de origem, que é usado no corpo do PR de testes gerados.
34+
- Manter `workflow_run` com filtro extra — não é possível filtrar por merge via `workflow_run`; exigiria lógica de shell para verificar via `gh api`, mais frágil.
35+
36+
**Rationale:** O evento `pull_request.closed` com `merged == true` é a forma idiomática do GitHub Actions para "PR mergeado". Fornece `github.event.pull_request.number` diretamente, mantendo a rastreabilidade no PR gerado.
37+
38+
### Base do diff: `github.event.pull_request.base.sha`
39+
40+
**Decisão:** No step "Check for Kotlin file changes", substituir `origin/main...HEAD` por `${{ github.event.pull_request.base.sha }}...HEAD` quando o gatilho for `pull_request`.
41+
42+
**Rationale:** Com `pull_request.closed`, o checkout ocorre no merge commit. Usar o SHA base do PR garante que o diff cubra exatamente os arquivos modificados naquele PR — o mesmo conjunto analisado pelo CI.
43+
44+
### Remoção do step "Resolve trigger context"
45+
46+
**Decisão:** Remover o step `ctx` que normalizava `head_sha` e `pr_number` entre os dois gatilhos (`workflow_dispatch` vs `workflow_run`).
47+
48+
**Rationale:** Com apenas `pull_request` e `workflow_dispatch`, os valores são obtidos diretamente:
49+
- `pr_number`: `github.event.pull_request.number` (ou `"manual"` no dispatch)
50+
- `head_sha`: `github.event.pull_request.merge_commit_sha` (ou `github.sha` no dispatch)
51+
52+
Isso elimina a indireção e simplifica os steps subsequentes.
53+
54+
## Risks / Trade-offs
55+
56+
- **[Risco] PRs mergeados em branches que não `main`** → O job pode ser restrito adicionando `if: github.event.pull_request.base.ref == 'main'`. Incluir essa condição como precaução.
57+
- **[Trade-off] Geração só ocorre pós-merge** → Antes, testes podiam ser gerados ainda com o PR aberto (como efeito colateral). Agora é intencional — só pós-merge. Aceito como comportamento desejado.
58+
59+
## Migration Plan
60+
61+
1. Editar `.github/workflows/generate-tests.yml`:
62+
- Substituir bloco `workflow_run` por `pull_request: types: [closed]`
63+
- Remover step `Resolve trigger context`
64+
- Atualizar condição `if` do job para verificar `merged == true` e base `main`
65+
- Atualizar referências de `steps.ctx.outputs.*` nos steps seguintes
66+
2. Fazer commit e push — sem necessidade de rollback especial; reverter o arquivo restaura o comportamento anterior.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## Why
2+
3+
O workflow `generate-tests.yml` dispara a cada commit em qualquer branch porque o gatilho `workflow_run` reage à conclusão de "Build and Test for PRs" independente de o PR ter sido mergeado ou não. Isso gera execuções desnecessárias e custo de API durante o desenvolvimento, quando o ideal é gerar testes apenas uma vez — ao merge no `main`.
4+
5+
## What Changes
6+
7+
- Substituir o gatilho `workflow_run` por `pull_request` com o tipo `closed` + filtro `merged == true`
8+
- Remover a lógica de resolução de contexto para o gatilho `workflow_run` (step "Resolve trigger context")
9+
- Ajustar o step "Check for Kotlin file changes" para usar `github.event.pull_request.base.sha` como base do diff em vez de `origin/main`
10+
- Manter o gatilho `workflow_dispatch` inalterado para acionamento manual
11+
12+
## Capabilities
13+
14+
### New Capabilities
15+
16+
- `generate-tests-trigger`: Controle de gatilho do workflow de geração de testes — restringe execução a PRs mergeados no `main`
17+
18+
### Modified Capabilities
19+
20+
<!-- Nenhuma spec existente a alterar -->
21+
22+
## Impact
23+
24+
- **Arquivo afetado:** `.github/workflows/generate-tests.yml`
25+
- **Comportamento anterior:** workflow roda a cada push que passe no CI de qualquer branch com PR aberto
26+
- **Comportamento novo:** workflow roda apenas quando um PR é mergeado no `main`
27+
- **Sem impacto** em outros workflows, código da lib ou testes existentes
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
## ADDED Requirements
2+
3+
### Requirement: Workflow executa apenas em PRs mergeados no main
4+
O workflow `generate-tests.yml` SHALL ser acionado automaticamente somente quando um pull request for mergeado na branch `main`.
5+
6+
#### Scenario: PR mergeado no main dispara o workflow
7+
- **WHEN** um pull request é fechado com `merged == true` e `base.ref == 'main'`
8+
- **THEN** o job `generate-tests` é executado
9+
10+
#### Scenario: PR fechado sem merge não dispara o workflow
11+
- **WHEN** um pull request é fechado com `merged == false`
12+
- **THEN** o job `generate-tests` NÃO é executado
13+
14+
#### Scenario: Push em branch sem merge não dispara o workflow
15+
- **WHEN** um commit é feito em qualquer branch sem que haja um merge no main
16+
- **THEN** o job `generate-tests` NÃO é executado
17+
18+
#### Scenario: PR mergeado em branch que não main não dispara o workflow
19+
- **WHEN** um pull request é mergeado em uma branch diferente de `main` (ex: `develop`)
20+
- **THEN** o job `generate-tests` NÃO é executado
21+
22+
### Requirement: Workflow_dispatch mantido para acionamento manual
23+
O workflow SHALL continuar suportando acionamento manual via `workflow_dispatch` com o parâmetro opcional `override_files`.
24+
25+
#### Scenario: Disparo manual sem override roda scan completo
26+
- **WHEN** o workflow é acionado via `workflow_dispatch` sem `override_files`
27+
- **THEN** o job escaneia todos os arquivos `.kt` sem cobertura em `craftd-core`
28+
29+
#### Scenario: Disparo manual com override_files usa arquivos informados
30+
- **WHEN** o workflow é acionado via `workflow_dispatch` com `override_files` preenchido
31+
- **THEN** o job processa apenas os arquivos listados em `override_files`
32+
33+
### Requirement: Número do PR de origem preservado no PR gerado
34+
O workflow SHALL incluir o número do PR que disparou a geração no corpo do PR de testes criado automaticamente.
35+
36+
#### Scenario: PR de testes referencia o PR de origem
37+
- **WHEN** o workflow é disparado por um merge de PR número `N`
38+
- **THEN** o corpo do PR gerado contém `Triggered by PR #N`
39+
40+
#### Scenario: Disparo manual usa label "manual"
41+
- **WHEN** o workflow é acionado via `workflow_dispatch`
42+
- **THEN** o corpo do PR gerado contém `Triggered by PR #manual`
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
## 1. Substituir gatilho do workflow
2+
3+
- [x] 1.1 Remover o bloco `workflow_run` de `.github/workflows/generate-tests.yml`
4+
- [x] 1.2 Adicionar gatilho `pull_request: types: [closed]` no lugar
5+
6+
## 2. Atualizar condição do job
7+
8+
- [x] 2.1 Adicionar condição `if` no job `generate-tests` para verificar `github.event.pull_request.merged == true`
9+
- [x] 2.2 Adicionar filtro `github.event.pull_request.base.ref == 'main'` na condição do job (ou manter para `workflow_dispatch`)
10+
11+
## 3. Remover e simplificar lógica de contexto
12+
13+
- [x] 3.1 Remover o step "Resolve trigger context" (`id: ctx`) inteiramente
14+
- [x] 3.2 Atualizar o step "Checkout" para usar `github.event.pull_request.merge_commit_sha` (ou `github.sha` para dispatch)
15+
- [x] 3.3 Atualizar referências `steps.ctx.outputs.pr_number` e `steps.ctx.outputs.head_sha` nos steps seguintes para usar os valores diretos do evento
16+
17+
## 4. Ajustar diff de Kotlin
18+
19+
- [x] 4.1 No step "Check for Kotlin file changes", substituir a base do diff de `origin/main...HEAD` por `${{ github.event.pull_request.base.sha }}...HEAD` para o gatilho `pull_request`
20+
- [x] 4.2 Garantir que o modo `workflow_dispatch` continue usando o scan completo (sem base SHA de PR)
21+
22+
## 5. Validação
23+
24+
- [x] 5.1 Revisar o YAML final e confirmar que a sintaxe está correta (sem erros de indentação ou referências quebradas)
25+
- [x] 5.2 Confirmar que `pr_number` no body do PR gerado continua referenciando o número correto (ou "manual" para dispatch)
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
schema: spec-driven
2+
created: 2026-04-24
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
## Context
2+
3+
O workflow `generate-tests.yml` usa `workflow_run` como gatilho, o que faz com que ele execute toda vez que o workflow "Build and Test for PRs" conclui com sucesso — independentemente de haver um merge. Isso significa que a geração de testes (e o custo associado à Claude API) ocorre a cada push em branches com PR aberto.
4+
5+
O estado atual do gatilho:
6+
```yaml
7+
workflow_run:
8+
workflows: ["Build and Test for PRs"]
9+
types: [completed]
10+
```
11+
12+
A mudança substitui esse gatilho por `pull_request` com tipo `closed`, filtrando apenas merges reais.
13+
14+
## Goals / Non-Goals
15+
16+
**Goals:**
17+
- Garantir que `generate-tests.yml` rode apenas quando um PR é mergeado no `main`
18+
- Manter o `workflow_dispatch` para acionamento manual com `override_files`
19+
- Simplificar a lógica de contexto eliminando a ramificação `workflow_run`
20+
21+
**Non-Goals:**
22+
- Não alterar a lógica de geração de testes em si (Python script, Claude API, PR criado)
23+
- Não modificar outros workflows (`pr.yml`)
24+
- Não mudar o comportamento do `workflow_dispatch`
25+
26+
## Decisions
27+
28+
### Gatilho: `pull_request` com tipo `closed` + condição `merged`
29+
30+
**Decisão:** Usar `on: pull_request: types: [closed]` com `if: github.event.pull_request.merged == true` no job.
31+
32+
**Alternativas consideradas:**
33+
- `push` no branch `main` — funcionaria, mas perderia o número do PR de origem, que é usado no corpo do PR de testes gerados.
34+
- Manter `workflow_run` com filtro extra — não é possível filtrar por merge via `workflow_run`; exigiria lógica de shell para verificar via `gh api`, mais frágil.
35+
36+
**Rationale:** O evento `pull_request.closed` com `merged == true` é a forma idiomática do GitHub Actions para "PR mergeado". Fornece `github.event.pull_request.number` diretamente, mantendo a rastreabilidade no PR gerado.
37+
38+
### Base do diff: `github.event.pull_request.base.sha`
39+
40+
**Decisão:** No step "Check for Kotlin file changes", substituir `origin/main...HEAD` por `${{ github.event.pull_request.base.sha }}...HEAD` quando o gatilho for `pull_request`.
41+
42+
**Rationale:** Com `pull_request.closed`, o checkout ocorre no merge commit. Usar o SHA base do PR garante que o diff cubra exatamente os arquivos modificados naquele PR — o mesmo conjunto analisado pelo CI.
43+
44+
### Remoção do step "Resolve trigger context"
45+
46+
**Decisão:** Remover o step `ctx` que normalizava `head_sha` e `pr_number` entre os dois gatilhos (`workflow_dispatch` vs `workflow_run`).
47+
48+
**Rationale:** Com apenas `pull_request` e `workflow_dispatch`, os valores são obtidos diretamente:
49+
- `pr_number`: `github.event.pull_request.number` (ou `"manual"` no dispatch)
50+
- `head_sha`: `github.event.pull_request.merge_commit_sha` (ou `github.sha` no dispatch)
51+
52+
Isso elimina a indireção e simplifica os steps subsequentes.
53+
54+
## Risks / Trade-offs
55+
56+
- **[Risco] PRs mergeados em branches que não `main`** → O job pode ser restrito adicionando `if: github.event.pull_request.base.ref == 'main'`. Incluir essa condição como precaução.
57+
- **[Trade-off] Geração só ocorre pós-merge** → Antes, testes podiam ser gerados ainda com o PR aberto (como efeito colateral). Agora é intencional — só pós-merge. Aceito como comportamento desejado.
58+
59+
## Migration Plan
60+
61+
1. Editar `.github/workflows/generate-tests.yml`:
62+
- Substituir bloco `workflow_run` por `pull_request: types: [closed]`
63+
- Remover step `Resolve trigger context`
64+
- Atualizar condição `if` do job para verificar `merged == true` e base `main`
65+
- Atualizar referências de `steps.ctx.outputs.*` nos steps seguintes
66+
2. Fazer commit e push — sem necessidade de rollback especial; reverter o arquivo restaura o comportamento anterior.
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
## Why
2+
3+
O workflow `generate-tests.yml` dispara a cada commit em qualquer branch porque o gatilho `workflow_run` reage à conclusão de "Build and Test for PRs" independente de o PR ter sido mergeado ou não. Isso gera execuções desnecessárias e custo de API durante o desenvolvimento, quando o ideal é gerar testes apenas uma vez — ao merge no `main`.
4+
5+
## What Changes
6+
7+
- Substituir o gatilho `workflow_run` por `pull_request` com o tipo `closed` + filtro `merged == true`
8+
- Remover a lógica de resolução de contexto para o gatilho `workflow_run` (step "Resolve trigger context")
9+
- Ajustar o step "Check for Kotlin file changes" para usar `github.event.pull_request.base.sha` como base do diff em vez de `origin/main`
10+
- Manter o gatilho `workflow_dispatch` inalterado para acionamento manual
11+
12+
## Capabilities
13+
14+
### New Capabilities
15+
16+
- `generate-tests-trigger`: Controle de gatilho do workflow de geração de testes — restringe execução a PRs mergeados no `main`
17+
18+
### Modified Capabilities
19+
20+
<!-- Nenhuma spec existente a alterar -->
21+
22+
## Impact
23+
24+
- **Arquivo afetado:** `.github/workflows/generate-tests.yml`
25+
- **Comportamento anterior:** workflow roda a cada push que passe no CI de qualquer branch com PR aberto
26+
- **Comportamento novo:** workflow roda apenas quando um PR é mergeado no `main`
27+
- **Sem impacto** em outros workflows, código da lib ou testes existentes

0 commit comments

Comments
 (0)