{"id":155,"date":"2019-12-05T16:19:00","date_gmt":"2019-12-05T19:19:00","guid":{"rendered":"https:\/\/www.linuxpro.com.br\/2019\/12\/devops-ci-cd\/"},"modified":"2026-10-05T13:45:45","modified_gmt":"2026-10-05T16:45:45","slug":"devops-ci-cd","status":"publish","type":"post","link":"https:\/\/www.linuxpro.com.br\/en\/2019\/12\/devops-ci-cd\/","title":{"rendered":"DevOps: what is CI\/CD?"},"content":{"rendered":"<p><img loading=\"lazy\" decoding=\"async\" alt=\"Mascote do LinuxPro colocando uma caixa de container Docker na esteira de CI\/CD, entre a esta\u00e7\u00e3o do Git, o portal de testes e o rack Kubernetes, com o cachorro caramelo ao lado\" src=\"\/wp-content\/uploads\/2026\/10\/devops-cicd-v4.webp\" width=\"1486\" height=\"856\" \/><\/p>\n<div style=\"background:#fff8e1;border-left:4px solid #8b1a1a;padding:.8em 1em;margin:1em 0\"><strong>Nota (2026):<\/strong> Texto original de dezembro de 2019 \u2014 gloss\u00e1rio de CI\/CD ainda no vocabul\u00e1rio Jenkins\/Red Hat, com a nota \u201cvai ser melhorado em breve\u201d. Sete anos depois o YAML no Git virou o padr\u00e3o (GitHub Actions, GitLab CI, Forgejo\/Gitea Actions), o CD em Kubernetes virou GitOps (Argo CD \/ Flux) e o pr\u00f3prio pipeline passou a ser alvo de ataque \u00e0 cadeia de suprimentos. O conceito n\u00e3o mudou; a ferramenta e a amea\u00e7a, sim. <em>Revisado em 05\/10\/2026 com vers\u00f5es atuais e um diagrama do fluxo.<\/em><\/div>\n<p>CI\/CD n\u00e3o \u00e9 produto. \u00c9 o h\u00e1bito de <strong>integrar, testar e soltar software em ciclo curto<\/strong>, com o m\u00e1ximo de passos autom\u00e1ticos. O \u201cdia do merge\u201d de 2019 continua sendo o antipadr\u00e3o. O que mudou \u00e9 onde o YAML mora, quem roda o job e o que acontece <em>depois<\/em> que o pipeline fica verde.<\/p>\n<p><!-- more --><\/p>\n<h2>CI, entrega e implanta\u00e7\u00e3o \u2014 os tr\u00eas CDs<\/h2>\n<p><strong>CI (integra\u00e7\u00e3o cont\u00ednua):<\/strong> cada push ou merge request vira build e teste autom\u00e1ticos sobre o tronco compartilhado. O conflito aparece hoje, n\u00e3o na sexta-feira da release.<\/p>\n<p><strong>Entrega cont\u00ednua:<\/strong> o artefato aprovado (bin\u00e1rio, imagem OCI, pacote) vai sozinho para um registro e fica pronto para produ\u00e7\u00e3o. A subida ainda depende de um humano no bot\u00e3o \u2014 ou de um crit\u00e9rio: tag, aprova\u00e7\u00e3o, janela de mudan\u00e7a.<\/p>\n<p><strong>Implanta\u00e7\u00e3o cont\u00ednua:<\/strong> o mesmo artefato sobe sozinho para produ\u00e7\u00e3o se os testes passaram. O feedback do usu\u00e1rio chega em minutos. Exige testes em que voc\u00ea realmente confia, n\u00e3o um job verde oco.<\/p>\n<p>N\u00e3o vale brigar pelo acr\u00f4nimo. Vale desenhar o pipeline: o que \u00e9 autom\u00e1tico, o que \u00e9 porta e como se faz o rollback.<\/p>\n<figure><img loading=\"lazy\" decoding=\"async\" src=\"\/wp-content\/uploads\/2026\/10\/devops-ci-cd-pipeline-gitops.webp\" alt=\"Diagrama do pipeline: desenvolvedor faz push, o runner de CI roda lint, testes, build e assinatura, envia a imagem ao registry e atualiza o reposit\u00f3rio GitOps; Argo CD ou Flux sincronizam o Kubernetes, e a observabilidade fecha o ciclo de feedback\" width=\"1200\" height=\"620\" \/><figcaption>O CI produz e assina o artefato; o CD leva o estado desejado do Git ao cluster; m\u00e9tricas e alertas devolvem o feedback.<\/figcaption><\/figure>\n<h2>O pipeline em 2026: YAML no Git<\/h2>\n<p>Jenkins com plugins ainda roda muito legado. O ponto de partida no Linux hoje \u00e9 um arquivo no reposit\u00f3rio, um runner em container e o artefato em um registry.<\/p>\n<p><strong>GitHub Actions<\/strong> \u2014 o padr\u00e3o de quem j\u00e1 est\u00e1 no GitHub. Fixe cada action pelo <em>SHA do commit<\/em>, n\u00e3o por tag flutuante: em mar\u00e7o de 2025 as tags da action <code>tj-actions\/changed-files<\/code> foram reapontadas para um commit malicioso que despejava secrets nos logs (<a href=\"https:\/\/www.cve.org\/CVERecord?id=CVE-2025-30066\">CVE-2025-30066<\/a>). Quem usava <code>@v45<\/code> rodou o c\u00f3digo do atacante; quem tinha fixado o SHA, n\u00e3o.<\/p>\n<pre><code class=\"language-yaml\"># .github\/workflows\/ci.yml\nname: ci\non:\n  pull_request:\n  push:\n    branches: [main]\npermissions:\n  contents: read\njobs:\n  test:\n    runs-on: ubuntu-latest\n    steps:\n      - uses: actions\/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1\n      - run: make test\n<\/code><\/pre>\n<p>O bloco <code>permissions<\/code> reduz o token do job ao m\u00ednimo necess\u00e1rio \u2014 sem ele, o padr\u00e3o pode ser mais amplo do que o teste precisa.<\/p>\n<p><strong>GitLab CI<\/strong> \u2014 o que o post irm\u00e3o de 2019 j\u00e1 usava para Terraform. Um <code>.gitlab-ci.yml<\/code> e runners pr\u00f3prios, se voc\u00ea quiser soberania:<\/p>\n<pre><code class=\"language-yaml\"># .gitlab-ci.yml\nstages: [test, image]\n\ntest:\n  stage: test\n  image: golang:1.27\n  script:\n    - go test .\/...\n\nimage:\n  stage: image\n  image: docker:29\n  services: [docker:29-dind]\n  script:\n    - echo \"$CI_REGISTRY_PASSWORD\" | docker login -u \"$CI_REGISTRY_USER\" --password-stdin \"$CI_REGISTRY\"\n    - docker build -t \"$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA\" .\n    - docker push \"$CI_REGISTRY_IMAGE:$CI_COMMIT_SHA\"\n  rules:\n    - if: $CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH\n<\/code><\/pre>\n<p>As vari\u00e1veis <code>CI_REGISTRY*<\/code> s\u00e3o preenchidas pelo pr\u00f3prio GitLab para o registry do projeto: nenhuma senha fica escrita no YAML.<\/p>\n<p><strong>Forgejo Actions \/ Gitea Actions<\/strong> \u2014 sintaxe compat\u00edvel em boa parte com o GitHub Actions, rodando self-hosted, sem mandar o c\u00f3digo para a nuvem alheia. O passo a passo com runner est\u00e1 no post sobre o <a href=\"\/2026\/09\/gitea-git-self-hosted-runner-tea\/\">Gitea com Actions e runner<\/a>. O Woodpecker \u00e9 a outra op\u00e7\u00e3o leve. No homelab Linux, isso compete com o GitLab CE.<\/p>\n<p>O <a href=\"\/2017\/08\/curso-de-docker-gratis\/\">curso de Docker<\/a> continua sendo pr\u00e9-requisito: o job moderno <em>\u00e9<\/em> um container. Infraestrutura como c\u00f3digo segue o mesmo esp\u00edrito: <a href=\"\/2026\/09\/automatizando-servidores-linux-com-ansible\/\">Ansible<\/a> e o pipeline de <a href=\"\/2019\/12\/terraform-pipelines-in-gitlab\/\">Terraform no GitLab<\/a>.<\/p>\n<h2>CD virou GitOps<\/h2>\n<p>Implantar no Kubernetes em 2026 raramente \u00e9 <code>kubectl apply<\/code> dentro do job de CI. O CI constr\u00f3i a imagem, assina, envia ao registry e <em>atualiza o Git<\/em> (tag ou digest). O cluster puxa o estado desejado:<\/p>\n<ul>\n<li><strong><a href=\"https:\/\/argo-cd.readthedocs.io\/\">Argo CD<\/a><\/strong> \u2014 aplica\u00e7\u00f5es declaradas no Git, detec\u00e7\u00e3o de drift e sincroniza\u00e7\u00e3o. A linha 3.5 (2026) trouxe mTLS no repo-server e uma verifica\u00e7\u00e3o opcional, ainda em alpha, da integridade das fontes no hydrator.<\/li>\n<li><strong><a href=\"https:\/\/fluxcd.io\/\">Flux<\/a><\/strong> \u2014 o outro projeto graduado da CNCF para GitOps, com controllers dentro do cluster.<\/li>\n<\/ul>\n<p>O Git passa a ser a fonte da verdade. O runner deixa de ter credencial de produ\u00e7\u00e3o eterna: OIDC para a nuvem, tokens de vida curta e admission no cluster verificando a assinatura (Cosign) antes do pod subir. Quem ainda faz <code>docker compose up<\/code> num VPS via SSH (como no <a href=\"\/2026\/09\/vaultwarden-bitwarden-self-hosted\/\">Vaultwarden<\/a>) est\u00e1 no degrau da entrega cont\u00ednua \u2014 v\u00e1lido, s\u00f3 n\u00e3o \u00e9 GitOps. Para o contexto de onde vieram as pe\u00e7as, veja <a href=\"\/2026\/09\/a-historia-do-docker\/\">a hist\u00f3ria do Docker<\/a> e <a href=\"\/2026\/09\/a-historia-do-kubernetes\/\">a do Kubernetes<\/a>.<\/p>\n<h2>O pipeline como alvo<\/h2>\n<p>Em 2019 o medo era o merge quebrado. Em 2026 o medo \u00e9 o job que <em>passa<\/em> e publica malware: action comprometida, pacote npm sequestrado, secret vazando no log.<\/p>\n<ul>\n<li>Fixe actions e imagens por SHA ou digest, nunca por <code>@v3<\/code> solto.<\/li>\n<li>Secrets no cofre (GitHub\/GitLab, Vault, SOPS) \u2014 nunca no YAML.<\/li>\n<li>Token do job com o m\u00ednimo de permiss\u00f5es (<code>permissions:<\/code> no Actions).<\/li>\n<li>SBOM e assinatura com <strong><a href=\"https:\/\/www.sigstore.dev\/\">Cosign<\/a><\/strong> (Sigstore, keyless via OIDC) na imagem.<\/li>\n<li>Proveni\u00eancia <strong><a href=\"https:\/\/slsa.dev\/\">SLSA<\/a><\/strong> Build L2\/L3 quando quem gera \u00e9 a plataforma de build, n\u00e3o um script do reposit\u00f3rio.<\/li>\n<li>PR vindo de fork: n\u00e3o rode o workflow do branch do atacante com secrets da organiza\u00e7\u00e3o (<code>pull_request_target<\/code> mal usado).<\/li>\n<\/ul>\n<p>Depois do deploy, o <a href=\"\/2026\/09\/monitorando-servidores-linux-com-prometheus\/\">Prometheus<\/a> diz se o verde mentiu.<\/p>\n<h2>Por onde come\u00e7ar de verdade<\/h2>\n<ol>\n<li>Tronco compartilhado, PRs pequenos, CI no PR (lint + teste). Sem isso, o resto \u00e9 teatro.<\/li>\n<li>Imagem OCI versionada pelo SHA do commit, em registry pr\u00f3prio ou no GHCR\/GitLab.<\/li>\n<li>Staging autom\u00e1tico; produ\u00e7\u00e3o com porta (tag ou aprova\u00e7\u00e3o) at\u00e9 os testes merecerem implanta\u00e7\u00e3o cont\u00ednua.<\/li>\n<li>S\u00f3 ent\u00e3o GitOps, assinatura e SLSA.<\/li>\n<\/ol>\n<p>Muita empresa para no passo 2 e chama isso de DevOps. N\u00e3o \u00e9 pecado; \u00e9 honesto. Pular para o Argo CD sem testes \u00e9 pintar o avi\u00e3o.<\/p>\n<p>Se o objetivo \u00e9 formalizar o conhecimento, o post sobre a <a href=\"\/2026\/09\/certificacao-lpi-devops\/\">certifica\u00e7\u00e3o LPI DevOps Tools Engineer<\/a> cobre CI\/CD, containers e automa\u00e7\u00e3o.<\/p>\n<h2>Uma volta visual<\/h2>\n<p>O epis\u00f3dio do <em>Dicion\u00e1rio do Programador<\/em>, do canal C\u00f3digo Fonte TV, resume pipeline e CI\/CD em poucos minutos:<\/p>\n<div style=\"position:relative;padding-bottom:56.25%;height:0;overflow:hidden;margin:1.5em 0\">\n<iframe src=\"https:\/\/www.youtube.com\/embed\/AZtTd3pFVTY\" title=\"Pipeline (CD\/CI) \/\/ Dicion\u00e1rio do Programador\" allow=\"accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share\" allowfullscreen style=\"position:absolute;top:0;left:0;width:100%;height:100%;border:0\"><\/iframe>\n<\/div>\n<h2>Refer\u00eancias<\/h2>\n<ul>\n<li><a href=\"\/2019\/12\/terraform-pipelines-in-gitlab\/\">Pipelines Terraform no GitLab<\/a> \u2014 o CD de infraestrutura no mesmo ano deste post<\/li>\n<li><a href=\"\/2026\/09\/gitea-git-self-hosted-runner-tea\/\">Gitea: Git self-hosted com Actions, runner e tea CLI<\/a><\/li>\n<li><a href=\"\/2026\/09\/a-historia-do-gitlab\/\">A hist\u00f3ria do GitLab<\/a><\/li>\n<li><a href=\"\/2017\/08\/curso-de-docker-gratis\/\">Curso de Docker gr\u00e1tis<\/a><\/li>\n<li><a href=\"\/2026\/09\/automatizando-servidores-linux-com-ansible\/\">Automatizando servidores Linux com Ansible<\/a><\/li>\n<li><a href=\"\/2026\/09\/monitorando-servidores-linux-com-prometheus\/\">Prometheus e Node Exporter<\/a><\/li>\n<li><a href=\"https:\/\/docs.gitlab.com\/ci\/\">GitLab CI\/CD docs<\/a> \u00b7 <a href=\"https:\/\/docs.github.com\/en\/actions\">GitHub Actions docs<\/a> \u00b7 <a href=\"https:\/\/forgejo.org\/docs\/latest\/user\/actions\/overview\/\">Forgejo Actions<\/a><\/li>\n<li><a href=\"https:\/\/slsa.dev\/\">SLSA<\/a> \u00b7 <a href=\"https:\/\/www.sigstore.dev\/\">Sigstore<\/a> \u00b7 <a href=\"https:\/\/argo-cd.readthedocs.io\/\">Argo CD<\/a> \u00b7 <a href=\"https:\/\/fluxcd.io\/\">Flux<\/a><\/li>\n<\/ul>\n<p>CI\/CD continua sendo o mesmo pipeline de 2019: integrar cedo, testar sempre, soltar em peda\u00e7os pequenos. O YAML foi para o Git, o cluster passou a puxar o estado, e o job verde agora precisa provar de onde veio o bin\u00e1rio. O resto \u00e9 ferramenta.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>CI\/CD is not a product. It's the habit of integrating, testing, and releasing software in short cycles, with as many automated steps as possible. The \u201cmerge day\u201d of 2019 is still the antipattern. What has changed is where the YAML lives, \u2026 <a title=\"DevOps: what is CI\/CD?\" class=\"read-more\" href=\"https:\/\/www.linuxpro.com.br\/en\/2019\/12\/devops-ci-cd\/\" aria-label=\"Read more about DevOps: o que \u00e9 CI\/CD?\">Read more<\/a><\/p>","protected":false},"author":0,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[108,103,46],"tags":[105,106,9,47,156,48,49,517,104,518,225,519],"class_list":["post-155","post","type-post","status-publish","format-standard","hentry","category-ci-cd","category-cloud","category-devops","tag-ci-cd","tag-cloud","tag-dev","tag-devops","tag-docker","tag-git","tag-github","tag-github-actions","tag-gitlab","tag-gitops","tag-kubernetes","tag-supply-chain"],"_links":{"self":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts\/155","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/comments?post=155"}],"version-history":[{"count":10,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts\/155\/revisions"}],"predecessor-version":[{"id":1779,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/posts\/155\/revisions\/1779"}],"wp:attachment":[{"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/media?parent=155"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/categories?post=155"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.linuxpro.com.br\/en\/wp-json\/wp\/v2\/tags?post=155"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}