Criando Releases com Apache Ant

Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Para efetuar o download você precisa estar logado. Clique aqui para efetuar o login
Confirmar voto
0
 (2)  (0)

Nesse artigo será detalhada a criação de releases de liberação do sistema de forma automática, utilizando a ferramenta Ant, da comunidade Apache.

Este artigo demonstra o processo de criação de releases de projeto, utilizando a ferramenta Ant. Os arquivos gerados da release são o “html/css/js/php”, necessários para enviar ao cliente, destacando que os arquivos “js” e “css” são concatenados e compactados em um único arquivo. O objetivo deste artigo é que através de um simples comando “ant” a release seja gerada e possa ser enviada para o cliente.

De acordo com a Apache, “A Apache Ant é uma biblioteca Java e uma ferramenta de linha de comando, cuja missão é conduzir os processos descritos na construção de arquivos como alvos e pontos de extensão, que dependem uns dos outros. Ant fornece uma série de tarefas internas que permitem compilar, montar, testar e executar aplicativos”. Essa ferramenta é um software livre, projetado e licenciado pela “Apache Software Foundation.

Instalação do Apache Ant

Para a instalação da ferramenta Ant deve ser realizado o download do arquivo correspondente, compactado, pelo site http://ant.apache.org/bindownload.cgi.

Com o download completo, o arquivo “rar” deve ser copiado para o diretório de sua preferencia e descompactado. A Figura 1 apresenta o exemplo de caminho que foi realizado a descompactação do arquivo (D:\ant).

Apache Ant

Figura 1: Apache Ant

Com o Ant descompactado, deve ser criada uma variável de ambiente apontando para o caminho de localização do Ant, como exemplificado na Figura 2.

Variável de Ambiente Ant

Figura 2: Variável de Ambiente Ant

A pasta Bin deve ser acrescentada ao PATH de comandos do sistema operacional (D:\>SET PATH=%PATH%;%ANT_HOME%\bin) conforme ilustrado na Figura 3.

Pasta Bin ao Path de comandos do Sistema Operacional

Figura 3: Pasta Bin ao Path de comandos do Sistema Operacional

A verificação de configuração do Ant é possível pela execução do comando “ant”, exemplificado na Figura 4.

Comando Ant

Figura 4: Comando Ant

O comando de verificação direciona o usuário a uma mensagem informativa, de sucesso ou não, como Figura 5.

Ant configurado com Sucesso

Figura 5: Ant configurado com Sucesso

A mensagem apresentada na Figura 5 ilustra a configuração bem sucedida.

Entendendo o projeto ant-build-xml

Com o Ant configurado corretamente é possível iniciar o processo de geração de releases para liberar para o cliente. O projeto “ant-build-xml”, apresenta na Figura 6, pode ser encontrado no Github.

Projeto ant-build-xml

Figura 6: Projeto "ant-build-xml"

O projeto está divido em “build-xml”, “projeto-exemplo”, “release-liberacao”. Na pasta “build-xml” (Figura 7) encontra-se os arquivos utilizados pela ferramenta Ant.

Pasta build-xml

Figura 7: Pasta build-xml

A Figura 8 apresenta o “projeto-exemplo” que será utilizado de base para geração de releases.

Projeto exemplo utilizado para geração das releases

Figura 8: "projeto-exemplo" utilizado para geração das releases

Na Figura 8, dentro da pasta “app” se encontra arquivos “php”, utilizados no projeto. Já na pasta “css” os arquivos “css”, seguindo da mesma forma para as demais pastas.

A Figura 9 apresenta “release-liberacao”, um exemplo de releases geradas, que devem ser enviadas para o cliente.

Releases liberação

Figura 9: Releases liberação

A release enviada para o cliente (Figura 9), é considerada a versão 0.0.4. no exemplo.

Entendendo a pasta build-xml

O Ant trabalha com arquivos “XML”, denominados “buildfiles”, estes são interpretados pelo Ant, para que o mesmo possa executar as tarefas que estão descritas.

Dentro da pasta “build-xml” deve ser criada a pasta “templates”, que conterá arquivos padrões do projeto, também a pasta “yui” com o arquivo “jar”, responsável por compactar arquivos “js” e “css” e um arquivo “build.xml”, conforme Figura 10.

Pasta build-xml

Figura 10: Pasta "build-xml"

Na pasta “templates -> js” esta o arquivo “loader.js”, desenvolvido por terceiros, arquivo responsável por inserir os “js” e “css” desenvolvidos na página.

O arquivo “yuicompressor-2.4.2.jar” responsável por compactar os arquivos “js” e “css” do projeto se encontra na pasta “yui” - maiores informações do “yuicompressor” em http://yui.github.io/yuicompressor/

Criação do arquivo build.xml

O arquivo “build.xml” é o arquivo que será interpretado pelo Ant, neste arquivo irá conter as operações necessárias para geração do “deploy” do projeto.

Configurações Iniciais

Todo “build.xml” deve iniciar com a tag “project”, representando o escopo de inicio e fim do projeto, cada “buildfile” só deve conter uma tag “project”. A Listagem 1 apresenta os primeiro passos para criação do “build.xml” do projeto proposto “ant-build-xml”.

Listagem 1: Inicio arquivo “build.xml”

<?xml version="1.0" encoding="UTF-8"?>
<project name="${project.name}" basedir="." default="deploy" >
	<!-- projeto ant-build-xml -->
</project>

Na tag “project” (Listagem 1), o atributo “name” é setado a variável “project.name”, a qual está valorizada com o nome do projeto. O atributo “basedir” ter a função de informar a localização do diretório base, no caso “.” - referência ao diretório que o “build.xml” está localizado. O atributo “default” informa para o Ant qual o primeiro procedimento que deve ser executado ao iniciar o “deploy”.

A Listagem 2 apresenta a configuração inicial do projeto, definindo o nome do projeto como “project.name”, versão da aplicação que será gerada a release “project.vs” e a pasta que será enviada a release “project.folder.save”.

A tag “property” no Ant deve conter nome e valor, no exemplo foi utilizado para declarar as variáveis.

Listagem 2: Configuração da aplicação pelo “build.xml”

 
<?xml version="1.0" encoding="UTF-8"?>
<project name="${project.name}" basedir="." default="deploy" >

    <!-- projeto ant-build-xml -->

    <!-- configurações da aplicacação -->
    <property name="project.name"        value="projeto-teste" />   
    <property name="project.vs"          value="vs.0.0.4" />    
    <property name="project.folder.save" value="release-liberacao" />   
    
    <!-- Diretório para o deploy -->
    <property name="dir.deploy" value="${basedir}/../deploy/" 
        description="diretório do deploy" />   
    
    <!-- YUICompressor -->
    <property name="YUI" value="${basedir}/yui/yuicompressor-2.4.2.jar" 
        description="YUICompressor" /> 

    <!-- Diretório dos templates -->
    <property name="dir.templates" value="${basedir}/templates/" />
    <property name="dir.templates.js" value="${dir.templates}/js/" />
    <property name="js.loader" value="loader.js" />    

</project>

Ainda na Listagem 2, foi definido o diretório que será gerado a release “dir.deploy”. No projeto ant-build-xml o diretório “deploy” é criado, zipado em um arquivo, enviado para a pasta de liberação “release-liberacao” e para então ser excluído este diretório.

A property “YUI“ especifica o caminho do “yuicompressor”, responsável por compactar os arquivos “js” e “css”.

A property “dir.templates” “dir.templates.js” e “js.loader” especifica para o Ant o caminho do arquivos padrões do projeto, neste caso apenas utiliza-se o “js loader” como arquivo padrão, poderia ser por exemplo, um arquivo “php” com a conexão padrão do cliente. A vantagem de se utilizar “templates” padrões é que depois da geração da release não haverá a necessidade de alteração de algum arquivo.

Continuando com o desenvolvimento do “deploy.xml”, deve ser especificado para o Ant quais os arquivos são necessários para envio ao cliente, como apresenta a Listagem 3.

Listagem 3: Configuração dos arquivos necessários para Envio.

 
    <!-- Index da Aplicação -->
    <property name="dir.deploy.index.php" value="${dir.deploy}/index.php" />    
    <property name="dir.base.index.php" value="${basedir}/../projeto-exemplo/index.php" />  

    <!-- Localização das pastas padrões do projeto -->
    <property name="dir.deploy.img" value="${dir.deploy}/img" />    
    <property name="dir.base.img" value="${basedir}/../projeto-exemplo/img" />  
    
    <property name="dir.deploy.css" value="${dir.deploy}/css" />    
    <property name="dir.base.css" value="${basedir}/../projeto-exemplo/css" />  

    <property name="dir.deploy.js"  value="${dir.deploy}/js"  />    
    <property name="dir.base.js"  value="${basedir}/../projeto-exemplo/js"  />  

    <property name="dir.deploy.app" value="${dir.deploy}/app" />    
    <property name="dir.base.app" value="${basedir}/../projeto-exemplo/app" />  

Na Listagem 3, os arquivos necessários para geração da release são, a pasta “img, css, js, app” e o arquivo “index.php”. As demais pastas do “projeto-exemplo” como, “releases e scripts” não são necessárias para release, são apenas utilizadas pelo desenvolvedor.

Criação da Release

A primeira etapa do arquivo “build.xml”, responsável pela configuração do projeto exemplo, foi finalizada com sucesso, sendo iniciado o processo de criação do projeto, com o envio das pastas e arquivos para release, concatenação e também a tarefa de comprimir os arquivos “js” e “css” e gerar a release no formato “zip”.

A Listagem 4 apresenta o primeiro método que o Ant ira executar, o qual é responsável por chamar as dependências do projeto para geração da release.

Listagem 4: Inicio do “deploy” do projeto.

 
    <!-- Iniciando o deploy -->
    <echo>Iniciando deploy do projeto ${project.name}</echo>
    <target name="deploy"
        description="realiza o deploy da aplicação"   
        depends="index, img, css, js, app, zip" >
        
        <echo>Deploy finalizado em ${dir.deploy}</echo>
    </target>   

A tag “target” é utilizada para executar suas tarefas e suas dependências.

Na Listagem 5 são apresentadas as “targets”, responsáveis por copiar o arquivo “index.php” e diretório “img, app” para a pasta do “deploy”.

Listagem 5: Target index, img e app.

 
    <target name="index" depends="clean"
        description="copia o arquivo index.php" >
        
        <echo>Copiando o arquivo index.php</echo>
        <copy file="${dir.base.index.php}"
            tofile="${dir.deploy.index.php}" 
            overwrite="true" />     
    </target>   
    
    <target name="img"
        description="copiando os arquivos da pasta img e enviado para a pasta de deploy do projeto">
        
        <echo>Copiando os arquivos da pasta ${dir.base.img} para ${dir.deploy.img}</echo>
        <mkdir dir="${dir.deploy.img}" />

        <copy todir="${dir.deploy.img}">
            <fileset dir="${dir.base.img}" />
        </copy>
    </target>   

    <target name="app"
        description="copiando os arquivos da pasta app e enviado para a pasta de deploy do projeto">
        
        <echo>Copiando os arquivos da pasta ${dir.deploy.app}</echo>
        <mkdir dir="${dir.deploy.app}" />

        <copy todir="${dir.deploy.app}" >
            <fileset dir="${dir.base.app}" />
        </copy>
    </target>

A “target img e app” são semelhantes, a única diferença é o diretório que será copiado para a pasta “deploy”.

A Listagem 6 mostra a semelhança entre as “targets js e css”, onde a única diferença é que a “target js” é responsável por mover o arquivo “loader.js”.

Listagem 6: Target js e css.

 
    <target name="js.copyright" 
        description="criando o copyright js">
    
        <echo>criando o copyright js</echo>
        <echo message="/* copyright ejs */${line.separator}" file="${dir.deploy.js}/copyright.txt"/>
    </target>   
    
    <target name="js.move" depends="js.copyright"
        description="movendo os arquivos da pasta js para a pasta de deploy do projeto e adicionando o copyright nos arquivos">
    
        <echo>Movendo os arquivos da pasta ${dir.deploy.js} para ${dir.base.js}</echo>
        <copy todir="${dir.deploy.js}" >
            <fileset dir="${dir.base.js}" />
            <filterchain>
                <concatfilter prepend="${dir.deploy.js}/copyright.txt"/>
            </filterchain>
        </copy>
    </target>   

    <target name="js.compact" depends="js.move" 
        description="concatena os js em um unico arquivo" >
        
        <echo>Construindo o compact js</echo>
        <concat destfile="${dir.deploy.js}/system/compact.js">
            <fileset dir="${dir.deploy.js}/system/" includes="*.js" />
        </concat>
        <echo>Operação de compactação do js realizada</echo>
    </target>       
    
    <target name="js.min" depends="js.compact" 
        description="minimiza os arquivos js" >
        
        <echo>Construindo o js.min</echo>
        <apply executable="java" parallel="false" verbose="true" 
            dest="${dir.deploy.js}/system">
            
            <fileset dir="${dir.deploy.js}/system" >
                <include name="compact.js" />
            </fileset>
            <arg line="-jar" />
            <arg path="${YUI}" />
            <arg value="--charset" />
            <arg value="UTF-8" />
            <arg value="-o" />
            <targetfile />
            <mapper type="glob" from="compact.js" to="compact-min.js" />
        </apply>
        <echo>Operação js.min realizada</echo>
    </target>   

    <target name="js.loader" depends="js.min" 
        description="movendo arquivo js template para a pasta de deploy" >
    
        <echo>Movendo arquivo js template para a pasta ${dir.deploy.js}</echo>
        <copy todir="${dir.deploy.js}/others" overwrite="true" >
            <fileset dir="${basedir}/templates/js/" />
        </copy>
    </target>   

    <target name="js" depends="js.loader" 
        description="excluir arquivos js não utilizados" >
        
        <echo>Excluindo arquivos js não utilizados</echo>
        <delete includeemptydirs="true">
            <fileset dir="${dir.deploy.js}/system">
                <include name="*.js"/>
                <exclude name="compact-min.js"/>
            </fileset>
        </delete>   
    </target>   

A Listagem 6 também declara a target “js”, responsável por excluir os arquivos js não utilizados pela release, destacando que esta target depende da target “js.loader”.

A target “js.loader” é responsável por mover o arquivo js template para a pasta do “deploy”, sendo dependente da target “js.min”, responsável por comprimir o arquivo “js”, deixando o mesmo em apenas uma linha. Salientando que a target “js.min” depende da target “js.compact”, a qual é responsável por concatenar todos os arquivos “js” em apenas um arquivo, porém sendo essa dependente da target “js.move”.

A target “js.move”, como o próprio nome já sugere, é responsável por enviar todos os arquivos “js” do sistema para a pasta de deploy, adicionando o conteúdo do arquivo txt copyright no inicio dos arquivos do projeto.

A Listagem 7 apresenta toda a codificação do arquivo deploy.xml, responsável pela criação da release de liberação.

Listagem 7: Arquivo “deploy.xml”.

 
<?xml version="1.0" encoding="UTF-8"?>
<project name="${project.name}" basedir="." default="deploy" >

    <!-- configurações da aplicacação -->
    <property name="project.name"        value="projeto-teste" />   
    <property name="project.vs"          value="vs.0.0.4" />    
    <property name="project.folder.save" value="release-liberacao" />   
    
    <!-- Diretório para o deploy -->
    <property name="dir.deploy" value="${basedir}/../deploy/" 
        description="diretório do deploy" />   
    
    <!-- YUICompressor -->
    <property name="YUI" value="${basedir}/yui/yuicompressor-2.4.2.jar" 
        description="YUICompressor" />  
        
    <!-- Diretório dos templates -->
    <property name="dir.templates" value="${basedir}/templates/" />
    <property name="dir.templates.js" value="${dir.templates}/js/" />
    <property name="js.loader" value="loader.js" />     

    <!-- Index da Aplicação -->
    <property name="dir.deploy.index.php" value="${dir.deploy}/index.php" />    
    <property name="dir.base.index.php" value="${basedir}/../projeto-exemplo/index.php" />  

    <!-- Localização das pastas padrões do projeto -->
    <property name="dir.deploy.img" value="${dir.deploy}/img" />    
    <property name="dir.base.img" value="${basedir}/../projeto-exemplo/img" />  
    
    <property name="dir.deploy.css" value="${dir.deploy}/css" />    
    <property name="dir.base.css" value="${basedir}/../projeto-exemplo/css" />  

    <property name="dir.deploy.js"  value="${dir.deploy}/js"  />    
    <property name="dir.base.js"  value="${basedir}/../projeto-exemplo/js"  />  

    <property name="dir.deploy.app" value="${dir.deploy}/app" />    
    <property name="dir.base.app" value="${basedir}/../projeto-exemplo/app" />  
    
    <!-- INIT -->
    
    <!-- Iniciando o deploy -->
    <echo>Iniciando deploy do projeto ${project.name}</echo>
    <target name="deploy"
        description="realiza o deploy da aplicação"   
        depends="index, img, css, js, app, zip" >
        
        <echo>Deploy finalizado em ${dir.deploy}</echo>
    </target>   
    
    <target name="index" depends="clean"
        description="copia o arquivo index.php" >
        
        <echo>Copiando o arquivo index.php</echo>
        <copy file="${dir.base.index.php}"
            tofile="${dir.deploy.index.php}" 
            overwrite="true" />     
    </target>   
    
    <target name="img"
        description="copiando os arquivos da pasta img e enviado para a pasta de deploy do projeto">
        
        <echo>Copiando os arquivos da pasta ${dir.base.img} para ${dir.deploy.img}</echo>
        <mkdir dir="${dir.deploy.img}" />

        <copy todir="${dir.deploy.img}">
            <fileset dir="${dir.base.img}" />
        </copy>
    </target>       
    
    <target name="css.copyright" 
        description="criando o copyright css">
    
        <echo>criando o copyright css</echo>
        <echo message="/* copyright ecss */${line.separator}" file="${dir.deploy.css}/copyright.txt"/>
    </target>   

    <target name="css.move" depends="css.copyright"
        description="movendo os arquivos da pasta css para a pasta de deploy do projeto e adicionando o copyright nos arquivos">
        
        <echo>Movendo os arquivos da pasta ${dir.deploy.css} para ${dir.base.css}</echo>
        <copy todir="${dir.deploy.css}" >
            <fileset dir="${dir.base.css}" />
            <filterchain>
                <concatfilter prepend="${dir.deploy.css}/copyright.txt"/>
            </filterchain>
        </copy>
    </target>

    <target name="css.compact" depends="css.move" 
        description="concatena os css em um unico arquivo" >
        
        <echo>Construindo o css compactado</echo>
        <concat destfile="${dir.deploy.css}/system/style.css">
            <fileset dir="${dir.base.css}/system/" includes="*.css" />
        </concat>
        <echo>Operação de compactação do css realizada</echo>
    </target>   
    
    <target name="css.min" depends="css.compact" 
        description="minimiza os arquivos css" >
        
        <echo>Construindo o css.min</echo>
        <apply executable="java" parallel="false" verbose="true" 
            dest="${dir.deploy.css}/system">
            
            <fileset dir="${dir.deploy.css}/system" >
                <include name="style.css" />
            </fileset>
            <arg line="-jar" />
            <arg path="${YUI}" />
            <arg value="--charset" />
            <arg value="UTF-8" />
            <arg value="-o" />
            <targetfile />
            <mapper type="glob" from="style.css" to="style-min.css" />
        </apply>
        <echo>Operação css.min realizada</echo>
    </target>   
    
    <target name="css" depends="css.min" 
        description="excluir arquivos css não utilizados" >
        
        <echo>Excluindo arquivos css não utilizados</echo>
        <delete includeemptydirs="true">
            <fileset dir="${dir.deploy.css}/system">
                <include name="*.css"/>
                <exclude name="style-min.css"/>
            </fileset>
        </delete>       
    </target>   

    <target name="js.copyright" 
        description="criando o copyright js">
    
        <echo>criando o copyright js</echo>
        <echo message="/* copyright ejs */${line.separator}" file="${dir.deploy.js}/copyright.txt"/>
    </target>   
    
    <target name="js.move" depends="js.copyright"
        description="movendo os arquivos da pasta js para a pasta de deploy do projeto e adicionando o copyright nos arquivos">
    
        <echo>Movendo os arquivos da pasta ${dir.deploy.js} para ${dir.base.js}</echo>
        <copy todir="${dir.deploy.js}" >
            <fileset dir="${dir.base.js}" />
            <filterchain>
                <concatfilter prepend="${dir.deploy.js}/copyright.txt"/>
            </filterchain>
        </copy>
    </target>   

    <target name="js.compact" depends="js.move" 
        description="concatena os js em um unico arquivo" >
        
        <echo>Construindo o compact js</echo>
        <concat destfile="${dir.deploy.js}/system/compact.js">
            <fileset dir="${dir.deploy.js}/system/" includes="*.js" />
        </concat>
        <echo>Operação de compactação do js realizada</echo>
    </target>       
    
    <target name="js.min" depends="js.compact" 
        description="minimiza os arquivos js" >
        
        <echo>Construindo o js.min</echo>
        <apply executable="java" parallel="false" verbose="true" 
            dest="${dir.deploy.js}/system">
            
            <fileset dir="${dir.deploy.js}/system" >
                <include name="compact.js" />
            </fileset>
            <arg line="-jar" />
            <arg path="${YUI}" />
            <arg value="--charset" />
            <arg value="UTF-8" />
            <arg value="-o" />
            <targetfile />
            <mapper type="glob" from="compact.js" to="compact-min.js" />
        </apply>
        <echo>Operação js.min realizada</echo>
    </target>   

    <target name="js.loader" depends="js.min" 
        description="movendo arquivo js template para a pasta de deploy" >
    
        <echo>Movendo arquivo js template para a pasta ${dir.deploy.js}</echo>
        <copy todir="${dir.deploy.js}/others" overwrite="true" >
            <fileset dir="${basedir}/templates/js/" />
        </copy>
    </target>   

    <target name="js" depends="js.loader" 
        description="excluir arquivos js não utilizados" >
        
        <echo>Excluindo arquivos js não utilizados</echo>
        <delete includeemptydirs="true">
            <fileset dir="${dir.deploy.js}/system">
                <include name="*.js"/>
                <exclude name="compact-min.js"/>
            </fileset>
        </delete>   
    </target>   
    
    <target name="app"
        description="copiando os arquivos da pasta app e enviado para a pasta de deploy do projeto">
        
        <echo>Copiando os arquivos da pasta ${dir.deploy.app}</echo>
        <mkdir dir="${dir.deploy.app}" />

        <copy todir="${dir.deploy.app}" >
            <fileset dir="${dir.base.app}" />
        </copy>
    </target>

    <target name="clean" 
        description="recriando diretório de deploy" >
        
        <reset-dir dir="${dir.deploy}" 
            description="recriando diretório de deploy" />     
    </target>       
    
    <macrodef name="reset-dir"
        description="reseta o diretório deploy" >
        
        <attribute name="dir" />
        <sequential>
            <delete dir="@{dir}" />
            <mkdir dir="@{dir}" />
        </sequential>
    </macrodef> 
    
    <target name="zip" 
        description="compacta o projeto em um arquivo ZIP">
        
        <echo>Compactando os arquivos</echo>        
        <zip destfile="${dir.deploy}/../${project.folder.save}/${project.name}.${project.vs}.zip">
            <zipfileset dir="${dir.deploy}" prefix="${project.name}.${project.vs}" />
        </zip>

        <delete dir="${dir.deploy}" />
    </target>
    
</project>

A Listagem 7 traz a target zip, responsável por zipar a release do projeto, também a target clean, responsável por deletar a pasta “deploy”.

Conclusão

No artigo foi abordada de forma prática e didática a utilização da ferramenta Ant, da comunidade Apache.

Apresentando a equipes de desenvolvimento a possibilidade de criação de releases do projeto para disponibilização a clientes na implantação e atualização de produtos.

Espero que todos os leitores tenham gostado e possam utilizar a aplicação exemplificada em suas próprias aplicações.

Continuo à disposição para esclarecimento de dúvidas e aberto a sugestões para novos posts.

O projeto desenvolvido para o artigo pode ser baixado no topo desse artigo ou se preferir ser visto no GitHub.

Obrigado e um abraço!

Agradecimentos

Amiga e Colega Ivânia pela correção do artigo e por estar sempre colaborando no enriquecimento dos mesmos.

 
Você precisa estar logado para dar um feedback. Clique aqui para efetuar o login
Receba nossas novidades
Ficou com alguma dúvida?