Ambiente de stage para páginas estáticas
Problema
Dado as definições de ambiente de stage definidas em requirements/environments, e considerando que utilizamos o gitlab pages para hospedagem de páginas estáticas, precisamos resolver o problema de criar uma ambiente de stage que cumpra com os requisitos definidos para este ambiente, e que possa ser automatizado, para ser disparado diretamente pelo CI/CD, conforme definido pelo fluxo de desenvolvimento e deploy.
Soluções para o ambiente
Dado que o ambiente de produção é no gitlab pages, que devemos manter o stage no mesmo ambiente (segundo definição deste ambiente), e que podemos ter somente um gitlab pages por repositório, testamos algumas abordagens.
Fork de repositório para cada colaborador
A ideia é que o colaborador realize um fork do projeto principal, desenvolva suas modificações no seu próprio repositório, e quando chegar a hora do deploy para stage, jogue para a sua master, onde um CI/CD deve realizar o deploy do gitlab pages em seu próprio repositório. Ao final da validação ele abriria uma MR para a master do repositório original, onde seria executado do deploy de produção.
Esta abordagem altera o fluxo de desenvolvimento e deploy. Utilizamos ela por algum tempo, entretanto alguns problemas surgiram conforme o time crescia:
- Por ser projetos privados o fork também é privado, assim ao abrir MR para o repositório original o reviewer não conseguia acessar a branch que deu origem a MR, sendo necessário aceitar a MR em uma branch separada para testar o código e abrir outra MR para a branch desejada.
- Não era possível saber o que outras pessoas estavam fazendo olhando o git. Era difícil de ajudar a outra pessoa com o projeto pois acessar o código em desenvolvimento era complicado.
- Não era possível fazer um cherry-pick, para pegar pequenas modificações de outra pessoa.
- Novos colaboradores passaram a precisa adicionar o cartão de crédito para habilitar o uso do CI/CD que é necessário para criar o pages do gitlab, sendo assim novos colaboradores não conseguiriam fazer deploy para stage em seu próprio repositório com facilidade.
Múltiplas pastas no mesmo repositório
O gitlab pages serve arquivos estáticos que ficam na pasta public, exportados como artefatos pelo CI/CD. Por repositório só podemos ter um gitlab pages. A ideia desta abordagem era dentro da pasta public colocar na raiz o projeto que está em produção, e criar uma pasta dentro da public com o projeto que está em stage (/public/stage).
Testamos esta abordagem, e encontramos 2 grandes problemas:
- Como por definição do ambiente a página servida em stage deve ser privada e não listada por buscadores, e a configuração do repositório para este gitlab pages era pública, seria necessário fazer na aplicação, somente no bundle da versão de stage, algo privasse o acesso.
- Sempre que é executado um pipeline e gerado um artefato na "/public" o antigo é substituido por completo, isto é, para que na public tenhamos 2 bundle (um da branch master, e outro da branch stage em uma pasta a parte), é necessário que o CI/CD execute tanto p/ master quanto p/ a stage, executando seguinte pipe:
- checkout master -> install dependencies -> lint -> test -> build -> deploy at the public
- -> checkout stage -> install dependencies -> lint -> test -> build -> deploy at the public/stage
Essa abordagem além de mais trabalhosa por conta do item 1, é mais custosa computacionalmente por conta do item 2. Se considerado que temos limite de minutos para executar CI/CD o custo é ainda maior.
Abordagem escolhida
A abordagem escolhida foi criar um fork do repositório dentro do time, assim podemos ter 2 gitlab pages com configurações diferentes.
O repositório original é o que será utilizado para desenvolver o código e hospedar o ambiente de produção, com visibilidade pública para acesso a página. Quando na master deste repo o CI/CD executa colocando o blundle do projeto no pages.
O repositório de stage é o que será utilizado somente para stage, com visibilidade somente para membros para acesso a página. Este repo é criado dentro de um sub-grupo, onde existe um usuário de teste que consegue somente visualizar a wiki e o gitlab pages, e não consegue visualizar o código, assim para acessa a página é necessário que usuário externos façam login com este usuário de teste. Quando na master deste repo o CI/CD executa colocando bundle do projeto no pages.
Nesta abordagem para realizar deploy em stage basta dar merge na master do outro repositório, semelhante ao que é feito com o heroku.
Como não encontramos limitação p/ o número de repositório que podem ser criados, e esta abordagem permite privatizar o acesso, optamos por seguir utilizando ele.
Porém o desafio de criar o ambiente de stage não termina aqui, precisamos automatizar esse processo de deploy com CI/CD.
Deploy automatizado
Dado a abordagem escolhido para o ambiente de stage, fica faltando automatizar o processo, uma vez que ele por si só requer ação manual, e não segue o fluxo definido para desenvolvimento.
Pesquisando como automatizar o processo de staging sabíamos que era necessário transferir as modificações da branch stage do repositório de origem para outro e rodar o CI/CD sem interferir no funcionamento do outro.
A ideia inicial era utilizar os comandos git dentro do CI/CD do repositório de origem, ele iria executar os mesmos comandos que o usuário realiza manualmente para dar push no outro repositório.
Pesquisando a respeito encontramos outro meio de fazer isso, utilizando o espelhamento de repositórios do gitlab, que acreditamos ser uma melhor abordagem, pois utilizar comandos do git dentro do CI/CD seria mais complexo e demorado de se implementar e também mais instável, podendo parar de funcionar a qualquer momento por causa do usuário do git que deveria ser utilizado para fazer o push da branch.
O espelhamento de repositório consiste em fazer algumas poucas configurações apontando ao gitlab qual repositório ele deve espelhar as modificações feito no repositório de origem. Para essa configuração é necessário utilizar login e senha de um usuário que tenha acesso aos 2 repositórios (a senha não fica visível). Desta forma, qualquer alteração no repositório de origem é executado no repositório espelhado também.
Por fim, nesta abordagem foi necessário criar um novo arquivo de CI/CD e configurar no repositório espelhado que seja utilizado ele e não o arquivo padrão. Assim, ao ocorre um push na branch stage do repo origem, essa modificação é espelhada no repositório de stage e o CI/CD configurado executa, realizando o deploy do gitlab pages, enquanto o CI/CD original continua somente executando na master do repositório original para deploy em produção.
A abordagem utilizando o espelhamento de repositório foi selecionada, pois ela é prática de se implementar.
Veja como configurar esse espelhamento aqui.