NAnt: To Work and Beyond

Publicado por Fabio A. Falavinha
02/2/2011
Categoria:
Tags: , , ,

Desenvolver software não é uma tarefa simples. Ainda mais realizar o trabalho de deploy, após um bom tempo de escrita de código e testes. O que vou dizer nas próximas linhas, não foi baseado em estatísticas: todo desenvolvedor, não importa a linguagem ou plataforma que ele trabalhe, já desenvolveu por alguns minutos ou horas, scripts para a execução do deploy de sua aplicação ou parte dela (componentes, bibliotecas, outros recursos).

Automatizar o trabalho de deploy, incluindo compilação e empacotamento da aplicação, não é uma tarefa fácil se você conhece apenas o editor visual que utiliza para desenvolver suas aplicações. Não vou entrar em discussão, pois fere a ética de muitos desenvolvedores. Mas, aprender a compilar e realizar o deploy através da “antiga” (e não obsoleta) linha de comando é obrigatório!

Neste artigo vou descrever o uso da ferramenta NAnt para automação do processo de deploy de uma aplicação ASP.NET. Note, que a ênfase será dada ao script criado e não para o desenvolvimento da aplicação.

A ferramenta NAnt foi portada da versão da ferramenta Apache Ant, desenvolvida em Java, e muito disseminada entre os desenvolvedores Java e da plataforma Linux.

A ferramenta NAnt é baseada em tasks que são descritas por classes, ou seja, uma task pode ser extendida para atender uma necessidade específica. Portanto, não há necessidade de escrever comandos, pois, as tasks são escritas pelo desenvolvedor em um arquivo XML, onde estas são organizadas em targets, que serão executados conforme a ordem informada no arquivo de configuração.

Por ser extensível e baseada em tasks, a ferramenta NAnt pode ser executada em qualquer plataforma (sistema operacional onde rode o framework .NET), garantindo a mesma forma de execução. Com isso, o desenvolvedor não perde tempo para reescrever os comandos utilizados, pois todos são abstraídos em um conjunto de tasks.

Para este artigo será utilizado a versão NAnt 0.91 Alpha 2 e o framework .NET 3.5 tudo rodando em um Windows 7 Professional 64 bits.

Instalando o NAnt

Faça o download no site da ferramenta NAnt da versão utilizada neste artigo ou superior.
Após o download, descompacte o arquivo em um diretório qualquer e adicone na variável de sistema PATH o caminho da ferramenta NAnt até o subdiretório bin.


D:/Tools/DotNet/NAnt 0.91 Alpha 2/bin

Configuração do NAnt

Compilando uma aplicação ASP.NET

A ferramenta NAnt disponibiliza uma task chamada <solution /> para realizar a compilação de uma solução .NET, porém, as únicas versões do Visual Studio suportadas são; 2002 e 2003. Caso, a versão do Visual Studio seja superior a estas, não se desespere. Há um forma bem simples de utilizar os comandos utilitários do framework .NET para realizar esta tarefa, integrados com o NAnt:

@ECHO OFF

if /i {%1} == {} goto :params
if /i {%2} == {} goto :params

ECHO Using the following parameters:
ECHO Target: %1
ECHO Configuration: %2

C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe D:\Projects\MyProject\MyProject.sln /t:Clean
C:\Windows\Microsoft.NET\Framework\v3.5\MSBuild.exe D:\Projects\MyProject\MyProject.sln /t:Rebuild /p:Configuration=%2;AspNetConfiguration=Release

ECHO About to deploy Web project to %1

C:\Windows\Microsoft.NET\Framework\v2.0.50727\Aspnet_compiler.exe -f -p D:\Projects\MyProject\MyProject -v / %1\MyProject

ECHO Finish

goto :end

:params
ECHO Syntax: %0 [target] [configuration]
ECHO Example: %0 D:\Runtime\ DEBUG

:end

O script acima descreve como compilar e fazer o deploy de uma aplicação ASP.NET através dos comandos utilitários do framework .NET. Este script recebe dois argumentos: o diretório para deploy da aplicação ASP.NET e a configuração na qual o projeto será gerado, por exemplo: Debug ou Release.
Mas, como integrar este script BAT com a ferramenta NAnt?
O primeiro passo é criar um arquivo de extensão .build, com o código abaixo:

<?xml version="1.0"?>
<project name="Build MyProject" default="compile">

  <property name="deploy.dir" value="D:\Deploy"/>
  <property name="projectConfiguration" value="Release" />

  <target name="compile">
    <exec program="compile-myproject.bat" basedir="${project::get-base-directory()}">
      <arg value="${deploy.dir}" />
      <arg value="${projectConfiguration}" />
    </exec>
  </target>

</project>

O script NAnt começa com a tag <project /> no qual define um projeto para o qual será realizado um conjunto de operações através da execução de targets e tasks. Note, que o atributo default informa o target a ser executado, ou seja, tudo começa por ele. A partir dele, outros targets podem ser executados, basta realizar a configuração correta.

Um target foi definido com o nome compile, no qual organiza o contexto para a chamada das tasks para compilação do projeto. A partir deste ponto, foi utilizado a task <exec /> que realiza a execução de arquivos externos a ferramenta NAnt, como por exemplo: arquivos BAT e EXE.
Observe que a task <exec /> define o programa a ser executado através do atributo program e o diretório no qual encontra-se este arquivo através do atributo basedir. Para os argumentos, informamos o diretório de deploy e a configuração na qual o projeto será gerado. Mas, notem que uma notação  é utilizada para informar os valores de forma dinâmica aos atributos da tag <exec /> e <arg />. As notações utilizam a passagem de variáveis, definidas como propriedades através da tag <property />. Esta prática garante flexibilidade e reuso das tasks no decorrer do script, pois muitos targets podem ser reutilizados dentro do mesmo script com valores diferentes. Um detalhe interessante é o uso da função project::get-base-directory. Esta função é definida pelo framework NAnt, e recupera o diretório atual de execução do script.

Outros Recursos

O passo mais complicado de compilar e realizar o deploy de um aplicação ASP.NET foi realizado. Outros recursos podem ser utilizados para aprimorar e facilitar a tareta de deploy, como:

Apagar diretórios, arquivos

<?xml version="1.0"?>
<project name="Clean up MyProject" default="clean">

  <property name="deploy.dir" value="D:\Deploy"/>
  <property name="zipName" value="MyProject"/>
  <property name="applicationName" value="MyProject"/>

  <target name="clean">
    <delete>
      <fileset>
        <include name="${deploy.dir}/${zipName}.zip"/>
      </fileset>
    </delete>
    <delete dir="${deploy.dir}/${applicationName}" />
  </target>

</project>

Compactar (ZIP) e descompactar (UNZIP)

<?xml version="1.0"?>
<project name="Zip/Unzip MyProject">

  <property name="deploy.dir" value="D:\Deploy"/>
  <property name="zipName" value="MyProject"/>
  <property name="applicationName" value="MyProject"/>

  <target name="clean">
    <delete>
      <fileset>
        <include name="${deploy.dir}/${zipName}.zip"/>
      </fileset>
    </delete>
    <delete dir="${deploy.dir}/${applicationName}" />
  </target>

  <target name="zip" depends="clean">
    <zip zipfile="${deploy.dir}/${zipName}.zip">
      <fileset basedir="${deploy.dir}/${applicationName}">
        <include name="**/*" />
      </fileset>
    </zip>
  </target>

  <target name="unzip">
    <unzip zipfile="${deploy.dir}/${zipName}.zip"/>
  </target>

</project>

Note que o código acima, executa duas tarefas de forma sequencial, ou seja, o target zip tem uma dependência para o target clean, no qual será executado primeiro, para depois executar a tarefa de compactação do diretório de deploy.

Outro ponto importante a ser visto neste script é que não foi definido um target padrão (default) para execução. Neste caso, basta informar na linha de comando ao executar o script NAnt:


nant -buildfile:myproject.build zip

ou

nant -buildfile:myproject.build unzip

Enviar pacotes, arquivos através de FTP

<?xml version="1.0"?>
<project name="Zip/Unzip MyProject">

  <property name="deploy.dir" value="D:\Deploy"/>
  <property name="zipName" value="MyProject"/>
  <property name="applicationName" value="MyProject"/>

  <target name="clean">
    <delete>
      <fileset>
        <include name="${deploy.dir}/${zipName}.zip"/>
      </fileset>
    </delete>
    <delete dir="${deploy.dir}/${applicationName}" />
  </target>

  <target name="zip" depends="clean">
    <zip zipfile="${deploy.dir}/${zipName}.zip">
      <fileset basedir="${deploy.dir}/${applicationName}">
        <include name="**/*" />
      </fileset>
    </zip>
  </target>

  <target name="unzip">
    <unzip zipfile="${deploy.dir}/${zipName}.zip"/>
  </target>

  <target name="ftp" depends="zip">
    <loadtasks assembly="D:\Tools\NAnt\nant-0.91-alpha2\tasks\ftp\bin\Release\ftptask.dll" />
    <connection id="ftp-server-connection" server="server" username="user" password="password" />							<echo message="The application is being deployed to server..." />
    <ftp connection="ftp-server-connection" connectmode="PASSIVE">
      <put type="bin" localdir="${deploy.dir}" remotedir="MyCompanyFiles" flatten="false">
        <include name="${zipName}.zip"/>
      </put>
    </ftp>
    <echo message="The application was deployed to server!" />
  </target>

</project>

Utilizar FTP com NAnt não é uma tarefa simples, pois a ferramenta não disponibiliza uma task nativa. Para fazer isso, pesquisei algumas opções antes de começar a desenvolver a minha própria solução. Encontrei uma solução chamada FTP Task. Após fazer o download desta task, basta descompactar e colocar as DLLs em diretório de sua preferência e utilizar a tag <loadtasks /> para carregar as classes desta task, conforme o exemplo acima.
As tags <connection />, <ftp /> e <put /> estão descritas dentro da DLL ftptask.dll.
Mais uma vez, foi utilizado o atributo depends para realizar tarefas de forma sequencial. Neste caso o target ftp depende do resultado gerado pelo target zip.

Integrar ao sistema de versionamento: SVN

<?xml version="1.0"?>
<project name="Zip/Unzip MyProject">

<?xml version="1.0"?>
<project name="Integrate with SVN" default="svn-update">

  <property name="project.svn.url" value="https://svn.mycompany/MyProject/Trunk" />

  <target name="svn-update">
    <loadtasks assembly="D:/Tools/NAnt/nantcontrib-0.85/bin/NAnt.Contrib.Tasks.dll" />
    <svn-update destination="${project::get-base-directory()}" uri="${project.svn.url}" />
  </target>

</project>

O script acima descreve como atualizar o código do projeto que está sendo versionado pelo SVN. Utilizando a tasks do projeto NAntContrib e carregando a task <svn-update /> através da tag <loadtasks />, basta informar o diretório destino destination e a url de localização do projeto no SVN uri.

Conclusão

Automatizar o processo de deploy ou outros processos no desenvolvimento de software é primordial para a produção rápida e controlada na criação de software.

Mas, não apenas para o desenvolvimento de software a automação de nossas tarefas, via NAnt, pode ser utilizada, tudo aquilo que for considerado um processo árduo, pode ser simplificado com esta ferramenta ou até mesmo utilizando outras como o caso de Shell scripts e BAT scripts.

Referências





Desenvolvido por hacklab/ com WordPress