Cada desenvolvedor é diferente, porém o ambiente da sua equipe de desenvolvimento não precisa ser. Um aplicativo web moderno usa muitas tecnologias diferentes. As dependências comuns para um ambiente de desenvolvimento web funcionar incluem PHP e suas extensões necessárias, um servidor web, um banco de dados, frameworks de testes, e outros aplicativos e serviços. A abordagem clássica para ajudar uma equipe de desenvolvedores é implementar um servidor e instalar todos os pacotes necessários para o desenvolvimento. Essa metodologia fornece um ambiente consistente para todos os desenvolvedores da equipe, garantindo que todos os colaboradores recebam a mesma experiência durante todo o ciclo do desenvolvimento. No entanto, tão consistente quanto um desenvolvimento homogêneo e remoto pode ser, o desenvolvimento remoto apresenta uma série de problemas, incluindo sacrifícios de velocidade e uma dependência desagradável de uma conexão confiável à Internet. Também é difícil consertar os pacotes experimentais quando você sabe que isso poderia afetar o ambiente de todos em sua equipe.
Navegar por um sistema de arquivos remoto a fim de encontrar o arquivo que deseja editar pode ser complicado. Muitos editores de texto e IDEs possuem recursos que buscam atenuar essa dificuldade, porém nunca encontrei um que funcionasse de forma confiável e que fosse comparável à velocidade de desenvolvimento local. Salvar um arquivo em uma rede pode apresentar atraso que se soma a uma quantidade significativa de perda de produtividade com o tempo. Deixando a navegação de arquivo, nada supera a velocidade de trabalhar localmente. Para trabalhar em sua máquina local, você tem que instalar todos os pacotes que a equipe está usando, e cada membro precisa fazer isso também. Essa abordagem introduz inconsistência. Como desenvolvedores, nós procuramos consistência, velocidade e, apesar de amarmos a Internet, gostaríamos de ser capazes de trabalhar sem ela às vezes. Então, o que fazemos? Nós construímos uma máquina dentro de uma máquina que funciona em todas as plataformas e garante homogeneidade em ambientes de desenvolvimento.
Graças aos avanços da tecnologia de virtualização e da comunidade open source, existe uma série de ferramentas gratuitas que qualquer pessoa pode aproveitar para facilitar o fornecimento de máquinas virtuais consistentes para sua equipe.
VirtualBox, Vagrant e Puppet
Existem alguns aplicativos que são necessários para começar. VirtualBox é um software de virtualização de hardware que permite que você execute outro sistema operacional em sua máquina local. Já Vagrant é um conjunto de scripts que permite que você manipule facilmente essas máquinas virtuais a partir da linha de comando. E, por fim, Puppet permite definir quais alterações de configuração devem ser feitas para que a máquina funcione como você gostaria.
Instale o VirtualBox
Baixe e instale o VirtualBox. Agora você está pronto para instalar qualquer sistema operacional e executá-lo localmente.
Instale o Vagrant
Vagrant é uma ferramenta de linha de comando para a construção e a distribuição de ambientes de desenvolvimento virtualizados com VirtualBox. Executando apenas poucos comandos, você pode baixar e fornecer uma máquina virtual que corresponde à de sua equipe.
O Ruby e seu gerenciador de pacotes RubyGems são necessários para dar início ao Vagrant.
Uma vez que Ruby e RubyGems são instalados, execute o seguinte comando em sua máquina local para garantir que seus pacotes estão atualizados.
gem update --system
Para instalar Vagrant, emita o seguinte comando na sua máquina local:
gem install vagrant
Configure Vagrant
Assumindo que tudo correu bem, configurar Vagrant deve ser fácil. Eu criei um exemplo Vagrantfile e uma configuração Puppet de base para fornecer uma máquina com Apache, MySQL, PHP, MySQL, Xdebug, PEAR, CodeSniffer PHP, e PHPUnit. Você pode clonar meu repositório.
Depois de ter clonado o repositório de exemplo, é hora de instalar a imagem do Vagrant. O comando a seguir irá baixar a caixa pela Internet e armazená-la em cache. É um download de 300 MB, mas você só precisa fazer isso uma vez.
vagrant box add base http://files.vagrantup.com/lucid32.box
O próximo passo é modificar seu Vagrantfile. Sua configuração irá transmitir as portas de sua máquina local para a máquina virtual, montar uma pasta local de sua escolha dentro de sua VM, e inicializar Puppet como seu provedor padrão. Já fiz isso para você.
Existem algumas diretrizes de configuração importantes no Vagrantfile. Vamos dar uma olhada.
# This enables Puppet as the default provisioner config.vm.provision :puppet # For verbose output, and you wish to do a dry run, substitute this line config.vm.provision :puppet, :options => "--verbose --debug"
Depois que o provisionamento estiver completo, você vai acessar o ambiente LAMP do seu navegador via http://localhost:8080/. A seguinte linha é a mágica que faz isso:
config.vm.forward_port "http", 80, 8080
Já que todo esse exercício existe para trabalhar com arquivos locais que são fornecidos pela VM, vamos precisar compartilhar um diretório local para a máquina. A linha a seguir monta a pasta chamada www no seu diretório home para DocumentRoot/var/www) do Apache na máquina virtual.
config.vm.share_folder "www", "/var/www", "~/www"
Se você optou por deixar essa configuração como está ou modificá-la, você pode inicializar a máquina virtual e começar a provisionar com o seguinte comando na máquina local. Verifique se você está no diretório que contém o Vagrantfile.
vagrant up
(Se você receber um stack dump e um erro de permissão, uma explicação está disponível.)
Vagrant inicializa a imagem com o VirtualBox, então executa Puppet com a configuração localizada em manifests/base.pp. Eu comentei as linhas no arquivo base.pp para você compreender melhor a sua função. Além disso, mantive a configuração simples intencionalmente. Uma configuração mais avançada vai exigir que você crie módulos que possam ser herdados, incluídos, parametrizados etc.
Para referência, aqui há mais documentos sobre as diretrizes do Puppet.
Muitos desenvolvedores também têm escrito e compartilhado scripts do Puppet com o mundo. Aqui está uma configuração LAMP mais complicada.
Uma vez que a máquina estiver funcionando, se quiser se conectar via SSH nela, você pode fazer assim:
vagrant ssh
A fim de se conectar via SSH à máquina sem o uso de Vagrant (por exemplo, ao criar um túnel para usar um cliente GUI MySQL), use a sintaxe mais longa:
ssh vagrant@localhost -p 2222 (password: vagrant)
Existem bem poucas razões que você deve ter para configurar a máquina virtual de dentro dela mesma. Conectar-se à máquina dessa forma deve ser limitado à execução de ferramentas de linha de comando dependentes do ambiente, como PHPUnit e MySQL.
Distribuição e provisionamento com o Puppet
Puppet é o verdadeiro herói aqui. Assim que uma mpaquina virtual é distribuída, Puppet facilita manter a configuração das máquinas sincronizadas. Pense na sua máquina virtual como algo descartável. Você deve ser capaz de destruí-la e recriá-la sem perder a funcionalidade. Quaisquer alterações de configuração que precisam ser feitas na máquina devem ser propagadas para o arquivo de configuração Puppet e distribuídas através de um repositório Git ou um servidor Puppet (puppetmaster). Lembre-se, a chave é que todos tenham o mesmo ambiente e, para isso, nenhuma modificação personalizada deve ser feita na máquina virtual sem compartilhar as alterações na configuração através do arquivo Puppet.
Se você modificou base.pp, você pode facilmente reconfigurar a máquina da seguinte maneira:
vagrant reload
Você também pode destruir completamente a máquina e começar de novo:
vagrant destroy vagrant up
Se você quiser apenas suspender a sua máquina virtual para mais tarde:
vagrant suspend vagrant resume
Depois de ter configurado um box, você também pode empacotá-lo e distribuir uma versão binária usando o comando Vagrant do pacote. Eu prefiro criar um repositório Git com muitas pastas contendo diferentes configurações. Por exemplo, você poderia ter um ambiente LAMP estável em uma pasta, e outro contendo um script para instalar o release candidate do PHP 5.4. No entanto, um outro pode conter um ambiente Ruby ou Python. Alternar entre elas é tão simples como a suspensão de uma máquina e a inicialização outra.
Desenvolver com um ambiente consistente e local
Agora você deve ser capaz de modificar facilmente arquivos dentro do diretório www em sua máquina local, recarregar o seu browser para http://localhost:8080/, e ver os resultados.
Essa configuração serve como um ótimo ambiente de desenvolvimento com o qual começar. Cada aplicativo terá seu próprio conjunto de dependências. Você pode até mesmo distribuir a configuração da máquina virtual dentro do repositório do aplicativo para servir como uma definição explícita das dependências que tem. Com isso, você pode configurar o servidor de integração contínua para implementar uma máquina, provisioná-la, instalar o aplicativo, executar seus testes e reportar de volta para você.
Há um derradeiro nível de configuração e flexibilidade com uma configuração como essa. Acima de tudo, porém, sua equipe agora é capaz de trabalhar de forma mais rápida e eficiente, e você não vai acabar em uma situação em que algo funciona de forma diferente no ambiente do outro. Espero que encontre uma maneira de usar essas ferramentas para sua própria sanidade.
***
Texto original disponível em http://phpadvent.org/2011/facilitating-development-environment-consistency-by-jeff-loiselle