paint-brush
Prática de CI/CD: um fluxo de trabalho de integração contínua simples, mas funcional [Parte 1]por@j04n
3,622 leituras
3,622 leituras

Prática de CI/CD: um fluxo de trabalho de integração contínua simples, mas funcional [Parte 1]

por Joan Flotats6m2023/09/05
Read on Terminal Reader

Muito longo; Para ler

Li dezenas de artigos sobre o assunto e experimentei a implementação de um pipeline de CI/CD ponta a ponta. A realidade é que implementar um pipeline de CI/CD é muito mais complexo do que ler artigos, compreender o panorama geral de CI/CD e usar a teoria. Este artigo explica como construir um exemplo de pipeline de CI mínimo viável de um aplicativo Python.
featured image - Prática de CI/CD: um fluxo de trabalho de integração contínua simples, mas funcional [Parte 1]
Joan Flotats HackerNoon profile picture
0-item
1-item


CI/CD é um dogma de desenvolvimento de software bem estabelecido. A Internet está cheia de artigos e páginas falando sobre CI/CD. Eles sempre têm a mesma imagem CI/CD . Aposto que você conhece a imagem da qual estou falando.


Li dezenas de artigos sobre o assunto e experimentei a implementação de um pipeline de CI/CD ponta a ponta. A realidade é que implementar um pipeline de CI/CD é muito mais complexo do que ler artigos, compreender o panorama geral de CI/CD e usar a teoria. O desenvolvimento de um pipeline de CI/CD requer equipes interdisciplinares e experientes.


Este artigo explica como construir um pipeline de CI mínimo viável de um aplicativo Python. Você pode adaptar o conteúdo do artigo para outros idiomas e requisitos. O exemplo usa FastAPI e GitHub Actions.


CI: Integração Contínua

Deixe-me acrescentar meus dois centavos às descrições existentes de integração contínua. A integração contínua significa mesclar regularmente alterações de código testadas, aprovadas e entregues automaticamente no repositório do projeto.


Este exemplo usa GitHub Actions para executar automaticamente as verificações necessárias em cada evento 'Pull Request' ou 'Push to Main' para garantir que o código atenda aos padrões de qualidade do repositório. O mercado oferece uma coleção diversificada de ferramentas de CI/CD: Jenkins , Travis , CircleCI , GitLab, etc.


O fluxo de trabalho de exemplo verifica se o novo código segue as regras de formatação em execução pre-commit . Em seguida, executa os pequenos testes utilizando Pytest e, por fim, os médios instalando a aplicação Helm Chart em um cluster Kin D.


Seu fluxo de trabalho de integração contínua dependerá do tamanho da equipe, da maturidade, dos requisitos do aplicativo e da estratégia de ramificação.

Análise de código estático

Analise as alterações no código sem executá-las. As ferramentas de análise estática verificam se o seu código segue as regras de formatação, não usa dependências obsoletas ou corrompidas e é legível e simples o suficiente. Eles também sugerem codificação de antipadrões e bugs dependendo da linguagem de programação.


Explicaremos como instalar, configurar e executar o Pré-commit. Você pode combinar o Pre-commit com outras ferramentas de análise como Sonar ou Synk .

Pré-comprometer

Pré-commit é uma ferramenta escrita em Python. Configurá-lo em seu repositório é tão simples quanto criar um arquivo YAML e adicionar os ganchos versionados que você deseja executar antes de cada commit. O pré-commit gerencia automaticamente as dependências exigidas pelos ganchos e corrige automaticamente os erros encontrados. Suporta vários tipos de arquivo: JSON, YAML, tf, py, ts, etc.


Economize custos de infraestrutura executando localmente suas verificações de código antes de enviá-las. Você pode executar o Pre-commit no seu CI para verificar o formato do código enviado.


Instale, configure e execute a ferramenta Pre-commit:


 repos: - repo: https://github.com/pre-commit/pre-commit-hooks rev: v2.3.0 hooks: - id: check-yaml - id: end-of-file-fixer - id: trailing-whitespace


 $ pip install pre-commit $ pre-commit install $ pre-commit run --all-files


Sugestões de ganchos Python:

  • Mypy: verificador de tipo estático para Python
  • Ruff: verificador de formato estático para Python
  • Refurb: Sugira práticas recomendadas de codificação para Python
  • Commitizen: Garanta o uso de commits padrão e gerenciamento de versão


Teste

As definições e o escopo dos testes de unidade, integração e ponta a ponta às vezes são difusos. Assim como fiz com a descrição da Integração Contínua, acrescentarei meus dois centavos aos tipos de teste de Engenharia de Software no Google :


  • Pequeno : testes rápidos. Teste pequenos pedaços de código. Use testes duplos ou ambientes simulados (por exemplo, SQLite). Não é necessário construir nenhum artefato. Tempo: ~ 60 segundos.

  • Médio : teste a interação entre vários trechos de código. Eles podem incluir a construção dos artefatos, o uso de artefatos de terceiros (por exemplo, banco de dados ) e a conexão à rede localhost. Uso de ambientes falsificados (por exemplo, docker-compose, Kind, Minikube, etc.) ou serviços externos (por exemplo, Azure Blob Storage ou AWS S3). Tempo: ~ 300 segundos.

  • Grande : Eles usam ambientes semelhantes aos de produção (por exemplo, testes de desempenho). Tempo: + 900 segundos.


Ter ou não testes de médio/grande porte em seu pipeline de integrações contínuas depende de seus requisitos.

Pequeno

O exemplo usa Pytest para executar os testes e o cliente de teste FastAPI para simular o ambiente. Sem segredos; sua ferramenta de teste de linguagem de programação deve fornecer todas as dependências necessárias para testar seu aplicativo.


Além disso, você pode adicionar uma verificação mínima de cobertura de teste e carregá-la como parte de seus resultados. A cobertura do teste é uma métrica complicada. Uma alta cobertura de teste não significa implicitamente ter um código bem testado, mas 50% é mais do que 0% de código testado.

Médio

Kin D é um cluster Kubernetes leve docker-in-docker usado para desenvolvimento local ou CI. Usamos Kind para configurar um ambiente de teste e executar os testes nele:


  1. Crie o cluster Kind
  2. Construir a imagem Docker
  3. Carregue a imagem do Docker para o tipo
  4. Instale o MetalLB e aplique os CDRs necessários
  5. Instale o Ingress-Nginx
  6. Instale seu gráfico Helm
  7. Configure o host do seu sistema operacional


Carregar imagens do Docker

O Kind não conseguirá baixar sua imagem porque ela não pode ser baixada de um registro. Kind requer que a imagem seja carregada antes de usá-la.

MetalLB

MetalLB é um balanceador de carga bare metal do Kubernetes. Leia mais sobre por que um balanceador de carga é necessário na página do MetalLB .


Depois de instalado usando o Helm Chart, podemos criar os CRDs necessários:


 --- apiVersion: metallb.io/v1beta1 kind: L2Advertisement metadata: name: kind-advertisement --- apiVersion: metallb.io/v1beta1 kind: IPAddressPool metadata: name: kind-address-pool spec: addresses: - "172.26.255.0/24"


Docker cria uma sub-rede para o cluster Kind (por exemplo, 172.26.0.0/16). Inspecione a interface de rede Kind para saber o intervalo de endereços IP atribuído e use o endereço como um valor para o recurso IPAddressPool. Mais informações sobre a configuração do MetalLB estão na página do KinD .

Expor aplicativo

Instale o gráfico Helm do Ingress-Nginx. Em seguida, instale sua aplicação Helm Chart, definindo um objeto Ingress. Defina a propriedade ingressClassName como nginx e defina um host (por exemplo, api.local). Finalmente, modifique o /etc/host para anexar a seguinte linha:


 192.168.1.10 api.local


Você pode definir quantos hosts desejar, apontando para o mesmo endereço. Nginx fará o resto.


Desenvolva uma ferramenta para iniciar, atualizar e excluir um ambiente local usando Kind. Os desenvolvedores podem usá-lo para depurar facilmente o aplicativo, reproduzir bugs relatados localmente ou executar o teste no CI.


Este exemplo funciona para distribuições baseadas em Linux. Para Windows/MacOS pode não funcionar como está, podem ser necessárias alterações.

Entrega

Antes de entregar os artefatos necessários, o fluxo de trabalho executa as etapas de linting e teste.


Usamos o Commitizen para gerenciar as liberações dos artefatos. O Commtizen atualiza automaticamente a versão do artefato e envia as alterações. Ele cria uma nova tag git com o formato de tag configurado. Você também pode configurar o Commtizen para atualizar seu Changelog com as alterações mais recentes.


 [tool.commitizen] tag_format = "v$major.$minor.$patch" version_scheme = "semver" version_provider = "pep621" major_version_zero = true update_changelog_on_bump = true version_files = [ "charts/ci-example/Chart.yaml:version", "charts/ci-example/Chart.yaml:appVersion" ]


O fluxo de trabalho usa a versão de saída Commitizen para definir a tag Docker Image e Helm Chart.


Você pode ter versões diferentes para cada artefato (Imagem e Gráfico). Mas então as alterações do gráfico e da imagem devem ser compatíveis com versões anteriores. Isso adicionará complexidade ao processo de desenvolvimento e lançamento. Para evitá-lo, usamos a mesma versão para ambos os artefatos.


Conclusões

Este artigo esboça um fluxo de trabalho de integração contínua simples, mas funcional. Podem ser necessárias alterações para funcionar em outras linguagens de programação ou atender aos seus requisitos, mas algumas etapas devem ser facilmente exportáveis e funcionar como estão.


Prática de CI/CD: implantação contínua [parte 2] em breve…