Um (pequeno)guia para verificar o padrão de commits no git usando huksy 7.x: Parte 1

Thiago Lopes Silva
6 min readJan 29, 2022

--

Olá pessoal, neste post irei criar um pequeno guia sobre como aumentar a qualidade do seu código através do uso do huksy 7.X para verificar o padrão do commit no hook commit-msg do git.

Mas antes precisamos conversar um pouco sobre o breaking change que aconteceu do husky 4.x para o 5.x

No husky versão 4.X no hook commit-msg do git, era possível ler as informações do commit através da variável de ambiente HUSKY_GIT_PARAMS “setada” pelo husky.

O valor da variável de ambiente HUSKY_GIT_PARAMS enviada pelo husky irá ter o caminho do arquivo gerado pelo git contendo a mensagem do commit.

Logo, podemos ler o conteudo deste arquivo gerado pelo git quando o hook de commit-msg é lançado, porém no husky 7.x temos o problema do desuso daesta variável de ambiente segundo a documentação oficial abaixo.

Environment variables:

  • HUSKY_SKIP_HOOKS becomes HUSKY.
  • HUSKY_SKIP_INSTALL is removed.
  • HUSKY_GIT_PARAMS is removed. Instead, Git parameters should be used directly in scripts (e.g. $1).
  • PATH for locally installed tools is not automatically set anymore. You'll need to use your package manager to run them.

Fonte: https://github.com/typicode/husky/tree/main/docs

Logo, no husky 7.X devemos substituir a variável de ambiente HUSKY_GIT_PARAMS pelo argumento $1.

Para facilitar o entendimento irei colocar nesta primeira parte do post o uso do commitlint para analisar o padrão do commit e na segundo post irei mostrar como criar regras customizadas sem a necessidade do uso do commitlint para analisar o padrão dos commits.

1. Usando o framework commitlint

O commitlint tem como proposta ajudar na verificação na padronização do commit através de regras pré-estabecidas pelo framework ou através da criação de novas utilizando o conceito de plugins.

Uma das possibildades para facilitar a configuração das regras, seguindos as boas práticas sugeridas pelo site conventional commit pattern, é através do uso do plugin @commitlint/config-conventional no qual já vem com várias regras pré-configuradas usandos estas boas práticas.

Porém antes de tudo, o que precisamos fazer é criar um novo arquivo na raiz do projeto seguindo um dos padrões abaixo

  • .commitlintrc
  • .commitlintrc.json
  • .commitlintrc.yaml
  • .commitlintrc.yml
  • .commitlintrc.js
  • .commitlintrc.cjs
  • .commitlintrc.ts
  • commitlint.config.js
  • commitlint.config.cjs
  • commitlint.config.ts
  • commitlint field in package.json

Fonte: https://github.com/conventional-changelog/commitlint#config

Em seguida colocar o conteúdo abaixo no arquivo, no qual vai seguir as regras do @commitlint/config-conventional.

module.exports = {      extends: ['@commitlint/config-conventional'],}

Por fim, adicionar as dependências das bibliotecas no arquivo package.json e instala-las usando o comando yarn install ou npm install.

"devDependencies": {     "@commitlint/cli": "16.1.0",     "@commitlint/config-conventional": "16.0.0",}

Integrando com o husky 7.x

Para integrar o commitlint com o husky o que devemos fazer é criar um hook no evento commit-msg gerado pelo git, através do uso do comando abaixo que irá utilizar inclusive o novo argumento $1 explicado na seção breaking change.

O comando abaixo precisa apenas ser rodado uma única vez para o hook ser criado.

npx husky add .husky/commit-msg 'npx --no -- commitlint --edit "$1"'

Regras do commitlint

Algo importante que deve ser comentado é que você pode usar as regras pré-definidas do commitlint ou criar algumas customizadas.

Para mais detalhes sobre como usar as regras pré-definidas eu recomendo uma leitura na documentação oficial.

Basicamente vocẽ vai precisar adicionar uma nova regra pré-existente no arquivo criado no passo anterior seguindo a sintaxe abaixo.

Sintaxe:

  • Level [0..2]: 0 disables the rule. For 1 it will be considered a warning for 2 an error.
  • Applicable always|never: never inverts the rule.
  • Value: value to use for this rule.

Fonte: https://github.com/conventional-changelog/commitlint/blob/master/docs/reference-rules.md

Exemplo:

Digamos que o nosso use case é que todo branch deva possuir um dos nomes abaixo.

  • improv
  • build
  • chore
  • ci
  • docs
  • feat
  • fix
  • perf
  • refactor
  • revert
  • style
  • test

Bem, para resolver este problema, tudo o que precisamos fazer é usar a rule pré-definida chamada type-enum e preencher os valores do nome esperado do branch no 3 item do array, conforme mostrado no código abaixo.

Para mais detalhes da configuração usada acima você pode dar uma olhada no meu repositório abaixo.

Pronto, todo vez que você rodar o commitlint ele irá verificar se o seu branch esta de acordo com a regra acima.

Regras customizadas no commitlint

No cenário onde você vai precisar criar suas regras customizadas é recomendável criar um novo plugin seguindo a documentação oficial.

Para exeplificar, digamos que precisamos verificar se o nome do branch tem o padrão de uma task do jira seguindo o padrão “project-number”, ou seja, “project-1020”.

Como iremos verificar este ponto? Uma boa alternativa seria usarmos regex como iremos ver a seguir.

Primeiro, vamos precisar criar o nosso regex para identificar o pattern do branch, conforme código abaixo.

/project-[0-9]+$/gm

Você pode usar o site https://regex101.com/ para testar o seu regex ou até mesmo criar um novo. Neste site tem uma documentação bem vasta que irá ajuda-lo a construir o regex que atenda as suas necessidades.

Em seguida vamos precisar criar um novo plugin com uma nova regra chamada type-enum/check-jira-branch-pattern que terá como objetivo verificar o padrão do branch do jira usando o regex, de acordo com o código abaixo.

Por ultimo, vamos precisar adicionar o parseOpts para o commitlint utilizar o hyphen como parte do parse do nome do branch, desabilitar a regra type-enum para não verificar o padrão do branch extendido da configuração @commitlint/config-conventioinal e finalmente usar a nossa nova regra, conforme descrito na linha 24 na propriedade Rules.

Com o intuito de facilitar o entendimento da criação de uma regra customizada no commitlint, eu convido vocẽs a lerem o fluxograma abaixo.

fluxograma de criação de regras customizadas

Logo, após a gente definir estas regras customizadas no nosso arquivo commitlint.config.js o commitlint irá utiliza-las para verificar se a mensagem do commit esta de acordo com o padrão regex “project-[número]” e caso tenha algo errado o framework irá expor os erros encontrados, consoante irei mostrar na próxima seção.

Testando as regras com o commitlint CLI

Um detalhe muito importante que me ajudou a testar as regras do meu commit foi através do uso do commitlint CLI.

Basicamente ele é um CLI que irá rodar e verificar se uma mensagem esta de acordo com as regras pré-definidas no arquivo de configuração que criamos acima.

Para rodar o commitlint CLI, é bem simples. Tudo o que precisamos fazer é rodar o comando abaixo em um terminal e para verificar se a nossa mensagem esta de acordo com o esperado.

echo "project-321: random message" | ./node_modules/.bin/commitlint
Commit dentro do padrão esperado

E caso a gente passe algo fora do padrão das regras, então o commitlint irá mostrar os erros encontrados.

echo "project-321E: random message" | ./node_modules/.bin/commitlint

Conclusão

Em síntese espero que esta primeira parte do post tenha ajudado vocês a entender um pouco do poder do commitlint tem em cojunto com o husky para verificar a padronização da mensagem dos commits e principalmente manter a qualidade no projeto.

Não esquecendo que irei escrever uma segunda parte deste post com o objetivo de mostrar como criar regras de verificação de mensagem de commit usando typescript puro sem o uso do commitlint.

Se você gostou do post não esqueça de apertar no 👏.

--

--