Março 3rd 2008 02:11 pm
Integração contínua com CruiseControl + phpUnderControl
"Continuous Integration is a software development practice where members of a team integrate their work frequently, usually each person integrates at least daily, leading to multiple integrations per day. Each integration is verified by an automated build (including test) to detect integration errors as quickly as possible. Many teams find that this approach leads to significantly reduced integration problems and allows a team to develop cohesive software more rapidly."
Neste post pretendo apresentar algumas ferramentas que facilitam a utilização da Integração Contínua, como prática de desenvolvimento de seus projetos.
O CruiseControl é uma ferramenta que automatiza o processo de build, provendo várias tarefas que facilitam o controle sobre o código, incluindo uma interface para visualizar os detalhes sobre cada build.
O phpUnderControl é um plugin para o CruiseControl que facilita a integração de algumas ferramentas voltadas para projetos PHP: phpDocumentor, PHPUnit, PHP_CodeSniffer.
Instalação
Primeiro precisamos fazer o download e a instalação do CruiseControl.
$ wget http://ufpr.dl.sourceforge.net/sourceforge/cruisecontrol/cruisecontrol-bin-2.7.1.zip
$ unzip cruisecontrol-bin-2.7.1.zip -d /opt/
O CruiseControl é uma ferramenta que fica trabalhando em background, seu processo fica executando builds configurados através do arquivo de configuração chamado config.xml onde podemos definir o intervalo com que cada build será executado, para iniciar o CruiseControl precisamos apenas executa-lo. É necessário ter o java instalado em seu computador para que o CruiseControl rode.
$ /opt/cruisecontrol-bin-2.7.1/cruisecontrol.sh
Se tudo correu como o esperado, você pode acessar http://localhost:8080/, deverá ter um projeto já existente de exemplo, chamado connectfour.
Antes de proseguir com a instalação do phpUnderControl, iremos instalar o phpDocumentor e ao PHP_CodeSniffer. Iremos precisar também do PHPUnit, caso não tenha instalado em seu computador ainda, leia este post onde explico como fazer isso.
$ wget http://ufpr.dl.sourceforge.net/sourceforge/phpdocu/PhpDocumentor-1.4.1.tgz
$ tar zxf PhpDocumentor-1.4.1.tgz
$ mv PhpDocumentor-1.4.1 /opt/phpdoc
$ pear install PHP_CodeSniffer
Aqui, vale lembrar que as três ferramentas (phpDocumentor, PHP_CodeSniffer e o PHPUnit) devem estar no PATH de seu sistema. O executável do phpDocumentor (phpdoc) você pode encontrar em /opt/phpdoc e o executável do PHP_CodeSniffer (phpcs) você pode encontrar na pasta bin do PHP. Outro detalhe, não esqueça de configurar o diretório do PEAR no include path do PHP (eu havia esquecido :)).
Agora vamos ao phpUnderControl
$ svn co svn://svn.phpunit.de/phpunit/phpUnderControl/trunk /opt/phpUnderControl #download do projeto
$ /opt/phpUnderControl/bin/phpuc.php install /opt/cruisecontrol-bin-2.7.1 #instalando no CruiseControl
Feito isso, você poderá acessar novamente http://localhost:8080/ e ver que os estilos do CruiseControl foram modificados.
Criando um projeto de exemplo
O phpUnderControl é capaz de criar um projeto de exemplo, uma espécie de "esqueleto" para você não ter que criar todos os arquivos na mão. Para isso iremos executar o seguinte comando.
$ /opt/phpUnderControl/bin/phpuc.php example --project-name blog /opt/cruisecontrol-bin-2.7.1
onde:
- example - opção que cria um projeto de exeplo
- --project-name - serve para definirmos o nome do projeto, no exemplo acima utilizei o nome "blog"
- /opt/cruisecontrol-bin-2.7.1 - é o workspace configurado pelo CruiseControl. (é possivel configurar em outra localização)
Após isso é possível ver o novo projeto criado pelo browser, acessando http://localhost:8080
Se clicarmos sobre o projeto é possivel ver as informações dele, por padrão o projeto vem com alguns erros nos testes unitários. Isso faz com que seu build não seja feito com sucesso. Podemos ver essas informações através do link Metrics;
Ok, agora vamos fazer algumas modificações em nosso projeto para ter nosso primeiro build com sucesso.
Abra o arquivo /opt/cruisecontrol-bin-2.7.1/projects/blog/source/tests/MathTest.php e na linha 92 faça a seguinte alteração.
Substitua isso.
-
$this->assertEquals(0, $this->math->sub(2,1));
Por isso:
-
$this->assertEquals(1, $this->math->sub(2,1));
Após isso remova o método testFail da linha 95 à 102 (provavelmente).
Após fazer isso vá novamente a página inicial do phpUnderControl e force um novo build, clicando no link abaixo do nome de seu projeto. Após alguns instantes você poderá ver que seu novo build foi feito com sucesso.
Navegando pelas estatísticas do projeto é possível ver que existem alguns warnings e alguns erros gerados pelo CodeSniffer e pelo PHPUnit PMD, estes erros normalmente são gerados por o código do projeto não está escrito no devido padrão definido no projeto.
O PHPUnit PMD é capaz de fazer a detecção de Copy&Paste, isso é muito util para podermos refatorar a duplicação do código no projeto, no projeto de exemplo que criamos, é possivel ver um exemplo da detecção do PMD através do link PHPUnit PMD.
Arquivos de configuração
O CruiseControl pode ser configurado apartir do arquivo config.xml que está dentro do diretório /opt/cruisecontrol-bin-2.7.1, este é o arquivo onde são configurados os projetos existentes em seu workspace. Quando executamos o comando do phpUnderControl para criar um novo projeto, são adicionadas novas entradas neste arquivo, com as configurações iniciais de nosso projeto. Ex.:
Para o projetos que criamos acima as entradas adicionadas foram:
-
<project name="blog" buildafterfailed="false">
-
<listeners>
-
<currentbuildstatuslistener file="logs/${project.name}/status.txt"/>
-
</listeners>
-
<modificationset>
-
<alwaysbuild/>
-
</modificationset>
-
<schedule interval="300">
-
<ant anthome="apache-ant-1.7.0" buildfile="projects/${project.name}/build.xml"/>
-
</schedule>
-
<log dir="logs/${project.name}">
-
<merge dir="projects/${project.name}/build/logs/"/>
-
</log>
-
<publishers>
-
<currentbuildstatuspublisher file="logs/${project.name}/buildstatus.txt"/>
-
<artifactspublisher dir="projects/${project.name}/build/api" dest="artifacts/${project.name}" subdirectory="api"/>
-
<artifactspublisher dir="projects/${project.name}/build/coverage" dest="artifacts/${project.name}" subdirectory="coverage"/>
-
<execute command="/opt/phpUnderControl/src/../bin/phpuc.php graph logs/${project.name} artifacts/${project.name}"/>
-
</publishers>
-
</project>
Uma configuração importante deste arquivo, é o intervalo de tempo com que o CruiseControl irá gerar um novo build de nossa aplicação, este tempo é definido em segundos através da tag
-
<schedule interval="300">
Para cada novo projeto que criamos, existe um arquivo de configuração com as peculiaridades de cada projeto, este arquivo - normalmente chamado build.xml - é executado pelo Ant (ferramenta de build default para o CruiseControl), para o projeto que criamos este arquivo pode ser encontrado no diretório /opt/cruisecontrol-bin-2.7.1/projects/blog. Ex.:
-
<project name="blog" default="build" basedir=".">
-
<target name="build" depends="php-documentor,php-codesniffer,phpunit"/>
-
<target name="php-documentor">
-
<exec executable="phpdoc" dir="${basedir}/source" logerror="on">
-
<arg line="--title '${ant.project.name}' -ue on -t ${basedir}/build/api -d . -tb '/opt/phpUnderControl/data/phpdoc' -o HTML:Phpuc:phpuc"/>
-
</exec>
-
</target>
-
<target name="php-codesniffer">
-
<exec executable="phpcs" dir="${basedir}/source" output="${basedir}/build/logs/checkstyle.xml">
-
<arg line="--report=checkstyle --standard=PEAR ."/>
-
</exec>
-
</target>
-
<target name="phpunit">
-
<exec executable="phpunit" dir="${basedir}/source" failonerror="on">
-
<arg line=" --log-xml ${basedir}/build/logs/phpunit.xml --log-pmd ${basedir}/build/logs/phpunit.pmd.xml --log-metrics ${basedir}/build/logs/phpunit.metrics.xml --coverage-xml ${basedir}/build/logs/phpunit.coverage.xml --coverage-html ${basedir}/build/coverage PhpUnderControl_Example_MathTest tests/MathTest.php"/>
-
</exec>
-
</target>
-
</project>
No arquivo criado para nosso projeto existem basicamente três tarefas configuradas, a execução do php-documentor, php-codesniffer e o phpunit. Um detalhe aqui neste arquivo é a execução do PHPUnit. Na tag exec existe um atributo chamado failonerror que por padrão vem setado para "on". Isto faz com que o build falhe caso a execução de seus testes possua algum teste com falha ou gere um erro.
É possivel adicionar muitas tarefas ao build de seus projeto apartir deste arquivo (mover diretórios, mandar e-mail, criar arquivos, etc), para saber como fazer isso, recomendo a leitura do manual do Ant, disponível em http://ant.apache.org/manual/index.html.
Estas ferramentas que apresentei são de grande importância para gerenciarmos a qualidade de nosso projetos, nem que eu quisesse, conseguiria abordar aqui todas as funcionalidades dessas ferramentas, nem todas as vantagens de utilizar Integração Contínua, mas espero ter sido claro.
Certamente haverão duvidas, caso eu possa ajudar estou a disposição.
Abraço a todos.
7 Comments »














Fábio T. da Costa on 03 Mar 2008 at 16:49 #
Olá Diego,
Achei muito interessante o phpunderControl, tive problemas com o PATH do PEAR mas já resolvi. Outro erro que estava dando é que faltava o xdebug, então instalei usando o pecl e aí funcionou tudo corretamente e sem erros.
Tenho uma (grande) dúvida:
Para usar o phpUnderControl nos projetos já existentes aqui da empresa, o que eu teria que fazer?
Usar o comando “example –project-name” para gerar o esqueleto da aplicação ?
Vi que é criado as pastas “builds” e “sources/src” e “sources/tests”. Tem como eu setar estas duas últimas pastas citadas para que elas apontem para os diretórios das aplicações que ficam dentro do htdocs do apache?
Obrigado
Diego Tremper on 04 Mar 2008 at 00:50 #
Olá Fábio,
no arquivo build.xml de seu projeto, você pode fazer da seguinte forma.
Criar uma task property do Ant, configurar o caminho dos códigos de sua aplicação.
ex.:
< project name="blog" default="build" basedir=".">
…
< property name="srcdir" value="/PATH/PARA/SEU/CODIGO"/>
…
< target name="build" depends="php-documentor,php-codesniffer,phpunit"/>
ai configurar as aplicações para apontarem para o caminho que você setou:
…
< exec executable="phpdoc" dir="${srcdir}" logerror="on">
< exec executable="phpcs" dir="${srcdir}" output="${basedir}/build/logs/checkstyle.xml">
< exec executable="phpunit" dir="${srcdir}" failonerror="on">
…
[]’s
Fábio T. da Costa on 06 Mar 2008 at 14:34 #
Certo Diego,
Deu certo mesmo isso, só setei o diretório como sendo o srcdir que funcionou perfeitamente.
Obrigado.
Willian V. on 14 Out 2008 at 17:59 #
Olá Diego,
Instalei o CC e o phpUnderControl.
Rodei o exemplo do Blog que você citou acima. Sem problemas.
O problema é direcionar o phpUnderControl para rodar minha aplicação.
Gero um exemplo e neste exemplo coloco no build.xml as referências para a minha aplicação? Esta é a única maneira?
[]s
WV
Diego Tremper on 14 Out 2008 at 20:45 #
A princípio, o phpUnderControl não deveria estar rodando sua aplicação a partir dos diretórios em que você está trabalhando, você deve utilizar um sistema de controle de versão (CVS, SVN,…) e configurar o build para fazer uma cópia local de tempos em tempos para o diretório do CC. Para configurar seu build para fazer a cópia do repositório, você pode utilizar o phpundercontrol na linha de comando, de maneira semelhante como cria um projeto de exemplo.
Ex.:
phpuc.php project –project-name meu_projeto –version-control svn –version-control-url http://meurepositorio –username username_svn –password senha_svn
Existem outras opções disponíveis, você pode olha o help do comando project “phpec.php project –help”
[]s
Willian V. on 15 Out 2008 at 16:50 #
Olá
É que não estou usando um controle de versão. Estou rodando tudo na mesma máquina.
Estou tentando entender o funcionamento da ferramenta antes de colocar na parte de produção.
Queria analisar seu funcionamento.
Assim como o Fábio comentou, só que não consegui fazer o mesmo que ele.
Tem como fazer isso sem um Controle de versão ou é obrigatório o seu uso?
Diego Tremper on 22 Out 2008 at 23:30 #
Sim, tem como fazer isso, você pode fazer com que o CruiseControl (config.xml) e o Ant (build.xml) apontem para os diretórios onde está sua aplicação. Porém, não recomendo que faça isso, pois não é recomendável que as ferramentas fiquem trabalhando nos mesmos arquivos que você está trabalhando.
O solução para isso, seria você configurar o seu script do Ant para fazer uma cópia dos arquivos dos diretórios onde estão sua aplicação, para dentro do diretório project do CruiseControl, você pode fazer isso utilizando a task copy do Ant (http://ant.apache.org/manual/CoreTasks/copy.html).
Ex.:
< target name="copiar"> < copy todir="/opt/cruisecontrol/projects/(seu projeto)/source"> < fileset dir="/caminho/diretorio/seu/codigo"/> < /copy> < /target>Abraço