Eu construi um mini-github
Mini github
Olá, neste post irei contar sobre como construi um mini-github utilzando laravel.
Disclaimer: não sou especialista, o post traz opniões MINHAS, nem tudo tem base técnica, o post é para contar uma experiência, não um documento técnico ;D
A ideia
Bom, lá estava eu procrastinando um pouco em meu pc, até que tive a curiosidade de: como o github ou o gitlab funcionam? inicialmente enviei alguns git push
a um webhook, para ver o que ele mandava. E era interessantemente inutil, nenhum corpo, alguns cabeçalhos. Bom, ai acabei arregando para o chatgpt :P, e ele não me devolveu nada de interessante(literalmente nada), então fui na doc do git, e depois de ler um pouco, pronto! descobri que para tal feito precisava configurar o git-http-backend(porque não ssh? Ninguém usa isso :D).
A jornada do git-http-backend
Bom, o git-http-backend recebe as informações via CGI, simples né? só que não, pelo menos para mim que não tinha mto experiência configurando servidores, tinha 3 opções para implementar isto:
- Programar uma comunicação cgi pelo php
- Configurar um servidor apache
- Configurar um nginx
CGI pelo PHP
Bom, a primeira opção que tentei foi o cgi pelo php, e por incrivel que pareça não tem quase nada na internet sobre isto, tirando o Pacote do TuzelKo, porém a implementação dele não é muito customizavel, então por que não adaptar? ninguém curte o proc_open e levaria mais tempo :P.
Configurar o apache
Então, neste daqui não perdi muito tempo, não manjo nada de apache, mais é a opção com mais exemplos na internet.
Configurar nginx
Bom, está foi a solução escolhida até agora(ainda sonho com o PHP cgi), eu implementei ela utilizando docker, que por sorte tinha uma imagem pronta. E com alguns volumes e horas de luta com o meu windows(não use windows), tinha um servidor http de repositorios git.
Interface
Para construir a interface(parte mais divertida), utilizei a TALL stack, junto com o Preline, para poder interagir com os repositorios utilizei o git-php, está parte não tem muito misterio, é básicamente o seguinte: da o comando para pegar as informações, trata elas e joga na tela.
OBS: os repositorios que são armazenados no servidor são repositorios bare, que não armazenam nenhum arquivo, além dos arquivos de configuração do git
Exemplo de comandos
Montar arvore de objetos(simplificada):
$tree = $repo->execute(
'ls-tree', "--format='%(objectmode) %(objecttype) %(objectname) %(path)",
'HEAD',
);
$objects = [];
foreach ($tree as $object) {
$data = explode(' ', $object);
$lastCommit = explode(
'-separator-',
$repo->execute(
'log',
'--find-object=' . $data[2],
"--pretty=format:'%ad-separator-%s'",
'--date=short'
)[0]
);
$objects[] = [
'type' => $data[1],
'full_name' => $data[3],
'name' => str_replace($this->tree . '/', '', $data[3]),
'last_commit' => [
'date' => $lastCommit[0],
'description' => $lastCommit[1]
]
];
}
Como exibir um arquivo/blob:
$repositoryPath = storage_path('repositories/' . $this->repository->title . '.git');
$gitCommand = 'git show HEAD:' . $this->blobName;
$blobContent = shell_exec("cd $repositoryPath && $gitCommand");
Conclusão
Aprendi muito sobre git :D