Pipeline no git: PR valida, main/tag publica. Detecte a stack (package.json, go.mod, Cargo.toml, *.csproj, Gradle, Xcode) e não copie um workflow Node em app Go.
Lojas mobile: github-actions-android / github-actions-ios. Mac: github-actions-macos. Watch: github-actions-watchos. Checklist de go-live: production-readiness. Imagens: docker.
Organização
.github/
workflows/
ci.yml
deploy.yml # ou job no mesmo arquivo
dependabot.yml # updates de actions
- Um workflow de CI em todo PR. Deploy em workflow/job separado com
needs:. - Preserve os arquivos já no repo; não invente um segundo
ci.ymlparalelo.
Regras inegociáveis
permissions:explícito no workflow/job. Default mental:contents: read.id-token: writesó no job que troca OIDC (AWS/GCP/Azure). Sem access key longa se OIDC existir.- Secrets só em GitHub Secrets / Environments. Nunca no YAML,
echo, nempull_requestde fork (secrets não vazam para fork — não tente “consertar”). - Deploy:
if: github.ref == 'refs/heads/main'(ou tag) eenvironment: production(reviewer em prod). - Actions oficiais pinadas no major (
actions/checkout@v4). Sem@master/@mainde terceiros. npm ci/go mod downloaddeterminístico; nãonpm installno CI.
CI mínimo
name: CI
on:
pull_request:
push:
branches: [main]
concurrency:
group: ci-${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true
permissions:
contents: read
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
# setup da stack + cache do action oficial
- run: make test # ou npm ci && npm test, go test ./..., etc.
- Dispare o que o repo já tem: lint, typecheck, unit. Não adicione ferramenta nova só para o YAML.
- Jobs paralelos (lint ∥ test ∥ build) quando o job único passar de ~10 min.
- Matrix só com versões que o produto suporta (não 6 JDKs “por via das dúvidas”).
Cache e artefatos
- Cache via
setup-node/setup-go/setup-javacache:.actions/cachesó se o setup não cobrir. upload-artifactpara o que o deploy/job seguinte precisa; retenção curta.- Não cacheie secrets nem
~/.ssh.
CD (genérico)
deploy:
needs: test
if: github.ref == 'refs/heads/main' && github.event_name == 'push'
runs-on: ubuntu-latest
environment: production
permissions:
contents: read
id-token: write
steps:
- uses: actions/checkout@v4
# OIDC → cloud; migrate → app → smoke
- Ordem: testes verdes → migrate → app → health/smoke (
production-readiness). - Environments:
stagingautomático;productioncom proteção. - Play / App Store / notarize Mac / Watch não entram aqui — skills
github-actions-*da plataforma.
Reuso
- Monorepo:
paths:/paths-ignorepara não buildar o mundo. Reusable workflow (workflow_call) se 3+ apps repetem o mesmo job. - Composite action em
.github/actions/para sequências internas (setup + cache).
Segurança do workflow
pull_request_targetquase nunca. Não rode código do fork com secrets.GITHUB_TOKENleast privilege; nãopersist-credentials: truesem necessidade.- Dependabot:
package-ecosystem: github-actions. actions/checkoutde SHA de PR é o default empull_request— não faça checkout demainpara “testar o PR”.
Anti-padrões
permissions: write-all- Secret de AWS em todo job
- Deploy no mesmo job do
npm testsemneeds curl | bashno step- Workflow copiado com
node-version: 16morto continue-on-errorno test de PR
Integração com outras skills
- Android Play:
github-actions-android - iOS TestFlight/App Store:
github-actions-ios - macOS notarize / Mac App Store:
github-actions-macos - watchOS:
github-actions-watchos - Go-live:
production-readiness - Imagem:
docker - Testes da stack:
testing-fullstack,golang-unit-testing,android-unit-testing,swift-testing, …
Critérios de conclusão
- CI no PR: lint/test/build da stack detectada
permissionsmínimos; secrets só no ambiente certo- Deploy gated (
needs+ branch + environment) - Cache dos setup actions
- Sem
@masterde actions