Configuração do Ambiente de Desenvolvimento
O ecossistema do Jenkins é fundamentado em Java. Para iniciar a criação de extensões, é imprescindível ter o Java Development Kit (JDK) e o Apache Maven devidamente instalados e configurados nas variáveis de ambiente da máquina.
Geração do Projeto Base
O ponto de partida mais eficiente é utilizar os arquétipos oficiais fornecidos pela comunidade. Crie um diretório para o seu workspace e execute o comando Maven abaixo para filtrar os templates disponíveis para extensões vazias:
mvn -U archetype:generate -Dfilter=io.jenkins.archetypes:empty-plugin
Durante a execução interativa, o Maven solicitará o preenchimento de metadados essenciais:
- Selecione a versão do arquétipo desejada.
- Defina o
artifactId(por exemplo,custom-ci-extension). - Informe a versão base do Jenkins para a qual o plugin será compilado.
Confirme as configurações digitando Y para materializar a estrutura de diretórios do projeto.
Execução e Depuração Local
Para testar a extensão em um ambiente isolado, o plugin Maven HPI provê um servidor Jetty embutido. Navegue até a raiz do diretório recém-criado e dispare o ciclo de vida de execução:
mvn hpi:run
É comum encontrar falhas de compilação relacionadas à versão do Java. Muitas extensões legadas ou configurações específicas exigem o JDK 8. Caso enfrente este problema, aponte o Maven para a instalação correta antes de executar o comando:
export JAVA_HOME=/Library/Java/JavaVirtualMachines/jdk1.8.0_231.jdk/Contents/Home
export PATH=$JAVA_HOME/bin:$PATH
mvn hpi:run
Com o servidor ativo na porta padrão 8080 (certifique-se de que não haja conflitos de porta no sistema operacional), acesse http://localhost:8080/jenkins/ no navegador. Para validar o esqueleto inicial, crie um job do tipo Freestyle, adicione o passo de construção padrão gerado pelo template, execute a tarefa e inspecione os logs no console de saída.
Arquitetura e Modificação do Código Fonte
A estrutura do projeto gerado contém os componentes essenciais para uma extensão funcional, divididos entre classes Java (lógica de negócio) e arquivos Jelly/Groovy (renderização da interface). As propriedades expostas na UI são gerenciadas através de métodos get e construtores anotados com @DataBoundConstructor.
Abaixo, uma implementação robusta de um Builder personalizado. O código inclui a validação de parâmetros na interface de configuração (via DescriptorImpl) e o método perform, que concentra a regra de execução durante o build:
package com.empresa.ci;
import hudson.Extension;
import hudson.Launcher;
import hudson.model.AbstractBuild;
import hudson.model.BuildListener;
import hudson.tasks.BuildStepDescriptor;
import hudson.tasks.Builder;
import hudson.util.FormValidation;
import org.kohsuke.stapler.DataBoundConstructor;
import org.kohsuke.stapler.QueryParameter;
import java.io.IOException;
public class CustomTestRunner extends Builder {
private final String targetEndpoint;
private final int maxTimeout;
@DataBoundConstructor
public CustomTestRunner(String targetEndpoint, int maxTimeout) {
this.targetEndpoint = targetEndpoint;
this.maxTimeout = maxTimeout;
}
public String getTargetEndpoint() { return targetEndpoint; }
public int getMaxTimeout() { return maxTimeout; }
@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
listener.getLogger().println("Iniciando execução da suíte no endpoint: " + targetEndpoint);
listener.getLogger().println("Timeout configurado para: " + maxTimeout + " segundos");
// Lógica de integração com API externa
return true;
}
@Extension
public static final class DescriptorImpl extends BuildStepDescriptor<Builder> {
public FormValidation doCheckTargetEndpoint(@QueryParameter String value) {
if (value == null || !value.startsWith("http")) {
return FormValidation.error("Informe uma URL válida iniciando com http ou https.");
}
return FormValidation.ok();
}
@Override
public boolean isApplicable(Class jobType) { return true; }
@Override
public String getDisplayName() { return "Executar Suite de Testes Customizada"; }
}
}
Para validações que dependam do contexto de execução (em vez da configuração inicial do job), a lógica deve ser inserida dirteamente dentro do método perform, lançando exceções quando as condições não forem atendidas.
Compilação e Empactoamento
Para gerar o arquivo binário instalável no formato .hpi, utilize o ciclo de empacotamento do Maven. Caso os testes unitários apresentem falhas devido a restrições do ambiente local, é possível ignorá-los utilizando as flags apropriadas:
mvn clean package -DskipTests
Atenção à compatibilidade: Se ocorrerem erros de dependência durante a compilação, verifique a tag jenkins.version no arquivo pom.xml. Esta versão deve ser estritamente compatível com a instância do servidor Jenkins onde o plugin será implantado. Ajuste o parenet POM caso necessário.
Integração em Pipelines
Uma vez compilado e instalado, a extensão pode ser orquestrada via Jenkins Pipeline. Utilizando a anotação @Symbol na classe descritora, a sintaxe de invocação torna-se nativa e limpa.
Implementação utilizando o formato Scripted:
node {
stage('Testes') {
customTestRunner targetEndpoint: 'http://api.interno.local:8080/v2/run', maxTimeout: 300
}
}
Implementação utilizando o formato Declarative:
pipeline {
agent any
stages {
stage('Validação de Qualidade') {
steps {
customTestRunner targetEndpoint: 'http://api.interno.local:8080/v2/run', maxTimeout: 300
}
}
}
}