Padronizando seu código através dos Git Hooks
Tags: git, laravel, php, braziliandevs
Published: 2024-03-06 14:02:15

## Introdução

No universo do desenvolvimento de software a padronização e consistência de um código são questões importantes. Porém, alcançá-las não é uma tarefa tão trivial, principalmente quando se trabalha em equipe. Neste contexto, os Git Hooks surgem como uma alternativa para lidar com estas questões, uma vez que permitem adicionar ações personalizadas durante o ciclo de vida do desenvolvimento de software.

## O que são os Git Hooks

Basicamente os Git Hooks são scripts executados automaticamente sempre que um evento é executado em um repositório git, alguns desses eventos são, por exemplo, um commit ou um push.

Ao iniciar um repositório do git, automaticamente os Git Hooks são criados no projeto, eles são basicamente scripts shell que vivem na pasta `.git/hooks` do seu projeto. Porém, incialmente eles não são executados, pois possuem uma extensão `.sample`, para serem executados basta remover esta extensão. (É importante que estes arquivos tenham permissão de execução)


![mostra a criação dos git hooks](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/o22la0bwvlt9a8o0q3kd.gif)

Como ilustrado na figura acima, são criados inúmeros hooks logo na inicialização do repositório git, alguns dos hooks mais utilizados são:
- `pre-commit` (me atentarei apenas a este hook)
- `prepare-commit-msg`
- `commit-msg`
- `post-commit`
- `post-checkout`
- `pre-rebase`

### O pre-commit Hook

Assim como o nome sugere, este hook é disparado assim que o comando `git commit` é executado. Como o nosso objetivo é garantir a consistência e a padronização do código, este hook pode ser um grande aliado, pois com ele é possível, por exemplo, executar os testes automatizados do projeto para garantir que o commit atual não quebre uma funcionalidade existente, ou também é possível executar algum `code sniffer` para verificar se o código segue os padrões definidos. 

Caso o commit tenha alterações que quebrem algum dos testes automatizados ou não estejam no padrão do code sniffer, o commit não será executado, o que evitará que chegue ao repositório de produção qualquer código fora do padrão ou que quebre alguma funcionalidade existente.

### O problema dos Hooks em equipe

Os Git Hooks são grandes aliados durante o desenvolvimento e permitem garantir a consistência e o padrão de codificação, porém, temos um problema quando o trabalho em equipe entra em cena, uma vez que os hooks não são versionados, então, não seria possível os membros terem as versões atualizadas dos hooks. Contudo, existem alguns gerenciadores que auxiliam nessa situação como o caso do [Husky](https://typicode.github.io/husky/) e do [CaptainHook](https://github.com/captainhookphp/captainhook) (que irei mostrar neste post).

## O CaptainHook

O **CaptainHook** é uma biblioteca PHP responsável por gerenciar os Git Hooks de um projeto. Através dele é possível configurar ações dos hooks através de um arquivo `.json`, o que facilita bastante a configuração, pois normalmente estas são configuradas utilizando `shell script`.

Com este arquivo de configuração `.json` o captainhook consegue "transformar" as instruções em formato shell script nos arquivos dentro da pasta `.git/hooks`. Uma vez que o arquivo json é versionado, todos os membros da equipe terão os git hooks atualizados e sempre iguais. 

### Como instalar

Acesse a [documentação](https://captainhookphp.github.io/captainhook/) para mais detalhes.

A instalação é bem simples e pode ser feita através do composer:

```bash
composer require --dev captainhook/captainhook
```

Para garantir que os membros da equipe utilizem os mesmos hooks você pode executar o comando a seguir, assim a cada `composer install` ou `composer update` os hooks serão ativados, responda às perguntas conforme a sua necessidade:

```bash
composer require --dev captainhook/plugin-composer
```

### Como configurar

Com o CaptainHook instalado é hora de criar o arquivo de configuração que se chamará `captainhook.json`, este arquivo conterá as ações a serem realizadas nos hooks do seu projeto, este arquivo é criado com o seguinte comando:

```bash
vendor/bin/captainhook install
```

Ele lhe permitirá escolher quais hooks você quer instalar e criará o arquivo de configuração, por enquanto instalarei apenas o pre-commit hook:

![instalaçaõ do captainhook](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/myqn945ibubo4mbtonwp.png)

Após as configurações o captainhook irá criar um arquivo de configuração parecido com este, onde temos o nome do hook, se ele está ativado ou não e as ações que devem executadas em cada hook:

```json
{
    "commit-msg": {
        "enabled": true,
        "actions": []
    },
    "pre-commit": {
        "enabled": true,
        "actions": []
    },
}
```

### Definindo ações para o pre-commit

Antes de mais nada é importante garantir que um novo commit não quebrará as funcionalidades já existentes no projeto, então nossa primeira ação será executar os testes antes de cada commit, para isso utilizarei o [Pest PHP](https://pestphp.com/) e modificarei o arquivo de configuração da seguinte forma:

```json
"pre-commit": {
     "enabled": true,
     "actions": [
        {
            "action": "vendor/bin/pest --parallel"
        }
     ]
},
```

Um exemplo de teste utilizando o Pest seria algo assim, neste momento o teste deveria passar:

```php
test('1 + 1 equals 2', function () {
  expect(1 + 1)
    ->toBe(2);
});
```

Agora com o hook devidamente configurado, a cada commit que fizer o captainhook deveria executar os testes primeiramente, caso os teste falhem ele deve cancelar o commit:

![resultado captainhook apenas testes](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/czitlpm8aqz1bwub08p8.png)

Outro ponto mencionado anteriormente que é de extrema importância, é a padronização do estilo de código. Vamos adicionar um padronizador de estilo de código chamado [Laravel Pint](https://laravel.com/docs/10.x/pint) às nossas ações de `pre-commit`:

```json
"pre-commit": {
     "enabled": true,
     "actions": [
        {
            "action": "vendor/bin/pest --parallel"
        },
        {
            "action": "vendor/bin/pint --test"
        }
     ]
},
```
Com isso temos as duas ações executadas a cada commit, outras ações poderiam ser adicionadas tranquilamente caso fosse necessário, como, por exemplo, uma ferramenta de análise estática de código poderia ser adicionada como, por exemplo, o **PHPStan** ou o **Larastan**, o que mostra o poder e a facilidade de se utilizar o captainhook.

![resultado captainhook testes e pint](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ph0xjzta4rrddmf9qolw.png)

## Conclusão

Os Git Hooks são ferramentas poderosas que auxiliam no desenvolvimento de software, principalmente quando se trabalha em equipe. Neste post apresentei algumas possibilidades do hook `pre-commit` que permite executar ações antes que um código seja commitado, ações como, executar testes automatizados, analizadores de códigos, entre outras, além disso, conhecemos o **CaptainHook**, que permite que os membros de uma equipe tenham acesso e configurem os hooks de forma fácil e intuitiva, por meio de um arquivo em formato `.json`. Utilizando - se de tais ferramentas, o código desenvolvido em equipe ou até mesmo em projetos pessoais se tornará muito mais padronizado e dificilmente receberá bugs que já haviam sido corrigidos.