The Social Project: configurando o servidor de CI

Padrão

Se você ainda não conhece as motivações deste projeto, leia o primeiro artigo aqui.

No post anterior, criamos o repositório com um projeto vazio e configuramos o repositório com as branches persistentes que farão parte do nosso Git Flow.

Para essa tarefa, escolherei o CircleCI. Por quê? Primeiramente pelo seu suporte a Docker, o que facilita e muito na hora de fazer o setup do ambiente, caso a gente precise customizar o tooling. Além disso, ele possui uma cota gratuita generosa não só para projetos open-souce (que está sendo o caso deste daqui), mas também para projetos privados no Github ou Bitbucket.

Bom, primeiramente faremos o login no CircleCI com a nossa conta do Github e faremos o setup do nosso repositório.

Na tela seguinte, selecionamos uma máquina Linux e o Gradle como ferramenta de build. Nessa mesma tela, será oferecido um arquivo de configuração default, a ser colocado na pasta .circleci do repositório, com o nome de config.yml. O conteúdo inicial do arquivo é:

# Java Gradle CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-java/ for more details
#
version: 2
jobs:
  build:
    docker:
      # specify the version you desire here
      - image: circleci/openjdk:8-jdk
      
      # Specify service dependencies here if necessary
      # CircleCI maintains a library of pre-built images
      # documented at https://circleci.com/docs/2.0/circleci-images/
      # - image: circleci/postgres:9.4

    working_directory: ~/repo

    environment:
      # Customize the JVM maximum heap limit
      JVM_OPTS: -Xmx3200m
      TERM: dumb
    
    steps:
      - checkout

      # Download and cache dependencies
      - restore_cache:
          keys:
          - v1-dependencies-{{ checksum "build.gradle" }}
          # fallback to using the latest cache if no exact match is found
          - v1-dependencies-

      - run: gradle dependencies

      - save_cache:
          paths:
            - ~/.gradle
          key: v1-dependencies-{{ checksum "build.gradle" }}
        
      # run tests!
      - run: gradle test

A partir desse modelo, faremos algumas alterações. A primeira delas é mudar a imagem do docker para uma que já contenha todo o setup para que possamos buildar apps Android – temos uma lista das imagens mantidas pelo próprio CircleCI aqui. Além disso, configuramos a versão da JDK a ser utilizada e configuramos o cache de dependências (para que não precise ser baixadas novamente, caso não haja mudança nos arquivos do Gradle). Colocamos também uma task preventiva (Accept licenses) para evitar que o processo de build quebre por conta de licenças não aceitas.

Na task de build, configuramos a execução do Lint (através da task check), a compilação e execução de testes locais (através da task build) e, por enquanto, a compilação dos testes instrumentados (através da task assembleAndroidTest) – posteriormente faremos a delegação da execução desses testes para o Firebase Test Lab.

O arquivo final fica assim:

version: 2
jobs:
  build:
    docker:
      - image: circleci/android:api-27-alpha

    working_directory: ~/social-app

    environment:
      JVM_OPTS: -Xmx3200m
      CIRCLE_JDK_VERSION: oraclejdk8

    steps:
      - checkout

      - restore_cache:
          key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}

      - run:
          name: Accept licenses
          command: yes | sdkmanager --licenses || true

      - run:
          name: Build
          command: ./gradlew clean check build assembleAndroidTest

      - save_cache:
          paths:
            - ~/.gradle
          key: jars-{{ checksum "build.gradle" }}-{{ checksum "app/build.gradle" }}

Feito isso, também colocarei um badge no README.md do repositório, indicando o atual status da nossa build. Tudo isso será então commitado em uma branch chamada rt/setup-ci e então um pull request será aberto.

Como sou administrador, eu poderia simplesmente ignorar o fluxo e eu mesmo mergear meu Pull Request. Porém, iria quebrar o fluxo que eu mesmo estou propondo! 🙂

Para fazer o review do meu PR, adicionei a Elessandra como revisora. No caso, a pessoa que revisa o PR pode fazer apontamentos e, caso esteja tudo certo, aprovar e mergear.

Como nem tudo são flores, eu commitei o arquivo com alguns erros de digitação na primeira tentativa. Como ainda não tínhamos o CI integrado para validar o arquivo de configuração, os olhos humanos deixaram passar. Com isso, fui obrigado a fazer outro PR revertendo a modificação. Pela própria interface do Github é possível solicitar desfazer o PR.

Corrigidos os erros (e, após algumas tentativas), finalmente consegui configurar o CI corretamente.

Como foram vários commits de tentativa e erro, o PR ficou com vários commits. Para esse caso, o ideal é que se faça o Squash (juntar todos os commits em um único), evitando assim que o histórico do Git seja poluído.

Por fim, após o merge é importante excluir a branch de origem, já que ela não é uma branch persistente. Assim, mantemos o repositório limpo e organizado 🙂

Por hoje é isso. O repositório já com as modificações está disponível aqui.