'Webhook not configured']); exit; } define('DEPLOY_QUEUE', '/tmp/jarvis-deploy-queue.txt'); define('DEPLOY_LOG', '/var/www/jarvis/logs/deploy.log'); header('Content-Type: application/json'); $payload = file_get_contents('php://input'); $sig = $_SERVER['HTTP_X_HUB_SIGNATURE_256'] ?? ''; $expected = 'sha256=' . hash_hmac('sha256', $payload, WEBHOOK_SECRET); if (!hash_equals($expected, $sig)) { http_response_code(403); echo json_encode(['error' => 'Invalid signature']); exit; } $data = json_decode($payload, true); $repo = $data['repository']['name'] ?? ''; $ref = $data['ref'] ?? ''; $pusher = $data['pusher']['name'] ?? 'unknown'; // Only deploy on pushes to main if ($ref !== 'refs/heads/main') { echo json_encode(['ok' => true, 'skipped' => "ref $ref is not main"]); exit; } $repoMap = [ 'jarvis' => '/var/www/jarvis', ]; if (!isset($repoMap[$repo])) { http_response_code(404); echo json_encode(['error' => "Unknown repo: $repo"]); exit; } $path = $repoMap[$repo]; // NovaCPX lives on a private VM — the VM polls GitHub every minute via cron // This webhook receipt confirms GitHub delivered the push notification if ($path === '__NOVACPX_VM__') { $commit = $data['after'] ?? 'HEAD'; $msg = "[" . date('Y-m-d H:i:s') . "] NovaCPX push by $pusher (commit: $commit) — VM will deploy within 1 min"; file_put_contents(DEPLOY_LOG, $msg . "\n", FILE_APPEND | LOCK_EX); echo json_encode(['ok' => true, 'queued' => 'novacpx', 'commit' => $commit]); exit; } file_put_contents(DEPLOY_QUEUE, $path . "\n", FILE_APPEND | LOCK_EX); $msg = "[" . date('Y-m-d H:i:s') . "] Queued deploy: $repo by $pusher -> $path"; file_put_contents(DEPLOY_LOG, $msg . "\n", FILE_APPEND | LOCK_EX); echo json_encode(['ok' => true, 'queued' => $repo, 'path' => $path]);