dummybot/app/Http/Controllers/WebhookController.php
javiservices 3afc8a1b9c
Some checks are pending
Deploy DummyBot / Build & Deploy to ${{ env.DEPLOY_HOST }} (push) Waiting to run
fix(deploy): substr offset 11 (refs/heads/ tiene 11 chars)
2026-06-18 12:18:23 +02:00

74 lines
2.7 KiB
PHP

<?php
namespace App\Http\Controllers;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
use Symfony\Component\Process\Process;
class WebhookController extends Controller {
/**
* Webhook de Gitea → deploy self-contained.
*
* Gitea envía POST al hacer push a main, con X-Hub-Signature-256.
* Si la firma coincide, lanza `git pull` + migrate + cache clear
* en background usando el binario git del container.
*
* IMPORTANTE: este código debe existir ANTES de que el webhook
* se active. El primer deploy se hace a mano vía SSH.
*/
public function deploy(Request $r): JsonResponse {
$secret = env('DEPLOY_WEBHOOK_SECRET');
$body = $r->getContent();
$sig = $r->header('X-Hub-Signature-256', '');
if ($secret && ! $this->validSignature($body, $sig, $secret)) {
Log::warning('[webhook] firma inválida', ['sig' => substr((string) $sig, 0, 20)]);
return response()->json(['ok' => false, 'error' => 'invalid signature'], 401);
}
$payload = json_decode($body, true) ?: [];
$ref = $payload['ref'] ?? '';
$branch = str_starts_with($ref, 'refs/heads/') ? substr($ref, 11) : 'main';
if (! in_array($branch, ['main', 'master'], true)) {
Log::info("[webhook] push a '$branch' ignorado");
return response()->json(['ok' => true, 'skipped' => 'branch != main'], 200);
}
$logFile = storage_path('logs/deploy-' . date('Ymd-His') . '.log');
$this->dispatchDeployInBackground($branch, $logFile);
Log::info("[webhook] deploy branch=$branch lanzado log=$logFile");
return response()->json([
'ok' => true,
'status' => 'deploy started',
'log' => basename($logFile),
], 202);
}
private function dispatchDeployInBackground(string $branch, string $logFile): void {
$script = base_path('deploy-runner.sh');
if (! file_exists($script)) {
// Modo fallback: registrar en log y salir
Log::warning("[webhook] $script no existe, deploy no ejecutado");
return;
}
$cmd = sprintf(
'BRANCH=%s BRANCH=%s nohup bash %s > %s 2>&1 &',
escapeshellarg($branch),
escapeshellarg($branch),
escapeshellarg($script),
escapeshellarg($logFile)
);
exec($cmd);
}
private function validSignature(string $body, string $sig, string $secret): bool {
if (! str_starts_with($sig, 'sha256=')) return false;
$expected = 'sha256=' . hash_hmac('sha256', $body, $secret);
return hash_equals($expected, $sig);
}
}