Do commit ao deploy: a anatomia de um pipeline DevSecOps moderno

As etapas de um pipeline DevSecOps de ponta a ponta — do planejar ao operar — e o que cada uma entrega para um software publicado com confiança.

Um pipeline DevSecOps não é uma ferramenta — é um fluxo contínuo que conecta o trabalho desde a ideia até a operação em produção. Quando bem desenhado, cada etapa alimenta a próxima e a telemetria do fim volta a alimentar o começo. A diferença entre um pipeline que "funciona" e um pipeline que sustenta um time de verdade está nas costuras: como o build passa o artefato para a segurança, como a segurança decide o que barra, como o release controla o blast radius e como a operação devolve sinal para o planejamento. Vamos percorrer esse caminho etapa por etapa, com o que cada uma entrega e como implementá-la na prática com GitLab CI/CD.

1. Planejar

Tudo começa no backlog: épicos, histórias e requisitos conectados ao código desde o primeiro card. O trabalho já nasce rastreável — dá para seguir uma decisão de produto até a linha de código que a implementou.

Na prática, isso significa que cada merge request referencia uma issue, e cada issue carrega o contexto que justifica a mudança. Quando uma vulnerabilidade aparece em produção seis meses depois, você consegue reconstruir a cadeia: qual decisão de produto, qual MR, qual commit, qual deploy. Essa rastreabilidade não é burocracia — é o que permite auditoria sem caça às bruxas e postmortems sem achismo.

2. Codificar

Commits, branches e merge requests fluem para o repositório com revisão e contexto. Cada mudança entra no fluxo desde o início, com histórico claro de quem fez o quê e por quê.

Dois controles fazem essa etapa render: branches protegidas e revisão obrigatória. Trabalhar em branches curtas reduz conflitos de merge e mantém o feedback do pipeline próximo de quem escreveu o código. Configure regras de aprovação para que ninguém faça merge do próprio MR sem revisão, e use code owners para rotear automaticamente as mudanças sensíveis para quem entende daquele domínio.

# Pipeline diferente por contexto: MR roda o ciclo completo,
# push direto na branch roda só o essencial
workflow:
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
    - when: never

3. Build

Os runners de CI acordam sob demanda e transformam código em artefato versionado em minutos — com cache e paralelismo para que ninguém fique esperando na fila.

O artefato gerado aqui é o que vai ser escaneado, testado e implantado nas etapas seguintes. Por isso a regra de ouro: construa uma vez, promova o mesmo artefato. Recompilar a cada estágio abre espaço para divergência entre o que foi testado e o que sobe em produção. Versione o artefato de forma imutável (uma tag derivada do commit SHA, por exemplo) e use cache com chave baseada nos arquivos de dependência para encurtar o tempo de build sem comprometer a reprodutibilidade.

build:
  stage: build
  image: docker:27
  services:
    - docker:27-dind
  script:
    - docker build -t "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA" .
    - docker push "$CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA"
  cache:
    key:
      files:
        - package-lock.json
    paths:
      - node_modules/

Defina expire_in nos artefatos para não estourar o storage do projeto, e revise o consumo periodicamente — runners ociosos e artefatos eternos são dois dos maiores desperdícios silenciosos em CI.

4. Segurança

Cinco checkpoints contínuos — SAST, segredos, dependências, containers e IaC — rodam antes do merge. Vulnerabilidades são tratadas no contexto da mudança, não semanas depois.

Esse é o coração do "Sec" no DevSecOps. Cada scanner cobre uma superfície de ataque diferente:

Scanner O que cobre
SAST Padrões inseguros no código-fonte
Secret Detection Tokens, senhas e chaves vazados no repositório
Dependency Scanning Vulnerabilidades conhecidas em dependências
Container Scanning Imagens base e camadas antes do deploy
IaC Scanning Erros de configuração em Terraform e manifests Kubernetes

O GitLab traz esses scanners como templates prontos. A chave para não travar o time é a política de bloqueio: comece falhando o merge apenas em achados de severidade alta e crítica, e deixe o resto como aviso visível no MR.

include:
  - template: Jobs/SAST.gitlab-ci.yml
  - template: Jobs/Secret-Detection.gitlab-ci.yml
  - template: Jobs/Dependency-Scanning.gitlab-ci.yml
  - template: Jobs/Container-Scanning.gitlab-ci.yml

Para regras de bloqueio finas — por exemplo, barrar merge só quando houver vulnerabilidade crítica — use as Scan Result Policies do GitLab, configuradas em Secure > Policies. A referência completa de sintaxe e templates está na documentação oficial de segurança do GitLab.

5. Testes

Portões de validação automatizados (unidade, integração, performance e API) decidem objetivamente se a mudança avança. Nada passa sem sinal verde.

A estratégia que escala é a pirâmide de testes: muitos testes unitários rápidos em cada commit, testes de integração por MR e suítes end-to-end mais caras em execuções agendadas (schedules). Rodar tudo a cada push parece seguro, mas mata o tempo de feedback — e um pipeline lento é um pipeline que o time aprende a contornar.

unit:
  stage: test
  script:
    - make test-unit
  rules:
    - if: '$CI_PIPELINE_SOURCE == "merge_request_event"'

e2e:
  stage: test
  script:
    - make test-e2e
  rules:
    - if: '$CI_PIPELINE_SOURCE == "schedule"'

Trate flaky tests como bug de prioridade alta. Um teste que falha de forma intermitente envenena a confiança no sinal verde — e quando o time para de confiar no pipeline, todos os outros controles perdem força.

6. Release

Aprovações e entrega progressiva controlam como a mudança chega à produção: de 10% a 100% do tráfego, com rollback pronto a qualquer momento.

Aqui separamos dois conceitos que costumam ser confundidos: deploy é colocar o código no ambiente; release é expor o código aos usuários. Desacoplar os dois — com feature flags e entrega progressiva — é o que permite subir código em produção sem ativá-lo, e ativá-lo só quando a telemetria confirmar que está saudável.

As estratégias mais comuns:

  • Canary — uma fatia pequena do tráfego (digamos 10%) recebe a nova versão; se as métricas seguem boas, você amplia gradualmente.
  • Blue-green — dois ambientes idênticos; você direciona o tráfego do antigo para o novo de uma vez, com rollback instantâneo apenas reapontando o roteamento.
  • Rolling — substituição incremental das instâncias, padrão nativo do Kubernetes.
deploy_prod:
  stage: deploy
  script:
    - ./deploy.sh "$CI_COMMIT_SHORT_SHA"
  environment:
    name: production
  rules:
    - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH'
      when: manual   # gate humano antes de produção

Use ambientes protegidos (Settings > CI/CD > Protected environments) para impor aprovadores e gerar trilha de auditoria de quem promoveu o quê, quando.

7. Deploy

Pods e containers entram em formação na infraestrutura declarativa — em Kubernetes ou em qualquer nuvem — de forma reproduzível e auditável.

O princípio que sustenta essa etapa é infraestrutura como código: o estado desejado vive no repositório, não na cabeça de alguém nem em ajustes manuais no console. Isso elimina o clássico "funciona na minha máquina" no nível de infra e torna cada ambiente recriável a partir do zero.

Trade-offs que valem decidir conscientemente:

Abordagem Ganho Custo
Push (pipeline empurra para o cluster) Simples de começar; tudo num lugar Pipeline precisa de credencial de cluster
Pull / GitOps (cluster reconcilia o repo) Estado auditável e autocorretivo Mais ferramentas e curva de aprendizado

Em qualquer dos modelos, mantenha os manifests versionados e evite kubectl apply manual em produção. A diferença entre um deploy reproduzível e um deploy heroico é justamente não depender de ninguém digitar o comando certo na pressa.

8. Monitorar e operar

Métricas, logs, traces e alertas em tempo real fecham o ciclo. E é aqui que está o segredo: a telemetria volta ao início do pipeline. Os dados de produção informam o próximo planejamento, e o ciclo recomeça mais inteligente.

Operação madura se mede por números, não por sensação. Quatro métricas DORA dão o pulso do pipeline inteiro:

  • Deployment frequency — com que frequência você entrega em produção.
  • Lead time for changes — quanto tempo do commit ao deploy.
  • Change failure rate — que fração das mudanças causa incidente.
  • Time to restore service — quanto tempo para recuperar de uma falha.

Os três pilares de observabilidade (métricas, logs e traces) só rendem quando estão correlacionados: um alerta de métrica deve levar ao trace da requisição, que deve levar ao log da exceção. Defina SLIs e SLAs para os fluxos críticos e automatize alertas para regressões — inclusive de performance dos próprios jobs do pipeline, monitorando duração e taxa de sucesso ao longo do tempo.

Checklist de maturidade

Use esta lista para avaliar onde seu pipeline está hoje:

  1. Build único e imutável — o mesmo artefato é promovido de ponta a ponta, sem recompilar.
  2. Segurança no MR — os cinco scanners rodam antes do merge, com bloqueio só no que é crítico.
  3. Feedback rápido — testes unitários em cada commit; suítes pesadas em schedules.
  4. Deploy desacoplado de release — feature flags e entrega progressiva no lugar.
  5. Rollback ensaiado — você já testou voltar atrás, não só avançar.
  6. Infra declarativa — nada de ajuste manual em produção.
  7. Telemetria realimentando o planejamento — DORA e SLOs guiam o próximo ciclo.

O ciclo não termina — ele evolui

A maturidade não está em ter todas as etapas, mas em conectá-las. Um pipeline em que segurança, testes e observabilidade conversam é o que separa entregar software de entregar software com confiança.

Etapa Entrega
Planejar Trabalho rastreável
Codificar Histórico e revisão
Build Artefato versionado
Segurança Vulnerabilidades barradas cedo
Testes Sinal verde objetivo
Release Entrega progressiva
Deploy Infraestrutura reproduzível
Operar Feedback contínuo

Vale lembrar: não tente implantar as oito etapas de uma vez. Escolha o gargalo que mais dói hoje — quase sempre é tempo de feedback ou segurança barrando tarde demais — e amadureça uma costura por vez. Um pipeline evolui melhor por iteração do que por big bang.

Quer desenhar (ou afinar) o seu pipeline de ponta a ponta? Vamos conversar.