Automatização de processos CI/CD de aplicativos React Native no Jusbrasil

Luciano Lima
Jusbrasil Tech
Published in
7 min readApr 2, 2019

Você talvez já tenha passado por isso: cria um aplicativo, introduz novas funcionalidades e disponibiliza nas lojas para seus usuários. Mas agora precisa mantê-lo funcional, acessível e com qualidade à medida que continua com o desenvolvimento. Para isso precisa levar em conta vários fatores que vão desde como o código foi escrito, os testes que foram feitos e como as novas funcionalidades serão integradas à versão atual. Nesse artigo vamos conhecer como montamos nossa stack para garantir a entrega de atualizações frequentes com a maior qualidade possível para nossos usuários.

Conceitos

Primeiro, vamos conhecer alguns conceitos estabelecidos pelo mercado que ajudam a manter uma aplicação atualizada e com qualidade.

Continuous Integration, ou somente CI, permite que o código que está sendo desenvolvido receba atualizações frequentes. Entre uma atualização e outra todo o código é avaliado através de testes, ferramentas de lint e outras técnicas de qualidade e padronização de código. Se toda verificação for concluída sem erros, as novas alterações passam a fazer parte do código mais recente da aplicação.

Continuous Delivery, ou somente CD, garante que o código mais recente da aplicação estará disponível para o usuário em produção e funcionando corretamente. Isso pode envolver etapas de compilação, transpilação, deploy, testes de aceitação entre outras.

O que usamos durante o desenvolvimento

São várias as ferramentas do ecossistema do JavaScript que nós utilizamos em nossos produtos. Dentre elas destacamos:

  • Relay Modern + GraphQL
  • Redux + Redux Persist
  • Jest + Enzyme
  • Flow (estamos migrando para TypeScript)
  • Prettier + Eslint

Identificando e solucionando problemas

A publicação de um aplicativo é bem diferente quando comparado a de uma aplicação web. Em uma aplicação web, nós temos controle do ambiente, ou seja, das configurações do servidor que será acessado pelos nossos usuários. Ao fazer um deploy, todos os usuários, a partir daquele momento, tem acesso à última versão da aplicação.

Em um aplicativo o processo é outro. Primeiro porque ele precisa ser enviado para as lojas do Google Play e da Apple App Store. Os usuários acessam essas lojas, que também são aplicativos, e fazem a instalação do aplicativo que desejam, seja ele gratuito ou pago. E aqui reside o primeiro problema. Quando enviamos um aplicativo, ele precisa ser avaliado e só depois de liberado, passa a estar disponível na loja. Isso pode levar algumas horas ou alguns dias. Também levamos outro detalhe em consideração: o usuário não é obrigado a instalar uma atualização! Isso pode acarretar em recebermos reclamações de usuários sobre problemas que já foram corrigidos.

Para solucionar estes dois problemas, usamos o Code-push!

Code-push

Publicação de aplicativos. Fonte: Roxiler Systems

O Code-push é uma ferramenta criada pela Microsoft que nos permite atualizar o bundle JS de nosso aplicativo diretamente no dispositivo do usuário e sem precisar passar pela aprovação das lojas. Nós atualizamos o bundle sempre que uma nova funcionalidade ou correção é adicionada em nosso aplicativo. Essa nova atualização é identificada automaticamente e aplicada na próxima abertura do app.

Apenas mudanças na camada JS é passível de atualização via Code-push, visto que ele apenas atualiza o bundle JS (isso inclui imagens, ícones, fontes e outros arquivos estáticos que são usados através de require()).

Para quem se interessar, escrevi aqui no Medium sobre o Code-push um tempo atrás:

Certo… mas então, temos que atualizar o bundle JS através do Code-push toda vez que implementarmos novas funcionalidades ou correções? Isso seria repetitivo e muito desgastante. O que fizemos foi automatizar o processo através de uma ferramenta de CI.

Wercker

Para CI usamos o Wercker, que foi comprado pela Oracle e passou a fazer parte do Oracle Container Pipelines. Criamos uma rotina que envolve algumas atividades como:

  • Baixar o repositório do github
  • Instalar as dependências através do yarn
  • Checar o código com eslint e flow
  • Executar os testes com o jest
  • Checar se é necessário fazer um build nativo (criamos um script que procura por mudanças nos diretórios android e ios)
  • Gerar um novo release com o Code-push
  • Avisar no Slack (caso tenha feito um build nativo)

São várias etapas que conseguimos automatizar e economizar no tempo de desenvolvimento! Quando fazemos um merge na master, tudo isso é feito automaticamente! Yeah! 😎✌️

Mas então nos deparamos com mais outras atividades que poderíamos automatizar e ter mais tempo livre para desenvolver de fato. Para atualizar um aplicativo React Native precisamos passar por duas etapas:

  1. Gerar o bundle JS (explicado acima)
  2. Gerar o arquivo binário (APK para Android e IPA para iOS)

Nosso time de desenvolvimento mobile possui 4 desenvolvedores atualmente. Precisávamos garantir que todos poderiam gerar o mesmo aplicativo independentemente do ambiente que estavam utilizando (Windows, Linux, MacOS).

No Android, precisamos criar um arquivo keystore de produção que será usado para assinar o binário após a compilação. Mas a versão de desenvolvimento também usa uma keystore que é gerada na máquina quando instalamos o SDK do Android. Isso gera um problema porque cada máquina tem uma keystore diferente e alguns serviços, como o Login do Facebook por exemplo, precisam de todas as keystores utilizadas para poder permitir o teste durante o desenvolvimento. Ou seja, se o time aumentar, precisaríamos cadastrar novas keystores para que esses novos desenvolvedores não tivessem problemas com alguns serviços.

No caso do iOS a coisa se complica mais. Para gerar um binário é necessário uma combinação de 3 informações:

  1. O certificado de desenvolvedor ou de produção
  2. A lista de dispositivos autorizados que podemos instalar o aplicativo durante o desenvolvimento
  3. Um arquivo de provision que une o ID do aplicativo, certificados criados para ele e os dispositivos autorizados.

Ou seja, se não temos um certificado para o aplicativo, não podemos testá-lo. Se um dispositivo não está incluído na lista, não conseguimos instalar o aplicativo nele. Se não temos o provision instalado na máquina não conseguimos fazer praticamente nada! 😢

Então resolvemos esse novo problema com o fastlane.

Fastlane

Site do Fastlane

Usamos o Fastlane na automatização de processos de compilação, criação de certificados, gerar versão no repositório (git tags) e outras tarefas relacionadas a geração e/ou distribuição do app. Com o Fastlane simplificamos bastante várias etapas relacionadas ao gerenciamento de uma aplicação mobile e novamente conseguimos usar o tempo que seria gasto nessas atividades para desenvolver.

Também escrevi uma publicação falando sobre o Fastlane aqui no Medium:

Até aqui já conseguimos automatizar a geração do bundle JS, atualizar o aplicativo diretamente no dispositivo do usuário sem precisar passar pela avaliação das lojas e gerar os binários. Mas como falei acima, o Code-push só nos permite atualizar quando não temos uma modificação na camada nativa.

Para citar um exemplo, fizemos a atualização do react-navigation para a versão 3. Uma mudança que teve nessa versão foi a inclusão do pacote react-native-gesture-handler. Para a instalação desse pacote precisamos rodar no terminal o comando react-native link react-native-gesture-handler. Ao executar este comando, mudanças são feitas na camada nativa. E isso faz com que precisemos gerar um novo binário e enviar para as lojas. Já configuramos o Fastlane para isso, mas como podemos automatizá-lo?

Bitrise

O Code-push é uma ferramenta do Appcenter, serviço voltado para aplicativos da Microsoft. Tentamos utilizar o Appcenter para automatizar a compilação do aplicativo nas duas plataformas, mas encontramos um serviço que não permite muita customização. Como por exemplo, não fazer a compilação do binário caso não fosse necessário (tivesse apenas mudanças na camada JS).

Então decidimos usar o Bitrise que é tanto uma ferramenta de CD como de CI para aplicativos mobile. No Bitrise, criamos workflows, que são listas de tarefas a serem executadas. No nosso caso, criamos dois workflows separados: um para a versão Android e outro para a versão iOS. Assim temos a flexibilidade de compilar uma única plataforma, caso seja necessário. Esse tipo de configuração também nos permite fazer a compilação das duas plataformas em paralelo.

Quando criamos uma aplicação no Bitrise e fazemos o link com o repositório Git, ele identifica sua aplicação e cria um workflow de acordo com a tecnologia utilizada (Cordova, React Native, Xamarin, etc). Podemos criar uma conta gratuita que permite rodar uma compilação por 10min, mas não permite fazer compilações em paralelo. Há a possibilidade de pagar pelo serviço e ter acesso a compilações de até 45min.

Em nossos workflows no Bitrise nós:

  • Clonamos o repositório do github
  • Instalamos o react-native para gerar o bundle de produção
  • Usamos o fastlane para fazer o build da aplicação
  • Enviamos para as lojas (TestFlight na Apple App Store e para a faixa beta no Google Play)
  • Usamos o fastlane para gerar uma tag, criar um commit relacionado à versão e fazer push no repositório
  • Avisamos no Slack quando termina todo o procedimento

A documentação do Bitrise é muito boa e possui um fórum de suporte que ajuda a resolver grande parte dos problemas. A grande vantagem que destacamos no Bitrise, além da flexibilidade e customização, é podermos ter um ambiente MacOS para poder compilar para o iOS gratuitamente.

Conclusão

Bom, vimos alguns problemas relacionados a desenvolvimento de aplicativos e quais foram algumas ferramentas que usamos para solucionar esses problemas, automatizar processos e ganhar um tempo a mais para nos dedicarmos ao desenvolvimento.

Foi um resumo de nosso ambiente de Continuous Integration e Continuous Delivery aqui no Jusbrasil, onde não abordamos nada de forma técnica pois o objetivo era mais dar um contexto dos problemas e as possíveis soluções.

Se tiverem interesse em saber mais como usamos o Wercker e o Bitrise, deixa um comentário, que em breve faremos um post sobre essas ferramentas mais aprofundado e com exemplos de código que criamos.

Gosta de automatizar processos? Você quer trabalhar com aplicações com entrega contínua, testes e tecnologias modernas? Venha trabalhar conosco!

--

--

Luciano Lima
Jusbrasil Tech

Desenvolvedor Web e Mobile. Amante de tecnologia e TI em geral. Além de ser fã de games e mangás!