Ficha 02 · Workflow profissional, GitHub avançado
- Workflow
- Conventions
- Actions
- Security
Parte I · Convenções
Exercício 1 · Conventional commits (15 pts)
Reescreve estas mensagens de commit seguindo Conventional Commits:
a) "fixed bug in login" b) "added new payment method" c) "updated readme" d) "refactored user model" e) "fixed typos"
Reescrito com Conventional Commits:
a) fix(auth): correct invalid credentials error on login
b) feat(payments): add PayPal payment method
c) docs(readme): update installation section
d) refactor(user): simplify validation logic in User model
e) docs: fix typos throughout codebase
Estrutura:
<type>(<scope>): <subject>
[body]
[footer]
Types principais: - feat: nova funcionalidade. - fix: correcção bug. - docs: documentação. - style: formatação (sem mudança de lógica). - refactor: refactoring (sem mudança funcional). - test: testes. - chore: manutenção (dependencies, build). - perf: melhoria de performance. - build: build system. - ci: CI configuration.
Scope (opcional):
- Módulo/área afectada: auth, cart, ui, api, etc.
- Coloca entre parêntesis após o type.
Subject: - Imperativo presente: "add" não "added". - Sem ponto final. - Minúsculas. - < 50 caracteres.
Body (opcional, para mudanças complexas): - Explica por que, não o quê (que está no diff). - Linha em branco após subject. - < 72 caracteres por linha.
Footer (opcional):
- Closes #123 para fechar issues.
- BREAKING CHANGE: ... para incompatibilidades.
Exemplos completos:
feat(auth): add multi-factor authentication
Implement TOTP-based MFA using Google Authenticator.
Users can now enable MFA in their profile settings.
Includes backup codes for recovery.
Closes #234
fix(checkout): correct tax calculation for EU
Tax was being calculated using US rates for EU orders.
Now uses country-specific rates from TaxService.
Affects all orders to EU since v2.1.0.
Fixes #567
BREAKING CHANGE: feat(api): remove deprecated v1 endpoints
All v1 API endpoints have been removed.
Clients must migrate to v2.
Migration guide: docs/migration-v1-to-v2.md
Vantagens:
- Histórico legível: scan fácil dos commits.
- Changelog automático: ferramentas geram baseado nos types.
- Semantic versioning automático:
feat→ minor version.fix→ patch version.BREAKING CHANGE→ major version.- Filtrar commits:
git log --grep="^feat"mostra só features. - Consistência entre equipa.
Ferramentas:
- commitizen (cz commit): assistente interactivo.
- commitlint: valida mensagens (em hook).
- standard-version / release-please: gera CHANGELOG automaticamente.
Exercício 2 · Branch naming (10 pts)
Sugere nomes apropriados para branches em cada cenário:
a) Adicionar página de perfil de utilizador. b) Corrigir bug onde botão de submit não funciona. c) Actualizar versão do React. d) Refactorizar código de autenticação. e) Adicionar testes para módulo de pagamentos.
Branch Names — Conventional Naming:
a) Página de perfil:
- feature/user-profile-page
- feature/add-profile-page
b) Bug no submit:
- fix/submit-button-broken
- fix/issue-123-submit-button (linkando issue)
- bugfix/submit-button
c) Update React:
- chore/update-react-to-18
- deps/react-18
- chore/upgrade-react
d) Refactor autenticação:
- refactor/auth-module
- refactor/simplify-auth-flow
e) Tests de pagamentos:
- test/add-payment-tests
- test/payment-coverage
Convenções:
Prefixos por tipo:
- feature/ ou feat/ — nova funcionalidade.
- fix/ ou bugfix/ — correcção bug.
- chore/ — manutenção.
- refactor/ — refactoring.
- test/ — testes.
- docs/ — documentação.
- hotfix/ — correcção urgente em produção.
- release/ — preparação de release.
Estrutura: - kebab-case (palavras separadas por hífenes). - descritivo mas conciso. - sem espaços (Git não permite).
Opcionalmente incluir issue number:
- fix/123-submit-button
- feature/issue-456-user-profile
Para projectos com muitos developers:
- <username>/<feature>:
- joana/add-login
- pedro/fix-cart
Útil para identificar dono visualmente.
Para Jira / similar:
- <ticket>/<description>:
- JIRA-123/add-login
- JIRA-456/fix-cart
Automatiza linking com Jira.
Más práticas a evitar:
❌ temp — vago, esquece-se.
❌ test1, test2 — sem informação.
❌ joana-branch — quem és tu não importa.
❌ bug — qual bug?
❌ WIP — work in progress (use comentário do PR).
❌ Acentos / espaços / caracteres especiais.
❌ Maiúsculas inconsistentes (Feature/Login vs feature/login).
Manutenção:
- Apagar branches após merge.
- Renomear se nome perde sentido:
bash git branch -m old-name new-name - Limpar periodicamente branches stale:
bash git branch --merged main | xargs git branch -d
Parte II · GitHub avançado
Exercício 3 · GitHub Actions (15 pts)
Escreve workflow GitHub Actions para: - Correr testes em cada push e PR. - Testar em Node.js 18 e 20. - Linter (ESLint). - Build do projecto.
GitHub Actions Workflow — CI
Ficheiro: .github/workflows/ci.yml
name: CI
on:
push:
branches: [main, develop]
pull_request:
branches: [main, develop]
jobs:
test:
name: Test on Node ${{ matrix.node-version }}
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18, 20]
fail-fast: false
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run linter
run: npm run lint
- name: Run tests
run: npm test -- --coverage
- name: Upload coverage
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
if: matrix.node-version == 20
build:
name: Build
runs-on: ubuntu-latest
needs: test
steps:
- name: Checkout code
uses: actions/checkout@v4
- name: Setup Node.js
uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Build project
run: npm run build
- name: Upload build artifacts
uses: actions/upload-artifact@v3
with:
name: build-output
path: dist/
retention-days: 7
Explicação:
name: nome do workflow visível na UI.
on:
- push: corre quando alguém faz push.
- pull_request: corre quando PR é aberto/actualizado.
- branches: filtra quais branches triggerem.
jobs: trabalhos paralelos.
test job:
- strategy.matrix: corre N versões em paralelo.
- Node 18 e 20: testa em ambas.
- fail-fast: false: não cancela todos se um falhar.
Steps: 1. Checkout: clona código. 2. Setup Node: instala versão específica. 3. Cache: poupa tempo em runs seguintes. 4. npm ci: install com lockfile (reproduzível). 5. Lint: ESLint. 6. Test: corre testes com cobertura. 7. Upload coverage: Codecov para visualização.
build job:
- needs: test: só corre se test passar.
- Build final.
- Upload artifacts: build files acessíveis no UI.
Outros workflows úteis:
Deploy automático (em merge para main):
name: Deploy to Production
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- run: npm run build
- name: Deploy to Vercel
uses: amondnet/vercel-action@v25
with:
vercel-token: ${{ secrets.VERCEL_TOKEN }}
vercel-org-id: ${{ secrets.ORG_ID }}
vercel-project-id: ${{ secrets.PROJECT_ID }}
vercel-args: '--prod'
Dependabot updates auto-merge:
name: Dependabot Auto-Merge
on: pull_request
jobs:
dependabot:
runs-on: ubuntu-latest
if: github.actor == 'dependabot[bot]'
steps:
- uses: dependabot/fetch-metadata@v1
id: meta
- name: Auto-merge patch updates
if: steps.meta.outputs.update-type == 'version-update:semver-patch'
run: gh pr merge --auto --merge "$PR_URL"
env:
PR_URL: ${{ github.event.pull_request.html_url }}
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Security scan:
name: Security Scan
on:
push:
branches: [main]
schedule:
- cron: '0 0 * * 0' # Weekly
jobs:
security:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Snyk
uses: snyk/actions/node@master
env:
SNYK_TOKEN: ${{ secrets.SNYK_TOKEN }}
Custos: - Repos públicos: ilimitado, grátis. - Repos privados: 2000 min/mês grátis (depois 0.008$/min Linux).
Marketplace: github.com/marketplace?type=actions — milhares de actions prontos.
Boas práticas:
- Cache sempre que possível.
- Matrix para múltiplas versões.
- Secrets em GitHub Secrets, nunca no código.
- Reusable workflows para DRY.
- Manual triggers com workflow_dispatch se útil.
Resultado: - Cada PR mostra status dos checks. - Bloqueia merge se falhar. - Garante qualidade. - Reduz bugs em produção.
Exercício 4 · Issues e Projects (10 pts)
Como usar GitHub Issues + Projects para gerir projecto de software?
Gestão de Projecto — GitHub Issues + Projects
Issues:
O que são: unidade de trabalho rastreável (bug, feature, task).
Estrutura típica:
Título: - Descritivo, conciso. - "Login button not working on Safari" (não "bug").
Description: - Contexto. - Steps to reproduce (para bugs). - Expected vs actual behavior. - Screenshots.
Labels:
- bug, feature, documentation.
- priority: high/medium/low.
- status: in-progress/blocked.
- good first issue (para contribuidores externos).
Assignees: quem trabalha.
Milestone: agrupar para release.
Linked PRs: PRs que resolvem este issue.
Templates de issues:
.github/ISSUE_TEMPLATE/bug_report.md:
---
name: Bug report
about: Create a report to help us improve
labels: bug
---
## Describe the bug
A clear description.
## To Reproduce
Steps to reproduce:
1. Go to '...'
2. Click on '...'
3. See error
## Expected behavior
What you expected.
## Screenshots
If applicable.
## Environment
- OS: [e.g. iOS 15]
- Browser: [e.g. Chrome 98]
- Version: [e.g. 2.4.1]
.github/ISSUE_TEMPLATE/feature_request.md:
---
name: Feature request
about: Suggest an idea
labels: enhancement
---
## Is your feature request related to a problem?
A description of the problem.
## Describe the solution
What you want to happen.
## Alternatives considered
Other solutions you've thought about.
## Additional context
Any other context or screenshots.
Projects (GitHub Projects v2):
O que é: kanban / table view para organizar issues e PRs.
Setup:
- Profile/Org → Projects → New project.
- Template: Board (kanban), Table, Roadmap.
Estrutura típica:
Colunas (Kanban): - 📋 Backlog: ideias futuras. - 🎯 To Do: priorizado para próximo. - 🔄 In Progress: a trabalhar agora. - 👀 In Review: aguardar code review. - ✅ Done: concluído.
Fields customizáveis: - Priority (Low / Medium / High / Critical). - Estimate (story points: 1, 2, 3, 5, 8, 13). - Sprint (Sprint 23, 24, 25). - Type (Bug / Feature / Task). - Assignee.
Views múltiplos: - Board view: kanban visual. - Table view: tabela com filtros. - Roadmap view: timeline (Gantt-like).
Automatizações: - Quando PR aberto → mover para "In Review". - Quando PR merged → mover para "Done". - Quando issue closed → mover para "Done".
Workflow exemplo — Equipa Scrum:
Início do sprint: 1. Refinement: equipa revê backlog. 2. Priorizar: top issues priorizadas. 3. Estimate: story points. 4. Sprint planning: mover issues para "Sprint X".
Durante sprint:
1. Daily: olhar board, mover cards.
2. Trabalhar:
- Pegar issue de "To Do" → "In Progress".
- Atribuir a si próprio.
- Criar branch: feature/issue-123-add-x.
- Trabalhar, commitar.
- Abrir PR linkando issue (Closes #123).
- Issue automaticamente vai para "In Review".
3. Code review:
- Reviewer aprova.
- Merge.
- Issue auto-fecha (devido a "Closes #123").
- Vai para "Done".
Fim de sprint: 1. Sprint review: demo das features. 2. Retrospective: análise. 3. Próximo sprint.
Labels strategy:
Por tipo:
- bug (vermelho).
- enhancement / feature (verde).
- documentation (azul).
- question (roxo).
Por prioridade:
- priority: critical (vermelho escuro).
- priority: high (laranja).
- priority: medium (amarelo).
- priority: low (cinza).
Por status:
- status: blocked (vermelho).
- status: needs-info (amarelo).
- status: ready (verde).
Por área:
- area: frontend.
- area: backend.
- area: design.
Especiais:
- good first issue (atrair contribuidores).
- help wanted.
- wontfix.
- duplicate.
Milestones:
Para releases:
- v1.0.0: features para release 1.0.
- v1.1.0: próxima minor.
- v2.0.0: próxima major.
Para sprints:
- Sprint 23 (2-2 weeks).
Para iniciativas:
- Q1 2026 Goals.
- Mobile App Launch.
Boas práticas:
✅ 1 issue por unidade de trabalho (não juntar 3 bugs num).
✅ Linkar PRs a issues (Closes #123).
✅ Atualizar status (mover cards).
✅ Comentar progresso em issues grandes.
✅ Fechar issues quando feitos.
❌ Issues vagas ("fix things"). ❌ Issues que ninguém vê (não atribuídos, sem labels). ❌ Issues abandonadas (rever periodicamente).
Para projectos open-source:
good first issuelabel atrai contribuidores novos.- CONTRIBUTING.md explica processo.
- Code of Conduct importante.
- Responder rápido a issues / PRs.
- Reconhecer contribuidores.
Integrações úteis:
- Slack/Discord: notificações de issues novas.
- Jira: sync bi-directional.
- Zapier: automações.
GitHub CLI:
# Criar issue
gh issue create --title "Bug X" --body "..."
# Listar
gh issue list
# Ver
gh issue view 123
# Comentar
gh issue comment 123 --body "..."
# Fechar
gh issue close 123
Muito mais rápido que UI web.
Resultado:
GitHub Issues + Projects = ferramenta poderosa e gratuita para gestão de projecto, especialmente para equipas tech. Substitui Jira, Trello para muitos casos.
Parte III · Segurança
Exercício 5 · Secrets (15 pts)
Acidentalmente commitaste API key num ficheiro .env. O que fazer?
Recuperação — API Key Commitada Acidentalmente
⚠️ ATENÇÃO: secret commitada é comprometida, mesmo que apagas depois. Histórico Git mantém-na.
Passo 1 — REVOGAR API key imediatamente (máxima prioridade):
Ir ao serviço (AWS, Stripe, Google, etc.): 1. Settings → API keys. 2. Revoke / Delete a chave compromised. 3. Generate new key.
Tempo: 5 minutos. Crítico.
Por que primeiro: - Bot scrapers fazem scan de GitHub procurando keys 24/7. - Em horas, key pode ser usada para activities maliciosas (mining crypto, spam, etc.). - Custo pode acumular rapidamente (AWS bills de milhares por uso fraudulento).
Passo 2 — Adicionar .env ao .gitignore:
echo ".env" >> .gitignore
git add .gitignore
git commit -m "chore: add .env to gitignore"
Passo 3 — Remover .env do tracking:
git rm --cached .env
git commit -m "chore: remove .env from tracking"
git push
--cached remove do Git mas mantém o ficheiro localmente.
Passo 4 — Limpar histórico (key continua no histórico até aqui):
Opção A — BFG Repo-Cleaner (mais fácil):
# Instalar BFG (Java required)
brew install bfg # Mac
# Ou download de github.com/rtyley/bfg-repo-cleaner
# Backup do repo
git clone --mirror git@github.com:user/repo.git
cd repo.git
# Substituir texto sensível por marcador
echo "OLD_API_KEY==>REDACTED" > replacements.txt
bfg --replace-text replacements.txt
# Limpeza
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# Force push
git push --force
Opção B — git filter-branch (built-in, mais complexo):
git filter-branch --force --index-filter \
"git rm --cached --ignore-unmatch .env" \
--prune-empty --tag-name-filter cat -- --all
# Cleanup
git reflog expire --expire=now --all
git gc --prune=now --aggressive
# Force push
git push --force --all
git push --force --tags
Opção C — git filter-repo (recomendado moderno):
# Instalar
brew install git-filter-repo
# Remover ficheiro do histórico
git filter-repo --invert-paths --path .env
# Force push
git remote add origin git@github.com:user/repo.git # re-add se necessário
git push --force --all
⚠️ AVISOS:
- Force push reescreve histórico.
- Outros developers terão de re-clone (não fazer pull).
- Comunicar à equipa antes.
- Branches no GitHub podem ter de ser fechadas e re-abertas.
Passo 5 — Comunicar à equipa:
Subject: ⚠️ Force push needed — please re-clone repo
Hi team,
I accidentally committed an API key. I'm rewriting Git history to remove it.
What you need to do:
1. Save any uncommitted work to a temporary location.
2. Delete your local copy of the repo.
3. Re-clone: git clone git@github.com:org/repo.git
4. Resume work.
I'll force-push in 15 minutes. Please confirm when ready.
The compromised key has been revoked. New key is in 1Password.
Sorry for the inconvenience!
João
Passo 6 — Audit (verificar uso fraudulento):
- AWS: CloudTrail logs, check unusual usage, bills.
- Stripe: API logs.
- Google Cloud: Activity Logs.
Procurar: - Calls de IPs desconhecidos. - Uso fora do normal. - Custos inesperados.
Se houve uso fraudulento: - Reportar ao provider (podem reverter charges). - Documentar para legal/security team.
Passo 7 — Adicionar prevenção:
Git hooks (pre-commit):
# Usar pre-commit framework
brew install pre-commit
cd repo
echo "
repos:
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
" > .pre-commit-config.yaml
pre-commit install
Agora cada commit é scanned para secrets.
GitGuardian / Snyk: - Serviços que monitorizam repos para secrets exposed. - Free tier para individuals. - Alertas em tempo real.
Boa prática:
- .env.example (commitable) com variáveis listadas mas valores em branco.
- .env (não commitable) com valores reais.
.env.example:
DATABASE_URL=
API_KEY=
SECRET_KEY=
.env (local, não commitado):
DATABASE_URL=postgres://user:pass@localhost:5432/db
API_KEY=sk-1234567890abcdef
SECRET_KEY=my-secret-here
Lições aprendidas:
- Antes de cada commit, verificar
git statuspara confirmar o que está a ser commitado. .envao.gitignoredesde o primeiro commit.- Hooks pre-commit automatizam prevenção.
- Secrets managers (1Password, HashiCorp Vault) em vez de ficheiros locais.
- Educação contínua da equipa.
Custos potenciais sem revogar rapidamente:
- AWS: bills de milhares de € (crypto mining).
- Email: usado para spam (reputação queimada).
- Database: dados roubados.
- GDPR fines se dados pessoais expostos.
- Reputação: clientes perdem confiança.
Tempo é crítico. Revogar primeiro, limpar depois.
Resumo:
- ⚠️ Revogar key (5 min).
.gitignore+ remove tracking (2 min).- Limpar histórico (BFG, 15 min).
- Force push + avisar equipa (10 min).
- Audit uso fraudulento.
- Implementar prevenção.
Total: ~30 min de trabalho, mas poupa potencial desastre.
Exercício 6 · 2FA + SSH (10 pts)
Como configurar GitHub para máxima segurança?
Segurança Máxima no GitHub
1. Password forte: - Mínimo 16 caracteres. - Misto de letras (maiús + minus), números, símbolos. - Único (não usado noutros sites). - Password manager (1Password, Bitwarden) gera + guarda.
2. Autenticação Dois Factores (2FA) — OBRIGATÓRIO desde 2023:
Opção A — TOTP (recomendado): - App: Google Authenticator, Authy, 1Password. - Settings → Password and authentication → Two-factor authentication. - Scan QR code com app. - Guardar recovery codes (offline, em local seguro).
Opção B — Security key (mais seguro): - YubiKey ou similar. - Hardware physical. - Imune a phishing.
Opção C — Passkeys (moderno): - Biometria do device (Touch ID, Face ID). - Sem password.
Não usar SMS (vulnerável a SIM-swap).
3. SSH key authentication:
Setup (já visto, recap):
# Gerar
ssh-keygen -t ed25519 -C "email@example.com"
# Adicionar ao agent
eval "$(ssh-agent -s)"
ssh-add ~/.ssh/id_ed25519
# Copiar pública
cat ~/.ssh/id_ed25519.pub | pbcopy # Mac
cat ~/.ssh/id_ed25519.pub | xclip # Linux
# No GitHub: Settings → SSH and GPG keys → New SSH key
# Testar
ssh -T git@github.com
Vantagens vs HTTPS + token: - Sem password a cada push. - Cifragem forte (ed25519 melhor que RSA). - Auditable: ver onde a chave foi usada.
4. GPG signing commits:
Verificar autoria dos commits:
# Gerar chave GPG
gpg --full-generate-key
# Listar
gpg --list-secret-keys --keyid-format LONG
# Copiar (formato armor)
gpg --armor --export YOUR_KEY_ID
# Adicionar ao GitHub: Settings → SSH and GPG keys → New GPG key
# Configurar Git para usar
git config --global user.signingkey YOUR_KEY_ID
git config --global commit.gpgsign true
Commits aparecem "Verified" no GitHub.
5. Revisão de SSH keys:
Periodicamente: - Settings → SSH keys: ver lista de chaves. - Remover chaves de devices antigos / vendidos. - Datas de criação visíveis.
6. Sessions activas:
- Settings → Sessions: ver onde estás logged in.
- Revogar sessões suspeitas.
7. Authorized applications:
- Settings → Applications: ver apps com acesso.
- Revogar apps que já não usas.
8. Notifications de security:
- Settings → Notifications:
- Vulnerable dependencies alerts.
- Code scanning alerts.
- Secret scanning alerts.
9. Repos com proteções:
Para cada repo importante:
Branch protection rules (main): - Settings → Branches → Add rule. - Require pull request reviews (1+ approvers). - Require status checks to pass. - Require conversation resolution. - Require signed commits (se usar GPG). - No force pushes. - No deletions.
10. Dependabot:
- Settings → Security & analysis:
- Dependabot alerts: notifica de vulnerabilidades.
- Dependabot security updates: auto-PRs com fixes.
- Dependabot version updates: auto-PRs com upgrades.
11. Secret scanning:
- GitHub scaneia repos para secrets commitados.
- Notifica owner.
- Notifica provider (AWS, Stripe) para revogar automaticamente.
12. Code scanning (GitHub Advanced Security):
- CodeQL corre análise estática.
- Detecta vulnerabilidades (SQL injection, XSS, etc.).
- Gratuito para repos públicos.
13. Recovery codes:
Ao activar 2FA, GitHub gera 10 recovery codes.
Guardar: - Imprimir e guardar em local seguro. - Password manager (encriptado). - Não em ficheiro plain text no PC.
Cada código usado uma vez. Se perderes 2FA device, podes recuperar conta.
14. Audit log (organizações):
- Organização → Settings → Audit log.
- Ver todas as actividades.
- Detectar comportamentos suspeitos.
15. IP allowlist (Enterprise):
- Limitar acesso a IPs específicos.
- Para empresas com VPN obrigatória.
Checklist mensal de segurança:
- [ ] 2FA activo e funcional.
- [ ] SSH keys actuais (sem antigas).
- [ ] Apps autorizadas (rever).
- [ ] Sessions activas (sem suspeitas).
- [ ] Repos importantes com branch protection.
- [ ] Dependabot alerts atendidos.
- [ ] Secret scanning sem alerts.
- [ ] Recovery codes guardados.
Se conta comprometida:
- Mudar password imediatamente.
- Reset 2FA se necessário.
- Rever SSH keys e remover suspeitas.
- Audit log para ver actividade.
- Contactar GitHub Support (suporte@github.com).
- Notificar colaboradores se org affected.
Princípio: defense in depth. Múltiplas camadas de segurança protegem mesmo se uma falha.
Parte IV · Workflow
Exercício 7 · Resolver problema (15 pts)
Trabalhas numa equipa de 5. Há semanas que estás a fazer commits directamente para main, sem PRs. Várias vezes quebrou o build de outros. Como melhorar workflow?
Implementar Workflow Profissional na Equipa
Diagnóstico:
Problemas actuais: - Sem branches → conflitos directos. - Sem PRs → sem code review. - Sem CI → builds quebrados não detectados. - Sem testes obrigatórios → bugs em produção. - Sem proteções → main é instável.
Resultado: equipa pisa-se mutuamente, qualidade baixa, frustração alta.
Plano de implementação (4-6 semanas):
Semana 1 — Educação + planeamento:
Reunião de equipa (1h): - Apresentar problemas (com dados: quantas vezes build quebrou, etc.). - Propor nova abordagem (GitHub Flow). - Discutir benefícios. - Obter buy-in da equipa (essencial — sem isto, falha).
Decisões a tomar: - Branching strategy: GitHub Flow (mais simples) ou Git Flow (mais formal)? - PR requirements: 1 ou 2 approvers? - Tests obrigatórios? - Merge strategy: squash, merge commit, rebase?
Conventional commits: adoptar?
Semana 2 — Setup técnico:
1. Configurar branch protection rules no GitHub:
Para main: - ☑ Require pull request reviews (1 approver mínimo). - ☑ Dismiss stale reviews when new commits pushed. - ☑ Require status checks to pass. - ☑ Require branches to be up to date. - ☑ Require conversation resolution. - ☑ Include administrators (todos seguem regras, incluindo chefes). - ☐ Restrict who can push (apenas via PR).
2. Setup CI básico:
.github/workflows/ci.yml:
name: CI
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 20
cache: 'npm'
- run: npm ci
- run: npm run lint
- run: npm test
- run: npm run build
3. PR template:
.github/pull_request_template.md:
## Description
[What does this PR do?]
## Type
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation
## Testing
[How was this tested?]
## Checklist
- [ ] Tests added
- [ ] Documentation updated
- [ ] Self-review done
4. Code owners (opcional):
.github/CODEOWNERS:
# Auto-assign reviewers based on files
/frontend/ @joana @pedro
/backend/ @pedro @maria
/docs/ @ana
Semana 3 — Workshop + começar:
Workshop hands-on (2h): - Demo do novo workflow. - Cada um clona repo, cria branch, faz PR exemplo. - Resolver dúvidas. - Documento de referência (cheat sheet).
Documento WORKFLOW.md no repo:
# Team Workflow
## Daily flow
1. `git checkout main && git pull`
2. `git checkout -b feature/your-feature`
3. Work, commit (use conventional commits)
4. `git push -u origin feature/your-feature`
5. Open PR on GitHub
6. Address review comments
7. Merge when approved + CI green
## PR rules
- Small (< 400 lines)
- Clear description
- Tests included
- 1 reviewer minimum
## Commit messages
Use conventional commits:
- feat: new feature
- fix: bug fix
- docs: documentation
- chore: maintenance
Começar com workflow novo: - A partir de Segunda, todas mudanças via PR. - Sem excepções (excepto hotfix emergência, com regra clara).
Semana 4-6 — Adopção + ajustes:
Suporte: - Programador sénior disponível para ajudar com PRs. - Pair programming nos primeiros PRs. - Code review pedagógico (explicar por que mudanças sugeridas).
Retrospectiva semanal (curta, 30 min): - O que está a funcionar? - O que é frustrante? - Como ajustar?
Ajustes comuns: - Se PRs demoram demais para review: definir SLA (ex: < 24h). - Se PRs ficam grandes: educar para PRs pequenos. - Se conflitos persistem: melhor coordenação.
Métricas a monitorizar:
| Métrica | Antes | 4 semanas | 8 semanas |
|---|---|---|---|
| Builds quebrados / semana | 3-4 | 1 | 0 |
| Bugs em produção | 5/sprint | 3/sprint | 1/sprint |
| Tempo de review (média) | N/A | 8h | 4h |
| PRs merged / semana | N/A | 15 | 25 |
| Conflitos / semana | 4-5 | 2 | 1 |
Desafios comuns e como gerir:
Desafio 1 — "Isto é mais lento":
Resposta: - Sim, individualmente pode parecer. - Mas equipa como um todo é mais rápida (menos bugs, menos retrabalho). - Builds quebrados que afectam todos custam mais que tempo de PR.
Mostrar com dados após 4 semanas.
Desafio 2 — "Tenho hotfix urgente":
Definir processo de hotfix:
- Branch hotfix/<descrição> direto de main.
- PR ainda obrigatório, mas review pode ser expedito (15 min).
- 1 approver suficiente.
- Merge → deploy imediato.
- Outras mudanças aguardam.
Desafio 3 — "Não sei fazer code review":
Formação: - Sessão sobre code review (1h). - Materiais: artigos, vídeos. - Pair review nos primeiros (sénior + júnior).
Desafio 4 — "Tests demoram":
Optimizar CI: - Cache de dependencies. - Tests em paralelo. - Skip tests irrelevantes ao PR. - Targets: < 5 min para CI total.
Desafio 5 — "Conflito constante no main":
- Branches mais curtas.
- Sync com main mais frequente.
- Coordenar com equipa (quem trabalha em quê).
Sucessos a celebrar:
- 30 dias sem build quebrado.
- PR mais bem reviewed da semana.
- Métricas melhoradas mostradas mensalmente.
- Junior que se tornou bom reviewer.
Long-term evolution:
3 meses depois: - Adicionar integration tests ao CI. - Code coverage mínimo. - Security scanning. - Performance benchmarks.
6 meses depois: - Continuous deployment (auto-deploy de main). - Feature flags para releases controladas. - Monitoring + alertas.
1 ano: - Equipa madura. - DORA metrics monitorizadas. - High-performing team.
Cultura:
A componente mais importante:
✅ Tolerância a erros (todos cometem). ✅ Aprendizagem contínua. ✅ Respeito mútuo em code reviews. ✅ Celebrar pequenas vitórias. ✅ Iteração constante (workflow evolui).
❌ Não punir quem comete erro de workflow. ❌ Não tornar PRs em ataques pessoais. ❌ Não desistir se primeira semana é difícil.
Resultado esperado:
Em 2-3 meses: - Builds estáveis. - Menos bugs em produção. - Equipa colabora melhor. - Cada um aprende com os outros (code reviews). - Mais confiança em pushes. - Onboarding de novos developers facilitado (workflow documentado).
Investimento inicial paga-se em semanas.
Exercício 8 · Projecto prático (10 pts)
Cria pequeno projecto demo em GitHub para mostrar competências Git/GitHub no teu portfolio:
Projecto Portfolio — Demo Git/GitHub Skills
Conceito: pequena app (calculator, todo list, etc.) bem-feita demonstrando boas práticas Git/GitHub.
Stack sugerida (escolher conforme tua stack): - Frontend: HTML + CSS + JavaScript / React / Vue. - Backend: Node.js + Express / Python + Flask. - DB (se aplicável): SQLite / PostgreSQL.
Estrutura do repo:
my-portfolio-project/
├── .github/
│ ├── workflows/
│ │ ├── ci.yml
│ │ └── deploy.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── pull_request_template.md
│ └── CODEOWNERS
├── src/
│ ├── components/
│ ├── utils/
│ └── index.js
├── tests/
│ └── unit/
├── docs/
│ ├── architecture.md
│ └── api.md
├── .gitignore
├── .env.example
├── package.json
├── README.md
├── CONTRIBUTING.md
├── LICENSE
├── CHANGELOG.md
└── CODE_OF_CONDUCT.md
Elementos essenciais a demonstrar:
1. README impecável:
# Awesome Calculator
[] [] []
Modern calculator app with history, themes, and keyboard shortcuts.

## Features
- ✅ Basic arithmetic
- ✅ Scientific functions (sin, cos, sqrt, etc.)
- ✅ History (last 100 operations)
- ✅ Light/Dark theme
- ✅ Keyboard shortcuts
- ✅ Mobile responsive
## Live Demo
[awesome-calculator.vercel.app](https://example.com)
## Quick Start
```bash
git clone https://github.com/user/awesome-calculator.git
cd awesome-calculator
npm install
npm run dev
Tech Stack
- React 18
- TypeScript
- Vite
- Tailwind CSS
- Vitest (tests)
Documentation
License
MIT — see LICENSE
Author
João Silva — @joaosilva
**2. Convenção de commits**:
Histórico mostra:
feat(calc): add scientific functions feat(ui): implement dark theme fix(calc): correct floating point precision docs(readme): update installation steps test(calc): add tests for division by zero chore: bump dependencies
Reviewer / employer pode ver: sabes convencional commits.
**3. Branches e PRs**:
Mesmo trabalhando sozinho:
- Cada feature em branch.
- PRs com descrição.
- Self-merge (justificado em projecto solo).
Mostra: conheces o workflow profissional.
**4. CI/CD**:
`.github/workflows/ci.yml` corre em cada push:
- Linter.
- Tests.
- Build.
Badge no README mostra status.
**5. Tests**:
Cobertura > 80%:
```javascript
// tests/calculator.test.js
import { describe, it, expect } from 'vitest';
import { Calculator } from '../src/calculator';
describe('Calculator', () => {
it('should add two numbers', () => {
expect(new Calculator().add(2, 3)).toBe(5);
});
it('should handle division by zero', () => {
expect(() => new Calculator().divide(10, 0))
.toThrow('Cannot divide by zero');
});
});
6. Documentação:
docs/architecture.md: explica decisões técnicas.docs/api.md: se houver API.- Comentários inline úteis (não óbvios).
7. Issues:
Algumas issues abertas/fechadas mostrando: - Features planeadas. - Bugs resolvidos com PRs linkados. - Labels usados.
8. Releases:
git tag -a v1.0.0 -m "Initial release"
git push --tags
GitHub mostra release com: - Notas detalhadas. - Assets (downloadable). - Changelog.
9. License:
LICENSE file com MIT (ou outra apropriada).
10. Deploy:
App publicada em: - Vercel (frontend). - Netlify (frontend). - Heroku / Railway / Render (full-stack). - GitHub Pages (static).
Link no README + repo description.
Diferenciadores extras (para impressionar):
✅ Pre-commit hooks (Husky):
// package.json
"husky": {
"hooks": {
"pre-commit": "npm test && npm run lint",
"commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
}
}
✅ Conventional commits enforcement: - commitlint config.
✅ Dependabot configurado:
- .github/dependabot.yml.
✅ Security policy:
- SECURITY.md explicando como reportar vulnerabilidades.
✅ Code of Conduct:
- CODE_OF_CONDUCT.md.
✅ Funding:
- .github/FUNDING.yml (links para sponsors).
✅ Templates profissionais para issues e PRs.
✅ Storybook (UI components).
✅ Live preview deploys (Vercel para cada PR).
Tempo investido:
- Versão básica: 1-2 dias.
- Versão polida: 1 semana.
- Versão impressive: 2-4 semanas.
Retorno:
- Portfolio distintivo.
- Demonstra competências técnicas + soft skills (documentação, organização).
- Linkado em CV + LinkedIn.
- Conversa em entrevistas: "fala sobre este projecto".
Tópicos para o projecto:
Ideias que mostram skills:
- Calculadora moderna (matemática + UI).
- Todo app com features avançadas (drag&drop, sync, etc.).
- Markdown editor com preview.
- Weather app (consome API externa).
- Password manager (cifragem).
- URL shortener (full-stack com DB).
- Personal blog (CMS simples).
- Game (Wordle clone, snake, etc.).
Escolher algo que gostes — vais investir tempo.
Apresentação no CV:
Personal Projects
─────────────────
Awesome Calculator (2026)
React, TypeScript, Vitest
github.com/user/awesome-calculator
Live: awesome-calculator.vercel.app
- Implemented from scratch in React + TypeScript
- 95% test coverage with Vitest
- CI/CD pipeline with GitHub Actions
- Conventional commits, branching strategy
- Comprehensive documentation
Princípio fundamental:
Quality > Quantity.
1 projecto excelente > 10 projectos medíocres.
Mostra: - Sabes fazer Git/GitHub profissionalmente. - Disciplina. - Atenção a detalhes. - Pensamento estruturado.
Estas são exactamente as qualidades que employers procuram em developers.