[{"data":1,"prerenderedAt":1935},["ShallowReactive",2],{"article-\u002Fautomacao\u002Fpipeline-ci-cd-escalavel":3},{"id":4,"title":5,"author":6,"body":7,"category":1919,"date":1920,"description":1921,"extension":1922,"keywords":1923,"meta":1929,"navigation":388,"path":1930,"seo":1931,"slug":1932,"stem":1933,"updated":1920,"__hash__":1934},"content\u002Fautomacao\u002Fpipeline-ci-cd-escalavel.md","Pipeline de CI\u002FCD escalável: do commit ao deploy","Inicialize Tec",{"type":8,"value":9,"toc":1887},"minimark",[10,15,86,90,115,118,133,140,144,147,178,181,259,263,266,277,292,296,299,304,356,454,458,461,467,472,475,479,482,486,493,497,500,520,529,533,539,543,563,567,636,640,647,789,793,799,803,831,835,838,928,932,935,939,942,1013,1024,1028,1042,1046,1061,1065,1068,1072,1075,1079,1082,1688,1691,1722,1726,1787,1791,1870,1873,1883],[11,12,14],"h2",{"id":13},"índice","Índice",[16,17,18,26,32,38,44,50,56,62,68,74,80],"ol",{},[19,20,21],"li",{},[22,23,25],"a",{"href":24},"#o-que-e","O que é CI\u002FCD (em palavras simples)",[19,27,28],{},[22,29,31],{"href":30},"#por-que-escalar","Por que um pipeline precisa \"escalar\"",[19,33,34],{},[22,35,37],{"href":36},"#etapas","As etapas de um pipeline completo",[19,39,40],{},[22,41,43],{"href":42},"#build","Build: a fundação do pipeline",[19,45,46],{},[22,47,49],{"href":48},"#testes","Testes: a rede de segurança",[19,51,52],{},[22,53,55],{"href":54},"#deploy","Deploy automático: do commit à produção",[19,57,58],{},[22,59,61],{"href":60},"#rollback","Rollback: o botão \"desfazer\" profissional",[19,63,64],{},[22,65,67],{"href":66},"#times-grandes","Estratégias para times grandes",[19,69,70],{},[22,71,73],{"href":72},"#exemplo-github","Exemplo real com GitHub Actions",[19,75,76],{},[22,77,79],{"href":78},"#erros","Erros comuns",[19,81,82],{},[22,83,85],{"href":84},"#checklist","Checklist final",[11,87,89],{"id":88},"o-que-é-cicd-em-palavras-simples-o-que-e","O que é CI\u002FCD (em palavras simples) {#o-que-e}",[91,92,93,94,98,99,103,104,98,107,110,111,114],"p",{},"Antes de usar a sigla, vamos explicar o que ela significa. ",[95,96,97],"strong",{},"CI"," é ",[100,101,102],"em",{},"Continuous\nIntegration"," (Integração Contínua) e ",[95,105,106],{},"CD",[100,108,109],{},"Continuous Delivery"," (Entrega\nContínua) ou ",[100,112,113],{},"Continuous Deployment"," (Deploy Contínuo), dependendo do nível de\nautomação que você deseja.",[91,116,117],{},"Imagine uma cozinha de restaurante. Sem CI, cada cozinheiro prepara seu prato\nsozinho, no seu canto, e só no final tudo é juntado — frequentemente os temperos\nnão combinam e ninguém percebeu até o cliente reclamar. Com CI, a cada passo\ntodo mundo prova a receita juntos e ajusta na hora. Com CD, o prato sai da\ncozinha para a mesa do cliente automaticamente, sem precisar de um garçom\nintermediário que confere tudo de novo.",[91,119,120,121,123,124,126,127,129,130,132],{},"Em software: ",[95,122,97],{}," é integrar o código de todas as pessoas desenvolvedoras\nvárias vezes ao dia em um branch compartilhado, rodando testes automaticamente\na cada integração. ",[95,125,106],{}," é garantir que esse código integrado esteja sempre\npronto para ir para produção — seja com um clique humano (",[100,128,109],{},")\nou sozinho (",[100,131,113],{},").",[91,134,135,136,139],{},"Um ",[95,137,138],{},"pipeline"," é a sequência automática de etapas que executa tudo isso. Pense\nnuma esteira de montagem de uma fábrica: a peça entra crus, passa por várias\nestações (solda, pintura, teste, embalagem) e sai pronta para entrega. Se\nqualquer estação detecta defeito, a peça é rejeitada e volta para correção.",[11,141,143],{"id":142},"por-que-um-pipeline-precisa-escalar-por-que-escalar","Por que um pipeline precisa \"escalar\" {#por-que-escalar}",[91,145,146],{},"Um pipeline que funciona para 2 pessoas em um repositório quase sempre quebra\ncom 50 pessoas em 20 repositórios. Os sintomas clássicos:",[148,149,150,160,166,172],"ul",{},[19,151,152,155,156,159],{},[95,153,154],{},"Builds lentos",": o pipeline demora 40 minutos, o time para de esperar e\nfaz ",[100,157,158],{},"push"," direto na main (pulo do gato para o desastre).",[19,161,162,165],{},[95,163,164],{},"Gargalo de infraestrutura",": só há 2 runners disponíveis, 10 PRs esperando\nna fila, ninguém revisa código porque está esperando CI.",[19,167,168,171],{},[95,169,170],{},"Falsos negativos",": testes instáveis (\"flaky tests\") quebram aleatoriamente,\no time aprende a ignorar o CI vermelho, e bugs reais passam despercebidos.",[19,173,174,177],{},[95,175,176],{},"Custo cloud explosivo",": cada PR roda testes E2E completos em 10 ambientes,\na fatura da AWS triplica sem ninguém perceber.",[91,179,180],{},"Um pipeline escalável é aquele que continua rápido, confiável e barato mesmo\nquando o time, o número de repositórios e a frequência de deploys crescem\n5x, 10x, 50x. Isso não acontece por acidente — é projeto.",[182,183,184,200],"table",{},[185,186,187],"thead",{},[188,189,190,194,197],"tr",{},[191,192,193],"th",{},"Sintoma",[191,195,196],{},"Pipeline que NÃO escala",[191,198,199],{},"Pipeline que escala",[201,202,203,215,226,237,248],"tbody",{},[188,204,205,209,212],{},[206,207,208],"td",{},"Tempo de build",[206,210,211],{},"30-60 min, cresce linearmente",[206,213,214],{},"5-10 min, paralelizado",[188,216,217,220,223],{},[206,218,219],{},"Confiabilidade",[206,221,222],{},"80% verde, 20% flaky",[206,224,225],{},"99%+ verde, flaky = bloqueio",[188,227,228,231,234],{},[206,229,230],{},"Custo por PR",[206,232,233],{},"$5-15",[206,235,236],{},"$0.50-2",[188,238,239,242,245],{},[206,240,241],{},"Fila em horário pico",[206,243,244],{},"20+ min esperando runner",[206,246,247],{},"\u003C 2 min",[188,249,250,253,256],{},[206,251,252],{},"Onboarding de novo repo",[206,254,255],{},"2 dias de config",[206,257,258],{},"1 comando (template reutilizável)",[11,260,262],{"id":261},"as-etapas-de-um-pipeline-completo-etapas","As etapas de um pipeline completo {#etapas}",[91,264,265],{},"Um pipeline moderno tem, no mínimo, estas estações:",[267,268,273],"pre",{"className":269,"code":271,"language":272},[270],"language-text","[Commit\u002FPR]\n    ↓\n1. Checkout & cache         ← baixar código e dependências cacheadas\n    ↓\n2. Lint & format check      ← estilo de código (rapidíssimo)\n    ↓\n3. Build                    ← compilar, empacotar, criar imagem Docker\n    ↓\n4. Testes unitários         ← isolados, rápidos (\u003C 1 min)\n    ↓\n5. Testes de integração     ← sobem dependências (banco, Redis) em containers\n    ↓\n6. Security scan            ← SAST, dependências vulneráveis, secrets leak\n    ↓\n7. Artefato + imagem        ← publicar em registry\n    ↓\n8. Deploy (staging)         ← ambiente de validação\n    ↓\n9. Testes E2E \u002F smoke       ← fluxo crítico em ambiente real\n    ↓\n10. Deploy (produção)       ← com estratégia + rollback automático\n","text",[274,275,271],"code",{"__ignoreMap":276},"",[91,278,279,280,283,284,287,288,291],{},"Cada etapa deve ser ",[95,281,282],{},"paralelizável"," quando possível e ",[95,285,286],{},"cachear"," tudo que\npuder. A regra de ouro: ",[95,289,290],{},"o que muda pouco deve ser reaproveitado, o que muda\nmuito deve rodar em paralelo",".",[11,293,295],{"id":294},"build-a-fundação-do-pipeline-build","Build: a fundação do pipeline {#build}",[91,297,298],{},"O build é onde o código-fonte vira algo executável. Em linguagens compiladas\n(Go, Rust, Java) é a compilação; em linguagens interpretadas (Python, Node) é\na instalação de dependências + transpilação (TypeScript → JavaScript, por\nexemplo).",[91,300,301],{},[95,302,303],{},"Dicas de build escalável:",[16,305,306,327,337,350],{},[19,307,308,311,312,315,316,315,319,322,323,326],{},[95,309,310],{},"Cache de dependências",": reusar ",[274,313,314],{},"node_modules\u002F",", ",[274,317,318],{},"~\u002F.m2",[274,320,321],{},"~\u002F.cargo"," entre\nexecuções economiza minutos. GitHub Actions tem ",[274,324,325],{},"actions\u002Fcache"," nativo.",[19,328,329,332,333,336],{},[95,330,331],{},"Build em container",": garantir que o build rode igual na máquina de\nqualquer pessoa e no CI. Um ",[274,334,335],{},"Dockerfile"," de build padroniza o ambiente.",[19,338,339,342,343,315,346,349],{},[95,340,341],{},"Docker layer caching",": em imagens Docker, copie primeiro os arquivos de\ndependência (",[274,344,345],{},"package.json",[274,347,348],{},"go.mod",") e instale antes de copiar o código.\nAssim a layer de dependências fica em cache e só invalida quando muda.",[19,351,352,355],{},[95,353,354],{},"Build matrix",": testar em múltiplas versões (Node 18 e 20, Python 3.10 e\n3.12) em paralelo, não em sequência.",[267,357,361],{"className":358,"code":359,"language":360,"meta":276,"style":276},"language-dockerfile shiki shiki-themes github-light github-dark","# Dockerfile otimizado para cache de layers\nFROM node:20-alpine AS builder\nWORKDIR \u002Fapp\n\n# Copia só manifestos primeiro → layer de deps cacheada\nCOPY package*.json .\u002F\nRUN npm ci --omit=dev\n\n# Só agora copia o código → só esta layer invalida a cada commit\nCOPY . .\nRUN npm run build\n\n# Imagem final enxuta (multi-stage)\nFROM nginx:alpine\nCOPY --from=builder \u002Fapp\u002Fdist \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\n","dockerfile",[274,362,363,371,377,383,390,396,402,408,413,419,425,431,436,442,448],{"__ignoreMap":276},[364,365,368],"span",{"class":366,"line":367},"line",1,[364,369,370],{},"# Dockerfile otimizado para cache de layers\n",[364,372,374],{"class":366,"line":373},2,[364,375,376],{},"FROM node:20-alpine AS builder\n",[364,378,380],{"class":366,"line":379},3,[364,381,382],{},"WORKDIR \u002Fapp\n",[364,384,386],{"class":366,"line":385},4,[364,387,389],{"emptyLinePlaceholder":388},true,"\n",[364,391,393],{"class":366,"line":392},5,[364,394,395],{},"# Copia só manifestos primeiro → layer de deps cacheada\n",[364,397,399],{"class":366,"line":398},6,[364,400,401],{},"COPY package*.json .\u002F\n",[364,403,405],{"class":366,"line":404},7,[364,406,407],{},"RUN npm ci --omit=dev\n",[364,409,411],{"class":366,"line":410},8,[364,412,389],{"emptyLinePlaceholder":388},[364,414,416],{"class":366,"line":415},9,[364,417,418],{},"# Só agora copia o código → só esta layer invalida a cada commit\n",[364,420,422],{"class":366,"line":421},10,[364,423,424],{},"COPY . .\n",[364,426,428],{"class":366,"line":427},11,[364,429,430],{},"RUN npm run build\n",[364,432,434],{"class":366,"line":433},12,[364,435,389],{"emptyLinePlaceholder":388},[364,437,439],{"class":366,"line":438},13,[364,440,441],{},"# Imagem final enxuta (multi-stage)\n",[364,443,445],{"class":366,"line":444},14,[364,446,447],{},"FROM nginx:alpine\n",[364,449,451],{"class":366,"line":450},15,[364,452,453],{},"COPY --from=builder \u002Fapp\u002Fdist \u002Fusr\u002Fshare\u002Fnginx\u002Fhtml\n",[11,455,457],{"id":456},"testes-a-rede-de-segurança-testes","Testes: a rede de segurança {#testes}",[91,459,460],{},"Sem testes, CI é só um empacotador caro. A pirâmide de testes clássica continua\nválida e é o que mantém o pipeline rápido:",[267,462,465],{"className":463,"code":464,"language":272},[270],"            ▲\n           \u002FE2E\\          ← poucos, lentos, em ambiente real\n          \u002F──────\\\n         \u002FIntegração\\     ← médios, sobem dependências\n        \u002F────────────\\\n       \u002F   Unitários   \\   ← muitos, rápidos, isolados\n      \u002F──────────────────\\\n",[274,466,464],{"__ignoreMap":276},[468,469,471],"h3",{"id":470},"testes-unitários","Testes unitários",[91,473,474],{},"Rápidos (milissegundos), sem rede nem banco. Devem cobrir a maior parte da\nlógica de negócio. Se um teste unitário demora mais que 200ms, algo está errado\n— provavelmente ele não é unitário de verdade.",[468,476,478],{"id":477},"testes-de-integração","Testes de integração",[91,480,481],{},"Sobem dependências reais em containers (Testcontainers é a ferramenta padrão).\nValidam que seu código conversa certo com Postgres, Redis, Kafka. Demoram\nsegundos, não milissegundos.",[468,483,485],{"id":484},"testes-e2e","Testes E2E",[91,487,488,489,492],{},"Simulam um usuário real navegando (Playwright, Cypress). São lentos e frágeis,\npor isso devem ser poucos e focar nos fluxos críticos: login, checkout, pagamento.\nRodar E2E em ",[95,490,491],{},"todo"," PR é o erro mais comum de custo de CI.",[468,494,496],{"id":495},"lidando-com-testes-flaky","Lidando com testes flaky",[91,498,499],{},"Teste flaky é aquele que ora passa, ora falha, sem mudança de código. É o pior\ninimigo da confiança no pipeline. Estratégia:",[16,501,502,508,514],{},[19,503,504,507],{},[95,505,506],{},"Detectar",": marcar testes que falham e passam no retry como suspeitos.",[19,509,510,513],{},[95,511,512],{},"Quarentena",": mover para uma suite separada que não bloqueia o PR.",[19,515,516,519],{},[95,517,518],{},"Corrigir ou remover",": um teste flaky é pior que não ter teste, porque\nensina o time a ignorar o CI vermelho.",[521,522,523],"blockquote",{},[91,524,525,528],{},[95,526,527],{},"Regra",": um pipeline que pisca verde\u002Fvermelho é tratado como enfeite.\nPreferência absoluta: CI confiável, mesmo que mais lento, do que CI rápido\ne instável.",[11,530,532],{"id":531},"deploy-automático-do-commit-à-produção-deploy","Deploy automático: do commit à produção {#deploy}",[91,534,535,536,291],{},"Deploy automatizado é onde o \"CD\" brilha. Mas automático não significa\nirresponsável — significa ",[95,537,538],{},"repetível e auditável",[468,540,542],{"id":541},"ambientes","Ambientes",[148,544,545,551,557],{},[19,546,547,550],{},[95,548,549],{},"Dev",": local da pessoa desenvolvedora.",[19,552,553,556],{},[95,554,555],{},"Staging",": cópia fiel de produção (mesma versão de libs, dados anonimizados).",[19,558,559,562],{},[95,560,561],{},"Produção",": onde o usuário real está.",[468,564,566],{"id":565},"estratégias-de-deploy","Estratégias de deploy",[182,568,569,582],{},[185,570,571],{},[188,572,573,576,579],{},[191,574,575],{},"Estratégia",[191,577,578],{},"Como funciona",[191,580,581],{},"Quando usar",[201,583,584,597,610,623],{},[188,585,586,591,594],{},[206,587,588],{},[95,589,590],{},"Rolling",[206,592,593],{},"Substitui instâncias antigas por novas aos poucos",[206,595,596],{},"Default, sem downtime",[188,598,599,604,607],{},[206,600,601],{},[95,602,603],{},"Blue\u002FGreen",[206,605,606],{},"Dois ambientes idênticos; switch de tráfego num botão",[206,608,609],{},"Rollback instantâneo",[188,611,612,617,620],{},[206,613,614],{},[95,615,616],{},"Canary",[206,618,619],{},"1% → 5% → 25% → 100% do tráfego na nova versão",[206,621,622],{},"Risco alto de regressão",[188,624,625,630,633],{},[206,626,627],{},[95,628,629],{},"Feature flag",[206,631,632],{},"Código novo dorme em produção, liga por flag",[206,634,635],{},"Experimentação A\u002FB",[468,637,639],{"id":638},"pipeline-de-deploy-vs-deploy-manual","Pipeline de deploy vs. deploy manual",[91,641,642,643,646],{},"O deploy manual depende de uma pessoa rodar ",[274,644,645],{},"kubectl apply"," ou clicar num painel.\nÉ lento, propenso a erro e não escalável. O deploy via pipeline é determinístico:\nas mesmas ações sempre na mesma ordem, com logs auditáveis e gates de qualidade.",[267,648,652],{"className":649,"code":650,"language":651,"meta":276,"style":276},"language-yaml shiki shiki-themes github-light github-dark","# Trecho de deploy com gate de aprovação\n- name: Deploy to staging\n  run: .\u002Fscripts\u002Fdeploy.sh staging\n\n- name: Smoke tests\n  run: .\u002Fscripts\u002Fsmoke.sh staging-url\n\n- name: Aguardar aprovação manual (produção)\n  uses: trstringer\u002Fmanual-approval-gateway@v1\n  with:\n    approvers: tech-leads\n    minimum-approvals: 1\n\n- name: Deploy to production (canary 10%)\n  run: .\u002Fscripts\u002Fdeploy.sh production --canary 10\n","yaml",[274,653,654,660,677,687,691,702,711,715,726,736,744,754,765,769,780],{"__ignoreMap":276},[364,655,656],{"class":366,"line":367},[364,657,659],{"class":658},"sJ8bj","# Trecho de deploy com gate de aprovação\n",[364,661,662,666,670,673],{"class":366,"line":373},[364,663,665],{"class":664},"sVt8B","- ",[364,667,669],{"class":668},"s9eBZ","name",[364,671,672],{"class":664},": ",[364,674,676],{"class":675},"sZZnC","Deploy to staging\n",[364,678,679,682,684],{"class":366,"line":379},[364,680,681],{"class":668},"  run",[364,683,672],{"class":664},[364,685,686],{"class":675},".\u002Fscripts\u002Fdeploy.sh staging\n",[364,688,689],{"class":366,"line":385},[364,690,389],{"emptyLinePlaceholder":388},[364,692,693,695,697,699],{"class":366,"line":392},[364,694,665],{"class":664},[364,696,669],{"class":668},[364,698,672],{"class":664},[364,700,701],{"class":675},"Smoke tests\n",[364,703,704,706,708],{"class":366,"line":398},[364,705,681],{"class":668},[364,707,672],{"class":664},[364,709,710],{"class":675},".\u002Fscripts\u002Fsmoke.sh staging-url\n",[364,712,713],{"class":366,"line":404},[364,714,389],{"emptyLinePlaceholder":388},[364,716,717,719,721,723],{"class":366,"line":410},[364,718,665],{"class":664},[364,720,669],{"class":668},[364,722,672],{"class":664},[364,724,725],{"class":675},"Aguardar aprovação manual (produção)\n",[364,727,728,731,733],{"class":366,"line":415},[364,729,730],{"class":668},"  uses",[364,732,672],{"class":664},[364,734,735],{"class":675},"trstringer\u002Fmanual-approval-gateway@v1\n",[364,737,738,741],{"class":366,"line":421},[364,739,740],{"class":668},"  with",[364,742,743],{"class":664},":\n",[364,745,746,749,751],{"class":366,"line":427},[364,747,748],{"class":668},"    approvers",[364,750,672],{"class":664},[364,752,753],{"class":675},"tech-leads\n",[364,755,756,759,761],{"class":366,"line":433},[364,757,758],{"class":668},"    minimum-approvals",[364,760,672],{"class":664},[364,762,764],{"class":763},"sj4cs","1\n",[364,766,767],{"class":366,"line":438},[364,768,389],{"emptyLinePlaceholder":388},[364,770,771,773,775,777],{"class":366,"line":444},[364,772,665],{"class":664},[364,774,669],{"class":668},[364,776,672],{"class":664},[364,778,779],{"class":675},"Deploy to production (canary 10%)\n",[364,781,782,784,786],{"class":366,"line":450},[364,783,681],{"class":668},[364,785,672],{"class":664},[364,787,788],{"class":675},".\u002Fscripts\u002Fdeploy.sh production --canary 10\n",[11,790,792],{"id":791},"rollback-o-botão-desfazer-profissional-rollback","Rollback: o botão \"desfazer\" profissional {#rollback}",[91,794,795,796,291],{},"Todo deploy vai falhar um dia. A diferença entre um incidente de 5 minutos e\num de 5 horas é ter rollback ",[95,797,798],{},"automático e testado",[468,800,802],{"id":801},"tipos-de-rollback","Tipos de rollback",[148,804,805,811,825],{},[19,806,807,810],{},[95,808,809],{},"Rollback de versão (imagem)",": voltar para a imagem Docker anterior. Rápido,\nresolve bugs de código.",[19,812,813,816,817,820,821,824],{},[95,814,815],{},"Rollback de schema (banco)",": mais delicado. Migrações destrutivas\n(",[274,818,819],{},"DROP COLUMN",") não têm volta trivial. Por isso, ",[95,822,823],{},"migrações devem ser\nreversíveis"," e feitas em duas fases (expand → contract).",[19,826,827,830],{},[95,828,829],{},"Rollback de feature flag",": desligar a flag. O mais barato — não precisa\nnem redeployar.",[468,832,834],{"id":833},"automatizando-o-rollback","Automatizando o rollback",[91,836,837],{},"Defina métricas que disparam rollback sozinhas: taxa de erro > 1% por 2 minutos,\nlatência P99 > 500ms, taxa de 5xx acima do baseline. Ferramentas como Argo Rollouts\ne Flagger fazem isso nativamente no Kubernetes.",[267,839,841],{"className":649,"code":840,"language":651,"meta":276,"style":276},"# Argo Rollouts: análise automática que reverte se erro subir\nanalysis:\n  templates:\n    - templateName: success-rate\n  startingStep: 2   # só analisa depois de 10% de tráfego\nmetrics:\n  - name: success-rate\n    successCondition: result >= 0.99\n    failureLimit: 2   # 2 falhas consecutivas → rollback automático\n",[274,842,843,848,855,862,875,888,895,906,916],{"__ignoreMap":276},[364,844,845],{"class":366,"line":367},[364,846,847],{"class":658},"# Argo Rollouts: análise automática que reverte se erro subir\n",[364,849,850,853],{"class":366,"line":373},[364,851,852],{"class":668},"analysis",[364,854,743],{"class":664},[364,856,857,860],{"class":366,"line":379},[364,858,859],{"class":668},"  templates",[364,861,743],{"class":664},[364,863,864,867,870,872],{"class":366,"line":385},[364,865,866],{"class":664},"    - ",[364,868,869],{"class":668},"templateName",[364,871,672],{"class":664},[364,873,874],{"class":675},"success-rate\n",[364,876,877,880,882,885],{"class":366,"line":392},[364,878,879],{"class":668},"  startingStep",[364,881,672],{"class":664},[364,883,884],{"class":763},"2",[364,886,887],{"class":658},"   # só analisa depois de 10% de tráfego\n",[364,889,890,893],{"class":366,"line":398},[364,891,892],{"class":668},"metrics",[364,894,743],{"class":664},[364,896,897,900,902,904],{"class":366,"line":404},[364,898,899],{"class":664},"  - ",[364,901,669],{"class":668},[364,903,672],{"class":664},[364,905,874],{"class":675},[364,907,908,911,913],{"class":366,"line":410},[364,909,910],{"class":668},"    successCondition",[364,912,672],{"class":664},[364,914,915],{"class":675},"result >= 0.99\n",[364,917,918,921,923,925],{"class":366,"line":415},[364,919,920],{"class":668},"    failureLimit",[364,922,672],{"class":664},[364,924,884],{"class":763},[364,926,927],{"class":658},"   # 2 falhas consecutivas → rollback automático\n",[11,929,931],{"id":930},"estratégias-para-times-grandes-times-grandes","Estratégias para times grandes {#times-grandes}",[91,933,934],{},"Quando o time passa de ~10 pessoas, surgem problemas novos. Aqui vão as\nestratégias que separam pipelines que escalam de pipelines que travam.",[468,936,938],{"id":937},"_1-reusable-workflows","1. Reusable workflows",[91,940,941],{},"No GitHub Actions, você pode reutilizar workflows inteiros. Em vez de cada\nrepositório copiar 200 linhas de YAML, chame um workflow central:",[267,943,945],{"className":649,"code":944,"language":651,"meta":276,"style":276},"# .github\u002Fworkflows\u002Fdeploy.yml em qualquer repo\njobs:\n  deploy:\n    uses: org\u002Finicialize-pipeline\u002F.github\u002Fworkflows\u002Fdeploy-template.yml@v3\n    with:\n      service-name: ${{ github.repository }}\n      environment: production\n    secrets: inherit\n",[274,946,947,952,959,966,976,983,993,1003],{"__ignoreMap":276},[364,948,949],{"class":366,"line":367},[364,950,951],{"class":658},"# .github\u002Fworkflows\u002Fdeploy.yml em qualquer repo\n",[364,953,954,957],{"class":366,"line":373},[364,955,956],{"class":668},"jobs",[364,958,743],{"class":664},[364,960,961,964],{"class":366,"line":379},[364,962,963],{"class":668},"  deploy",[364,965,743],{"class":664},[364,967,968,971,973],{"class":366,"line":385},[364,969,970],{"class":668},"    uses",[364,972,672],{"class":664},[364,974,975],{"class":675},"org\u002Finicialize-pipeline\u002F.github\u002Fworkflows\u002Fdeploy-template.yml@v3\n",[364,977,978,981],{"class":366,"line":392},[364,979,980],{"class":668},"    with",[364,982,743],{"class":664},[364,984,985,988,990],{"class":366,"line":398},[364,986,987],{"class":668},"      service-name",[364,989,672],{"class":664},[364,991,992],{"class":675},"${{ github.repository }}\n",[364,994,995,998,1000],{"class":366,"line":404},[364,996,997],{"class":668},"      environment",[364,999,672],{"class":664},[364,1001,1002],{"class":675},"production\n",[364,1004,1005,1008,1010],{"class":366,"line":410},[364,1006,1007],{"class":668},"    secrets",[364,1009,672],{"class":664},[364,1011,1012],{"class":675},"inherit\n",[91,1014,1015,1016,1019,1020,1023],{},"Mudou a versão do template? Atualize ",[274,1017,1018],{},"@v3"," para ",[274,1021,1022],{},"@v4"," e todos os repositórios\nherdam a melhoria num commit.",[468,1025,1027],{"id":1026},"_2-monorepo-vs-multi-repo","2. Monorepo vs. multi-repo",[148,1029,1030,1036],{},[19,1031,1032,1035],{},[95,1033,1034],{},"Monorepo",": um repositório, pipeline precisa ser inteligente para só rodar\ntestes dos pacotes afetados (ferramentas: Nx, Turborepo, Bazel).",[19,1037,1038,1041],{},[95,1039,1040],{},"Multi-repo",": cada repo tem seu pipeline, mas compartilha templates\nreutilizáveis para não repetir configuração.",[468,1043,1045],{"id":1044},"_3-cache-agressivo","3. Cache agressivo",[148,1047,1048,1051,1058],{},[19,1049,1050],{},"Cache de build tools (npm, pip, cargo, gradle).",[19,1052,1053,1054,1057],{},"Cache de Docker (actions\u002Fcache para ",[274,1055,1056],{},"\u002Fvar\u002Flib\u002Fdocker"," ou BuildKit).",[19,1059,1060],{},"Cache de testes (Playwright armazena screenshots e traces).",[468,1062,1064],{"id":1063},"_4-self-hosted-runners-runners-sob-demanda","4. Self-hosted runners \u002F runners sob demanda",[91,1066,1067],{},"Runners do GitHub são limitados e pagos por minuto. Para times grandes,\nrunners auto-hospedados com auto-scaling (Actions Runner Controller no K8s)\nreduzem custo e fila. Para builds esporádicos pesados, use runners efêmeros\nsubidos on-demand.",[468,1069,1071],{"id":1070},"_5-gates-de-qualidade-não-de-egos","5. Gates de qualidade, não de egos",[91,1073,1074],{},"Bons gates: cobertura não pode cair, testes novos obrigatórios para novos\narquivos, SAST sem vulnerabilidades críticas. Maus gates: \"precisa de 3\napprovals de staff engineers\" — vira gargalo humano e não escala.",[11,1076,1078],{"id":1077},"exemplo-real-com-github-actions-exemplo-github","Exemplo real com GitHub Actions {#exemplo-github}",[91,1080,1081],{},"Aqui está um pipeline completo, comentado, pronto para adaptar:",[267,1083,1085],{"className":649,"code":1084,"language":651,"meta":276,"style":276},"# .github\u002Fworkflows\u002Fci-cd.yml\nname: CI\u002FCD\n\non:\n  push:\n    branches: [main]\n  pull_request:\n\n# Cancela runs anteriores do mesmo PR — economiza runners\nconcurrency:\n  group: ci-${{ github.ref }}\n  cancel-in-progress: true\n\njobs:\n  # Job 1: tudo rápido e paralelo\n  lint:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with: { node-version: 20, cache: npm }\n      - run: npm ci\n      - run: npm run lint        # ESLint, Prettier\n\n  test-unit:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: actions\u002Fsetup-node@v4\n        with: { node-version: 20, cache: npm }\n      - run: npm ci\n      - run: npm test -- --coverage   # Vitest\u002FJest\n\n  # Job 2: build só roda se lint+test passarem\n  build:\n    needs: [lint, test-unit]\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\u002Fcheckout@v4\n      - uses: docker\u002Fsetup-buildx-action@v3\n      - uses: docker\u002Fbuild-push-action@v5\n        with:\n          context: .\n          push: false\n          tags: app:${{ github.sha }}\n          cache-from: type=gha     # cache de layers no GitHub\n          cache-to: type=gha,mode=max\n      - uses: actions\u002Fupload-artifact@v4\n        with: { name: image, path: image.tar }\n\n  # Job 3: deploy só na main, nunca em PR\n  deploy:\n    if: github.ref == 'refs\u002Fheads\u002Fmain'\n    needs: build\n    environment: production\n    steps:\n      - uses: actions\u002Fdownload-artifact@v4\n        with: { name: image }\n      - run: .\u002Fscripts\u002Fdeploy.sh ${{ github.sha }}\n",[274,1086,1087,1092,1101,1105,1112,1119,1133,1140,1144,1149,1156,1166,1176,1180,1186,1191,1199,1210,1218,1232,1244,1274,1287,1302,1307,1315,1324,1331,1342,1353,1376,1387,1402,1407,1413,1421,1439,1448,1455,1466,1478,1490,1497,1508,1519,1530,1544,1555,1567,1593,1598,1604,1611,1622,1632,1642,1649,1661,1676],{"__ignoreMap":276},[364,1088,1089],{"class":366,"line":367},[364,1090,1091],{"class":658},"# .github\u002Fworkflows\u002Fci-cd.yml\n",[364,1093,1094,1096,1098],{"class":366,"line":373},[364,1095,669],{"class":668},[364,1097,672],{"class":664},[364,1099,1100],{"class":675},"CI\u002FCD\n",[364,1102,1103],{"class":366,"line":379},[364,1104,389],{"emptyLinePlaceholder":388},[364,1106,1107,1110],{"class":366,"line":385},[364,1108,1109],{"class":763},"on",[364,1111,743],{"class":664},[364,1113,1114,1117],{"class":366,"line":392},[364,1115,1116],{"class":668},"  push",[364,1118,743],{"class":664},[364,1120,1121,1124,1127,1130],{"class":366,"line":398},[364,1122,1123],{"class":668},"    branches",[364,1125,1126],{"class":664},": [",[364,1128,1129],{"class":675},"main",[364,1131,1132],{"class":664},"]\n",[364,1134,1135,1138],{"class":366,"line":404},[364,1136,1137],{"class":668},"  pull_request",[364,1139,743],{"class":664},[364,1141,1142],{"class":366,"line":410},[364,1143,389],{"emptyLinePlaceholder":388},[364,1145,1146],{"class":366,"line":415},[364,1147,1148],{"class":658},"# Cancela runs anteriores do mesmo PR — economiza runners\n",[364,1150,1151,1154],{"class":366,"line":421},[364,1152,1153],{"class":668},"concurrency",[364,1155,743],{"class":664},[364,1157,1158,1161,1163],{"class":366,"line":427},[364,1159,1160],{"class":668},"  group",[364,1162,672],{"class":664},[364,1164,1165],{"class":675},"ci-${{ github.ref }}\n",[364,1167,1168,1171,1173],{"class":366,"line":433},[364,1169,1170],{"class":668},"  cancel-in-progress",[364,1172,672],{"class":664},[364,1174,1175],{"class":763},"true\n",[364,1177,1178],{"class":366,"line":438},[364,1179,389],{"emptyLinePlaceholder":388},[364,1181,1182,1184],{"class":366,"line":444},[364,1183,956],{"class":668},[364,1185,743],{"class":664},[364,1187,1188],{"class":366,"line":450},[364,1189,1190],{"class":658},"  # Job 1: tudo rápido e paralelo\n",[364,1192,1194,1197],{"class":366,"line":1193},16,[364,1195,1196],{"class":668},"  lint",[364,1198,743],{"class":664},[364,1200,1202,1205,1207],{"class":366,"line":1201},17,[364,1203,1204],{"class":668},"    runs-on",[364,1206,672],{"class":664},[364,1208,1209],{"class":675},"ubuntu-latest\n",[364,1211,1213,1216],{"class":366,"line":1212},18,[364,1214,1215],{"class":668},"    steps",[364,1217,743],{"class":664},[364,1219,1221,1224,1227,1229],{"class":366,"line":1220},19,[364,1222,1223],{"class":664},"      - ",[364,1225,1226],{"class":668},"uses",[364,1228,672],{"class":664},[364,1230,1231],{"class":675},"actions\u002Fcheckout@v4\n",[364,1233,1235,1237,1239,1241],{"class":366,"line":1234},20,[364,1236,1223],{"class":664},[364,1238,1226],{"class":668},[364,1240,672],{"class":664},[364,1242,1243],{"class":675},"actions\u002Fsetup-node@v4\n",[364,1245,1247,1250,1253,1256,1258,1261,1263,1266,1268,1271],{"class":366,"line":1246},21,[364,1248,1249],{"class":668},"        with",[364,1251,1252],{"class":664},": { ",[364,1254,1255],{"class":668},"node-version",[364,1257,672],{"class":664},[364,1259,1260],{"class":763},"20",[364,1262,315],{"class":664},[364,1264,1265],{"class":668},"cache",[364,1267,672],{"class":664},[364,1269,1270],{"class":675},"npm",[364,1272,1273],{"class":664}," }\n",[364,1275,1277,1279,1282,1284],{"class":366,"line":1276},22,[364,1278,1223],{"class":664},[364,1280,1281],{"class":668},"run",[364,1283,672],{"class":664},[364,1285,1286],{"class":675},"npm ci\n",[364,1288,1290,1292,1294,1296,1299],{"class":366,"line":1289},23,[364,1291,1223],{"class":664},[364,1293,1281],{"class":668},[364,1295,672],{"class":664},[364,1297,1298],{"class":675},"npm run lint",[364,1300,1301],{"class":658},"        # ESLint, Prettier\n",[364,1303,1305],{"class":366,"line":1304},24,[364,1306,389],{"emptyLinePlaceholder":388},[364,1308,1310,1313],{"class":366,"line":1309},25,[364,1311,1312],{"class":668},"  test-unit",[364,1314,743],{"class":664},[364,1316,1318,1320,1322],{"class":366,"line":1317},26,[364,1319,1204],{"class":668},[364,1321,672],{"class":664},[364,1323,1209],{"class":675},[364,1325,1327,1329],{"class":366,"line":1326},27,[364,1328,1215],{"class":668},[364,1330,743],{"class":664},[364,1332,1334,1336,1338,1340],{"class":366,"line":1333},28,[364,1335,1223],{"class":664},[364,1337,1226],{"class":668},[364,1339,672],{"class":664},[364,1341,1231],{"class":675},[364,1343,1345,1347,1349,1351],{"class":366,"line":1344},29,[364,1346,1223],{"class":664},[364,1348,1226],{"class":668},[364,1350,672],{"class":664},[364,1352,1243],{"class":675},[364,1354,1356,1358,1360,1362,1364,1366,1368,1370,1372,1374],{"class":366,"line":1355},30,[364,1357,1249],{"class":668},[364,1359,1252],{"class":664},[364,1361,1255],{"class":668},[364,1363,672],{"class":664},[364,1365,1260],{"class":763},[364,1367,315],{"class":664},[364,1369,1265],{"class":668},[364,1371,672],{"class":664},[364,1373,1270],{"class":675},[364,1375,1273],{"class":664},[364,1377,1379,1381,1383,1385],{"class":366,"line":1378},31,[364,1380,1223],{"class":664},[364,1382,1281],{"class":668},[364,1384,672],{"class":664},[364,1386,1286],{"class":675},[364,1388,1390,1392,1394,1396,1399],{"class":366,"line":1389},32,[364,1391,1223],{"class":664},[364,1393,1281],{"class":668},[364,1395,672],{"class":664},[364,1397,1398],{"class":675},"npm test -- --coverage",[364,1400,1401],{"class":658},"   # Vitest\u002FJest\n",[364,1403,1405],{"class":366,"line":1404},33,[364,1406,389],{"emptyLinePlaceholder":388},[364,1408,1410],{"class":366,"line":1409},34,[364,1411,1412],{"class":658},"  # Job 2: build só roda se lint+test passarem\n",[364,1414,1416,1419],{"class":366,"line":1415},35,[364,1417,1418],{"class":668},"  build",[364,1420,743],{"class":664},[364,1422,1424,1427,1429,1432,1434,1437],{"class":366,"line":1423},36,[364,1425,1426],{"class":668},"    needs",[364,1428,1126],{"class":664},[364,1430,1431],{"class":675},"lint",[364,1433,315],{"class":664},[364,1435,1436],{"class":675},"test-unit",[364,1438,1132],{"class":664},[364,1440,1442,1444,1446],{"class":366,"line":1441},37,[364,1443,1204],{"class":668},[364,1445,672],{"class":664},[364,1447,1209],{"class":675},[364,1449,1451,1453],{"class":366,"line":1450},38,[364,1452,1215],{"class":668},[364,1454,743],{"class":664},[364,1456,1458,1460,1462,1464],{"class":366,"line":1457},39,[364,1459,1223],{"class":664},[364,1461,1226],{"class":668},[364,1463,672],{"class":664},[364,1465,1231],{"class":675},[364,1467,1469,1471,1473,1475],{"class":366,"line":1468},40,[364,1470,1223],{"class":664},[364,1472,1226],{"class":668},[364,1474,672],{"class":664},[364,1476,1477],{"class":675},"docker\u002Fsetup-buildx-action@v3\n",[364,1479,1481,1483,1485,1487],{"class":366,"line":1480},41,[364,1482,1223],{"class":664},[364,1484,1226],{"class":668},[364,1486,672],{"class":664},[364,1488,1489],{"class":675},"docker\u002Fbuild-push-action@v5\n",[364,1491,1493,1495],{"class":366,"line":1492},42,[364,1494,1249],{"class":668},[364,1496,743],{"class":664},[364,1498,1500,1503,1505],{"class":366,"line":1499},43,[364,1501,1502],{"class":668},"          context",[364,1504,672],{"class":664},[364,1506,1507],{"class":763},".\n",[364,1509,1511,1514,1516],{"class":366,"line":1510},44,[364,1512,1513],{"class":668},"          push",[364,1515,672],{"class":664},[364,1517,1518],{"class":763},"false\n",[364,1520,1522,1525,1527],{"class":366,"line":1521},45,[364,1523,1524],{"class":668},"          tags",[364,1526,672],{"class":664},[364,1528,1529],{"class":675},"app:${{ github.sha }}\n",[364,1531,1533,1536,1538,1541],{"class":366,"line":1532},46,[364,1534,1535],{"class":668},"          cache-from",[364,1537,672],{"class":664},[364,1539,1540],{"class":675},"type=gha",[364,1542,1543],{"class":658},"     # cache de layers no GitHub\n",[364,1545,1547,1550,1552],{"class":366,"line":1546},47,[364,1548,1549],{"class":668},"          cache-to",[364,1551,672],{"class":664},[364,1553,1554],{"class":675},"type=gha,mode=max\n",[364,1556,1558,1560,1562,1564],{"class":366,"line":1557},48,[364,1559,1223],{"class":664},[364,1561,1226],{"class":668},[364,1563,672],{"class":664},[364,1565,1566],{"class":675},"actions\u002Fupload-artifact@v4\n",[364,1568,1570,1572,1574,1576,1578,1581,1583,1586,1588,1591],{"class":366,"line":1569},49,[364,1571,1249],{"class":668},[364,1573,1252],{"class":664},[364,1575,669],{"class":668},[364,1577,672],{"class":664},[364,1579,1580],{"class":675},"image",[364,1582,315],{"class":664},[364,1584,1585],{"class":668},"path",[364,1587,672],{"class":664},[364,1589,1590],{"class":675},"image.tar",[364,1592,1273],{"class":664},[364,1594,1596],{"class":366,"line":1595},50,[364,1597,389],{"emptyLinePlaceholder":388},[364,1599,1601],{"class":366,"line":1600},51,[364,1602,1603],{"class":658},"  # Job 3: deploy só na main, nunca em PR\n",[364,1605,1607,1609],{"class":366,"line":1606},52,[364,1608,963],{"class":668},[364,1610,743],{"class":664},[364,1612,1614,1617,1619],{"class":366,"line":1613},53,[364,1615,1616],{"class":668},"    if",[364,1618,672],{"class":664},[364,1620,1621],{"class":675},"github.ref == 'refs\u002Fheads\u002Fmain'\n",[364,1623,1625,1627,1629],{"class":366,"line":1624},54,[364,1626,1426],{"class":668},[364,1628,672],{"class":664},[364,1630,1631],{"class":675},"build\n",[364,1633,1635,1638,1640],{"class":366,"line":1634},55,[364,1636,1637],{"class":668},"    environment",[364,1639,672],{"class":664},[364,1641,1002],{"class":675},[364,1643,1645,1647],{"class":366,"line":1644},56,[364,1646,1215],{"class":668},[364,1648,743],{"class":664},[364,1650,1652,1654,1656,1658],{"class":366,"line":1651},57,[364,1653,1223],{"class":664},[364,1655,1226],{"class":668},[364,1657,672],{"class":664},[364,1659,1660],{"class":675},"actions\u002Fdownload-artifact@v4\n",[364,1662,1664,1666,1668,1670,1672,1674],{"class":366,"line":1663},58,[364,1665,1249],{"class":668},[364,1667,1252],{"class":664},[364,1669,669],{"class":668},[364,1671,672],{"class":664},[364,1673,1580],{"class":675},[364,1675,1273],{"class":664},[364,1677,1679,1681,1683,1685],{"class":366,"line":1678},59,[364,1680,1223],{"class":664},[364,1682,1281],{"class":668},[364,1684,672],{"class":664},[364,1686,1687],{"class":675},".\u002Fscripts\u002Fdeploy.sh ${{ github.sha }}\n",[91,1689,1690],{},"Pontos de atenção nesse exemplo:",[148,1692,1693,1698,1704,1710,1716],{},[19,1694,1695,1697],{},[274,1696,1153],{}," cancela runs velhas do mesmo PR → economia de runner.",[19,1699,1700,1703],{},[274,1701,1702],{},"needs"," define a ordem e falha rápida: se lint quebra, build nem roda.",[19,1705,1706,1709],{},[274,1707,1708],{},"cache-from: type=gha"," reaproveita layers Docker entre execuções.",[19,1711,1712,1715],{},[274,1713,1714],{},"environment: production"," cria um gate de aprovação configurável no GitHub.",[19,1717,1718,1719,1721],{},"Deploy só na ",[274,1720,1129],{}," — PRs não tocam produção.",[11,1723,1725],{"id":1724},"erros-comuns-erros","Erros comuns {#erros}",[16,1727,1728,1737,1747,1757,1763,1769,1775,1781],{},[19,1729,1730,1733,1734,1736],{},[95,1731,1732],{},"Rodar tudo em série",": cada job esperando o anterior terminar. Solução:\nparalelize jobs independentes com ",[274,1735,1702],{}," apenas onde há dependência real.",[19,1738,1739,1742,1743,1746],{},[95,1740,1741],{},"Ignorar cache",": instalar dependências do zero a cada run. Cada ",[274,1744,1745],{},"npm ci","\nsem cache custa 1-3 minutos que se somam em milhares de runs por mês.",[19,1748,1749,1752,1753,1756],{},[95,1750,1751],{},"Segredos no código",": colocar chaves AWS direto no YAML. Use secrets do\nGitHub\u002FOIDC e ",[95,1754,1755],{},"nunca"," logue tokens.",[19,1758,1759,1762],{},[95,1760,1761],{},"Testes E2E em todo PR",": lentidão e custo explosivo. Separe E2E para\nagendamento noturno ou apenas na main.",[19,1764,1765,1768],{},[95,1766,1767],{},"Sem rollback testado",": \"vamos voltar manual se quebrar\". No pânico do\nincidente, ninguém lembra os passos. Teste o rollback em staging periodicamente.",[19,1770,1771,1774],{},[95,1772,1773],{},"Deploy direto na main sem gate",": em times grandes, um push errado derruba\nprodução. Use protection rules + revisão + checks obrigatórios.",[19,1776,1777,1780],{},[95,1778,1779],{},"Migrações de banco no mesmo pipeline do app",": quebra se a nova versão do\napp for rejeitada mas o schema já mudou. Separe migrações em pipeline próprio\ncom deploy antes do app (padrão expand\u002Fcontract).",[19,1782,1783,1786],{},[95,1784,1785],{},"Achar que CI\u002FCD é ferramenta, não cultura",": comprar Jenkins\u002FGitHub Actions\nnão entrega valor se o time não segue a disciplina de \"main sempre verde\".",[11,1788,1790],{"id":1789},"checklist-final-checklist","Checklist final {#checklist}",[148,1792,1795,1804,1810,1816,1822,1828,1834,1840,1846,1852,1858,1864],{"className":1793},[1794],"contains-task-list",[19,1796,1799,1803],{"className":1797},[1798],"task-list-item",[1800,1801],"input",{"disabled":388,"type":1802},"checkbox"," Pipeline roda em menos de 10 minutos para 90% dos PRs",[19,1805,1807,1809],{"className":1806},[1798],[1800,1808],{"disabled":388,"type":1802}," Dependências cacheadas (build tools + Docker layers)",[19,1811,1813,1815],{"className":1812},[1798],[1800,1814],{"disabled":388,"type":1802}," Testes flaky em quarentena, não no caminho crítico",[19,1817,1819,1821],{"className":1818},[1798],[1800,1820],{"disabled":388,"type":1802}," Lint, unit, integração, security scan em paralelo",[19,1823,1825,1827],{"className":1824},[1798],[1800,1826],{"disabled":388,"type":1802}," Deploy com estratégia (rolling\u002Fblue-green\u002Fcanary) e gate",[19,1829,1831,1833],{"className":1830},[1798],[1800,1832],{"disabled":388,"type":1802}," Rollback automático disparado por métricas (erro rate, latência)",[19,1835,1837,1839],{"className":1836},[1798],[1800,1838],{"disabled":388,"type":1802}," Migrações de banco separadas e reversíveis (expand\u002Fcontract)",[19,1841,1843,1845],{"className":1842},[1798],[1800,1844],{"disabled":388,"type":1802}," Templates reutilizáveis para novos repositórios",[19,1847,1849,1851],{"className":1848},[1798],[1800,1850],{"disabled":388,"type":1802}," Runners com auto-scaling para evitar fila em horário pico",[19,1853,1855,1857],{"className":1854},[1798],[1800,1856],{"disabled":388,"type":1802}," Custo de CI monitorado e com alertas (orçamento mensal)",[19,1859,1861,1863],{"className":1860},[1798],[1800,1862],{"disabled":388,"type":1802}," main sempre deployable — protection rules + checks obrigatórios",[19,1865,1867,1869],{"className":1866},[1798],[1800,1868],{"disabled":388,"type":1802}," Runners e secrets auditados periodicamente",[1871,1872],"hr",{},[91,1874,1875,1878,1879,291],{},[95,1876,1877],{},"Quer um pipeline que escala com seu time?"," A Inicialize Tec implementa CI\u002FCD\ndo commit ao deploy, com rollback automático, observabilidade e templates\nreutilizáveis para múltiplos repositórios. ",[22,1880,1882],{"href":1881},"\u002F#top","Conversamos sobre seu caso",[1884,1885,1886],"style",{},"html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":276,"searchDepth":379,"depth":379,"links":1888},[1889,1890,1891,1892,1893,1894,1900,1905,1909,1916,1917,1918],{"id":13,"depth":373,"text":14},{"id":88,"depth":373,"text":89},{"id":142,"depth":373,"text":143},{"id":261,"depth":373,"text":262},{"id":294,"depth":373,"text":295},{"id":456,"depth":373,"text":457,"children":1895},[1896,1897,1898,1899],{"id":470,"depth":379,"text":471},{"id":477,"depth":379,"text":478},{"id":484,"depth":379,"text":485},{"id":495,"depth":379,"text":496},{"id":531,"depth":373,"text":532,"children":1901},[1902,1903,1904],{"id":541,"depth":379,"text":542},{"id":565,"depth":379,"text":566},{"id":638,"depth":379,"text":639},{"id":791,"depth":373,"text":792,"children":1906},[1907,1908],{"id":801,"depth":379,"text":802},{"id":833,"depth":379,"text":834},{"id":930,"depth":373,"text":931,"children":1910},[1911,1912,1913,1914,1915],{"id":937,"depth":379,"text":938},{"id":1026,"depth":379,"text":1027},{"id":1044,"depth":379,"text":1045},{"id":1063,"depth":379,"text":1064},{"id":1070,"depth":379,"text":1071},{"id":1077,"depth":373,"text":1078},{"id":1724,"depth":373,"text":1725},{"id":1789,"depth":373,"text":1790},"automacao","2026-08-26","Como montar um pipeline de CI\u002FCD que escala com seu time: build, test, deploy automático, rollback e estratégias para times grandes.","md",[1924,138,1925,1926,1927,1928],"CI\u002FCD","GitHub Actions","deploy automatizado","DevOps","integração contínua",{},"\u002Fautomacao\u002Fpipeline-ci-cd-escalavel",{"title":5,"description":1921},"pipeline-ci-cd-escalavel","automacao\u002Fpipeline-ci-cd-escalavel","jI-EIrG_5zCP1q40kPTdCt8GAm-ABBMGbDKkmZnGLEU",1787796309109]