chore(meta): institutionalize PR ↔ Issue cross-reference pattern#159
Conversation
Aprendizado da sessão de redeploy: durante auditoria pós-T7, descobri que issues criadas por PRs (#151, #153, #155) não tinham comentário automático linkando à PR de origem, o que prejudica rastreabilidade depois de meses. Corrigi manualmente as 3 issues existentes nesta sessão. Esta PR institucionaliza o padrão para que NÃO ACONTEÇA DE NOVO no futuro. Mudanças: 1. .github/PULL_REQUEST_TEMPLATE.md - Consolidado: existiam DOIS templates (PULL_REQUEST_TEMPLATE.md e pull_request_template.md em minúscula). GitHub buscava em ordem case-insensitive e podia usar qualquer um — bug latente. - Removido o duplicado em minúscula via 'git rm'. - Reescrito com instruções explícitas sobre keywords (Closes/Fixes/Refs/Part of) e padrão do projeto sobre cross-reference. 2. .github/ISSUE_TEMPLATE/bug_report.yml + feature_request.yml - Adicionado campo 'PR de origem' (input opcional) - Texto explica o padrão do projeto 3. .github/ISSUE_TEMPLATE/tracking.yml (NOVO) - Template específico para issues de tracking / tech-debt / discussion - Campo 'PR de origem' marcado como required (forma de impor o padrão) - DoD obrigatória, prioridade obrigatória, contexto obrigatório 4. .github/workflows/cross-reference-issues.yml (NOVO, 179 linhas) - Roda em pull_request e issues events - Quando PR menciona 'Closes #N' ou 'Refs #N': adiciona comentário automático na issue linkando à PR - Quando PR é mergeada: adiciona comentário final com merge SHA - Quando issue nova declara 'PR de origem #N': adiciona comentário na PR referenciando a issue - Idempotente (usa markers HTML pra evitar duplicação) - Permissions mínimos: pull-requests:write + issues:write 5. CONTRIBUTING.md - Nova seção '🔗 Cross-reference Issue ↔ PR (obrigatório)' - Explica os 2 fluxos (PR descobre issue / PR resolve issue) - Justifica o porquê (rastreabilidade pra futuras sessões) - Aponta para o workflow que automatiza Benefício: o problema que peguei manualmente nesta sessão (issues #151 e #153 sem cross-reference para suas PRs #152 e #154) não vai mais acontecer porque o bot detecta e adiciona automaticamente. Refs #151 Refs #153 Refs #155 Co-Authored-By: Claude <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
Caution Review failedPull request was closed or merged during review WalkthroughAdiciona workflow GitHub Actions que cria comentários bidirecionais entre PRs e issues; adiciona campo ChangesIssue templates
Pull request templates
Cross-reference workflow
Documentação de processo
Sequence DiagramsequenceDiagram
participant Dev as Developer
participant GH as GitHub
participant WF as Workflow (cross-reference)
participant PR as Pull Request
participant IS as Issue
Dev->>GH: Open/Edit PR com "Closes/Refs/Part of `#123`"
GH->>WF: Trigger pull_request event
WF->>PR: Parse body, extract referenced issue numbers via keywords
WF->>GH: GET /repos/.../issues/123
alt 123 é Issue
WF->>IS: Check dedup HTML marker
alt sem marker
alt PR merged
WF->>IS: POST comment (merged — SHA, time)
else PR não merged
WF->>IS: POST comment (cross-reference pending)
end
else com marker
WF->>WF: Skip (já comentado)
end
else 123 é PR
WF->>WF: Skip (não é issue)
end
Dev->>GH: Open Issue com campo origin_pr: "#456"
GH->>WF: Trigger issues opened
WF->>IS: Extract origin_pr from issue body
WF->>GH: GET /repos/.../pulls/456
alt PR 456 encontrada
WF->>PR: Check dedup HTML marker
alt sem marker
WF->>PR: POST comment (link to new issue)
else com marker
WF->>WF: Skip
end
else PR não encontrada
WF->>WF: Log 404 warning
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: b4ae5826c4
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| // Captura tanto "Closes #123" quanto "closes part of #155" etc | ||
| const issueRefs = new Set(); | ||
| const patterns = [ | ||
| /(?:closes|fixes|resolves|refs|references|part of)\s+#(\d+)/gi, |
There was a problem hiding this comment.
Support documented partial-close references
When contributors follow the new documented pattern Closes part of #155 from CONTRIBUTING.md, this regex does not match it because closes must be followed directly by #; the only alternative that would match is part of #155 without Closes. In that documented scenario the workflow exits at issueRefs.size === 0, so no cross-reference comment is added even though the instructions say it will be.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/cross-reference-issues.yml:
- Around line 158-172: The code always posts a new PR comment (using marker,
commentBody and github.rest.issues.createComment) without checking for an
existing marker, causing duplicate comments on re-runs; fix by first listing
comments for the PR (github.rest.issues.listComments with issue_number = prNum),
search for a comment whose body includes the marker (`<!--
cross-ref-bot:issue-${issue.number} -->`), and only call
github.rest.issues.createComment if no existing comment is found; if a matching
comment exists, skip creation and adjust the core.info message accordingly.
- Around line 44-52: The fallback regex patterns[1] is never applied because the
code only iterates body.matchAll(patterns[0]); update the logic around the const
patterns array so you also run body.matchAll for the fallback (either always
loop over both patterns or run patterns[1] only when no matches found by
patterns[0]), and for each match call issueRefs.add(parseInt(m[1], 10)) just
like the primary loop; look for the variables patterns, body.matchAll, and
issueRefs.add to place the additional iteration.
- Around line 87-110: The multiline template assigned to commentBody (in the
isMerged / isOpened branches using marker, pr, title, etc.) is leaking raw
newlines into the workflow YAML and breaking the script block; instead build a
single-line serialized string (e.g., join an array of lines or escape newlines)
and ensure it is JSON/string-escaped before embedding into the YAML script, so
commentBody contains escaped \n sequences (or use JSON.stringify) and any
backticks or quotes are escaped; update the assignments to commentBody in the
isMerged and isOpened/!existing branches to produce a safely serialized
single-line value.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: f09ee39a-129d-49d1-b8e5-676b0d9e2d90
📒 Files selected for processing (7)
.github/ISSUE_TEMPLATE/bug_report.yml.github/ISSUE_TEMPLATE/feature_request.yml.github/ISSUE_TEMPLATE/tracking.yml.github/PULL_REQUEST_TEMPLATE.md.github/pull_request_template.md.github/workflows/cross-reference-issues.ymlCONTRIBUTING.md
💤 Files with no reviewable changes (1)
- .github/pull_request_template.md
| const patterns = [ | ||
| /(?:closes|fixes|resolves|refs|references|part of)\s+#(\d+)/gi, | ||
| /#(\d+)/g // pega outras menções diretas no body como fallback | ||
| ]; | ||
|
|
||
| // Pattern principal (palavras-chave) | ||
| for (const m of body.matchAll(patterns[0])) { | ||
| issueRefs.add(parseInt(m[1], 10)); | ||
| } |
There was a problem hiding this comment.
Fallback de referência direta (#N) nunca é usado.
Você declara dois regexes, mas só percorre patterns[0]. Hoje, menções diretas no body (sem keyword) não entram no issueRefs.
💡 Patch sugerido
- const patterns = [
- /(?:closes|fixes|resolves|refs|references|part of)\s+#(\d+)/gi,
- /#(\d+)/g // pega outras menções diretas no body como fallback
- ];
-
- // Pattern principal (palavras-chave)
- for (const m of body.matchAll(patterns[0])) {
- issueRefs.add(parseInt(m[1], 10));
- }
+ const patterns = [
+ /(?:closes|fixes|resolves|refs|references|part of)\s+#(\d+)/gi,
+ /#(\d+)/g // fallback para menções diretas
+ ];
+
+ for (const pattern of patterns) {
+ for (const m of body.matchAll(pattern)) {
+ issueRefs.add(parseInt(m[1], 10));
+ }
+ }📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| const patterns = [ | |
| /(?:closes|fixes|resolves|refs|references|part of)\s+#(\d+)/gi, | |
| /#(\d+)/g // pega outras menções diretas no body como fallback | |
| ]; | |
| // Pattern principal (palavras-chave) | |
| for (const m of body.matchAll(patterns[0])) { | |
| issueRefs.add(parseInt(m[1], 10)); | |
| } | |
| const patterns = [ | |
| /(?:closes|fixes|resolves|refs|references|part of)\s+#(\d+)/gi, | |
| /#(\d+)/g // fallback para menções diretas | |
| ]; | |
| for (const pattern of patterns) { | |
| for (const m of body.matchAll(pattern)) { | |
| issueRefs.add(parseInt(m[1], 10)); | |
| } | |
| } |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.github/workflows/cross-reference-issues.yml around lines 44 - 52, The
fallback regex patterns[1] is never applied because the code only iterates
body.matchAll(patterns[0]); update the logic around the const patterns array so
you also run body.matchAll for the fallback (either always loop over both
patterns or run patterns[1] only when no matches found by patterns[0]), and for
each match call issueRefs.add(parseInt(m[1], 10)) just like the primary loop;
look for the variables patterns, body.matchAll, and issueRefs.add to place the
additional iteration.
There was a problem hiding this comment.
Pull request overview
Institucionaliza um padrão de rastreabilidade entre Pull Requests e Issues via templates + um workflow do GitHub Actions que cria cross-references automáticas, reduzindo perda de contexto ao longo do tempo.
Changes:
- Consolida o template de PR e explicita keywords/padrão de linkage com issues.
- Adiciona/ajusta templates de issue para capturar “PR de origem” (inclui novo template Tracking/Discussion).
- Introduz workflow para comentar automaticamente em issues/PRs com base em referências detectadas.
Reviewed changes
Copilot reviewed 7 out of 7 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
CONTRIBUTING.md |
Documenta o padrão obrigatório de cross-reference Issue ↔ PR e o workflow responsável. |
.github/workflows/cross-reference-issues.yml |
Implementa automação de comentários cruzados entre PRs e issues. |
.github/PULL_REQUEST_TEMPLATE.md |
Reorganiza o template e adiciona seção dedicada a keywords de issues relacionadas. |
.github/pull_request_template.md |
Remove template duplicado (minúsculo) para evitar ambiguidade. |
.github/ISSUE_TEMPLATE/tracking.yml |
Novo template Tracking/Discussion com “PR de origem” obrigatório e DoD obrigatório. |
.github/ISSUE_TEMPLATE/feature_request.yml |
Adiciona campo opcional “PR de origem”. |
.github/ISSUE_TEMPLATE/bug_report.yml |
Adiciona campo opcional “PR de origem”. |
Comments suppressed due to low confidence (1)
.github/workflows/cross-reference-issues.yml:170
- O handler de issues não está idempotente: ele sempre cria comentário na PR e não verifica se já existe um comentário com o marker
<!-- cross-ref-bot:issue-... -->. Em caso deedited(se habilitado) ou re-run do workflow, isso vai duplicar comentários; liste comentários existentes e pule/crie apenas se o marker não estiver presente.
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNum,
body: commentBody,
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| const patterns = [ | ||
| /(?:closes|fixes|resolves|refs|references|part of)\s+#(\d+)/gi, | ||
| /#(\d+)/g // pega outras menções diretas no body como fallback | ||
| ]; |
| const { data: comments } = await github.rest.issues.listComments({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: issueNum, | ||
| per_page: 100, | ||
| }); |
| if (commentBody && (!existing || isMerged)) { | ||
| await github.rest.issues.createComment({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: issueNum, |
| - name: Cross-reference on Issue events | ||
| if: github.event_name == 'issues' && github.event.action == 'opened' | ||
| uses: actions/github-script@v8 |
CodeRabbit identificou 3 issues importantes:
1. Branch 'Issue events' não checava marker antes de comentar
→ posts duplicados em re-runs (issue.edited dispara o mesmo workflow)
Fix: listComments primeiro, search por marker, skip se já existe
2. Dead code: const patterns = [keywordPattern, fallbackRegex]
patterns[1] declarado mas nunca usado no loop
Fix: removido, apenas keywordPattern fica
3. Template literals com newlines no commentBody podiam dar parsing issues
Fix: tudo construído via array.join('\n') agora — explícito e safe
Bônus além dos achados:
- Markers diferenciados :opened vs :merged
Antes: 1 marker por PR → comentário de merged sobrescrevia o de opened
Agora: dois markers permitem coexistir ambos os comentários (que é o
comportamento desejado: histórico tem evento opened E evento merged)
- error.message agora consistente em todos os catch blocks
Diff: 200 linhas (era 179) — verbosidade extra justificada pela correção
das 3 falhas + robustez adicional.
Refs CodeRabbit review em #159
Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 95c50fcb2c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const { data: comments } = await github.rest.issues.listComments({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| issue_number: issueNum, | ||
| per_page: 100, | ||
| }); |
There was a problem hiding this comment.
Paginate comment scans to preserve idempotency
For issues or PRs that already have more than 100 comments, this only checks one page of comments before deciding whether the marker exists. In that scenario the marker can be outside the fetched page, so every later edited/synchronize/closed run creates another bot comment even though the workflow promises idempotency; use pagination for the marker lookup instead of a single per_page: 100 request.
Useful? React with 👍 / 👎.
🎯 Por que esta PR existe
Durante a auditoria pós-redeploy (sessão de hoje), descobri que issues criadas por PRs não tinham comentário automático linkando à PR de origem. Isso prejudica rastreabilidade depois de meses (e, no nosso caso, entre sessões de Claude).
Corrigi manualmente as 3 issues existentes (#151, #153, #155 com cross-refs para #152, #154 e #140-#142). Esta PR institucionaliza o padrão para que não aconteça de novo.
📋 Mudanças
1.
.github/PULL_REQUEST_TEMPLATE.md— consolidação🚨 Bug latente descoberto: existiam DOIS templates de PR:
.github/PULL_REQUEST_TEMPLATE.md(89 linhas, com seção de "Sistemas afetados").github/pull_request_template.md(32 linhas, minúscula, sem essa seção)GitHub busca em ordem case-insensitive e usa um deles, sem garantia. Removido o duplicado em minúscula. Template consolidado tem o melhor dos dois + instruções explícitas sobre keywords (
Closes/Fixes/Refs/Part of).2. Templates de issue — campo "PR de origem"
bug_report.ymlPR de origemopcionalfeature_request.ymlPR de origemopcionaltracking.yml(NOVO)PR de origemobrigatório + DoD obrigatórioO template de tracking é o padrão para issues como #151, #153, #155 (tech-debt / discussion / follow-up).
3.
.github/workflows/cross-reference-issues.yml(NOVO, 179 linhas)A peça que importa. Bot que automatiza cross-references:
Closes #NPR de origem #Npull-requests: write,issues: write)4.
CONTRIBUTING.md— nova seçãoDocumenta o padrão em prosa para humanos lerem. Explica:
✅ Benefício esperado
Daqui pra frente, qualquer dev (ou Claude em sessão futura) que abrir uma issue #999 mencionando "PR de origem #998" vai automaticamente ver um comentário do bot na #998 dizendo "esta PR descobriu a issue #999". E vice-versa.
O problema que peguei manualmente hoje não vai mais acontecer.
🧪 Validação
Sem mudança de código de runtime
Apenas
.github/eCONTRIBUTING.md. Risco zero pra produção.Refs #151
Refs #153
Refs #155
Co-Authored-By: Claude noreply@anthropic.com
Summary by CodeRabbit
Melhorias
Chores
Documentation