Como parte da evolução do GitLab CI, a forma como conhecemos nos permite criar uma CI para nosso projeto, criar um template para diversos projetos que compartilham da mesma stack ou ainda usar uma CI com manutenção centralizada. Porém, quando falamos de componentes, a situação muda um pouco, e é sobre isso que queremos abordar neste artigo: conhecendo o GitLab Componentes e criando o seu primeiro componente.
Estrutura e Funcionamento dos Componentes
Estrutura de um JOB
Antes de mostrar como criar seu primeiro componente, gostaria de falar sobre a anatomia de um. A nível de código, ele é um JOB que permite que você passe inputs, defina valores padrão e ainda adicione descrições em cada um deles. Em outras palavras, isso é um componente:
spec:
inputs:
name:
description: "Defina o nome do JOB"
default: test
stage:
description: "Defina o estagio em que rodará o JOB"
default: test
name_user:
description: "Nome de quem está executando o JOB"
default: test
---
$[[ inputs.name ]]:
script: "Olá $[[ inputs.stage ]]"
stage: $[[ inputs.stage ]]
YAMLCaso essa estrutura inicial te assuste, recomendamos a leitura de: Introdução aos arquivos YAML.
Este é um JOB relativamente simples: ele tem os parâmetros de nome do JOB, estágio em que será executado e ainda uma variável que será usada para imprimir a mensagem de script, até então algo bem simples.
Estrutura de Diretórios
A nível de diretórios, o que esperamos para transformar seu projeto em um componente é que ele tenha uma pasta chamada templates
e, dentro dela, um arquivo com o nome do componente ou uma pasta com o nome do componente. No nosso exemplo prático, vamos demonstrar. Porém, este é o mínimo necessário para a criação de um componente. Além disso, podemos adicionar os arquivos LICENSE.md
, README.md
, e .gitlab-ci.yml
, sendo este último usado para testar nossos componentes.
├── templates/
│ └── meu-componente.yml
├── LICENSE.md
├── README.md
└── .gitlab-ci.yml
YAMLTipos de Componentes Disponíveis
Como comentado anteriormente, você pode criar um componente em um único arquivo ou múltiplos arquivos, o que, na teoria, seria muito bom, uma vez que poderíamos ter o seguinte cenário:
├── templates/
│ └── meu-componente/
│ ├── template.yml
│ ├── Dockerfile
│ └── test.sh
├── LICENSE.md
├── README.md
└── .gitlab-ci.yml
YAMLNesse cenário, todos os arquivos necessários para o funcionamento do meu componente estariam nele, como a documentação sugere. Porém, até a versão 17.3 do GitLab, isso não funciona dessa forma; você precisa, de alguma forma, trazer os arquivos para a área de execução, seja no before_script
, fazendo o clone do componente, ou baixando via API os arquivos necessários. Na prática, atualmente, só temos um tipo de componente.
Boas Práticas para Uso de Componentes
Quando vamos escrever nosso primeiro componente, seja para uso interno ou externo, devemos sempre prestar atenção a alguns pontos:
- Crie descrições claras e objetivas para seus inputs. A ideia de um componente é que ele seja usado sob demanda, ou seja, alguém além de você vai usá-lo e precisará entender o que ele faz.
- Crie uma documentação clara e objetiva.
- Crie repositórios com funcionalidades correlatas. Quando criamos um projeto, podemos incluir alguns componentes que façam sentido no contexto.
- Apesar de possível, mantenha seu projeto sempre com um número pequeno de dependências. Projetos com muitas dependências podem tornar a manutenção extremamente complexa.
- Caso use dependências, mantenha-as sempre atualizadas.
- Faça uso do versionamento semântico.
Criando um GitLab Component
Agora que já entendemos como criar um componente, vamos iniciar um projeto no GitLab onde criaremos o build Maven. A ideia é que, nos próximos artigos, tenhamos todos os componentes criados e possamos usá-los em nosso projeto: Criando uma API Rest com Quarkus: Parte 1
Criando nosso grupo
Como recomendação do GitLab, vamos criar um grupo chamado components
e nele vamos agrupar todos os nossos repositórios de componentes. No nosso exemplo, ficou assim: https://gitlab.com/codeinloop/components
Criando seu primeiro CI/CD Component
A criação de um repositório não difere de um repositório comum, porém ao finalizar a criação, devemos ir em Configurações > Geral e, na aba de “Visibilidade, recursos do projeto, permissões”, marcar a caixa “CI/CD Catalog project”.
É importante destacar que, mesmo após selecionar a opção que transforma seu projeto em um Catálogo CI/CD, ele só terá todas as funcionalidades, como a possibilidade de usar a versão ~latest
, ter a pagina de componente disponível, entre outras funcionalidades, após criar a primeira release. Antes disso, a página retornará 404:
Após criar seu repositório, vamos iniciar nosso arquivo build.yml
e nele identificar nossas variáveis. Nelas, vamos definir nome, valor padrão e descrição. Em alguns casos, como a variável maven_cli
, adicionamos também as opções. Dessa forma, o usuário tem como validar os valores aceitos.
spec:
inputs:
as:
default: 'build'
description: 'Defines the name of this job.'
stage:
default: 'build'
description: 'Defines the stage that this job will belong to.'
jdk_image:
default: 'maven:3.9.8-eclipse-temurin-21-alpine'
description: 'The Docker image containing the JDK and Maven that should be used for this job.'
maven_cli:
default: './mvnw'
options:
- './mvnw'
- 'mvn'
description: 'Command-line interface to use for Maven operations, allowing you to select either the Maven Wrapper (mvnw) or the system-installed Maven (mvn).'
maven_opts:
default: " -Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$CI_PROJECT_DIR/$__CACHE_KEY_HACK -Dorg.slf4j.simpleLogger.showDateTime=true -Djava.awt.headless=true"
description: 'Options to pass to the Maven command via the MAVEN_OPTS environment variable.'
maven_cli_opts:
default: "--batch-mode --errors --fail-at-end --show-version --no-transfer-progress -DinstallAtEnd=true -DdeployAtEnd=true"
description: 'Options to pass to the Maven command-line interface for controlling the build process.'
maven_args:
default: 'package -DskipTests'
description: 'Arguments to pass to the Maven command for specific build goals and properties.'
m2_dir:
default: '.m2/repository'
description: 'Specifies the directory for the local Maven repository where dependencies will be cached.'
target_dir:
default: 'target'
description: 'Specifies the output directory for the build artifacts generated by Maven.'
YAMLAo finalizar as variáveis, o próximo passo é a construção do JOB. Dessa forma, vamos construir:
'$[[ inputs.as ]]':
stage: $[[ inputs.stage ]]
cache:
key: "$__CACHE_KEY_HACK"
policy: push
paths:
- "$__CACHE_KEY_HACK"
artifacts:
paths:
- "$[[ inputs.target_dir ]]"
expire_in: one hour
variables:
__CACHE_KEY_HACK: "$[[ inputs.m2_dir ]]"
MAVEN_OPTS: "$[[ inputs.maven_opts ]]"
MAVEN_CLI_OPTS: "$[[ inputs.maven_cli_opts ]]"
MAVEN_ARGS: "$[[ inputs.maven_args ]]"
image:
name: '$[[ inputs.jdk_image ]]'
script:
- "$[[ inputs.maven_cli ]] $MAVEN_ARGS"
YAMLEstamos definindo de forma dinamica o nome do job, stage, cache e artefatos, afinal, não sabemos que vai usar nosso componente, então deiamos ele o mais flexivel possivel. Ao finalizar o JOB, o próximo passo será integrar e testar seu componente.
Testando nosso componente
Finalizando nosso componente, vamos testar-lo, e nesse caso criamos um projeto java, conforme descrito nesse artigo: Criando uma API Rest com Quarkus: Parte 1.
Além disso vamos precisar criar uma ci padrão onde vamos consumir nossos componentes, inicialmente ela ficaria desta forma:
include:
- component: $CI_SERVER_FQDN/codeinloop/components/maven/build@$CI_COMMIT_SHA
inputs:
as: 'build'
stage: 'build'
stages:
- build
YAMLDessa forma estamos indicando que nosso componente se chamará build e rodará na etapa de build, além disso estamos passando a variavel CI_COMMIT_SHA que garante que seja executando sempre no ultimo commit daquela branch de excução, fazendo assim rodar sempre com a ultima versão. vale destacar que essa forma de uso é apenas para testes dentro do componente para testes fora seria usado ~latest, main ou alguma tag espefica do componente.
Localizando outros componentes
Como desde o inicio nossa ideia é criar componentes reutilizaveis, é esperado que tenhamos uma página aonde podemos encontrar todos eles, e para isso não é uma tarefa tão simples, através do menu de busca, você precisa ir para o menu explorar, e só assim aparecerá no menu esquerdo a opção de Ci/CD Catalogo como pode ser visto na imagem abaixo ou nesse link
Vale ressaltar que a página exibe apenas os componentes públicos; porém, caso seu namespace tenha componentes, ele terá uma página própria na aba ao lado.
Como contribuir
Neste momento, temos então nosso primeiro componente criado, e você pode contribuir com ele para torná-lo cada vez melhor para todos. E para isso, é bem simples: basta acessar a página do componente ou nossa namespace. A ideia é que façamos diversos componentes.
Conclusão
Nesse artigo exploramos os principais pontos sobre um componente no gitlab e mostramos como criar um componente, como proximo passo vamos criar uma CI para um projeto usando apenas componentes, o que acha desssa ideia? ficou com alguma duvida? não deixe de comentar.