$code, 'message' => $message]); exit; } function read_env(string $key, string $default = ''): string { static $env = null; if ($env === null) { $env = []; $file = APP_ROOT . DIRECTORY_SEPARATOR . '.env'; if (file_exists($file)) { foreach (file($file, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES) as $line) { $line = trim($line); if ($line === '' || str_starts_with($line, '#')) { continue; } if (str_contains($line, '=')) { [$k, $v] = explode('=', $line, 2); $env[trim($k)] = trim($v, " \t\"'"); } } } } return $env[$key] ?? (getenv($key) ?: $default); } // ── Hanya terima POST ──────────────────────────────────────────────────────── if ($_SERVER['REQUEST_METHOD'] !== 'POST') { respond(405, 'Method Not Allowed'); } $payload = file_get_contents('php://input'); if (empty($payload)) { respond(400, 'Empty payload'); } // ── Sahkan signature Gitea ─────────────────────────────────────────────────── $secret = read_env('WEBHOOK_SECRET'); if (!empty($secret)) { $signature = $_SERVER['HTTP_X_GITEA_SIGNATURE'] ?? ''; $expected = hash_hmac('sha256', $payload, $secret); if (!hash_equals($expected, $signature)) { log_msg('WARN: Signature tidak sah dari IP ' . ($_SERVER['REMOTE_ADDR'] ?? 'unknown')); respond(403, 'Invalid signature'); } } // ── Parse payload ──────────────────────────────────────────────────────────── $data = json_decode($payload, true); if (json_last_error() !== JSON_ERROR_NONE) { respond(400, 'Invalid JSON payload'); } $event = $_SERVER['HTTP_X_GITEA_EVENT'] ?? 'unknown'; $ref = $data['ref'] ?? ''; $branch = basename($ref); $pusher = $data['pusher']['login'] ?? 'unknown'; $commitId = substr($data['after'] ?? '', 0, 8); log_msg("Event: $event | Branch: $branch | Pusher: $pusher | Commit: $commitId"); // ── Hanya deploy pada push ke master/main ─────────────────────────────────── $targetBranch = read_env('WEBHOOK_BRANCH', 'master'); if ($event !== 'push' || $branch !== $targetBranch) { respond(200, "Skipped — event=$event branch=$branch (target=$targetBranch)"); } // ── Jalankan deployment script ─────────────────────────────────────────────── $deployScript = APP_ROOT . '\\scripts\\deploy.ps1'; $deployLog = APP_ROOT . '\\storage\\logs\\deploy-' . date('Ymd-His') . '.log'; if (!file_exists($deployScript)) { log_msg('ERROR: Deploy script tidak dijumpai: ' . $deployScript); respond(500, 'Deploy script not found'); } $command = sprintf( 'powershell.exe -NonInteractive -ExecutionPolicy Bypass -File "%s" > "%s" 2>&1', $deployScript, $deployLog ); log_msg("Menjalankan: $command"); $descriptors = [ 0 => ['pipe', 'r'], 1 => ['file', $deployLog, 'a'], 2 => ['file', $deployLog, 'a'], ]; $process = proc_open($command, $descriptors, $pipes, APP_ROOT); if (!is_resource($process)) { log_msg('ERROR: Gagal memulakan proses deployment'); respond(500, 'Failed to start deployment process'); } fclose($pipes[0]); $exitCode = proc_close($process); log_msg("Deployment selesai — exit code: $exitCode | log: $deployLog"); if ($exitCode === 0) { respond(200, "Deployment berjaya — commit $commitId"); } else { respond(500, "Deployment gagal — exit code $exitCode, semak $deployLog"); }