GithubHelp home page GithubHelp logo

jenkins-pipeline's Introduction

Pipeline como código no Jenkins

Olá pessoal! Neste post quero mostrar um modo diferente para criar Pipelines no Jenkins. Pipeline criado como código.

Geralmente temos um certo trabalho com configuração quando precisamos criar uma estrutura de pipeline, pois envolve criação de múltiplos jobs, configuração do SCM, agendamento para execução, log rotation, arquivamento de artefatos, publicação de relatórios, etc.

Após a criação dos jobs necessários para o projeto é necessário configurar a ligação entre eles, informar ao job filho que terá que utilizar determinado artefato do job pai, e assim por diante.

Todo esse processo leva tempo para configurar, dar manutenção e entender a relação entre os jobs, e já que não queremos perder tempo com isso, vamos criar apenas 1 job. Sim, eu disse 1 JOB!

Mas como!? Vamos utilizar código para criar cada passo do nosso projeto! =]

Código em Groovy

Para o Pipeline no Jenkins escrevemos em Groovy, uma linguagem desenvolvida para a plataforma Java, como alternativa à mesma. Ou seja, se você domina Java, não terá dificuldade alguma para pintar e bordar no Pipeline! =]

Se não domina, não se preocupe, pois no Jenkins existe uma opção chamada Pipeline Syntax, que ajuda muito!!!

Como falamos no início, nosso job será criado apenas com código, e com Pipeline temos duas maneiras de fazer.

  1. Escrevendo o código diretamente no job.
  2. Criando o "Jenkinsfile" na raiz do repositório, com o código.

Na minha opinão, a segunda forma é a mais legal, pois com o Jenkinsfile na raiz do repositório teremos todo o histórico de alterações no Git, e o desenvolvedor não precisará abrir o Jenkins para alterar qualquer vírgula no job.

Sendo assim, mãos à obra!!!

Para nosso projeto vamos utilizar a versão 2.xx do Jenkins, um repositório do BitBucket e emulador ou dispositivo com Android.

Neste post não farei instalação/configuração do Jenkins. Utilizaremos o Docker, com o container jenkinsci/jenkins, que já instala por padrão os plugins que utilizaremos, como "Pipeline", "Git Plugin", etc.

Iniciando o Jenkins e criando o Job

Para baixar o container:

$ docker pull jenkinsci/jenkins

Para iniciar o Jenkins com diretório de persistência e redirecionamento de portas:

$ docker run -d --name jenkins -v /opt/jenkins:/var/jenkins_home -p 8080:8080 -p 50000:50000 jenkinsci/jenkins

Com o Jenkins em execução, vamos criar nosso job:

Jenkins 01

Vamos dar um nome ao job, informar que ele será um "Pipeline" e clicar em OK para criar:

Jenkins 02

Configuração do job:

  1. Navegar até o campo Pipeline.
  2. Em Definition, selecionar "Pipeline script from SCM" (Essa opção utiliza o Jenkinsfile contido no repositório).
  3. Em SCM selecionar "Git".
  4. Em Repositories vamos informar a URL do repositório em "Repository URL" e informar as credenciais em "Credentials".
  5. Em Branches to build vamos informar a branch desejada em "Branch Specifier".
  6. Em Script Path vamos informar o nome do nosso "Jenkinsfile" que, neste caso, será Jenkinsfile mesmo.
  7. Salve o job!

Jenkins 03

Pronto!!!

Jenkins 04

Iniciando o Jenkinsfile

Vamos criar este projeto utilizando o Jenkinsfile contido no repositório. Para iniciá-lo, começaremos com o código abaixo:

stage 'Checkout'
 node('slave') {
  deleteDir()
  checkout scm
 }
  • Este trecho de código criou o "stage" chamado "Checkout" (O nome do stage fica a seu critério).
  • Em "node" foi definido que o job será executado no nó chamado "slave" (Caso não informe o nó, conhecido como "slave", o job será executado no Jenkins master).
  • Adicionamos "deleteDir()" para excluir o diretório clonado a cada início de build.
  • A opção "checkout scm" indica que o Jenkinsfile foi criado com suporte a multibranch.

Feito isso, ao construir nosso projeto, temos a execução:

Jenkins 05

E o fim:

Jenkins 06

Legal! Já conseguimos clonar nosso repositório e iniciar o Pipeline. Agora, vamos fazer um build do aplicativo e arquivar o artefato, que neste caso será o aplicativo gerado.

Para isso vamos conectar um dispositivo Android no Jenkins Slave ou iniciar um emulador. Para nosso projeto, utilizarei o Genymotion para emular um dispositivo com Android.

Vamos ver o dispositivo conectado ao slave:

$ adb devices
List of devices attached
192.168.56.101:5555	device

O nome do device é "192.168.56.101:5555". Vamos utilizá-lo a seguir.

No Jenkinsfile adicionamos o bloco:

stage 'Build & Archive Apk'
 node('slave') {
  sh 'export ANDROID_SERIAL=192.168.56.101:5555 ; ./build.sh'
  step([$class: 'ArtifactArchiver', artifacts: 'meu_aplicativo/build/outputs/apk/meu_aplicativo.apk'])
 }
  • Para este stage demos o nome de "Build & Archive Apk".
  • Mantivemos a execução no node "slave".
  • Acrescentamos "sh" para utilizar Shell Script, no qual exportamos a variável "ANDROID_SERIAL" com o nome do nosso dispositivo e na sequência chamamos um script que fará o build do aplicativo.
  • Criamos um "step" para arquivar o aplicativo gerado utilizando "ArtifactArchiver", e passamos o caminho do aplicativo.

Nosso Jenkinsfile ficou assim:

stage 'Checkout'
 node('slave') {
  deleteDir()
  checkout scm
 }

stage 'Build & Archive Apk'
 node('slave') {
  sh 'export ANDROID_SERIAL=192.168.56.101:5555 ; ./build.sh'
  step([$class: 'ArtifactArchiver', artifacts: 'meu_aplicativo/build/outputs/apk/meu_aplicativo.apk'])
 }

Vamos construir o projeto!

Jenkins 07

Como podemos ver, ao finalizar o primeiro stage, foi criado automaticamente o stage "Build & Archive Apk".

Jenkins 08

No fim, temos mais um stage finalizado e em "Last Successful Artifacts" temos o aplicativo arquivado, "meu_aplicativo.apk".

Ae, está ficando bom! Pelo menos eu acho... rs

Vamos agora executar os testes e publicar os relatórios.

No Jenkinsfile, vamos adicionar:

stage 'Run Tests'
 node('slave') {
  sh 'export ANDROID_SERIAL=192.168.56.101:5555 ; ./runtests.sh'
  publishHTML(target: [reportDir: 'meu_aplicativo_testes/build/reports/androidTests/connected/', reportFiles: 'index.html', reportName: 'Testes Instrumentados'])
  step([$class: 'JUnitResultArchiver', testResults: 'meu_aplicativo_testes/build/outputs/androidTest-results/connected/*.xml'])
 }
  • Para este stage demos o nome de "Run Tests".
  • Novamente estamos utilizando "sh" para exportar a variável com o nome do dispositivo Android, e na sequência executamos um script que fará os testes no aplicativo.
  • Adicionamos "publishHTML" para publicar o relatório de testes, passamos o caminho, o arquivo que será publicado e o nome que daremos ao relatório.
  • Adicionamos "step" para criar um gráfico de "Tendência de resultados de teste" utilizando "JUnitResultArchiver", e passamos o caminho dos arquivos XML.

O Jenkinsfile ficou assim:

stage 'Checkout'
 node('slave') {
  deleteDir()
  checkout scm
}

stage 'Build & Archive Apk'
 node('slave') {
  sh 'export ANDROID_SERIAL=192.168.56.101:5555 ; ./build.sh'
  step([$class: 'ArtifactArchiver', artifacts: 'meu_aplicativo/build/outputs/apk/meu_aplicativo.apk'])
 }

stage 'Run Tests'
 node('slave') {
  sh 'export ANDROID_SERIAL=192.168.56.101:5555 ; ./runtests.sh'
  publishHTML(target: [reportDir: 'meu_aplicativo_testes/build/reports/androidTests/connected/', reportFiles: 'index.html', reportName: 'Testes Instrumentados'])
  step([$class: 'JUnitResultArchiver', testResults: 'meu_aplicativo_testes/build/outputs/androidTest-results/connected/*.xml'])
}

Vamos construir!!!

Jenkins 09

Podemos ver que o stage "Run Tests" foi criado automaticamente.

Jenkins 10

E no fim da construção podemos ver que o relatório, chamado "Testes Instrumentados", foi publicado com sucesso!!!

Mas opa, está faltando algo... O gráfico de "Tendência de resultados de teste".

Não temos o gráfico porque precisamos arquivar pelo menos 2 jobs para ter o ponto inicial e ponto final.

Sendo assim, vamos executar novamente!

Jenkins 11

O Pipeline está sendo construído mais uma vez...

Jenkins 12

E no fim temos tudo que tínhamos antes mais o gráfico de "Tendência de resultados de teste".

Mas e se algum step quebrar?

Jenkins 13

Como visto, o step Build & Archive Apk quebrou, e o stage Run Tests não foi executado.

Após correções no código, executamos novamente.

Jenkins 14

Os stages voltam a executar após correção do build, e mantêm o histórico dos builds que quebraram.

  • Obs.: É possível tratar a quebra dos stages com script, caso queira por exemplo arquivar artefatos ou passar para o stage seguinte mesmo com a quebra do anterior.

Bônus

Ao criar um job de Pipeline no Jenkins, aparece uma opção chamada Pipeline Syntax, que ajuda muito quem está começando a trabalhar com Pipeline feito com código.

Olha ali no final... Clica lá!

Jenkins 15

Funciona assim:

  • Em Sample Step você seleciona o que pretende fazer.
  • Os campos mudam de acordo com a opção escolhida.
  • Preencha de acordo com o desejado e clique em Generate Groovy.

Jenkins 16

No exemplo foi utilizado o step do plugin HTML Publisher plugin, no qual foi informado o caminho dos arquivos HTML, a página inicial e o nome que o relatório terá quando for publicado.

Agora é só copiar o código gerado e utilizar dentro dos stages no Jenkinsfile de acordo com sua necessidade.

publishHTML([allowMissing: false, alwaysLinkToLastBuild: false, keepAll: false, reportDir: 'caminho/do/relatorio/', reportFiles: 'index.html', reportName: 'Meu Relatorio'])
  • Obs.: Quanto mais plugins instalados no Jenkins, mais opções para gerar o código em Groovy.

A documentação para o Pipeline do Jenkins pode ser acessada aqui.

Bom pessoal, por enquanto é isso. Espero que tenham gostado! Se tiver alguma dúvida ou contribuição, use os campos abaixo. Um abraço e até a próxima!

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.