Executando inspeções do IntelliJ IDEA no Jenkins

O IntelliJ IDEA hoje possui o mais avançado analisador de código estático Java, que em suas capacidades deixa para trás “veteranos” como estilo de verificação и Percevejos. Suas inúmeras “inspeções” verificam o código em vários aspectos, desde o estilo de codificação até bugs típicos.

Porém, desde que os resultados da análise sejam exibidos apenas na interface local do IDE do desenvolvedor, eles são de pouca utilidade para o processo de desenvolvimento. Análise estática deve ser cumprido Como a primeira etapa do pipeline de construção, seus resultados devem definir as portas de qualidade, e a construção deve falhar se as portas de qualidade não forem ultrapassadas. Sabe-se que o TeamCity CI está integrado ao IDEA. Mas mesmo que você não use o TeamCity, você pode facilmente tentar executar inspeções IDEA em qualquer outro servidor de CI. Eu sugiro que você veja como isso pode ser feito usando o plugin IDEA Community Edition, Jenkins e Warnings NG.

Passo 1. Execute a análise no contêiner e obtenha um relatório

A princípio, a ideia de rodar um IDE (aplicativo desktop!) dentro de um sistema de CI que não possui interface gráfica pode parecer duvidosa e muito problemática. Felizmente, os desenvolvedores do IDEA forneceram a capacidade de executar formatação de código и inspeções na linha de comando. Além disso, para executar o IDEA neste modo, não é necessário um subsistema gráfico e essas tarefas podem ser executadas em servidores com shell de texto.

As inspeções são iniciadas usando um script bin/inspect.sh do diretório de instalação do IDEA. Os parâmetros necessários são:

  • caminho completo para o projeto (os relativos não são suportados),
  • caminho para o arquivo .xml com configurações de inspeção (geralmente localizado dentro do projeto em .idea/inspectionProfiles/Project_Default.xml),
  • caminho completo para a pasta onde serão armazenados os arquivos .xml com relatórios dos resultados da análise.

Além disso, espera-se que

  • o caminho para o Java SDK será configurado no IDE, caso contrário a análise não funcionará. Essas configurações estão contidas no arquivo de configuração jdk.table.xml na pasta de configuração global do IDEA. A configuração global do IDEA está localizada no diretório inicial do usuário por padrão, mas esse local pode ser explicitamente especificado no arquivo idea.properties.
  • O projeto analisado deverá ser um projeto IDEA válido, para o qual será necessário submeter alguns arquivos que normalmente são ignorados pelo controle de versão, a saber:
    • .idea/inspectionProfiles/Project_Default.xml — configurações do analisador, que serão obviamente utilizadas durante a realização de inspeções no contentor,
    • .idea/modules.xml — caso contrário, receberemos o erro ‘Este projeto não contém módulos’,
    • .idea/misc.xml — caso contrário, receberemos o erro ‘O JDK não está configurado corretamente para este projeto’,
    • *.iml-файлы — caso contrário, receberemos um erro sobre um JDK não configurado no módulo.

Embora esses arquivos geralmente sejam incluídos em .gitignore, eles não contêm nenhuma informação específica do ambiente de um desenvolvedor específico - ao contrário, por exemplo, de um arquivo workspace.xml, onde tais informações estão contidas e, portanto, não há necessidade de confirmá-las.

A solução óbvia é empacotar o JDK junto com o IDEA Community Edition em um contêiner em um formato pronto para ser “colocado” nos projetos analisados. Vamos escolher um contêiner base adequado e nosso Dockerfile será assim:

dockerfile

FROM openkbs/ubuntu-bionic-jdk-mvn-py3

ARG INTELLIJ_VERSION="ideaIC-2019.1.1"

ARG INTELLIJ_IDE_TAR=${INTELLIJ_VERSION}.tar.gz

ENV IDEA_PROJECT_DIR="/var/project"

WORKDIR /opt

COPY jdk.table.xml /etc/idea/config/options/

RUN wget https://download-cf.jetbrains.com/idea/${INTELLIJ_IDE_TAR} && 
    tar xzf ${INTELLIJ_IDE_TAR} && 
    tar tzf ${INTELLIJ_IDE_TAR} | head -1 | sed -e 's//.*//' | xargs -I{} ln -s {} idea && 
    rm ${INTELLIJ_IDE_TAR} && 
    echo idea.config.path=/etc/idea/config >> idea/bin/idea.properties && 
    chmod -R 777 /etc/idea

CMD idea/bin/inspect.sh ${IDEA_PROJECT_DIR} ${IDEA_PROJECT_DIR}/.idea/inspectionProfiles/Project_Default.xml ${IDEA_PROJECT_DIR}/target/idea_inspections -v2

Usando a opção idea.config.path forçamos o IDEA a procurar sua configuração global na pasta /etc/idea, porque a pasta pessoal do usuário ao trabalhar no CI é algo incerto e muitas vezes completamente ausente.

Esta é a aparência do arquivo copiado para o contêiner: jdk.table.xml, que contém os caminhos para o OpenJDK instalado dentro do contêiner (um arquivo semelhante do seu próprio diretório com configurações do IDEA pode ser tomado como base):

jdk.table.xml

<application>
 <component name="ProjectJdkTable">
   <jdk version="2">
     <name value="1.8" />
     <type value="JavaSDK" />
     <version value="1.8" />
     <homePath value="/usr/java" />
     <roots>
       <annotationsPath>
         <root type="composite">
           <root url="jar://$APPLICATION_HOME_DIR$/lib/jdkAnnotations.jar!/" type="simple" />
         </root>
       </annotationsPath>
       <classPath>
         <root type="composite">
           <root url="jar:///usr/java/jre/lib/charsets.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/deploy.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/access-bridge-64.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/cldrdata.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/dnsns.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/jaccess.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/jfxrt.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/localedata.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/nashorn.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunec.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunjce_provider.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunmscapi.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/sunpkcs11.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/ext/zipfs.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/javaws.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jce.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jfr.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jfxswt.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/jsse.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/management-agent.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/plugin.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/resources.jar!/" type="simple" />
           <root url="jar:///usr/java/jre/lib/rt.jar!/" type="simple" />
         </root>
       </classPath>
     </roots>
     <additional />
   </jdk>
 </component>
</application>

A imagem finalizada disponível no Docker Hub.

Antes de prosseguir, vamos verificar se o analisador IDEA está rodando no contêiner:

docker run --rm -v <путь/к/вашему/проекту>:/var/project inponomarev/intellij-idea-analyzer

A análise deverá ser executada com êxito e vários arquivos .xml com relatórios do analisador deverão aparecer na subpasta target/idea_inspections.

Agora não há mais dúvidas de que o analisador IDEA pode ser executado de forma independente em qualquer ambiente de CI e passamos para a segunda etapa.

Passo 2. Exibir e analisar o relatório

Obter o relatório no formato de arquivos .xml é metade da batalha; agora você precisa torná-lo legível por humanos. E também seus resultados devem ser usados ​​em portões de qualidade – a lógica para determinar se a mudança aceita é aprovada ou reprovada de acordo com critérios de qualidade.

Isso vai nos ajudar Plug-in NG de avisos do Jenkins, que foi lançado em janeiro de 2019. Com seu advento, muitos plug-ins individuais para trabalhar com resultados de análises estáticas no Jenkins (CheckStyle, FindBugs, PMD, etc.) agora são marcados como obsoletos.

O plugin consiste em duas partes:

  • numerosos coletores de mensagens do analisador (lista completa inclui todos os analisadores conhecidos pela ciência, desde AcuCobol até ZPT Lint),
  • um único visualizador de relatórios para todos eles.

A lista de coisas que o Warnings NG pode analisar inclui avisos do compilador Java e avisos dos logs de execução do Maven: embora estejam constantemente visíveis, raramente são analisados ​​especificamente. Os relatórios IntelliJ IDEA também estão incluídos na lista de formatos reconhecidos.

Como o plugin é novo, inicialmente ele interage bem com o Jenkins Pipeline. A etapa de construção com sua participação será semelhante a esta (simplesmente informamos ao plugin qual formato de relatório reconhecemos e quais arquivos devem ser verificados):

stage ('Static analysis'){
    sh 'rm -rf target/idea_inspections'
    docker.image('inponomarev/intellij-idea-analyzer').inside {
       sh '/opt/idea/bin/inspect.sh $WORKSPACE $WORKSPACE/.idea/inspectionProfiles/Project_Default.xml $WORKSPACE/target/idea_inspections -v2'
    }
    recordIssues(
       tools: [ideaInspection(pattern: 'target/idea_inspections/*.xml')]
    )
}

A interface do relatório é semelhante a esta:

Executando inspeções do IntelliJ IDEA no Jenkins

Convenientemente, esta interface é universal para todos os analisadores reconhecidos. Ele contém um diagrama interativo da distribuição das descobertas por categoria e um gráfico da dinâmica das mudanças no número de descobertas. Você pode realizar uma pesquisa rápida na grade na parte inferior da página. A única coisa que não funcionou corretamente para as inspeções IDEA foi a capacidade de navegar pelo código diretamente no Jenkins (embora para outros relatórios, por exemplo Checkstyle, este plugin possa fazer isso perfeitamente). Parece que este é um bug no analisador de relatórios IDEA que precisa ser corrigido.

Entre os recursos do Warnings NG está a capacidade de agregar descobertas de diferentes fontes em um relatório e programar Quality Gates, incluindo uma “catraca” para a montagem de referência. Alguma documentação de programação do Quality Gates está disponível aqui - no entanto, não está completo e você deve consultar o código-fonte. Por outro lado, para controle total sobre o que está acontecendo, a “catraca” pode ser implementada de forma independente (veja meu postagem antecipada sobre este tema).

Conclusão

Antes de começar a preparar este material, resolvi pesquisar: alguém já escreveu sobre esse assunto no Habré? eu só encontrei entrevista 2017 с cordaonde ele diz:

Pelo que eu sei, não há integração com Jenkins ou plugin maven […] Em princípio, qualquer entusiasta poderia fazer amizade com IDEA Community Edition e Jenkins, muitos só se beneficiariam com isso.

Bom, dois anos depois temos o Warnings NG Plugin, e finalmente essa amizade se concretizou!

Fonte: habr.com

Adicionar um comentário