O Jenkins oferece duas abordagens principais para definição de pipelines: declarativa e scripted. Ambas utilizam o mecanismo do Groovy, mas diferem significativamente em sintaxe, legibilidade e flexibilidade.
Comparação entre Pipeline Declarativo e Scripted
Pontos em comum:
- Ambos são persistentes e podem usar steps fornecidos por plugins ou bibliotecas compartilhadas.
- Suportam extensão via bibliotecas globais do Jenkins.
Diferenças:
- O pipeline declarativo possui uma estrutura rígida, facilitando a leitura e validação prévia de erros de sintaxe. Ideal para cenários padrão.
- O pipeline scripted, baseado diretamente no Groovy, oferece maior liberdade para lógica complexa, controle de fluxo avannçado e manipulação dinâmica.
O pipeline declarativo é construído sobre a base do scripted e permite incorporar blocos script para recuperar flexibilidade quando necessário.
Estrutura Básica do Pipeline Declarativo
Um pipeline declarativo válido deve conter os seguintes blocos obrigatórios:
agentstages- Um ou mais
stage stepsdentro de cada stage
Além disso, suporta diretivas opcionais como: environment, parameters, options, triggers, post, tools, input, when e parallel.
agent
Define onde o pipeline (ou estágio) será executado. Pode ser colocado no nível raiz (pipeline) ou dentro de um stage.
pipeline {
agent none
stages {
stage('Build') {
agent { docker 'maven:3.8-jdk-11' }
steps {
sh 'mvn clean package'
}
}
stage('Test') {
agent { label 'linux-worker' }
steps {
sh 'npm test'
}
}
}
}
// Exemplo com workspace personalizado
agent {
node {
label 'k8s-agent'
customWorkspace '/build/workspace/project-x'
}
}
options
Configurações globais do pipeline, como tempo limite, descarte de builds antigos ou tentativas de repetição.
pipeline {
agent any
options {
timeout(time: 30, unit: 'MINUTES')
buildDiscarder(logRotator(numToKeepStr: '10'))
disableConcurrentBuilds()
timestamps()
}
stages {
stage('Run') {
steps {
echo 'Executando com opções configuradas'
}
}
}
}
parameters
Permite que o usuário forneça entradas ao acionar o pipeline. Os valores ficam acessíveis via params.NOME.
pipeline {
agent any
parameters {
string(name: 'VERSION', defaultValue: '1.0.0', description: 'Versão da aplicação')
choice(name: 'ENVIRONMENT', choices: ['dev', 'staging', 'prod'], description: 'Ambiente alvo')
booleanParam(name: 'RUN_TESTS', defaultValue: true, description: 'Executar testes?')
}
stages {
stage('Deploy') {
steps {
echo "Implantando versão ${params.VERSION} no ambiente ${params.ENVIRONMENT}"
script {
if (params.RUN_TESTS) {
sh './run-tests.sh'
}
}
}
}
}
}
environment
Define variáveis de ambiente no nível do pipeline ou de um estágio específico. Suporta injeção segura de credenciais via credentials().
pipeline {
agent any
environment {
DB_HOST = 'db.prod.internal'
API_KEY = credentials('my-api-secret')
}
stages {
stage('Use Env') {
steps {
sh 'echo "Conectando a $DB_HOST com chave secreta"'
}
}
}
}
input
Pausa a execução até que um usuário autorizado confirme a continuação.
stage('Approval') {
input {
message "Continuar implantação em produção?"
ok "Sim, implantar"
submitter "admin,deploy-team"
parameters {
string(name: 'APPROVER_NOTES', defaultValue: '', description: 'Justificativa')
}
}
steps {
echo "Aprovado por: ${APPROVER_NOTES}"
}
}
parallel
Permite execução simultânea de múltiplos estágios.
stage('Testes Paralelos') {
parallel {
stage('Linux') {
agent { label 'linux' }
steps { sh './test-linux.sh' }
}
stage('Windows') {
agent { label 'windows' }
steps { bat 'test-windows.bat' }
}
}
}
post
Define ações a serem executadas após a conclusão do pipeline ou estágio, com base no status final.
post {
success {
echo 'Pipeline concluído com sucesso!'
emailext subject: 'Sucesso!', body: 'Build OK', recipientProviders: [[$class: 'DevelopersRecipientProvider']]
}
failure {
echo 'Falha na execução!'
slackSend channel: '#alerts', message: 'Pipeline falhou!'
}
always {
cleanWs()
}
}
when
Controla a execução condicional de um estágio com base em critérios como branch, variáveis de ambiente ou expressões Groovy.
stage('Deploy to Prod') {
when {
allOf {
branch 'main'
environment name: 'DEPLOY_ENV', value: 'production'
expression { return params.DEPLOY_ENABLED }
}
}
steps {
sh './deploy-prod.sh'
}
}
tools
Garante que versões específicas de ferramentas (JDK, Maven, Gradle) estejam disponíveis, desde que configuradas em Gerenciar Jenkins → Configuração de Ferramentas Globais.
pipeline {
agent any
tools {
jdk 'openjdk-17'
maven 'maven-3.9'
}
stages {
stage('Build') {
steps {
sh 'mvn --version'
sh 'java -version'
}
}
}
}
triggers
Define gatilhos automáticos para execução do pipeline.
triggers {
cron('H 2 * * 1-5') // Executa às 2h nos dias úteis
// pollSCM('H/15 * * * *') // Verifica SCM a cada 15 minutos
// upstream(upstreamProjects: 'build-job', threshold: SUCCESS)
}
script
Permite inserir código Groovy arbitrário dantro de um pipeline declarativo, útil para lógica complexa ou iterações.
stage('Dynamic Steps') {
steps {
script {
def services = ['auth', 'payment', 'user']
services.each { svc ->
echo "Construindo serviço: ${svc}"
sh "./build-${svc}.sh"
}
}
}
}
Pipeline Scripted: Controle Total com Groovy
O pipeline scripted oferece liberdade total com a sintaxe do Groovy, incluindo estruturas de controle nativas.
Condicionais com if/else
node('worker') {
stage('Conditional') {
if (env.GIT_BRANCH == 'origin/main') {
sh 'echo "Branch principal"'
} else {
sh 'echo "Branch de feature"'
}
}
}
Tratamento de Erros com try/catch
node {
stage('Risky Operation') {
try {
sh 'flaky-command || exit 1'
} catch (Exception e) {
echo "Erro capturado: ${e.message}"
currentBuild.result = 'UNSTABLE'
} finally {
sh 'cleanup.sh'
}
}
}
Laços com for ou each
node {
stage('Loop Example') {
def regions = ['us-east', 'eu-west', 'ap-southeast']
regions.each { region ->
echo "Processando região: ${region}"
sh "./deploy.sh --region ${region}"
}
}
}
Embora o pipeline declarativo seja recomendado para a maioria dos casos de uso devido à sua clareza e validação antecipada, o scripted permanece essencial para cenários que exigem lógica dinâmica, manipulação avançada de dados ou integração profunda com APIs externas.