Validando os commits do seu projeto
Tags: automation, git, pattern, productivity
Published: 2020-10-23 00:41:47

Em complemento ao artigo anterior [escrevendo commits do jeito certo](https://dev.to/brunohafonso95/escrevendo-commits-do-jeito-certo-5bio), nós já vimos um pouco de como utilizar padrões de commit, mas por conta conventional commit pattern ter uma serie de diretivas a serem seguidas isso faz com que haja uma curva de aprendizado para aqueles que não conhecem o padrões ou que nunca aplicou num projeto.

Mas para isso podemos utilizar algumas ferramentas para nos auxiliar tanto na escrita dos commits quanto validação dos commits escritos nos projetos, e um detalhe importante essa configuração vale apenas para projeto em `nodeJS`, no futuro vou tentar replicar o mesmo artigo para uma forma mais genérica.

# Leque de ferramentas

- [commitlint](https://github.com/conventional-changelog/commitlint)
- [commitizen cli](https://github.com/commitizen/cz-cli)
- [husky](https://github.com/typicode/husky)

# Commitlint

O `commitlint` é uma ferramenta de linha de comando que faz a validação das mensagem de commit de acordo com padrões estabelecidos na configuração, a partir disso quando passamos um commit por ela, ela faz a checagem dos pontos commit de acordo conforme o exemplo abaixo.

![commitlint exemplo 1](https://dev-to-uploads.s3.amazonaws.com/i/q7ah6tgoppqojsod5hdk.gif)
![commitlint exemplo 2](https://dev-to-uploads.s3.amazonaws.com/i/2e2up26pigm1fe3r4sqn.gif)

A ideia é utilizarmos ela para dar um "tapa na mão" de quem não seguir o padrão estabelecido no time para as mensagens de commit.

# Commitzen cli

Vamos pensar na seguinte situação, temos algum novo no time ou até mesmo todos no projeto não estão familiarizados com a escrita de commits utilizando o conventional commit pattern e sendo menos produtivos porque precisam ficar sempre consultando a documentação ou vendo commits anteriores/de outros colegas para garantir que estão seguindo o padrão correto, isso é um cenário que pode ocorrer e que tem um impacto negativo no uso do conventional commit, podendo desencorajar os membros do projeto ou até mesmo fazer como que tomemos a decisão de utilizar o mesmo, mas para isso nós temos uma ferramenta de linha de comando para no ajudar a contornar isso, o `commitzen cli` ele basicamente faz uma seria de perguntas que vamos respondendo para compor o nosso commit conforme podemos ver a seguir.

![commitzen em ação](https://dev-to-uploads.s3.amazonaws.com/i/7j7qgipuh6wet211fl9m.gif)
 

Viu como é simples de seguir os padrões quando temos uma ajudinha, agora não tem mais desculpa pra não começar a adotar o conventional commits nos seus projetos.

![facinho](https://dev-to-uploads.s3.amazonaws.com/i/2iaowt8xkhm0hrfrlbra.gif)

# Husky

Agora vamos ao `husky` e antes que você pergunte, não não é aquele cachorro que a gente vê nos filmes puxando trenó, na verdade ele é um pacote que nos auxilia na criação de git hooks, que nada mais são que gatilhos em que podemos executar algum script, por exemplo podemos rodar um script antes de cada commit, antes do push, na hora de preparar a mensagem de commit e etc.

E nesse caso ele vai nos ajudar da seguinte forma, queremos que antes de efetuarmos um commit ele utilize o commitlint para validar se a nossa mensagem de commit está de acordo com os nossos padrões e se não estiver vai ter um cachorro bem bravo pra morder a sua mão.

![giphy](https://dev-to-uploads.s3.amazonaws.com/i/eheosyiqeydt4az7ejqp.gif)
 
Brincadeira, na verdade o seu commit não vai ser realizado, suas alterações vão ser mantidas mas até que você crie um commit que atenda os critérios você não vai conseguir commitar.

# Configuração

Bom agora chega de teoria e vamos para a prática

1. criando um novo projeto

antes de mais nada precisamos criar um novo projeto e para isso criamos uma pasta e nela executamos:

para criar um projeto com o npm

```bash
# se você quiser responder os detalhes do projeto
npm init

# ou se preferir usar as opções default do projeto
npm init -y
```

para criar um projeto com o yarn

```bash
# se você quiser responder os detalhes do projeto
yarn init

# ou se preferir usar as opções default do projeto
yarn init -y
```

2. configurando o `commitlint`

para configurarmos o `commitlint` instalamos ele como dependência de desenvolvimento

```bash
npm install -D commitlint

# ou com yarn
yarn add -D commitlint
```

e para não precisarmos criar todas as regras do zero e extendermos das regras que temos no conventional commit instalamos o seguinte pacote em modo de desenvolvimento também

```bash
npm install -D @commitlint/config-conventional

# ou com yarn
yarn add -D @commitlint/config-conventional
```

e ai criamos um arquivo na raiz do projeto chamado `commitlint.config.js` com o seguinte conteúdo

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

isso vai fazer com que ao rodarmos o commitlint no projeto ele utilize as regras setadas nesse pacote, mas se for necessário podemos adicionar opções personalizadas da seguinte forma

```javascript
module.exports = {
    extends: ['@commitlint/config-conventional'], rules: {
        'type-enum': [
            2,
            'always',
            [
                'build',
                'chore',
                'ci',
                'docs',
                'feat',
                'fix',
                'perf',
                'refactor',
                'revert',
                'style',
                'test',
                'foo'
            ],
        ],
    }
};
```

nesse exemplo adicionaríamos o tipo de commit `foo` como um tipo válido e poderíamos utilizar ele no nosso projeto, você consegue achar mais opções de configuração [aqui](https://github.com/conventional-changelog/commitlint#config).

3. configurando o `commitzen cli`

Ok agora vamos configurar o `commitzen cli` para isso vamos usar um próprio auxiliar dele com o comando abaixo

```bash
commitizen init cz-conventional-changelog --save-dev --save-exact

# ou usando o yarn
commitizen init cz-conventional-changelog --save-dev --yarn --save-exact
```

o comando acima vai instalar os pacotes necessários e criar uma sessão de configuração no `package.json` conforme descrito a seguir

```javascript
"config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog"
    }
  }
```

nela também pode adicionar configurações extras conforme o exemplo anterior, vamos adicionar a opção do tipo foo como um dos tipos disponiveis no `commitzen cli`

```javascript
 "config": {
    "commitizen": {
      "path": "./node_modules/cz-conventional-changelog",
      "types": {
        "feat": {
          "description": "A new feature",
          "title": "Features"
        },
        "fix": {
          "description": "A bug fix",
          "title": "Bug Fixes"
        },
        "docs": {
          "description": "Documentation only changes",
          "title": "Documentation"
        },
        "style": {
          "description": "Changes that do not affect the meaning of the code (white-space, formatting, missing semi-colons, etc)",
          "title": "Styles"
        },
        "refactor": {
          "description": "A code change that neither fixes a bug nor adds a feature",
          "title": "Code Refactoring"
        },
        "perf": {
          "description": "A code change that improves performance",
          "title": "Performance Improvements"
        },
        "test": {
          "description": "Adding missing tests or correcting existing tests",
          "title": "Tests"
        },
        "build": {
          "description": "Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)",
          "title": "Builds"
        },
        "ci": {
          "description": "Changes to our CI configuration files and scripts (example scopes: Travis, Circle, BrowserStack, SauceLabs)",
          "title": "Continuous Integrations"
        },
        "chore": {
          "description": "Other changes that don't modify src or test files",
          "title": "Chores"
        },
        "revert": {
          "description": "Reverts a previous commit",
          "title": "Reverts"
        },
        "foo": {
          "description": "New type to show custom config",
          "title": "Foo"
        }
      }
    }
  }
```

e pronto o `commitzen cli` já está configurado, podemos adicionar um script de commit, para facilitar o uso dele no projeto

```javascript
"scripts": {
  "commit": "npx git-cz"
}
```

4. configurando o `husky`

Agora vamos configurar o nosso amado `husky` que vai ser o nosso "tapa na mão" caso alguém não siga os padrões de commit definidos no projeto.

!["tapa na mão"](https://dev-to-uploads.s3.amazonaws.com/i/x0towdq1ibxqwi2tzp21.gif)
 
então agora que você foi avisado vamos lá, antes de mais nada precisamos iniciar um reposítório git, porque como o husky cria os git hooks para o git, se o projeto ainda não tiver um reposítório iniciado vamos instalar o husky mas ele não vai funcionar.

inicializamos nosso repositório local
```bash
git init
```

e depois instalamos o husky como dependência de desenvolvimento

```bash
npm install -D husky

# ou com yarn
yarn add -D husky
```
uma vez instalado temos que configura-lo, então vamos criar uma sessão no nosso `package.json` com os hooks que temos que usar

```javascript
"husky": {
    "hooks": {
       "commit-msg": "commitlint -E HUSKY_GIT_PARAMS"
    }
  }
```

5. testando se fizemos tudo certo

se todas as nossas configurações estiverem corretas temos que ter os seguinte resultado.

> commit inválido

![commit inválido](https://dev-to-uploads.s3.amazonaws.com/i/hf280noy1ql19j9ss9r4.gif)

> commit válido

![commit válido](https://dev-to-uploads.s3.amazonaws.com/i/w1upn8gqb6gg4au2sd6d.gif)
 

# Conclusão

![FIM](https://dev-to-uploads.s3.amazonaws.com/i/kh5d13m5kn6pq9ckoqrd.gif)
 
Pronto o artigo foi longo, mas pelo menos temos como recompensa um projeto configurado, seguindo as boas práticas do conventional commit pattern e com uma validação automática a cada commit, o código final desse tutorial você pode encontrar [aqui](https://github.com/brunohafonso95/conventional-commit-initial-nodejs-setup).