Ir para o conteúdo

Se você está desenvolvendo uma aplicação, é bem provável que em algum momento precise gerenciar as operações DDL e DML realizadas pela sua equipe no banco de dados. Ou seja, criação/exclusão/alteração de tabelas e colunas ou mesmo a execução de scripts puros. Para fazer isso de forma segura e padronizada é importante automatizarmos essas tarefas no nosso processo de CI/CD.

Neste artigo abordaremos uma possibilidade de automação utilizando o Gitlab em conjunto com o Entity Framework. Para replicação da abordagem é necessário que o seu projeto utilize o Entity Framework, entretanto, não necessariamente precisa ser feito com o Gitlab. A ideia proposta pode ser replicada em qualquer ferramenta de CI/CD.


Requisitos:

  • Noções de CI/CD;
  • Conhecimento básico de SQL;
  • Conhecimento básico de Entity Framework;
  • Conhecimento básico de Shell Scripts;

Entity Framework

Conforme citado anteriormente, para que seja viável a utilização desta implementação é necessário que o seu projeto esteja com as configurações do Entity Framework previamente realizadas. Caso necessite de mais informações sobre este ponto recomendo este link da documentação da Microsoft.

Partindo do princípio de que a etapa anterior esteja funcional em sua aplicação, iremos destacar alguns comandos que serão utilizados em nossa automação.

  1. dotnet tool install dotnet-ef
dotnet tool install --global dotnet-ef --version 6.0.4

Faça a instalação da ferramenta dotnet-ef, possibilitando a execução das operações com as migrations;

* Para este exemplo utilizaremos a versão 6.0.4

2. dotnet ef migrations add

dotnet ef migrations add <<NOME_DA_MIGRATION>> --context OSeuDbContext --startup-project ./ex-path/start-up-project/ --project ./ex-path/db-project/

Comando necessário para geração das migrations, a partir dos arquivos gerados iremos controlar a execução dessas alterações na base de dados;

* Para que você consiga simular o funcionamento posteriormente é necessário que você tenha ao menos uma migration gerada;

3. dotnet ef migrations list

dotnet ef migrations list --context OSeuDbContext --startup-project ./ex-path/start-up-project/ --project ./ex-path/db-project/

Retorne a listagem das migrations aplicadas e pendentes do Context do seu projeto;

4. dotnet ef migrations script

dotnet ef migrations script  <<FROM>> <<TO>> -o ./script.sql --context OSeuDbContext --startup-project ./ex-path/start-up-project/ --project ./ex-path/db-project/

Gere um arquivo script .sql a partir do intervalo das migrations especificado em <<FROM>> <<TO>>. A seguir esses parâmetros serão úteis para geração do nosso script de rollback;

5. dotnet ef database update

dotnet ef database update --context OSeuDbContext --startup-project ./ex-path/start-up-project/ --project ./ex-path/db-project/

Aplique as alterações pendentes na base de dados, baseado nos arquivos de migration do seu projeto.


Gitlab CI/CD

Partindo desta revisão dos comandos do Entity Framework, agora podemos ir para a implementação deles em nosso pipeline. O objetivo é criar um job para ser responsável pela atualização da base de dados a cada nova migration gerada.

Para deixarmos mais organizado e reutilizável a solução criaremos este job como um template no Gitlab e apenas iremos consumi-lo em nossa aplicação posteriormente. Dessa forma basta seguirmos o padrão de uso em todos os nossos projetos.

  • Considerando que você já tenha uma noção da estrutura de arquivos de configuração de CI/CD, a estrutura base do nosso job database.gitlab-ci.yml será a seguinte, caso você não possua um repositório para armazenamento dos seus templates sugiro cria-lo.
Estrutura base

Conforme é possível observar, na estrutura acima não está contido nada do que foi descrito anteriormente. Os comandos do Entity Framework estarão no template .job_template utilizado internamente pelo job:

Job template
.job_template

Caso você esteja pensando de onde surgirá as variáveis $DATABASE_CONTEXT, $STARTUP_PROJECT_PATH e $DATA_PROJECT_PATH, falaremos disso em breve.

O fluxo de execução consiste basicamente em cinco etapas:

  1. Instalação das dependências;
  2. Definição das variáveis de ambiente;
  3. Build da aplicação;
  4. Geração do script de rollback, ao final do processo esse arquivo é armazenado nos artefatos do Gitlab;
  5. Aplicação das alterações na base de dados;

Este template interno é interessante para a reutilização dos comandos em outros jobs no mesmo arquivo, caso você possua múltiplos ambientes, por exemplo:

Exemplo de outros jobs para os ambientes de staging e production:
  • Finalizada a construção do nosso template, podemos agora consumi-lo a partir do pipeline de outros projetos da seguinte forma:
Exemplo de consumo do template database.gitlab-ci.yml a partir do pipeline de outro projeto

Observações:

  1. Neste ponto estamos definindo as variáveis $DATABASE_CONTEXT, $STARTUP_PROJECT_PATH e $DATA_PROJECT_PATH, que serão utilizadas no job criado a partir do template database.gitlab-ci.yml;
  2. O caminho do projeto e o nome do template pode mudar dependendo de onde e como você salvar o seu template.

Considerações finais

Conforme mencionado anteriormente, a solução proposta é uma alternativa relativamente simples e ágil de ser implementada que não exige nada além do ferramental básico que um Desenvolvedor .NET utiliza diariamente para o gerenciamento de migrations com o Entity Framework.

Além disso, é importante destacar que algumas melhorias ainda podem ser feitas neste exemplo, caso seja necessário a execução do script de rollback, o mesmo exige ação manual do Desenvolvedor ou DBA.

Por fim, tudo dependerá do seu contexto e know-how. Eventualmente outras ferramentas específicas para resolver este problema podem ser mais adequadas.


Referências

  • https://learn.microsoft.com/en-us/dotnet/core/tools/dotnet-tool-install
  • https://learn.microsoft.com/en-us/ef/core/managing-schemas/migrations/?tabs=dotnet-core-cli
  • https://docs.gitlab.com/ee/development/cicd/templates.html

Outras publicações