- Novo runbook KB-PLUGIN-031: nascimento do plugin ate validacao E2E no GLPI dev (scaffold, Forgejo local, deploy CT100, console, bootstrap Kernel para testes CLI). Validado de ponta a ponta com o assetinherit. - Registros KB-PLUGIN-021..030 existiam apenas no disco (drift) e foram incluidos no versionamento; index.json sincronizado via kb-fix. - Ignora lixo AppleDouble/.DS_Store do macOS. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
6.4 KiB
| id | title | domain | tags | status | severity | created_at | updated_at | applies_to | related_records | |||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| KB-PLUGIN-031 | Runbook — Workflow de desenvolvimento e deploy DEV de plugins GLPI | plugin-dev |
|
active | high | 2026-06-11 | 2026-06-11 |
|
|
Runbook — Workflow de desenvolvimento e deploy DEV de plugins GLPI
Procedimento padrão do nascimento de um plugin até sua validação no GLPI de desenvolvimento. A publicação em produção (Mindplace/licenciamento) é outro processo — ver KB-PLUGIN-013.
Primeiro plugin a seguir este fluxo de ponta a ponta: assetinherit (2026-06-11).
Mapa do ambiente
| Componente | Onde |
|---|---|
| Servidor dev (docker) | CT 100 — root@192.168.100.49 (SSH key do Mac já cadastrada) |
| Diretório de plugins | /opt/projects/GLPI11/docker/glpi/plugins/ (bind → /var/www/glpi/plugins, ver [KB-INFRA-001]) |
| Container GLPI | glpi11-app (GLPI dev em http://192.168.100.49:8081) |
| Git de dev | Forgejo local — git@192.168.100.101:administrador/<plugin>.git (remote origin) |
| Git de produção | Forgejo Mindtek — remote production, usado só na publicação |
Fase 1 — Scaffold do plugin
Estrutura mínima obrigatória (a chave/diretório do plugin define TUDO — funções, hooks, constantes):
<key>/
├── setup.php # plugin_init_<key>, plugin_version_<key> + 4 callbacks
├── hook.php # install/uninstall e demais hooks
├── logo.png # PNG 128x128 na raiz — obrigatório [KB-INFRA-002]
├── README.md # dor que resolve, como funciona, instalação, configuração
├── CHANGELOG.md # Keep a Changelog
├── LICENSE # GPL-3.0-or-later (compatível com o GLPI)
└── .gitignore # padrão de plugins [KB-PLUGIN-013]
Checklist de armadilhas conhecidas:
setup.phpcom os 4 callbacks:check_prerequisites,check_config,install,uninstall— sem eles a instalação falha genericamente ([KB-PLUGIN-001]).- Toda chave em
$PLUGIN_HOOKS[...]['<key>']é o plugin key exato (= nome do diretório). Variações falham em silêncio ([KB-PLUGIN-004]). logo.pngé PNG real (SVG renomeado não funciona) ([KB-INFRA-002]).versionnosetup.phpem SemVer — o release de produção lê de lá.
Fase 2 — Repositório no Forgejo local
Criar o repo via API (ou UI em http://192.168.100.101:3000):
curl -s -u 'administrador:<senha>' -X POST \
http://192.168.100.101:3000/api/v1/user/repos \
-H 'Content-Type: application/json' \
-d '{"name":"<key>","private":true,"default_branch":"main"}'
No diretório do plugin (na máquina de dev):
git init && git branch -M main
git add -A && git commit -m "<key> 0.1.0: scaffold"
git remote add origin git@192.168.100.101:administrador/<key>.git
git push -u origin main
Convenção de remotes: origin = Forgejo local (push contínuo de dev);
production = Forgejo Mindtek (adicionado apenas na publicação, [KB-PLUGIN-013]).
Fase 3 — Deploy no servidor dev
ssh root@192.168.100.49
cd /opt/projects/GLPI11/docker/glpi/plugins
git clone git@192.168.100.101:administrador/<key>.git
git config --global --add safe.directory \
/opt/projects/GLPI11/docker/glpi/plugins/<key>
chown -R www-data:www-data <key>
O bind mount entrega o plugin no container instantaneamente — não precisa recriar o container.
Fase 4 — Instalação e ativação (sempre via console)
docker exec glpi11-app sh -c '
php -l /var/www/glpi/plugins/<key>/setup.php &&
php -l /var/www/glpi/plugins/<key>/hook.php &&
php /var/www/glpi/bin/console plugin:install <key> -n --username=glpi &&
php /var/www/glpi/bin/console plugin:activate <key> -n &&
php /var/www/glpi/bin/console plugin:list | grep <key>'
Esperado: status Habilitado. O console dá erros legíveis; a UI só mostra falha genérica.
Fase 5 — Validação funcional (teste E2E em CLI)
⚠️ Gotcha do GLPI 11: em CLI, include 'inc/includes.php' não carrega
mais o core (classes como RuleAsset ficam indisponíveis). O bootstrap correto
para scripts de teste é o do bin/console:
require '/var/www/glpi/vendor/autoload.php';
$kernel = new \Glpi\Kernel\Kernel();
$kernel->boot(); // carrega core + plugins ativos (plugin_init roda aqui)
// sessão CLI mínima para CommonDBTM::add()/update()
$_SESSION['glpiactiveentities'] = [0];
$_SESSION['glpiactive_entity'] = 0;
$_SESSION['glpiactiveprofile']['interface'] = 'central';
Padrão do teste: criar massa de dados de teste com prefixo TEST →
exercitar os cenários → deletar tudo com purge no final. Executar:
scp test_<key>.php root@192.168.100.49:/tmp/
ssh root@192.168.100.49 'docker cp /tmp/test_<key>.php glpi11-app:/tmp/ &&
docker exec glpi11-app php /tmp/test_<key>.php'
Exemplo real completo: teste E2E do assetinherit (6 cenários, incluindo
descoberta de comportamento que virou documentação — critério PATTERN_EXISTS
não casa com users_id = 0).
Fase 6 — Ciclo de iteração
- IDE no Mac → Remote SSH em
root@192.168.100.49, pasta do plugin. - Editar in-place — GLPI é PHP, refresh no browser e a mudança aparece.
git add . && git commit && git push→ Forgejo local (origin).- Mudanças feitas no Mac:
git push originno Mac +git pullno CT 100 (lembrarchown -R www-data:www-datase criar arquivos novos como root).
Fase 7 — Promoção para produção (fora deste runbook)
Quando validado no dev: seguir [KB-PLUGIN-013] (kill switch de licença, release ZIP com wrapper directory [KB-PLUGIN-018], catálogo Mindplace, serial do cliente).
Regra para agentes
Ao criar/depurar plugin novo no ambiente dev, seguir este runbook na ordem.
Antes de diagnosticar erro funcional, validar Fases 3-4 (mount, ownership,
instalação via console). Para testes E2E em CLI, usar SEMPRE o bootstrap do
Kernel (Fase 5), nunca inc/includes.php.
Classificação
- Tipo: Runbook operacional de desenvolvimento.
- Reutilização: obrigatória para todo plugin novo.