Destino Dev

Blog

Transforme Pull Requests em estudos de caso práticos para seu portfólio

Por John Pires · 09 de março de 2026

Transforme Pull Requests em estudos de caso práticos para seu portfólio

Contexto e motivacao

Por que usar PRs como matéria-prima do portfólio

Pull Requests (PRs) são artefatos reais do seu trabalho: mostram decisões, trade-offs, comunicação, testes e revisão de código. Para devs com 1-3 anos de experiência, usar PRs como base de estudo de caso é mais convincente do que projetos toy. Um bom estudo de caso a partir de um PR mostra impacto e raciocínio, não só código.

Em vez de apresentar um repositório monolítico com README genérico, um estudo de caso extraído de PR deixa explícito o problema, a solução, e as decisões técnicas. Isso reduz a distância entre o que você fez e o que o avaliador quer ver.

Objetivos práticos deste artigo

Vou te tratar como num code review: mostro o caminho errado e depois o certo. Você vai aprender a:

  • Selecionar PRs relevantes;
  • Extrair conteúdo e reorganizar em uma narrativa concisa;
  • Automatizar geração de estudos de caso com scripts e workflows;
  • Avoid pitfalls comuns na divulgação de trabalho de time.

O foco é prático: padrões, snippets e um fluxo que funciona em times que usam GitHub/GitLab. Não é teoria abstrata — é engenharia do seu portfólio.

Como funciona por baixo dos panos

O que um PR carrega de valor

Um PR encapsula múltiplas dimensões: descrição do problema, commits com mensagens, diffs, comentários de revisão, CI status, métricas de cobertura e etiqueta (labels). Cada dimensão é material para um capítulo do seu estudo de caso.

Nem tudo é útil: diffs brutos são verborrágicos. O papel é filtrá-los em: resumo técnico, decisões, impactos mensuráveis e aprendizados. O leitor do seu portfólio quer sinalização rápida do seu papel e da complexidade técnica.

Arquitetura do fluxo automático

Fluxo recomendado (simplificado):

  1. Selecionar PRs alvo (manual ou tag automático).
  2. Extrair metadados via API.
  3. Gerar Markdown estruturado com front-matter para seu SSG (Next.js, Hugo, etc.).
  4. Commitar em um branch / publicar site.

Automatizar essas etapas reduz trabalho manual e mantém consistência — essencial para manter um portfólio vivo. A seguir, exemplos de implementação que demonstram a diferença entre uma abordagem pobre e uma limpa.

Implementacao passo a passo

1) Escolha do PR — o jeito errado e o certo

Jeito errado: exportar qualquer PR numeroso e difuso. Isso cria estudos de caso longos, sem foco no seu papel. Jeito certo: selecionar PRs que mostram um componente técnico claro ou uma melhoria de processo, e onde seu trabalho é identificável.

Critérios práticos de seleção:

  • Você foi o autor ou reviewer principal;
  • Mudança tem impacto mensurável (tempo, bugs, performance);
  • Discussões interessantes que mostram trade-offs;
  • Possibilidade de extrair 2-4 trechos de código relevantes.

2) Script para extrair metadados do GitHub (exemplo prático)

Contexto: script Node.js que busca informações básicas do PR (título, autor, commits, diffs, comentários). Use para automatizar a coleta antes de escrever o case manualmente ou gerar Markdown.

O código abaixo demonstra chamada à API do GitHub com fetch. Ele faz paginação simples e salva um JSON com os dados do PR.

/*
  Extrai metadados e diffs de um PR no GitHub.
  Usa: NODE_GITHUB_TOKEN no ambiente.
  Resultado: pr-data.json
*/
const fetch = require('node-fetch');
const fs = require('fs');

const token = process.env.NODE_GITHUB_TOKEN;
if (!token) throw new Error('Set NODE_GITHUB_TOKEN');

async function get(url) {
  const res = await fetch(url, { headers: { Authorization: `token ${token}`, Accept: 'application/vnd.github.v3+json' } });
  if (!res.ok) throw new Error(`HTTP ${res.status} ${res.statusText}`);
  return res.json();
}

(async () => {
  const owner = 'seu-usuario-ou-org';
  const repo = 'seu-repo';
  const prNumber = 123; // ajuste
  const base = `https://api.github.com/repos/${owner}/${repo}`;

  const pr = await get(`${base}/pulls/${prNumber}`);
  const comments = await get(`${base}/issues/${prNumber}/comments`);
  const commits = await get(`${base}/pulls/${prNumber}/commits`);
  const files = await get(`${base}/pulls/${prNumber}/files`);

  fs.writeFileSync('pr-data.json', JSON.stringify({ pr, comments, commits, files }, null, 2));
  console.log('pr-data.json gerado');
})();

O que acontece: gera um JSON com o PR, commits, arquivos alterados e comentários. Use esse artefato como entrada para gerar Markdown organizado.

3) Template de Markdown: errado vs certo

Jeito errado: colar o título do PR e o diff inteiro no README. Pior ainda: sem contexto, isso torna o portfolio ilegível. Jeito certo: usar um template com seções fixas (Problema, Abordagem, Patches importantes, Testes, Métricas, Lições aprendidas).

Exemplo de template gerado automaticamente.

---
title: Corrige leak em cache de sessão
date: 2025-01-10
tech: [nodejs, redis, express]
role: author
pr: 123
---

# Corrige leak em cache de sessão

## Problema
O servidor acumulava entradas no cache quando cookies expiravam, causando uso excessivo de memória.

## Abordagem
Identifiquei duas causas: key collision e falha no TTL. Alterei a geração de key e adicionei um worker de expiração segura.

## Trechos relevantes
- src/middleware/sessionCache.js (mudança na função keyFor)

```js
// função keyFor antes: retornava `${userId}:${cookie.value}` sem normalizar
// agora normaliza e adiciona namespace
function keyFor(req) {
  const uid = String(req.user.id);
  const token = String(req.cookie.sessionId).replace(/\s+/g, '');
  return `sessions:${uid}:${token}`;
}
```

## Resultados
- Memória média por pod reduzida em 30%
- Incidentes relacionados a OOM caíram a zero em 2 semanas

## Lições
Documentar invariantes de key, e escrever testes de integração para expiração.

O que acontece: esse Markdown é direto ao ponto. O leitor vê problema, abordagem e evidência de impacto — tudo em 2-3 minutos.

4) Automação com GitHub Actions

Contexto: um workflow que roda manualmente (workflow_dispatch) e gera arquivos de case no repositório de portfólio. É uma forma prática de manter seu site atualizado sem trabalho manual repetitivo.

# .github/workflows/generate-case.yml
name: Generate Case from PR
on:
  workflow_dispatch:
    inputs:
      pr_number:
        description: 'PR number to export'
        required: true
        type: number

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout
        uses: actions/checkout@v4

      - name: Run extractor
        env:
          NODE_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
        run: |
          node scripts/extract-pr.js ${{ github.event.inputs.pr_number }}

      - name: Commit generated case
        run: |
          git config user.name 'github-actions'
          git config user.email 'actions@github.com'
          git add cases/*.md
          git commit -m "Add case for PR #${{ github.event.inputs.pr_number }}" || echo 'no changes'
          git push

O que acontece: dispara o script que gera Markdown e comita no branch atual. Use branch separado para publicações em site estático se quiser revisão manual antes do deploy.

Patterns e boas praticas

Narrativa concisa: problema -> ação -> resultado

Um padrão repetível: sempre comece com o contexto (por que isso importa), descreva sua ação com foco técnico e finalize com dados quantificáveis. Evite longas descrições do processo do Git; foque no valor técnico.

Use métricas quando possível: números de redução de latência, cobertura de testes, tempo de build. Métricas tornam o case verificável e memorável.

Isolar trechos de código com propósito

Não mostre diffs inteiros. Extraia 2-4 trechos significativos e comente ao lado: o que mudou e por quê. Se for um refactor, mostre o antes e o depois com comentários que expliquem o benefício.

Use code snippets pequenos e explique trade-offs no texto; não deixe o leitor adivinhar.

Boas práticas de privacidade e propriedade

Se trabalhou em repositório privado, redija casos agregando informações não sensíveis. Remova segredos, nomes internos ou arquiteturas proprietárias. Prefira abstrair: "sistema de cache" em vez de nome real do cliente.

Inclua sempre uma nota de autorização quando pertinente, e não publique diffs que exponham dados sensíveis.

Armadilhas comuns e como evitar

Armadilha 1: colar diffs brutos

Problema: diffs longos e pouco comentados escondem sua contribuição. Revisores não querem ler 2000 linhas para achar uma função relevante. Solução: extraia o essencial.

Regra prática: cada trecho de código no case deve ter no máximo ~25 linhas e uma legenda que responda: "por que isso mudou".

Exemplo: em vez de colar o arquivo inteiro, isole a função refatorada com comentário que explique a escolha algorítmica.

Armadilha 2: atribuir impacto sem evidência

Problema: afirmar "melhorei performance" sem números soa vago e reduz confiança. Solução: sempre agregue métricas ou logs que suportem a afirmação — exemplo: antes/depois do p99, contagem de erros ou custo por operação.

Se não tiver métricas, descreva o experimento que provaria o impacto (benchmark, A/B). Isso mostra pensamento científico.

Armadilha 3: expor trabalho de terceiros sem crédito

Problema: muitos PRs são colaboração. Apagar nomes dos colaboradores ou não mencionar revisores é deselegante e antiético. Solução: credite coautores e mencione discussões relevantes que influenciaram a solução.

Inclua uma seção "Colaboração" listando reviewers e decisões chave que vieram da revisão.

Dica prática de revisão de case (estilo code review)

Ao revisar seu próprio case, aplique as mesmas perguntas que faria num PR: esse trecho é necessário? Está claro o impacto? Há evidência? Alguém mais contribuiu?

Essa autoverificação evita casos encharcados de detalhes irrelevantes e melhora a qualidade narrativa.

Conclusao pratica

Checklist final antes de publicar

Use este checklist rápido antes de adicionar um case ao portfólio:

  • Existe um problema bem definido? (sim/não)
  • Minha contribuição está destacada?
  • Há 1-3 trechos de código explicados?
  • Existem métricas ou plano de validação?
  • Removi informações sensíveis e creditei coautores?

Cumprir esse checklist transforma um PR into um case de impacto, fácil de consumir por recrutadores e líderes técnicos.

Fluxo mínimo viável para 1-2 horas

Se tem pouco tempo: escolha 1 PR, rode o script extractor, gere um Markdown a partir do template, escreva as seções Problema/Abordagem/Resultados e publique. Em 1-2 horas você tem um case legível. Automatize o restante com Actions quando tiver escala.

O objetivo é criar repetibilidade: quanto mais rápido você converter um PR em case, mais casos terá para mostrar diversidade técnica.

Próximos passos práticos

Execute o script de extração no PR mais recente onde você liderou a solução. Gerar um primeiro case manualmente ajuda a calibrar o template. Depois, limpe e automatize com um workflow dispatch para criar novas entradas sem esforço.

Se precisar, adicione um script extra para validar privacidade (regex que detecte emails/URLs internos) antes de comitar cases.

Recursos e scripts adicionais

Script para sanitizar conteúdo sensível (exemplo)

Contexto: pequeno snippet para remover emails e endpoints internos antes de publicar o case. Útil quando seu extractor traz comentários ou mensagens de commit contendo dados sensíveis.

// sanitiza.js
// uso: node sanitiza.js pr-data.json > sanitized.json
const fs = require('fs');
const data = JSON.parse(fs.readFileSync(process.argv[2]));

function scrub(text) {
  return text
    .replace(/[\w.-]+@[\w.-]+\.[A-Za-z]{2,6}/g, '[email]')
    .replace(/https?:\/\/([\w.-]+)(:\d+)?(\/\S*)?/g, '[url]')
    .replace(/seu-cliente-interno/g, '[cliente]');
}

const cleaned = JSON.parse(JSON.stringify(data), (k, v) => {
  if (typeof v === 'string') return scrub(v);
  return v;
});

console.log(JSON.stringify(cleaned, null, 2));

O que acontece: remove endereços de email e URLs, e aplica uma substituição simples. Não é perfeito, mas reduz riscos antes da publicação.

Exemplo final: como apresentar no LinkedIn ou README

Contexto: snippet com texto enxuto para colocar link do case no LinkedIn ou README do portfólio.

Corrigi memory leak no cache de sessão (Node.js + Redis) — reduzi uso médio de memória por pod em 30% e eliminei incidentes OOM em 2 semanas. Case: https://seu-site.com/cases/corrige-leak-cache

O que acontece: mensagem curta, métrica e link. Isso chama atenção e convida à leitura do estudo de caso completo.

Encerramento

Trate PRs como matérias-primas: nem todo PR vira um case, mas os melhores sempre devem. Automatize coleta, padronize templates e escreva narrativas com foco técnico. Fazer isso de forma repetida aumenta sua credibilidade e melhora sua performance em entrevistas.

Próxima ação recomendada: rode o script de extração em um PR onde você foi autor e crie um case em 1 hora. Refatore o template após a primeira iteração e automatize com um workflow dispatch quando estiver satisfeito com o resultado.

Nota final

Este artigo foi escrito no estilo de code review: expõe práticas erradas e corrige com padrões aplicáveis. Aplique o checklist, escolha bons PRs e mantenha o portfólio enxuto e verificável.

Assuntos: portfoliodev, pull-requests, Git, Carreira, case-study

Leia também