Automatizando seu ambiente de desenvolvimento

Hoje irei falar como utilizar scripts bash para deixar seu ambiente de desenvolvimento mais produtivo.

Gosto muito de ser preguiçoso e sempre que me vejo fazendo alguma coisa repetidas vezes fico imaginando formas de automatizar. Isso me ajuda a ser mais produtivo.

Muitas vezes, em um projeto de software você tem uma rotina de deploy ou build ou até as duas e normalmente utilizamos um ambiente de produção e outro de teste, mas antes de implantar o sistema em qualquer desses ambientes você precisa fazer uma série de passos... Então, porquê não automatizá-los? Dentre as vantagens de se fazer isso posso listar as seguintes:

  1. Ajuda a não esquecer os passos de implantação
  2. Aumenta a velocidade de entrega
  3. Ajuda na padronização do processo de implantação
  4. Evita erros comuns

Hoje em dia temos muitos serviços de CI e CD onde você cria pipelines de entrega, serviços como Travis CI e Circle CI, além do software Jenkins se beneficiam dessa prática.

Pouco importa a ferramenta, o importante aqui é o conceito, todas elas utilizam a mesma lógica: definir tarefas para serem executadas a cada passo, sendo que cada tarefa possui um mais comandos para serem executados.

 

Para exemplificar melhor vamos pensar num projeto Java que possui um frontend em Vue.js, para colocar esse projeto online teríamos que no mínimo:

  1. Fazer o build do Java (gerar o .war)
  2. Colocar o .war num servidor web Java (Tomcat ou wikdfly)
  3. Fazer o build do Vue
  4. Enviar os arquivos gerados para um servidor web (nginx ou Apache)

Esses são passos básicos, nem estou colocando na lista, atualização de banco de dados, troca de domínio, envio de assets para um storage(como aws s3 ou google cloud storage), build de imagem Docker e por aí vai... Então, como seria uma pipeline de entrega desse software?

Por onde começar?

Antes de tudo pense nas ações que sempre faz, depois isole isso em tarefas, em seguida crie um script para cada tarefa. Por exemplo, se toda vez que você precisa subir um servidor web para começar a trabalhar, crie um script que suba o servidor web com os parâmetros certos, com as variáveis de ambiente adequadas e com a porta correta. Se precisa rodar os testes de uma forma específica ou se precisa rodar algo antes de rodar os testes, crie um script que faça isso.

No último caso acima, por exemplo, você poderia ter um script que prepara o ambiente para executar os testes e um outro que executa os testes.  Algo assim:


      #scripts/test
      #!/bin/bash
      ./scripts/preparar-ambiente-teste
      ./scripts/run-testes
      

Eu particularmente gosto de ter uma pasta chamada scripts em cada projeto que faço. Nessa pasta crio vários scripts bash que automatizam algo para mim e muitas vezes reutilizando eles, por exemplo, se antes de fazer a implantação do sistema eu preciso rodar os testes, depois o build do projeto e só depois enviar o projeto para o servidor, eu crio um script chamado deploy e dentro dele chamo o script de teste, depois o de build e por fim o do deploy. Seria algo assim:


      #scripts/deploy
      #/bin/bash
      ./scripts/test
      ./scripts/build
      ./scripts/send-server
      

Daí quando quero fazer o deploy só preciso executar ./scripts/deploy e esperar toda a pipeline rodar. Se amanhã ou depois eu ficar algum tempo sem dar manutenção no projeto e de repente preciso ajustar algo, não preciso recorrer a documentações (que podem ficar defasadas), ou pior, recorrer a minha memória, apenas executo o script e pronto.

Projeto de exemplo

Voltando ao projeto Java com Vue.js... Como poderia ser a automatização das tarefas dele? Como falei acima: "Antes de tudo, pense nas ações que sempre faz, depois isole isso em tarefas, em seguida crie um script para cada tarefa", então vamos lá.

Pense nas ações que sempre faz
  • Fazer o build do projeto
  • Enviar o .war para o servidor tomcat
  • Fazer o build o Vue
  • Enviar o conteúdo do build para o nginx
Isole isso em tarefas
  • Rodar o ./gradlew build
  • Enviar o .war via scp
  • Rodar o npm run build
  • Enviar os arquivos da pasta build via scp
Crie um script para cada tarefa

      # scripts/build-java
      #!/bin/bash
      ./grandlew build

      # scripts/deploy-war
      #!/bin/bash
      scp app.war deployer@meuhost.com :/opt/tomcat/webapps/ROOT.war
      ssh deployer@meuhost.com 'service tomcat restart'

      # scripts/build-vue
      #!/bin/bash
      npm run build

      # scripts/deploy-frontend
      #!/bin/bash
      scp ./build/* deployer@meuhost2.com :/var/www/
      
De quebra eu posso criar um script que faz tudo

      # scripts/deploy
      #! /bin/bash
      ./scripts/build-java
      ./scripts/deploy-war
      ./scripts/build-vue
      ./scripts/deploy-frontend
      

Pronto, a pipeline está completa! :)

Gerenciadores de dependência que dão suporte a scripts

Alguns gerenciadores de dependência como o npm do node dão suporte ao uso e definição de scripts locais. Nos projetos com npm, o arquivo package.json possui uma sessão só para scripts e isso facilita muita coisa, muitos atalhos podem ser definidos lá, por exemplo, você poderia definir no seu package.json um script de deploy e nele você chamaria um ou mais comandos. Dessa forma:


        ...
        "scripts": {
          "deploy": "./scripts/build && ./scripts/deploy-frontend"
        }
        ...
      
No ecossistema Ruby temos o rake e aqui vão dois artigos interessantes que achei https://www.rubyguides.com/2019/02/ruby-rake/ e https://www.akitaonrails.com/2009/02/16/automatizando-tarefas-com-ruby-e-rake, no ecossistema PHP tempos o composer que no composer.json, podemos definir alguns scripts https://getcomposer.org/doc/articles/scripts.md#writing-custom-commands. No ecossistema python isso pode ser feito pelo Pipenv https://pipenv-fork.readthedocs.io/en/latest/advanced.html#custom-script-shortcuts e aqui vai um artigo bem massinha sobre isso https://dev.to/elanorigby/i-love-pipenvs-custom-script-shortcuts-156k.

Criando script na sua linguagem prefereida

Muitas vezes não temos tanta familiaridade com o bash e as linguagens que usamos tem uma série de recursos e facilidades que gostamos. Então sim, você pode criar scripts na sua linguagem favorita. Basicamente o que você precisa é definir um cabeçalho novo. Por padrão, arquivos bash possuem a primeira linha com #!/bin/bash, basta você alterar para a localização do executável da sua linguagem ex: scripts em PHP #!/usr/bin/php, scripts em ruby #!/usr/bin/ruby e no conteúdo do arquivo é o código da linguagem.

Crie um arquivo com o nome que quiser, por exemplo, hello e coloque o conteúdo:


      #!/usr/bin/ruby
      puts "Hello George"
      

Depois execute no terminal o comando chmod +x ./hello, pronto, agora é só executar o script:


        ./hello
        Hello George
        

Isso é tudo pessoal :)
anúncio