Enem Amigo
1 - Introdução
[editar | editar código-fonte]Propósito
[editar | editar código-fonte]Este plano de gerência de configuração de software tem como objetivo especificar as práticas e ferramentas que serão utilizadas no processo de manutenção do software enem amigo. O software em questão foi desenvolvido por estudantes da Universidade de Brasília no segundo semestre de 2015 e sua proposta é atuar como uma ferramenta de auxílio aos estudos para o Exame Nacional do Ensino Médio (ENEM).
Escopo
[editar | editar código-fonte]O planejamento de mudanças tem como proposta adicionar uma ferramenta de automatização de integração continua ao projeto, automatizar sua implantação, produção de pacotes .deb para instalação em ambientes debian e evolução do repositório oficial visando atrair colaboradores.
Repositório do Projeto
[editar | editar código-fonte]O repositório do projeto está disponível em https://github.com/pedrodelyra/enem-amigo.
2 - Gerência de Configuração de Software
[editar | editar código-fonte]Organização, Responsabilidades e Interfaces
[editar | editar código-fonte]Papel | Responsabilidade | Responsável |
---|---|---|
Gestor de configuração do projeto | Acompanha as alterações dos itens de configuração. | Renata Soares |
Gestor de ferramentas de gerência de configuração de software | Mantém a infraestrutura necessária para a gerência de configuração. | Pedro de Lyra e Renata Soares. |
Gestor de configuração de software | Aprova e gerencia as atividades. | Pedro de Lyra |
Auditor de configuração de software | Realiza as auditorias. | Pedro de Lyra e Renata Soares. |
Desenvolvedores | Desenvolvem os itens de configuração que serão gerenciados. | Pedro de Lyra e Renata Soares. |
Ferramentas, Ambiente e Infraestrutura
[editar | editar código-fonte]Git
O git será o sistema de controle de versão utilizado para gerenciar as versões do projeto.
Github
O Github sera utilizado para hospedar o repositório oficial do projeto.
Travis CI
O Travis CI é um ambiente web destinado à automatização da integração contínua de projetos de software. Ele será a ferramenta escolhida para adicionar integração contínua ao projeto.
Vagrant
O Vagrant é uma ferramenta utilizada para realizar a automatização da construção de ambientes de desenvolvimento.
Hospedagem
O Digital Ocean é um sistema que fornece diversos serviços de hospedagem e será utilizado para criação do servidor que hospedará a aplicação após sua implantação.
Capistrano
O Capistrano será a ferramenta utilizada para automatização do deploy do projeto.
Shell Script
O Shell Script será utilizado para produção de scripts que automatizem determinadas partes do projeto que não necessitem de ferramentas externas além de um interpretador de linhas de comandos.
Chef
O chef é uma ferramenta para automatizar a infraestrutura, aplicações e todo o fluxo de trabalho DevOps.
Dh_make e debuild
Estas ferramentas serão usadas no empacotamento debian do projeto.
3 - Gerência de Configuração de Programa
[editar | editar código-fonte]Identificação da Configuração
[editar | editar código-fonte]A baseline que será gerenciada de acordo com o plano é a branch master do repositório que consiste em uma versao entregável do projeto.
Configuração e Controle de Mudança
[editar | editar código-fonte]Os recursos adicionados pelo gerenciamento de configuração serão experimentados em uma versão independente do projeto mantida em uma branch específica.
Relato do Status de Configuração
[editar | editar código-fonte]O status de configuração será registrado no repositório através da ferramenta de controle de versão, contendo todas as alterações realizadas, a descrição, o autor, a data e horário de cada uma delas.
4 - Cronograma
[editar | editar código-fonte]Data | Entrega |
---|---|
27/04/2016 | Plano de gerência de software |
04/05/2016 | Evolução do repositório oficial |
11/05/2016 | Adicionar integração contínua |
25/05/2016 | Realizar deploy |
08/06/2016 | Automatizar deploy |
22/06/2016 | Realizar empacotamento Debian |
5 - Resultados
[editar | editar código-fonte]Automatização da Integração Contínua com Travis CI
[editar | editar código-fonte]A ferramenta Travis CI foi selecionada para realizar a automatização da integração contínua do projeto. Seu uso é simples, rápido e fácil. Em primeiro lugar, é necessário sincronizar as contas do Github e do Travis CI. Em seguida, basta selecionar o repositório que deseja ser monitorado pelo Travis e adicionar um arquivo de configuração no diretório raíz do projeto, denominado ".travis.yml". Este arquivo contém algumas especificações sobre o projeto, as branches que serão rastreadas pelo Travis e uma lista de comandos que deve ser executada. Qualquer modificação nas branches sendo monitoradas dispara a execução do Travis e o mesmo fornece um relatório informando o status da build gerada. A atual versão do arquivo .travis.yml deste projeto se encontra assim:
language: ruby
rvm:
- 2.2.0
env:
- DB=sqlite
script:
- bundle exec rake test
before_script:
- bundle exec rake db:migrate --trace RAILS_ENV=test
- bundle exec rake db:test:prepare
notifications:
email:
recipients:
- pedrodelyra@gmail.com
branches:
only:
- master
Automatização da criação de ambientes de desenvolvimento com Vagrant
[editar | editar código-fonte]O Vagrant é uma ferramenta utilizada para automatizar a criação de ambientes virtuais. Seu propósito é facilitar a configuração, reprodução e distribuição de ambientes virtuais e pode ser utilizado, por exemplo, para unificar o ambiente de desenvolvimento de uma equipe. Como os ambientes criados pelo Vagrant são virtuais (o Vagrant se baseia no uso de máquinas virtuais, por exemplo: VirtualBox, VMWare, etc...), estes podem ser construídos sobre qualquer sistema operacional que ofereça suporte ao Vagrant.
O uso do Vagrant é fácil e ágil, relataremos em seguida um pequeno tutorial de como usá-lo em sistemas Gnu/Linux.
Em primeiro lugar, é necessário realizar sua instalação. Utilize o gerenciador de pacotes da sua distribuição. No Debian, o pacote a ser instalado é:
$ sudo apt-get install vagrant
Em segundo lugar, siga ao diretório do projeto e execute o comando:
$ vagrant init
Este comando inicializa o Vagrant para o projetoatual e cria um arquivo de configuração utilizado pelo Vagrant denominado Vagrantfile. Este arquivo irá conter uma série de comentários que exemplificam o seu uso. Neste arquivo, é possível especificar, por exemplo, a box* que será utilizada na criação do ambiente e alguns scripts que devem ser executados durante a criação e configuração do novo ambiente. Em uma primeira versão do nosso projeto, o Vagrantfile se encontrava assim: * Uma box do Vagrant é uma imagem base de uma máquina virtual.
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
config.vm.box = "hashicorp/precise64"
config.vm.provision :shell, path: "bootstrap.sh"
end
Decidimos utilizar uma box já disponibilizada pela hashicorp que contém o sistema operacional Ubuntu 12.04 LTS 64-bit. O arquivo bootstrap.sh contém uma série de comandos que serão executados durante a construção do ambiente e que são responsáveis por configurar um ambiente de desenvolvimento pronto para o projeto Enem Amigo.
#!/usr/bin/env bash
apt-get update
sudo apt-get install -y vim
sudo apt-get install -y git
sudo apt-get install -y nodejs
gpg --keyserver hkp://keys.gnupg.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3
sudo apt-get install -y curl
\curl -L https://get.rvm.io | bash -s stable --ruby --autolibs=enable --auto-dotfiles
source /usr/local/rvm/scripts/rvm && source /home/vagrant/.rvm/scripts/rvm
rvm install 2.2.0
rvm use --default 2.2.0
rvm gemset create rails4
rvm gemset use --default rails4
git clone https://github.com/pedrodelyra/enem-amigo.git
sudo chmod -R 777 enem-amigo/
cd enem-amigo
sudo gem install bundler
bundle install
Este arquivo será executado durante a criação do ambiente. Esta criação é realizada quando o seguinte comando é executado:
$ vagrant up
Após a execução deste comando, o ambiente de desenvolvimento já está criado e pronto para uso. Para acessá-lo, basta executar o comando:
$ vagrant ssh
Desta forma, é possível unificar o ambiente de desenvolvimento do projeto e diminuir as chances de uma certa funcionalidade funcionar apenas em um computador ou sistema específico. Qualquer desenvolvedor do projeto pode utilizar o ambiente criado pelo Vagrant de forma fácil e rápida. É possível levantar um ambiente pronto do zero em poucos minutos e essa automatização tende a produzir um aumento no rendimento da equipe.
Chef
[editar | editar código-fonte]Na versão final do projeto, foi utilizada a ferramenta Chef para substituir o shell script utilizado na versão anterior e automatizar a configuração do ambiente da box. O Vagrantfile foi alterado de forma que fossem adicionados recipes através do chef e que fosse especificado o caminho para os cookbooks. Um cookbook é uma unidade de configuração que possui recipes (coleções de recursos, definidas de acordo com padrões como nomes de recursos, atributos e ações), atributos, distribuições de arquivos e extensões do Chef.
# -*- mode: ruby -*-
# vi: set ft=ruby :
# Vagrantfile API/syntax version. Don't touch unless you know what you're doing!
VAGRANTFILE_API_VERSION = "2"
Vagrant.configure(VAGRANTFILE_API_VERSION) do |config|
# All Vagrant configuration is done here
# Every Vagrant virtual environment requires a box to build off of.
config.vm.box = "ubuntu/trusty64"
config.ssh.forward_agent = true
config.vm.network "private_network", ip: "10.3.3.3"
# Forward ports for MongoDB and Express app
config.vm.network "forwarded_port", guest: 27017, host: 27017, auto_correct: true
config.vm.network "forwarded_port", guest: 3000, host: 3000, auto_correct: true
config.vm.provision :shell, :inline => "sudo apt-get update -y"
config.vm.provision :shell, :inline => "sudo apt-get install curl -y"
config.vm.provision :shell, :inline => "curl -L https://www.opscode.com/chef/install.sh | sudo bash"
config.vm.provision :shell, :inline => "git clone https://github.com/pedrodelyra/enem-amigo.git"
config.vm.provision :chef_solo do |chef|
# Paths to your cookbooks (on the host)
chef.cookbooks_path = ["cookbooks"]
# Add chef recipes
chef.add_recipe 'nodejs'
chef.add_recipe 'git' # Is required for NPM
chef.add_recipe "apt"
chef.add_recipe "ruby_build"
chef.add_recipe "rbenv::user"
chef.add_recipe "rbenv::vagrant"
chef.add_recipe "vim"
end
# Install express and express-generator packages globally
config.vm.provision :shell, :inline => "npm install -g express express-generator"
# Share an additional folder to the guest VM. The first argument is
# the path on the host to the actual folder. The second argument is
# the path on the guest to mount the folder. And the optional third
# argument is a set of non-required options.
config.vm.synced_folder "../enem-amigo", "/enem-amigo"
end
No arquivo Cheffile foram especificados os cookbooks necessários para a configuração.
site 'https://supermarket.getchef.com/api/v1'
cookbook "nodejs"
cookbook "mongodb"
cookbook "git"
cookbook 'apt'
cookbook 'build-essential'
cookbook 'mysql', '5.5.3'
cookbook 'ruby_build', '2.2.0'
cookbook 'vim'
cookbook 'rvm',
:git => 'https://github.com/fnichol/chef-rvm'
Empacotamento Debian
[editar | editar código-fonte]Um pacote de software é uma coleção de arquivos agrupados em uma configuração pré-determinada para permitir a instalação e distribuição de um software. O objetivo do empacotamento de software é automatizar o processo de instalação, atualização, configuração e remoção de aplicações.
Um pacote debian é um pacote de software que pode ser instalado pelo sistema de gerenciamento de pacotes do Debian. Pacotes debian possuem a extensão ".deb". Neste projeto de gerência de configuração, foi realizado o empacotamento debian do Enem Amigo.
Antes de relatar como empacotamos o projeto, é interessante comentar sobre alguns conceitos centrais sobre empacotamento.
- Tarball: um tarball é um conjunto de arquivos agrupados através do utilitário tar. Sua extensão é ".tar". Muitos arquivos .tar são comprimidos com o compressor de arquivos gzip e o resultado é o arquivo com extensão ".tar.gz" (esse é seu tarball).
- Upstream tarball: é um tarball que contêm o código-fonte do software que será empacotado.
- Source package: é um pacote construído a partir do upstream tarball e que é utilizado para a criação do pacote binário.
- Binary package: é um pacote construído à partir do source package e que será instalado de fato (este é o .deb).
Durante o empacotamento, duas ferramentas essenciais do Debian foram utilizadas: o dh_make e o debuild. É necessário instalar alguns pacotes que são utilizados durante o empacotamento:
$ sudo apt-get install dh-make
$ sudo apt-get install build-essential
O empacotamento é um processo relativamente burocrático e exige que uma série de convenções sejam seguidas. Porém, este processo se faz necessário para garantir que a instalação daquela versão do software seja realizada corretamente. Em primeiro lugar, é necessário criar o upstream tarball do projeto. Para isso, basta adicionar ao nome do projeto a versão correspondente do software que será empacotado, no caso do Enem Amigo a seguinte renomeação foi feita:
$ mv enem-amigo enem-amigo-1.0
Em seguida, o tarball foi criado com os seguintes comandos:
$ tar zcf enem-amigo-1.0.tar.gz enem-amigo-1.0/
$ mv enem-amigo-1.0.tar.gz enem-amigo_1.0.orig.tar.gz
Vale lembrar que estes padrões de nome não são por acaso, as ferramentas de empacotamento do Debian esperam que os pacotes sigam estas convenções. O nome consiste no nome do source package, um underscore e a versão do software seguida pela extensão .orig.tar.gz. Em seguida, é necessário entrar na raíz do projeto e criar um diretório debian/ que será usado durante o empacotamento. Para realizar esta etapa, a ferramenta dh_make foi utilizada da seguinte forma:
$ cd enem-amigo-1.0/
$ dh_make -s
Após a confirmação de alguns dados, o dh_make irá criar o diretório debian com uma série de arquivos de exemplo. Optamos por remover estes arquivos:
$ rm debian/*.ex debian/*.EX
Vale a pena citar os principais arquivos deste diretório:
- debian/control: contém alguns detalhes sobre o software empacotado e seu mantenedor.
- debian/compat: contém o nível de compatibilidade do pacote. Deve ser 9.
- debian/rules: é um arquivo Makefile que é executado durante a geração do pacote binário.
- debian/source/format: contém a versão do formato do source package, que é "3.0 (quilt)".
Cada projeto possui seu próprio contexto, sua própria forma de geração de build, seus arquivos de configuração, manuais, enfim, suas peculiaridades. Portanto, é difícil fornecer uma receita genérica para empacotar um software, pois cada sistema possuirá um contexto próprio. No caso do Enem Amigo, nós criamos alguns arquivos para a execução da build do projeto e instalação do seu pacote em uma distribuição Debian.
Script utilizado para executar o projeto após sua instalação (enem-amigo)
#!/bin/bash
current_path=$(pwd)
cd /etc
if [ -e enem-amigo_1.0.orig.tar.gz ]; then
sudo tar xzf enem-amigo_1.0.orig.tar.gz
sudo rm enem-amigo_1.0.orig.tar.gz
fi
cd enem-amigo_1.0
bundle install > /dev/null
bundle exec rake db:migrate > /dev/null
bundle exec rails server
cd $current_path
Makefile utilizado para especificar como a instalação do software deve ser realizada
bindir = /usr/bin
srcdir = /etc
install:
mkdir debian/enem-amigo
mkdir debian/enem-amigo/usr
mkdir debian/enem-amigo/usr/bin
mkdir debian/enem-amigo/etc
install enem-amigo $(DESTDIR)$(bindir)
install ../enem-amigo_1.0.orig.tar.gz $(DESTDIR)$(srcdir)
Para a geração do pacote binário (.deb), basta executar o comando:
$ debuild -us -uc
Este comando irá gerar o pacote binário enem-amigo_1.0-1_amd64.deb que pode ser distribuído e instalado em sistemas Debian-like através do gerenciador de pacotes dpkg. Exemplo de instalação:
$ sudo dpkg -i enem-amigo_1.0-1_amd64.deb
O empacotamento Debian é uma técnica excelente para a distribuição de um software, porém, ela possui uma certa curva de aprendizado.
Deploy
[editar | editar código-fonte]A realização do deploy foi através dos servidores em nuvem do DigitalOcean. O primeiro passo é a criação de um droplet, para isso é necessário criar um usuário e acessar o DigitalOcean onde pode ser criado e escolhido a distruição, os one-click apps, os snapshots (cria cópias do backup), o backup, o tamanho do seu droplet, a região que está o servidor e opções adicionais como private networking, ipv6, entre outros.
Através do SSH é possível o acesso ao servidor para o início da sua configuração, o IP para essa etapa é o Floating IP disponibilizado pelo DigitalOcean. Para a configuração, foram instalados os seguintes pacotes:
- Nginx: um servidor proxy HTTP.
- Sqlite3: o banco de dados utilizado na aplicação.
- RVM: gerenciador de versões do ruby.
- Puma: um servidor HTTP para aplicações Ruby/Rack.
- Rails: framework utilizado na aplicação.
- Bundler: Lê o Gemfile e instala automaticamente todas as gems.
O próximo passo necessário é criar uma chave SSH para o seu repositório no GitHub e associá-la ao seu droplet. O último passo é alterar as configurações no arquivo de configuração do nginx que fica em /config/nginx.conf.
upstream puma {
server unix:///home/demo/apps/enem-amigo/shared/tmp/sockets/enem-amigo-puma.sock;
}
server {
listen 80 default_server deferred;
# server_name example.com;
root /home/demo/apps/enem-amigo/current/public;
access_log /home/demo/apps/enem-amigo/current/log/nginx.access.log;
error_log /home/demo/apps/enem-amigo/current/log/nginx.error.log info;
location ^~ /assets/ {
gzip_static on;
expires max;
add_header Cache-Control public;
}
try_files $uri/index.html $uri @puma;
location @puma {
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_redirect off;
proxy_pass http://puma;
}
error_page 500 502 503 504 /500.html;
client_max_body_size 10M;
keepalive_timeout 10;
}