-
Notifications
You must be signed in to change notification settings - Fork 1
Home
Execute um code-review de forma automática, criando regras personalizadas conforme sua necessidade!
Ou seja, ao abrir um merge request, uma série de verificações serão executadas sobre o merge request, adicionando de forma automática comentários ao merge request, diminuindo assim o tempo gasto com code review em itens básicos, permitindo assim focar mais em verificações voltada a regra de negócio que o merge request está implementando.
A ferramenta Automatic Code Review tem como objetivo realizar a revisão automática de merge requests. Ao abrir um merge, um conjunto de validações serão executadas, automatizando assim o processo de code review.
Essas validações são direcionadas a pontos passíveis de automação, ou seja, pontos que podem ser verificados por algoritmos. Mais a frente nesta documentação, apresentarei algumas ideias e possibilidades de regras que permitam identificar quais pontos podem ser automatizados. Essas regras são adaptáveis às necessidades específicas do projeto e às normas estabelecidas.
Um dos pontos-chaves dessa ferramenta é a flexibilidade oferecida ao usuário para implementar regras personalizadas. Dessa forma, não se limita-se apenas a validações já existentes, possibilitando a verificação de situações específicas conforme a necessidade, seja relacionada ao produto em si ou a requisitos definidos internamente pela equipe de desenvolvimento, como padrões, boas práticas, entre outros pontos.
Em resumo, a ferramenta permite automatizar a identificação de regras recorrentes em merge requests, evitando a necessidade de cobrança manual em pontos específicos. Por exemplo, se uma regra específica sempre surge nos merge requests, pode-se automatizar a inclusão de um comentário no próximo merge que apresentar esse detalhe. A ideia central da ferramenta é proporcionar esse tipo de automação, visando otimizar o processo de revisão de código.
Se um detalhe sempre volta a acontecer nos merges requests, porque não tirar um tempo para criar um algoritmo que valide esse detalhe de forma automática?
O tempo que será gasto para automatizar, não poupará um tempo no futuro? Ou ainda, não evitará que por algum deslize esse detalhe passe no merge request?
Se você precisou comentar duas vezes sobre a mesma situação, considere criar um algoritmo para automatizar essa validação
Uma possível pergunta que pode surgir, que já quero responder, é a seguinte
Por que "reinventar a roda" quando se tem tantas ferramentas disponíveis, como Sonar, Veracode, Cppcheck, Uncrustify, CodeFactor, entre outras?
Entenda que a ferramenta nada mais é do que um agrupador de validações. O objetivo é permitir que você possa utilizar várias ferramentas de seu interesse em um único processo de revisão, além de possibilitar a criação de regras específicas de forma simples. Por exemplo, se você deseja usar o Sonar, que é uma ferramenta robusta, sem problemas, vamos utilizá-la, quer usar o Cppcheck, vamos usar também, vamos unir essas duas ferramentas em um único fluxo. E se em algum momento, você não encontrar uma ferramenta que atenda a uma determinada necessidade, ou se configurá-la e implementá-la for complexa, ou ainda se estiver disponível somente na versão paga, como é o caso de muitas ferramentas, você terá a liberdade de criar essa validação da maneira que considerar mais adequada.
Se a comunidade contribuir para criar extensões para code-review automático, com o tempo teremos uma ferramenta que irá atender muitos cenários, além de acessível, o principal ponto, simples de implementar
Como principais pontos da ferramenta gostaria de citar
- Gratuita
- Fácil de entender
- Fácil de configurar
- Fácil de modificar
- Sem limitação de linguagem
Deixo uma pergunta no ar...
Como podemos usar inteligência artificial para automatizar e melhorar o processo de code review?
Lhe convido a ler mais sobre a ferramenta, e entender a proposta, talvez esses minutos de leitura lhe poupem horas no futuro
- Sistema de controle de versão
- Plataforma de hospedagem de código
- GitLab
- GitHub
- Linguagem usada no desenvolvimento da ferramenta
- Vale pontuar que as extensões podem ser desenvolvidas em outras linguagens.
- GIT_TYPE
- Plataforma de hospedagem de código
- GIT_LAB
- GIT_HUB
- Plataforma de hospedagem de código
- GIT_URL
- Host do serviço de hospedagem de código
- GIT_USER
- Usuário com permissão no projeto
- GIT_TOKEN
- Token de acesso referente ao usuário
- GIT_PROJECT
- ID do projeto
- GIT_MERGE_REQUEST_ID
- ID do merge request
- STAGE
- Stage da executacao, caso nao informado possui o valor default como "default"
- SOURCE_PATH
- Caminho para um projeto ja clonado, dessa forma para o código source não sera feito um clone em tempo de execução, apenas ira apontar para o path ja existente, posibilitando assim rodar o review sobre um código pre processado, como por exemplo um código c++ compilado
- Caso a propriedade não seja informada, ira efetuar o clone normalmente do projeto source
Vou citar alguns pontos que me fizeram iniciar o desenvolvimento da ferramenta
Trabalho com desenvolvimento de software desde 2016, tive muito contato com o processo de code review, tanto como desenvolvedor como tech lead
Já estive no lugar do desenvolvedor que entrega um código e acaba deixando passar alguns detalhes, até porque revisar o proprio código que você passou horas e horas desenvolvendo torna difícil enxergar alguns detalhes
Também já estive no lugar de quem revisa o código, e por inúmeras vezes acaba encontrando o mesmo detalhe em merges e mais merges, detalhes que de pouco em pouco vão impactando no tempo de entrega das demandas
Vamos imaginar que se eu abro um merge request, horas depois algum comentário é adicionado, dificilmente eu vou ver na hora, então o merge ficará pendente, e quando a correção for feita, provavelmente o review tambem nao vai ser logo na sequência, fora que mesmo que o review seja feito na sequência, terá o custo de rodar novamente as pipelines
Basicamente o que estou querendo dizer é
O quanto mais cedo identificarmos um problema, mais cedo ele será resolvido
Desde sempre ajudei no processo de code review, tanto como desenvolvedor como tech lead, é muito visível que o code review e um processo muito importante do desenvolvimento de software
Quanto maior o projeto ficar, quanto maior o time ficar, mais difícil e demorado vai ser efetuar o code review, no início trabalhei com uma equipe de cinco desenvolvedores, o tempo gasto em code review era muito baixo, e o code review era muito efetivo, em outro momento trabalhei com um time que chegou a vinte desenvolvedores, ou seja o fluxo de merge é muito maior, detalhe importante que não estou querendo dizer que o code review tenha que ser feito de forma mais flexível, deixando detalhes de lado, mas sim que precisamos de alguma forma automatizar o que pode ser automatizável
Sendo sincero?
Gosto do desafio de automatizar as coisas, o que sempre falo e, se você precisou fazer a mesma coisa duas vezes, pense em como automatizar esse processo
Em resumo, a ferramenta funciona da seguinte maneira: ela busca os dados do merge request, clona o projeto tanto na branch source quanto na branch target, remove os arquivos que não estão listados nas alterações e, em seguida, itera sobre a lista de extensões. Para cada extensão, a ferramenta executa uma série de etapas, e em seguida, busca os comentários existentes no merge request, adiciona novos comentários e resolve os comentários que não estão mais presentes na validação. Quando o código é alterado resolvendo o detalhe que gerou um comentário, ele é resolvido automaticamente, sem a interação do usuário.
Vamos entender em detalhes cada etapa:
Essa etapa é responsável por configurar o ambiente de trabalho.
- Buscar dados do merge request: A ferramenta chama a API da plataforma de versionamento de código para obter os dados relevantes do merge request, como URLs para clonagem dos projetos, branches source e target, título, lista de arquivos alterados, entre outros.
- Clonar projeto: Os projetos referentes às branches source e target são clonados, criando cópias locais para análise.
- Remover arquivos não relacionados ao merge: Iterando sobre os arquivos e pastas de cada repositório clonado, são removidos todos os arquivos que não estão listados nas alterações. Dessa forma, apenas os arquivos que sofreram alterações no merge request permanecem nas pastas.
Nesta etapa, a ferramenta itera sobre a lista de extensões e executa uma série de passos para cada extensão.
- Carregar as configurações da extensão: A ferramenta carrega as configurações da extensão a partir de um arquivo
config.json
. - Gerar nova configuração: É gerado um novo arquivo
config.json
, combinando as configurações previamente definidas com as configurações em tempo de execução, como o caminho dos projetos source e target, o caminho onde o arquivooutput.json
será gerado e os dados do merge request. - Executar a extensão: A extensão é executada conforme o seu desenvolvimento específico, gerando um arquivo
output.json
com uma lista de comentários. - Carregar o arquivo
output.json
: O arquivooutput.json
é carregado e os comentários são adicionados a uma lista de comentários. - Referente aos comentarios, devem seguir o seguinte formato
- id
- campo obrigatório
- deve ser unico na lista de comentarios
- comment
- campo obrigatório
- formato markdown
- position
- nao obrigatório
- se refere ao arquivo e linha relacionado ao comentario
- language
- nao obrigatório
- linguagem do code snipset
- path
- obrigatório
- caminho do arquivo
- startInLine
- obrigatório
- linha inicial
- endInLine
- obrigatório
- linha final
- snipset
- nao obrigatório
- se deve adicionar o respectivo codigo ao comentario
- possui default True
- language
- id
{
"id": "...",
"comment": "...",
"position": {
"language": "..",
"path": "...",
"startInLine": 0,
"endInLine": 0,
"snipset": True
}
}
- O arquivo config.json gerado nesse passo possui os seguintes dados inseridos em tempo de runtime, alem dos dados do config.json referente a extensão em si
{
"path_target": "...",
"path_source": "...",
"path_output": "...",
"merge": {
"git_type": "...",
"title": "...",
"changes": [
{
"diff": "...",
"new_path": "...",
"old_path": "...",
"a_mode": "...",
"b_mode": "...",
"new_file": false,
"renamed_file": false,
"deleted_file": false
}
],
"branch": {
"target": "...",
"source": "..."
},
"project_id": "...",
"merge_request_id": "..."
}
}
Nesta etapa, os comentários obtidos na etapa de revisão são publicados no merge request.
- Buscar comentários existentes: Os comentários já existentes são buscados, filtrando pelo usuário especificado. Esse usuário deve ser exclusivo para os comentários da ferramenta.
- Verificar comentários já existentes: É verificado quais comentários já estão presentes no merge request e não precisam ser adicionados novamente. Mesmo que um comentário já esteja resolvido, ele é considerado como existente.
- Verificar comentários a serem resolvidos: São verificados quais comentários estão presentes no merge request, mas não foram retornados na etapa de revisão. Esses comentários foram corrigidos e não são mais relevantes. Portanto, devem ser resolvidos.
- Adicionar novos comentários: São adicionados os novos comentários obtidos na etapa de revisão.
Por fim, caso haja pelo menos um comentário não resolvido relacionado a ferramentas, a execução é considerada como falha. Isso permite que a pipeline do merge request seja tratada como falha, interrompendo a execução dos demais passos da pipeline, conforme desejado.
Veja mais sobre o codigo fonte
A extensão acr-regex realiza a verificação de expressões regulares configuráveis em cada arquivo e tambem no título do merge.
Link para a extensão
Exemplo:
Suponha que, em arquivos .cpp e .h, seja necessário encontrar todos os comentários "//TODO" que nao possuem uma descricao. Nesses casos, um comentário será adicionado ao merge com a mensagem "Explicar do que se trata o TODO".
Ja na parte do merge, vamos imaginar que para garantir um boa rastreabilidade das demandas, todo merge deve conter o número da atividade no formato #PRO-XXX no título, se um merge for aberto sem esse número, um comentário será adicionado automaticamente ao merge.
A extensão acr-dont-edit verifica se um arquivo no merge request não permite alteração, em casos que apos aceitar o merge não se pode alterar o conteudo do arquivo, como por exemplos migrations de banco
Link para a extensão
A extensão acr-assigned verifica se o merge request possui um assigned
Link para a extensão
A extensão acr-logs-qt verifica se os logs em cada arquivo estão em conformidade com o padrão configurável. Essa verificação é específica para logs que utilizam o framework Qt.
Link para a extensão
Exemplo:
Suponha que exista um padrão definido no projeto em que todos os logs devem conter o nome da classe entre colchetes no início da linha do log, como por exemplo: "qInfo() << "[MyClass] Processando...";". Caso algum log não esteja nesse padrão, um comentário será adicionado ao merge, informando sobre o log que está fora do padrão estabelecido.
A extensão acr-cpp-unused-using verifica se os using declarados no arquivo, estão realmente sendo utilizados.
Link para a extensão
Exemplo:
O using X nao esta sendo utilizado no arquivo Y.
A extensão acr-cpp-member verifica se os atributos de um header (c++) respeitam as regras configuradas. As regras disponiveis estão documentadas no README.md da propria extensao.
Link para a extensão
Exemplo:
Os atributos do tipo private, devem possuir o prefixo _
.
A extensão acr-branch verifica se as branches source e target são equivalentes.
Link para a extensão
Exemplo:
Suponha que seja um requisito que a branch source e a branch target tenham o mesmo nome, especialmente ao trabalhar com forks por usuários, em que o merge request é direcionado ao fork principal. Caso as branches não tenham o mesmo nome, será gerado um comentário indicando a necessidade de ajustar a branch target para que sejam equivalentes.
A extensão acr-sonar realiza a verificação de problemas de código nos arquivos, utilizando a ferramenta SonarQube.
Link para a extensão
Exemplo:
A análise do código pode variar dependendo da linguagem e das configurações definidas no servidor SonarQube. Por exemplo, se o SonarQube identificar que um método está muito complexo, um comentário será adicionado ao merge, destacando essa questão específica apontada pela análise.
A extensão acr-cpp-cppcheck realiza a verificação de problemas de código nos arquivos, utilizando a ferramenta cppcheck.
Link para a extensão
Exemplo:
Se o cppcheck identificar que em determinado ponto do codigo pode-se utilizar o std::find_if, ou qualquer method relacionado a lib Algorithms, um comentário será adicionado ao merge, destacando essa questão específica apontada pela análise.
OBS: Esta extensão ainda esta em desenvolvimento...
A extensão acr-cpp-include
verifica se os includes em cada arquivo são necessários, exclusivamente para a linguagem C++.
Link para a extensão
Exemplo:
Suponha que em uma classe tenha sido adicionado o include , porém esse include não é utilizado na classe. Nesse caso, o include é considerado desnecessário. Será adicionado um comentário ao merge, informando sobre o include que pode ser removido por não ser utilizado no código.
Vamos precisar criar um workspace para a revisão do código
Exemplo de estrutura de pastas
automatic-code-review-processor
resources
configs
extension-01
config.json
extensions
extension-01
Vamos criar um exemplo usando o acr-regex e acr-branch, a estrutura de pasta ficaria dessa forma
automatic-code-review-processor
resources
configs
acr-regex
config.json
acr-branch
config.json
extensions
acr-regex
acr-branch
Agora vamos para a prática, imaginando que estamos em um ambiente Linux
mkdir -p workspace
cd workspace
git clone https://github.com/automatic-code-review/automatic-code-review-processor.git
cd automatic-code-review-processor
mkdir -p resources/configs/acr-regex
touch resources/configs/acr-regex/config.json
mkdir -p resources/extensions/acr-regex
git clone https://github.com/automatic-code-review/acr-regex.git resources/extensions/acr-regex
mkdir -p resources/configs/acr-branch
touch resources/configs/acr-branch/config.json
mkdir -p resources/extensions/acr-branch
git clone https://github.com/automatic-code-review/acr-branch.git resources/extensions/acr-branch
Em seguida apenas precisamos configurar os arquivos config.json conforme a necessidade
Arquivo resources/configs/acr-regex/config.json
{
"data": [
{
"type": "MERGE_FILE_CONTENT",
"message": "Adicione uma descrição ao TODO",
"inverted": false,
"regexFile": [
"*.cpp|*.h"
],
"regex": [
"\/\/TODO(?!.*\S)"
]
},
{
"type": "MERGE_TITLE",
"message": "Adicione um prefixo ao merge, como feat, fix, refactor, etc...",
"regex": [
"feat.*|feat.*|refactor.*"
]
}
]
}
Arquivo resources/configs/acr-branch/config.json
{
"data": [
{
"message": "Branch target e branch source devem ser iguais"
}
]
}
Com isso temos um ambiente configurado com 2 extensões, a partir desse exemplo pode-se configurar outras extensões conforme a necessidade, cada extensão deve possuir no seu README.md um exemplo do arquivo config.json, facilitando dessa forma a configuração de uma nova extensão
Cada extensao pode ter um stage, basicamente no config.json de cada extensao, pode ser adicionado a propriedade stage, com base nisso ao executar a extensao passando qual stage esta executando, so ira executar as extensoes que estao relacionadas a aquele stage. Caso a extensao nao tenha um stage atributo, sera considerado como o stage "default", e para rodar essa extensao deve executar a revisao passando o stage como "default"
Basicamente isso possibilita executar um grupo de extensoes em codigo static, na sequencia compilar o projeto e executar um grupo de extensoes em codigo dynamic, e assim por diante, os stage static e dynamic sao apenas exemplos, os stage podem ser definido de acordo com sua necessidade
Cada extensão pode customizar para quais autores a extensão será executada, para isso é preciso configurar no arquivo config.json o atributo createdBy com uma lista de usuarios que terão seus códigos revisados pela extensão em questão, permitindo assim colocar uma extensão rodar para um grupo seleto de usuários
Exemplo de arquivo config.json
{
"createdBy": [
"kielsonzinn",
"example"
],
...
}
Para executar a revisão, precisamos executar o arquivo python passando os parâmetros necessários
Lembre de ajustar os parâmetros de acordo com suas configs
python main.py \
--GIT_TYPE=GIT_LAB \
--GIT_URL=https://gitlab.com.br \
--GIT_USER=`USER` \
--GIT_TOKEN=`TOKEN` \
--GIT_PROJECT_ID=1 \
--GIT_MERGE_REQUEST_ID=2
--STAGE=default
A princípio de forma "nativa" a ferramenta só suporta extensões em python, porém a partir de uma extensão python pode-se interagir com outras linguagens e assim por diante, conforme veremos mais abaixo. Conforme a necessidade podemos incrementar as formas "nativas" de criar uma extensão
Existe um template para extensao python, que pode ser usada como base, voce pode encontrar esse template no seguinte link
Dentro desse template, temos os seguintes arquivos
src
review.py
.gitignore
README.md
app.py
requirements.txt
Vamos entender para que serve cada arquivo
- .gitignore
- Mapeia quais arquivos devem ser ignorado no versionamento de código
- README.md
- Documentação referente à extensão, sendo muito importante mapear um exemplo do arquivo config.json
- requirements.txt
- Dependências python necessárias para funcionamento da extensão
- src/review.py
- Aqui é onde a regra em si deve ser criada, o arquivo possui um código de exemplo, que pode ser usado como base para implementar a nova extensão, a partir desse ponto depende da sua necessidade e do que pretende criar
- app.py
- Arquivo padrão que lê o arquivo config.json, que possui as configs da própria extensão, com mais algumas configs runtime, as quais são
- path_output
- Caminho do arquivo onde deve ser gravado a lista de comentários retornadas pela extensão
- path_target
- Caminho do projeto clonado que se refere ao target do merge request
- path_source
- Caminho do projeto clonado que se refere ao source do merge request
- merge
- Objeto json que possui os dados referente ao merge
{ "title": "feat: Implementa nova funcionalidade", "branch": { "target": "master", "source": "develop", }, "project_id": 1, "merge_request_id": 2, }
- Objeto json que possui os dados referente ao merge
- path_output
- Arquivo padrão que lê o arquivo config.json, que possui as configs da própria extensão, com mais algumas configs runtime, as quais são
A princípio podemos usar o template python para a partir dele chamar um executável, imagine que no src/review.py posso simplesmente usar as libs que o python fornece para chamar um executável, que por sua vez deve de alguma forma gerar os comentarios, seja em arquivo ou o que for, a partir disso a extensão python deve retornar a lista de comentários
A princípio podemos usar o template python para a partir dele chamar um arquivo shell script, imagine que no src/review.py posso simplesmente usar as libs que o python fornece para chamar um shell script, que por sua vez deve de alguma forma gerar os comentarios, seja em arquivo ou o que for, a partir disso a extensão python deve retornar a lista de comentários
A princípio podemos usar o template python para a partir dele chamar outros arquivos ou executáveis, escrito na linguagem que desejarmos, imagine que no src/review.py posso simplesmente usar as libs que o python fornece para chamar um script, ou executar um código java, e assim por diante, que por sua vez deve de alguma forma gerar os comentarios, seja em arquivo ou o que for, a partir disso a extensão python deve retornar a lista de comentários
Pode-se configurar webhook para notificar o processo de verificação
Para configurar, no arquivo config.json direto na pasta resources adicionar a propriedade webhooks
{
"webhooks": [
{
"name": "acr-report",
"host": "http://127.0.0.1:5013/comment",
"events": [
"ADD_COMMENT"
]
}
]
}
No final da execução chama os webhook enviando os dados do merge e comentários adicionados naquela execução
{
"merge": {
"idMerge": 1,
"idProject": 1,
"idGroup": 1,
"dsAuthorUsername": "username",
"dhMerge": "2023-07-16 10:33:00"
},
"comments": [
{
"idComment": 1,
"lkComment": "",
"dsType": "acr-regex",
"txComment": ""
}
]
}
Projeto que serve como webhook recebendo os dados dos comentários adicionados, permitindo revisar os comentários e também disponibilizar um banco de dados para gerar gráficos, como por exemplo usando o grafana
Para ver mais sobre acesse o projeto
- WIP
- WIP
A ideia do projeto é ser open source, isso porque quanto mais a comunidade contribuir, mais opções de automações vamos ter disponíveis, tornando assim a ferramenta mais robusta
Este ponto ainda está em construção, mas a ideia é que quem achar válido contribuir com o projeto monetariamente, incentivando assim a manutenção e melhoria da ferramenta
Envie suas sugestoes no seguinte formulário
Acredito que esta seja melhor forma de contribuir, crie extensões de forma open source, inclusive caso queiram que seja listado dentro da documentação oficial da ferramenta, envie no formulário de sugestões
Fique a vontade para explorar o código fonte da ferramenta, caso encontre algum bug, contribua reportando, ou ainda se ver alguma forma de melhorar faça um fork, altere, e abra um pull request, toda ajuda é bem vinda
Se tratando de futuras implementações, existem vários itens mapeados, mas o foco principal é criar novas extensões genéricas, para automatizar ainda mais o processo de revisão de código
Algo a se pontuar é que existem várias melhorias a serem feitas e estudadas, principalmente na forma de escrever novas extensões, e como passar e pegar dados para as extensões
Outro ponto que ainda será revisada e a licença do software em si
As issues da ferramenta estao sendo centralizadas no seguinte projeto
A ferramenta foi pensada e desenvolvida por mim, me chamo Kielson Zinn da Silva, e sou desenvolvedor de soluções
A ideia é que a ferramenta seja open source, e a comunidade ajude a desenvolver, dando manutencao mas principalmente criando novas extensões
- documentar novas funcionalidades do processor
- adicionar apenas comentarios em codigo novo
- novos argumentos
--SOURCE_PATH --EXTRA_ARGS --CLONE_PATH_TARGET
- apenas algumas pessoas poder resolver um comentario
- ordenação de extensões
- abortar ao encontrar 1 comentario na extensao x
- limitar a nivel de extensao de quem valida o merge
- limitar a nivel de extensao de qual projeto valida o merge
- nova propriedade path_source_v2
- suporte a extensao em java
- suporte a extensao em python
- novos atributos no json do webhook
- novos atributos no json do merge enviado para cada extensao
- method autofix em alguma extensões
- como usar dentro do qtcreator ou via sh
- arquivo corrente
- todos os arquivos no gitstatus
- proximas extensoes
- acr-unused-include
- acr-code-coverage
- proximos autofix
- using nao usado
- documentar extensões
- acr-filename-mapped
- acr-commits-behind
- acr-cpp-include-order
- acr-cpp-param-name
- acr-cpp-include-quote-or-bracket
- acr-java-parser
- acr-cpp-ban-define
- acr-cpp-static-class
- acr-cpp-using-namespace
- acr-cpp-using-namespace
- acr-cpp-inheritance
- acr-json
- acr-regex-within-string
- acr-todo-pattern
- acr-uncrustify
- acr-cpp-move-implementation-to-source
- acr-qml-format
- acr-cpp-mapped-enum
- acr-cpp-member-order
- acr-cmake-format
- acr-cpp-method-required-prefix
- acr-cpp-uninitialized-attribute
- acr-clang-tidy
- acr-cpp-header-precompilacao
- documentar sobre o commons
- documentar sobre o dashboard
- documentar sobre o report
- documentar ideia de listar comentarios dentro da ide
- filtrar por arquivos no status
- filtrar por arquivo aberto
- filtrar por projeto, etc
- documentar como rodar o processor local
Kielson Zinn da Silva
Angelo Hank
Vagner Gross Klaus
Eduardo Cordeiro
André Almeida
Keller Renato Kichel
Gabriel (Zaro) Negri
Gabriel Bertaluci
Leandro Henrique Bellanzon
Luiz Antonio Nicolau Anghinoni