DEV Community

Cover image for Jenkins Pipeline com Jenkinsfile
Mattheus Cassundé
Mattheus Cassundé

Posted on • Updated on

Jenkins Pipeline com Jenkinsfile

O Problema

O time está gastando muito tempo com implantações e atualizações de sistemas nos ambientes de homologação e produção, esse time faz essas operações de forma manual ou seja acessando o servidor e rodando todos os comandos necessários, vale lembrar que esse processo é repetido diversas vezes durante o mês.

Precisamos de alguma forma melhorar esse processo dando mais agilidade e deixando o time livre para trabalhar em outras tarefas.

Quais práticas existem para ajudar ?

Em uma situação como essa podemos tirar proveito dos conceitos de CI/CD. Antes de entrar no significado dessas siglas, vamos deixar claro que DevOps não é CI/CD, DevOps é sobre pessoas, um desenvolvedor não pode simplesmente avisar que terminou e esperar que o time de Operação faça a implantação, o time de Operação quando se depara com um erro após a implantação não pode simplesmente abrir um card de erro e encerrar sua parte. Em caso de falhas sistêmicas logo após a implantação quem é o profissional mais apto para resolver o problema ? um profissional de Operações ou o desenvolvedor que criou determinada feature ?

Vamos imaginar agora que o time de operação não faz mais implantações, quem vai fazer agora é o próprio time de desenvolvimento. Mas por que isso? “Quem pariu Mateus que o balance” ou "cachorro com muitos donos morre de fome”, essas frases falam de responsabilidade, quando atualizamos uma aplicação no servidor do cliente não estamos apenas trocando o .jar ou exe , estamos entregando uma solução para resolver um problema, o acompanhamento dessa solução desde a implantação até está em uso diário deve ser do time que planejou e desenvolveu essa solução. Estruturas como Servidores, Sistema operacional, versão de libs e etc depois de configurados é muito difícil dar problema, o que está mais propício a dar problema é código desenvolvido, é aplicação.

Ok, como podemos melhorar isso?

Vamos falar sobre como o Jenkins e Jenkinsfile conseguem ajudar na criação de um pipeline, a sintaxe que precisamos usar para conseguir escrever um pipeline é baseada em duas formas uma chamada de Declarativa e outra chamada de Script, nesse nosso papo vamos usar a forma Declarativa.

A Arquitetura ficará mais ou menos assim:

Image description

Iniciando com Jenkinsfile

Um jenkinsfile nada mais é do que um arquivo com código que será interpretado pelo Jenkins, esse código é baseado em Groovy uma linguagem de programação bastante usada no mercado e roda na JVM do Java. Um Jenkinsfile é como qualquer outro código do software,precisa ser versionado, pode evoluir e que provavelmente precisará de manutenções.

Vamos rapidamente voltar nos passos básicos para entregar um software em produção ou homologação.

  • Devemos rodar testes de unidade
  • Devemos rodar build
  • Devemos armazenar artefato
  • Devemos implantar artefato no servidor

pronto, agora que mapeamos os passos básicos que fazemos para entregar um software, podemos começar a pensar em como automatizar e deixar uma máquina fazendo esse trabalho.

Para iniciarmos vamos criar um arquivo na raiz do projeto chamado Jenkinsfile, não precisa de extensão, basta Jenkinsfile, vamos colocar o conteúdo abaixo:



pipeline {
    agent any

    stages {      
        stage('Test') {
            steps {
                echo 'Testando..'
            }
        }
                stage('Build') {
            steps {
                    echo 'Compilando..'
            }
        }
        stage('Store') {
            steps {
                echo 'Armazenando....'
            }
        }
                stage('DeploY') {
            steps {
                echo 'Implantando....'
            }
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

Analisando o conteúdo que colamos, vamos observar algumas palavras reservadas como, pipeline, agent, stages, stage e steps, vamos conhecer um pouco mais sobre eles nos blocos abaixo.

Pipeline

Quando estamos montando um Pipeline de forma Declarativa todo o conteúdo fica dentro desse principal que chamamos de pipeline {}

Agent

Define o Executorque será responsável por executar os comando dos pepiline, no formato Declarativo essa definição é obrigatória pois sem não saberá como executar. Podemos definir um agentde forma global como em nosso exemplo, no topo do arquivo, ou dentro de cada stagedando mais possibilidades para nosso pipeline.

Temos alguns tipos de Agent, mas para não alongar muito vamos focar em none, any e Docker.

Tipo none é bem simples, não será executado por nenhum Executor mas obriga a definição nos stage.

Tipo anydiz que será executado por qualquer Executordisponível, em nosso exemplo até o momento estamos usando esse valor.



agent any


Enter fullscreen mode Exit fullscreen mode

Tipo Dockerdiz que o Executorusará uma imagem docker especificada para que ele execute seu trabalho, essa forma é a que usaremos em nossos exemplos, usando esse tipo de agent conseguimos realizar várias operações bastando ter uma imagem docker que contenha o que precisamos e pronto, não precisaremos "encher” nosso Jenkins com Plugins.

Confira mais detalhes aqui.

Stages e Stage

Agrupa um ou vários stagecada stage representa uma etapa do nosso pipeline, como test,build, deploy e etc.



...
    stages {      
        stage('Test') {
            steps {
                echo 'Testando..'
            }
        }
                stage('Build') {
            steps {
                    echo 'Compilando..'
            }
        }
        stage('Store') {
            steps {
                echo 'Armazenando....'
            }
        }
                stage('DeploY') {
            steps {
                echo 'Implantando....'
            }
        }
    }
...


Enter fullscreen mode Exit fullscreen mode

Steps

Define como o stage será executado, em nosso caso estamos apenas executando o comando echomas podemos ter vários outros comando para executar o objetivo do stage.

Evoluindo colunas

Agora vamos evoluir mais ainda nosso Jenkinsfile preenchendo algumas colunas para entender como o Jenkins vai executar os passos que definimos.

Evoluindo coluna de Teste

Vamos ver como podemos evoluir a stagede teste, atualmente está super simples, apenas exibindo um texto no console, veja abaixo:



...
stage('Test') {
      steps {
          echo 'Testando..'
      }
}
...


Enter fullscreen mode Exit fullscreen mode

Nosso projeto foi escrito em java usando maven como gerenciador, para rodarmos os testes unitários executamos o comando:



$ mvn test


Enter fullscreen mode Exit fullscreen mode

Mas a partir de agora quem vai executar esse comando será o Jenkins, nesse nosso papo usaremos um agent do tipo docker com uma imagem contendo o Java já configurado, primeiro vamos mudar o agentglobal que está como agent anypara agent none dessa forma vamos definir o agent apenas dentro do stage como no exemplo abaixo:



...
agent none
    stages {      
        stage('Test') {
          agent { docker 'adoptopenjdk/openjdk11:jdk-11.0.9.1_1' }            
        }
}
...


Enter fullscreen mode Exit fullscreen mode

agora basta implementar o steps passando o comando para rodar os testes, veja como fica:



...
agent none

    stages {      
        stage('Test') {
          agent { docker 'adoptopenjdk/openjdk11:jdk-11.0.9.1_1' }
          sh './mvnw test'
        }
     }
}
...


Enter fullscreen mode Exit fullscreen mode

Se observar usamos o comando sh dentro da chave steps, pronto com isso finalizamos nossa primeira coluna, nosso arquivo está fincando assim:



pipeline {
    agent none

    stages {      
        stage('Test') {
            agent { docker 'adoptopenjdk/openjdk11:jdk-11.0.9.1_1' }
            steps {
                sh './mvnw test'
        }
    } 
    stage('Build') {
        agent any
        steps {
        echo 'Compilando..'
        }
    }
    stage('Store') {
        agent any
        steps {
            echo 'Armazenando....'
        }
    }
    stage('DeploY') {
        agent any
        steps {
            echo 'Implantando....'
        }
    }
}


Enter fullscreen mode Exit fullscreen mode

observe que nos demais stage adicionei um agent do tipo any pois como comentei, se colocarmos no agent global o tipo none seremos obrigados a definir um agent em cada stage.

Evoluindo coluna de Build

Como na coluna de teste, vamos definir um agent do tipo docker, passar uma imagem com java e executar um outro comando para fazer o build da aplicação.



stage('Test') {
    agent { docker 'adoptopenjdk/openjdk11:jdk-11.0.9.1_1'}            
    steps {
        sh './mvnw package'
    }
}


Enter fullscreen mode Exit fullscreen mode

pronto agora o Jenkins saberá empacotar toda nossa aplicação em um arquivo jar que ficará disponível para a próxima etapa que pode ser por exemplo criar uma imagem docker.

Conclusão

Vimos com é simples criar um arquivo Jenkinsfile e começamos a entender como o Jenkins vai usa-lo para automatizar os passos das nossas entregas de Software.

Top comments (0)